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 Manic

I want to bind two entities together--namely, I want to have a player entity with an arm entity so the arm can swivel wherever the mouse is pointing. I tried to set it up so that the arm entity is a property of the player entity, and in its update method it sets its pos to the pos of the player (just to test, you understand). It ends up sort of stutter-lagging behind the player, rather than being positioned directly on the player every frame like I want it to.

I've commented out some stuff, but here's the code for player.js.
ig.module(
	'game.entities.player'
).requires(
	'game.entities.character'
).defines(function() {
	EntityPlayer = EntityCharacter.extend({
		
		size:{x:64,y:128},
		
		maxVel: {x: 400, y: 400},
		friction: {x: 500, y: 0},
		
		animSheet: new ig.AnimationSheet( 'media/player.png', 64, 128 ),
		
		gunshot: new ig.Sound('media/sound/gun.*'),
		
		//arm: new EntityArm(this.x,this.y, {attachee: this}),
		
		type:ig.Entity.TYPE.A,
		collides: ig.Entity.COLLIDES.PASSIVE,
		
		flip: false,
		accelGround: 400,
		accelAir: 200,
		jump: 300,
		health: 100,
		maxHealth: 100,
		cooldown: 0,
		
		zIndex: 1,
		
		init: function( x, y, settings ) {
			this.parent( x, y, settings );
			
			//this.arm = ig.game.spawnEntity(EntityArm, this.pos.x,this.pos.y, {attachee: this});
			
			// Add the animations
			this.addAnim( 'idle', .5, [0,1,2,3] );
			this.addAnim( 'run', 0.25, [4,5,6,7,8,9] );
			//this.addAnim( 'jump', 1, [4] );
			//this.addAnim( 'fall', 1, [4] );
		},
		
		update: function() {
			// move left or right
			var accel = this.standing ? this.accelGround : this.accelAir;
			if( ig.input.state('left') ) {
				this.accel.x = -accel;
				this.flip = true;
			}
			else if( ig.input.state('right') ) {
				this.accel.x = accel;
				this.flip = false;
			}
			else {
				this.accel.x = 0;
			}
			
			
			// jump
			if( this.standing && ig.input.state('jump') ) {
				this.vel.y = -this.jump;
			}
			
			// shoot
			if( ig.input.state('shoot') && this.cooldown == 0) {
				ig.game.spawnEntity( EntityBullet, this.pos.x+this.size.x/2, this.pos.y+this.size.y/2, {flip:this.flip, d:{x:ig.input.mouse.x, y:ig.input.mouse.y}} );
				this.gunshot.play();
				this.cooldown = 10;
			}
			
			
			// set the current animation, based on the player's speed
			if( this.vel.y < 0 ) {
				this.currentAnim = this.anims.run;
			}
			else if( this.vel.y > 0 ) {
				this.currentAnim = this.anims.run;
			}
			else if( this.vel.x != 0 ) {
				this.currentAnim = this.anims.run;
			}
			else {
				this.currentAnim = this.anims.idle;
			}
			
			this.currentAnim.flip.x = this.flip;
			
			if (this.cooldown > 0)
				this.cooldown--;
				
			//this.arm.pos.x = this.pos.x;
			//this.arm.pos.y = this.pos.y;
			
			// move!
			this.parent();
		},
	});
	
	//currently a stump (har)
	EntityArm = ig.Entity.extend({
		animSheet: new ig.AnimationSheet('media/arm.png', 16, 8),
		size: {x:16, y:8},
		type: ig.Entity.TYPE.A,
		checkAgainst: ig.Entity.TYPE.B,
		collides: ig.Entity.COLLIDES.LITE,
		gravityFactor: 0,
		
		zIndex: 0,
		
		receiveDamage: function(amount, other) {
			this.attachedTo.receiveDamage(amount,other);
		},
		
		init: function(x,y,settings) {
			this.parent(x,y,settings);
			
			this.pos.x = x;
			this.pos.y = y;

			this.attachedTo = settings.attachee;
			this.addAnim('notShooting', 1, [0]);
			this.addAnim('shooting', 1, [1]);
		},
		
		update: function() {
			this.currentAnim = this.anims.notShooting;
			this.parent();
			
			//this.pos.x = this.attachedTo.pos.x;
			//this.pos.y = this.attachedTo.pos.y;
			
		},
		
		draw: function() {
			this.parent();
		}
	});
	
	EntityBullet = ig.Entity.extend({
		size:{x:6, y:2},
		offset:{x:1,y:1},
		animSheet: new ig.AnimationSheet('media/bullet.png',8,4),
		gravityFactor: 0,
		
		type: ig.Entity.TYPE.A,
		checkAgainst: ig.Entity.TYPE.B, // Check Against B - our evil enemy group
		collides: ig.Entity.COLLIDES.PASSIVE,
		
		maxVel: {x:10000000, y:10000000},
		
		
		init: function( x, y, settings ) {
			this.parent( x, y, settings );
			
			this.pos.x = x;
			this.pos.y = y;
			
			this.vel.x = (settings.flip ? -this.maxVel.x : this.maxVel.x);
			this.vel.y = -50;
			
			
			this.vel.x = ig.game.screen.x+settings.d.x - this.pos.x;
			this.vel.y = settings.d.y+ ig.game.screen.y- this.pos.y;
			var vectorLength = Math.sqrt(this.vel.x*this.vel.x + this.vel.y*this.vel.y);
			this.vel.x /= vectorLength;
			this.vel.y /= vectorLength;
			this.vel.x*=2000;
			this.vel.y*=2000;
			//this.vel.x*=3000;
			//this.vel.y*=3000;
			var angle = Math.atan2(settings.d.y - this.pos.y + ig.game.screen.y, settings.d.x - this.pos.x + ig.game.screen.x);
			this.addAnim( 'idle', 1, [0] );
			this.anims.idle.pivot.x = 0;
			this.anims.idle.angle = angle;
			this.pos.y -= this.animSheet.height/2;
		},
		
		handleMovementTrace: function( res ) {
			this.parent( res );
			if( res.collision.x || res.collision.y || res.collision.slope) {
				this.kill();
			}
		},
		
		update: function() {
			var mapWidth = ig.game.collisionMap.width*ig.game.collisionMap.tilesize;
			var mapHeight = ig.game.collisionMap.height*ig.game.collisionMap.tilesize;
			
			if (this.pos.x > mapWidth+ig.system.width || this.pos.x < 0-ig.system.width || this.pos.y > mapHeight+ig.system.height || this.pos.y < 0-ig.system.height ) {
				this.kill();
			}
			
			this.parent();
		},
		
		// This function is called when this entity overlaps anonther entity of the
		// checkAgainst group. I.e. for this entity, all entities in the B group.
		check: function( other ) {
			other.receiveDamage( 10, this );
			for (var i = 0; i < 40;i++) {
				ig.game.spawnEntity(EntityBloodParticle, this.pos.x, this.pos.y, {dx: this.vel.x, dy: this.vel.y});
			}
			this.kill();
		}
	});
});

