Collision check between vectors - moving vectors - HTML, JS, P5 - javascript

I have created the collision check function for my player to every time when the object (in this case vector - circle) touches the player (also a vector - circle) the game is over.
I have managed to create a logic and there is a collision check working, however it's not calculating the actual distance between elements (instead of ending game when they actually touch its ending when they are some distance from each other.
Both objects are moving - obstacle is moving x+=6 and the player is following the coursor so the speed varies.
I have tried adjusting distance slightly and I have managed to end the game when the x of obstacle is touch x of the player but could not managed actually to when boarders touch. I attach the code I have below;
class Player {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(500, 500);
this.mag = 3;
this.velLerp = 0.1;
}
update() {
let mouse = createVector(mouseX - width / 2,
mouseY - height / 2);
mouse.setMag(this.mag);
this.vel.lerp(mouse, this.velLerp);
this.pos.add(this.vel);
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
console.log("GAME OVER");
return true;
}

The issue is caused by the fact that the movement of the circles is 3 (this.mag) pixel. You just get the exact point of contact by chance. Most time they are intersecting.
If a collision is detected, change the player's position slightly by an offset of this.r + obstacle.r - d:
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
let shift = p5.Vector.sub(this.pos, obstacle.pos);
shift.setMag(this.r + obstacle.r - d);
this.pos.add(shift);
console.log("GAME OVER");
return true;
}
}

Related

How would I make a collider that stops the game when it collides with the "character"?

