DeathRun Part 7 : Background graphics and map changes

I've made some quick changes to DeathRun in preparation for changes to come.  At this point the base game is finished and working and all the major components are in place.  Next I need to start working on content generation and figuring out how the game is going to flow.  So I wanted to generate some new content and get it into the game.  The goal is to be able to create new content and integrate it with what I already have quickly and easily, so this will be a good test.

Adding a new enemy

I decided to add a new enemy to the game.  This is an enemy that simply jumps up and down in one place.  There isn't much logic to it, so the framework that I've already built should work nicely. 

I created a new class called Jumper.hx.  There isn't much in there.  Here's the contents:

class Jumper extends Enemy
{

	var JMPSTR = 600;
	public function new(X:Float=0, Y:Float=0) 
	{
		super(X, Y);
		makeGraphic(50, 50, FlxColor.RED);
	}
	
	override public function step() 
	{
		if (isTouching(FlxObject.FLOOR))
		velocity.y = -JMPSTR;
	}
	
}

In my new funciton I'm just making a red rectangle as a temporary placement.  My enemy class takes care of the gravity already, so there isn't anything that I need to add. 

Next I overrode my step function which is called during every update.  It just has a simple statement that says if the Jumper is touching the floor jump back up. The Jumper is done.

Now I'll add him to the game in the LevelState.create() function.

addEnemy(new Jumper(), 1200, 100);

Done!  He is jumping up and down in the game with no issues.  He can be killed and respawns normally and hurts the player when touched.  All for only a couple lines of code.  I'm extremely happy with how this turned out.

DeathRun Part 6 : Basic game in place

I've made a bunch of progress to DeathRun this update.  Here's what is now done.

  • Added in-game changing of Death's acceleration and not just velocity
  • Added debug code to help me see what is going on for animations
  • Added animations to Death and Guy
  • Changed map
  • Camera follows player instead of static placement
  • Added support for multiple platform types
  • Drop through platforms added
  • Death kills targets when he hits them
  • Enemies hurt player
  • Dead player and enemies respawn on from the top of the screen.

This is quite a lot, but really most of the code is very simple.  Click Read More for more details or to play the game in its current state.

DeathRun Part 5 : Enemies, taunting and general tweaking (not in that order)

Now that I've got Death moving around the stage and chasing the player I've got a couple more mechanics to work on before the game becomes technically playable.  I know I've got to add some enemies to the game, and I know that I want the player to be able to taunt Death to make him charge.  I also realized that the last time I was testing the game my laptop was doing updates in the background so the framerate was lower than normal.  As a result, when I played the game later at the normal rate it moved much faster than I thought it would.  So I need to balance the speed of the player and Death.

I also need to have some idea how the game plays at different speeds.  My goal is to have Death speed up over time to increase the difficulty, but I'm going to need some playtesting to discover what the upper and lower limits should be.  So I also want a way to change Death's speed in real time so I can test.

Charge of Death

Making Death charge is actually pretty straightforward.  I need a new variable, a new function, and some changes to Death's update function.  The basic plan is when the player taunts, Death will move straight in the direction of the player at a speed that is greater than normal for a set amount of time. 

//Death dash variables
var DASHLEN:Float = .75;
var dashRatio:Float = 2;
var dashTime:Float = 0;


/**
 * Makes Death dash at a target.
 */
public function dashAtTarget() {
	maxVelocity.set(maxSpeed * dashRatio, maxSpeed * dashRatio);
	dashTime = DASHLEN;
	acceleration.set();
	velocity = FlxAngle.rotatePoint(maxSpeed * dashRatio, 0, 0, 0, FlxAngle.angleBetween(this, target, true));
}

I declare three variables at the top of Death.hx.  DASHLEN is how long I want Death to charge for before reverting back to his standard accelerate-at-my-target routine.  DashRatio is how much faster Death should speed up when charging.  Right now it is set to 2, so Death's charge speed is twice his maximum movement speed.  DashTime is a variable that will start at DASHLEN and then count down.  When I hit 0 or below I know that Death is done charging. 