1 decade ago by lTyl

Inverse Kinematics? Here is a pretty good JavaScript example: http://www.dhteumeuleu.com/the-law-of-robotics and here is the source: http://www.dhteumeuleu.com/the-law-of-robotics/source. It should help you out I hope

1 decade ago by Manic

Thanks for the link--interesting stuff there.

Unfortunately, the issue isn't that it doesn't rotate correctly. The issue is that I can't have it tethered to the player entity at all. Whenever the player moves, the arm entity just stutters along behind the player. Unlike the player's movement along the plane, which looks smooth and consistent, the arm ends up stutter-oscillating a few pixels behind the player. It looks bad and it works poorly. The reason this is confusing is that almost exactly the same code worked perfectly in the previous engine i was using, although that engine had a ton of different problems.

I'm guessing it's something to do with the velocity/acceleration/friction and how it's handled for movement.

1 decade ago by Ransome

Not certain this will resolve your issue, but there are 2 factors I see in play here:

1. zIndex. If the zIndex of your arm is higher than the zIndex of your player it will get updated after the player. Keep that in mind when deciding whether to put the position adjustment on the player or on the arm.

2. In the example where the arm is attached to the player, the this.update() call is called AFTER the position adjustment. This means the player's position is updated AFTER you set the position of the arm, creating that weird stutter effect you see. Try swapping those:

update:function() {
...
// move!
this.parent();

this.arm.pos.x = this.pos.x;
this.arm.pos.y = this.pos.y;
...
}

As an aside, because objects in javascript are treated like references, I think you could also remove the .pos.x and .pos.y adjustments in the update call and instead set the arm .pos to the player .pos, like so:

EntityArm = ig.Entity.extend({
  ...
  init: function(x,y,settings) {
    ...
    this.parent(x,y,settings); // should call before if you're going to call it
    this.pos = settings.attachee.pos;
  }
}

It's funky but might work.

1 decade ago by Manic

Thanks, that seems to have worked perfectly!
Page 1 of 1
« first « previous next › last »