Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

1 decade ago by axphin

Since I'm still learning, I'm having a hard time converting the sample project for jumpnrun to a topdown style game. I cleared out a lot of the code and have been able to get my custom character drawn on the screen, but am having trouble figuring out basic movement. I have the jumpnrun player.js file next to my player.js file in Komodo so I can compare but I'm still a little lost.

Is it just a matter of setting up the init and update functions properly? The character just moves in 4 directions similar to the rpgjs.com example. However mine is even more simple in that the animation only cycles through 3 frames and the sprite just gets rotated to face the direction it is going. I don't have unique sprites for each direction (although learning how to do that would be nice I suppose).

It also took me a while to figure out that the player entity won't show up in weltmeister without adding the addAnim line to specify a starting frame.

It would be great if Impact had a few more gametype sample projects, like topdown (tank, rpg), puzzle game, etc.

Thanks

1 decade ago by Graphikos

The Pong sample and video tutorial is top down. Probably give you a lot of direction. Source is on your download page.

http://impactjs.com/documentation/video-tutorial-create-a-game

1 decade ago by axphin

Thanks, yeah I forgot about the Pong sample.

I pieced it together and now I have four way movement. However I want to prevent diagonal movement.

	update: function() {
		if( ig.input.state('left') ) {
			this.vel.x = -50;
		}
		else if( ig.input.state('right') ) {
			this.vel.x = 50;
		}
		else if( ig.input.state('up') ) {
			this.vel.y = -50;
		}
		else if( ig.input.state('down') ) {
			this.vel.y = 50;
		}
		else {
			this.vel.x = 0;
			this.vel.y = 0;
		}
		
		// set the current animation, based on the player's speed
		if( this.vel.y < 0 ) {
			this.currentAnim = this.anims.driveForward;
		}
		else if( this.vel.y > 0 ) {
			this.currentAnim = this.anims.driveBackward;
		}
		else if( this.vel.x != 0 ) {
			this.currentAnim = this.anims.driveForward;
		}
		else {
			this.currentAnim = this.anims.idle;
		}
		
		this.parent();

	}

1 decade ago by axphin

Ok, so I locked it down so that diagonal movements don't happen by adding this.vel.x = 0 for a y movement and this.vel.y = 0 for an x movement.

My player sprite png has 3 frames of animation for the up direction and 3 frames for the right direction. I am trying to use the flip command to just flip the x for left and y for down.

I have two problems now.

1). The left arrow key input state is the first item in the update function so it takes precedence over other keys, so if I'm going left, I can't hold down the up key and have that take precedence. Is it possible to make any current input state the priority?

2). How do I set the flip state so that it stays on the last state used instead of reverting back to the idle state? I tried using currentAnim like what is used in the jumpnrun example but it doesn't work (which is why it is commented out right now).

This is what I have so far:

update: function() {
		if( ig.input.state('left') ) {
			this.vel.x = -50;
			this.vel.y = 0;
		}
		else if( ig.input.state('right') ) {
			this.vel.x = 50;
			this.vel.y = 0;
		}
		else if( ig.input.state('up') ) {
			this.vel.y = -50;
			this.vel.x = 0;
		}
		else if( ig.input.state('down') ) {
			this.vel.y = 50;
			this.vel.x = 0;
		}
		else {
			this.vel.x = 0;
			this.vel.y = 0;
		}
		
		// set the current animation, based on the player's speed
		if( this.vel.y < 0 ) {
			this.currentAnim = this.anims.driveForward;
			this.currentAnim.flip.y = false;
		}
		else if( this.vel.y > 0 ) {
			this.currentAnim = this.anims.driveBackward;
			this.currentAnim.flip.y = true;
		}
		else if( this.vel.x > 0 ) {
			this.currentAnim = this.anims.driveRight;
			this.currentAnim.flip.x = false;
		}
		else if( this.vel.x < 0 ) {
			this.currentAnim = this.anims.driveLeft;
			this.currentAnim.flip.x = true;
		}
		else {
			this.currentAnim = this.anims.idle;
		}
		
		//this.currentAnim.flip.x = this.flip;
		//this.currentAnim.flip.y = this.flip;
		
		this.parent();

	}

