Collision detection is not returning inside limits - javascript

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

Related

Javascript - if-statement with multiple numeric conditions doesn't work

I'm trying to make a simple program in javascript+html. If exp exceeds within a certain range/exceeds a certain number, the level displayed goes up by 1. I've tried to make it show onload, but the level doesn't change no matter what happens to the exp staying at the highest one I've written code for so far.
Javascript:
var exp6 = localStorage.exp6;
var pexp6 = parseInt(exp6);
function char6() {
res.innerHTML = res6;
var lsps = pexp6;
localStorage.setItem("lsp", lsps);
return PrUpdate();
}
var lsp = localStorage.lps;
function PrUpdate() {
if (lsp <= 999) {
lvl.innerHTML = 1;
}
else if (lsp >= 1000 && lsp <= 1999) {
lvl.innerHTML = 2;
}
else if (lsp >= 2000 && lsp <= 2999) {
lvl.innerHTML = 3;
}
else if (lsp >= 3000 && lsp <= 3999) {
lvl.innerHTML = 4;
}
else if (lsp >= 4000 && lsp <= 4999) {
lvl.innerHTML = 5;
}
}
I've also included the setChar() function in the window.onload of the page. I've tried including the function itself in it as well, but whether I add it at the end of the setChar() or in the window.onload the problem stays the same. All other functions work fine, it's just this part that doesn't. I'm also trying to make it generic to fit other 'accounts' I'm trying to make to save myself time. But I just can't make it work.
Edit:
I've figured out why it didn't work, and it was cause I had my localStorage.lsp in the wrong place.
I'm trying to figure out now how to make it so I don't have to refresh the page to get it to appear.
[ Solved my issue :), if unclear by my edit above]
The way you are trying to access values from localstorage is incorrect. This is not valid: localstorage.exp6.
Instead try this: localstorage.getItem('exp6')
See the documentation of Web Storage API for more information

calling object.width is returning NaN in JavaScript

