Jump to content

Implementing state design pattern


Meowts
 Share

Recommended Posts

Hey,

 

So I'm trying to implement the State design pattern, and I've come across some strange behavior.

 

What I'm trying to achieve:

The longer the player is moving left or right, the faster they move until max speed is reached (same as good ol' Mario).

 

Result:

The timer that the affects speed increment sometimes doesn't happen...? I'll move left and right, sometimes it increments, sometimes it doesn't.

 

Also, sometimes when pressing the left key while in Standing state, the velocity of the player sprite will continue to increase, seemingly not entering the Standing state... (ie, press left, stop pressing left, player sprite keeps moving forward). However from logging when entering the states, it definitely should be hitting the right update function...

 

Hypothesis:

 

Either...

 

A: The timer isn't instancing quick enough, or being mixed up somehow?

 

B: There's something about Javascript I don't quite get, and should switch to C++... XD

 

Code:

//As for what's being called... there's an instance of Player called player_, and it's being called in main update loop as player_.update();//player.js:create : function(){        this.state = Player.State.Standing(this);}update : function() {        this.state.update();}//and in playerState.js:Player.State = function(){};Player.State.Standing = function(player){	this.player = player;};Player.State.Walking = function(player){	this.player = player;	isWalking = false;};Player.State.Jumping = function(player){	this.player = player;	isJumping = false;};Player.State.Standing.prototype = {	update : function(){		//Slow down if already moving		if(this.player.movingLeft || this.player.movingRight){			if(this.player.sprite.body.velocity.x !== 0){				this.player.sprite.body.velocity.x -= 10;				if(this.player.movingLeft){					if(this.player.sprite.body.velocity.x > 0){						this.player.sprite.body.velocity.x = 0;						this.player.movingLeft = null;					}				}				if(this.player.movingRight){					if(this.player.sprite.body.velocity.x < 0){						this.player.sprite.body.velocity.x = 0;						this.player.movingRight = null;					}				}							}		}				//Set proper frame		if(this.player.sprite.frame !== 0){			this.player.sprite.frame = 0;		}		//Stop any animations		if(this.player.sprite.animations.currentAnim.isPlaying){			this.player.sprite.animations.stop();		}                //Handle inputs		if(this.player.controller_.cursor.left.isDown || this.player.controller_.cursor.right.isDown){			this.player.state = new Player.State.Walking(this.player);		}		if(this.player.controller_.cursor.up.isDown && this.player.sprite.body.onFloor()){			this.player.state = new Player.State.Jumping(this.player);		}	}};Player.State.Walking.prototype = {	update : function(){		//Initialize flag and start timer upon entering state		if(!this.isWalking){                        //This is what seems to not make it in the update loop...                        //As you can see below, I destroy the timer object when changing states.                        //However, it only seems to happen 'sometimes', which obviously isn't                        //sufficient...			this.player.timer = this.player.game.time.create(false);			this.player.timer.start();			this.isWalking = true;		}		//Increment the player's walking speed based on time		if(this.player.timer.ms % this.player.incrementSpeed === 0 && this.player.walkingSpeed <= this.player.maxSpeed){			this.player.walkingSpeed += this.player.incrementSpeedValue;		}		//Start animation if it hasn't already		if(!this.player.sprite.animations.currentAnim.isPlaying){			this.player.sprite.animations.play('walk');		}				//Increment the speed of the animation by how fast the player is moving		this.player.sprite.animations.currentAnim.speed = this.walkingSpeed/5;		//Walking left or right		if(this.player.controller_.cursor.left.isDown){			//Set flag			this.player.movingLeft = true;			//Face left			this.player.sprite.scale.x = -1;			// Move the player to the left			this.player.sprite.body.velocity.x = -this.player.walkingSpeed;		}		else if(this.player.controller_.cursor.right.isDown){			//Set flag			this.player.movingRight = true;						//Face left			this.player.sprite.scale.x = 1;			// Move the player to the left			this.player.sprite.body.velocity.x = this.player.walkingSpeed;		}		//No input, stop what's going on		else{			this.reset();			this.player.state = new Player.State.Standing(this.player);		}		//Jumping from walking		if(this.player.controller_.cursor.up.isDown && this.player.sprite.body.onFloor()){			this.reset();			this.player.state = new Player.State.Jumping(this.player);		}	},	reset : function(){		this.isWalking = false;		this.player.walkingSpeed = this.player.initialSpeed;		this.player.timer.destroy();	}};Player.State.Jumping.prototype = {	update : function(){		if(this.player.sprite.animations.currentAnim.isPlaying){			this.player.sprite.animations.stop();		}				if(this.player.sprite.frame != 4){			this.player.sprite.frame = 4;		}				if(this.player.sprite.body.onFloor()){			if(!this.isJumping){				this.player.sprite.body.velocity.y = -this.player.jumpHeight;				this.isJumping = true;			}			else{				this.isJumping = false;				this.player.state = new Player.State.Standing(this.player);			}		}	}};

This seems pretty straight forward to me... but it's just not doing it, particularly the timer object that's created when entering Walking state. What am I missing?

 

Why it's imporant to me:

 

The state pattern makes a huge impact on how my game will work. It will be a fighting game, and like any fighting game, there will be a combination of different inputs that will determine the next move, and both state and timers will affect the subsequent moves. Rather than having one ridiculously large update function with n^n different flags, states seem like the best way to handle it.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...