Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


25. July 2015

 

In this chapter we are going to look at using audio in XNA.  Originally XNA supported one way of playing audio, using XACT (Cross Platform Audio Creation Tool ).  Since the initial release they added a much simplified API.  We will be taking a look at both processes.

 

There is an HD video of this chapter available here.

 

When playing audio there is always the challenge of what formats are supported, especially when you are dealing with multiple different platforms, all of which have different requirements.  Fortunately the content pipeline takes care of a great deal of the complications for us.  Simply add your audio files ( mp3, mp4, wma, wav, ogg ) to the content pipeline and it will do the rest of the work for you.   As you will see shortly though, it is also possible to load audio files outside of the content pipeline.  In this situation, be aware that certain platforms do not support certain formats ( for example, no wma support on Android or iOS, while iOS doesn’t support ogg but does support mp3 ).  Unless you have a good reason, I would recommend you stick to the content pipeline for audio whenever possible.

 

The Perils of MP3

Although MP3 is supported by MonoGame, you probably want to stay away from using it. Why?
Patents. If your game has over 5,000 users you could be legally required to purchase a license. From a legal perspective, Ogg Vorbis is superior in every single way. Unfortunately Ogg support is not as ubiquitous as we'd like it to be.

 

Adding Audio Content using the Content Pipeline

This process is virtually identical to adding a graphic file in your content file.

image

 

Simply add the content like you did using right click->Add Existing Items or the Edit menu:

image

 

If it is a supported format you will see the Processor field is filled ( otherwise it will display Unknown ).  The only option here is to configure the mp3 audio quality, a trade off between size and fidelity.

 

Playing a Song

Now let’s look at the code involved in playing the song we just added to our game.

// This example shows playing a song using the simplified audio api

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Example1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Song song;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            this.song = Content.Load<Song>("prepare");
            MediaPlayer.Play(song);
            //  Uncomment the following line will also loop the song
            //  MediaPlayer.IsRepeating = true;
            MediaPlayer.MediaStateChanged += MediaPlayer_MediaStateChan
                                             ged;
        }

        void MediaPlayer_MediaStateChanged(object sender, System.
                                           EventArgs e)
        {
            // 0.0f is silent, 1.0f is full volume
            MediaPlayer.Volume -= 0.1f;
            MediaPlayer.Play(song);
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

 

Notice that we added the using statement Microsoft.Xna.Framework.Media.  We depend on this for the MediaPlayer and Song classes.  Our Song is loaded using the ContentManager just like we did earlier with Texture, this time with the type Song.  Once again the content loader does not use the file’s extension.  Our Song can then be played with a call to MediaPlayer.Play().  In this example we wire up a MediaStateChanged event handler that will be called when the song completes, decreasing the volume and playing the song again.

 

Playing Sound Effects

 

This example shows playing sound effects.  Unlike a Song, SoundEffects are designed to support multiple instances being played at once.  Let’s take a look at playing SoundEffect in MonoGame:

// Example showing playing sound effects using the simplified audio 
api
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;
using System.Collections.Generic;

namespace Example2
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<SoundEffect> soundEffects;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            soundEffects = new List<SoundEffect>();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            soundEffects.Add(Content.Load<SoundEffect>("airlockclose"))
                             ;
            soundEffects.Add(Content.Load<SoundEffect>("ak47"));
            soundEffects.Add(Content.Load<SoundEffect>("icecream"));
            soundEffects.Add(Content.Load<SoundEffect>("sneeze"));

            // Fire and forget play
            soundEffects[0].Play();
            
            // Play that can be manipulated after the fact
            var instance = soundEffects[0].CreateInstance();
            instance.IsLooped = true;
            instance.Play();
        }


        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.D1))
                soundEffects[0].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D2))
                soundEffects[1].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D3))
                soundEffects[2].CreateInstance().Play();
            if (Keyboard.GetState().IsKeyDown(Keys.D4))
                soundEffects[3].CreateInstance().Play();


            if (Keyboard.GetState().IsKeyDown(Keys.Space))
            {
                if (SoundEffect.MasterVolume == 0.0f)
                    SoundEffect.MasterVolume = 1.0f;
                else
                    SoundEffect.MasterVolume = 0.0f;
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            base.Draw(gameTime);
        }
    }
}

 

