Archive

Archive for the ‘Game Update’ Category

Debug Menu in Flixel

October 29th, 2013 No comments

So for the first feature to review, let’s look at the last one I added, a debug menu.

debugMenu

The textbox on the left displays the details of the current enemy wave list. It’s only there for informational purposes. The one next to it is where the real business is. It can be used to edit and then reset the current wave list. Assuming my towers are already balanced (they’re not), I can use this to tweak the difficulty curve of each level while still in the game. This saves having to re-compile every time I need to update the enemy list for a level.

The other things I can do from this level are remove all the towers from the current level and reset the funds available in the current level. Again, these is used to reset the level state for testing.

The other menus I’d like to add would let me change tower and enemy stats on the fly in order to tweak game balance without having to re-compile. Obviously this menu won’t be in the production release, but it will help immensely during development.

Now, on to the code. My flixel game state is set to a zoom level of 200%. This makes the sprites look a lot better, but text tends to look like crap. My solution is to code all the debug textboxes as regular AS3 textfields overlain on top of the actual game. Here’s the constructor on my DebugMenu class.

public class DebugMenu extends FlxGroup 
{
public var bgSprite:FlxSprite;
public var waveDisplay:TextField;
public var waveEntry:TextField;
public var moneyText:TextField;
public var resetTowerButton:AltButton; // Custom button class
public var resetWaveButton:AltButton;  // extending FlxSprite
public var setMoneyButton:AltButton;   //

public static var width:int = 400;
public static var height:int = 150;

public function DebugMenu() 
{
	bgSprite = new FlxSprite(0, 150, null);
	bgSprite.makeGraphic(DebugMenu.width, DebugMenu.height, 0x00cccccc);
	var gfx:Graphics = FlxG.flashGfx;
	gfx.clear();
	gfx.lineStyle(1, 0x000000, 1);			
	gfx.beginFill(0xffffff, 1);
	gfx.drawRoundRect(0, 0, DebugMenu.width - 1, DebugMenu.height - 1, 3);
	gfx.endFill();
	bgSprite.pixels.draw(FlxG.flashGfxSprite);
	bgSprite.dirty = true;
	bgSprite.exists = true;
	this.add(bgSprite);
	
	waveEntry = new TextField();
	waveEntry.x = 220;
	waveEntry.y = 310;
	waveEntry.width = 200;
	waveEntry.height = 200;
	waveEntry.setTextFormat(new TextFormat(null, 6, 0x000000));
	waveEntry.selectable = true;
	waveEntry.border = true;
	waveEntry.type = TextFieldType.INPUT;
	waveEntry.multiline = true;
	FlxG.stage.addChild(waveEntry);

        //same as above for waveDisplay and moneyText
	
	resetTowerButton = new AltButton(215, 185, 0xcccccc, 
              "Reset Towers", 50, 30, this.destroyAllTowers);
	resetTowerButton.label.color = 0x000000;
	this.add(resetTowerButton);
	
	resetWaveButton = new AltButton(215, 215, 0xcccccc,
              "Reset Waves", 50, 30, this.resetWaveList);
	resetWaveButton.label.color = 0x000000;
	this.add(resetWaveButton);
	
	setMoneyButton = new AltButton(265, 155, 0xcccccc,
              "Set Funds", 50, 30, this.setFunds);
	setMoneyButton.label.color = 0x000000;
	this.add(setMoneyButton);
}

As you can see, all the Flixel elements are added directly to DebugMenu, an extension of FlxGroup. This makes it really easy to show or hide them. On the textfields, making them selectable allows copy/paste operations. The type has to be set to TextFieldType.INPUT in order to alter the contents.

Since I’m using a mix of Flixel objects and AS3 objects, I needed to write an additional function to show/hide the debug menu. If I was just using Flixel objects, setting Registry.debugMenu.exists = false; would hide all the elements. Here’s that code:

public function showHide(makeVisible:Boolean):void {
	if (makeVisible) {
		this.exists = true;
		if(!this.waveEntry.stage) {
			FlxG.stage.addChild(this.waveEntry);
		}
		if(!this.waveDisplay.stage) {
			FlxG.stage.addChild(this.waveDisplay);
		}
		if(!this.moneyText.stage) {
			FlxG.stage.addChild(this.moneyText);
		}
	}
	else {
		this.exists = false;
		if(this.waveEntry.stage) {
			FlxG.stage.removeChild(this.waveEntry);
		}
		if(this.waveDisplay.stage) {
			FlxG.stage.removeChild(this.waveDisplay);
		}
		if(this.moneyText.stage) {
			FlxG.stage.removeChild(this.moneyText);
		}
		FlxG.stage.focus = null;
	}
}

Above is a technique I learned recently that I wish I had known when I was coding this whole thing from scratch in AS3. On a textfield, .stage will be null if the object has not been placed and non-null otherwise. This is the most surefire way to make sure you’re not using .removeChild on an object that hasn’t been placed and that you’re not using .addChild on an object that’s already on the stage.

One last interesting piece of code to deal with textfields in AS3. I thought I could just use .text.split(“n”) to divide the text into an array of lines. Unfortunately, .text removes the new line characters, but using .getRawText().split(“n”); gives you the behavior you want in order to split up the text by line.

In order to get all this stuff working the way I wanted, I needed to rewrite my PlayState class in order to update certain parts of the game when the debug menu is visible, other parts when the game is paused and basically everything when the game is running. I might have shown how I did the last two parts before, but here’s what my PlayState.update() function looks like now.

override public function update():void
{
	//NUMPADPERIOD is used to show and hide the debug menu
	if (FlxG.keys.justPressed("NUMPADPERIOD")) {
		trace("Toggling Debug Menu");
		Registry.debugMenu.showHide(!Registry.debugMenu.exists);
		this.debugActive = !this.debugActive;
	}

	//Freezes everything once the level is over
	if (gameIsOver) {
		if (FlxG.keys.justPressed("ENTER") ||
				FlxG.keys.justPressed("P")) {
			FlxG.switchState(new MenuState());
		}
	}
	//Only update the debug menu when it's visible
	else if (this.debugActive) {
		Registry.debugMenu.update();
	}
	//Update the game otherwise
	else {
		//PlayState.update gets run at 30FPS
		//Scaling gameSpeed allows the game to run
		//At 2x/4x speed in order to fast forward the game
		//This is a common tower defense device
		for (var i:int = 0; i < gameSpeed; i++) {
			super.update();
		}
		
		//Runs things like checking for mouse clicks,
		//button presses and allowing tower placement
		//while the game is paused
		this.runNonGameUpdates();
	}
}

So that’s pretty much it for my debug menu. If you’re curious how the AltButton class is set up, I can answer questions in the comments or do a separate post.

Finding Motivation to Finish a Game

October 27th, 2013 No comments

It’s been a long time since I posted, so here’s a related joke.

Q: How many people does it take to NOT develop a game?

A: Hundreds. One person to not develop it and hundreds to make all the 
   games and books that the one person plays with instead of working 
   on their game.

I’ve been slowly adding things to the game over the last 4 months, but I just couldn’t work up the motivation to make a post until now. I’ll try to post several updates in the near future talking about some of the difficult or fun bits of code I wrote in the last few months. This post is just to talk about the ups and downs of seriously working on a video game.

I have heard many people say that the most important thing for an indie developer to do is to release your games. They said that you will want to keep working on your game until it’s perfect. They said you will have trouble seeing past all the flaws in your game. That you’ll never think it’s good enough. I thought they were all full of shit.

I was wrong.

I went into working on this game saying that I had a reasonable set of features I wanted to include. I was so proud of the first few steps, that I didn’t think I’d ever feel ashamed of showing my game to the public. But as I got closer and closer to having an actual “Game” on my hands, I started to feel less and less confident. When you’re still thinking of your game as a prototype, everything that isn’t broken is a point of pride.

PurePride

Pure Pride

As soon as you start thinking about releasing it, every single flaw sticks out like a sore thumb.

LevelSelectionShit


GameMenuShitComplete Crap

At some point, you have to learn your limits. I can get the buttons and text to look a little better. I can add sound effects and find some music to play during the game. I can even animate the sprites that I currently have. But I can’t make sprites that look much better than they currently do. I can’t design a beautiful looking menu. I can’t write a stirring soundtrack that everyone will want to listen to.

So that’s what my game is going to be. Coherent looking menus, crappy but functional sprites, basic sound effects, basic music and a decent selection of levels. It’s a first game. It will work and I’ll be happy with it. And I will get it released.

I’ve been working on my own game instead of playing other people’s games the last week or two, and I’m very happy with the progress I’ve made in that time. The best advice I can give to anyone else that gets stuck on their first game is to keep pushing through it, because it gets better. My game isn’t ready yet, but I’ve accepted the limits of how good it’s going to be and I know what it’s going to take to get it finished.

Categories: Game Development, Game Update, Personal Tags:

Overriding Inherited Functions in Flixel

June 12th, 2013 No comments

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.

Re-coding complete and then some

May 4th, 2012 2 comments

I’ve completed re-coding my game from scratch and the code is much cleaner and much more reusable this time. I managed to add some background music and sound effects during attacks. I’ve also got a stage selection page working (though admittedly it’s not much at this point). I think it’s much more obvious now which units can still be moved, and the flow of each turn is much smoother (though you’ve lost the ability to attack before moving). The music and sound effects are just filler at the moment, I’m going to try and compose my own bg music at some point. As promised, here’s the video:

Please ignore the 2 spots in the video where the music skips forward. I had a couple bugs pop up that required me to review my code midway through the videos and didn’t have the time to figure out what was causing the errors.

I need some feedback on the control scheme. Currently, you choose to not attack anything by clicking on the unit again or by clicking on an empty attack square. I forgot to show it in the video, but if you click outside of the highlighted move/attack area, you cancel the turn (this can’t be done after an attack is completed). Should I change this? I found myself accidently choosing not to attack a couple times during testing. Would a menu that gives you the option to attack, end or cancel be more useful after the movement selection is complete? Your feedback is appreciated!

I’m Back

May 1st, 2012 2 comments

It’s been a while since I’ve posted anything and I think I can finally share what else I’ve been doing outside of work and programming my game. My wife and I are preparing to move out of state.

We’ve both lived in the Ann Arbor, MI area our whole lives and we’re making plans to move to Savannah, GA this summer. So most of March was spent getting the house ready for sale, applying for jobs and looking at apartments. We took a trip down there in the beginning of April, but weren’t able to anything productive besides relax. I think I’ve finally recovered from all the prep work we had to do and I’m ready to return to game development.

As far as the game goes, my reprogramming from scratch is nearly complete. The game is playable once again by two players and I’m in the process of rewriting the game’s AI. Once that’s done I’ll post another video (this week, I promise). So far I’ve added the ability to switch stages to the game and made it so you can move the screen with a click and drag instead of moving the mouse to the edge of the screen.

Upcoming list of changes:
-Auto end turn after all units have moved
-Highlight units left to move, darken units after turn complete
-Add zombie units to game
-Create unit images/animations (could be a while on this one)
-Add music/sound effects (trying to add temp music/effects soon)

Categories: Game Update, Personal Tags:

First Gameplay Video

March 4th, 2012 1 comment

So it’s another busy weekend, with little time for coding. But I did have time to create a gameplay video from the old code which is currently uploaded to Flash Game License.



Some of the features seen in this video have already been removed from the newest version. The two buttons that appear when you click on a unit have been removed in favor of automatically going to movement. The game no longer scrolls when you go to the edges of the map either, it’s now a click and drag interface.

Also, none of the images in the video are the final versions, they’re just pictures I pulled from Google to have something to work with. Let me know what you think in the comments.

No Work Done in a While

February 29th, 2012 1 comment

So…. not much work has been done on my game lately. I’ve been really busy with house repairs being done last week into this weekend and my car needing to be fixed late this weekend up until today. On a positive note, I’ve been so exhausted when I get home that I’ve been getting 9-10 hours of sleep every day this week. So this weekend I should be good to go.

Also, it seems that computer issues are catching in my house. A week after I recovered my game code with the decompiler, my desktop died. I’m planning on using the desktop to create my game art, so this is yet another set back. I’m going to need to reinstall Windows XP on it, so I’ll do that once I get my installation disk back from my friend. Fortunately, I installed Windows XP on a separate partition from all my data in case of such an issue. So I’ll also start working on my game art this weekend.

I’m not going to wait this long for my next update. I promise something will be done for my game this weekend and if I can figure out my video capture software, I’ll post a video on Sunday.

Decompilers Good, Hibernating Bad

February 11th, 2012 No comments

So I haven’t done any work at all on my game since last weekend. Mostly because losing a week’s worth of work on it was depressing me. I believe I’ve found a way to fix it, but it’s still a pain in the butt.

Hibernation Fail
Here’s what happened. I loaded up my computer on Tuesday night to start doing some coding. FlashDevelop was open when the computer put itself into hibernation due to a low battery. I pulled it up to see this:

FlashDevelop post hibernation

There might not appear to be anything wrong with that at first. The only problem is that when I shut down my computer on Saturday night, I had about 14 classes and there’s only 6 in that picture. I figured, “Well, that just must be because that’s what I had open.” So I browse to the folder where I had been saving all my files. Which I had been saving regularly. And what did I see? 7 files with the last modified date listed as 1/29/2012. Even though I had been working on my code as recently as 2/4/2012.

Looking For The cause
Now I can’t say for sure that it was the hibernation file that caused the issue. I don’t see how loading the contents of RAM should affect a folder full of files saved on the hard drive. I suppose it’s possible that “Saving” was only occurring in FlashDevelop’s memory, but that seems unlikely.

The odd part about it all, was that the compiled swf file – the one that’s created every time I try to debug the game – was still showing a last modified date of 2/4/2012. I loaded it up and, lo and behold, it was the same file I had pulled screenshots from last Saturday.

I still don’t know for sure what happened. But I’ve turned off all hibernation on the laptop just in case. I really don’t mind shutting it down every night when I’m done working. It forces me to save more often anyways.

Finding a Fix
I did try downloading a trial for a deleted files recovery tool. But it acted as if the files had never existed as well. I knew about the importance of securing your code before releasing it into the public. This is because it’s supposed to be really easy to decompile unencrypted flash files. I figured I would look for a decompiler and see what my finished swf file could give me.

I can tell you to NOT try sothink’s swf decompiler. It will let you see your code, but the local variable names will be changed and you can only copy out the code if you buy the full version.

I knew there had to be a free decompiler out there, so I googled “free actionscript 3 decompiler” and was led to F.L.A.S.W.F.. He had links to several decompilers and the one I decided to try was ASDec. Looking at the output I was surprised to find that every variable name is identical to the original version.

My Code Is Reborn!

The decompiler isn’t perfect though. It still has to leave out all the comments because those aren’t compiled at all. It also has many extra lines added in declaring variables and then initializing them on separate lines. Fortunately, it should recompile fine for now and I can update it as I go. I was really concerned for a couple days, but I’m ready to return to coding my game once again.

I’ve learned to appreciate decompilers, so long as they aren’t used to steal my game and pass it off as someone else’s. Anyone else every have computer nightmares resulting in lost code?

Move Engine Recompleted

February 4th, 2012 1 comment

Once again I can move my units as I desire. Next is the reprogramming of the AI. For now, enjoy this screenshot of the movement area, recreated.

3 Steps Forward, 2 Steps Back

Well, time to tuck into bed for the night. While it’s disappointing that I haven’t gotten back to where I was 2 weeks ago, I think I’ll be much happier with the code once it’s done. Just about every variable is private now and the classes are properly encapsulated.

Programming A Click and Drag Function

February 3rd, 2012 No comments

Last night I decided to program in a function to allow easier map scrolling when using mouse controls. Previously I had made it similar to the Wii’s turning functionality in first-person shooters. When you got near the edge of the screen, the game would start to scroll in that direction.

The problems arose when you were just trying to access buttons that were off screen because the game would try to scroll in the direction of the buttons. It was just too easy to accidentally scroll. And if you wanted to scroll to the other side of the screen from where you were, you needed to move your mouse all the way to the other side.

Enter Click and Drag
So last night, I decided I was going to make my game scroll when I clicked and dragged. This was a more intuitive interface, similar to the iPhone’s scrolling functionality.

My first attempt at setting this up had mixed results. The scrolling was jittery and it wasn’t 1:1 for some reason. Check out my code below to see if you can spot the error. For reference, the mouseDown function is called when the user presses the left mouse button while on the map, the mouseUp function is called when the user releases the left mouse button while on the map and the mouseMove function is called when the user moves the mouse around the playField, but only after the mouse button is pressed.

private function mouseDown(e:MouseEvent):void {
	this.startMouseX = this.mouseX;
	this.startMouseY = this.mouseY;
	this.startX = this.x;
	this.startY = this.y;
		
	this.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
	this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
	Main.stageSprite.addEventListener(Event.DEACTIVATE, mouseUp);		
}

private function mouseUp(e:Event):void {
	this.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
	this.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
	Main.stageSprite.removeEventListener(Event.DEACTIVATE, mouseUp);	
}

private function mouseMove(e:Event):void {
	this.x = (this.startX - this.startMouseX + this.mouseX);
	this.y = (this.startY - this.startMouseY + this.mouseY);
}

Ignore the fact that the game will keep scrolling if you happen to release the mouse button while your mouse is outside the flash screen. I haven’t yet figured out how to fix that, so anyone that has a solution should let me know. If you can spot the other error in my code, then you’re a better programmer than I was last night.

The Solution
The problem, it turned out, was caused by my use of this.mouseX and this.mouseY. You see, as you move a sprite around, it’s mouseX and mouseY coordinates change to reflect the relative position of the mouse from the sprite’s (0,0) point, usually the upper-left hand corner.

What was happening was the game would update the mouse coordinates at the same time it tried to update the map’s coordinates. Resulting in what some would call hilarity, but what I called annoyance. To fix the problem, all I had to do was update the references to this.mouseX and this.mouseY to Main.stageSprite.mouseX and Main.stageSprite.mouseY.

Main is my initializing class and stageSprite is a static reference to a sprite that never moves. So as the map scrolled around, the stageSprite stays where it is and provides an accurate reference point to calculate how far the mouse has moved. Here are the results:

Starting Position

The ending point after one click and drag

So overall, I’m pretty happy with the results. I’m trying to reintegrate my old classes for moving units around and attacking other units now. The only problem is that I changed many of the variable names for my units and actually implemented private variables instead of public variables, so I have a lot of updates left to make before I can even run the game without compiler errors. Maybe I just need to program those classes from scratch too. As I write this I’m buzzing from my 2nd coffee this week (I only drink coffee 2-3 times per week to avoid developing a tolerance) and I’m probably feeling way too ambitious. Maybe that’s for the best.