Upgrade Guide 3.x


The minimum Haxe version for this release is 3.1.0.

On flash, gamepad support has been added. For your project to work, you have to modify your Project.xml so that either:

  • <set name="SWF_VERSION" value="11.8" /> is used (min. flash player version 11.8) or
  • <haxedef name="FLX_NO_GAMEPAD" if="flash" /> is used.

When compiling to HTML5, make sure to remove <haxelib name="openfl" /> from your Project.xml. This is already being handled in flixel's own include.xml.

HaxeFlixel 3.2.x HaxeFlixel 3.3.0
FlxTween.multiVar() FlxTween.tween()
FlxTween.singleVar() FlxTween.tween()
FlxTween.fader(0, 5); FlxTween.tween(FlxG.sound, {volume: 0}, 5);
FlxSound.survive FlxSound.persist
MouseEventManager.addSprite() MouseEventManager.add()
FlxObject.forceComplexRender = true; FlxObject.pixelPerfectRender = false;
FlxText.width FlxText.fieldWidth
FlxSprite.setOriginToCenter() FlxSprite.centerOrigin()
FlxG.safeDestroy() FlxDestroyUtil.destroy()
FlxTilemap.scaleX FlxTilemap.scale.x
FlxTilemap.scaleY FlxTilemap.scale.y
sprite.animation.addByIndicies() sprite.animation.addByIndices()
sprite.animation.addByStringIndicies() sprite.animation.addByStringIndices()
FlxTimer.userData removed
FlxTween.userData removed
FlxG.sound.add() FlxG.sound.cache()

There has also been a slight optimization for simple FlxSprites in FLX_RENDER_BLIT mode (flash and HTML5). This might require an additional dirty = true; for the change to show up if you manipulate the sprite's BitmapData directly.

FlxSprite flipping

Flipping sprite graphics now works differently - the flipped variable has been removed, as well as the Reverse parameter of loadGraphic() and loadGraphicFromTexture(). You can now directly manipulate the new flipX and flipY variables (flipping vertically is now possible).

If you want to continue to use facing to flip the graphic (e.g. in a platformer), you can use the following logic:

sprite.setFacingFlip(RIGHT, false, false);
sprite.setFacingFlip(LEFT, true, false);

FlxTimer and FlxPath

FlxPath and FlxTimer were being pooled internally, which could lead to buggy behaviour in certain use cases. Due to that, pooling has been removed from these classes.

HaxeFlixel 3.2.x HaxeFlixel 3.3.0
start() new FlxTimer() / FlxPath()
run() start()

Also, the following API changes have been made for consistency:

HaxeFlixel 3.2.x HaxeFlixel 3.3.0
paused active
abort() cancel()


HaxeFlixel 3.1.0 HaxeFlixel 3.2.0
FlxTween.multiVar(object, vars, duration, { delay: 1}); FlxTween.multiVar(object, vars, duration, { startDelay: 1});
FlxG.camera.followAdjust(4, 5); FlxG.cameras.followLead.set(4, 5);
FlxTilemap.arrayToCSV() FlxStringUtil.arrayToCSV()
FlxTilemap.bitmapToCSV() FlxStringUtil.bitmapToCSV()
FlxTilemap.imageToCSV() FlxStringUtil.imageToCSV()
FlxMath.computeVelocity() FlxVelocity.computeVelocity()
FlxState.setSubState() FlxState.openSubState()


HaxeFlixel 3.1 is a continuation of our efforts of making the API cleaner and more intuitive, keeping the amount of bugs as low as possible and adding new features. It is one of the biggest releases so far.

This page is a summary of all breaking changes - for a more in-depth list of changes, please refer to the changelog.

FlxTypedButton / FlxButton refactor

FlxTypedButton has been completely refactored, which includes the following breaking API changes:

  • A new FlxButtonEvent class was added for the onDown, onUp, onOver and onOut events. Instead of the setCallback()-functions, you now set callbacks like this:

    button.onDown.callback = someFunction;

    This class also contains a sound property:

    button.onDown.sound = FlxG.sound.load("pathToASound");

    You might say: "What happened to custom callback arguments? The callback has the type Void->Void!" While that's true, you can still use callback arguments by leveraging function binding:

    button.onDown.callback = someFunction.bind(1);

    In that example, someFunction is of type Int->Void and will always be called with 1.

  • labelOffset:FlxPoint is now an array (labelOffsets:Array<FlxPoint>) which uses the button status constants as indices for more control over the button position.

  • The highlight frame of the button spritesheet is now ignored by default on mobile devices, since it does not make much sense there - you can't hover over a button on a touchscreen.

  • It is now possible to "swipe-press" a button, which means you can press it if the input (mouse or touch) has been moved over the button and then released. Previously, you could only press a button if the press happened while you were already hovering over the button. This especially makes FlxVirtualPad more usable.