I'm still pretty new to this, so I don't know how to create a collider. My end goal is to have a game like the chrome dinosaur game. Same principles, and all. My question is, though, how do I even make a collider. I will be using a .gif for the "dinosaur". I'd like to make it where if this collider were to touch another collider, the game stops and a "game over" is shown. I have tried to create a collider, but they just keep showing up underneath the screen where the game is shown. Ant tips, tricks, or advice? Thanks
Code is as follows:
let img; //background
var bgImg; //also the background
var x1 = 0;
var x2;
var scrollSpeed = 4; //how fast background is
let music; //for music
let catBus; //catbus
//collider variables
let tinyToto;
let tiniestToto;
let hin;
let totoWithBag;
let noFace;
let happySoot;
var mode; //determines whether the game has started
let gravity = 0.2; //jumping forces
let velocity = 0.1;
let upForce = 7;
let startY = 730; //where cat bus jumps from
let startX = 70;
let totoX = 900;
let totoY = 70;
let tinToX = 900;
let tinToY = 70;
var font1; //custom fonts
var font2;
p5.disableFriendlyErrors = true; //avoids errors
function preload() {
bgImg = loadImage("backgwound.png"); //importing background
music = loadSound("catbus theme song.mp3"); //importing music
font1 = loadFont("Big Font.TTF");
font2 = loadFont("Smaller Font.ttf");
//tinyToto.setCollider("rectangle",0,25,75,75)
}
function setup() {
createCanvas(1000, 1000); //canvas size
img = loadImage("backgwound.png"); //background in
x2 = width;
music.loop(); //loops the music
catBus = {
//coordinates for catbus
x: startX,
y: startY,
};
/*
tinyToto = {
x: totoX,
y: totoY,
}
tinTo = {
x : tinToX,
y: tinToY,
}
*/
catGif = createImg("catgif.gif"); //creates catbus
catGif.position(catBus.x, catBus.y); //creates position
catGif.size(270, 100); //creates how big
/*
tinyToto = createImg("TinyToto.gif")
tinyToto.position(tinyToto.x, tinyToto.y)
tinyToto.size(270,100)
tiniestTo = createImg("tiniest Toto.gif")
tiniestTo.position(tinToX.x, tinToY.y)
tiniestTo.size(270,100)
*/
mode = 0; //game start
textSize(50); //text size
}
function draw() {
let time = frameCount; //start background loop
image(img, 0 - time, 0);
image(bgImg, x1, 2, width, height);
image(bgImg, x2, 2, width, height);
x1 -= scrollSpeed;
x2 -= scrollSpeed;
if (x1 <= -width) {
x1 = width;
}
if (x2 <= -width) {
x2 = width;
} //end background loop
fill(128 + sin(frameCount * 0.05) * 128); //text colour
if (mode == 0) {
textSize(20);
textFont(font1);
text("press SPACE to start the game!", 240, 500); //what text to type
}
fill("white");
if (mode == 0) {
textSize(35);
textFont(font2);
text("CATBUS BIZZARE ADVENTURE", 90, 450); //what text to type
}
catBus.y = catBus.y + velocity; //code for jumping
velocity = velocity + gravity;
if (catBus.y > startY) {
velocity = 0;
catBus.y = startY;
}
catGif.position(catBus.x, catBus.y);
//setCollider("tinyToto")
}
function keyPressed() {
if (keyCode === 32 && velocity == 0) {
//spacebar code
mode = 1;
velocity += -upForce;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
well, this is how I would generally do that kind of thingy:
function draw(){
for(let i in objects) // objects would be cactuses or birds
if(objects[i].x > player.x &&
objects[i].x < player.x + player.width &&
objects[i].y > player.y &&
objects[i].y < player.y + player.height){
noLoop()
// maybe do something else here
} // you could also use: for(let object of objects)
}
or if you want to do class stuff:
let player = new Player()
class Entity {
hasCollided_pointRect(_x, _y, _width, _height){
if(this.x > _x &&
this.x < _x + _width &&
this.y > _y &&
this.y < _y + _height){
return true
}
}
}
class Cactus extends Entity {
update(){
if(hasCollided_pointRect(player.x, player.y, player.width, player.height))
lossEvent()
}
}
class Player {
// ...
}
function lossEvent(){
noLoop()
}
this is a pretty classy way to do it and for a small game you really don't need all of this
also MDN has a nice article on rect with rect & point with rect collisions,
point with point collision is just (x == x && y == y)
https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
this is one of my recent loss "functions":
if(flag.health <= 0){
noLoop()
newSplashText("You lost!\nPress F5 to restart!", "center", "center", 1)
}
The way I handled game states in my Processing games was by making seperate classes for them. Then my main sketch's draw function looked something like
fun draw()
{
currentState.draw();
}
Each gamestate then acted as their own sketches (for example a menu screen, playing, game over, etc), and had a reference to the main sketch which created the states. They would then alter the main's currentState to, i.e., a new GameOverState() etc. where needed.
For now, don't worry about doing that too much if all you want a really simple gameoverscreen with an image and some text.
I would suggest a structure like this instead. Use this pseudocode in your main draw function:
fun draw()
{
if (gameOver)
{
// show game over screen
img(gameOver);
text("game over!");
// skip rest of the function
return;
}
// normal game code goes here
foo();
bar();
// update game over after this frame's game code completes
gameOver = checkGameOver();
}
Now you need a way of checking for a collision to determine the result of checkGameOver()
For the collision handling, check out Jeffrey Thompson's book/website on collision handling. It's an amazing resource, I highly recommend you check it out.
From the website I just linked, here's an excerpt from the website talking about handling collisions between 2d rectangles.
And here's a modified version of the collision handling function listed there (I updated the variable names to be a little more intuitive)
boolean rectRect(float rect1X, float rect1Y, float rect1Width, float rect1Height, float rect2X, float rect2Y, float rect2Width, float r2h)
{
// are the sides of one rectangle touching the other?
if (rect1X + rect1Width >= rect2X && // r1 right edge past r2 left
rect1X <= rect2X + rect2Width && // r1 left edge past r2 right
rect1Y + rect1Height >= rect2Y && // r1 top edge past r2 bottom
rect1Y <= rect2Y + r2h)
{ // r1 bottom edge past r2 top
return true;
}
return false;
You can use that function in your checkGameOver() function which would return a bool depending on whether your collision criteria are met.
For your game, you would loop over every obstacle in your game and check whether the dino and the obstacle overlap.
Pseudocode:
boolean checkGameOver()
{
foreach (Obstacle obstacle in obstacles)
{
if (rectRect(dino, obstacle))
{
return true;
}
}
return false;
}

Give circle random direction after hitting another circle in p5.js

Im am creating a COVID-19 simulator where every circle in the simulation is a person. When two persons hit each other, i want the direction that they "bounce" off each other to be random. Currently i just mirror the current speed, which means the the persons follow a pre defined path, even when bouncing of each other.
This is my "move" function
move() {
if (this.willMove) {
this.xPos += this.xSpeed;
this.yPos += this.ySpeed;
}
}
This where i do my collision detection
collision(other) {
let distance = dist(this.xPos, this.yPos, other.xPos, other.yPos);
if (distance < this.personRadius + other.personRadius) {
this.changeDirection();
return true;
} else {
return false;
}
}
The things handeling the changing of direction:
changeDirection() {
this.mirrorXSpeed();
this.mirrorYSpeed();
}
mirrorXSpeed() {
this.xSpeed = this.xSpeed * -1;
}
mirrorYSpeed() {
this.ySpeed = this.ySpeed * -1;
}
I have tried multiplying the speed by -0.95, but this just decreases the speed.
The full project can be found here: https://github.com/perkynades/Simulation-of-COVID19/tree/part1
This might help, it will make all the people bounce in a random direction when called.
You will have to add this.speed to your person constructor, and make sure angle mode is set to radians.
changeDirection() {
//This next line will change the speed by a random amount,
//delete it if you don't like it,
//or change the range for a different behavior
this.speed += random(1,3) * random([-1,1])
let ang = random(PI * 2)
this.changeXSpeed(ang);
this.changeYSpeed(ang);
}
changeXSpeed(ang) {
this.xSpeed = this.speed * cos(ang);
}
changeYSpeed(ang) {
this.ySpeed = this.speed * sin(ang);
}
}
If you want a more realistic bounce, I would check out Chris courses video on Collision detection it gives a natural fell to circle on circle collisions, and even though it is not all P5.js, it is was very helpful to me and I hope that it will be for you too.

JavaScript canvas make object shoot toward object

I'm new in JavaScript and I'm creating a kind of shooting game. I'm to make 1 object to move toward another object. So the "bullet" get the location of the "prey" and it will move toward it. I have no idea how to implement that, I can't find anything similar on the internet. So, I tried at first something simpler:
In the following code the "bullet" move to the left. How can I specify to move it toward an object?
I have 2 object. It's the enemyBullet object(not the bullet object) which should go toward another object.
PS: English is not my native language. Sorry for any confusion
thanks.
this.draw = function () {
this.context.clearRect(this.x + 2, this.y + 1.5, this.width - 4.5, this.height);
//x+ the speed make it go to the left
this.x += this.speed;
if (self === "bullet" && this.x >= this.canvasWidth) {
return true;
}
else if (self === "enemyBullet" && this.x >= 1000) {
console.log(this.x);
return true;
}
else {
if (self === "bullet") {
this.context.drawImage(imageRepository.bullet, this.x, this.y);
}
else if (self === "enemyBullet") {
this.context.drawImage(imageRepository.enemyBullet, this.x, this.y);
}
return false;
}
};
Normalised vector
You need to find the normalised vector from one object to the next. A vector is just an arrow that has a direction and a length. In this case we normalise the length, that is make it equal to 1 unit long. We do this so we can easily set a speed when using the vector.
Function to return a vector from one point to the next
// Code is in ES6
// fx, fy is from coordinate
// tx, ty is to coordinate
function getNormVec(fx, fy, tx, ty){
var x = tx - fx; // get differance
var y = ty - fy;
var dist = Math.sqrt(x * x + y * y); // get the distance.
x /= dist; // normalised difference
y /= dist;
return {x,y};
}
Once you have the vector you can move an object by adding the vector times the speed. Example of creating and moving a bullet from myObj to myTarget
var myObj = {}
var myTarget = {};
var myBullet = {}
myObj.x = 100;
myObj.y = 100;
myTarget.x = 1000
myTarget.y = 1000
var vecToTag = getNormVect(myObj.x, myObj.y, myTarget.x, myTarget.y);
myBullet.nx = vecToTag.x; // set bullets direction vector
myBullet.ny = vecToTag.y;
myBullet.x = myObj.x; // set the bullet start position.
myBullet.y = myObj.y;
myBullet.speed = 5; // set speed 5 pixels per frame
To move the bullet
myBullet.x += myBullet.nx * myBullet.speed;
myBullet.y += myBullet.ny * myBullet.speed;

wall collision detection with html5 canvas [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am making a game and there is a wall that I don't want the player to pass. I am using html5 canvas and have a player object to hold the x and y values. The wall is at x: 650 and y: 0. Since the player is 20x20 pixels when its x coordinate is 630, it touches the wall.
if(player.x > 630 && player.y <= 500) {
player.x = 630;
}
What is wrong with this code? I appreciate any help!
Answer
The code you have give is OK, there is nothing wrong with it. So I suspect the problem is elsewhere in the code, most likely in the movement code. If you are moving the player after the wall test and then display it, the player may start to creep into the wall, but without the rest of the code it is hard to know what is wrong with your code.
I have included more details on the correct way to do collision tests as there are two answers showing only a partial solution. It is there as a general guide to collision testing and may not be directly applicable to the question.
Inter frame movement
The correct way to reflect an object from a surface.
You must take into account that the ball is moving between frames and that the collision may have happened at any time during the previous frame. The ball's distance from the wall after the collision is dependent on when during the previous frame it hit the wall. This is important if the ball moves slowly or quickly.
var dx = 10; // delta x velocity of object in pixels
var wx = 10; // width of object in pixels
var px = 90; // position of object in pixels
var wallX = 105; // position of wall
px += dx; // move the ball. Its position is now 100.
// its right side is at px + wx = 110.
// test if it has it the wall
if(px+wx > wallX){
dx = -dx; // reflect delta x
// The object is 5 pixel into the wall.
// The object has hit the wall some time during the last frame
// We need to adjust the position as the ball may have been
// traveling away from the wall for some time during the last frame.
var dist = (px+wx)-wallX; // get the distance into the wall
px -= dist*2; // the object hit the wall at position 95 and has been
// traveling away since then so it is easy to just
// subtract 2 times the distance the ball entered the wall
// the above two lines can be done in one
// px -= ((px+wx)-wallX)*2;
}
Why it matters
Below is a simulation of a ball bouncing inside the canvas.
To illustrate that the ball is moving between frames it has been motion blurred to show its motion between frames. Please note this is not the perfect solution as the bounce is assumed to occur while the ball is in linear motion while infact it is in freefall and under constant acceleration. But it still conserves energy.
In the correct test the height the ball bounces back to, stays around the same over time. No energy is lost or gained.
Right click to turn off the inter frame adjustment and you will notice that the ball begins to decrease its height each frame. This is because at each collision the ball loses a little energy because it motion during the previous frame is not taken into account when positioning it after the collision test. It will settle down to a constant rate when the collision occurres at precisely the frame time. When that will be is very hard to determine in advance.
Left click to slow the simulation frame rate, left click again to return to normal.
The code below is not really part of the answer, it is there to demonstrate the effect of not correctly adjusting the position during collision test on the overall accuracy of the simulation.
// helper functions. NOT part of the answer
var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");
var mouseButton = 0;
canvas.addEventListener('mousedown',function(event){mouseButton = event.which;});
canvas.addEventListener('mouseup' ,function(){mouseButton = 0;});
canvas.addEventListener("contextmenu", function(e){ e.preventDefault();}, false);
var currentSurface = ctx;
var createImage = function (w, h) {// create an canvas image of size w,h and attach context 2d
var image = document.createElement("canvas");
image.width = w;
image.height = h !== undefined?h:w;
currentSurface = image.ctx = image.getContext("2d");
return image;
}
var setColour = function (fillC, strokeC, lineW) {
currentSurface.fillStyle = fillC !== undefined ? fillC : currentSurface.fillStyle;
currentSurface.strokeStyle = strokeC !== undefined ? strokeC : currentSurface.strokeStyle;
currentSurface.lineWidth = lineW !== undefined ? lineW : currentSurface.lineWidth;
}
var circle = function(x,y,r,how){
currentSurface.beginPath();
currentSurface.arc(x,y,r,0,Math.PI*2);
how = how.toLowerCase().replace(/[os]/g,"l"); // how to draw
switch(how){
case "f": // fill
currentSurface.fill();
break;
case "l":
currentSurface.stroke();
break;
case "lf":
currentSurface.stroke();
currentSurface.fill();
break;
case "fl":
currentSurface.fill();
currentSurface.stroke();
break;
}
}
function createGradImage(size,col1,col2){
var image = createImage(size);
var g = currentSurface.createLinearGradient(0,0,0,currentSurface.canvas.height);
g.addColorStop(0,col1);
g.addColorStop(1,col2);
currentSurface.fillStyle = g;
currentSurface.fillRect(0,0,currentSurface.canvas.width,currentSurface.canvas.height);
return image;
}
function createColouredBall (ballR,col) {
var ball = createImage(ballR*2);
var unit = ballR/100;
setColour("black");
circle(ballR,ballR,ballR,"f");
setColour("hsl("+col+",100%,30%)");
circle(ballR-unit*3,ballR-unit*3,ballR-unit*7,"f");
setColour("hsl("+col+",100%,50%)");
circle(ballR-unit*10,ballR-unit*10,ballR-unit*16,"f");
setColour("White");
circle(ballR-unit*50,ballR-unit*50,unit*16,"f");
return ball;
}
//===================================
// _
// /_\ _ _ ____ __ _____ _ _
// / _ \| ' \(_-< V V / -_) '_|
// /_/ \_\_||_/__/\_/\_/\___|_|
//
// ==================================
// Answer code
// lazy coder variables
var w = canvas.width;
var h = canvas.height;
// ball is simulated 5cm
var pixSize = 0.24; // in millimeters for simulation
// Gravity is 9.8 ms^2 so convert to pixels per frame squared
// Assuming constant 60 frames per second. ()
var gravity = 9800*pixSize/60;
gravity *= 0.101; // because Earth's gravity is stupidly large let's move to Pluto
// ball 5cm
var ballR = (25/pixSize)/2; // radius is 2.5cm for 5cm diamiter ball
var ballX = w/2; // get center of canvas
var ballY = ballR+3; // start at the top
var ballDX = (Math.random()-0.5)*15; // start with random x speed
ballDX += ballDX < 0 ? -5 : 5; // make sure it's not too slow
var ballDY = 0; // star with no downward speed;
var ballLastX = ballX;
var ballLastY = ballY;
//create an image of the Ball
var ball = createColouredBall(ballR,Math.floor(Math.random()*360)); // create an image of ball
// create a background. Image is small as it does not have much detail in it
var background = createGradImage(16,"#5af","#08C");
// time to run for
var runFor = 10*60; // ten secons yimes 60 frames per second
// draws the ball motion blured. This introduces extra complexity
var drawMotionBlur = function(image,px,py,dx,dy,steps){
var i,sx,sy;
sx = dx / steps;
sy = dy / steps;
px -= dx; // move back to start position
py -= dy;
ctx.globalAlpha = 1/(steps*0.8); // set alpha to slightly higher for each step
for(i = 0; i < steps; i+= 1){
ctx.drawImage(image,px+i*sx,py+i*sy);
}
ctx.globalAlpha = 1; // reset alpha
}
// style for text
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.textAlign = "center";
ctx.lineJoin = "round"; // stop some letters getting ears.
ctx.lineWidth = 3;
ctx.textBaseline = "bottom";
var textCenterX = w/2;
var maxHeight = Infinity;
var lastMaxHeight = ballY;
var slowMotion = false; // slow motion flag
var frameTravel = true; // use frame travel in collision test
var update = function(){
var blurSteps = 10; // motion blur ball render steps
const bSteps = 10;
if(mouseButton === 1){
slowMotion = ! slowMotion;
mouseButton = 0;
}
if(mouseButton === 3){
frameTravel = ! frameTravel;
ballX = w/2; // get center of canvas
ballY = ballR+3; // start at the top
ballDY = 0; // start at 0 y speed
mouseButton = 0;
}
// clear the canvas with background canvas image
ctx.drawImage(background,0,0,w,h);
ballDY += gravity; // accelrate due to grav
// add deltas to ball position
ballX += ballDX;
ballY += ballDY;
// test for collison on left and right walls. Need to
// ajust for motion blur
if (ballX < ballR) {
ballDX = -ballDX; // refect delta x
if (frameTravel) { // if using frame travel time
// blur the outward traveling ball only for the time it has been traveling away
blurSteps = Math.ceil(10 * ((ballX - ballR) / -ballDX));
// get position it should have traveled since
ballX -= (ballX - ballR) * 2;
}else{
ballX = ballR; // move ball to touching wall
blurSteps = 1; // there is no outward motion
}
} else
if (ballX > w - ballR) {
ballDX = -ballDX;
if (frameTravel) { // if using frame travel time
// blur the outward traveling ball only for the time it has been traveling away
blurSteps = Math.ceil(10 * ((ballX - (w - ballR)) / -ballDX));
ballX -= (ballX - (w - ballR)) * 2;
}else{
ballX = w - ballR; // move ball to touching wall
blurSteps = 1; // there is no outward motion
}
}
if (ballY > h - ballR) {
ballDY = -ballDY;
// to show max height
lastMaxHeight = maxHeight;
maxHeight = Infinity;
if (frameTravel) { // if using frame travel time
// blur the outward traveling ball only for the time it has been traveling away
blurSteps = Math.ceil(10 * ((ballY - (h - ballR)) / -ballDY));
ballY -= (ballY - (h - ballR)) * 2;
}else{
ballY = h - ballR; // move ball to touching wall
blurSteps = 1; // there is no outward motion
}
}
// draw the ball motion blured
drawMotionBlur(
ball, // image to draw
ballX - ballR, // offset radius
ballY - ballR,
ballDX * (blurSteps / bSteps), // speed and adjust for bounced
ballDY * (blurSteps / bSteps),
blurSteps // number of blurs
);
// show max height. Yes it is min but everything is upside down.
maxHeight = Math.min(maxHeight,ballY);
lastMaxHeight = Math.min(ballY,lastMaxHeight);
// show max height
ctx.font = "12px arial black";
ctx.beginPath();
ctx.moveTo(0,lastMaxHeight - ballR);
ctx.lineTo(w,lastMaxHeight - ballR);
ctx.stroke();
ctx.fillText("Max height.",40,lastMaxHeight - ballR + 6);
var str = ""; // display status string
if(slowMotion){ // show left click help
str += "10fps."
ctx.fillText("click for 60fps.",textCenterX,43);
}else{
str += "60fps."
ctx.fillText("click for 10fps.",textCenterX,43);
}
if(frameTravel){ // show mode and right click help
str += " Mid frame collision.";
ctx.fillText("Right click for Simple collision",textCenterX,55);
}else{
str += " Simple collision.";
ctx.fillText("Right click for mid frame collision",textCenterX,55);
}
// display help text
ctx.font = "18px arial black";
ctx.strokeText(str,textCenterX,30);
ctx.fillText(str,textCenterX,28);
if(slowMotion){
setTimeout(update,100); // show in slow motion
}else{
requestAnimationFrame(update); // request next frame (1/60) seconds from now
}
// all done
}
update(); // to start the ball rolling
.canC { width:500px; height:500px;}
<canvas class="canC" id="canV" width=500 height=500></canvas>
For a wall running along the X axis at the bottom (Y = 0) of a 650 x 650 field, we would want:
if (player.y <= 20) {
player.y = 20;
}
For a wall running along the Y axis at the left side (X = 0) of a 650 x 650 field, we would want:
if (player.x <= 20) {
player.x = 20;
}
For a wall running along the Y axis at the right side (X = 650) of a 650 x 650 field, we would want:
if (player.x >= 630) {
player.x = 630;
}
For a wall running along the X axis at the top (Y = 650) of a 650 x 650 field, we would want:
if (player.y >= 630) {
player.y = 630;
}
This code is similar to the code I use, if we attach horizontal (h) and vertical (v) velocity attributes to the player object we can multiply them by negative one to get them to bounce off of the wall if the player is going to go beyond the bounds. Or if you want it to stop, set them equal to zero at the wall.
//player.x+player.h gives us the future position of the player
if (player.x+player.h>630||player.x+player.h<0)
{
player.h*=-1;//bounce
//stop player.h=0;
}
if (player.y+player.v>500||player.y+player.v<0)
{
player.v*=-1;
//stop player.v=0;
}
//new player coordinates
player.x+=player.h;
player.y+=player.v;
Hope this helps.

JavaScript 2D collision anomaly

I'm experimenting with HTML5 canvas scripting in JavaScript and am having an issue with 2D collision detection. I'm basically checking the coordinates of the "player" against the coordinates of a box I've placed on screen but a strange result is occurring. I know why it's happening, but I don't know how to solve the problem.
Some of my code:
function Arc()
{
// Coordinates.
this.x = 540 / 2;
this.y = 0;
// Radius
this.r = 50;
// Gravity / velicoty.
this.g = 3;
this.vy = 15;
// Bounce.
this.b = -0;
this.speed = 20;
this.max_speed = 20;
this.friction = 0.03444;
}
Arc.prototype.collision = function()
{
for(var i = 0; i < game.sprites.length; i++)
{
if
(
// If the right side of the player is greater than the left side of the object.
this.x + this.r > game.sprites[i].x &&
// If the bottom of the player is greater than (meaning lower than) the top of the object.
this.y + this.r > game.sprites[i].y &&
// If the left side of the player is greater than the right side of the object.
this.x - this.r < game.sprites[i].x + game.sprites[i].w &&
// if the top of the player is greater than (meaning lower than) the bottom of the object.
this.y - this.r < game.sprites[i].y + game.sprites[i].h
)
{
this.y = game.sprites[i].y - this.r;
this.vy *= this.b;
}
}
}
The anomaly is that when I move the player sprite over the left or right of the box, it jumps upwards on the Y-axis because the logical check above is always true. Obviously this is unexpected because the sprite should only interact with the top of the box if a jump has occurred.
Note: I'm not looking for a solution that adds collision to the sides of the box only (that's very simple). Rather, I'm looking for the solution that allows for collision on all sides of the box (including the top) in the same way it currently works but without the anomaly where the sprite suddenly jumps on top of the box upon touching it.
I've reproduced my entire project on JSFiddle for the purposes of demonstration (keys a, d and space bar): http://jsfiddle.net/h5Fun/
Whether or not this is what you want, it solves the problem:
this.x = game.sprites[i].x + 150;
this.vx *= this.b;
The issue was you were setting the incorrect component upon collision. If you want the circle to stop when it hits the rectangle, not go on top of it, then use x, not y.
150 is the size of the rectangle. This means it will stop at the right side of the sprite. The bouncing is already there due to modifying the velocity (this.vx).

Categories