Overriding Inherited Functions in Flixel
I now have working tower select buttons on the side menu and the ability to pause, unpause and speed up the game working again. In order to get these abilities working, I had to override Flixel’s default update() function on PlayState (an extention of FlxState). Things can get messy real quick when changing those inherited functions, so I’ll share some of the issues I ran in to, but first, here’s a video of the game’s current status.
First of all, when I override the update() function for a FlxSprite, I’m usually trying to add behavior without removing the default behavior. To do this, I start with this basic function override:
override public function update():void { super.update(); //Add new code here }
All this does is override the inherited update() function, with a new function that calls super.update() (the inherited version of update). You can then add any additional code as needed.
My favorite addition this iteration is the ability to speed up and slow down the game. I did this by rewriting PlayState’s update() function to this:
override public function update():void { for (var i:int = 0; i < gameSpeed; i++) { super.update(); } }
This was a really simple way to add this feature. It just runs the update code as many times as needed per frame in order to reach the requested speed. Note: if gameSpeed is 0 or less, the update function won’t be run at all, effectively pausing the game.
Now, for anyone that’s played a standard Tower Defense game, you’ll know that you usually want to place some towers before the enemies start coming. To do this, the game should start in a “paused” state and then let you “unpause” to start the enemy waves. If you haven’t played a Tower Defense game, think of it like the Sims. You go into build mode to add your furniture so that the Sims aren’t getting in your way while you place things. Having this pause function lets you do that.
Unfortunately, I placed the code that enables you to press buttons and that let’s your currently selected tower follow your mouse into the TowerMenu.update() and Tower.update() functions respectively. Those functions are called from FlxState’s update function. And when gameSpeed is set to 0, FlxState’s update function is never called. To make matters worse, the code that tells the towers to fire is located in Tower.update(). So if I just call that function while the game is paused, the towers would keep firing.
My solution was to move those pieces of code directly into the PlayState class. Since the code only affect one specific object (the currently selected Tower) and not every Tower object, it’s okay to take that code out of the Tower class. So here’s my new PlayState.update() function:
override public function update():void { for (var i:int = 0; i < gameSpeed; i++) { super.update(); } this.runNonGameUpdates(); } public function runNonGameUpdates():void { var tileWidth:int = Registry.currentLevel.xWidth; var tileHeight:int = Registry.currentLevel.yWidth; if(this.activeTower !== null) { this.activeTower.x = FlxG.mouse.x - FlxG.mouse.x % tileWidth; this.activeTower.y = FlxG.mouse.y - FlxG.mouse.y % tileHeight; if (FlxG.mouse.justReleased()) { this.activeTower.placed = true; this.activeTower = null; } } Registry.towerMenu.checkMenuButtons(); }
That Registry.towerMenu.checkMenuButtons() is where the code checks if menu buttons are being pressed. Flixel doesn’t have a function to check if a FlxSprite was just clicked, so what I did was add code that would get checked when FlxG.mouse.justPressed() is true and again when FlxG.mouse.justReleased() is true. When pressing the mouse, the code checks to see if your mouse is on top of a button and then sets that as the active button. When the mouse is once again released, it checks to make sure your mouse is on top of the same button. If it is, the button’s clicked function is activated. Afterwards, regardless of whether a button was “clicked” the active button is cleared out. Here’s what the code looks like:
public function mouseButton():int { var i:int; for (i = 0; i < TowerMenu.buttonCount; i++) { if (FlxG.mouse.x >= TowerMenu.startX && FlxG.mouse.x <= (TowerMenu.startX + buttonWidth) && FlxG.mouse.y >= (TowerMenu.startY + (buttonHeight + buttonGap) * i) && FlxG.mouse.y <= (TowerMenu.startY + buttonHeight * (i + 1) + buttonGap * i)) { return i; } } return -1; } public function checkMenuButtons():void { if (FlxG.mouse.justPressed()) { TowerMenu.buttonPushed = this.mouseButton(); } if (FlxG.mouse.justReleased()) { if (TowerMenu.buttonPushed == this.mouseButton() && TowerMenu.buttonPushed >= 0) { Registry.playState.setActiveTower(TowerMenu.buttonPushed); } TowerMenu.buttonPushed = -1; } }
So now that I’ve got this code working, it’s time to add the bottom menu that tracks current funds, health, waves remaining and some victory/loss conditions. I think that will bring me back to where I was before I switched to Flixel. So far, it’s been a lot easier using Flixel. I’ll definitely be using it for any future game jams, because it makes prototyping a lot easier.
Recent Comments