Using Sothink SWF Decompiler To Convert Flash Games To HTML5

Hey guys,

If you’ve been following me for a while, you’re aware that one of the services I offer is to convert Flash games to HTML5 canvas. I’ve done this with the game Blasteroids, which was originally a Flash game I coded for a client.

Now, when doing the conversion, if you have the all the original code and assets, including any Flash FLA files that Adobe Animate use, that’s the best option. Some smaller Flash projects (and I mean very small) may use a single FLA file with all the code and assets built into it. Usually, that will not be the case…

But for the sake of this article, let’s assume that is the case. But!… You do not have this FLA file or any of its assets! And without that FLA file, you’re f*cked right? Well, maybe not! That’s where a tool called Sothink SWF Decompiler may come to the rescue!

This tool is designed to extract code and assets from Flash files so you can use them to rebuild the game in HTML5 canvas. The tool can even extract any FLA files it finds, and there is even a function to export to HTML5 format (more on this later).

Remember: When converting a Flash game to HTML5, you will need to rebuild the game from scratch, particularly, the coding and functionality.

I’ve been working with a client who has several Flash games that needed to be converted. He does not have the FLA files for most of them. And the only way for me to even get SWF files was to download them by accessing the developer console within the browser.

Trying Out Sothink SWF Decompiler

Without the FLA files, I decided to give Sothink SWF Decompiler a try. I told the client that there may not be a guarantee that the decompiler might not be able to assist with converting all his SWFs (because you don’t know what you’re dealing with – it would be dumb to assume you can do the job without having seen how anything works yet).

Fortunately, the makers of the decompiler, SourceTec Software, allow you to download a trial. They even allow you to send them a SWF file, and they will decompile the SWF and inform you the test result (albeit they keep the resultant FLA file).

I opted to try the latter option, and to my surprise, they were able to successfully extract assets from the SWF!

Deciding to take a risk, I went ahead and bought the full version of the decompiler, and took on the client’s request to convert all his requested games (or to let him know of any that could not be converted).

And so far, the decompiler has delivered! I’ve been able to extract the main FLA file, as well as all the necessary code and assets from the every SWF encountered.

You can extract pretty much any element from the SWF file to your computer to reuse it when you build the game as HTML5 from the ground up.

Exporting the FLA File from the SWF

When you open a SWF with the decompiler, it will attempt to run the SWF and display the output in the main window. The Export panel to the right will allow view and extract individual elements found within. You can press the Export FLA/FLEX button to attempt to extract an FLA file it finds.

The only issue I’ve encountered so far is how it handles text. The text inside TextField objects may not display properly you export them has TextFields. You can export them as graphics and they’ll appear correctly, but you won’t be able to edit the text should you need to.

Exporting Code And Assets From The SWF

When you open the the FLA file using Adobe Animate, it will contain all assets inside. However, you can still all the extract individual assets to separate files (many will be contained inside smaller FLAs) using the Export Resources button.

For some resources, you can specify the format you want them to export to. I find FLA useful for things like buttons and actions.

This method can be useful if you want to export graphics and button images, because the FLA files that they are contained within will already have the stage size to match the graphic you’re exporting.

As for the ActionScript code, if there was any code placed inside timelines of the FLA, they will be preserved in the conversion process, which is super. Your task here – and this is the most laborious part of the process – would be to rewrite all the ActionScript code to JavaScript (or TypeScript in my case). But at least you don’t have to reinvent the wheel, with designing the game’s logic, as the previous programmer has already done that for you. 😏

Rebuilding The Game Into HTML5

After you’ve exported all the assets, next begins the process of transferring graphics to your new HTML5 project. Raster graphics such as bitmaps, PNGs, and JPEGs can simply be copied over if exported in their native formats. However, for vector graphics, you’ll need to export them as rasters, so they can be loaded onto the HTML5 canvas. Adobe Animate can do this conversion for you.

