How to create an advanced 2d object collision? JavaScript Canvas - javascript

How do you create a rectangle-to-rectangle collision system that stops the player from moving in that direction? e.g. making the player not able to move up if an object is in the way. I know how to make the player not able to go off the edge, but I don't know how to make a collision for a solid object. e.g. A box or cube that you can't go through and stops player movement on that side of the cube.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cWidth = 400;
var cHeight = 250;
var keyboardKeys = [];
var friction = 0.8;
var solidObjs = [];
class Player {
constructor(x, y, width, height, color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.velX = 0;
this.velY = 0;
this.speed = 5;
}
}
function createObj(x, y, width, height, color) {
solidObjs.push({
x: x,
y: y,
width: width,
height: height,
color: color
});
}
var player1 = new Player(cWidth / 2, cHeight / 2, 25, 25, "#0080ff");
canvas.width = cWidth;
canvas.height = cHeight;
createObj(0, 0, 10, cHeight, "#808080");
createObj(cWidth - 10, 0, 10, cHeight, "#808080");
createObj(0, 0, cWidth, 10, "#808080");
createObj(0, cHeight - 10, cWidth, 10, "#808080");
createObj(50, 50, 100, 100, "#808080");
function drawFrame() {
ctx.clearRect(0, 0, cWidth, cHeight);
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, cWidth, cHeight);
if (keyboardKeys["w"] || keyboardKeys["ArrowUp"]) {
if (player1.velY > player1.speed * -1) {
player1.velY--;
}
}
if (keyboardKeys["s"] || keyboardKeys["ArrowDown"]) {
if (player1.velY < player1.speed) {
player1.velY++;
}
}
if (keyboardKeys["a"] || keyboardKeys["ArrowLeft"]) {
if (player1.velX > player1.speed * -1) {
player1.velX--;
}
}
if (keyboardKeys["d"] || keyboardKeys["ArrowRight"]) {
if (player1.velX < player1.speed) {
player1.velX++;
}
}
player1.velX *= friction;
player1.velY *= friction;
player1.x += player1.velX;
player1.y += player1.velY;
ctx.fillStyle = player1.color;
ctx.fillRect(player1.x, player1.y, player1.width, player1.height);
for (i = 0; i < solidObjs.length; i++) {
ctx.fillStyle = solidObjs[i].color;
ctx.fillRect(solidObjs[i].x, solidObjs[i].y, solidObjs[i].width, solidObjs[i].height);
advancedCollisionCheck(player1, solidObjs[i]);
}
ctx.fillStyle = "white";
ctx.font = "16px arial";
ctx.fillText("Add collision to this box.", 50, 66);
}
function simpleCollisionCheck(obj1, obj2) {
if (obj1.x < obj2.x + obj2.width && obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height && obj1.y + obj1.height > obj2.y) {
return true;
}
}
function advancedCollisionCheck(obj1, obj2) {
//looking for an answer for this
}
setInterval(() => {
drawFrame();
}, 1000 / 60);
document.body.addEventListener("keydown", (e) => {
keyboardKeys[e.key] = true;
});
document.body.addEventListener("keyup", (e) => {
keyboardKeys[e.key] = false;
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
padding: 0px 0px;
margin: 0px 0px;
box-sizing: border-box;
}
</style>
<title>Document</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="pg2d.js"></script>
</body>
</html>
I've tried but it seems to disable the player from moving even if they aren't touching any objects.

Related

How would I get movement in a direction with 360 degree angles

Im making a pong game and I want to make the ball have a speedX and a speedY that is added to the ball that makes it move along the X and Y axis but im not sure how to adjust those variables based off of the balls angle. In function ballPhysics() I need to replace the 0's with something to get the speed it should go along that axis. But if anyone finds anything else that should be worked on itd be great if you let me know thanks.
let cvs, ctx;
let width = 600, height = 500;
let keysPressed = [];
class Wall {
constructor(x, y, w, h, speed) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.speed = speed;
}
}
class Ball {
constructor(x, y , w, h, speedX, speedY, angle) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.speedX = speedX;
this.speedY = speedY;
this.angle = angle;
}
}
let left = new Wall(25, 250, 10, 100, 10);
let right = new Wall(width-25, 250, 10, 100, 10)
let ball = new Ball(width/2, height/2, 5, 5, 0, 0, 0);
function ballPhysics() {
ball.x += ball.speedX;
ball.y += ball.speedY;
ball.speedX = 0//figure out direction;
ball.speedY = 0//figure out direction;
}
function start() {
ball.x = width/2;
ball.y = height/2;
if(Math.random() < 0.5) {
ball.angle = 90;
} else {
ball.angle = -90;
}
console.log(ball.angle);
}
function update() {
setInterval(function () {
ballPhysics();
for(let i = 0; i < keysPressed.length; i++) {
if(keysPressed[i] == 'KeyW' && left.y >= 0) {
left.y -= left.speed;
}
if(keysPressed[i] == 'KeyS' && left.y + left.h <= height) {
left.y += left.speed;
}
if(keysPressed[i] == 'ArrowUp' && right.y >= 0) {
right.y -= right.speed;
}
if(keysPressed[i] == 'ArrowDown' && right.y + right.h <= height) {
right.y += right.speed;
}
if(keysPressed[i] == 'Space') {
start();
}
}
}, 16)
}
function renderPlayers() {
ctx.fillStyle = '#FF0000';
ctx.fillRect(left.x, left.y, left.w, left.h);
ctx.fillRect(right.x, right.y, right.w, right.h);
}
function renderBall() {
ctx.fillStyle = '#0000FF';
ctx.fillRect(ball.x, ball.y, ball.w, ball.h);
}
function render() {
ctx.clearRect(0, 0, cvs.width, cvs.height);
renderBall();
renderPlayers();
requestAnimationFrame(render);
}
window.addEventListener("DOMContentLoaded", function () {
cvs = document.getElementById("cvs");
ctx = cvs.getContext("2d");
cvs.width = width;
cvs.height = height;
update();
render();
});
window.addEventListener('keydown', function(e) {
if(!keysPressed.includes(e.code)) {
keysPressed.push(e.code);
}
});
window.addEventListener('keyup', function(e) {
for(let i = 0; i < keysPressed.length; i++) {
if(keysPressed[i] == e.code) {
keysPressed.splice(i, 1);
}
}
});
#cvs {
border: solid 1px black;
background: #D1C3C3;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Platformer</title>
<link rel="stylesheet" href="/style.css" />
<script src="/script.js" defer></script>
</head>
<body>
<canvas width="0" height="0" id="cvs"></canvas>
</body>
</html>

