Together with a friend of mine we are creating a multiplayer snake game. We are both beginners with JavaScript, so it is a real challenge for us.
So far I've managed to create this:
http://jsfiddle.net/tbmluijten/RG76t/3/
This is the collision detection code I have so far:
Snake.prototype.collision = function (x, y, array) {
for(var i = 0; i < Snake.length; i++){
if(Snake.pieces[0].x == x && Snake.pieces[0].y == y)
return true;
}
return false;
};
The problem I have is the collision with the snake itself. I can't figure out what I am doing wrong. Note that I am looking for collision with the snake itself not with the borders since we are going to put a loop into that. :-)
The short answer is - you are not checking for collision at all!
The working collision: http://jsfiddle.net/RG76t/10/
Explanation:
At first you need to put the collision method in the game loop function.
// line 32
if (game.snakes.length !== 0) {
for (i = 0; i < game.snakes.length; i++) {
var s = game.snakes[i];
s.paint(ctx, game);
// Check for collision.
if (s.collision()) {
// Do something, if the collision happens.
alert('collision');
}
}
}
Then in the collision method check if the first piece collides with any other. The loop starts from the 4th piece, since the snake's head can't really touch it's "neck" (2nd and 3rd pieces).
Snake.prototype.collision = function () {
// Loop the snake pieces from the 4th one.
for(var i = 3; i < this.length; i++){
// Check if this piece collides with the first piece.
if(
this.pieces[0].x === this.pieces[i].x &&
this.pieces[0].y === this.pieces[i].y
) {
return true; // collision
}
}
return false;
};
Also notice that Snake.length and Snake.pieces[i] are changed to this.length and this.pieces[i]. The keyword this refers to the instance of a Snake on which you invoke the collision method. When you were using Snake in this piece of code, you were checking the properties of a constructor.
Related
Is there a way to detect collision with an object created using a while loop?
I'm repeating an image across the screen using a while loop:
this.spikeX = 0;
while (this.spikeX < this.world._width) {
this.spike = this.add.sprite(this.spikeX, 0, 'spikes');
this.physics.arcade.enable(this.spike);
this.gameObjects.push(this.spike);
this.spikeX += (this.spike.width * 0.75);
}
I have a collision function:
collision: function(obj1, obj2) {
if (obj1.body.x < obj2.body.x + obj2.body.width &&
obj1.body.x + obj1.body.width > obj2.body.x &&
obj1.body.y < obj2.body.y + obj2.body.height &&
obj1.body.height + obj1.body.y > obj2.body.y) {
return true;
}
},
if(this.collision(this.player, this.spike)) {
console.log('spike');
}
When I call this function in the update function it doesn't detect collision but works when I just create a single spike outside the while loop.
That's probably because you have only one this.spike.
If you have multiple sprites, you need to put them into a group, and create them like this:
spike_group = game.add.group();
spike = spikes.create(spikeX, 0, 'spikes');
Then you check collision for each spike inside spike_group and a player.
And, why don't you use arcade collision like this:
// inside update function
physics.arcade.collide(player, spike_group , overlap_spikes, this);
// out of update function
function overlap_spikes()
{
console.log("touch spike");
}
Note: These examples does not use 'this' keyword.
Full code here
I am trying to setup the functions to detect collisions and for now just log to the console. This is the section for checkCollision function;
Player.prototype.update = function(dt) {
checkCollision(this.leftLimit, this.rightLimit);
this.leftLimit = this.x - 40.5;
this.rightLimit = this.x + 40.5;
}
function checkCollision(playerl,playerr) {
for (var i = 0; i < 5; i++) {
var thisEnemy = allEnemies[i];
if (thisEnemy.leftlimit > playerl && thisEnemy.rightLimit < playerr) {console.log("1")}
else {console.log('else')}
}
}
Question
The character is never registering as colliding with the enemy, why is this not working?
Testing/Debugging
I know this function is working as consoles logging else, I've also put logging in other locations and when in the Enemy.prototype.update function, console was showing values like 202.000000093, since the for..else function is using < or >, not absolute values, that should be fine, but still nothing is matching inside the player left and right limits. I also tried changing the Enemy limits to be smaller, +/- 40.5, incase the enemy was too wide to fit inside the player limits.
player.leftLimit and player.rightLimit are undefined when checkCollision method is first running
I added a better if statement to check if there's a collision;
if (
thisEnemy.leftLimit < player.rightLimit &&
thisEnemy.rightLimit > player.leftLimit &&
thisEnemy.upperLimit > player.lowerLimit &&
thisEnemy.lowerLimit < player.upperLimit) {
console.log("collision");
}
I am making a javascript game, and I can't make the enemy die when hit with a bullet. Here is the part of the code that I just can't understand:
for(var i=0;i<enemies.length;i++){
ctx.fillRect(enemies[i].x,enemies[i].y,30,100);
if(player.x+player.width>enemies[i].x && player.x<enemies[i].x+30 && player.y+player.height>enemies[i].y && player.y<enemies[i].y+100){
document.location.reload();
}
}
for (var b=0;b<bullets.length;b++){
ctx.beginPath();
ctx.arc(bullets[b].x,bullets[b].y,2,0,Math.PI*2);
ctx.fill();
bullets[b].x += bullets[b].dx;
if(bullets[b].x>enemies[i].x && bullets[b].x<enemies[i].x+enemies[i].width && bullets[b].y>enemies[i].y && bullets[b].y<enemies[i].y+enemies[i].height){
enemies.splice(i,1);
}
}
So, I know that the problem is that it can't read the property "x" of enemies[i] because I didn't put it in the enemies for loop, but if i put it there then it can't read the property "x" of bullets[b]. I've been stuck on this for two days now and searched everything I could find, but didn't find anything useful at all. I would appreciate any help...
Thanks in advance!
What you want is to check all the ennemies, for each bullet.
This is done using nested loops:
for (var b=0;b<bullets.length;b++){
ctx.beginPath();
ctx.arc(bullets[b].x,bullets[b].y,2,0,Math.PI*2);
ctx.fill();
bullets[b].x += bullets[b].dx;
for (var j=ennemies.length; j-- >0;) {
if(bullets[b].x>enemies[j].x && bullets[b].x<enemies[j].x+enemies[j].width && bullets[b].y>enemies[j].y && bullets[b].y<enemies[j].y+enemies[j].height){
enemies.splice(j,1);
}
}
}
Note: In this example I loop over enemies in reverse order in order to avoid missing an ennemy when splicing.
I'm encountering a collision issue that I can't quite figure out. The point of my program is to generate a random number of circles (between 2 and 15) with random velocities in a bounding box that is 1920x900. If they touch each other, they're supposed to fly off in opposite directions (not great physics, I know, but that'll come later.)
To do this, I've got four arrays: two for the coordinates of the circles (xcords[] and ycords[], and two for the momentum of each circle (xdirs[] and ydirs[]).
Here's my collision function
function collides(x, y)
{
if(Math.hypot(xcords[y]-xcords[x], ycords[y]-ycords[x]) < 50)
{
return true;
}
else return false;
}
When I hardcode certain values, such as
if(collides(xcords[1],xcords[0])
{
xdirs[0] *= -1;
xdirs[1] *= -1;
ydirs[0] *= -1;
ydirs[1] *= -1;
}
then it works fine. The two circles I hardcode will collide correctly. But when I try to apply this to every circle:
for(i=0; i<circles; i++)
{
for(j=0; j<circles; j++)
{
if(collides(xcords[i], xcords[j]))
{
xdirs[i] *= -1;
xdirs[j] *= -1;
ydirs[i] *= -1;
ydirs[j] *= -1;
}
}
}
Then the circles just ignore each other, and I have no idea why. This is the only time I use a double for loop in this code, but I do the first for loop multiple times, and it handles it correctly for every other function.
Here's a jsfiddle for it. https://jsfiddle.net/sekbr0pg/
The bounding box is a little off, but it's enough to see that the collision is wonky.
Let's take circle 1 and circle 2. You want to check whether they collide or not only once. Is the following loop good for that?
for(i=0; i<circles; i++) {
for(j=0; j<circles; j++){
// if collides ...
}
}
Answer is no, and the reason is that they will run twice, for i=1 and j=2 and i=2 and j=1. So basically it won't change anything since -1*-1 = 1. In your loop change j=0 to j=i+1.
Also your collides function accept circles, so I think collides(i,j) will do the job.
I am making a little game using HTML5 Canvas and javascript. I am so far that I have a kite moving some sort of power up on collision and an obstacle on collision.
Now I'm at the point I want to add lives and when you hit an obstacle your life will decrease 1.
I tried some stuff and when you hit an obstacle the life decreases but it decreases constantly and the player image gets removed instead of the obstacle image.
here is the life thing you can check all the code there.
http://nickzijlstra.com/kite
Here the code I think is the most important for the problem.
function hitObject(player, obj){
var a = (obj.x - player.x),
b = (obj.y - player.y),
c = Math.sqrt(a*a + b*b),
r0 = player.image.width/2,
r1 = obj.image.width/2;
if (c < r0+r1) {
player.drawable = false;
lifes -=1;
window.location.reload(true);
}
}
If someone sees the problem or knows the solution I would really appreciate it!
The reason the player disappears is because of this line in the hitObject function:
player.drawable = false;
This will cause the player to not be drawn because of this condition in your drawing function:
if (player.drawable == true) {
context.drawImage(player.image, player.x, player.y, player.image.width, player.image.height);
}
I presume you actually want to move the obj back to a random spot on the top of the screen if the player gets hit. It doesn't do this at the moment, which is why the lives go down rapidly: the object hits the player, it removes a life, and then the next frame it hits the player again (even though the player isn't visible).
What you might want is something like:
...
if (c < r0+r1) {
lifes -=1;
// Respawn the object.
obj.y = -50;
obj.x = Math.random() * canvas.width;
...
At a guess, I'd say that you should replace the
player.drawable = false;
with
obj.drawable = false;
and wrap the whole collision detection inside of an if obj.drawable=true so that removed obstacles won't collide with the kite.