You can package up all the extracted graphics into one or more spritesheets using TexturePacker. And if you’re using an HTML5 canvas engine like Phaser, it has built-in support for the TexturePacker spritesheets.

If there were animations – hopefully simple ones – you’ll need to extract each frame as a separate raster graphic, then rebuild the animation for use with canvas. Again, Phaser, if you’re using it, can rebuild the animations.

As a super bonus ⭐… If you’re using Phaser, you can use Phaser Editor to rebuild the layouts exactly as they were (or as close to it as possible) in the original Flash. I’ve demonstrated this before, and you can use the Editor along with the newly extracted graphics to convert your Flash stage to a Phaser scene.

Export to HTML5

I previously mentioned that the decompiler can export to HTML5. If your Flash is simple enough, I suspect this can convert your Flash game without incident. I say suspect, because, unfortunately, when I tried it, it didn’t work out too well for me.

When I tried it, it produced two files: one HTML file, and once JavaScript file. However, when I ran it, it didn’t behave as intended. The stage content was transitioning from one frame to the next, but it was leaving behind the previous frame’s content. Furthermore, the game logic wasn’t running as expected. Here’s a screenshot of the result:

The text from the previous frames wasn’t removed, and they’re jumbled behind the current frame’s text.

So, let’s have a look inside the HTML and JavaScript files:

What the…! 😵

Good luck trying to edit that! Even with a code formatter like this one, you’ll still be hardpressed with fixing the game to make it work. As I’ve said before, best to rebuild the codebase from scratch, converting the ActionScript code to JavaScript/TypeScript.

Closing

Even if you don’t have the original FLA and assets, there may be a way to still convert the Flash game to HTML5 with a tool like Sothing SWF Decompiler. Overall, I’ve not had much trouble using this tool, and I would recommended giving the trial a try if you’re working to convert your Flash content.

And if you can’t (or don’t want to ) be bothered with the conversion process, reach out to me. I could take a look at your SWF. Or even if you have all the original code and assets, and are looking for a programmer to convert it for you, contact me directly at
cartrell @ gameplaycoder dot com, or you can use this contact form.

And if you’d like to get on my e-mailing list, you can sign up using the form below. There, you’ll get first access to projects that I’m working one as I make noteworthy process. You’ll see the games I work on come to life as I continually work on them.

Thanks for reading! Talk to you next time,

– C. out.

What’s Next

Hey guys,

It’s been pretty quiet lately here on GameplayCoder, but I’ve also been busy behind the scenes learning new skills for more games to add to my portfolio.

Poker Game

Having finished up the card-matching and hand-comparing techniques for poker, the next project will involve coding an actual poker (Texas Hold’em) game.

As for implementing the rules for poker itself, I found a useful article on 888poker that goes over basics, terminology, and flow of the game. There is also this game available from 24/7 Free Poker, which I’ve been playing to help further understand the game/

But I want it to be a multiplayer game (as well as single-player vs AI), and it’s the multiplayer functionality that will prove most challenging.

So, I’ve been taking a course over on Zenva called MMORPG Academy, which teaches you how to build a multiplayer game using various technologies, and middlewares, including but not limited to:

The only tool in this list I did not use was Docker, because it requires virtualization to run, and if your operating system is Windows 10 Home, you’re pretty much outta luck. Of all the suggestions I’ve tried around the net, none of them worked, and I wasn’t about to upgrade to Pro just for Docker. Besides, you don’t really need it to complete this course anyway.

Everything except Phaser and JavaScript on that list was completely new to me. 🙃 So, I’m taking in a lot of new material in this course. But as Tony Stark himself said,

Flash To HTML5 Game Conversion

According to my data, an article I wrote, Converting a Flash Game To HTML5, by far, has received the most views.

After looking at these numbers, I’m like:

So I will be revisiting this topic by converting another Flash game I coded for a previous client, called Blasteroids. This is a remake of Atari’s Asteroids.