I am currently working on a game that has to do with a rocket ship moving around and objects(circles) are falling from the top. The goal of this game is to not hit the objects as they are falling down the screen. I am running into problems when writing my collision algorithm.
I have declared var hit = false; at the top of my code
I have also put all of the circles into an array called projectiles.
I believe that I have the logic correct but I discovered that when calling either p.width or ship.width it returns NaN. I have tried using offsetWidth and that didn't work either. I am wondering how else to go about getting the width of my objects
The else statement at the bottom is just to check if .width is returning the correct number. Once I get it to work it will be removed and replaced with the final parts of the collision algorithm.
function checkCollision()
{
for (i = 0; i < projectiles.length; i++) {
var p = projectiles[i];
if((p.x + p.width) < ship.x)
{
hit = false;
}
else if(p.x > (ship.x + ship.width))
{
hit = false;
}
else if(p.y > (ship.y + ship.height))
{
hit = false;
}
else if((p.y + p.height) < ship.y)
{
hit = false;
}
else {
console.log(ship.x + ship.width);
}
In the documentation for createjs.Bitmap there do not exist properties for .width and .height. Instead access it's .image (HTMLImageElement) property which have defined width and height properties: ship.image.width and ship.image.height.
If your object is an EaselJS Bitmap, you can retrieve the physical size using getBounds(). This method works for some EaselJS display objects (ie, not Shapes, and accuracy varies with Text).
var bounds = ship.getBounds();
var w = bounds.width;
Notes:
per #Spencer's message, you can access the .image, and get the width/height, but it will be the original size of the image, so if you transform the bitmap instance, or any of the parent containers, the value will be wrong. The getBounds will consider the scale transformation (if it exists)
values may not be correct if the item is rotated.
bounds are based on the registration point, so the x/y might be non-zero.
You will get 0 for width/height if the image is not yet loaded
For your projectile, if it is a shape, the bounds will always be null, but you can manually set them if you know them, and they will be properly calculated/transformed:
var p = new createjs.Shape();
p.graphics.beginFill("red").drawCircle(0,0,20);
p.setBounds(new createjs.Rectangle(-20,-20,40,40));
Here is some info on why there is no .width or .height: http://blog.createjs.com/update-width-height-in-easeljs/

Collision detection simple snake game

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.

Prevent touching corners (JS Game)

How can I prevent this map generator from creating touching corners like this:
-X
X-
Or
X-
-X
Here is a simplified example of the generator: http://jsfiddle.net/fDv9C/2/
Your question answers itself, almost.
Here's the fiddle: http://jsfiddle.net/qBJVY/
if (!!grid[y][x] && !!grid[y+1][x+1] && !grid[y+1][x] && !grid[y][x+1]) {
good=false;
grid[y+1][x]=2;
}
It simply checks for the combinations you do not want and patches them up. It always adds a grid point so as not to disconnect any parts of the map.
This in turn may lead to another situation where the issue may occur, but if it changed anything (that is, if it found a problem), it will simply check again. This can be optimized, for instance by recursively adjusting whatever was changed, but usually it only needs 1 or 2 passes. There's a limiter on there to not allow more than 100 passes, just in case there is some unforeseen circumstance in which it cannot fix it (I can't think of such a situation, though :) ).
Because of the way that you are creating board it's very difficulty to do this checking during generation. I create simple function that check board after. It's using flood algorithm. Here is the fiddle http://jsfiddle.net/jzTEX/8/ (blue background is original map, red background is map after checking)
Basically we create second array grid2. After filling grid we run recursively floodV function
function floodV(x,y) {
var shiftArray = [[0,1],[0,-1],[1,0],[-1,0]];
grid2[y][x]=1;
for(var k=0;k<4;k++) {
var x1=x+shiftArray[k][0];
var y1=y+shiftArray[k][1];
if(grid[y1][x1] == 1 && grid2[y1][x1] == 0 && checkV(x1,y1)) {
grid2[y1][x1] = 1;
floodV(x1,y1);
}
}
}
with the check function
function checkV(x,y) {
var checkVarr = [[-1,-1], [-1,1], [1,1], [1,-1]];
for(var k=0;k<4;k++) {
if(grid[y+checkVarr[k][0]][x+checkVarr[k][1]] == 1 && grid[y+checkVarr[k][0]][x] == 0 && grid[y][x+checkVarr[k][1]] == 0 && grid2[y+checkVarr[k][0]][x+checkVarr[k][1]] == 1)
return false;
}
return true;
}
This isn't perfect because we can sometimes throw away big parts of the map but if we try to start adding new elements we have to check whole map again (in worths case).
This is what I did: http://jsfiddle.net/fDv9C/13/
Where's the magic happening? Scroll down to lines 53 through 58:
var bottom = y_next + 1;
var left = x_next - 1;
var right = x_next + 1;
var top = y_next - 1;
if (grid[top][left] || grid[top][right] ||
grid[bottom][left] || grid[bottom][right]) continue;
In short your touching corner points can only occur at the computed next position. Hence if any one of the four corner neighbors of the next position exists, you must compute another next position.
You may even decrement the counter i when this happens to get as many paths as possible (although it doesn't really make a big difference):
var bottom = y_next + 1;
var left = x_next - 1;
var right = x_next + 1;
var top = y_next - 1;
if (grid[top][left] || grid[top][right] ||
grid[bottom][left] || grid[bottom][right]) {
i--;
continue;
}
See the demo here: http://jsfiddle.net/fDv9C/12/
Edit: I couldn't resist. I had to create an automatic map generator so that I needn't keep clicking run: http://jsfiddle.net/fDv9C/14/

How to speed up this moving algorithm? In Javascript

I have an Array of 16 billiard balls in JS and want to move each ball smoothly with its direction and speed.
For that I set up a timer, calling UpdateThis() every 42ms (for 24 fps).
The problem is that UpdateThis() takes 53ms as firebug states.
Now UpdateThis iterates over every ball and calls UpdateBall(ball).
I assume that the problem lies there.UpdateBall looks like this:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
it seems that the most time is spent in ball.MoveTo() which looks like this:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
-- UPDATE --
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
and onload looks like
nx = setInterval(function() { UpdateThis(); }, 42);
Does somebody have any ideas on how to speed this up?
-- UPDATE 2 --
You can download the folder with the HTML file here (the password is password)
What about separating the position updates from the drawing? So have something like this (untested code):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
If indeed it's the moving of the position that's slow, this way the logic update still happens at 42ms, and the framerate is no faster than 42ms but it can skip frames. (I haven't actually tried this, so this is all theoretical and you may need to tweak some stuff)
Why moving may be (and most probably is) slow?
Move functionality could be slow, because it has more things to do than simple variable assignment. It has to actually render some element to some other place. You could test this if you run this on IE9. I anticipate it should run faster since it uses hardware video acceleration.
As for the other routine I hope others will dissect it. :)
Questions for you
Can you please describe how do balls move? Sporadically? How do you call UpdateBall() for each ball? Do you queue those calls?
Provide VMul and VAdd functionality
Have you played with styling? Maybe relative positioning of balls' immediate parent may speed up rendering. And setting overflow:hidden on it as well. I don't know. Depends on how you've done it. Hence a JSFiddle would be very helpful.
A suggestion
Instead of using setInterval to call your function you should maybe just queue them and let them execute as fast as it gets. And just for the sake of it, provide a central setInterval with some watcher that they don't run too fast.
But I guess that it still utilizes your processor to 100% which isn't good anyway.
Very important note: Don't run you app while Firebug's enabled because it's a well known fact that Javascript executes much slower when Firebug is running.
That's tough, if MoveTo() is in fact your bottleneck, since there is not a whole lot going on there. About the only things I can think of, right off hand, are
1) Cache the style property of the image and position for faster lookups. Everytime you see a dot in the object chain it's requires stepping through the scope chain. Ideally you can cache this property at the time the parent of MoveTo() is constructed.
2) Are the 'px' strings required? It may result in an invalid CSS specification, but it may still work. I have a hard time believing 2 string concats would really change all that much though.
The main problem here is likely the fact that anytime you change the DOM, the browsers re-flows the entire page. Your only other option may be to refactor such that instead of changing the styles, you actually remove the previous contents, and replace it with the a document fragment describing the new state. This would result in only 2 re-flows for the entire step (1 for removal, 1 for addition), instead of 2 for each ball.
EDIT: Regarding #1 above, when I say cache, I don't mean just locally in the function call. But perhaps as a closure in the parent object. For example:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};

Categories