1 decade ago by axphin

Here is another try. The flip stays flipped for the down movement, but not left or right. I think that is because the flip property is working off of the idle animation? Sorry this is so messy.

EntityPlayer = ig.Entity.extend({
	
	size: {x: 12, y:14},
	offset: {x: 2, y: 2},
	collides: ig.Entity.COLLIDES.ACTIVE,
	type: ig.Entity.TYPE.A,
	animSheet: new ig.AnimationSheet( 'media/tank.png', 16, 16 ),	
	
	health: 10,
	//flip: false,
	
	init: function( x, y, settings ) {
		this.parent( x, y, settings );
		
		this.addAnim( 'idle', 0.1, [0] );
		this.addAnim( 'driveUp', 0.07, [0,1,2] );
		this.addAnim( 'driveDown', 0.07, [0,1,2] );
		this.addAnim( 'driveLeft', 0.07, [3,4,5] );
		this.addAnim( 'driveRight', 0.07, [3,4,5] );
		
		//this.vel.x = -200;
		//this.vel.y = 100;
	},
	
	update: function() {
		if( ig.input.state('up') ) {
			this.vel.y = -50;
			this.vel.x = 0;
			this.currentAnim.flip.x = false;
			this.currentAnim.flip.y = false;
		}
		else if( ig.input.state('down') ) {
			this.vel.y = 50;
			this.vel.x = 0;
			this.currentAnim.flip.x = false;
			this.currentAnim.flip.y = true;
		}
		else if( ig.input.state('left') ) {
			this.vel.x = -50;
			this.vel.y = 0;
			this.currentAnim.flip.x = true;
			this.currentAnim.flip.y = false;
		}
		else if( ig.input.state('right') ) {
			this.vel.x = 50;
			this.vel.y = 0;
			this.currentAnim.flip.y = false;
			this.currentAnim.flip.x = false;
		}
		else {
			this.vel.x = 0;
			this.vel.y = 0;
		}
		
		// set the current animation, based on the player's speed
		if( this.vel.y < 0 ) {
			this.currentAnim = this.anims.driveUp;
		}
		else if( this.vel.y > 0 ) {
			this.currentAnim = this.anims.driveDown;
		}
		else if( this.vel.x > 0 ) {
			this.currentAnim = this.anims.driveLeft;
		}
		else if( this.vel.x < 0 ) {
			this.currentAnim = this.anims.driveRight;
		}
		else {
			this.currentAnim = this.anims.idle;
		}
		
		//this.currentAnim.flip.x = this.flip.x;
		//this.currentAnim.flip.y = this.flip.y;
		
		this.parent();

	}

});

1 decade ago by axphin

Thanks to domsz and Graphikos for help in IRC..

Here is the working code. We ditched using the flip method for the .angle method.
This still doesn't solve the issue with keypress priority, but not sure if I need to fix that.

ig.module(
	'game.entities.player'
)
.requires(
	'impact.entity'
)
.defines(function(){

EntityPlayer = ig.Entity.extend({
	
	size: {x: 14, y:14},
	collides: ig.Entity.COLLIDES.ACTIVE,
	type: ig.Entity.TYPE.A,
	animSheet: new ig.AnimationSheet( 'media/tank.png', 16, 16 ),	
	
	health: 50,
	
	init: function( x, y, settings ) {
		this.parent( x, y, settings );
		
		this.addAnim( 'idle', 0.1, [0] );
		this.addAnim( 'drive', 0.07, [0,1,2] );
		this.angle = 0;
	},
	
	update: function() {
		var speed = 50
		this.vel.x = 0;
		this.vel.y = 0;
		
		if( ig.input.state('up') ) {
			this.vel.y = -speed;
			this.angle = 0;
		}
		else if( ig.input.state('down') ) {
			this.vel.y = speed;
			this.angle = Math.PI;
		}
		else if( ig.input.state('left') ) {
			this.vel.x = -speed;
			this.angle = -Math.PI/2;
		}
		else if( ig.input.state('right') ) {
			this.vel.x = speed
			this.angle = Math.PI/2;
		}

		if( this.vel.x || this.vel.y ) {
			this.currentAnim = this.anims.drive;
		}
		else {
			this.currentAnim = this.anims.idle;
		}
		
		this.currentAnim.angle = this.angle;
		this.parent();

	}

});

});