If you’d like to play the Flash game I coded, you can play it on my old portfolio site here. Otherwise, if you can’t (or won’t) be bothered with Flash, you can watch this video of my gameplay – and epic fails. 😅

Thanks for being a reader of this blog, and stay tuned. There’s more to come!

– C. out.

Converting a Flash Game To HTML5

Hey guys,

I’m working on an interesting project now. A repeat client has requested that I convert a cards game I previously made for them from Flash to HTML5.

As you may be aware, Adobe is discontinuing their Flash player browser plugin by the end of 2020.

There really aren’t any true “conversion” tools out there. In other words, say you have a Flash project that consists of a few Flash FLA files with library assets in them, and maybe some exported to external classes, as well as additional external asses loaded at run-time, as well as external AS3 files. And your build process (what you use to generate your final SWF file) uses either Flash CSx/Animate or say, FlashDevelop (good tool, by the way – I highly recommend it if you’re using Adobe AIR to build mobile games).

There is no conversion tool that can just convert all that into a HTML + JavaScript files with all the assets extracted from FLA files, and present you with an HTML index file that you can simply run and be on your merry away.

That. Would. Be. Awesome.

If you want to convert a Flash game to HTML5, you pretty much have to learn JavaScript if you don’t already know it, and rebuild it from scratch).

Depending on the simplicity of your game, you may get some help from Adobe’s Flash Animate, but I’ve never tried it, and due to the complexity of the games I make, it’s likely to not work.

There are several other tools out there, your best bet may be to simple rebuild the code, but you can still use the assets.

However, if you have the original source code – the ActionScript 3 .AS files, sounds, and Flash .FLA files (which I do have because I wrote the original Flash project in the first place) – you already have everything you need to do this. Meaning, you don’t need to go through the trouble of decompiling SWF files and other dubious tasks.

Also, fortunately, the Flash game I’m converting doesn’t do any blitting of bitmaps. All graphics are either bitmaps imported into the FLA, or vector art saves as library symbols. The library symbols can be converted to bitmaps so they can then be used in the HTML5 version.

The biggest challenge for assets and layout is no longer having a super-convenient WSYISYG (what you see is what you get) editor like Flash CS/Animate. This allows you to place and size the objects in a scene as they should look when the game is running. Without this vital tool, you have a few options:

1). Hard-code all the sizes and positions of everything, and references to what everything looks like. (OUCH! This is not the old days of game development. I’m pretty sure we can come up with something quicker and easier, right? 🤔 )

2). Use an editor, like Phaser Editor. A visual editor to build your layout, position and size objects on the scene. This editor has a built-in code Canvas Compiler that will translate your layout into JavaScript code, placing and sizing all your objects for you. You can then focus on building the layout. Now…

For the most part, converting AS3 to JavaScript files is fairly simple. Although it’s a laborious task of recoding, ActionScript 3 and JavaScript share many similarities, both having roots in the ECMAScript standards for example. Sure, you can’t just copy AS3 code, paste it into a JS file and call it a day, but if you know both languages well, the conversion process isn’t all that painful.

Here a quick example of an original source file written in AS3 for Flash, and below it, the JavaScript counterpart.

public final class EZ_PlayerData {
  private var mvo_dailyScores:Vector.<BJ_DailyScoresData>;
  private var mvo_cardsData:Vector.<EZ_PlayerCardsData>;
  private var mn_betValue:Number;
  private var mn_credits:Number;
  private var mu_selectedHandIndex:uint;
  private var mn_tournamentCredits:Number;
  private var mb_isTournamentEnabled:Boolean;
  
