Context :
I'm making a version of the popular game, Snake. And I encounter some issues when I try to avoid the appearance of the food at the same place of the parts of my snake.
So I produced this code with the framework Phaser :
generateFood: function() {
var randomX, randomY;
var rightLocation = false;
var foodOnSnake = false;
while(rightLocation === false) {
randomX = Math.floor(Math.random() * (this.game.width / squareSize)) * squareSize;
randomY = Math.floor(Math.random() * (this.game.height / squareSize)) * squareSize;
foodOnSnake = false;
for (var i = 0; i < snake.length; i++) {
if (snake[i].x === food.x && snake[i].y === food.y) {
foodOnSnake = true;
break;
}
}
if(foodOnSnake === false) {
rightLocation = true;
}
}
food = this.game.add.sprite(randomX, randomY, 'snake', 15);
}
The aim, is to create some random coordinates on the game. And, while the food is generate on a part of the snake (the for loop), I will generate other coordinates. But for unknown reason, after my snake is eaten the first food, the game crashed and the tab of Google Chrome does not responding.
I think there is a mistake with a loop but I can't find it.
You compare the coordinates of the snake's segments with food.x and food.y, which you never update inside the loop:
if (snake[i].x === food.x && snake[i].y === food.y) {
I believe you want to compare it to randomX and randomY instead:
if (snake[i].x === randomX && snake[i].y === randomY) {
Depending on the value of food's coordinates, your function likely results in an infinite loop.
Related
I'm building a snake game with 2 snakes, so typically, when one snake touches the other, the game should restart. However, what I have right now only checks for the entire x/y line that snake 2 is on. For example, if snake 2 were to be moving to the right/horizontally (they move infinitely because the walls are only portals that return the snake to the side they started on) and snake 2 moved up, it would eventually intercept the y line that snake 1 was moving on.Even though the snake on the left(1) isn't going to directly hit the snake on the right(2), it is about to die because it is going to cross the line that snake 2 is moving on
This is how the snake was made:
var grid = 16;
var grid2 = 16;
var count = 0;
var count2= 0;
var snake2 = {
x: 160,
y: 160,
dx: grid2,
dy: 0,
cells: [],
maxCells: 4,
};
var apple2 = {
x: 32,
y: 320
};
var snake = {
x: 160,
y: 160,
// snake velocity. moves one grid length every frame in either the x or y direction
dx: grid,
dy: 0,
// keep track of all grids the snake body occupies
cells: [],
// length of the snake. grows when eating an apple
maxCells: 4
};
//In this case the apple does not matter
var apple = {
x: 32,
y: 320
};
// get random whole numbers in a specific range
// #see https://stackoverflow.com/a/1527820/2124254
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// game loop
function loop() {
requestAnimationFrame(loop);
// slow game loop to 15 fps instead of 60 (60/15 = 4)
if (++count < 4) {
return;
}
count = 0;
context.clearRect(0,0,canvas.width,canvas.height);
// move snake by it's velocity
snake.x += snake.dx;
snake.y += snake.dy;
snake2.x += snake2.dx;
snake2.y += snake2.dy;
// wrap snake position horizontally on edge of screen
if (snake.x < 0) {
snake.x = canvas.width - grid;
}
else if (snake.x >= canvas.width) {
snake.x = 0;
}
// wrap snake position vertically on edge of screen
if (snake.y < 0) {
snake.y = canvas.height - grid;
}
else if (snake.y >= canvas.height) {
snake.y = 0;
}
if (snake2.x < 0) {
snake2.x = canvas.width - grid;
}
else if (snake2.x >= canvas.width) {
snake2.x = 0;
}
// wrap snake position vertically on edge of screen
if (snake2.y < 0) {
snake2.y = canvas.height - grid;
}
else if (snake2.y >= canvas.height) {
snake2.y = 0;
}
// keep track of where snake has been. front of the array is always the head
snake.cells.unshift({x: snake.x, y: snake.y});
snake2.cells.unshift({x: snake2.x, y: snake2.y});
// remove cells as we move away from them
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}
if (snake2.cells.length > snake2.maxCells) {
snake2.cells.pop();
}
//Here the snake checks for collision with itself and with the 2nd snake
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y || cell.x === snake.cells[i].x && cell.y === snake2.cells[i].y)
The beginning of the code is just to check if snake 1 crossed paths with itself/ran into itself. After the OR statement is where it checks for snake 1 intercepting snake 2.
I attempted to tweak my code so it would look for the exact coordinate the snake is moving on, like this:
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y || cell.xy === snake.cells[i].xy && cell.xy === snake2.cells[i].xy)
I put xy to check for both coordinates to try to create one coordinate point to look for. However, this only resulted in immediate death.
Does anyone have an idea of how to fix this? EDIT What else is needed?
I am a beginner with THREE.js and currently have a animation that spins a 3D model around its Y axis but for the website I am creating I need to rotate it back to origin during the timespan of 90 frames. I have tried using a various different code snippets but the problem is that it seems to work half the time and the other half it totally messes it up. I believe that it messes up more if I let it spin for a while.
Here is my current code for the rotation:
//angle
angle = ((room.rotation.y * 180) / Math.PI) % 360;
total_deg = room.rotation.y;
//for calculating the lap:
if(angle > 0) {
positiv = true;
} else {
positiv = false;
}
if(angle < last_angle) {
direction = "down";
} else {
direction = "up";
}
if(direction == "up" && positiv == true) {
lap = 1;
} else if(direction == "down" && positiv == true) {
lap = 2;
} else if(direction == "down" && positiv == false) {
lap = 3;
} else if(direction == "up" && positiv == false) {
lap = 4;
}
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
last_angle = ((room.rotation.y * 180) / Math.PI) % 360;
//rotating it back depending on what lap it currently is on
if(lap == 4) {
room.rotation.y += -total_deg / 90;
}
if(lap == 3) {
room.rotation.y += -(Math.PI - Math.abs(total_deg)) / 90;
}
if(lap == 2) {
room.rotation.y += (Math.PI - Math.abs(total_deg)) / 90;
} else {
room.rotation.y -= total_deg / 90;
}
//reset the rotation when the room has spun a lap - don't know why this is works but seems to fix some of the rotation problems
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
Have been stuck with this problem for days so any help would be appreciated
I hope I'm understanding your objective properly but to me it seems that there may be some confusion with degrees and radians as the units. Three.js uses radians, but I'm seeing 360 in your code which I'm unsure about.
Anyway this code seems like what you're trying to do, notice how it divides 2 pi (one rotation in radians) into 90 frames.
var i=0;
function update( event ) {
//angle
if(i++<90){
this.rotation.y += 2*Math.PI/90;
}
}
I figured it out using a Quaternion of the objects first rotation and rotating to that later. This example was very helpful: https://threejs.org/examples/#webgl_math_orientation_transform
I have a player of 50 width and 30 height. My problem is calculating the collision correctly. I figured how to do this by checking the middle of the player (you can see it below), but I have problem with accounting for his width and height as well - half of him will go through the wall before he stops.
The map is divided into many squares (for example 100x100 pixels, the 100 is called tileSize) and between the squares there either is a wall or isn't (each square is an object which can have top or/and left true, when true, you cannot pass that side of the square - there is a wall).
the collision detection (item == player):
//inner walls - map collisions
var tileX = Math.floor(item.pos.x / this.tileSize);
var tileY = Math.floor(item.pos.y / this.tileSize);
var tileX = Math.floor(item.pos.x / this.tileSize);
var tileY = Math.floor(item.pos.y / this.tileSize);
if(tileX == item.last_X && tileY == item.last_Y){return;} //if its the same tile..
var colidedX = false;
var colidedY = false;
/* Check X */
if (item.last_X > tileX) {
if (this.map[item.last_Y][item.last_X].left) {
item.pos.x = item.last_X * this.tileSize;
colidedX = true;
}
}
if (item.last_X < tileX) {
if (this.map[item.last_Y][item.last_X+1].left) {
item.pos.x = (item.last_X+1) * this.tileSize;
colidedX = true;
}
}
/* Check Y */
if (item.last_Y > tileY) {
if (this.map[item.last_Y][item.last_X].top) {
item.pos.y = item.last_Y * this.tileSize;
colidedY = true;
}
}
if (item.last_Y < tileY) {
if (this.map[item.last_Y+1][item.last_X].top) {
item.pos.y = (item.last_Y+1) * this.tileSize;
colidedY = true;
}
}
if(colidedX == false){
item.last_X = tileX;
}
if(colidedY == false){
item.last_Y = tileY;
}
I have an idea how I could do it, but it would be very complicated and long, so I thought there must be a simpler way to do this.
So I have 2 functions that I was hoping would work together to bounce an object around a div. I'm using a graphics library, so there will be some unfamiliar pieces of code below. I think you'll still understand the gist of what I'm trying to do.
function homepage_screensaver()
{
/*
Create Raphael object in the space of the div with id "homeandidiv"
*/
var pappos = $("#homeanidiv").position();
var papx = pappos.left;
var papy = pappos.top;
var papheight = $("#homeanidiv").height();
var papwidth = $("#homeanidiv").width();
var paper = Raphael(papx, papy, papwidth, papheight);
/*
paper: space in which the circle will be bound
*/
var circx = Math.floor(Math.random() * Number.MAX_VALUE) % papwidth;
var circy = Math.floor(Math.random() * Number.MAX_VALUE) % papheight;
/*
circx, circy: initial positions of circle on the paper
*/
var mycirc = paper.circle(circx, circy, 10);
mycirc.attr("fill","#F9C624");
var theta = Math.floor(Math.random() * Number.MAX_VALUE) % 4 + 1;
/*
theta = 1 <---> object moving at a 45-degree angle
theta = 2 <---> object moving at a 135-degree angle
theta = 3 <---> object moving at a 225-degree angle
theta = 4 <---> object moving at a 315 degree angle
*/
var circwrapper = new Array(mycirc, theta);
window.setInterval(function() { move_obj(circwrapper, papwidth, papheight);}, 100);
}
function move_obj(obwrap, backwidth, backheight)
{
var ob = obwrap[0]; // object
var th = obwrap[1]; // theta, the current direction of the object
var BB = ob.getBBox(); // bounding box for object
var dx = 0;
var dy = 0;
if (BB.x >= backwidth && (th == 1 || th == 2))
dx = -1;
else if (BB.x <= 0 && (th == 3 || th == 4))
dx = 1;
if (BB.y >= backheight && (th == 2 || th == 3))
dy = -1;
else if (BB.y <= 0 && (th == 1 || th == 4))
dy = 1;
ob.transform("T " + dx + ", " + dy);
if (dx == 1 && dy == -1)
th = 1;
else if (dx == 1 && dy == 1)
th = 2;
else if (dx == -1 && dy == 1)
th = 3;
else // (dx == -1 && dy == -1)
th = 4;
obwrap[0] = ob;
obwrap[1] = th;
}
Here's the problem that I've realized after testing my page: my function move_obj(...) is not actually affecting the first parameter I'm passing to it. You can see at the end of my function that I have
obwrap[0] = ob;
obwrap[1] = th;
indicating that I'm trying to actually modify values of the array that is passed in as the first parameter.
Is there any "quick fix" to my problem? I would prefer not to go back and try to make things global variables.
Just so you know, I have researched the issue of passing by reference in JS and here it says that arrays are passed by reference: http://orizens.com/wp/topics/javascript-arrays-passing-by-reference-or-by-value/. So I don't see what's going wrong here.
You have to do the reassignment after the "move" function returns.
window.setInterval(function() {
var wrapper = [mycirc, theta];
move_obj(wrapper, papwidth, papheight);
mycirc = wrapper[0];
theta = wrapper[1];
}, 100);
Assigning new values to the array works but it only affects the array. When you build the array, you're making copies of the values of the two variables. There's no subsequent implicit relationship between the array slots and the variables, so changes to the array have no effect on the values of the independent variables.
I'm working on a simple html5 platformer, building of a previous game but having trouble with collisions and physics. below is a sample of code regarding the floor and how it handles collisions. the full code is here. http://www.ambitiongames.co.uk/dev/game.php with the game being here http://www.ambitiongames.co.uk/dev/
the problem I'm having is the collisions are based on events grabbing which sometimes leaves the player in the floor not on it.
also, due to the way jumping and falling work there's no gravity, meaning a player can simply jump on a higher ledge and then walk off into the air.
whats the a good way to set up a permanent state of gravity ?
whats a good way to interact / collide with the floor or other objects ?
that.draw = function(){
try {
ctx.drawImage(that.image, that.x, that.y, that.width, that.height);
} catch (e) {
}
}
return that;
};
var nrOffloors = 40,
floors = [],
floorWidth = 20,
floorHeight = 40;
var generatefloor = function(){
for (var i = 0; i < 10; i++) {
floors[i] = new Floor(i * 20,280);
}
for (var i = 10; i < 12; i++) {
floors[i] = new Floor(i * 20,260);
}
}();
var checkCollisionfloor = function(){
floors.forEach(function(e, ind){
if (
(player.X < e.x + floorWidth) &&
(player.X + player.width > e.x) &&
(player.Y + player.height > e.y) &&
(player.Y + player.height < e.y + floorHeight)
) {
e.onCollide();
}
});
}
You can try a library like Box2D.js. It handles everything from collision detection to gravity.
Check out it's demos.