FlxG.keys and FlxG.keyboard

In 3.0.0, FlxG.keyboard has been introduced. However, we realized that this does not make for an intuitive API - you can't tell the difference between the two from their name alone. In fact, even if you have been using the two for a while, it still seems confusing.

This is why me merged the two classes again. This required removing the following functions:

  • FlxG.keyboard.pressed()
  • FlxG.keyboard.justPressed()
  • FlxG.keyboard.justReleased()

You should use the following functions instead:

  • FlxG.keys.anyPressed()
  • FlxG.keys.anyJustPressed()
  • FlxG.keys.anyJustReleased()

Please note that those functions take an Array<String> instead of a variable amount of Strings. So the following...

if (FlxG.keyboard.pressed("LEFT", "RIGHT")) {}


if (FlxG.keys.anyPressed(["LEFT", "RIGHT"])) {}

FlxMouse refactor

The following breaking changes were made during the refactor of FlxMouse:

HaxeFlixel 3.0.x HaxeFlixel 3.1.0
FlxG.mouse.show(); FlxG.mouse.visible = true;
FlxG.mouse.hide(); FlxG.mouse.visible = false;
FlxState.useMouse removed

Also, the mouse cursor is now visible by default on non-mobile devices.

The middle and right click event listeners are now set up by default, which means FLX_MOUSE_ADVANCED has turned into FLX_NO_MOUSE_ADVANCED.

The recording system and FlxRandom

To put it bluntly... FlxRandom was a bit of a mess in 3.0. Some of the functions were deterministic, others weren't, which as a result made it very difficult to create deterministic games suitable for the recording system.

In 3.1.0, FlxRandom has been refactored to be completely deterministic. A new algorithm for pseudo-random-number-generation was implemented, which makes old replays incompatible / they will have unpredictable results.

Additionally, the following functions have been added to FlxRandom:

  • weightedPick()
  • weightedGetObject()
  • colorExt()

FlxSprite renamings

A noteworthy amount of fields inside of FlxSprite have been renamed to increase the consistency with other parts of the API:

HaxeFlixel 3.0.x HaxeFlixel 3.1.0
loadfromSprite() loadGraphicFromSprite()
setGraphicDimensions() setGraphicSize()
bakedRotation bakedRotationAngle
pixelsOverlapPoint() overlapsPoint()
loadImageFromTexture() loadGraphicFromTexture()
loadRotatedImageFromTexture() loadRotatedGraphicFromTexture()
setColorTransformation() setColorTransform()

Scale Modes

HaxeFlixel 3.1.0 introduces scale modes to simplify targeting multiple resolutions. FlxG.scaleMode can be an instance of the following classes:

  • RatioScaleMode (default!)
  • FillScaleMode
  • FixedScaleMode
  • RelativeScaleMode
  • StageSizeScaleMode

This change made FlxG.autoResize obsolete and it has thus been removed.

You can also write a custom scale mode that extends BaseScaleMode.

Be sure to check out the ScaleModes demo.


The way FlxTypedGroup.sort() has been changed for a significant performance improvement. If you want to sort by y, you now have to use the following syntax:

group.sort(FlxSort.byY, FlxSort.ASCENDING);

Instead of:

group.sort("y", FlxSort.ASCENDING);
// or

If you want to sort by anything other than y, you'll have to write a custom sorting function, as can be seen in this example:

function sortByAlpha(Order:Int, Sprite1:FlxSprite, Sprite2:FlxSprite):Int
	return FlxSort.byValues(Order, Sprite1.alpha, Sprite2.alpha);

// usage on a FlxTypedGroup<FlxSprite>:

Other breaking changes