  ////////////////////////////////////////////////////////////////////
  // ctor
  public function EZ_PlayerData(u_maxHands:uint, u_maxCardsPerHand:uint) {
    super();
    
    mn_betValue = mn_credits = mn_tournamentCredits = 0;
    mvo_dailyScores = new Vector.<BJ_DailyScoresData>();
    
    mvo_cardsData = new Vector.<EZ_PlayerCardsData>(u_maxHands);
    for (var u_index:uint = 0; u_index < u_maxHands; u_index++) {
      mvo_cardsData[u_index] = new EZ_PlayerCardsData(u_index, u_maxCardsPerHand);
    }
  }
  
  ////////////////////////////////////////////////////////////////////
  // public functions
  
  //==================================================================
  // addDailyScore
  //==================================================================
  public function addDailyScore(o_score:BJ_DailyScoresData):void {
    if (!o_score) {
      return;
    }
    
    mvo_dailyScores.push(o_score);
    mvo_dailyScores.sort(onSortDailyScores);
  }
  
  //==================================================================
  // betValue (get)
  //==================================================================
  public function get betValue():Number {
    return(mn_betValue);
  }
  
  //==================================================================
  // betValue (set)
  //==================================================================
  public function set betValue(n_value:Number):void {
    if (!isNaN(n_value)) {
      mn_betValue = n_value;
    }
  }
  
  //==================================================================
  // cardsData (get)
  //==================================================================
  public function get cardsData():Vector.<EZ_PlayerCardsData> {
    return(mvo_cardsData);
  }
  
  //==================================================================
  // credits (get)
  //==================================================================
  public function get credits():Number {
    return(mn_credits);
  }
  
  //==================================================================
  // credits (set)
  //==================================================================
  public function set credits(n_value:Number):void {
    if (!isNaN(n_value)) {
      mn_credits = n_value;
    }
  }
  
  //==================================================================
  // getDailyScores
  //==================================================================
  public function getDailyScores():Vector.<BJ_DailyScoresData> {
    return(mvo_dailyScores);
  }
  
  //==================================================================
  // isTournamentEnabled (get)
  //==================================================================
  public function get isTournamentEnabled():Boolean {
    return(mb_isTournamentEnabled);
  }
  
  //==================================================================
  // isTournamentEnabled (set)
  //==================================================================
  public function set isTournamentEnabled(b_value:Boolean):void {
    mb_isTournamentEnabled = b_value;
  }
  
  //==================================================================
  // removeLastDailyScore
  //==================================================================
  public function removeLastDailyScore():BJ_DailyScoresData {
    return(mvo_dailyScores.pop());
  }
  
  //==================================================================
  // selectedHandIndex (get)
  //==================================================================
  public function get selectedHandIndex():uint {
    return(mu_selectedHandIndex);
  }
  
  //==================================================================
  // selectedHandIndex (set)
  //==================================================================
  public function set selectedHandIndex(u_value:uint):void {
    mu_selectedHandIndex = u_value;
  }
  
  //==================================================================
  // tournamentCredits (get)
  //==================================================================
  public function get tournamentCredits():Number {
    return(mn_tournamentCredits);
  }
  
  //==================================================================
  // tournamentCredits (set)
  //==================================================================
  public function set tournamentCredits(n_value:Number):void {
    if (!isNaN(n_value)) {
      mn_tournamentCredits = n_value;
    }
  }
  
  ////////////////////////////////////////////////////////////////////
  // private functions
  
  //==================================================================
  // onSortDailyScores
  //==================================================================
  private function onSortDailyScores(o_score1:BJ_DailyScoresData, o_score2:BJ_DailyScoresData):Number {
    if (o_score1.score >= o_score2.score) {
      return( -1);
    }
    
    return(1);
  }
}

And here is the corresponding JavaScript code:

(function(global) {
  global.Multiplay = global.Multiplay || {};
  Multiplay.PlayerData = Multiplay.PlayerData || {};
  
  //===========================================================================================
  //"public"
  
  //-------------------------------------------------------------------------------------------
  //ctor
  //-------------------------------------------------------------------------------------------
  Multiplay.PlayerData = function(u_maxHands, u_maxCardsPerHand) {
    this.dailyScores = [];
    this.betValue = 0;
    this.credits = 0;
    this.selectedHandIndex = 0;
    this.tournamentCredits = 0;
    this.isTournamentEnabled = false;
    
    this.cardsData = [];
    for (var u_index = 0; u_index < u_maxHands; u_index++) {
      this.cardsData.push(new Multiplay.PlayerCardsData(u_index, u_maxCardsPerHand));
    }
  };
  
  //-------------------------------------------------------------------------------------------
  //addDailyScore
  //-------------------------------------------------------------------------------------------
  Multiplay.PlayerData.prototype.addDailyScore = function(dailyScoreData) {
    if (!dailyScoreData) {
      return;
    }
    
    this.dailyScores.push(dailyScoreData);
    this.dailyScores.sort(this._onSortDailyScores);
  };
  
  //-------------------------------------------------------------------------------------------
  //removeLastDailyScore
  //-------------------------------------------------------------------------------------------
  Multiplay.PlayerData.prototype.removeLastDailyScore = function() {
    return(this.dailyScores.pop());
  };
  
  //===========================================================================================
  //"private"
  
  //-------------------------------------------------------------------------------------------
  //_onSortDailyScores
  //-------------------------------------------------------------------------------------------
  Multiplay.PlayerData.prototype._onSortDailyScores = function(score1, score2) {
    if (score1.score >= score2.score) {
      return( -1);
    }
    
    return(1);
  };
})(window);

AS3 takes the usual object oriented programming approach with classes, by defining an actual ‘class’, its constructor, and added properties and methods onto that class.

JavaScript uses protoypes, and a function of the same name as the “class” acts like a constructor. You then add functions onto the prototype which act like the class’s methods.

Due to the absence of public getter/setter properties, the JavaScript file turned out to be way shorter than the original ActionScript. However, you have to be careful when accessing members of the Multiplay.PlayerData prototype, that you don’t accidentally modify a member intended to be treated as private. In JavaScript, I precede such functions and members with an underscore ( _ ).

Throughout the conversion process, I highly recommend that you constantly test the code in small updates to ensure that the code is working as expected (much like you would when building any game, but especially here). I convert AS3 classes as few as possible at a time, then re-test for errors.

How Phaser Editor Helps

Other than the aforementioned benefits of using a WSYIWYG editor, Phaser Editor also allows you to write custom code in the same files that it creates with its canvas compiler.

In most cases, I prefer to keep the UI code separate from logic/business/implementation code, adapting some concepts from Model View Controller design pattern. This makes it easier for me to convert classes from AS3 to JS, since the UI and logic code will be implemented different in the two scripting languages.

That said, in the files generated by the Phaser Editor canvas compiler, I can add an “initialization” method call the editor’s User Code section, and from there, set up all the UI objects that were created on the canvas.

This one line is the only one I write in the Create tab of the User Code dialog. I prefer to keep code in here minimal and focus on write what the _init does in the user code section of the canvas JS file. Phaser Editor will reserve areas of the JS file as user code for you, and the code there will not be overwritten the next time you save the canvas layout (which will cause the canvas compiler to update the corresponding JS file, overwriting any unsaved changes – make sure you always save your JS file first before going saving new changes in the editor’s canvas!)

In the “user code here” section of the JS file (marked by Phaser Editor in a commented at the bottom of the file), I defined an empty _init function. This is where you can custom setup any UI objects, and we’ll be revisiting this later.

GameView.prototype._init = function () {
};
Converting a Button

Next, say I want to create (or “re-create”, as we’re rebuilding the original Flash layout 😉 ) a button on the canvas named btnBet1 (from the casino cards game I’m converting for my client). Because I also have the field property set to true, the canvas compiler will create a property on the JavaScript file of the corresponding canvas called fBtnBet1. I also have the callback property set to a method on this instance of the canvas object this._onBet1Pressed. In my user code, I can define the _onBet1Pressed function. You’ll also want to add the button frames for over, out, down, and up so your button can respond to the various button states.

