jump algorithm isn't working when reaching a block - javascript

This is my jsfiddle: http://jsfiddle.net/seekpunk/whZ44/17/
As you can see in my jsfiddle when the ball reach a block the jump function is not working.I know i am missing something in my algorithm that i am using to make the ball jump but i can't figure it out i would appreciate some help from you
if (InAir) {
if (InAir == 1) {
if (ball.y > jumpMaxHeight) {
ball.y -= gravity;
} else {
InAir = 2;
}
}
if (InAir == 2) {
if (ball.y < 390) {
ball.y += gravity;
} else {
ball.y = 390;
InAir = false;
ball.color = "black";
}
}
} else if (keydown.up && !InAir) {
InAir = 1;
ball.color = "#4285F4";
}
for (var j = 0; j < Blocks.collection.length; j++) {
if (Collision(ball, Blocks.collection[j])) {
//console.log("collision");
ball.y = (Blocks.collection[j].blockY - ball.radius) ;
}
}

Maybe here is something to start with: http://jsfiddle.net/d247V/3/
I updated the jump to have a default jump of 80 (high enough to get to next platform), and then on keydown.up i update that with the current ball.y position + the default
I think though the issue is how you are tracking the ball being in the air or not, when a collision is detected, the ball is technically no longer in the air, but you didn't have anything saying as such, see code snipped below basically how #mainguy said but with a slight modification to not keep reassigning ball.y, in the fiddle it works pretty well:
if( InAir )
{
for (var j = 0; j < Blocks.collection.length; j++) {
if (Collision(ball, Blocks.collection[j])) {
//console.log("collision");
var calc = (Blocks.collection[j].blockY - ball.radius);
if( ball.y != calc ) {
ball.y = calc;
ball.color = "black";
InAir = 0;
}
}
}
}
My fiddle though broke the gravity portion of the code, because you now need to also know if the x of the circle is passed the x barrier of the rectangle, and fall if not. So this is by no means a complete solution, but if you jump and go right or left from a barrier, the gravity process works as expected as long as no collisions exist, you will fall down to the bottom. There are slight other tweaks but I think you will be able to find them by the comment //Tweaked next to the parts I added.

It seems like your collision detection is working pretty well.
Its the gameloop that has some issues.
You should not do a collision detection on keypress up because this will only fire once. You need to check for collides all the time while the ball is in the air.
Like so:
... } else if (keydown.up && !InAir) {
InAir = 1;
ball.color = "#4285F4";
}
if (InAir){
for (var j = 0; j < Blocks.collection.length; j++) {
if (Collision(ball, Blocks.collection[j])) {
//console.log("collision");
ball.y = (Blocks.collection[j].blockY - ball.radius) ;
InAir=false;
}
}
}
With his code you can jump on the first plattform. (Note also that i changed ball.y positioning).
But some issues remain:
The Ball can not leave the plattform because as soon as he is airborne the collision with the plattform he is lying on kicks in.
If you move the Ball left or right over the plattform border it would be way more fun if he starts falling down again, instead of hovering in the air. (Trust me, i played some games).
Maybe you should delay collision detection until the ball has gained some height to escape the collision detection.
I update your fiddle and converted it to a plunker (with firebug you have way better debugging functionality here) Play with me!
Not a perfect answer but i hope this will help you.

Related

Access all variables in an array

I'm sure this is a simple question but I'm asking it anyways. Basically I'm trying to do the following in javascript (no jquery) with less code:
var Ground = [];
function gameLoop()
{
Gravity += 0.2
if(Ground[0].isCollided(Player))
{
Player.dy = 0;
Gravity = 0;
}
if(Ground[1].isCollided(Player))
{
Player.dy = 0;
Gravity = 0;
}
if(Ground[2].isCollided(Player))
{
Player.dy = 0;
Gravity = 0;
}
Player.dy = Gravity;
}
I've simplified the code extremely from the code in my game I'm making using javascript and the html5 canvas.
What you see is my Ground mechanic as it stands. When the player collides with the Ground Block, the Player's .dy value will no longer change along with the Gravity.
What you saw above is how I would normally do it however this can take up a large amount of space if I have 50 FallingM variables. Is it possible to do something like:
if(Ground[i].isCollided(Player))
{
Player.dy = 0;
Gravity = 0;
}
So that the function will still run no matter how many Ground variables I add? Thanks ahead of time!
You should use a loop:
for(var x of Ground) {
if(x.isCollided(Player)) {
Player.dy = 0;
Gravity = 0;
break;
}
}
Remember, a Jedi's strength flows from the loops. But beware. Map,
reduce, some. The dark side are they. Once you start down the dark
path, forever will it dominate your destiny.
if (grounds.some(ground => ground.isCollided(player))) {
player.dy = 0;
gravity = 0;
}