Note the using Microsoft.Xna.Framework.Audio statement at the beginning.  Once again we added our audio files using the Content Pipeline, in this case I added several WAV files.  They are loaded using Content.Load() this time with the type SoundEffect.  Next it is important to note the two different ways the SoundEffects are played.  You can either call Play() directly on the SoundEffect class.  This creates a fire and forget instance of the class with minimal options for controlling it.  If you have need for greater control ( such as changing the volume, looping or applying effects ) you should instead create a SoundEffectInstance using the SoundEffect.CreateInstance() call.  You should also create a separate instance if you want to have multiple concurrent instances of the same sound effect playing.  It is important to realize that all instances of the same SoundEffect share resources, so memory will not increase massively for each instance created.  The number of simultaneous supported sounds varies from platform to platform, with 64 being the limit on Windows Phone 8, while the Xbox 360 limits it to 300 instances.  There is no hard limit on the PC, although you will obviously hit device limitations quickly enough.

 

In the above example, we create a single looping sound effect right away.  Then each frame we check to see if the user presses 1,2,3 or 4 and play an instance of the corresponding sound effect.  If the user hits the spacebar we either mute or set to full volume the global MasterVolume of the SoundEffect class.  This will affect all playing sound effects.

 

Positional Audio Playback

Sound effects can also be positioned in 3D space easily in XNA. 