1 decade ago by axphin

Ok, so I've been looking around trying to figure out how to fix button press priority and I'm still stumped.

See this example here:
http://glimr.rubyforge.org/cake/canvas.html#KeyboardTest

I want my player control to behave similar to this only without the diagonals.

Any ideas?

1 decade ago by dominic

What exactly is the problem? As your code is now, it only allows for one direction at a time, e.g. either up or left, but not up and left.

The priority of those keys is their order in the if conditions. If up is pressed, all following keys are ignored, if down is pressed, all following keys are ignored etc.

1 decade ago by axphin

Yes, I would like to be able to have each key press become the priority. This isn't a requirement for a game, necessarily, but more of a question of how to do it in code. Since I'm learning, I want to understand how this works better.

I do understand that the if conditions create the priority. I've played around with making each keypress a separate if condition which then makes diagonal movement happen.

I've seen other games that allow 4 way movement where the last key pressed takes priority. So if you are moving UP and tap to the RIGHT you will stop going up and head to the right. If you are still holding the UP key and press RIGHT you will go right and as soon as you let up on the RIGHT key you will continue going UP again.

Does that make sense?

1 decade ago by dominic

Well, you almost gave the answer to yourself :)

If you want to have the last pressed key to have the highest priority, you have to save somewhere which key was pressed last. You can use the .pressed() method and a new property of your entity that you call lastKey:

if( ig.input.pressed('up') ) {
	this.lastKey = 'up';
}
else if( ig.input.pressed('down') ) {
	this.lastKey = 'down';
}
else if( ig.input.pressed('left') ) {
	this.lastKey = 'left';
}
else if( ig.input.pressed('right') ) {
	this.lastKey = 'right';
}

After that, you can check if the key is still being held down, using the .state() method and if this key is indeed the key that was last pressed:

if( this.lastKey == 'up' && ig.input.state('up') ) {
	this.vel.y = -speed;
	this.angle = 0;
}
else if( this.lastKey == 'down' && ig.input.state('down') ) {
	this.vel.y = speed;
	this.angle = Math.PI;
}
else if( this.lastKey == 'left' && ig.input.state('left') ) {
	this.vel.x = -speed;
	this.angle = -Math.PI/2;
}
else if( this.lastKey == 'right' &&  ig.input.state('right') ) {
	this.vel.x = speed
	this.angle = Math.PI/2;
}

Edit: Ok, this will have a problem, too: when you press two keys and you release the one that you pressed last, the entity will stop moving completely, instead of moving in the direction of the key that is still being held down.

I can think of complicated solution right now, but there has to be an easy one 0_o

Btw.: the example you linked to doesn't have this "last key pressed" priority either.

Edit2: Untested:
keyStack: [],