HaxeFlixel 3.0 HaxeFlixel 3.1
FlxTypedGroup.autoReviveMembers removed
FlxG.gameFramerate FlxG.updateFramerate
FlxG.flashFramerate FlxG.drawFramerate
FlxG.gamepads.get() FlxG.gamepads.getByID()
FlxG.debugger.visualDebug FlxG.debugger.drawDebug
FlxG.paused removed (didn't have any functionality)
FlxArrayUtil.intToString() FlxStringUtil.toIntArray()
FlxArrayUtil.floatToString() FlxStringUtil.toFloatArray()
FlxMisc.openURL() FlxG.openURL()
FlxMisc removed
FlxSoundUtil removed (use a FlxTimer instead)

The classes from flixel.system.input have been moved to flixel.input.

FlxPoints in FlxObject and FlxSprite are now read-only / (default, null), which means you need to use .set() on them if you were previously creating new points. The following...

sprite.velocity = new FlxPoint(100, 50);


sprite.velocity.set(100, 50);


HaxeFlixel 3.0 is an evolution of the original Flixel API and while most of the API is very similar and quickly learnt, it requires some renames and modifications to update your code.

Major changes from version 2.10

We wanted to slim down up the core classes, which meant moving non-essential functionality into separate classes. We've also continued to focus on improving stability and adding features to the engine. Here's a quick overview of the biggest changes:



mySprite.animation.frameName = "String";

mySprite.animation.frameIndex = Int;

//inspect the advanced api features such as
addByNames, addByStringIndicies, addByIndicies, addByPrefix, findSpriteFrame, randomFrame ...

  • Added new FlxKeyShortcuts class, which replaces FlxG.keys. FlxG.keys.pressed is no longer a function, it's now an object, ex: if( FlxG.keys.pressed.ANY ) {...}

  • Added new FlxSpriteGroup class, which allows an FlxGroup to behave like an FlxSprite. This is a powerful new construct that will simplify building UI controls.

  • FlxU is now gone, we've moved all its functionality to several utility classes that specific contain functionality, ex: FlxArrayUtil, FlxAngle, FlxMath, FlxRandom, FlxSpriteUtil, FlxVelocity, etc.

  • FlxSprite Filters are now in a separate FlxSpriteFilter utility class.

Package Structure

HaxeFlixel no longer has an org package. Everything is now included as flixel.package.Class. For most cases you can just remove org. from your import statements.

This was a decision the core developers agreed upon, to make the package structure simpler and detach HaxeFlixel from old flash conventions.

FrontEnds and the FlxG refactor

Frontends in HaxeFlixel 3.x are a new structure to the core of Flixel and which tackles the often criticized bloated collection of static methods in FlxG.

Frontends are accessed in FlxG.frontend in a similar fashion to what Flixel devs are used to. Careful thought has been given to organise them into logical shortcuts. This way the api will be easier browse, remember and maintain.

For example in HaxeFlixel 2.x to add a FlxCamera you would use FlxG.addCamera(camera:FlxCamera);, this addCamera method has been moved into a camera frontend with all the other camera related shortcuts. So the code in HaxeFlixel 3.x to add a FlxCamera is now FlxG.cameras.add(camera:FlxCamera).

The Flixel FrontEnds are as follows:

  • FlxG.inputs
  • FlxG.console
  • FlxG.log
  • FlxG.bmpLog
  • FlxG.watch
  • FlxG.debugger
  • FlxG.vcr
  • FlxG.bitmap
  • FlxG.cameras
  • FlxG.plugins
  • FlxG.sound

More detail on the FrontEnds can be read on the FrontEnd docs page.

Core Assets

HaxeFlixel has system Assets for its debugger buttons, system sounds, etc. These assets were previously stored in every project in the assets/data folder. HaxeFlixel 3.x uses the OpenFL include.xml in core HaxeFlixel to omit the need to include them in every project.

So you do not need to have system assets anymore, everything in your project's ./assets/* folder should only be the assets you create.

New Debugger and Interactive Console

HaxeFlixel 3.x includes a powerful console and improved debugger. The new debugger system by default redirects the core trace() command to the log. Alternatively you can use FlxG.log.add() , FlxG.watch.add(), FlxG.log.warn and more.

New Flixel Command Line Tools

Our command line tools have been moved to an optional repository, so the old haxelib run flixel new command will not work. Install the tools from haxelib just like flixel and run setup and follow the prompts:

haxelib install flixel-tools

haxelib run flixel-tools setup

Now you can use the commands with just flixel, try the help command for more info.

flixel help

//see the new template tool options with:
flixel help template

//Shorthand version to create a template with a custom name
flixel tpl -n "CustomProject"

Automatic find and replace

A collection of most of the API name changes were collected for the flixel-tools command line tool. You can see what it replaces here.

To run the find and replace the command is simple:

flixel convert

FlxG Changes

The main changes that developers will notice are as follows:

HaxeFlixel 2.x HaxeFlixel 3.x
FlxG.getLibraryName() FlxG.libraryName
FlxG.setDebuggerLayout FlxG.debugger.setLayout
FlxG.log trace()
FlxG.resetDebuggerLayout FlxG.debugger.resetLayout
FlxG.visualDebug FlxG.debugger.visualDebug
FlxG.toggleKeys FlxG.debugger.toggleKeys
FlxG.random FlxRandom.float
FlxG.shuffle FlxArrayUtil.shuffle
FlxG.getRandom FlxArrayUtil.getRandom
FlxG.globalSeed FlxRandom.globalSeed
FlxG.tween FlxTween.multiVar
FlxG.resetInput FlxG.inputs.reset
FlxG.RED FlxColor.RED
FlxG.DEG FlxAngle.TO_DEG
FlxG.RAD FlxAngle.TO_RAD
FlxG.flashGfx FlxSpriteUtil.flashGfx
FlxG.flashGfxSprite FlxSpriteUtil.flashGfxSprite
FlxG.levels Reg.levels
FlxG.scores Reg.scores
FlxG.score Reg.score
FlxG.saves Reg.saves
FlxG.save Reg.save
FlxG.addCamera FlxG.cameras.add
FlxG.useBufferLocking FlxG.cameras.useBufferLocking
FlxG.lockCameras FlxG.cameras.lock
FlxG.renderCameras FlxG.cameras.render
FlxG.unlockCameras FlxG.cameras.unlock
FlxG.removeCamera FlxG.cameras.remove
FlxG.resetCameras FlxG.cameras.reset
FlxG.shake FlxG.cameras.shake
FlxG.bgColor FlxG.cameras.bgColor
FlxG.warn FlxG.log.warn
FlxG.error FlxG.log.error
FlxG.notice FlxG.log.notice
FlxG.advancedLog FlxG.log.advanced
FlxG.clearLog FlxG.log.clear
FlxG.watch FlxG.watch.add
FlxG.unwatch FlxG.watch.remove
FlxG.play FlxG.sound.play
FlxG.playMusic FlxG.sound.playMusic
FlxG.loadSound FlxG.sound.load
FlxG.addSound FlxG.sound.add
FlxG.stream FlxG.sound.stream
FlxG.destroySounds FlxG.sound.destroySounds
FlxG.updateSounds FlxG.sound.updateSounds
FlxG.pauseSounds FlxG.sound.pauseSounds
FlxG.resumeSounds FlxG.sound.resumeSounds
FlxG.music FlxG.sound.music
FlxG.sounds FlxG.sound.list
FlxG.mute FlxG.sound.muted
FlxG.volume FlxG.sound.volume
FlxG.volumeHandler FlxG.sound.volumeHandler
FlxG.keyVolumeUp FlxG.sound.keyVolumeUp
FlxG.keyVolumeDown FlxG.sound.keyVolumeDown
FlxG.keyMute FlxG.sound.keyMute
FlxG.addPlugin FlxG.plugins.add
FlxG.getPlugin FlxG.plugins.get
FlxG.removePlugin FlxG.plugins.remove
FlxG.removePluginType FlxG.plugins.removeType
FlxG.updatePlugins FlxG.plugins.update
FlxG.drawPlugins FlxG.plugins.draw
FlxG.plugins FlxG.plugins.list
FlxG.loadReplay FlxG.vcr.loadReplay
FlxG.reloadReplay FlxG.vcr.reloadReplay
FlxG.stopReplay FlxG.vcr.stopReplay
FlxG.recordReplay FlxG.vcr.startRecording
FlxG.stopRecording FlxG.vcr.stopRecording
FlxG.checkBitmapCache FlxG.bitmap.checkCache
FlxG.createBitmap FlxG.bitmap.create
FlxG.addBitmap FlxG.bitmap.add
FlxG.removeBitmap FlxG.bitmap.remove
FlxG.getCacheKeyFor FlxG.bitmap.getCacheKeyFor
FlxG.getUniqueBitmapKey FlxG.bitmap.getUniqueKey
FlxG.clearBitmapCache FlxG.bitmap.clearCache
FlxG.clearAssetsCache FlxG.bitmap.clearAssetsCache