The canvas file is actually a Phaser state, and the canvas compiler will automatically generate the following code in the state’s create method:

var _btnBet1 = this.add.button(931.0, 753.0, 'some_atlas', this._onBet1Pressed, this, 'bet_up_1_over', 'bet_up_1_norm', 'bet_up_1_over', 'bet_up_1_over', _buttons);
...
this.fBtnBet1 = _btnBet1;

In the user code section of the JS file, I can create the button pressed callback function like this:

GameView.prototype._onBet1Pressed = function () {
};

It’s similar to a MouseEvent handler from ActionScript 3 when setting up a button to respond to mouse clicks.

Keeping the UI code and implementation code separate, I won’t include what the button actually does inside this method. Instead, I’ll have it dispatch a notification, via a Phase Signal. I treat the signal is treated as a public property of the canvas object, and I define the signal in the _init method created earlier:

GameView.prototype._init = function () {
  this.onBetButtonPressed = new Phaser.Signal();
};

When the button is pressed, I want that signal to fire a notification to be handled by the implementation code. Modifying the _onBet1Pressed function, it now looks like this:

GameView.prototype._onBet1Pressed = function () {
  this.onBetButtonPressed.dispatch();
};

There is no logic code in this canvas JS file, since it’s for UI only. The implementation is handled by the code that processes the game logic. First, it assigns a function to be handled by the signal when it dispatches a notification:

var gameView;
...
gameView.onBetButtonPressed.add(function() {
  //do whatever when the button is pressed
});

Instead of inlining the function, you can also pass in a function reference:

gameView.onBetButtonPressed.add(onBetBtnPressed);
...
function onBetBtnPressed() {
  //do whatever when the button is pressed
}

That’s pretty much how all the buttons will be converted.

Converting Fonts

Fonts is a big one. In Flash, you can embed fonts directly into the SWF file to make sure that the fonts will show up, even if the fonts aren’t installed on the end users’ machines. However, you can’t do this with HTML5. Instead, you have to either use web fonts something like this, or you can use bitmap fonts. Phaser Editor can not show all the fonts installed on your system. A quick excerpt from this page about fonts in Phaser Editor:

Phaser Editor uses JavaFX to render the scenes but Phaser uses the browser for the same purpose. This means that in some cases the text object is not rendered in design-time like Phaser renders it at run-time.

Note that Phaser Editor can use the fonts installed in the OS, but the majority of them are not available in all platforms, so we recommend to use safe fonts or load the font files in the CSS of your game.

I decided to go with using Bitmap fonts. Phaser Editor also supports bitmap fonts. This means, I have to create a texture atlas and corresponding XML for all the fonts I want to use. There are a few tools out there for this task:

For this project, I went with the Generator. While it’s not as powerful as Littera in terms of customizations, because it supports font formats other than only True Type. And this game does use some True Type fonts, and I want to be as faithful to the original implementation as possible.

A quick note on using the Generator. When it creates your text image atlas, you’ll also get a .FNT data file. This is the XML file that Phaser (and Phaser Editor) uses when setting up bitmap fonts. You can simply rename the extension from FNT to XML, and you should be good.

That’s the jist of what I’ve done, and so far, I’m not running into any major hurdles. It’s just a detailed process, and you should convert and test in small increments. I may write future updates to this if I encounter anything that warrants an article. I’m thinking timeline animations, but because I didn’t use any in this game, I don’t expect any issues there.

That’s all for now guys. Thanks, and I’ll talk to you next time. Take care!

– C. out.

Thunderjack! (HTML5 Version) and Phaser Editor

Hey there.

In addition to the Android version of Thunderjack! that I’m working on, I’ve also started a browser version, using HTML5. Flash is reaching its end-of-life, but browser games are still a thing. So, HTML5 is the next step for me, and I’ve been improving my skills to produce web-based games that do not use a plugin.

