On my canvas I have two rectangles drawn. The first with a larger height and second with a smaller height.
Here is a screen shot:
In my code I represent them with classes and then instantiate them :
Here is how I do it:
class Rectangle {
constructor(x, y, width, height, color, value) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.color = color;
this.value = value;
}
// draw function of this rectance will let it appear on the screen;
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height , this.color, this.value);
}
// the update function will swap the rectangle's property and redraw them again
update(obj1, obj2) {
var temp;
// saving the values of the first rectancgle in the temp variables
for(var key in obj1) {
this.temp = this.obj1[key];
this.obj1[key] = this.obj2[key];
this.obj2[key] = this.temp;
}
this.obj1.draw();
this.obj2.draw();
}
}
var rect2 = new Rectangle(100, y-20, 50, 25, "pink", 40 );
rect2.draw();
var rect1 = new Rectangle(160, y, 50, 5, "black", 20);
rect1.draw();
rect1.update(rect1, rect2);
What I want to do is now make the pink rectangle appear in place of black and black in place of pink. Can anyone tell me how to do that?
class Rectangle {
constructor(x, y, width, height, color, value) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.color = color;
this.value = value;
}
// draw function of this rectance will let it appear on the screen;
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height , this.color, this.value);
}
reposition(x,y) {
this.x = x;
this.y = y;
}
}
var rect2 = new Rectangle(100, y-20, 50, 25, "pink", 40 );
rect2.draw();
var rect1 = new Rectangle(160, y, 50, 5, "black", 20);
rect1.draw();
// do this – after some wait, click or however you like to trigger it
let buffer_x = rect1.x, buffer_y = rect1.y;
rect1.reposition(rect2.x,rect2.y);
rect2.reposition(buffer_x,buffer_y);
rect1.draw();
rect2.draw();
You can try swap location of obj1 and obj2!!
ex:
var x1 = this.obj1.x, y1 = this.obj1.y;
this.obj1.x = this.obj2.x;
this.obj1.y = this.obj2.y;
this.obj2.x = x1;
this.obj2.y = y1;
after this, call update
Related
I am good with my jumping system in my canvas, but it looks like I need some transition so it just not bounce from top and bounce back to bottom. Transition will help with the gravity effect while jumping.
Heres my code:
function Game() {
this.start = function() {
generateObstacles();
for (var i = 0; i < Obstacles.length; i++) {
Paint.draw(Obstacles[i].x, Obstacles[i].y, Obstacles[i].width, Obstacles[i].height, Obstacles[i].color);
}
this.gravity();
}
this.stop = function() {
}
this.gravity = function() {
let gravity = 0.098;
let gravitySpeed = 0;
function gravityEffect() {
gravitySpeed += gravity;
Paint.erase(myPiece.x, myPiece.y, myPiece.width, myPiece.height);
myPiece.y += gravitySpeed;
Paint.draw(myPiece.x, myPiece.y, myPiece.width, myPiece.height, myPiece.color);
window.requestAnimationFrame(gravityEffect);
}
window.requestAnimationFrame(gravityEffect);
}
this.start();
}
function Paint() {
this.draw = function(x, y, width, height, color) {
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}
this.erase = function(x, y, width, height) {
ctx.beginPath();
ctx.clearRect(x, y, width, height);
ctx.closePath();
}
}
function generateObstacles() {
let x = myGame.width;
let y = myGame.height;
let maxWidth = 400;
let minWidth = 100;
let randomWidth = Random(maxWidth, minWidth);
let maxHeight = 20;
let minHeight = 5;
let randomHeight = Random(maxHeight, minHeight);
Obstacles.push(new Obstacle(x - randomWidth, y - randomHeight, randomWidth, randomHeight, true, 'green'));
}
function Random(max, min) {
return Math.floor(Math.random() * (max - min) + 1 + min);
}
function Piece(x, y, width, height, behavior, color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.behavior = behavior;
this.color = color;
Paint.draw(this.x, this.y, this.width, this.height, this.color);
}
function Obstacle(x, y, width, height, collidable, color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.collidable = collidable;
this.color = color;
}
The erase function is not doing well when I am adding y in myPiece and its decimal. For example if its 0.098, the erase will not be accurate idk why, Its only accurate when I am adding integer on y.
I want to draw quite a few dots. That's what I do:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
function render () {
window.requestAnimationFrame(render);
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
for (let p of particles) {
p.rmove();
p.render(ctx);
}
}
render();
The drawing function for my point looks like this:
class Point {
x: number;
y: number;
constructor(x, y) {
this.x = x;
this.y = y;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
render (ctx) {
ctx.fillStyle = "gray";
ctx.beginPath();
ctx.rect(this.x, this.y, 1.5,1.5);
ctx.fill();
ctx.stroke();
}
}
Note that I round the values in the rmove() function, as canvas draws points with integer coordinates more quickly.
I'd like to somehow put all these drawing calls together.
Make your points trace on the given context (could even be a Path2D), and keep the actual drawing for the renderer.
All your points have to do is to make the context moveTo their own coords before tracing the rect.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2 )
);
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
ctx.beginPath();
for (let p of particles) {
p.trace(ctx);
}
ctx.fillStyle = "gray";
ctx.stroke(); // OP has it reversed, but then the fill-color is almost not visible
// (1.5 width - 2*0.5 stroke leaves only 0.5 for the fill => antialiased...
ctx.fill();
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
But this works only because all your particles share the same color. If they didn't, then you'd need a bit more logic:
const colors = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow'];
class Point {
constructor(x, y, color=0) {
this.x = x;
this.y = y;
this.color = color;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2, (Math.random()*colors.length-1)|0 )
);
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
let last_color = -1;
for (let p of particles) {
let p_color = p.color;
if( p_color !== last_color ) {
paint();
last_color = p_color;
}
p.trace(ctx);
}
paint(); // the last
function paint() {
ctx.fillStyle = colors[ last_color ];
ctx.strokeStyle = colors[ (last_color + 1) % colors .length ];
ctx.stroke();
ctx.fill();
ctx.beginPath();
}
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
Though doing this, you may very well end up with a lot of drawings, so a final trick which might not work everywhere is to sort your particles by their color. This results in a different graphic since this one color will always be at the top, but it might work in some cases and the performance gain can outfit the downside.
const colors = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow'];
class Point {
constructor(x, y, color=0) {
this.x = x;
this.y = y;
this.color = color;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2, (Math.random()*colors.length-1)|0 )
);
particles.sort( (a, b) => a.color - b.color );
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
let last_color = -1;
for (let p of particles) {
let p_color = p.color;
if( p_color !== last_color ) {
paint();
last_color = p_color;
}
p.trace(ctx);
}
paint(); // the last
function paint() {
ctx.fillStyle = colors[ last_color ];
ctx.strokeStyle = colors[ (last_color + 1) % colors .length ];
ctx.stroke();
ctx.fill();
ctx.beginPath();
}
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
And nothing prevents you to generate chunks from these sorted particles so it looks more random.
I'm making an eCard with falling confetti and fireworks flying up from the bottom of the screen. The logic for both are almost identical:
I make an empty array for fireworks and confetti, and then fill them with objects, using my GetRandom(mix,max) function to create each one with a random value:
//fill confetti object array
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray.push(new Confetti(GetRandom(0,canvas.width), GetRandom(-200,-10), GetRandom(10,30), GetRandom(10,30), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(0,2*Math.PI),GetRandom(50,80)));
}
//fill firework object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray.push(new Firework(GetRandom(0,canvas.width), canvas.height, GetRandom(4,20), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(30,100), GetRandom(-10,10), GetRandom(50,200)));
}
Then they are drawn and updated in their specific ways, each one starting by setting context.fillStyle and .strokeStyle as the current object's color value:
//confetti.draw
Draw: function(x, y, width, height, color, rotationAngle) {
context.translate(x,y)
context.rotate(rotationAngle)
context.strokeStyle = color;
context.fillStyle = color;
context.beginPath();
context.rect(0, 0, width, height);
context.fill();
context.closePath();
context.resetTransform();
},
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color;
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
Then they are each updated:
//confetti.update
Update: function(modifier) {
this.y = this.y + (this.fallSpeed * modifier);
if (this.y > canvas.height) {this.x = GetRandom(0,canvas.width);this.y = GetRandom(-100,0);}
},
//firework.update
Update: function(modifier) {
this.x = this.x - this.swayX;
this.y = this.y - this.speedY;
if (this.y < -10) {this.x = GetRandom(0,canvas.width);this.y = canvas.height;this.speedY = GetRandom(30,100);this.swayX = GetRandom(-10,10)}
},
I have scoured the code over and over and I just can't seem to get a reason as to why the confetti all has random sizes, angles, fallrates, and colors, AND the fireworks all have random swayX and speedY values but all the same colors. The full code is below if anyone wants to run it in full:
//james gossling multimedia for web design spring 2018
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
var GetRandom = function(min, max) {
//set mins and maxes for ball speed to change angle slightly after ball reset
min = min;
max = max;
return Math.floor(Math.random() * (max - min + 1) + min);
};
//game classes go here
var Background = function(context,color) {
this.context = context;
this.color = color;
};
Background.prototype = {
DrawBackground: function() {
//for testing
//console.log('here')
context.strokeStyle = this.color;
context.fillStyle = this.color;
context.beginPath();
context.rect(0,0,canvas.width,canvas.height);
context.stroke(); // invoke stroke
context.fill(); // invoke fill
context.closePath();
},
};
Confetti = function(x, y, width, height, color, rotationAngle, fallSpeed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.rotationAngle = rotationAngle;
this.fallSpeed = fallSpeed;
};
Confetti.prototype = {
Draw: function(x, y, width, height, color, rotationAngle) {
context.translate(x,y)
context.rotate(rotationAngle)
context.strokeStyle = color;
context.fillStyle = color;
context.beginPath();
context.rect(0, 0, width, height);
context.fill();
context.closePath();
context.resetTransform();
},
GetX: function() {
return this.x;
},
GetY: function() {
return this.y;
},
GetWidth: function() {
return this.width;
},
GetHeight: function() {
return this.height;
},
GetColor: function() {
return this.color;
},
GetRotationAngle: function() {
return this.rotationAngle;
},
GetFallSpeed: function() {
return this.fallSpeed;
},
Update: function(modifier) {
this.y = this.y + (this.fallSpeed * modifier);
if (this.y > canvas.height) {this.x = GetRandom(0,canvas.width);this.y = GetRandom(-100,0);}
},
};
var DrawConfetti = function() {
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray[i].Draw(ConfettiArray[i].GetX(),ConfettiArray[i].GetY(),ConfettiArray[i].GetWidth(),ConfettiArray[i].GetHeight(),ConfettiArray[i].GetColor(),ConfettiArray[i].GetRotationAngle());
}
}
var UpdateConfetti = function(modifier) {
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray[i].Update(modifier);
}
};
Firework = function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
this.x = x;
this.y = y;
this.lineWidth = lineWidth;
this.color = color;
this.speedY = speedY;
this.swayX = swayX;
//this.rotationAngle = rotationAngle;
this.blastRadius = blastRadius;
};
Firework.prototype = {
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color;
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
GetX: function() {
return this.x;
},
GetY: function() {
return this.y;
},
GetLineWidth: function() {
return this.lineWidth;
},
GetColor: function() {
return this.color;
},
GetSpeedY: function() {
return this.speedY;
},
GetSwayX: function() {
return this.swayX;
},
GetRotationAngle: function() {
return this.rotationAngle;
},
GetBlastRadius: function() {
return this.blastRadius;
},
Update: function(modifier) {
this.x = this.x - this.swayX;
this.y = this.y - this.speedY;
if (this.y < -10) {this.x = GetRandom(0,canvas.width);this.y = canvas.height;this.speedY = GetRandom(30,100);this.swayX = GetRandom(-10,10)}
},
};
var DrawFireworks = function() {
//create confetti object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray[i].Draw(FireworkArray[i].GetX(), FireworkArray[i].GetY(), FireworkArray[i].GetLineWidth(), FireworkArray[i].GetColor(), FireworkArray[i].GetSpeedY(), FireworkArray[i].GetSwayX(), FireworkArray[i].GetBlastRadius());
}
};
var UpdateFireworks = function(modifier) {
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray[i].Update(modifier);
}
};
UncleSam = function() {
};
UncleSam.prototype = {
};
Text = function(context,title,x,y,color) {
this.context = context;
this.title = title;
this.x = x;
this.y = y;
this.color = color;
this.lineWidth = 2;
this.lineHeight =(this.context.measureText('W').width) + Math.pow((this.context.measureText('W').width),2);
this.font = '70pt Times New Roman';
//GET METRICS
this.metrics = this.context.measureText(this.title);
this.width = this.metrics.width;
this.maxWidth = canvas.width;
this.GradChangeSpeed = .5;
this.GradChangeOffset = .3;
this.debugCounter = 0;
};
Text.prototype = {
SetAttributes: function() {
context.font
context.textAlign = 'center'
context.font = this.font;
context.lineWidth = this.lineWidth;
context.lineHeight = this.GetHeight;
context.fillStyle = TextGradient;
context.strokeStyle = this.color;
//shadow attributes
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
},
//GETTTERS SETTERS///////////////////
GetTextX: function() {
return this.x;
},
GetTextY: function() {
return this.y;
},
GetTextLineHeight: function() {
return this.lineHeight;
},
GetTextWidth: function() {
return this.width;
},
//GETTERS SETTERS////////////
SetColorGradient: function() {
TextGradient.addColorStop(0,"red");
TextGradient.addColorStop(this.GradChangeOffset,"white");
TextGradient.addColorStop(.8,"blue");
},
Update: function(modifier) {
this.GradChangeOffset = this.GradChangeOffset + (this.GradChangeSpeed * modifier);
//GRADIENT DEBUGGERS
context.strokeText(this.GradChangeOffset.toFixed(2),canvas.width/2,canvas.height/2);
//GRADIENT DEBUGGERS
if (this.GradChangeOffset > .7 || this.GradChangeOffset < .2) {this.GradChangeSpeed = -(this.GradChangeSpeed);}
},
DrawText: function() {
this.WrapText(this.context, this.title, this.x, this.y, this.maxWidth, this.lineHeight);
},
WrapText: function(context, title, x, y, maxWidth, lineHeight) {
var words = title.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
context.strokeText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
context.strokeText(line, x, y);
},
};
//other functions
var ClearScreen = function() {
context.clearRect(0, 0, canvas.width, canvas.height);
};
var DrawObjects = function() {
ClearScreen();
Background1.DrawBackground();
Text1.SetAttributes();
Text1.SetColorGradient();
Text1.DrawText();
DrawFireworks();
DrawConfetti();
};
var UpdateObjects = function(modifier) {
//Text1.Update(modifier);
UpdateFireworks(modifier);
UpdateConfetti(modifier);
};
var Reset = function() {
};
//MAIN GAME LOOP FXN///////////////////
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
var frameRateAdjust = delta/1000;
DrawObjects(frameRateAdjust);
UpdateObjects(frameRateAdjust);
then = now;
//possibly do RESET
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
//START ECARD
//create variables
var then = Date.now();
var colorChoices = ["red","white","blue","deeppink","orange","limegreen","darkred"];
var NUM_CONFETTI = 25;
var NUM_FIREWORKS = 10;
var NUM_COLORS = colorChoices.length;
//create arrays for objects
var ConfettiArray = [];
var FireworkArray = [];
//create objects
Background1 = new Background(context,'black');
var Text1 = new Text(context,'Happy 4th of July!',canvas.width/2,canvas.height/10,'red');
var TextGradient = context.createLinearGradient(Text1.GetTextX(),Text1.GetTextY(),Text1.GetTextX()+Text1.GetTextWidth(),Text1.GetTextY()+Text1.GetTextLineHeight()/2)
//fill confetti object array
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray.push(new Confetti(GetRandom(0,canvas.width), GetRandom(-200,-10), GetRandom(10,30), GetRandom(10,30), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(0,2*Math.PI),GetRandom(50,80)));
}
//fill firework object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray.push(new Firework(GetRandom(0,canvas.width), canvas.height, GetRandom(4,20), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(30,100), GetRandom(-10,10), GetRandom(50,200)));
}
//start eCard animations
Reset();
main();
Begin a new path with ctx.beginPath()
The reason is because you are creating one path out of all the firework lines.
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color; // sets the stroke color
context.moveTo(x,y); // adds another line
context.lineTo(x-swayX,y-speedY);
context.stroke(); // stroke all lines up to this point
},
Each time stroke is called all the firework lines are render up to that point.
The result is that the last stroke call draws all the lines again the color of the last firework.
The fix
The fix is simple. Just start a new path with ctx.beginPath()
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color; // sets the stroke color
//========================================================
context.beginPath(); // start a new path
//========================================================
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
function startGame() {
myGamePiece = new component(30, 30, "red", 10, 120);
myGameArea.start();
myWall = new defense(30, 150, "black", 90, 120)
myGameArea.start();
myWall2 = new defense(30, 150, "black", 180, 0)
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 338;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas,
document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width,
this.canvas.height);
}
}
function defense(width, height, color, x, y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function(){
this.x;
this.y;
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
There's my snippet of code please help me with my collision between the wall and square. I also have buttons to move the square if you need to know.
Here's some more code for your convenience just please get me a answer thanks in advance.
I know its a lot of code but its also not all of it so ifyou need anything else just ask thanks.
Adding addendum: This code will only check for square entity collisions, ie a tile based 2d style of game. This will not work in a 3d based graphic set, or do any sort of fine collision detection (against non square entities).
Without seeing more of your code, such as how you're rendering or managing state of the entities, you just need a function call during your update() method, wherever that may be.
The method I used in a hobby project several years ago, the collision logic looked like this (a function that would return just a boolean). This is just a jist I can give unless I see more of your code.
function isColliding(entity1, entity2) {
var e1top = entity1.y;
var e1bot = entity1.y + entity1.height;
var e1left = entity1.x;
var e1right = entity1.x + entity1.width;
var e2top = entity2.y;
var e2bot = entity2.y + entity2.height;
var e2left = entity2.x;
var e2right = entity2.x + entity2.width;
var collision = true;
if ((e1top > e2bot) || (e1bot < e2top) || (e1left > e2right) || (e1right < e2left))
collision = false;
return collision;
}
So I'm trying to make a pong game in JavaScript. I've tried lots of stuff, but whatever I do won't get the ball to move.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() { Game.update(); Game.draw(); };
Game.fps = 50;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
I can't get the ball to move. Any Ideas? Also, what the neater way of classes? Is there a different way to do it than with functions?
Maybe like
class Apple {
function draw() {
//draw here
}
}
You are always drawing the ball in the same place, dead-center:
ctx.rect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
You're updating this.x and this.y elsewhere, but not using them. Try:
ctx.rect(this.x, this.y, 20, 20);
Now you have the problem of knowing when to stop moving, but that's a separate question.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() { Game.update(); Game.draw(); };
Game.fps = 50;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
<canvas id="myCanvas" height="300px" width="300px" />
I got your ball moving. you had just forgot to set the position to this.x and this.y in the draw function.
you'll notice it leaves a streak. So you'll need to either (1) clear everything and redraw everything on each frame, or (2), keep an oldx and oldy and draw white over oldx oldy before drawing black at x and y. Happy coding.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() {console.log("hi"); Game.update(); Game.draw(); };
Game.fps = 5;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
#myCanvas{width:200px;height:200px}
<canvas id="myCanvas"></canvas>
Here's a good html canvas game instructions that follows the style you're doing pretty well:
http://www.html5rocks.com/en/tutorials/canvas/notearsgame/