Can't detect collision in 3D JavaScript

I am using three.js to make a simulation of the Brownian Motion and I'm stuck on a part where I need to get the little molecules to collide against each other. This is what I have so far:
function intersects(sphere, other){ //check if the distance between one sphere and the other is less than radius of both (4)
var distance = Math.sqrt((sphere.position.x - other.position.x) * (sphere.position.x - other.position.x) +
(sphere.position.y - other.position.y) * (sphere.position.y - other.position.y) +
(sphere.position.z - other.position.z) * (sphere.position.z - other.position.z));
if(distance < (4)){
return true;
} else {
return false;
}
}
function checkCollision(current){
for(var i = 0; i < balls.length; i++) {
if(intersects(balls[current], balls[i]) == true){
// balls[current].velocity.negate();
alert('hey');
}
}
}
When I run the code, I know for certain that the balls don't collide/intersect with each other, however I continuously get an alert box. I've tried to check if it's less than (sphere.radius + other.radius) but I don't think that's correct since it didn't seem to work. Also when I do keep it '< 4', it messes up the performance and it starts to run slowly at around 5 fps or less. checkCollision gets used here during the animation, so basically it checks it every time.
function animate(){
for(var i = 0; i < balls.length; i++){
balls[i].position.add(balls[i].velocity);
checkWallBoundaries(i);
checkCollision(i);
}
THREEx.WindowResize(renderer, camera);
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
stats.update();
}
I don't know why I can't get this to work. If someone could help me, that'd be greatly appreciated.
edit: Here's a picture of what happens when I uncomment the balls[current].velocity.negate() line https://puu.sh/uG1eS.png. The balls keep going back and forth but they're not even remotely close to each other, so I don't know why collision is being detected
Every ball collides with itself. You need to exclude i === current
for(var i = 0; i < balls.length; i++) {
if(current === i) continue;
if(intersects(balls[current], balls[i]) == true){
alert('hey');
}
}

JavaScript canvas: "Random" errors with collision detection

Working on a simple canvas application where the user can shoot bullets with a gun. (click = new bullet, arrow key = new direction)
Works almost perfectly except there are seemingly "random" occurrences of where if the direction is changed, collision will fail.
Here's my jsFiddle. Relevant snippets:
Bullet.prototype - animate():
animate: function () {
if (gun.velocity.direction === keys.left) {
this.coordinates.x -= this.velocity.speed.x;
} else if (gun.velocity.direction === keys.up) {
this.coordinates.y += this.velocity.speed.y;
} else if (gun.velocity.direction === keys.right) {
this.coordinates.x += this.velocity.speed.x;
} else if (gun.velocity.direction === keys.down) {
this.coordinates.y -= this.velocity.speed.y;
}
return this;
},
Bullet.prototype - collision():
collision: function (str) {
if (str === 'boundary') {
if (this.coordinates.x + this.velocity.speed.x > canvas.width || this.coordinates.x + this.velocity.speed.x < 0) {
this.velocity.speed.x = -this.velocity.speed.x;
} else if (this.coordinates.y + this.velocity.speed.y > canvas.height || this.coordinates.y + this.velocity.speed.y < 0) {
this.velocity.speed.y = -this.velocity.speed.y;
}
}
}
Key handling:
document.onkeydown = function (e) {
e = e.keyCode;
if (e === keys.left) {
gun.velocity.direction = keys.left;
} else if (e === keys.up) {
gun.velocity.direction = keys.up;
} else if (e === keys.right) {
gun.velocity.direction = keys.right;
} else if (e === keys.down) {
gun.velocity.direction = keys.down;
}
};
How do I figure out why this is happening and how I can stop it?
Ok I had a look and found your bug.
You have bullets that you have given the property speed that is two values x, and y You also have a direction. When you animate the bullets you check the direction and move the bullet in the correct direction by adding only to x or y depending on direction. But then when you test if the bullets hit the wall you ignore the direction and test against the bullets speed. The whole time you have the bullets x and y speed both not equal to zero. You collision test is testing bullets moving diagonally.
If you add this bit of code
ctx.strokeStyle = this.color;
ctx.beginPath();
// draw a line in the direction you are testing the wall to be
ctx.moveTo(this.coordinates.x, this.coordinates.y);
ctx.lineTo(this.coordinates.x + this.velocity.speed.x*10, this.coordinates.y + this.velocity.speed.y*10);
ctx.stroke();
where you render the bullets, you will see that the bullets are not traveling in the direction indicated by this.velocity.speed, but you use these values to test for the wall.
There is to much to change for a simple fix.
What to do.
For each bullet
Keep speed as a single number.
Create delta.x, and delta.y as the bullets vector.
Keep direction as a single value. As you already have.
When you shoot you use the direction to set the bullet vector (delta);
up set delta {x:0,y:-1},
down set delta {x:0,y:1},
left set delta {x:-1,y:0},
right set delta {x:1,y:0},
To move the bullet just add the deltas times the speed;
bullet.pos.x += bullet.delta.x * bullet.speed;
bullet.pos.y += bullet.delta.y * bullet.speed;
Speed has nothing to do with direction. It is a positive value describing distance over time.
Delta x and y is really all you need for the bullets direction, but no harm in holding the direction as a single value as well as long as the two match.
To test for the wall
// check if the bullet is moving in the x direction
// then check if it's about to hit the wall
if(bullet.delta.x !== 0 && (bullet.pos.x + bullet.delta.x * bullet.speed > wallLoc ||
bullet.pos.x + bullet.delta.x * bullet.speed < 0)){
bullet.delta.x = -bullet.delta.x; // reverse bullet
}
do the same for the y direction.
I don't know if it is your intention to change all the bullet directions when you press a key. If it is just go through all the bullets and change there deltas when a key is pressed.
Hope this is clear. Do ask if you need more info.