// Display positional audio

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Example3
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SoundEffect soundEffect;
        SoundEffectInstance instance;
        AudioListener listener;
        AudioEmitter emitter;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            
            soundEffect = this.Content.Load<SoundEffect>("circus");
            instance = soundEffect.CreateInstance();
            instance.IsLooped = true;

            listener = new AudioListener();
            emitter = new AudioEmitter();

            // WARNING!!!!  Apply3D requires sound effect be Mono!  
            Stereo will throw exception
            instance.Apply3D(listener, emitter);
            instance.Play();
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
            {
                listener.Position = new Vector3(listener.Position.X-0.
                                    1f, listener.Position.Y, listener.
                                    Position.Z);
                instance.Apply3D(listener, emitter);
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                listener.Position = new Vector3(listener.Position.X + 
                                    0.1f, listener.Position.Y, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                listener.Position = new Vector3(listener.Position.X, 
                                    listener.Position.Y +0.1f, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Down))
            {
                listener.Position = new Vector3(listener.Position.X, 
                                    listener.Position.Y -0.1f, 
                                    listener.Position.Z);
                instance.Apply3D(listener, emitter);
            }            
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

 

In this example, we load a single SoundEffect and start it looping infinitely.  We then create an AudioListener and AudioEmitter instance.  The AudioListener represents the location of your ear within the virtual world, while the AudioEmitter represents the position of the sound effect.  The default location of both is a Vector3 at (0,0,0).  You set the position of a SoundEffect by calling Apply3D().  In our Update() call, if the user hits an arrow key we updated the Position of the AudioListener accordingly.  After changing the position of a sound you have to call Apply3D again.  As you hit the arrow keys you will notice the audio pans and changes volume to correspond with the updated position.  It is very important that your source audio file is in Mono ( as opposed to Stereo ) format if you use Apply3D, or an exception will be thrown.

 

Using XACT

As mentioned earlier, XACT used to be the only option when it came to audio programming in XNA.  XACT is still available and it enables your audio designer to have advanced control over the music and sound effects that appear in your game, while the programmer uses a simple programmatic interface.  One big caveat is XACT is part of the XNA installer or part of the Direct X SDK as is not available on Mac OS or Linux.  If you wish to install it but do not have an old version of Visual Studio installed, instructions can be found here ( http://www.gamefromscratch.com/post/2015/07/23/Installing-XNA-Tools-Like-XACT-without-Visual-Studio-2010.aspx ).  If you are on MacOS or Linux, you want to stick to the simplified audio API that we demonstrated earlier.

Xact is installed as part of the XNA Studio install, on 64bit Windows by default the Xact executable will be located in C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\Tools.  Start by running AudConsole3.exe:

image

 

The XACT Auditioning Tool needs to be running when you run the Xact tool.

Then launch Xact3.exe

image

First create a new project:

image

 

Next right click Wave Banks and select New Wave Bank

image

 

Drag and drop your source audio files into the Wave Bank window:

image

 

Now create a new Sound Bank by right clicking Sound Bank and selecting New Wave Bank

image

 

Now drag the Wave you wish to use from the Wave Bank to the Sound Bank

a1

 

Now create a Cue by dragging and dropping the Sound Bank to the Cue window.  Multiple files can be added to a cue if desired.

a2

 

You can rename the Cue, set the probability to play if you set several Sounds in the Cue and change the instance properties of the Cue in the properties window to your left:

image

Now Build the results:

image

 

This will then create two directories in the folder you created your project in:

image

 

These files need to be added directly to your project, you do not use the content pipeline tool!  Simply copy all three files to the content folder and set it’s build action to Copy.

image

 

Now let’s look at the code required to use these generated files:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Example4
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        AudioEngine audioEngine;
        SoundBank soundBank;
        WaveBank waveBank;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            audioEngine = new AudioEngine("Content/test.xgs");
            soundBank = new SoundBank(audioEngine,"Content/Sound Bank.
                        xsb");
            waveBank = new WaveBank(audioEngine,"Content/Wave Bank.
                       xwb");

            soundBank.GetCue("ak47").Play();
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
                ButtonState.Pressed || Keyboard.GetState().IsKeyDown(
                Keys.Escape))
                Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

 

First you create an AudioEngine using the xgs file, then a SoundBank using the xsb and a WaveBank unsing the xwb file.  We then play the Cue we created earlier with a call to SoundBank.GetQue().Play().  This process allows the audio details to be configured outside of the game while the programmer simply uses the created Que.

 

Finally it is possible to play audio files that weren’t added using the content pipeline or using Xact using a Uri. 

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw 
            textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // URL MUST be relative in MonoGame
            System.Uri uri = new System.Uri("content/background.mp3",
                             System.UriKind.Relative);
            Song song = Song.FromUri("mySong", uri);
            MediaPlayer.Play(song);
            MediaPlayer.ActiveSongChanged += (s, e) => {
                song.Dispose();
                System.Diagnostics.Debug.WriteLine("Song ended and 
                                                   disposed");
            };
        }

 

First you create a Uri that locates the audio file you want to load.  We then load it using the method FromUri, passing in a name as well as the uri.  One very important thing to be aware of here, on XNA you could use any URI.  In MonoGame it needs to be a relative path.

 

The Video

 

Programming , , ,

blog comments powered by Disqus

RecentPosts

  • This Week In GameDev–Dec 7/2016
  • TypeScript 2.1 Released
  • Unity Release Patch 5.5.0p1
  • Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

    11. January 2016

     

    Today Paymentwall released an SDK for the popular game engine Unity that enables developers to accept payments directly within their application.  From the press release:

    “We are very excited to release our Unity Integration to allow gamers to make in-game purchases in their local currency, and in their most preferred payment method,” said Jevin Tryon, Project Manager at Paymentwall. “As a result, game developers will be able to increase their revenue, and monetize their games all around the world, easily.

    The ability to offer different payment methods and manage in-game purchases will allow developers to reach different markets worldwide and maximize their revenue. This is especially important as the global gaming market is expected to grow at a rate of 9.4% annually, and reach a revenue of 107 billion US dollars by 2017, according to the 2015 Global Games Market Report from Newzoo. Through the Paymentwall SDK, Unity will become the most wanted platform among game developers. In 2015, the number of developers using Unity reached a million, as compared to 60,000 developers in 2014, said Unity CEO John Riccitiello.

    The Unity Editor comes with an array of tools for creating and enhancing graphics, animation, as well as 2D and 3D physics for games through effectors and colliders. Editor also supports C#, JavaScript, and Boo to help developers optimize user experience. To save time on game development and updates, Unity’s asset store offers ready-made plug-ins, models, extensions and services; which now includes Paymentwall SDK.

    Developers will be able to level up the gaming experience through Paymentwall SDK. Their end-users can now pay for in-game purchases in a manner that is most convenient for them. The SDK also supports customization of the checkout page to reflect the look and feel of the game itself, contributing to a seamless user experience. Fraud protection and risk monitoring services are also part of it, to ensure safety for both end-users and developers in every transaction.

    Unity checkout

    Example of Paymentwall’s one-click checkout page for Unity

    Unity developers will be able to increase their revenue with Paymentwall SDK, while providing their users a better experience within their games. The creation of Paymentwall SDK for Unity makes the game development platform an all-in-one solution for both new and existing developers that seek to earn money from their games.

    This is actually different than the myriad of In App Purchase plugins out there, as ultimately IAP make use of the underlying store (Steam, Google Play Store or Apple Store) for processing the payment, while in this case PaymentWall is the processor.  I would actually be somewhat shocked if Apple would allow this past their terms and conditions given their previous attitude towards transactions done on the AppStore (AKA, they want a 30% cut of everything, from app sales to Netflix subscriptions or Amazon purchases).  In fact, I am almost positive that neither Google nor Apple would allow you to use this SDK with their app store, making this desktop only.  I suppose this system could be effective for people directly selling a game they want to monetize in app purchases on.

     

    Paymentwall started life in 2010 as a way for developers to monetize Facebook applications, until Facebook effectively shut out outside providers a year later.   The name seems a bit odd to me, as I had always associated the expression “Pay Wall” as derogatory.

    GameDev News

    9. January 2016

     

    If I am completely honest up front, right from the very beginning the HTC Vive was an also ran to me.  The Samsung GearVR was first to market, while the Oculus Rift certainly had the brand recognition and the majority of the press.  Suddenly however with the pre-orders of the Oculus Rift, most of that press is suddenly quite negative.  First because the VR controllers were  delayed, although frankly this talking point is a pretty minor one.  No, the big reason for the negative press is the sticker shock.  Earlier comments from Luckey Palmer (Oculus founder) had people expecting the rift to be around $300 so a $600 price tag was certainly a suprise.  Couple that with the incredibly high system requirements and incompatibility with the majority of high end laptops, suddenly the Rift lost a heck of a lot of momentum.

     

    Of course the Rift isn’t the only horse in this race.  Ignoring Google Cardboard and GearVR, the two major players in the space are Sony with the PlayStation VR and HTC/Steam with the Vive.  With the sticker shock, the PlayStation VR had a huge opportunity here as the PS4 requirement is many times cheaper than the PC required to power the Oculus Rift (and assumedly the Vive).  They could have won on the price point alone… then this happened.  If you thought $600 was a painful price point, an Amazon.ca leak had the PSVR priced at $1,125 CDN!  (@800USD).  Of course this is only a leak at this point and I have trouble believing that Sony would actually price it at the same price point as 3x PlayStation 4s but crazier things have happened.

     

    This entire process has given HTC a gigantic opportunity.  Does everyone remember the classic Sony “mic drop” price announcement for the original PlayStation?

     

    And with the single comment of "$299" at E3 in 1995 the PlayStation won and the Sega Saturn died.

     

    Right now, HTC has that exact same opportunity.

    Totally Off Topic

    8. January 2016

     

    Special thanks to @Dillybob on Twitter for bringing this engine to my attention.  QICI Engine is a HTML5 game engine and toolset layered over top of Pixi and Phaser, a library I am a huge fan of.  The engine is well documented and completely free.  The source is available although oddly enough the Github page just contains prepackaged archives.

     

    In their own words, QICI Engine is:

    QICI Engine is a free and open source JavaScript game engine library with a web-based comprehensive suite of toolset for making HTML5 games.

    With QICI Engine, creating HTML5 Games just like Web Development, use your favorite code editor, use your favorite web browser, leverage JavaScript language and all the best web development tools. QICI Engine takes care of the complexity of the underlying technologies, so you just focus on what's important - making your game!

    Technology Stack

    QICI Engine is based on the free and open source HTML5 game framework Phaser, which uses Pixi.js for WebGL and Canvas rendering across desktop and mobile web browsers.

    Phaser is actively developed and maintained by @photonstorm, but QICI Engine uses the specific version Phaser 2.3.0. We keep track of bug fixes and performance improvements for Phaser, so you can use the customized Phaser version that QICI Engine provides safely.

    QICI Engine is made up of three parts: QICI Core, QICI Widget and QICI Editor:

    • QICI Core: A JavaScript Game Engine library that is based on Phaser.
    • QICI Widget: A JavaScript UI library for creating rich application.
    • QICI Editor: A web-based editor with a Node.js server for accelerating HTML5 game development.

    The QICI Core is the core of QICI Engine, the QICI Editor would not work without it, but the QICI Core can function on its own to be used to make a HTML5 Game by writing code without QICI Editor. But for complex UI, it’s really hard to build and maintain without the help of WYSIWYG visual interface, with QICI Editor even artists and designers can help to build the game’s UI.

    QICI Widget provides the HTML5 UI widgets for making the GUI in QICI Editor.

    QICI Core is a JavaScript Game library, QICI Widget is a JavaScript UI library, and QICI Editor uses Node.js for accessing the file system, so QICI Engine is a Full-Stack JavaScript Game Engine.

    Features

     

     

    Very cool project and certainly one I am checking out.  Oddly however, when you download the current version from their website, on first run they tell you an update is available and you download it.  I hate when this happens.

    GameDev News ,

    7. January 2016

     

    Tiled, the popular open source level editor, just released version 0.15.0.

     

    From the release notes:

    Those who remember the Tiled 0.14 release announcement may remember that I wanted the next release to be Tiled 1.0. We're not entirely there yet, but Tiled took a big step towards being more functionally complete.

    The most important changes regarding this made sure that you can now load maps that refer to files that are for whatever reason no longer accessible. Previously, you'd then have to fall back to correcting the map file by hand. Now Tiled will tell you about the problems it found and allows you to fix them:

    main.tmx — Tiled_068.png1210x713 91.7 KB

    In addition, you can change any of these references through the Properties view after clicking the relevant items. And when changing a tileset image, you can also change its parameters like tile size, margin and spacing.

    Enable/Disable Plugins

    Another important bit of functionality is that you can now choose which plugins are enabled. By default, only the generic plugins for exporting to Lua, JSON, CSV and for enabling Python import/export scripts are loaded. The project-specific plugins were often leading to confusion and now need to be explicitly enabled.

    Plugins can be enabled and disabled without restarting Tiled.

    Layer Combo Box

    The status bar got a little more useful, since it now allows you to quickly switch the current layer. If you're not actively changing around your layer stack, this can entirely replace the Layers view:

    isometric_grass_and_water.tmx — Tiled_071.png1028x120 94.3 KB

    Other Noteworthy Things

    If you're using an image collection tileset, you can now choose how many tile columns it should have. Eventually I'd also like to add a dynamic wrapping display mode, but this should help in the meantime.

    A Terrain Generator tool was added, which helps a lot with generating a certain type of terrain tileset. But, I still need to write the usage instructions and I forgot to include it in the binary packages.

    You can now go past the edges of the map when panning with the space bar, middle mouse button or the mini-map. This can be really helpful when you're editing things on the edge of the map.

    Change log
    • Allow loading maps with broken external references
    • Allow plugins to be enabled/disabled
    • Allow changing tileset image parameters
    • Allow changing the images of tiles in a collection tileset
    • Allow changing external tileset references
    • Allow panning over the edges of the map
    • Added Terrain Generator tool
    • Added column count property to image collection tilesets
    • Added a combo box for changing the current layer to the status bar
    • Moved the AutoMapping while drawing toggle into the menu
    • Removing tiles from collection tilesets no longer changes tile IDs
    • Unified layer offset handling
    • Default tile layer data format changed to CSV
    • Deprecated pure XML and Gzip-compressed tile layer data formats
    • Fixed random tile picker for tiles with zero probability (by Henrik Heino)
    • Fixed saving of alpha value of the map background color
    • Fixed crash in tmxrasterizer and tmxviewer
    • Fixed tmxrasterizer not reporting write errors
    • Fixed isometric rendering bug with odd tile heights (by Ryan Schmitt)
    • Updated Bulgarian, Dutch, French, German, Japanese, Russian and Spanish translations

    Many thanks to all who contributed!

     

    If you want to learn more about Tiled, we have a comprehensive tutorial series here on Gamefromscratch.com to get you started.

    GameDev News

    7. January 2016

     

    The Superpowers HTML5 game engine is now open source and available on Github. In the developers own words, Superpowers is:

    download

     

    Superpowers is a downloadable HTML5 app. You can use it solo like a regular offline game maker, or setup a password and let friends join in on your project through their Web browser. It's great for working together over long periods of time, for jamming over a weekend, or just for helping each other out with debugging!

    ... not just for making games!

    We've built the Superpowers Game engine and a bunch of asset editors to make games with TypeScript. But the coolest thing is this: Superpowers itself is actually engine-agnostic. It's just a piece of software for collaborating on projects and you can extend it with project types and editors.

    Use Superpowers to make static websites, Lua LÖVE games, slideshows, blogs, movies... whatever you can come up with!

     

    There is a pretty solid set of tutorials and documents available here should you require more information.  You can see a demo of SuperPowers in action in the video below.  WARNING!!! Mute your sound, trust me.

    GameDev News ,

    Month List

    Popular Comments