camera in a js game, follow player - javascript

So lately I've been trying to make a 2D Zelda-like game. I want to make a camera to follow the player.
So I looked at https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate, https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations, and some others in my search (MDN has an article on it but I couldn't follow although it didn't look like what I was looking for).
I also didn't want to just center the player, I want to have a camera which has a limit, so you have to go a certain amount outside of the camera for the map to start scrolling.
function camera(data) {
var x, y;
if(I.x <= 2 && I.x >= -2 && I.y <= 2 && I.y >= -2) { x = 0; y = 0;}
if(I.x > 2) { x = -I.size; y = 0; }
if(I.x < -2) { x = I.size; y = 0; }
if(I.y > 2) { x = 0; y = -I.size; }
if(I.y < -2) { x = 0; y = I.size; }
ctx.translate(x, y);
draw.map();
draw.camera();
draw.players(data);
ctx.resetTransform();
}
draw.map() draws the tiles.
draw.camera() draws a little dotted box so I know the boundary of the camera.
draw.players(data) draws every player.
I.size refers to the size of each tile(16 in this case).
I.x & I.y are self explanatory.
I do have a working version(uses node and socket.io):
http://dais-jaackotorus.codeanyapp.com:8080/
EDIT:
Almost forgot! The problem with this code is that it follows the player for only one tile and then it doesn't any longer, and it goes outside of the camera range instead of staying inside and I dont understand why.