JavaScript canvas game is dropping FPS after some time

Recently I've been trying to make JS canvas project and a few days ago I started coding it. I created enemies that generate random point on the canvas and move to it. I'm creating enemies by running createEnemy() function. It creates an object with enemy's data and stores it in "enemies" array. Everything works fine except of my FPS :( After some time they drop really hard. What's happening and why? Here's my code:
var c = document.getElementById("canv");
var context = c.getContext("2d");
var mouseX, mouseY;
const fpsTime = [];
var fps;
var enemies = []
var speed = 2
c.width = window.innerWidth;
c.height = window.innerHeight;
document.addEventListener("mousemove", e => { mouseX = e.pageX; mouseY = e.pageY;});
function getEnemies() {
return enemies;
}
function drawCharacter(x, y) {
context.clearRect(0, 0, c.width, c.height);
context.fillStyle = 'red';
context.fillRect(x, y,50,60);
context.save();
context.font = "30px Arial";
}
function getCurrentMouse() {
return {"x": mouseX, "y": mouseY}
}
function drawPoint(x, y) {
context.fillStyle = 'red';
context.fillRect(x, y,10,10);
context.save();
}
function createEnemy(name) {
var enemy = {
name: name,
didCompletePoint: true,
targetX: 0,
targetY: 0,
currentX: Math.floor(Math.random() * (+window.innerWidth + 1 - +0)) + +0,
currentY: Math.floor(Math.random() * (+window.innerHeight + 1 - +0)) + +0,
generatePoint: function() {
this.targetX = Math.floor(Math.random() * (+ window.innerWidth + 1 - +0)) + +0
this.targetY = Math.floor(Math.random() * (+ window.innerHeight + 1 - +0)) + +0
return [this.targetX, this.targetY];
},
draw: function() {
context.fillStyle = 'black';
context.fillRect(this.currentX, this.currentY,60,60);
context.save();
drawPoint(this.targetX, this.targetY)
context.font = "30px Arial";
}
};
enemies.push(enemy)
return enemy
}
var enemy = createEnemy("tak")
var enemy1 = createEnemy("tak")
var enemy2 = createEnemy("tak")
var enemy3 = createEnemy("tak")
var enemy5 = createEnemy("tak")
function drawFrame() {
document.getElementById("fps").innerHTML = "FPS: " + fps;
drawCharacter(getCurrentMouse().x, getCurrentMouse().y)
getEnemies().forEach((en, index) => {
if(en.didCompletePoint) {
en.didCompletePoint = false;
en.generatePoint()
}else {
if((en.targetX === en.currentX) && (en.targetY === en.currentY)) {
en.didCompletePoint = true;
}
else {
//vertical movement
if (en.targetY > en.currentY){
en.currentY++
}
else if (en.targetY < en.currentY) {
en.currentY--
}
//side movement
// going right
if (en.targetX > en.currentX) {
en.currentX++
}
// going left
else if (en.targetX < en.currentX) {
en.currentX--
}
}
}
en.draw()
})
}
function startLoop() {
window.requestAnimationFrame(() => {
const p = performance.now();
while (fpsTime.length > 0 && fpsTime[0] <= p - 1000) {
fpsTime.shift();
}
fpsTime.push(p);
fps = fpsTime.length;
drawFrame()
startLoop();
});
}
startLoop();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
</style>
</head>
<body>
<p id="fps" style="font-size: 30px; font-family: 'Calibri Light', serif; position: absolute; right: 2%; top: 0%;"></p>
<canvas id="canv" style="margin: 0;"></canvas>
</body>
<script src="script.js"></script>
</html>
First i need to say you are on good way. Using tradicional ecma is good to make fill
good/comform in canvas oriented scripts.
You make mistake in context.save() calling .
Constant calling save() without calling restore() make hard pain for program
and causes memory leaks.
canvas 2d context must be used on smart way.
Never use context without purpose.
Some setup's are more expensive like .font or shadows.
Usage for save restore
// we have some complex setup initial already
// but we need to change something
ctx.save()
ctx.fillStyle = "red";
ctx.fillText ('use it' , 1, 1, 111, 111)
ctx.restore()
// Now back me to the old setup
Almost to forgot one more bigger mistake:
i removed startLoop() i put it like last call in drawFrame function.
In that way we got fluid work.
Explanation:
You call drawFrame() and than in same time call startLoop func how calls Again drawFrame....
My english is bad but i am glad if i help...
drawFrame()
startLoop();
var c = document.getElementById("canv");
var context = c.getContext("2d");
var mouseX, mouseY;
const fpsTime = [];
var fps;
var enemies = []
var speed = 2
c.width = window.innerWidth;
c.height = window.innerHeight;
document.addEventListener("mousemove", e => { mouseX = e.pageX; mouseY = e.pageY;});
function getEnemies() {
return enemies;
}
function drawCharacter(x, y) {
context.clearRect(0, 0, c.width, c.height);
context.fillStyle = 'red';
context.fillRect(x, y,50,60);
// context.font = "30px Arial";
}
function getCurrentMouse() {
return {"x": mouseX, "y": mouseY}
}
function drawPoint(x, y) {
context.fillStyle = 'red';
context.fillRect(x, y,10,10);
}
function createEnemy(name) {
var enemy = {
name: name,
didCompletePoint: true,
targetX: 0,
targetY: 0,
currentX: Math.floor(Math.random() * (+window.innerWidth + 1 - +0)) + +0,
currentY: Math.floor(Math.random() * (+window.innerHeight + 1 - +0)) + +0,
generatePoint: function() {
this.targetX = Math.floor(Math.random() * (+ window.innerWidth + 1 - +0)) + +0
this.targetY = Math.floor(Math.random() * (+ window.innerHeight + 1 - +0)) + +0
return [this.targetX, this.targetY];
},
draw: function() {
context.fillStyle = 'black';
context.fillRect(this.currentX, this.currentY,60,60);
drawPoint(this.targetX, this.targetY)
context.font = "30px Arial";
}
};
enemies.push(enemy)
return enemy
}
var enemy = createEnemy("tak")
var enemy1 = createEnemy("tak")
var enemy2 = createEnemy("tak")
var enemy3 = createEnemy("tak")
var enemy5 = createEnemy("tak")
function drawFrame() {
document.getElementById("fps").innerHTML = "FPS: " + fps;
drawCharacter(getCurrentMouse().x, getCurrentMouse().y)
getEnemies().forEach((en, index) => {
if(en.didCompletePoint) {
en.didCompletePoint = false;
en.generatePoint()
}else {
if((en.targetX === en.currentX) && (en.targetY === en.currentY)) {
en.didCompletePoint = true;
}
else {
//vertical movement
if (en.targetY > en.currentY){
en.currentY++;
}
else if (en.targetY < en.currentY) {
en.currentY--;
}
//side movement
// going right
if (en.targetX > en.currentX) {
en.currentX++;
}
// going left
else if (en.targetX < en.currentX) {
en.currentX--;
}
}
}
en.draw();
})
startLoop();
}
function startLoop() {
window.requestAnimationFrame(() => {
const p = performance.now();
while (fpsTime.length > 0 && fpsTime[0] <= p - 1000) {
fpsTime.shift();
}
fpsTime.push(p);
fps = fpsTime.length;
drawFrame();
});
}
startLoop();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
</style>
</head>
<body>
<p id="fps" style="font-size: 30px; font-family: 'Calibri Light', serif; position: absolute; right: 2%; top: 0%;"></p>
<canvas id="canv" style="margin: 0;"></canvas>
</body>
<script src="script.js"></script>
</html>

