class Snake {
constructor() {
this.x = 400;
this.y = 400;
this.width = 25;
this.height = 25;
}
draw() {
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
let snake = new Snake();
class Food {
constructor() {
this.x = Math.floor(Math.random() * (canvasWidth - 0) + 0)
this.y = Math.floor(Math.random() * (canvasHeight - 0) + 0)
this.width = 50;
this.height = 50;
/* this.image = new Image()
this.image.src = 'img/apple.png' */
}
update() {
}
draw() {
/* ctx.drawImage(this.image, this.x, this.y, this.width, this.height); */
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
let food = new Food()
function collision(){
if(snake.x < food.x + food.width &&
snake.x + snake.width > food.x &&
snake.y < food.y + food.height &&
snake.height + snake.y > food.y){
alert("hit")
}
}
collision()
I have two JS classes one portrays a snake the other portrays food, I tried this collision algorithm I found but it's not working. where is my mistake or how can I make the collision happen?
Just had to call collision() in the animate function
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
snake.draw();
snake.update();
food.draw()
collision()
requestAnimationFrame(animate);
}
animate();
Related
I am currently trying to build a Digital Table Tennis game and I have a lot in place so far, but whenever I run the program, the non-AI player's bat (The green rectangle) isn't showing up. It doesn't seem to be there at all. Is there some bug in my code? Also make sure to mainly pay attention to the bottom of the code, where the animate() function is declared. The outcome so far is here: https://Digital-Table-Tennis.programprodigy.repl.co. PLS HELP!
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
let mouse = {
x: null
}
window.onmousemove = e => {
mouse.x = e.x;
}
class Ball {
constructor() {
this.dx = Math.random() * 4 - 2;
this.dy = Math.random() * 4 - 2;
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
}
draw() {
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
ctx.fill();
}
update() {
this.x += this.dx;
this.y += this.dy;
if (
this.x >= mouse.x &&
this.x <= mouse.x + 50 &&
this.y >= canvas.height - 5 &&
this.y <= canvas.height
) {
this.dx = -this.dx;
this.dy = -this.dy;
}
if (
this.x <= 0 ||
this.x >= canvas.width ||
this.y <= 0 ||
this.y >= canvas.height
) {
this.dx = -this.dx;
this.dy = -this.dy;
}
this.draw();
}
}
let ball = new Ball();
class AI {
constructor(lvl) {
this.x = 0;
this.color = 'red';
this.speed = lvl * 5;
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, 0, 50, 5);
}
update() {
if (ball.y < canvas.height / 2) {
let distance = ball.x - this.x;
this.x += distance / this.speed;
}
if (
ball.x >= this.x &&
ball.x <= this.x + 50 &&
ball.y >= 0 &&
ball.y <= 5
) {
ball.dx = -ball.dx;
ball.dy = -ball.dy;
}
this.draw();
}
}
let ai_player = new AI(5);
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'red';
ctx.fillRect(mouse.x - 25, canvas.height - 5, 50, 5);
ball.update();
ai_player.update();
requestAnimationFrame(animate);
}
animate();
I actually have a red player rectangle on my end, however I had to scroll down to see it since the canvas height was more than my viewport.
You specified that the player rectangle should be green, but it's declared in animate() as ctx.fillStyle = 'red';.
As for solving the scrolling issues, it should be a quick CSS fix by specifying a max-width of 100vw and a max-height of 100vh on your canvas element, assuming you don't have any conflicting styles.
I am trying to make a game in which a player has an equippable weapon. As of now, I have set this weapon to be an image of a bow, and I want to have said weapon to move around the player while facing the mouse. This is similar to buildroyale.io, where the player rotates along with his weapon to face the mouse.
As of now, with the help of #Justin, I've got the bow rotating (somewhat) on the screen. It only shows up when the left click is down, as desired, but does not rotate as expected. Here is a clip showcasing how it moves: clip
Here is the code I use:
class EventHandler {
equip_weapon() {
if (holding) {
player.weapon = player.bag.slot_1;
canv.globalAlpha = 1;
player.weapon.equip();
player.weapon.update();
}
}
}
class Weapon {
image_path;
constructor(image_path) {
this.x = player.x + 30;
this.y = player.y + 30;
this.width = 120;
this.height = 120;
this.angle = 0;
this.distance = 50;
this.image = image_path;
}
equip() {
this.angle = Math.atan2(mouse.y - this.y, mouse.x - this.x)
canv.save();
canv.translate(this.x, this.y);
canv.rotate(this.angle);
canv.drawImage(this.image, this.distance, -this.height/2, this.width, this.height);
canv.restore();
}
update() {
this.x = player.x + player.width / 2;
this.y = player.y + player.height / 2;
}
}
bow = new Weapon(bow_image);
player.bag.slot_1 = bow;
aim_bounds = document.documentElement.getBoundingClientRect();
class Player {
constructor() {
this.name = null;
this.speed = 5;
this.skin = player_sheet;
this.can_move = true;
this.is_moving = false;
this.width = 68;
this.height = 68;
this.scale = 1;
this.x = 566;
this.y = 316;
this.direction = facing.down;
this.frame = 0;
this.shadow_offset = 25;
this.frame_rate = 10;
this.health = 100;
this.clip_amount = 10;
this.weapon = null;
// Player inventory
this.bag = {
slot_1 : null,
slot_2 : null,
slot_3 : null,
slot_4 : null,
slot_5 : null,
offhand : null,
armor : null
}
this.is_menu_open = false;
console.log("Player constructed!");
}
update() {
// Animation updates
if (game.tick % this.frame_rate == 0 && this.is_moving && !this.is_menu_open) {
this.frame += 68;
if (this.frame >= 272) { this.frame = 0; }
} else if (!this.is_moving) { this.frame = 0; }
// Movement updates
if (this.can_move) {
if (controller.up) { this.direction = facing.up; this.y -= this.speed; this.is_moving = true; }
else if (controller.down) { this.direction = facing.down; this.y += this.speed; this.is_moving = true; }
else if (controller.left) { this.direction = facing.left; this.x -= this.speed; this.is_moving = true; }
else if (controller.right) { this.direction = facing.right; this.x += this.speed; this.is_moving = true; }
if (!controller.up && !controller.down && !controller.left && !controller.right) { this.is_moving = false; }
}
// Checks
if (this.is_menu_open) { this.can_move = false; } else { this.can_move = true; }
document.getElementById("health_bar").value = this.health;
if (this.is_menu_open) { menu.style.display = "block"; } else { menu.style.display = "none"; }
}
animate() {
// Player shadow
canv.drawImage(player_shadow, this.x, this.y + this.shadow_offset);
// Player
canv.globalAlpha = 1;
canv.drawImage(player_sheet, (sprite.x + this.frame), (sprite.y * this.direction),
sprite.width, sprite.height,
this.x, this.y,
this.width, this.height);
}
}
Here is a download to my current code in case you need more to debug: game.zip
The way I handle this is to make sure my image is first oriented correctly. In my case my bow image would look like this (ignore the quality). Just see that it faces right.
In the draw function I use translate() to position the image and I use the x and y inside the drawImage(img, x, y, w, h) to draw the image centered along the top edge of the canvas. The x (set to 50 in this example) position is essentially the radius of the image rotation and the y is just to center my bow's arrow on the y axis of the canvas.
Using Math.atan2() I can rotate the image
this.angle = Math.atan2(mouse.y - this.y, mouse.x - this.x)
In this snippet I have two lines that are commented out. If you uncomment them you will better see what is happening.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 600;
let mouse = {x: 10, y: 10}
let canvasBounds = canvas.getBoundingClientRect();
canvas.addEventListener('mousemove', e => {
mouse.x = e.x - canvasBounds.x
mouse.y = e.y - canvasBounds.y
})
let bow = new Image();
bow.src = "https://lh3.googleusercontent.com/g5Sr3HmGZgWx07sRQMvgvtxZ-ErhWNT0_asFdhLIlw-EQMTuUq3BV3YY8d5rrIrZBiJ-Uo2l836Qlmr8dmaCi-dcCCqN6veS6xnE8jSrmdtRtZKnmF5FQ5aTxuVBgB28n6ICoxSlpA=w2400";
class Weapon {
constructor() {
this.x = 200;
this.y = 200;
this.w = 60;
this.h = 60;
this.angle = 0
}
draw() {
this.angle = Math.atan2(mouse.y - this.y, mouse.x - this.x)
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
//ctx.fillStyle = 'lightgrey';
//ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(bow, 50, -this.h/2, this.w, this.h)
ctx.restore();
}
}
let bowArrow = new Weapon();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
bowArrow.draw();
requestAnimationFrame(animate)
}
animate();
<canvas id="canvas"></canvas>
UPDATE:
Here is what I changed in your files and it works well on my end.
engine.controller.js change mousemove and add listener for resize. I'm also pretty sure there's a way you can get rid of the getMouse function since the listener below gets mouse coordinates for you.
canvas.addEventListener("mousemove", function (event) {
mouse_position = event
mouse.x = event.x - canvas_bounds.x;
mouse.y = event.y - canvas_bounds.y;
})
window.addEventListener('resize', () => {
canvas_bounds = canvas.getBoundingClientRect();
})
engine.eventhandler.js
class Weapon {
image_path;
constructor(image_path) {
this.x = player.x + player.width/2;
this.y = player.y + player.height/2;
this.w = 60;
this.h = 60;
this.angle = 0;
this.image = image_path;
}
equip() {
this.x = player.x + player.width/2;
this.y = player.y + player.height/2;
this.angle = Math.atan2(mouse.y - this.y, mouse.x - this.x)
canv.save();
canv.translate(this.x, this.y);
canv.rotate(this.angle);
canv.drawImage(this.image, 50, -this.h/2, this.w, this.h);
canv.restore();
}
}
engine.main.js
function setup() {
game = new Game;
player = new Player;
controller = new Controller;
event_handler = new EventHandler;
canvas.width = 1200;
canvas.height = 700;
canvas_bounds = canvas.getBoundingClientRect();
// REMOVE LATER
bow = new Weapon(bow_image);
player.bag.slot_1 = bow;
document.getElementById("bag").style.display = "block";
}
engine.setup.js
// Weapon stuff
var weapon_equiped = false;
var canvas = document.getElementById("canvas");
let mouse = {
x : 10,
y : 10
}
let canvas_bound;
var mouse_position, holding;
var rect, mouse_x, mouse_y;
...and
//you have a space between canvas. height in both fillRect
canv.fillRect(0, 0, canvas.width, canvas. height);
I think that's all I changed. Pretty sure you can use your mouse_x or the mouse.x but you probably don't need both in your code.
var car;
var front;
var back;
var img = new Image();
img.src = 'https://cdn4.iconfinder.com/data/icons/transportation-2-4/60/transportation-2-flat-036-racing-car-top-512.png';
function startGame() {
car = new move(12, 20, "red", 600, 300);
pg.start();
}
var pg = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 1200;
this.canvas.height = 600;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateframe, 20);
window.addEventListener('keydown', function(e) {
e.preventDefault();
pg.keys = (pg.keys || []);
pg.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function(e) {
pg.keys[e.keyCode] = (e.type == "keydown");
})
},
stop: function() {
clearInterval(this.interval);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function move(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = pg.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(img, this.width / -2, this.height / -2,20,40);
ctx.beginPath();
ctx.moveTo(this.width / -2, this.height / -2);
ctx.lineTo(this.width / -2, 30);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(this.width / -2, 30);
ctx.lineTo(13, (this.height / -2)+40);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(14, (this.height / -2)+40);
ctx.lineTo(14, this.height / -2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(14, this.height / -2);
ctx.lineTo(this.width / -2, this.height / -2);
ctx.stroke();
ctx.restore();
ctx.beginPath();
ctx.moveTo(300, 150);
ctx.lineTo(600, 800);
ctx.stroke();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function updateframe() {
pg.clear();
car.moveAngle = 0;
car.speed = 0;
if (pg.keys && pg.keys[37]) {
if (pg.keys && pg.keys[40]) {
car.moveAngle = 5;
}
if (pg.keys && pg.keys[38]) {
car.moveAngle = -5;
}
}
if (pg.keys && pg.keys[39]) {
if (pg.keys && pg.keys[40]) {
car.moveAngle = -5;
}
if (pg.keys && pg.keys[38]) {
car.moveAngle = 5;
}
}
if (pg.keys && pg.keys[38]) {
car.speed = 5;
}
if (pg.keys && pg.keys[40]) {
car.speed = -5;
}
car.newPos();
car.update();
}
startGame();
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
There is a car and a line, now i want to make an alert whenever the car get touched by the the line.
I know how to do this logically. like if i convert the car image in four lines (border) then use line intersection formula to get if there is a intersection but i am new to this canvas drawing and i cant figure how to get the border line equation of car.
update: i have made lines of border around the car, now i just need help with getting if these lines intersects with each other...
code is updated plz check it now...
one more thing, at this point there is only one line and i am going to add more lines in it... so i need a function to call it more often and get if the lines are intersecting with car border...
Note : use arrow keys to move car in snippet
The ball seems to bounce off one side of the paddle, but when it comes from the side it glitches through the paddle. I just can't find a way behind it and it really bothers me. I am using some logic gates to define where the ball's direction is need to be invereted
function startGame() {
GameArea.start();
Ball1 = new CircleComp('white' , window.innerWidth - 200 , window.innerHeight - 20);
Ball1.ySpeed = 13.5;
Ball1.xSpeed = 6;
Paddle1 = new PaddleComp( 87, 83, 0, window.innerHeight / 2.5, 10, 70);
Paddle2 = new PaddleComp( 38, 40, window.innerWidth - 10, window.innerHeight / 2.5, 10 , 70);
}
var GameArea = {
canvas : canvas = document.querySelector("canvas"),
start : function (){
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
GameArea.keys = (GameArea.keys || []);
GameArea.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
GameArea.keys[e.keyCode] = false;
})
},
clear : function() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function CircleComp(color, x , y){
this.x = x;
this.y = y;
this.width = 8;
this.height = 8;
var context1 = GameArea.ctx;
this.update = function(){
context1.beginPath();
context1.fillStyle = color;
context1.fillRect(this.x, this.y, this.width, this.height);
context1.fill();
context1.stroke();
this.updatePosition();
}
this.updatePosition = function(){
this.y += this.ySpeed;
this.x += this.xSpeed;
if(this.x + this.width > GameArea.canvas.width){
this.xSpeed = -this.xSpeed;
}
if(this.y + this.height > GameArea.canvas.height){
this.ySpeed = -this.ySpeed;;
}
if(this.x - this.width < 0){
this.xSpeed = -this.xSpeed;
}
if(this.y - this.height < 0){
this.ySpeed = -this.ySpeed;
}
if(this.y + this.height > Paddle2.y && this.y - this.width < (Paddle2.y + 130) && this.x + this.width > Paddle2.x ){
this.xSpeed = -this.xSpeed;
}
if(this.y + this.height > Paddle1.y && this.y - this.width < (Paddle1.y + 70) && this.x - this.height < Paddle1.x + 10){
this.xSpeed = -this.xSpeed;
}
}
}
function PaddleComp(Upkey, Downkey, x, y, width, height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.ySpeed = 0;
var context2 = GameArea.ctx;
this.update = function(){
context2.fillStyle = 'white';
context2.fillRect(x,this.y,this.width,this.height);
this.updatePosition();
}
this.updatePosition = function() {
this.ySpeed = 0;
if (GameArea.keys && GameArea.keys[Upkey]) {
this.ySpeed = -15; //console.log('Up');
}
if (GameArea.keys && GameArea.keys[Downkey]) {
this.ySpeed = 15; //console.log('Down');
}
if ((GameArea.keys && GameArea.keys[Downkey]) && this.y + 130 > window.innerHeight){
this.ySpeed = this.ySpeed -15 ;
}
if ((GameArea.keys && GameArea.keys[Upkey]) && this.y < 0 ){
this.ySpeed = this.ySpeed +15 ;
}
this.y += this.ySpeed;
}
}
function updateGameArea(){
GameArea.clear();
Paddle1.update();
Paddle2.update();
Ball1.update();
}
<html>
<head>
<meta charset='urf-8'>
<style>
canvas{
border: 0px solid black;
background-color: black;
}
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body onload='startGame()'>
<canvas></canvas>
<script src='Pong.js'></script>
</body>
</html>
Could not see directly what the problem was with your code so i just rewrote the code with the ball, bat (paddle) test function in the ball Object and called from the players object. ball.checkPad(player); tests if the ball has hit the players bat. To help picture what is happening I have slowed it all down and made the bats real phat. When the ball hits the bat it will turn yellow and the bat red for a second or so.
There is plenty of comments in the parts you asked about,
Hope it helps
Demo copied from OP question.
const setting = {
speed : 2, // of ball
left : 0,
width : 400,
height : 200,
padWidth : 50,
padHeight : 80,
padSpeed : 4, // double balls
hitPauseCount : 30, // nuber of frames to hold when there is a collisiotn so you
// can check all is good
}
const keys = {
ArrowUp : false,
ArrowDown : false,
ArrowLeft : false,
ArrowRight : false,
keyEvent(e) { // dont use keyCode it has depreciated
if (keys[e.code] !== undefined) {
keys[e.code] = e.type === "keydown";
e.preventDefault();
}
}
}
var ctx;
var ball1, paddle1, paddle2;
var gameArea = {
start() {
canvas.width = setting.width;
canvas.height = setting.height;
ctx = canvas.getContext('2d');
requestAnimationFrame(updateGameArea);
},
clear() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
}
gameArea.start();
ball = new CircleComp('white', window.innerWidth - 200, window.innerHeight - 20);
ball.ySpeed = setting.speed;
ball.xSpeed = setting.speed;
paddle1 = new PaddleComp("ArrowUp", "ArrowDown", setting.left, setting.height / 2, setting.padWidth, setting.padHeight);
paddle2 = new PaddleComp("ArrowLeft", "ArrowRight", setting.width - setting.padWidth, setting.height / 2, setting.padWidth, setting.padHeight);
window.addEventListener('keydown', keys.keyEvent);
window.addEventListener('keyup', keys.keyEvent);
function CircleComp(color, x, y) {
this.x = x;
this.y = y;
this.width = 8;
this.height = 8;
this.xSpeed = setting.speed;
var hit = 0;
var restartCount;
var serveDirection;
this.reset = function(){
this.x = ctx.canvas.width /2;
this.y = ctx.canvas.height / 2;
this.xSpeed = -this.xSpeed
this.ySpeed = setting.speed * Math.sign(Math.random() - 0.5);
restartCount = 60;
}
this.draw = function () {
if(hit > 0){
hit -= 1;
ctx.fillStyle = "yellow";
}else{
ctx.fillStyle = color;
}
ctx.fillRect(this.x, this.y, this.width, this.height);
}
// next funtion is called by the player objects
this.checkPad = function (player) {
if (player.x > canvas.width / 2) { // is player on left or right
if (this.xSpeed > 0) { // player on right only check if ball moving rigth
if (this.x + this.width > player.x) { // ball is in paddles zone
//if not bottom of ball above top of bat or top of ball bellow bottom of bat
if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
// ball and bat in contact
// is ball moving down and the balls top edge above the player
// then ball has hit the top side of the bat
if(this.ySpeed > 0 && this.y <= player.y){
this.y = player.y - this.width;
this.ySpeed = -setting.speed;
}else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
this.y = player.y + player.height;
this.ySpeed = setting.speed;
}else{ // ball hit front of bat
this.x = player.x - this.width;
this.xSpeed = - setting.speed;
}
player.hit = setting.hitPauseCount; // counters to show FX when a hit happens
hit = setting.hitPauseCount;
}
}
}
} else { // player must be left
if (this.xSpeed < 0) { // ball must move left
if (this.x < player.x + player.width) { // ball is in paddles zone
if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
// ball and bat in contact
// ball and bat in contact
// is ball moving down and the balls top edge above the player
// then ball has hit the top side of the bat
if(this.ySpeed > 0 && this.y <= player.y){
this.y = player.y - this.width;
this.ySpeed = -setting.speed;
}else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
this.y = player.y + player.height;
this.ySpeed = setting.speed;
}else{ // ball hit front of bat
this.x = player.x + player.width;
this.xSpeed = setting.speed;
}
player.hit = setting.hitPauseCount; // counters to show FX when a hit happens
hit = setting.hitPauseCount;
}
}
}
}
}
this.update = function () {
if(restartCount > 0){ // wait for restart pause
restartCount -= 1;
}else{
if(hit > 0){ // do nothing if paused
return;
}
this.y += this.ySpeed;
this.x += this.xSpeed;
if (this.x + this.width >= canvas.width) {
this.reset(); // point
} else if (this.x < 0) {
this.reset(); // point
}
if (this.y + this.height >= canvas.height) {
this.y = canvas.height - this.height;
this.ySpeed = -setting.speed;
} else if (this.y < 0) {
this.y = 0;
this.ySpeed = setting.speed;
}
}
}
this.reset();
}
function PaddleComp(upKey, downKey, x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.hit = 0;
this.draw = function () {
if(this.hit > 0){
this.hit -= 1;
ctx.fillStyle = "red";
}else{
ctx.fillStyle = '#9CF';
}
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.update = function () {
if (keys[upKey]) {
this.y -= setting.padSpeed;
};
if (keys[downKey]) {
this.y += setting.padSpeed;
};
if (this.y < 0) {
this.y = 0;
}
if (this.y + this.height >= canvas.height) {
this.y = canvas.height - this.height;
}
ball.checkPad(this);
}
}
function updateGameArea() {
gameArea.clear();
paddle1.update();
paddle2.update();
ball.update();
paddle1.draw();
paddle2.draw();
ball.draw();
requestAnimationFrame(updateGameArea);
}
<canvas id=canvas style='background:#69C;border:2px blue solid'></canvas>
I'm working on a JQuery / JavaScript canvas brick break game, so I added the collision detection code if the ball hits the paddle or not, but when I ran the code, the collision detection code didn't work, I was wondering if anyone could help me? Here's the code.
JSFiddle: https://jsfiddle.net/18h7b9fd/
Main.js
$(document).ready(() => {
let fps = 60;
setInterval(init, 1000 / fps);
$(canvas).bind("mousemove", paddleControl);
})
// INIT
let init = () => {
draw(); //draw objects
animate(); //animate objects
collision(); //detect collision
}
// DRAW
let draw = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
paddle.draw();
ball.draw();
}
// ANIMATE
let animate = () => {
ball.animate();
}
// COLLISION
let collision = () => {
ball.collision();
}
// CONTROL
let paddleControl = (e) => {
// get mouse pos
let rect = canvas.getBoundingClientRect();
let root = document.documentElement;
let mouseX = e.pageX - rect.left - root.scrollLeft;
paddle.x = mouseX - paddle.w / 2;
}
Objects.js
class Paddle {
constructor(x, y, w, h, color) {
this.x = canvas.width / 2 - 100 / 2;
this.y = canvas.height - 60;
this.w = 100;
this.h = 10;
this.color = "#fff";
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
class Ball {
constructor(x, y, r, color, speedX, speedY) {
this.x = canvas.width / 2 - 10 / 2;
this.y = canvas.height / 2 - 10 / 2;
this.r = 10;
this.color = "#fff";
this.speedX = 6;
this.speedY = 6;
}
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.fill();
}
animate() {
this.x += this.speedX;
this.y += this.speedY;
}
collision() {
// BALL TO PADDLE
let paddleTop = paddle.y - paddle.h;
let paddleBottom = canvas.height - paddleTop;
let paddleLeft = paddle.x;
let paddleRight = paddle.x + paddle.w;
if(this.y >= paddleTop && this.y <= paddleBottom &&
this.x >= paddleLeft && this.x <= paddleRight) {
this.speedY *= -1;
}
// BALL TO WALL
if(this.x >= canvas.width) this.speedX *= -1; //left
if(this.x <= 0) this.speedX *= -1; //right
if(this.y >= canvas.height) this.reset(); //bottom
if(this.y <= 0) this.speedY *= -1; //top
}
reset() {
this.x = canvas.width / 2 - this.r / 2;
this.y = canvas.height / 2 - this.r / 2;
this.animate();
}
}
let paddle = new Paddle(this.x, this.y, this.w, this.h, this.color);
let ball = new Ball(this.x, this.y, this.r, this.color, this.speedX, this.speedY);
console.log(paddle);
console.log(ball);
The problem is the way you are setting the paddle top and bottom. Use this instead:
let paddleTop = paddle.y;
let paddleBottom = paddleTop + paddle.h;
Currently the way you are setting the values makes it impossible for the condition to ever be true (as paddle bottom is always less than paddle top).
I have put together a fiddle here: https://jsfiddle.net/gegbqv5p/
You will also notice that I didn't use jQuery. For what you have so far, it really isn't necessary.