Here's a simplified example:
https://jsfiddle.net/2xbo0kas/
The trick is to start drawing the world around the player. So, in the jsfiddle, you can see the player is stationary but the map moves, so that the player is always centered into the viewport.
What the fiddle does not show is the final position of the player once you reach the edge of the map (where you'd draw a stationary map but update the player rectangle).
function draw() {
var startx = Math.max([player.x - size.width], 0);
var endx = Math.min(startx + size.width, map.length);
var starty = Math.max([player.y - size.height], 0);
var endy = Math.min(starty + size.height, map[0].length);
for (var x = startx; x < endx; x++) {
for (var y = starty; y < endy; y++) {
var drawx = x - startx;
var drawy = y - starty;
//draw tile
}
}
//draw player
}

Related

passing through and outputting value to console but not drawing on the canvas

There are a few similar questions but none of the answers fix my issue. I am simulating a solar system using canvas. The animation function calls a function to update the positions and then these positions are shown on screen in the form of circles. I have tried not calling the function animate and simply drawing the bodies using the initial conditions and this works fine however when trying to draw them via the animate function nothing is drawn - no even the sun - even though the functions have been passed through.
Why are they not drawing on the canvas?
here is the code (i have removed the for loop which would draw all the planets to only draw the earth just for development purposes, i have also not copied in all the global variables at the top as they take up a lot of space):
var massList = [massMecury, massVenus, massEarth, massMars, massJupiter, massSaturn, massUranus, massNeptune];
var xPosList = [initialMecuryXPos, initialVenusXPos, initialEarthXPos, initialMarsXPos, initialJupiterXPos, initialSaturnXPos, initialUranusXPos, initialNeptuneXPos];
var yPosList = [initialMecuryYPos, initialVenusYPos, initialEarthYPos, initialMarsYPos, initialJupiterYPos, initialSaturnYPos, initialUranusYPos, initialNeptuneYPos];
var xVelList = [initialMecuryXVel, initialVenusXVel, initialEarthXVel, initialMarsXVel, initialJupiterXVel, initialSaturnXVel, initialUranusXVel, initialNeptuneXVel];
var yVelList = [initialMecuryYVel, initialVenusYVel, initialEarthYVel, initialMarsYVel, initialJupiterYVel, initialSaturnYVel, initialUranusYVel, initialNeptuneYVel];
//position and velocity scales so they fit on the screen
var posScale = 1.7E10;
//var velScale = 3E9;
var pauseButtonPressed = false;
function axis (){
var canvas = document.getElementById("solarsys");
c=canvas.getContext('2d');
//moves the origin to the centre of the page
c.translate(400, 275);
//makes the y axis grow up and shrink down
c.scale(1,-1);
//c.fillRect(-innerWidth/2,-innerHeight/2,innerWidth,innerHeight); if want a black background
}
function calAcc(i) {
//calculates distance between the earth and the sun
var r = Math.sqrt((xPosList[i]*xPosList[i]) + (yPosList[i]*yPosList[i]));
//calculates the angle of displacement between the earth and sun
var theta = Math.atan(yPosList[i]/xPosList[i]);
//calculate the force on the earth using F = Gm1m2/r^2
//force is towards the centre of the sun
var F = (G*massSun*massList[i])/(r*r);
//correct the angle based on which quadrant it is in
theta=Math.abs(theta);
if (xPosList[i] < 0 && yPosList[i] < 0){
theta = theta;
} else if (xPosList[i] > 0 && yPosList[i] < 0){
theta = Math.PI-theta;
} else if (xPosList[i] > 0 && yPosList[i] > 0){
theta = theta-Math.PI;
} else{
theta = (2*Math.PI)-theta;
}
var fX = Math.cos(theta)*F;
var fY = Math.sin(theta)*F;
//calculate earths acceleration using Newton 2nd a = F / m
var aX = (fX/massList[i]);
var aY = (fY/massList[i]);
return [aX, aY];
}
function leapfrog(i) {
var dt = 5000;
var a = calAcc(i);
xVelList[i] = xVelList[i] + (a[0]*dt);
yVelList[i] = yVelList[i] + (a[1]*dt);
xPosList[i] = xPosList[i] + (xVelList[i]*dt);
yPosList[i] = yPosList[i] + (yVelList[i]*dt);
}
function drawBody(i) {
c.beginPath();
c.arc(xPosList[i]/posScale, yPosList[i]/posScale, 1, 0, twoPi, false);
c.stroke();
c.closePath();
console.log('body drawn');
}
function drawSun(){
//draw a yellow circle - the sun
c.beginPath();
c.arc(0, 0, 2, 0, twoPi, false);
c.fillStyle = '#ffcc00';
c.fill();
c.stroke();
c.closePath();
}
function animate() {
var i = 2;
//for (var i=0; i< xPosList.length; i++){
leapfrog(i);
drawBody(i);
drawSun();
console.log(xPosList);
//clears canvas each new loop
c.clearRect(-innerWidth/2,-innerHeight/2,innerWidth,innerHeight);
}
window.onload=function() {
axis();
var looper=setInterval(animate,1);}
You have several problems to fix:
You have a setInterval which is executed with pauses of 1 milliseconds. This seems to be too quick and I absolutely do not see any guarantee that your browser will be able to draw the things to be drawn.
In your animate function you draw things, but instantly remove them. You need to clear the canvas first and only then draw things on the canvas.
Your code is very difficult to read, consider refactoring it

Collision detection between a Polyline and a Circle

So I am rendering a Polyline with the Y-Values of a sin wave with the code below
var amplitude = 50;
var dx = (TWO_PI / period) * 10
var yValues = new Array(floor(widthOfWave / xSpacing));
var poly = [];
this.calculate = () => {
//Increment theta
theta += 0.02;
//For every x value, calculate the y value with SIN function
var x = theta;
for(var i = 0; i < yValues.length; i++) {
yValues[i] = sin(x) * amplitude;
x += dx;
}
this.render = () => {
this.calculate();
ellipseMode(CENTER);
beginShape();
for(var i = 0; i < yValues.length; i++) {
var temp = createVector((i * spacing), windowWidth + yValues[i]);
curveVertex(temp.x, temp.y);
poly.push(temp);
}
endShape();
}
Which renders the wave
This is exactly what I want, but the problem I am having is when I try to incorporate p5.collide2d (Github Link Here). I want to have an ellipse, the 'Player' in this case, be able to ride the wave by holding left and right on the keyboard arrows. I haven't gotten to the keyboard interaction, because I am currently stuck on having the Ellipse (a perfect circle) not just falling through the curve at sometimes.
Here is my code for the current collision I am testing with.
this.checkCollision = (objX, objY, objSize) => {
var hit = false;
var hit = collideCirclePoly(objX, objY, objSize, poly);
return hit;
}
//Check for the collision
var hit = hill.checkCollision(player1.x, player1.y, player1.size);
if(hit) player1.didCollide();
//Player's didCollide function
this.didCollide = () => {
newSpeed = this.ySpeed * -0.8;
this.ySpeed = newSpeed;
}
This is how the circle (the "Player") and the wave intereact whenever I try to run it though.
I can't seem to figure out why the interaction is happening this way. I have tried extending the bounds of the collision, but it just makes it appear very glitchy and it still sometimes just passes through the wave with what appears to be no collision.
I am fairly new to p5.js and processing, so I am most likely missing something very simple. Thanks for your help ahead of time!

p5.js object collision and objects entangling

I wrote some code in p5.js to see if i can properly make a collision detection system but when i put more than 2 squares in, squares seem to bump each other inside of other squares. I'd like to know if there's anyway to stop this plus, if you have any good pointers on how to do tidy/shorten my code id like to hear them.
My code:
var r; //later defined as an array for the squares
var num; //number of squares
function setup(){
r = [];
num = 10;
createCanvas(windowWidth,windowHeight- 4);
for(var i = 0;i < num; i++){
r[i] = new Box(random(width-40),random(height-40),40,40);
}
}
function draw(){
background(40);
for(var i = 0;i < num; i++) {
r[i].show();
for(var j = 0;j<num; j++){
//this is the if statement evaluating if the left and right of the square is touching each other. i is one square and j is the other. you see in each if statement i have the acceleration being added, this is because if it wasn't then they would be true if the squares were touching each other on any side
if(r[i].right+r[i].xa >= r[j].left && r[i].bottom >= r[j].top && r[i].top <= r[j].bottom && r[i].left + r[i].xa <= r[j].right){
r[i].xa *= -1;
r[j].xa *= -1;
}
//this is also just as confusing just read through it carefully
if(r[i].bottom + r[i].ya >= r[j].top && r[i].right >=r[j].left && r[i].left <= r[j].right && r[i].top + r[i].ya <= r[j].bottom){
r[i].ya *= -1;
r[j].ya *= -1;
}
}
}
}
function Box(x, y, wid, hei){
this.x = x;//input for square shape
this.y = y;//ditto
this.width = wid;//ditto
this.height= hei;//ditto
this.xa = random(2,5);//xa is the x acceleration
this.ya = random(2,5);//ya is the y acceleration
this.left;
this.right;
this.top;
this.bottom;
this.show = function(){
this.left = this.x; //i define left,right,top,bottom in show function so they get updated
this.right = this.x +this.width;
this.top = this.y;
this.bottom = this.y +this.height;
push();
fill(255);
noStroke();
rect(this.x,this.y,this.width,this.height);
pop();//push pop just in case i want to change square colors individually in the future
this.x += this.xa;//adding acceleration to the squares
this.y += this.ya;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if(this.x > width-this.width||this.x <0){//bouncing off the right and left wall
this.xa *= -1;
if(this.x > width/2){// making sure if the square spawns or glitches on the other side of the wall it doesn't get stuck, this checks which side the square is on when it touches the wall then moves it directly on the wall
this.x = width-this.width;
}else{
this.x = 0;
}
}
if(this.y > height-this.height||this.y <0){// same as above but for the y axis
this.ya *= -1;
if(this.y > height/2){
this.y = height-this.height;
}else{
this.y = 0;
}
}
}
}
function windowResized(){
createCanvas(windowWidth,windowHeight- 4);//window resizing adjustment
}
you can view it using this.
just copy and paste.
The solution to the unsolvable
Sorry no such thing
Collision solutions are not easy when you have many moving objects in the scene.
Your immediate problem
Your problem if mainly because you are making an assumption on the box's direction of travel when they collide. You multiply the direction by -1 to reverse direction.
All good for 2 objects, but add a 3rd and you will end up with the 3 coming together. Each in turn you change the direction, box1 hits box2 both move away from each other, then in the same frame box1 hits box3 and now box1 and box3 are moving apart.Your speeds are constant so after a three way collision there will always be 2 boxes traveling in the same direction but overlapping.
The overlapping boxes on the next frame detect the overlap and both reverse direction, as they are already traveling in the same direction the direction switch does not help them move apart.
A step forward
Well a step apart, The following modification to the code just ensures that when possible a collision results in the box move away from each other.
function draw() {
background(40);
for (var i = 0; i < num; i++) {
const bx1 = r[i];
r[i].show();
for (var j = 0; j < num; j++) {
if (j !== i) {
// t for top, b for bottom, r for right and l for left. 1 for first box 2 for second
// bx for box
const bx2 = r[j];
const t1 = bx1.top + bx1.ya;
const b1 = bx1.bottom + bx1.ya;
const l1 = bx1.left + bx1.xa;
const r1 = bx1.right + bx1.xa;
const t2 = bx2.top + bx2.ya;
const b2 = bx2.bottom + bx2.ya;
const l2 = bx2.left + bx2.xa;
const r2 = bx2.right + bx2.xa;
// the or's mean that the condition will complete at the first passed clause
// If not (not over lapping) AKA is overlapping
if (!(t1 > b2 || b1 < t2 || l1 > r2 || r1 < l2)) {
if (r1 >= l2) {
bx1.xa = -Math.abs(bx1.xa);
bx2.xa = Math.abs(bx2.xa);
}
if (l1 <= r2) {
bx1.xa = Math.abs(bx1.xa);
bx2.xa = -Math.abs(bx2.xa);
}
if (b1 >= t2) {
bx1.ya = -Math.abs(bx1.ya);
bx2.ya = Math.abs(bx2.ya);
}
if (t1 <= b2) {
bx1.ya = Math.abs(bx1.ya);
bx2.ya = -Math.abs(bx2.ya);
}
}
}
}
}
}
But that only moves the problem away from overlapping, now there are many collision that are wrong as there is no test to determine the point of collision
In the above code you are trying to solve from an unsolvable position. Boxes in real life never overlap. Boxes in real life will slow down and speed up. perfectly flat sides will never collide with more than on side at a time.
To do this you will need to use integration. Its not that hard and is just a process of dividing time into smaller steps. Collide, move, check for overlap, move apart then back to collide.
Verlet integration
Also verlet integration will make it easier. Rather than store a boxes speed as a vector you store the current position and the previous position.
box.x = 10;
box.y = 10;
box.ox = 8; // the boxes old position
box.oy = 8;
You move a box as follows
sx = box.x - box.ox;
sy = box.y - box.oy;
box.ox = box.x;
box.oy = box.y;
box.x += sx; // the boxes old position
box.y += sy;
When you hit something you need to change the old position so as to give the next iteration the correct direction
if(box.y > ground){
box.y = ground - (box.y - ground); // move away from ground same dist as moved into ground
box.oy = box.y -sy;
}
Do them all in groups.
Move all at once, then test for collision at once. Dont move and test one at a time.
Verlet integration is much more forgiving as it lets speed of movement absorb some of the error. Rather than be all in position as the standard vector method does.

Canvas - bullets to mouse point

So I'm trying to implement shooting, and what I want to do is take the players x and y and use that as the base point where the projectile derives from and then it basically goes to the point pressed in the canvas. The projectile is deriving from the player, but instead of going to the cursor point it strangely ALWAYS goes right, but will go right+up or right+down depending on which direction was pressed; I've looked on-line and can't seem to find the answer.
Inside my javascript here is the shoot function:
function shoot(event){
bullets[bulletCount] = new Array(4);
bullets[bulletCount][0] = x;
bullets[bulletCount][1] = y;
bullets[bulletCount][2] = window.event.clientX;
bullets[bulletCount][3] = window.event.clientY;
bulletCount++;
}
In my javascript here is the bullet part in the update method:
for(var b = 0; b < bullets.length; b++){
if(bullets[b][0] < bullets[b][2]) bullets[b][0] += 5;
if(bullets[b][0] > bullets[b][2]) bullets[b][0] -= 5;
if(bullets[b][1] < bullets[b][3]) bullets[b][1] += 5;
if(bullets[b][1] > bullets[b][3]) bullets[b][1] -= 5;
ctx.fillRect(bullets[b][0],bullets[b][1], 8, 8);
}
and in my index.html page:
<canvas id="gameBoard" onClick="shoot(event)" width="500" height="500" tabindex="1"></canvas>
EDIT: fixed the problem, for anyone else who suffers this problem inside the shoot function change from what was originally up there to this:
function shoot(event){
var rect = canvas.getBoundingClientRect();
bullets[bulletCount] = new Array(4);
bullets[bulletCount][0] = x;
bullets[bulletCount][1] = y;
bullets[bulletCount][2] = event.clientX - rect.left;
bullets[bulletCount][3] = event.clientY - rect.top;
bulletCount++;
}
The problem lies within these two lines:
bullets[bulletCount][2] = window.event.clientX;
bullets[bulletCount][3] = window.event.clientY;
It is because that the location you save for the click is not the real location.
You see, event.clientX/Y give you the mouse coordinates relative to the top left corner of the window, but you only want the coordinates relative to the top left corner of your canvas element.
To fix this, first get to know another way to get the mouse coordinates, which is event.pageX/Y.
This will not give you the coordinates relative to the canvas, however you need this instead of event.clientX/Y because it will give you the mouse coordinates relative to the top left corner of the page, not the window, which means it doesn't matter if the user scrolls somewhere, the coordinates are always true to the page.
So, now that you're using event.pageX/Y, how to make it relative to the canvas? Well, we can just take these coordinates and subtract the top left corner coordinates of the canvas:
bullets[bulletCount][2] = window.event.pageX - canvas.offsetLeft;
bullets[bulletCount][3] = window.event.pageY - canvas.offsetTop;
Assuming that your canvas element is saved in a variable named canvas
Hope that solves it :D
var bullets = [];
var bullet_speed = 10;
call this in your init() fucntion: which could have your setInterval.
window.addEventListener('click', shoot, false);
call this in your draw function:
for (var i = 0; i < bullets.length; i++){
bullets[i].x += bullets[i].xChange;
bullets[i].y += bullets[i].yChange;
context.fillStyle ='black';
context.fillRect(bullets[i].x,bullets[i].y,4,4)
}
function shoot(event){
x = event.offsetX
y = event.offsetY
d = Math.sqrt(Math.pow(Math.abs(player.x-x),2)+Math.pow(Math.abs(player.y-y),2))
bullet = {
x : player.x,
y : player.y,
xChange : (x-player.x)/(d/bullet_speed),
yChange : (y-player.y)/(d/bullet_speed),
};
bullets.push(bullet);
}

html5 canvas elastic collision squares

I am re-asking this question since I did not make myself clear in what I wanted in my last question.
Does anyone know how to do elastic collision or handle collision in Canvas using rectangles? Or can point me in the right direction?
I created a canvas that has multiple square and would like each square to deflect when they touch.
Here is a quick fiddle that I put together showing to black buffer canvases http://jsfiddle.net/claireC/Y7MFq/10/
line 39 is where I started the collision detection and line 59 is where I tried to execute it. I will have more than 3 squares moving around and want them to deflect if/when they touch each other
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d");
context.fillStyle = "#FFA500";
context.fillRect(0, 0, canvas.width, canvas.height);
var renderToCanvas = function (width, height, renderFunction) {
var buffer = document.createElement('canvas');
buffer.width = width;
buffer.height = height;
renderFunction(buffer.getContext('2d'));
return buffer;
};
var drawing = renderToCanvas(100, 100, function (ctx) {
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
var drawing2 = renderToCanvas(100, 100, function (ctx) {
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
var x = 0,
y = 0,
x2 = 200,
y2 = 10,
vx = .80,
vy = .80,
vx2 = .80,
vy2 = .80;
function collides(rectA, rectB) {
return !(rectA.x + rectA.width < rectB.x2 ||
rectB.x2 + rectB.width < rectA.x ||
rectA.y + rectA.height < rectB.y2 ||
rectB.y2 + rectB.height < rectA.y);
};
function executeFrame() {
x+=vx;
y+=vy;
x2+=vx2;
y2+=vy2;
if( x < 0 || x > 579) vx = -vx;
if( y < 0 || y > 265) vy = -vy;
if( x2 < 0 || x2 > 579) vx2 = - vx2;
if( y2 < 0 || y2 > 233) vy2 = - vy2;
if(collides(drawing, drawing2)){
//move in different direction
};
context.fillStyle = "#FFA500";
context.fillRect(0, 0, canvas.width, canvas.height);
context.drawImage(drawing, x, y);
context.drawImage(drawing2, x2, y2);
requestAnimationFrame(executeFrame);
}
//start animation
executeFrame();
Rectangular collision detection
To do a rectangular collision detection can be more complicated than it perhaps looks.
It's not just about figuring out if the two rectangles intersects or overlaps, but we also need to know at what angle they collide and what direction they move in order to deflect them properly, ideally transfer "velocity" to each other (mass/energy) and so forth.
This method that I present here will do the following steps:
First do a simple intersect detection to find out if they collide at all.
If an intersection: calculate the angle between the two rectangle
Divide a set primary rectangle into four zones of a circle where zone 1 is right, zone 2 is bottom and so forth.
Depending on zone, check in what direction the rectangle is moving, if towards the other rectangle deflect it based on which zone was detected.
➔ Online demo
➔ Version with higher speed here
Detect intersection and calculate angle
The code for detecting the intersection and angle is as follows, where r1 and r2 are here objects with properties x, y, w and h.
function collides(r1, r2) {
/// classic intersection test
var hit = !(r1.x + r1.w < r2.x ||
r2.x + r2.w < r1.x ||
r1.y + r1.h < r2.y ||
r2.y + r2.h < r1.y);
/// if intersects, get angle between the two rects to determine hit zone
if (hit) {
/// calc angle
var dx = r2.x - r1.x;
var dy = r2.y - r1.y;
/// for simplicity convert radians to degree
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
if (angle < 0) angle += 360;
return angle;
} else
return null;
}
This function will return an angle or null which we then use to determine deflection in our loop (that is: the angle is used to determine the hit zone in our case). This is needed so that they bounce off in the correct direction.
Why hit zones?
With just a simple intersection test and deflection you can risk the boxes deflecting like the image on the right, which is not correct for a 2D scenario. You want the boxes to continue in the same direction of where there is no impact as in the left.
Determine collision zone and directions
Here is how we can determine which velocity vector to reverse (tip: if you want a more physical correct deflection you can let the rectangles "absorb" some of the other's velocity but I won't cover that here):
var angle = collides({x: x, y: y, w: 100, h: 100}, /// rect 1
{x: x2, y: y2, w: 100, h: 100}); /// rect 2
/// did we have an intersection?
if (angle !== null) {
/// if we're not already in a hit situation, create one
if (!hit) {
hit = true;
/// zone 1 - right
if ((angle >= 0 && angle < 45) || (angle > 315 && angle < 360)) {
/// if moving in + direction deflect rect 1 in x direction etc.
if (vx > 0) vx = -vx;
if (vx2 < 0) vx2 = -vx2;
} else if (angle >= 45 && angle < 135) { /// zone 2 - bottom
if (vy > 0) vy = -vy;
if (vy2 < 0) vy2 = -vy2;
} else if (angle >= 135 && angle < 225) { /// zone 3 - left
if (vx < 0) vx = -vx;
if (vx2 > 0) vx2 = -vx2;
} else { /// zone 4 - top
if (vy < 0) vy = -vy;
if (vy2 > 0) vy2 = -vy2;
}
}
} else
hit = false; /// reset hit when this hit is done (angle = null)
And that's pretty much it.
The hit flag is used so that when we get a hit we are marking the "situation" as a hit situation so we don't get internal deflections (which can happen at high speeds for example). As long as we get an angle after hit is set to true we are still in the same hit situation (in theory anyways). When we receive null we reset and are ready for a new hit situation.
Also worth to mention is that the primary rectangle here (whose side we check against) is the first one (the black in this case).
More than two rectangles
If you want to throw in more that two rectangle then I would suggest a different approach than used here when it comes to the rectangles themselves. I would recommend creating a rectangle object which is self-contained in regards to its position, size, color and also embeds methods to update velocity, direction and paint. The rectangle objects could be maintained by a host objects which performs the clearing and calls the objects' update method for example.
To detect collisions you could then iterate the array with these objects to find out which rectangle collided with the current being tested. It's important here that you "mark" (using a flag) a rectangle that has been tested as there will always be at least two in a collision and if you test A and then B you will end up reversing the effect of velocity change without using a flag to skip testing of the collision "partner" object per frame.
In conclusion
Note: there are special cases not covered here such as collision on exact corners, or where a rectangle is trapped between an edge and the other rectangle (you can use the hit flag mentioned above for the edge tests as well).
I have not optimized any of the code but tried to keep it as simple as I can to make it more understandable.
Hope this helps!
The answer is actually quite simple: swap the velocities of each block when they collide. That's it! Also for your collision test change RectA.x to just x, since they are normal variables given:
function collides(rectA, rectB) {
return !(x + rectA.width < x2 ||
x2 + rectB.width < x ||
y + rectA.height < y2 ||
y2 + rectB.height < y);
};
And swapping velocities:
if(collides(drawing, drawing2)){
var t = vx; var t2 = vy;
vx = vx2; vy = vy2;
vx2 = t; vy2 = t2;
};
And after those small changes we have working elastic collisions: http://jsfiddle.net/Y7MFq/11/

Categories

Resources