Triangle and circle in JavaScript

i'm a beginner to javascript, so there might be something that i dont know yet, but i'm trying
to make a logo in script, in html. this is the code to make a square that moves, but i need a triangle for my logo: also, i need to know how to make a circle in javascript for the same reason. please help me out.
var myGamePiece;
var myGamePiece2;
var myObstacles = [];
var myScore;
function startGame() {
myGamePiece = new component(30, 30, "yellow", 10, 240);
myGamePiece2 = new component(30, 10, "orange", 18, 250);
myGamePiece3 = new component(30, 10, "black", 18, 250);
myScore = new component("30px", "Consolas", "black", 280, 40, "text");
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
if (this.type == "text") {
ctx.font = this.width + " " + this.height;
ctx.fillStyle = color;
ctx.fillText(this.text, this.x, this.y);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, height, gap, minHeight, maxHeight, minGap, maxGap;
for (i = 0; i < myObstacles.length; i += 1) {
if (myGamePiece.crashWith(myObstacles[i])) {
myGameArea.stop();
return;
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = myGameArea.canvas.width;
minHeight = 20;
maxHeight = 200;
height = Math.floor(Math.random() * (maxHeight - minHeight + 1) + minHeight);
minGap = 50;
maxGap = 200;
gap = Math.floor(Math.random() * (maxGap - minGap + 1) + minGap);
myObstacles.push(new component(10, height, "green", x, 0));
myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));
}
for (i = 0; i < myObstacles.length; i += 1) {
myObstacles[i].speedX = -1;
myObstacles[i].newPos();
myObstacles[i].update();
}
myScore.text = "SCORE: " + myGameArea.frameNo;
myScore.update();
myGamePiece.newPos();
myGamePiece.update();
myGamePiece2.newPos();
myGamePiece2.update();
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {
return true;
}
return false;
}
function moveup() {
myGamePiece.speedY = -1;
myGamePiece2.speedY = -1;
myGamePiece3.speedY = -1;
}
function movedown() {
myGamePiece.speedY = 1;
myGamePiece2.speedY = 1;
myGamePiece3.speedY = 1;
}
function moveleft() {
myGamePiece.speedX = -1;
myGamePiece2.speedX = -1;
myGamePiece3.speedX = -1;
}
function moveright() {
myGamePiece.speedX = 1;
myGamePiece2.speedX = 1;
myGamePiece3.speedX = 1;
}
function clearmove() {
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
myGamePiece2.speedX = 0;
myGamePiece2.speedY = 0;
myGamePiece3.speedX = 0;
myGamePiece3.speedY = 0;
}
canvas {
border: 1px solid #d3d3d3;
background-color: #0033cc;
}
<!DOCTYPE html>
<html>
<head>
<title>Flappy!</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://www.w3schools.com/lib/w3-theme-black.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/160px-Apple_logo_black.svg.png" sizes="16x16">
<link rel="canonical" href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/160px-Apple_logo_black.svg.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body onload="startGame()">
<div class="w3-center w3-green w3-text-black">
<h1>Flappy!</h1>
<h4>the first game that tech gaming put out..., Flappy!</h4>
<div style="text-align:center;width:480px;">
<button onmousedown="moveup()" onmouseup="clearmove()" ontouchstart="moveup()">UP</button><br><br>
<button onmousedown="moveleft()" onmouseup="clearmove()" ontouchstart="moveleft()">LEFT</button>
<button onmousedown="moveright()" onmouseup="clearmove()" ontouchstart="moveright()">RIGHT</button><br><br>
<button onmousedown="movedown()" onmouseup="clearmove()" ontouchstart="movedown()">DOWN</button>
</div>
<p>The score will count one point for each split-second you manage to "stay alive".</p>
</div>
</body>
</html>
theres probably some code i dont know but like i said i dont know very much javascript.
I added the code below at the end of your component.update() to draw a circle and triangle. I got this from the Mozilla docs on drawing shapes, found here. See the full modified code as well farther below.
Added Code:
//DRAW CIRCLE
ctx.beginPath();
var x = 50; // x coordinate
var y = 150; // y coordinate
var radius = 20; // Arc radius
var startAngle = 0; // Starting point on circle
var endAngle = Math.PI + (Math.PI); // End point on circle
var anticlockwise = 0; // clockwise or anticlockwise
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
ctx.fillStyle = "red";
ctx.fill();
//DRAW TRIANGLE
ctx.beginPath();
ctx.moveTo(50, 30);
ctx.lineTo(25, 75);
ctx.lineTo(75, 75);
ctx.fillStyle = "black";
ctx.fill();
Full Modified Code:
<!DOCTYPE html>
<html>
<title>Flappy!</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://www.w3schools.com/lib/w3-theme-black.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/160px-Apple_logo_black.svg.png" sizes="16x16"><link rel="canonical" href="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/160px-Apple_logo_black.svg.png"/>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<div class="w3-center w3-green w3-text-black">
<h1>Flappy!<h1>
<h4>the first game that tech gaming put out..., Flappy!</h4>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #0033cc;
}
</style>
</head>
<body onload="startGame()">
<script>
var myGamePiece;
var myGamePiece2;
var myObstacles = [];
var myScore;
function startGame() {
myGamePiece = new component(30, 30, "yellow", 10, 240, "triangle");
myGamePiece2 = new component(30, 10, "orange", 18, 250);
myGamePiece3 = new component(30, 10, "black", 18, 250);
myScore = new component("30px", "Consolas", "black", 280, 40, "text");
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop : function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
if (this.type == "text") {
ctx.font = this.width + " " + this.height;
ctx.fillStyle = color;
ctx.fillText(this.text, this.x, this.y);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
//*************************MODIFIED CODE BELOW***********************************
//DRAW CIRCLE
ctx.beginPath();
var x = 50; // x coordinate
var y = 150; // y coordinate
var radius = 20; // Arc radius
var startAngle = 0; // Starting point on circle
var endAngle = Math.PI + (Math.PI); // End point on circle
var anticlockwise = 0; // clockwise or anticlockwise
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
ctx.fillStyle = "red";
ctx.fill();
//DRAW TRIANGLE
ctx.beginPath();
ctx.moveTo(50, 30);
ctx.lineTo(25, 75);
ctx.lineTo(75, 75);
ctx.fillStyle = "black";
ctx.fill();
//*************************MODIFIED CODE ABOVE***********************************
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, height, gap, minHeight, maxHeight, minGap, maxGap;
for (i = 0; i < myObstacles.length; i += 1) {
if (myGamePiece.crashWith(myObstacles[i])) {
myGameArea.stop();
return;
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = myGameArea.canvas.width;
minHeight = 20;
maxHeight = 200;
height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
minGap = 50;
maxGap = 200;
gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap);
myObstacles.push(new component(10, height, "green", x, 0));
myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));
}
for (i = 0; i < myObstacles.length; i += 1) {
myObstacles[i].speedX = -1;
myObstacles[i].newPos();
myObstacles[i].update();
}
myScore.text="SCORE: " + myGameArea.frameNo;
myScore.update();
myGamePiece.newPos();
myGamePiece.update();
myGamePiece2.newPos();
myGamePiece2.update();
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
function moveup() {
myGamePiece.speedY = -1;
myGamePiece2.speedY = -1;
myGamePiece3.speedY = -1;
}
function movedown() {
myGamePiece.speedY = 1;
myGamePiece2.speedY = 1;
myGamePiece3.speedY = 1;
}
function moveleft() {
myGamePiece.speedX = -1;
myGamePiece2.speedX = -1;
myGamePiece3.speedX = -1;
}
function moveright() {
myGamePiece.speedX = 1;
myGamePiece2.speedX = 1;
myGamePiece3.speedX = 1;
}
function clearmove() {
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
myGamePiece2.speedX = 0;
myGamePiece2.speedY = 0;
myGamePiece3.speedX = 0;
myGamePiece3.speedY = 0;
}
</script>
<div style="text-align:center;width:480px;">
<button onmousedown="moveup()" onmouseup="clearmove()" ontouchstart="moveup()">UP</button><br><br>
<button onmousedown="moveleft()" onmouseup="clearmove()" ontouchstart="moveleft()">LEFT</button>
<button onmousedown="moveright()" onmouseup="clearmove()" ontouchstart="moveright()">RIGHT</button><br><br>
<button onmousedown="movedown()" onmouseup="clearmove()" ontouchstart="movedown()">DOWN</button>
</div>
<p>The score will count one point for each split-second you manage to "stay alive".</p>
</div>
</body>
</html>

