[AS3]Difficulties/Game Mode Setups

11 posts

Flag Post

I have the same game but need to make different game modes. Is it easier to change the variables and only have one Game.as or make 3 different Game.as (Easy, Medium Hard.) I was thinking maybe different classes, EasyGame, MediumGame, HardGame.as, but I wanted the opinion of the community.

 
Flag Post

I think it is probably easier to have just one Class, and use different difficulties as variables to modify various things (like enemy health, damage, time to do things, etc.). It depends a little on your game though.

 
Flag Post

Avoid duplicate code, just add a difficulty variable in your Game.as, set it at the time the player chooses difficulty, and test its value whenever you want to do something that is difficulty-dependent. Otherwise I guarantee you will tire of having to change three files every time you modify something in the game. Tire of it real fast…

 
Flag Post

I spent some time pondering on how to approach this. Did some research, but couldn’t find much. I think I know the part I need to alter, I’m just not sure how to do it.

This is the part of my code that I believe needs to be changed for each difficulty(this is in the game.as)…


public function onTick(timerEvent:TimerEvent):void
{
ball.x += ballSpeedX;
ball.y += ballSpeedY;

The onTick method is what sets off my game and makes it run. ballSpeedX is a public class variable set to -3, and ballSpeedY is a public class variable set to -2.

As of right now I have the three buttons(easy, medium, hard) and they all just start a new Game. I just need something like


if onClickMedium.CLICK
ballSpeedX = -5
ballSpeedY = -4

I’ll provide more information if needed.

 
Flag Post

You can pass a parameter in the Game class constructor and use the target property to know what button was pressed.

 
public function Game(gameMode:int) {

if (gameMode == 0) {
ballSpeedX = -5

[...]
function onClickButton(e:MouseEvent) {
if (e.target == mediumButton) {
game = new Game(0);
}
}
 
Flag Post

I somewhat understand what you’re saying. Here’s my code, maybe you can help me out easier…

Game.as
http://pastebin.com/60hyjyfi

DocumentClass.as
http://pastebin.com/Vuq7MiwF

MainMenu.as (Holds each button, easy, medium, hard)
http://pastebin.com/fezfMndF

Navigation.as (Controls navigations of buttons)
http://pastebin.com/040dydYx

As of now I just need to know how to move the ball faster at different difficulties. From there I can change other things.

 
Flag Post

Make a Difficulty class that contains everything that is affected by difficulty settings:

public class Difficulty {
 public var ballSpeedX:Number, ballSpeedY:Number;

 public function Difficulty(ballSpeedX:Number, ballSpeedY:Number){
  this.ballSpeedX = ballSpeedX; this.ballSpeedY = ballSpeedY;
}

Create appropriate instances of that in your shell (I think that’s MainMenu):

private static var easy:Difficulty = new Difficulty(1.6, 1.3), medium:Difficulty = new Difficulty(5, 4);

… and then pass that as an argument to Game:

public class Game {
 private var difficulty:Difficulty;

 public Game(difficulty:Difficulty){
  this.difficulty = difficulty;
 }

 ...
}

Finally, replace ‘ballSpeedX’ with ‘difficulty.ballSpeedX’ in game code:

public function onTick(timerEvent:TimerEvent):void {
	ball.x += difficulty.ballSpeedX;
	ball.y += difficulty.ballSpeedY;
}

You pay a very small performance penalty for the extra object and field lookup, but when you have more settings that can be affected by difficulty changes, it’s far cleaner to have it packaged up in an object.

A couple of other points: if the ratio between X and Y speeds is always the same, you might only want one setting (a multiplier from a set default speed on each axis); and you probably want to use a single enter-frame handler in your main game class, instead of a timer, because that way you can much more easily implement pausing and fast or slow motion effects.

 
Flag Post

In a class constructor, you can pass paramenters, like in every other function. So, I was sugesting you could pass the game mode as a parameter.
In the Game constructor (Game.as line 82) you can use something like this: public function Game(gameMode:int)
And then :


if (gameMode == 0) {
ballSpeedX = -3;
ballSpeedY = 0;
//whatever you want to change
}
else if (gameMode == 1) {
ballSpeedX = -4;
ballSpeedY = 1;
}
//etc

Then if you use playScreen = new Game(0) ballSpeedX will be -3 and ballSpeedY will be 0, while if you use playScreen = new Game(1) then ballSpeedX will be -4 and ballSpeedY will be 1.

 
Flag Post

Thanks SumGato I understand what you’re getting at now (nothing against you Bob.) The problem I have is the ballSpeedX = -3; ballSpeedY = 0 is what the ball does when the game starts. In the onTick function that sets what speed the ball is going. So when the game beings it just goes straight for paddle (this is a pong type game to help put things in perspective.) After that the ball follows the speed x = -3, y = -2

Bob’s suggestion of using a ENTER_FRAME handler makes sense more than a timer. I just need to get my code from onTick into game constructor.

EDIT: I tried…


stage.addEventListener(Event.ENTER_FRAME, onTick);

…and put my onTick function inside the game constructor. I just get “cannot access a property or method of a null-object reference” in the debug.

 
Flag Post

My guess is that the null object being referred to is the stage. During the first several microseconds or so when a Flash game runs, the stage has yet to be initialized. You should use an added-to-stage event handler for executing code when the stage is initialized. Take a look at the following example to see when to add an enter-frame event listener:

package 
{
	import flash.display.Sprite;
	import flash.events.Event;

	public class Main extends Sprite 
	{

		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		} // public function Main

		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);

			// entry point
			stage.addEventListener(Event.ENTER_FRAME, onTick);
		} // private function init
		
		private function onTick(e:Event):void 
		{
			trace("tick");			
		} // private function onTick

	} // public class Main

} // package
 
Flag Post

Got it to work, thank you everyone!