Force, acceleration, and velocity with Javascript

I am attempting to make objects move on screen based on force on the x-axis and y-axis. It seems to work properly when a force is applied to an object, but when the force is no longer applied, instead of the object continuing at the same velocity and direction, it goes off in a different direction with a different velocity. Is the error in this section of code? This is the only part I can think would be the problem.
var update = function (modifier) {
// rock going up/down wh
if(rocks[i].y > 0 && rocks[i].y < worldSizeY){
if(rocks[i] != null){
rocks[i].accelerationy = rocks[i].forcey/rocks[i].mass;
rocks[i].velocityy += (modifier*1000)*rocks[i].accelerationy;
rocks[i].y += (modifier*1000)*rocks[i].velocityy;
}
}
// rock going right/left
if(rocks[i].x < worldSizeX && rocks[i].x > 0){
if(rocks[i] != null){
rocks[i].accelerationx = rocks[i].forcex/rocks[i].mass;
rocks[i].velocityx += (modifier*1000)*rocks[i].accelerationx;
rocks[i].x += (modifier*1000)*rocks[i].velocityx;
}
}
rocks[i].forcex = 0;
rocks[i].forcey = 0;
}

Moving a player in tilemaps

I am using vanilla tilemaps, I am not sure if there is software out there related to tilemaps, but if there is be assured I am just using plain javascript, I have an issue though, I want to move the x of a player when a button is pressed, but it doesn't move, the player is green, and is identified by the number 4 on the tilemap.
it registers that I press the button(in console), but doesn't move the player at all, can anyone point out the issue? look at lines 62-89, thats where the error mostly occurs except for some global variables.
here's a link to the jsfiddle, I used this because I needed to show that the blocks don't move.
http://jsfiddle.net/8jr2ha3h/
var playerY = 0;
var playerX = 0;
var moveLeft = 65;
var moveRight = -65;
//THE PLAYER
player.onload = function(){
for(var i = 0; i < mapArray.length; i++){
for(var j = 0; j < mapArray[i].length; j++){
if(mapArray[i][j]==4){
context.drawImage(player, playerX, playerY, 45,37);
}
playerX+=45;
}
playerX = 0;
playerY +=37;
}
};
//KEY FUNCTIONS
document.onkeydown = function(e) {
//identifying that it's a window event.
e = e || window.event;
switch(e.which || e.keyCode) {
//37 is key for left arrow.
case 37:
{
playerX = playerX - moveLeft;
console.log(playerX);
console.log('left');
}
break;
}
}
Seems as though you're only drawing the player in player.onload(). You'll likely want to have all the rendering code in a single render() function, and possibly call that in player.onload() and then also call that function whenever the screen changes (the player moves, enemies move/die, the map changes for whatever reason... there are any number of reasons you'd need to redraw).
You may want to consider a main game loop here, which would (very simply) be something to the effect of:
while (true) {
checkForInputFromThePlayer(); // this can update player coordinates, etc
doSomeAI(); // Move some enemies around, have them attack the player
render();
}
EDIT: A great example of a Game Loop can be seen in yckart's answer to requestAnimationFrame at a limited framerate

Categories

Resources