The function dashAtTarget only has a couple lines and sets up for the work to be done in the update function.  The first thing I need to do is change the maxVelocity.  I previously capped this so Death doesn't accelerate to huge speeds, but I need to increase this limit so Death can travel at charge speeds.  Simply setting the limits to maxSpeed*dashRatio takes care of that. 

Next I set my charge countdown timer dashTime to DASHLEN.  This countdown timer will be changed in the update() function.

DeathRun Part 4: Death cometh!

Ok, so now we have a player who can run around the map.  Let's give him something to run from.  Lets code Death!

First I created a new class called Death.hx in my source folder.  I gave Death a base class of FlxSprite because I wanted to use the base functionality of a FlxSprite but I think Death is different enough that I don't want him having any of the code that I end up with in my Entity class.  I may regret this decision later, but it will work for now.

class Death extends FlxSprite
{
	
	//Death movement variables
	var currentSpeed:Int = 100;
	
	//Variable that holds who death should pursue.
	var target:Entity;
	
	public function new(X:Float=0, Y:Float=0, ?SimpleGraphic:Dynamic) 
	{
		super(X, Y);
		makeGraphic(60, 60, FlxColor.PURPLE);
	}
	
	public function setTarget(target:Entity) {
		this.target = target;
	}
	
	override public function update():Void 
	{
		super.update();
		
		//If we have a target...
		if (target != null) {
			acceleration = FlxAngle.rotatePoint(currentSpeed, 0, 0, 0, FlxAngle.angleBetween(this, target, true));
			
		}
		
	}
	
}

DeathRun Part 3: Framework and Player

Now that I have a basic idea of the game I'm ready to start coding.  I like to start creating right away with the goal of getting something playable quickly.  There's nothing worse than investing a lot of time and effort into something only to find out at the end of the process that what you created isn't any fun or worth doing.  So here we go...

Setting up

I'm going to assume that you already have HaxeFlixel installed and configured, but if not you should work off the quite wonderful HaxeFlixel Getting Started page.  It walks you through all the necessary steps to get all the pieces installed that HaxeFlixel needs to run.  I always create new projects using the tools built into HaxeFlixel.  They are easy to access.  Just open up a Command Prompt, browse to the folder you want to create the project in, and use the following:

flixel tpl -n create "DeathRun"

After HaxeFlixel created all the files I needed I started with some initial setup.  I already decided that I wanted to target an 800x800 resolution to start with, so I went into the Project.xml file and made the following changes under Window settings

<!--------------------------------WINDOW SETTINGS------------------------------->
	
<!--These window settings apply to all targets-->
<window width="800" height="800" fps="60" background="#000000" hardware="true" vsync="true" />

This will control the size of the SWF file that is created when I compile the game or the default size of the Neko window that opens when I'm testing.  Now I need to set the game resolution to the same thing.  That is controlled in the Main.hx file.  I made the following changes:

var gameWidth:Int = 800; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
var gameHeight:Int = 800; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class<FlxState> = LevelState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
var framerate:Int = 60; // How many frames per second the game should run at.
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets

The first two variables I changed to be 800x800 so the game resolution and the screen resolution match so I'll be drawing everything at actual size.  The initialState variable I set to be LevelState, which is a thing that I haven't created yet and I'll explain in a minute.  I left the zoom and framerate alone but changed the skipSplash Boolean to true so it doesn't show me the HaxeFlixel logo every time I want to test a change.  I'll turn it back on when I go to release the game so people will know what I used to make it, but for now it will just get on my nerves every time I want to test.  I left the full screen variable at false too since I'm not worrying about a desktop target release at this time.

Now I have to create a new State called LevelState.hx in my source folder.  HaxeFlixel needs to know what state the game should start in.  Later on I'll have a splash screen or a main menu or something, but for now I want a state that I can use to quickly jump into a game.  So I created a new file in the source directory in my project called LevelState.hx and made sure to specify that it extends FlxState like so:


There are a couple more pieces that I want to get set up before I jump into actual code, so I might as well take care of them now.  I want to create some basic game objects that I can use in the future to do the actual work of the game.