update: function() {
	// remove all keys from the stack that are not being held down anymore
	for( var i = this.keyStack.length; i--; ) {
		if( !ig.input.state(this.keyStack[i]) ) {
			this.keyStack.splice(i, 1);
		}
	}

	// push the key to the stack if it was just pressed down
	if( ig.input.pressed('up') ) {
		this.keyStack.push('up');
	}
	if( ig.input.pressed('down') ) {
		this.keyStack.push('down');
	}
	if( ig.input.pressed('left') ) {
		this.keyStack.push('left');
	}
	if( ig.input.pressed('right') ) {
		this.keyStack.push('right');
	}

	// get the key from the top of the stack
	var lastKey = this.keyStack[this.keyStack.length-1];

	if( lastKey == 'up' ) {
		this.vel.y = -speed;
		this.angle = 0;
	}
	else if( lastKey == 'down' ) {
		this.vel.y = speed;
		this.angle = Math.PI;
	}
	else if( lastKey == 'left' ) {
		this.vel.x = -speed;
		this.angle = -Math.PI/2;
	}
	else if( lastKey == 'right' ) {
		this.vel.x = speed
		this.angle = Math.PI/2;
	}

	
	...
}

This seems overly complex for something like this :/

Maybe someone can come up with a more elegant solution. Maybe hack in into ig.Input directly and attach it to the keydown and keyup functions!?

1 decade ago by axphin

Here is my complete player.js code. I made a few modifications to make the player speed up and slow down. Also makes it so turns have a slight drift. Thanks again for all of your help. Now it is time to move on to having my tank shoot.

ig.module(
	'game.entities.player'
)
.requires(
	'impact.entity'
)
.defines(function(){

EntityPlayer = ig.Entity.extend({
	
	size: {x: 14, y:14}, // collision box size
	offset: {x: 1, y: 1},
	collides: ig.Entity.COLLIDES.ACTIVE,
	type: ig.Entity.TYPE.A,
	animSheet: new ig.AnimationSheet( 'media/tank.png', 16, 16 ),
	
	maxVel: {x: 40, y: 40},
	friction: {x: 20, y: 20},
	
	health: 50,
	
	init: function( x, y, settings ) {
		this.parent( x, y, settings );
		
		this.addAnim( 'idle', 0.1, [0] );
		this.addAnim( 'drive', 0.07, [0,1,2] );
		this.angle = 0;
	},
	
	keyStack: [],
	
	update: function() {
		var speed = 50
		var groundFric = 100
		this.accel.x = 0;
		this.accel.y = 0;
		
		// remove all keys from the stack that are not being held down anymore
		for( var i = this.keyStack.length; i--; ) {
			if( !ig.input.state(this.keyStack[i]) ) {
				this.keyStack.splice(i, 1);
			}
		}
		
		// push the key to the stack if it was just pressed down
		if( ig.input.pressed('up') ) {
			this.keyStack.push('up');
		}
		if( ig.input.pressed('down') ) {
			this.keyStack.push('down');
		}
		if( ig.input.pressed('left') ) {
			this.keyStack.push('left');
		}
		if( ig.input.pressed('right') ) {
			this.keyStack.push('right');
		}
		
		// get the key from the top of the stack
		var lastKey = this.keyStack[this.keyStack.length-1];
		
		if( lastKey == 'up' ) {
			this.accel.y = -speed;
			this.friction.x = groundFric;
			this.angle = 0;
		}
		else if( lastKey == 'down' ) {
			this.accel.y = speed;
			this.friction.x = groundFric;
			this.angle = Math.PI;
		}
		else if( lastKey == 'left' ) {
			this.accel.x = -speed;
			this.friction.y = groundFric;
			this.angle = -Math.PI/2;
		}
		else if( lastKey == 'right' ) {
			this.accel.x = speed
			this.friction.y = groundFric;
			this.angle = Math.PI/2;
		}
		

		if( this.vel.x || this.vel.y ) {
			this.currentAnim = this.anims.drive;
		}
		else {
			this.currentAnim = this.anims.idle;
		}
		
		this.currentAnim.angle = this.angle;
		this.parent();

	}

});

});

1 decade ago by jamaalsd

Hey, I'm new to the impact verse. I wanted to thank you guys for having this discussion because I just ran into the exact key priority issue axphin did :)

9 years ago by ijed

Yes, same as the guy above - thanks for posting your problems and solutions, this is incredibly helpful :)
Page 1 of 1
« first « previous next › last »