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 made a player entity that spawns bullet entities to collide with enemy entities. Unfortunately, when I added music the collision randomly quit working. Either the bullets phase through the enemies OR the player phases through the entities, unless the player is completely stopped. This disappeared when I changed the music to be a short loop rather than a full song, but then I added in an arm entity and it started happening again. This occurs even when I don't actually spawn the arm.

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();
		}
	});
});

enemySpider.js
ig.module(
	'game.entities.enemySpider'
).requires(
	'game.entities.character'
).defines(function() {
	EntityEnemySpider = EntityCharacter.extend({
		type: ig.Entity.TYPE.B,
		checkAgainst: ig.Entity.TYPE.A,
		
		collides: ig.Entity.COLLIDES.PASSIVE,
		
		maxVel: {x: 400, y: 400},
		friction: {x: 300, y: 0},
		size:{x:64,y:64},
		offset:{x:0,y:0},
		speed:100,
		
		health:1,
		
		animSheet: new ig.AnimationSheet( 'media/spider.png', 64, 64 ),
		
		init: function(x,y,settings) {
			this.parent(x,y,settings);
			
			this.addAnim('idle', 1, [0]);
			this.addAnim('walk', .3, [0,1]);
			this.currentAnim = this.anims.walk;
		},
		
		update: function() {
			if( !ig.game.collisionMap.getTile(
					this.pos.x + (this.flip ? +4 : this.size.x -4),
					this.pos.y + this.size.y+1
				)
			) {
				this.flip = !this.flip;
			}
			if(ig.game.collisionMap.getTile(this.pos.x + (this.flip ?- 4 : this.size.x+4),this.pos.y - this.size.y - 4)) {
				this.flip = !this.flip;
			}
			
			var xdir = this.flip ? -1 : 1;
			this.vel.x = this.speed * xdir;
			
			this.parent();
		},
		
		check: function( other ) {
			other.receiveDamage( 10, this );
			this.kill();
		}
	});
});

For good measure, levelLogic.js
ig.module('game.entities.levelLogic').requires('impact.entity').defines(function() {
	EntityLevelLogic = ig.Entity.extend({
		size:{x:64,y:64},
		_wmDrawBox: true,
		_wmBoxColor: 'rgba(0, 0, 255, 0.4)',
		
		paused: false,
		ignorePause: true,
		levelMusic: new ig.Sound('media/sound/loop_level1.*'),
		
		init: function(x,y,settings) {
			this.parent(x,y,settings);
			if (!ig.global.wm) {
				ig.game.spawnEntity(EntityHealthbar);
				ig.game.spawnEntity(EntityKeybinder);
				ig.music.add(this.levelMusic);
				ig.music.volume = .1;
				ig.music.play();
			}	
		},
		update: function() {
			this.parent();
			if (ig.input.pressed('pause')) {
				ig.game.togglePause();
				if (this.paused)
					ig.music.play();
				else ig.music.pause();
				this.paused = !this.paused;
			}
		}
	});
	
	EntityHealthbar = ig.Entity.extend({
		_wmIgnore: true,
		
		draw: function() {
			var playerEnt = (ig.game.getEntitiesByType(EntityPlayer)[0]);
								
			newhp = playerEnt.health;
			maxhp = playerEnt.maxHealth;
			if (newhp > maxhp)
				newhp = maxhp;
			
			var width = 150;
			var height = 30;
			var x = 10;
			var y = 10;
			
			var rectWidth = newhp/maxhp * width;
			ig.system.context.beginPath();
			ig.system.context.rect(x, y, rectWidth, height);
			ig.system.context.fillStyle = 'red';
			ig.system.context.fill();
			ig.system.context.beginPath();
			ig.system.context.rect(x, y, width, height);
			ig.system.context.strokeStyle = 'black';
			ig.system.context.lineWidth = 1;
			ig.system.context.stroke();
		}
	});
	
	EntityKeybinder = ig.Entity.extend({
		_wmIgnore: true,
		
		init: function() {
			ig.input.bind( ig.KEY.A, 'left' );
			ig.input.bind( ig.KEY.D, 'right' );
			ig.input.bind( ig.KEY.W, 'jump' );
			ig.input.bind(ig.KEY.MOUSE1, 'shoot');
			ig.input.bind(ig.KEY.ESC, 'pause');
		}
	});
});

What am I doing wrong?

1 decade ago by Manic

By the way, the game this all fits into can be seen at http://test.manic0892.com/ishoot/. Collision is broken on Chrome on Mac OSX and Windows.

1 decade ago by Joncom

Please make a simpler test case.
Start gradually pulling things out of the game until either:
1) You find the bug by removing it accidentally.
2) You've made the code small enough that people will be more willing to inspect it.

If you're using version control like Git, it should be super easy to restore everything you've removed once you find the issue.

1 decade ago by Ransome

Hi Manic, I tested the demo you posted and did not experience the issue you are referring to.

Try requiring 'impact.debug.debug' in your main game class (see http://impactjs.com/documentation/debug). Right now my best hypothesis is that the sounds are causing a fps drop. If this is the case, due to the velocity of the bullet there may be a "skip" over the positions that are used to calculate the check function and the seeming effect would be that the bullet went through the enemy. This would be more probable if the bullet "clipped" the enemy.

If you fire up your Chrome debugger (or Firebug if you're in firefox) and set a breakpoint at the check function you may also get some information from the stack trace that could help diagnose the issue. If the check function is never called, for instance, the above hypothesis may be true. If the check function is called but the enemy still does not die you can investigate the state of the system to deduce what the cause might be.

1 decade ago by Manic

I should have posted that I'd solved this--it turned out it was an issue with using the per pixel collision detection plugin combined with rotating a bullet's non-alpha pixels out of its collision box. It meant that the plugin was checking all pixels inside the collision box, but since I'd rotated the bullet image outside of the collision box there were no pixels to check against. I fixed it by using a circular bullet that doesn't require rotation instead of an oblong bullet.
Page 1 of 1
« first « previous next › last »