I found Phaser, an HTML5 game development library, and started learning it. This library is incredible! I’ve used it to create my first HTML5 game, Brickout.

Sure, I’m not the biggest fan of JavaScript (I took this course to get some quick JavaScript training), but that’s a relatively small hurdle to overcome – especially if you were like me – ego and attitude was keeping you from learning JavaScript.

I also wanted some sort of WYSIWYG IDE for designing the visual aspects of HTML5 games, similar to Adobe Flash/Animate. Eventually, I found the Phaser Editor.

Giving this software a try, I’m really liking most of what I’m finding with this editor. When you add visual objects the canvas scene, Phaser Editor generates the JavaScript code that creates those Phaser objects. No more having to hard-code things like the x/y positions of objects and line up your objects using trial and error.

You can even create custom, re-useable objects (known as prefabs in Phaser Editor), which can really facilitate the building process.

While the learning curve isn’t too steep, though I would have liked to see a tutorial that creates a game using the editor from scratch, rather than a pre-made game.

This editor also comes with its own JavaScript coding editor, with many of the standard features you’d expect from an editor, such as auto-completions, listing of JavaScript and Phaser API methods, code refactoring, and more.

Phaser Editor comes in two flavors: free and paid. The free version has some limitations, but not enough to stop you unless you’re building a massive game.

Overall, this is a very handy tool, and I’m excited about integrating it into my workflow as I add HTML5 game coding to my list of services.

More updates on Thunderjack! will be in the coming weeks. Stay tuned.

Talk to you soon.
– C. out.

Tools I Use

Hey.

I want to fill you in on the tools and resources I use when I’m coding games. This is not an exhaustive list.

Coding Editors/IDEs

  • FlashDevelop
    My current go-to IDE for all things ActionScript 3. I also like how it can download and configure updates of the Adobe AIR and Flex SDKs.
  • Adobe Flash CS/Animate
    I don’t use this for coding, but for managing assets. While I’m not an artist, graphic designer, game designer, I find its visual editor very easy to use and mostly intuitive.
  • Brackets
    Been using this free editor for a little while. I use it for JavaScript when coding HTML5 games using Phaser.

Programming Languages/Engines/SDKs/Runtimes

  • Adobe AIR
    Despite Flash being retired soon, Adobe AIR is still at large. AIR is not the same thing as Flash – they both happen to use ActionScript 3 and many of the same APIs (with AIR having access to many more of them, partly due to it being able to target desktops). Plus, Adobe AIR can be used to target mobile (Android and IOs) from the same code with minor changes.
  • Adobe Flash
    Yes, I know Flash will no longer be updated or distributed by end of 2020, but until then, hey, it’s still being used.
  • Phaser
    I only care enough about HTML5 and JavaScript because of Phaser and it’s capabilities for game making. I don’t give a damn about web development.
  • Unity
    While I haven’t used Unity to make any games yet, I found a good course on Udemy for it.

Graphics

  • Paint.NET
    I use this for editing of bitmap files. Another simple and intuitive tool to use.

Project Management

  • Trello
    A free online tool for keeping track of my progress, especially when working on larger projects. I use it in a Kanban style, and I’ll have three major categories for tasks: Backlog; Work In Progress; and Ready for Testing. Once the client has tested the latest updates and all’s well, I will archive all the tasks in the Ready for Testing category, and start anew.

Source Control

  • GitHub
    Using Git as the version control system.
    You can find me here, hint, hint.
  • Bitbucket
    I also use Git here, but have tried Mercurial.

Audio

  • Wavosaur
    Simple tool for editing audio files.
  • Audacity
    Not as easy to use as Wavosaur, but it has more functions, particularly in terms of effects you can apple to sounds.

Music

 

So, that’s pretty much the jist of what I use. If you have any questions about anything here, let me know in the comments!

– C. out.