Why HTML canvas collision is not happening for the ball and the paddle?

I am building my ping pong game with javascript, Canvas and HTML So here is my Javascript code below to create the paddle and the ball. I want to know how to make the collision happen between paddle and ball. Below are my javascript and HTML
Below is my HTML code. Here I am declaring the canvas element
var c = document.getElementById("frame");
c.width = window.innerWidth * 0.31;
c.height = window.innerHeight * 0.55;
var ctx = c.getContext("2d");
var x = 10;
var y = 10;
var rx = 10;
var ry = 400;
var height = 70;
var width = 12;
var radius = 10;
var vx = Math.floor(Math.random() * 2);
var vy = Math.floor(Math.random() * 4);
drawPad(rx, ry, height, width);
function drawPad(rx, ry, height, width) {
ctx.fillStyle = "#f2a34b";
ctx.fillRect(rx, ry, height, width);
}
function drawCircle() {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function moveCircle() {
requestAnimationFrame(moveCircle);
if ((x + radius > 500) || (x - radius < 0)) {
vx = 0 - vx;
}
if ((y + radius > 420) || (y - radius < 0)) {
vy = 0 - vy;
}
x = x + vx;
y = y + vy;
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
drawCircle();
}
moveCircle();
window.onkeydown = function(event) {
if (event.keyCode == 37 && rx > 20) {
rx = rx - 20;
} else if (event.keyCode == 39 && rx <= 420) {
rx = rx + 20;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
canvas {
border: 1px solid #c7c7c7;
background-color: rgb(175, 166, 166);
}
</style>
</head>
<body>
<canvas id="frame"></canvas>
<script src="canvas.js"></script>
</body>
</html>
I only see you verify the collision with the borders in your code, but not with the paddle itself.
You just need to add some condition to detect its collision with the paddle. If a collision happened then the ball will move up otherwise it moves down
if(y+radius>=ry)
{
moveUp = true;
moveDown = false;
}
if(y+radius<=0)
{
moveUp = false;
moveDown = true;
}
and later tell the programe how it will happen
if(moveUp){
//x = x + vx;
y = y - vy;
}
if(moveDown){
//x = x - vx;
y = y + vy;
}
which gives you something like that if i am not mistaken :
var c = document.getElementById("frame");
c.width = window.innerWidth * 0.31;
c.height = window.innerHeight * 0.55;
var ctx = c.getContext("2d");
var x = 10;
var y = 10;
var rx = 10;
var ry = (window.innerHeight*0.55)-10;
var height = 70;
var width = 12;
var radius = 10;
var vx = Math.floor(Math.random() * 2);
var vy = Math.floor(Math.random() * 4);
let moveUp = false;
let moveDown = true;
drawPad(rx, ry, height, width);
function drawPad(rx, ry, height, width) {
ctx.fillStyle = "#f2a34b";
ctx.fillRect(rx, ry, height, width);
}
function drawCircle() {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function moveCircle() {
requestAnimationFrame(moveCircle);
/*if ((x + radius > 500) || (x - radius < 0)) {
vx = 0 - vx;
}*/
if((x+radius>=rx)&&(y+radius>=ry))
{
moveUp = true;
moveDown = false;
}
if(y+radius<=0)
{
moveUp = false;
moveDown = true;
}
/*if ((y + radius > 420) || (y - radius < 0)) {
vy = 0 - vy;
}*/
if(moveUp){
//x = x + vx;
y = y - vy;
}
if(moveDown){
//x = x - vx;
y = y + vy;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
drawCircle();
}
moveCircle();
window.onkeydown = function(event) {
if (event.keyCode == 37 && rx > 20) {
rx = rx - 20;
} else if (event.keyCode == 39 && rx <= 420) {
rx = rx + 20;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
canvas {
border: 1px solid #c7c7c7;
background-color: rgb(175, 166, 166);
}
</style>
</head>
<body>
<canvas id="frame"></canvas>
<script src="canvas.js"></script>
</body>
</html>

HTML and Javascript button not working

I am trying to make a webpage to store all my games on i just started and i've been trying to make a button to load my pong game but when I press the button nothing happens here's my code
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Title</title>
<meta charset="UTF-8">
<style>
canvas {
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
</head>
<body>
<center>
<h1>Games</h1>
button code
<input id="Pong" type="button" value="Pong" onclick="go();" />
pong code
<script>
function go(){
var WIDTH = 700, HEIGHT = 600, pi = Math.PI;
var UpArrow = 38, DownArrow = 40;
var canvas, ctx, keystate;
var player, ai, ball, score;
player = {
x: null,
y: null,
width: 20,
height: 100,
update: function(){
if(keystate[UpArrow]) this.y -= 7;
if(keystate[DownArrow]) this.y += 7;
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
ai = {
x: null,
y: null,
width: 20,
height: 100,
update: function(){
var desty = ball.y - (this.height - ball.side)*0.5;
this.y += (desty - this.y) * 0.1;
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
ball = {
x: null,
y: null,
vel: null,
side: 20,
speed: 9,
serve: function(side){
var r = Math.random();
this.x = side===1 ? player.x : ai.x - this.side;
this.y = (HEIGHT - this.side)*r;
score.count += 1;
var phi = 0.1*pi*(1 - 2*r);
this.vel = {
x: side*this.speed*Math.cos(phi),
y: this.speed*Math.sin(phi)
};
score = {
x: null,
y: null,
count: 0,
width: 10,
height: 10,
update: function(){
Console.log(this.count);
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
},
update: function(){
this.x += this.vel.x;
this.y += this.vel.y;
if(0 > this.y || this.y+this.side > HEIGHT){
var offset = this.vel.y < 0 ? 0 - this.y : HEIGHT - (this.y+this.side);
this.y += 2*offset;
this.vel.y *= -1;
}
var AABBIntersect = function(ax, ay, aw, ah, bx, by, bw, bh){
return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
};
var pdle = this.vel.x < 0 ? player : ai;
if(AABBIntersect(pdle.x, pdle.y, pdle.width, pdle.height, this.x, this.y, this.side, this.side)){
this.x = pdle===player ? player.x+player.width : ai.x - this.side;
var n = (this.y + this.side - pdle.y)/(pdle.height+this.side);
var phi = 0.25*pi*(2*n - 1);
var smash = Math.abs(phi) > 0.2*pi ? 1.5 : 1;
this.vel.x = smash*(pdle === player ? 1 : -1)*this.speed*Math.cos(phi);
this.vel.y = smash*this.speed*Math.sin(phi);
}
if(0 > this.x+this.side || this.x > WIDTH){
this.serve(pdle === player ? 1 : -1);
}
},
draw: function(){
ctx.fillRect(this.x, this.y, this.side, this.side);
}
};
function main(){
canvas = document.createElement("canvas");
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
keystate = {};
document.addEventListener("keydown", function(evt) {
keystate[evt.keyCode] = true;
});
document.addEventListener("keyup", function(evt) {
delete keystate[evt.keyCode];
});
init();
var loop = function(){
update();
draw();
window.requestAnimationFrame(loop, canvas);
};
window.requestAnimationFrame(loop, canvas);
}
function init(){
player.x = player.width;
player.y = (HEIGHT - player.height)/2;
ai.x = WIDTH - (player.width + ai.width);
ai.y = (HEIGHT - ai.height)/2;
ball.serve(1);
}
function update(){
ball.update();
player.update();
ai.update();
}
function draw(){
ctx.fillRect(0, 0, WIDTH, HEIGHT);
ctx.save();
ctx.fillStyle = "#fff";
ball.draw();
player.draw();
ai.draw();
var w = 4;
var x = (WIDTH - w) * 0.5;
var y = 0;
var step = HEIGHT/15;
while (y < HEIGHT){
ctx.fillRect(x, y + step * 0.25, w, step * 0.5);
y += step;
}
ctx.restore();
}
main();
}
</script>
end of pong code
</center>
</body>
</html>
I merely took #Xufox's solutions and wrote them out. Also serperated the JS, CSS, and HTML. Enjoy
function go(){
score = {
x: null,
y: null,
count: 0,
width: 10,
height: 10,
update: function(){
console.log(this.count);
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
var WIDTH = 700, HEIGHT = 600, pi = Math.PI;
var UpArrow = 38, DownArrow = 40;
var canvas, ctx, keystate;
var player, ai, ball, score;
player = {
x: null,
y: null,
width: 20,
height: 100,
update: function(){
if(keystate[UpArrow]) this.y -= 7;
if(keystate[DownArrow]) this.y += 7;
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
ai = {
x: null,
y: null,
width: 20,
height: 100,
update: function(){
var desty = ball.y - (this.height - ball.side)*0.5;
this.y += (desty - this.y) * 0.1;
},
draw: function(){
ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
ball = {
x: null,
y: null,
vel: null,
side: 20,
speed: 9,
serve: function(side){
var r = Math.random();
this.x = side===1 ? player.x : ai.x - this.side;
this.y = (HEIGHT - this.side)*r;
score.count += 1;
var phi = 0.1*pi*(1 - 2*r);
this.vel = {
x: side*this.speed*Math.cos(phi),
y: this.speed*Math.sin(phi)
};
},
update: function(){
this.x += this.vel.x;
this.y += this.vel.y;
if(0 > this.y || this.y+this.side > HEIGHT){
var offset = this.vel.y < 0 ? 0 - this.y : HEIGHT - (this.y+this.side);
this.y += 2*offset;
this.vel.y *= -1;
}
var AABBIntersect = function(ax, ay, aw, ah, bx, by, bw, bh){
return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
};
var pdle = this.vel.x < 0 ? player : ai;
if(AABBIntersect(pdle.x, pdle.y, pdle.width, pdle.height, this.x, this.y, this.side, this.side)){
this.x = pdle===player ? player.x+player.width : ai.x - this.side;
var n = (this.y + this.side - pdle.y)/(pdle.height+this.side);
var phi = 0.25*pi*(2*n - 1);
var smash = Math.abs(phi) > 0.2*pi ? 1.5 : 1;
this.vel.x = smash*(pdle === player ? 1 : -1)*this.speed*Math.cos(phi);
this.vel.y = smash*this.speed*Math.sin(phi);
}
if(0 > this.x+this.side || this.x > WIDTH){
this.serve(pdle === player ? 1 : -1);
}
},
draw: function(){
ctx.fillRect(this.x, this.y, this.side, this.side);
}
};
function main(){
canvas = document.createElement("canvas");
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
keystate = {};
document.addEventListener("keydown", function(evt) {
keystate[evt.keyCode] = true;
});
document.addEventListener("keyup", function(evt) {
delete keystate[evt.keyCode];
});
init();
var loop = function(){
update();
draw();
window.requestAnimationFrame(loop, canvas);
};
window.requestAnimationFrame(loop, canvas);
}
function init(){
player.x = player.width;
player.y = (HEIGHT - player.height)/2;
ai.x = WIDTH - (player.width + ai.width);
ai.y = (HEIGHT - ai.height)/2;
ball.serve(1);
}
function update(){
ball.update();
player.update();
ai.update();
}
function draw(){
ctx.fillRect(0, 0, WIDTH, HEIGHT);
ctx.save();
ctx.fillStyle = "#fff";
ball.draw();
player.draw();
ai.draw();
var w = 4;
var x = (WIDTH - w) * 0.5;
var y = 0;
var step = HEIGHT/15;
while (y < HEIGHT){
ctx.fillRect(x, y + step * 0.25, w, step * 0.5);
y += step;
}
ctx.restore();
}
main();
}
canvas {
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Title</title>
<meta charset="UTF-8">
</head>
<body>
<center>
<h1>Games</h1>
<input id="Pong" type="button" value="Pong" onclick="go();" />
</center>
<script type="text/javascript" src="javascript.js"></script>
</body>
</html>

Categories