Property in JS class is not changing the value, always is undefined - javascript

This is a part of code for make an Snake Game in JS, the problem is that I want to set oldDirection the actual direction to make an animation with the sprites in the U-turns but this.direction is having new value but oldDirection is always undefined.
class SnakeBody {
constructor(x, y, ctx) {
this.x = x
this.y = y
this.oldX
this.oldY
this.ctx = ctx
this.direction
this.oldDirection
this.sprite = new Image()
}
// Draws Players Body taking direction from head to set the direction of sprite
draw(headDirection) {
this.direction = headDirection
this.sprite.onload = () => {
this.ctx.drawImage(this.sprite, this.x, this.y, 20, 20)
}
}
// Update Player Body to new X and Y, and this must receive direction to change sprite
update(newX, newY, newDirection) {
// Problem here OldDirection doesn't get the address value
this.oldDirection = this.direction
this.direction = newDirection
this.ctx.clearRect(this.x, this.y, 20, 20)
this.oldX = this.x
this.oldY = this.y
this.x = newX;
this.y = newY;
this.sprite.onload = () => {
this.ctx.drawImage(this.sprite, this.x, this.y, 20, 20)
}
}
setDirection(nDirection) {
this.oldDirection = this.direction
this.direction = nDirection
}
getDirection() {
return this.direction
}
// Sets the sprite for the snake body
setSnakeSpriteDirection(newDirection) {
switch (true) {
case this.direction == 'DOWN' && newDirection == 'LEFT':
this.sprite.src = 'src/assets/img/snakeBody_rotateDownLeft.png'
break
case this.direction == 'UP' || this.direction == 'UP' &&
newDirection == 'DOWN' || this.direction == 'DOWN':
this.sprite.src = 'src/assets/img/snakeBody_down.png'
break;
case this.direction == 'RIGHT' || this.direction == 'RIGHT' &&
newDirection == 'LEFT' || this.direction == 'LEFT':
this.sprite.src = 'src/assets/img/snakeBody_left.png'
break;
default:
this.sprite.src = 'src/assets/img/snakeBody_left.png'
break;
}
this.draw()
}
}
EDIT:
SnakeBody:
class SnakeBody {
constructor(x, y, ctx) {
this.x = x
this.y = y
this.oldX
this.oldY
this.ctx = ctx
this.direction
this.oldDirection
this.sprite = new Image()
}
draw(headDirection) {
this.direction = headDirection
this.sprite.onload = () => {
this.ctx.drawImage(this.sprite, this.x, this.y, 20, 20)
}
}
update(newX, newY, newDirection) {
this.oldDirection = this.direction
this.direction = newDirection
this.ctx.clearRect(this.x, this.y, 20, 20)
console.log('This.Direction:', this.direction, 'This.oldDirection:', this.oldDirection);
this.oldX = this.x
this.oldY = this.y
this.x = newX;
this.y = newY;
this.sprite.onload = () => {
this.ctx.drawImage(this.sprite, this.x, this.y, 20, 20)
}
}
setDirection(nDirection) {
this.oldDirection = this.direction
this.direction = nDirection
}
getDirection() {
return this.direction
}
setSnakeSpriteDirection(newDirection) {
switch(true) {
case this.direction == 'DOWN' && newDirection == 'LEFT':
this.sprite.src = 'src/assets/img/snakeBody_rotateDownLeft.png'
break
case this.direction == 'UP' || this.direction == 'UP'
&& newDirection == 'DOWN' || this.direction == 'DOWN':
this.sprite.src = 'src/assets/img/snakeBody_down.png'
break;
case this.direction == 'RIGHT' || this.direction == 'RIGHT'
&& newDirection == 'LEFT' || this.direction == 'LEFT':
this.sprite.src = 'src/assets/img/snakeBody_left.png'
break;
default:
this.sprite.src = 'src/assets/img/snakeBody_left.png'
break;
}
this.draw()
}
}
Player Class:
class Player {
constructor(x, y, name, ctx) {
this.x = x;
this.y = y;
this.oldX;
this.oldY;
this.name = name;
this.ctx = ctx;
this.direction
this.oldDirection
this.body = []
this.sprite = new Image()
this.counter = 0;
}
draw() {
switch (this.getDirection()) {
case 'UP':
this.sprite.src = 'src/assets/img/snakeHead.png'
break;
case 'DOWN':
this.sprite.src = 'src/assets/img/snakeHead_down.png'
break;
case 'RIGHT':
this.sprite.src = 'src/assets/img/snakeHead_right.png'
break;
case 'LEFT':
this.sprite.src = 'src/assets/img/snakeHead_left.png'
break;
default:
this.sprite.src = 'src/assets/img/snakeHead.png'
break;
}
this.sprite.onload = () => {
this.ctx.drawImage(this.sprite, this.x, this.y, 20, 20)
}
}
update(newX, newY) {
this.ctx.clearRect(this.x, this.y, 20, 20)
this.x = newX;
this.y = newY;
}
updateBody() {
if (this.body.length > 0) {
this.body.forEach((bodyPart, index) => {
if( index == 0 ) {
bodyPart.update(this.x, this.y, this.oldDirection)
bodyPart.setSnakeSpriteDirection(this.direction)
} else {
bodyPart.update(
this.body[index - 1].oldX,
this.body[index - 1].oldY,
this.body[index - 1].oldDirection
)
bodyPart.setSnakeSpriteDirection(this.body[index - 1].getDirection())
}
})
}
}
movement() {
this.updateBody()
this.oldY = this.y
this.oldX = this.x
switch (this.direction) {
case 'DOWN':
this.y != 380
? this.update(this.x, this.y + 20)
: this.update(this.x, 0)
break;
case 'UP':
this.y == 0
? this.update(this.x, 380)
: this.update(this.x, this.y - 20)
break;
case 'LEFT':
this.x == 0
? this.update(380, this.y)
: this.update(this.x - 20, this.y)
break;
case 'RIGHT':
this.x != 380
? this.update(this.x + 20, this.y)
: this.update(0, this.y)
break;
default:
break;
}
this.oldDirection = this.direction
}
setDirection(direction) {
this.oldDirection = this.direction
this.direction = direction
}
getDirection() {
return this.direction
}
checkCollision(block) {
if (
this.x < block.x + 20 &&
this.x + 20 > block.x &&
this.y < block.y + 20 &&
this.y + 20 > block.y
) {
let newBody = new SnakeBody(this.x, this.y, this.ctx)
newBody.setDirection()
this.body.push(newBody)
}
}
}
Game: (Where I set the Player direction):
document.addEventListener('DOMContentLoaded', (e) => {
const canvasGame = document.querySelector('canvas')
const ctx = canvasGame.getContext('2d')
const
cHeight = canvasGame.height = 400,
cWidth = canvasGame.width = 400;
let cells = 20;
const drawGrid = () => {
ctx.lineWidth = 1.1
ctx.strokeStyle = '#232332'
ctx.shadowBlur = 0
for (let i = 0; i < cells; i++) {
let f = (cHeight / cells) * i
ctx.beginPath()
ctx.moveTo(f, 0);
ctx.lineTo(f, cHeight)
ctx.stroke()
ctx.beginPath();
ctx.moveTo(0, f)
ctx.lineTo(cHeight, f)
ctx.stroke()
ctx.closePath()
}
}
const drawPlayer = () => {
let playerX = Math.floor(Math.random() * 19 - 0 + 1) * 20
let foodX = Math.floor(Math.random() * 19 - 0 + 1) * 20
let foodY = Math.floor(Math.random() * 19 - 0 + 1) * 20
let playerY = Math.floor(Math.random() * 19 - 0 + 1) * 20
let food = new Food(foodX, foodY, 'red', ctx)
let player = new Player(playerX, playerY, 'Moises', ctx)
player.draw()
food.draw()
document.addEventListener('keydown', (e) => {
switch (e.keyCode) {
case 37:
player.setDirection('LEFT')
break;
case 39:
player.setDirection('RIGHT')
break
case 38:
player.setDirection('UP')
break
case 40:
player.setDirection('DOWN')
break;
}
})
setInterval(() => {
player.movement()
player.checkCollision(food)
food.collision(player)
player.draw()
food.draw()
drawGrid()
}, 450)
}
drawGrid()
drawPlayer()
})
<canvas></canvas>
Food Class:
class Food {
constructor(x, y, color, ctx) {
this.x = x
this.y = y
this.color = color
this.ctx = ctx
}
draw() {
let img = new Image()
img.src = 'src/assets/img/apple.png'
img.onload = () => {
this.ctx.drawImage(img, this.x, this.y, 20, 20);
// this.ctx.fillStyle = this.color
// this.ctx.fillRect(this.x, this.y, 20, 20)
}
}
update(newX, newY) {
this.ctx.clearRect(this.x, this.y, 20, 20)
this.x = newX;
this.y = newY;
// this.ctx.fillRect(newX, newY, 20, 20)
}
collision(player) {
let newX = (Math.floor(Math.random() * 19 - 0 + 1)) * 20;
let newY = (Math.floor(Math.random() * 19 - 0 + 1)) * 20;
if (
player.x < this.x + 20 &&
player.x + 20 > this.x &&
player.y < this.y + 20 &&
player.y + 20 > this.y
) {
this.update(newX, newY)
}
}
}

Seems to work fine for me.
class SnakeBody {
constructor() {
this.direction
this.oldDirection
}
test( newDirection ) {
this.oldDirection = this.direction;
this.direction = newDirection;
}
}
const snake = new SnakeBody();
snake.test( 1 );
snake.test( 2 );
console.log( snake.oldDirection );
EDIT:
i'm guessing your problem is here, in your player class:
index == 0
? (
bodyPart.update(this.x, this.y, this.oldDirection),
bodyPart.setSnakeSpriteDirection(this.direction)
)
: (
bodyPart.update(
this.body[index - 1].oldX,
this.body[index - 1].oldY,
this.body[index - 1].oldDirection
),
bodyPart.setSnakeSpriteDirection(this.body[index - 1].getDirection())
)
Does this code not give you errors? it feels like you are using a different language here. you are putting commas in between lines of code. you are using a ternary operator as if it were just an if statement, or something like that. you're putting parenthesis around lines of code. i'm surprised its not giving errors in the console.
Edit 2:
Try replacing this strange ternary operator with this code instead:
if( index == 0 ) {
bodyPart.update(this.x, this.y, this.oldDirection)
bodyPart.setSnakeSpriteDirection(this.direction)
} else {
bodyPart.update(
this.body[index - 1].oldX,
this.body[index - 1].oldY,
this.body[index - 1].oldDirection
)
bodyPart.setSnakeSpriteDirection(this.body[index - 1].getDirection())
}

Related

How Can I give my player to the cross movement in JS Canvas Game?

This is a Canvas game for personal development and I am stuck in here.
Everything works pretty well until I try to give my player a cross-movement
I have a player class like this ==>
And it has methods like dw() {means go up and right} , as() {left and down at the same time } ... etc I want to give a cross moving to my player with the key combinations .
Maybe someone shows me a correct way to do this.
import { ctx } from "./app.js"
export default class Player {
constructor(x, y, radius, color) {
this.x = x
this.y = y
this.color = color
this.radius = radius
}
draw() {
ctx.beginPath()
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
ctx.fillStyle = this.color
ctx.fill()
ctx.closePath()
}
moveLeft() {
this.x -= .01
}
moveRight() {
this.x += .01
}
moveUp() {
this.y -= .01
}
moveDown() {
this.y += .01
}
aw() {
this.x -= .01
this.y -= .01
}
dw() {
this.x += .01
this.y -= .01
}
as() {
this.x -= .01
this.y += .01
}
ds() {
this.x += .01
this.y += .01
}
update() {
this.draw()
window.addEventListener('keydown', (event) => {
switch (event.key) {
case 'a':
this.moveLeft();
break;
case 'd':
this.moveRight();
break;
case 'w':
this.moveUp();
break;
case 's':
this.moveDown();
break;
case 'a' && 'w':
this.aw();
break;
case 'd' && 'w':
this.dw();
break;
case 'a' && 's':
this.as();
break;
case 'd' && 's':
this.ds();
break;
default:
break;
}
});
}
}
And the main file is this
import Bullet from "./bullet.js";
import Player from "./player.js";
import Enemy from "./enemy.js";
import ShatteredEnemy from "./shatteredEnemy.js";
// remove scroolbar
document.getElementById("board").onwheel = function (event) {
event.preventDefault();
};
document.getElementById("board").onmousewheel = function (event) {
event.preventDefault();
};
const modal = document.getElementById("modal")
const scoreElement = document.getElementById('score')
const startButton = document.getElementById('startBtn')
const h1 = document.getElementById('h1') // Modal score
const canvas = document.getElementById('board')
canvas.width = window.innerWidth
canvas.height = window.innerHeight // can be written as ctx.height = innerHeight
export const ctx = canvas.getContext('2d')
const middleX = innerWidth / 2
const middleY = innerHeight / 2
let playerOne = new Player(middleX, middleY, 15, 'white')
playerOne.draw()
let bullets = [] // projectiles
let enemies = []
let shatteredEnemyArray = []
function reset () {
playerOne = new Player(middleX, middleY, 15, 'white')
bullets = []
enemies = []
shatteredEnemyArray = []
score = 0
scoreElement.innerHTML = score
h1.innerHTML = score
}
function spawnEnemy() {
setInterval(() => {
const radius = Math.random() * (30 - 5) + 5
let x, y;
if (Math.random() < 0.5) {
x = Math.random() < 0.5 ? -radius : innerWidth + radius
y = Math.random() * innerHeight
} else {
x = Math.random() * innerWidth
y = Math.random() < 0.5 ? -radius : innerHeight + radius
}
const color = `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`
const angle = Math.atan2(middleY - y, middleX - x)
const velocity = {
y: Math.sin(angle),
x: Math.cos(angle)
}
const enemy = new Enemy(x, y, radius, color, velocity)
enemies.push(enemy)
}, 1500)
}
let animationID
let score = 0
function animate() {
animationID = requestAnimationFrame(animate)
ctx.fillStyle = `rgba(0, 0, 0, 0.2) ` // it is for making shadows on the background
ctx.fillRect(0, 0, innerWidth, innerHeight)
playerOne.update()
shatteredEnemyArray.forEach((shattered, sIdx) => { // if you want to render sth on the screen you must call update() method
if ( shattered.alpha <= 0) {
shatteredEnemyArray.splice(sIdx, 1)
} else {
shattered.update()
}
})
bullets.forEach((bullet, bulletIndex) => {
bullet.update()
// remove bullet if it goes out of bounds
if (bullet.x + bullet.radius < 0 || bullet.x - bullet.radius > innerWidth
|| bullet.y + bullet.radius < 0 || bullet.y - bullet.radius > innerHeight) {
setTimeout(() => {
bullets.splice(bulletIndex, 1)
}, 0)
}
})
enemies.forEach((enemy, eIdx) => {
enemy.update()
const killerDist = Math.hypot(playerOne.x - enemy.x, playerOne.y - enemy.y)
if (killerDist < playerOne.radius + enemy.radius) {
// console.log('you lose')
cancelAnimationFrame(animationID)
modal.style.display = 'flex'
h1.innerHTML = score
startButton.innerHTML = 'Restart'
}
// remove an enemy if it touches a bullet
bullets.forEach((bullet, bIdx) => {
const dist = Math.hypot(bullet.x - enemy.x, bullet.y - enemy.y)
if (dist < enemy.radius + bullet.radius) {
score += Math.floor(enemy.radius)
scoreElement.innerHTML = score
// if the bullet hits the enemy create a shattered enemy
for (let i = 0; i < enemy.radius; i++) {
shatteredEnemyArray.push(
new ShatteredEnemy
(bullet.x,
bullet.y,
Math.random() * 2 + 1,
enemy.color, {
x: (Math.random() - .5) * 5,
y: (Math.random() - .5) * 5
}))
}
if (enemy.radius - 10 > 10) {
gsap.to(enemy, { // for shrinking the enemy
duration: 0.5,
radius: enemy.radius - 10,
ease: 'power2.inOut',
})
setTimeout(() => {
bullets.splice(bIdx, 1)
}, 0)
} else {
setTimeout(() => {
enemies.splice(eIdx, 1)
bullets.splice(bIdx, 1)
}, 0)
}
}
})
})
}
addEventListener('click', (e) => {
const angle = Math.atan2(e.clientY - playerOne.y, e.clientX - playerOne.x)
const velocity = {
x: Math.cos(angle) * 5,
y: Math.sin(angle) * 5
}
const bullet = new Bullet(playerOne.x, playerOne.y, 5,
'wheat', velocity)
bullets.push(bullet)
})
startButton.addEventListener('click', () => {
reset()
animate()
spawnEnemy()
modal.style.display = 'none'
})

Collision detection in my js platformer game. Can't stop the object, but detection works

I'm creating a platformer game, and I'm adding collision, but I'm not sure how to stop the object after collision is detected. This is my javascript, and I have a basic html document with a tag. Could someone help me out with stopping an object after I detect collision? I feel like my solutions I've come up with are much to complicated.
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
const characterImage = document.getElementById('character')
const level = 1
canvas.width = document.body.scrollWidth
canvas.height = document.body.scrollHeight
let time; // Current time
let prevTime = Date.now(); // Store previous time
let isGrounded; // Check if player is on the ground
class Main {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.lives = 3;
this.speedX = 0;
this.speedY = 0;
this.gravity = .01;
// this.gravitySpeed = 0;
this.jumpSpeed = -1.5; // How fast to jump upwards
this.dx = 0;
this.dy = 0;
this.centerX = canvas.width / 2;
this.centerY = canvas.height / 2;
}
draw() {
if (this.x <= -0) {
this.x = -0
}
if (this.x >= canvas.width - 50) {
this.x = canvas.width - 50
}
const player = {
image: characterImage,
x: this.x,
y: this.y,
w: 50,
h: 50
}
const obstacle1 = {
x: this.centerX,
y: canvas.height - 100,
w: 50,
h: 50
}
const lava = {
}
const ground = {
x: 0,
y: canvas.height - 50,
w: canvas.width,
h: 50
}
//collision detection
if (player.x < obstacle1.x + obstacle1.w &&
player.x + obstacle1.w > obstacle1.x &&
player.y < obstacle1.y + obstacle1.h &&
player.y + player.h > obstacle1.y) {
}
ctx.beginPath();
ctx.fillStyle = '#9b7653'
ctx.fillRect(ground.x, ground.y, ground.w, ground.h)
ctx.closePath();
ctx.beginPath();
ctx.drawImage(player.image, player.x, player.y, player.w, player.h);
ctx.closePath();
//obstacles
ctx.beginPath();
ctx.fillStyle = '#df4759'
ctx.fillRect(obstacle1.x, obstacle1.y, obstacle1.w, obstacle1.h);
ctx.closePath();
}
newPos() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
}
update() {
// Calculate how much time has passed since last update
time = Date.now();
const deltaTime = time - prevTime;
// Update y-position based speed in y-direction
// If we jump this.speed will be set to this.jumpSpeed
this.y += this.speedY * deltaTime;
// Gravity should always affect the player!
// The ground check will make sure we don't fall through the floor
this.y += this.gravity * deltaTime;
// Make sure to reduce our player's speed in y by gravity!
this.speedY += this.gravity * deltaTime;
// Only allow the player to jump if he is on the ground
if (controller1.up && isGrounded) {
// Set the player y-speed to jump speed
this.speedY = this.jumpSpeed;
};
if (controller1.right) {
this.dx += 0.7
};
if (controller1.left) {
this.dx -= 0.7
};
this.x += this.dx;
// this.y += this.dy;
this.dx *= 0.9;
this.dy *= 0.9;
// Ground check
if (this.y >= canvas.height - 100) {
this.y = canvas.height - 100;
isGrounded = true;
} else {
isGrounded = false;
}
// Store the current time to use for calculation in next update
prevTime = Date.now();
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp" || e.code == "Space") {
this.up = e.type == 'keydown'
};
if (e.code == "KeyD" || e.code == "ArrowRight") {
this.right = e.type == 'keydown'
};
if (e.code == "KeyA" || e.code == "ArrowLeft") {
this.left = e.type == 'keydown'
};
}
addEventListener('keydown', keyEvent);
addEventListener('keyup', keyEvent);
addEventListener('mousemove', keyEvent)
}
}
let main1 = new Main(50, canvas.height - 150, 50, 50)
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
main1.update();
main1.draw();
requestAnimationFrame(animate)
}
function updatePos() {
main1.newPos();
}
animate()
setInterval(updatePos, 10)
<canvas id="canvas"></canvas>
<img src="http://placekitten.com/50/50" id="character" style="display: none">
It looks like your code has two sets of velocities for the character: this.speedY gives the vertical velocity from jumping, and this.dx gives the horizontal velocity from controller input, while this.dy isn't actually used. So if you want the character to stop from a collision, you could use something like this:
if (player.x < obstacle1.x + obstacle1.w &&
player.x + obstacle1.w > obstacle1.x &&
player.y < obstacle1.y + obstacle1.h &&
player.y + player.h > obstacle1.y) {
this.dx = this.speedY = 0;
}
You probably want to unify the velocities into one pair of values, e.g. this.dx and this.dy, and adjust either when the player's velocity changes (from any action or gravity).
If you want to disable certain actions while the player is colliding, you might want to set a variable that you can use in the update() function. For example:
this.isColliding =
player.x < obstacle1.x + obstacle1.w &&
player.x + obstacle1.w > obstacle1.x &&
player.y < obstacle1.y + obstacle1.h &&
player.y + player.h > obstacle1.y;
if (this.isColliding) {
this.dx = this.speedY = 0;
}
As another note, prevTime and isGrounded should really be properties of the class (this.prevTime, etc.), not global variables. And time could be declared local to update(), as it's not needed otherwise.
Collision detection in this way is not as simple as a single block of code. This is a good start to determine if the objects do collide but you will then need to pass that information to another function to handle the actions that should be taken based on the side of the collision. This is refered to as 'broad phase' and 'narrow phase'.
Note that there's is no, one perfect formula that handles every rectangle CD. You may find yourself needing to alter your main function to handle specific object within the game at some point because they have different properties.
Now I will provide you with a working example here using your code but I must highly recommend you don't continue piling all of your game objects into one class like you are doing. This is already making things difficult and will only make your game more complicated in the long run. You should break out you obstacles, lava, ground etc and give each their own class. I also notice that you are trying to put all of your CD into the class. This is sometimes ok but for what you are currently trying to accomplish I would have separate functions.
You'll notice in this snippet that the player actually enters into the ground a bit and the obstacles before going back to it's spot. The code overall is a bit finicky because of how it's written.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const characterImage = document.getElementById("character");
const level = 1;
canvas.width = document.body.scrollWidth;
canvas.height = 400//document.body.scrollHeight
let time; // Current time
let prevTime = Date.now(); // Store previous time
let player, obstacle1, obstacle2, ground;
class Main {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.lives = 3;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.01;
this.jumping = false;
//this.gravitySpeed = 0;
this.jumpSpeed = -1.5; // How fast to jump upwards
this.dx = 0;
this.dy = 0;
this.centerX = canvas.width / 2;
this.centerY = canvas.height / 2;
}
draw() {
if (this.x <= -0) {
this.x = -0;
}
if (this.x >= canvas.width - 50) {
this.x = canvas.width - 50;
}
player = {
image: characterImage,
x: this.x,
y: this.y,
w: 50,
h: 50
};
obstacle1 = {
x: this.centerX,
y: canvas.height - 100,
w: 50,
h: 50
};
obstacle2 = {
x: this.centerX + 50,
y: canvas.height - 100,
w: 50,
h: 50
};
const lava = {};
ground = {
x: 0,
y: canvas.height - 50,
w: canvas.width,
h: 50
};
ctx.beginPath();
ctx.fillStyle = "#9b7653";
ctx.fillRect(ground.x, ground.y, ground.w, ground.h);
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "pink";
ctx.fillRect(player.x, player.y, player.w, player.h);
ctx.closePath();
//obstacles
ctx.beginPath();
ctx.fillStyle = "#df4759";
ctx.fillRect(obstacle1.x, obstacle1.y, obstacle1.w, obstacle1.h);
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#df4759";
ctx.fillRect(obstacle2.x, obstacle2.y, obstacle2.w, obstacle2.h);
ctx.closePath();
}
newPos() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
}
update() {
// Calculate how much time has passed since last update
time = Date.now();
const deltaTime = time - prevTime;
if (controller1.up && !this.jumping) {
// Set the player y-speed to jump speed
this.speedY = this.jumpSpeed;
this.jumping = true; //prevents jumping while already in air
}
if (controller1.right) {
this.dx += 0.7;
}
if (controller1.left) {
this.dx -= 0.7;
}
this.y += this.speedY * deltaTime;
this.y += this.gravity * deltaTime;
this.speedY += this.gravity * deltaTime;
this.x += this.dx;
// this.y += this.dy;
this.dx *= 0.9;
this.dy *= 0.9;
// Store the current time to use for calculation in next update
prevTime = Date.now();
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp" || e.code == "Space") {
this.up = e.type == "keydown";
}
if (e.code == "KeyD" || e.code == "ArrowRight") {
this.right = e.type == "keydown";
}
if (e.code == "KeyA" || e.code == "ArrowLeft") {
this.left = e.type == "keydown";
}
};
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
addEventListener("mousemove", keyEvent);
}
}
function collision(player, obj) {
if (
player.x + player.w < obj.x ||
player.x > obj.x + obj.w ||
player.y + player.h < obj.y ||
player.y > obj.y + obj.h
) {
return;
}
this.narrowPhase(player, obj);
}
function narrowPhase(player, obj) {
let playerTop_ObjBottom = Math.abs(player.y - (obj.y + obj.h));
let playerRight_ObjLeft = Math.abs(player.x + player.w - obj.x);
let playerLeft_ObjRight = Math.abs(player.x - (obj.x + obj.w));
let playerBottom_ObjTop = Math.abs(player.y + player.h - obj.y);
if (
player.y <= obj.y + obj.h &&
player.y + player.h > obj.y + obj.h &&
playerTop_ObjBottom < playerRight_ObjLeft &&
playerTop_ObjBottom < playerLeft_ObjRight
) {
main1.y = obj.y + obj.h;
main1.speedY = 0;
}
if (
player.y + player.h >= obj.y &&
player.y < obj.y &&
playerBottom_ObjTop < playerRight_ObjLeft &&
playerBottom_ObjTop < playerLeft_ObjRight
) {
main1.y = obj.y - player.h - 0.05;
main1.speedY = 0;
main1.jumping = false;
}
if (
player.x + player.w >= obj.x &&
player.x < obj.x &&
playerRight_ObjLeft < playerTop_ObjBottom &&
playerRight_ObjLeft < playerBottom_ObjTop
) {
main1.x = obj.x - obj.w - 0.05;
main1.dx = 0;
}
if (
player.x <= obj.x + obj.w &&
player.x + player.w > obj.x + obj.w &&
playerLeft_ObjRight < playerTop_ObjBottom &&
playerLeft_ObjRight < playerBottom_ObjTop
) {
main1.x = obj.x + obj.w + 0.05;
main1.dx = 0;
}
}
let main1 = new Main(50, canvas.height - 250, 50, 50);
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
main1.draw();
main1.update();
collision(player, obstacle2);
collision(player, obstacle1);
collision(player, ground);
requestAnimationFrame(animate);
}
function updatePos() {
main1.newPos();
}
animate();
setInterval(updatePos, 10);
<canvas id="canvas"></canvas>
I'm going to provide a second example where I've removed the objects from the main class and made each there own. I also removed the dx and dy as I think there was confusion about those and mixing them with speedX and speedY. On another note in your newPos() function you have this.x += this.speedX; but you also have that in the update function so in reality your are doubling it. I don't think that;s what you wanted.
You'll see in this example the collision is much smoother
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const characterImage = document.getElementById("character");
const level = 1;
canvas.width = document.body.scrollWidth;
canvas.height = 400//document.body.scrollHeight
let time; // Current time
let prevTime = Date.now(); // Store previous time
class Entity {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.lives = 3;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.01;
this.jump = false;
this.jumpSpeed = -1.5; // How fast to jump upwards
this.centerX = canvas.width / 2;
this.centerY = canvas.height / 2;
}
draw() {
ctx.beginPath();
ctx.fillStyle = "pink";
ctx.fillRect(player.x, player.y, player.w, player.h);
ctx.closePath();
}
newPos() {
this.gravitySpeed += this.gravity;
//this.x += this.speedX;
}
collision() {
if (this.x <= -0) {
this.x = -0;
}
if (this.x >= canvas.width - 50) {
this.x = canvas.width - 50;
}
}
update() {
// Calculate how much time has passed since last update
time = Date.now();
const deltaTime = time - prevTime;
if (controller1.up && !this.jump) {
this.speedY = this.jumpSpeed;
this.jump = true;
}
if (controller1.right) {
this.speedX += 0.7;
}
if (controller1.left) {
this.speedX -= 0.7;
}
this.y += this.speedY * deltaTime;
this.y += this.gravity * deltaTime;
this.speedY += this.gravity * deltaTime;
this.x += this.speedX;
this.speedX *= 0.9;
this.speedY *= 0.9;
// Store the current time to use for calculation in next update
prevTime = Date.now();
}
}
class Obstacle {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = '#df4759';
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
/*
class Lava {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = 'red';
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
*/
class Ground {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = '#8a6c4e';
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp" || e.code == "Space") {
this.up = e.type == "keydown";
}
if (e.code == "KeyD" || e.code == "ArrowRight") {
this.right = e.type == "keydown";
}
if (e.code == "KeyA" || e.code == "ArrowLeft") {
this.left = e.type == "keydown";
}
};
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
addEventListener("mousemove", keyEvent);
}
}
function collision(player, obj) {
if (
player.x + player.w < obj.x ||
player.x > obj.x + obj.w ||
player.y + player.h < obj.y ||
player.y > obj.y + obj.h
) {
return;
}
this.narrowPhase(player, obj);
}
function narrowPhase(player, obj) {
let playerTop_ObjBottom = Math.abs(player.y - (obj.y + obj.h));
let playerRight_ObjLeft = Math.abs(player.x + player.w - obj.x);
let playerLeft_ObjRight = Math.abs(player.x - (obj.x + obj.w));
let playerBottom_ObjTop = Math.abs(player.y + player.h - obj.y);
if (
player.y <= obj.y + obj.h &&
player.y + player.h > obj.y + obj.h &&
playerTop_ObjBottom < playerRight_ObjLeft &&
playerTop_ObjBottom < playerLeft_ObjRight
) {
player.y = obj.y + obj.h;
player.speedY = 0;
}
if (
player.y + player.h >= obj.y &&
player.y < obj.y &&
playerBottom_ObjTop < playerRight_ObjLeft &&
playerBottom_ObjTop < playerLeft_ObjRight
) {
player.y = obj.y - player.h;
// player.dy = 0;
player.speedY = 0;
player.jump = false;
}
if (
player.x + player.w >= obj.x &&
player.x < obj.x &&
playerRight_ObjLeft < playerTop_ObjBottom &&
playerRight_ObjLeft < playerBottom_ObjTop
) {
player.x = obj.x - obj.w;
player.speedX = 0;
}
if (
player.x <= obj.x + obj.w &&
player.x + player.w > obj.x + obj.w &&
playerLeft_ObjRight < playerTop_ObjBottom &&
playerLeft_ObjRight < playerBottom_ObjTop
) {
player.x = obj.x + obj.w;
player.speedX = 0;
}
}
let obstacle1 = new Obstacle(canvas.width/2, canvas.height - 100, 50, 50)
let obstacle2 = new Obstacle(canvas.width/2 + 50, canvas.height - 100, 50, 50)
let ground = new Ground(0, canvas.height - 50, canvas.width, 50)
let player = new Entity(50, canvas.height - 250, 50, 50);
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
collision(player, obstacle2);
collision(player, obstacle1);
collision(player, ground);
player.draw();
player.update();
ground.draw();
obstacle1.draw();
obstacle2.draw();
requestAnimationFrame(animate);
}
function updatePos() {
player.newPos();
}
animate();
setInterval(updatePos, 10);
<canvas id="canvas"></canvas>

Refers to a global variable while encapsulated one is available

In case below "player" referring to global variables, that breaks OOP principle of encapsulation. Whatever I need from the global scope pass to the class instance via constructor. How can I did it?
If I create parent variable (some Character), than code will not work. Maybe this is a nube question, but I don't know, how it works.
p.s. - when I take "player" in "Enemy" thought "this", all construction breaks down.
var Enemy = function(x, y, speed, player) {
this.x = x;
this.y = y;
this.speed = speed;
this.sprite = 'images/enemy-bug.png';
this.player = player;
};
Enemy.prototype.update = function(dt) {
this.x += +(this.speed * dt);
if (this.x > canvasWidth) {
this.x = borgSpawn;
this.speed = Math.floor(100 + Math.random() * 200);
}
if (
player.x > this.x - enemySize &&
player.x < this.x + enemySize &&
player.y > this.y - enemySize &&
player.y < this.y + enemySize
) {
player.x = playerSpawnX;
player.y = playerSpawnY;
}
};
Enemy.prototype.render = function() {
ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};
var enemyLocation = [60, 140, 220];
var allEnemies = enemyLocation.map(y => new Enemy(0, y, 300, player));
var Player = function(x, y) {
this.x = x;
this.y = y;
this.sprite = 'images/char-boy.png';
};
Player.prototype.update = function() {
if (this.y < 60) {
this.x = playerSpawnX;
this.y = playerSpawnY;
}
};
Player.prototype.render = function() {
ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};
Player.prototype.handleInput = function(key) {
if (key === 'left' && this.x > 0) {
this.x = this.x - horizontalStep;
} else if (key === 'right' && this.x != stepZone) {
this.x = this.x + horizontalStep;
} else if (key === 'up') {
this.y = this.y - verticalStep;
} else if (key === 'down' && this.y != stepZone) {
this.y = this.y + verticalStep;
}
};
var player = new Player(playerSpawnX, playerSpawnY);
document.addEventListener('keyup', function(e) {
var allowedKeys = {
37: 'left',
38: 'up',
39: 'right',
40: 'down'
};
player.handleInput(allowedKeys[e.keyCode]);
});
No need to pass "player" parameter to "enemy" object. Your Enemy.prototype.update function will work fine without this reference.

Pong game my ball keep going above colisions

i have a simple pong game where i can shot the ball and check for colisions at the moment. I had the colisions with X and Y working, but since i added angles to the ball trajectory the colisions at X coordinate sometimes fail, dunno why. So this is what i have at the moment, the colisions checking is handled by the ballMovementHandler function.
var canvas;
var ctx;
var player;
var ball;
var gameStarted;
var flagY;
var flagX;
var angle;
function init() {
canvas = document.getElementById('myCanvas')
if (canvas.getContext) {
ctx = canvas.getContext('2d')
setCanvasSize(ctx)
player = new Player()
ball = new Ball()
attachKeyboardListeners()
reset();
animate();
}
}
function reset() {
flagX = -1;
flagY = -1;
angle = 90;
gameStarted = false
player = new Player();
ball = new Ball();
}
function animate () {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
drawIce()
player.drawPlayer();
ball.drawBall();
playerMovementeHandler()
if(gameStarted) {
ballMovementHandler();
}
window.requestAnimationFrame(animate);
}
function playerMovementeHandler() {
if(player.left === true) {
if(player.x > 0) {
player.movePlayer(-SPEED);
if(!gameStarted) {
ball.moveBallWithPlayer(-SPEED);
}
}
}
if(player.right === true) {
if(player.x + player.width < ctx.canvas.width) {
player.movePlayer(SPEED);
if(!gameStarted) {
ball.moveBallWithPlayer(SPEED);
}
}
}
}
function ballMovementHandler() {
if(ball.y - ball.radius <= 0) {
flagY = 1;
}
if(ball.y + ball.radius === player.y) {
if(ball.x + ball.radius >= player.x && ball.x < player.x + player.width) {
angle = playerAngleHandler()
flagY = -1;
}
else {
reset();
}
}
if(ball.x - ball.radius <= 0) {
flagX = 1;
}
if(ball.x + ball.radius >= ctx.canvas.width) {
flagX = -1;
}
radians = angle * Math.PI/ 180;
ball.moveBallY(Math.sin(radians) * ball.speed * flagY);
ball.moveBallX(Math.cos(radians) * ball.speed * flagX);
}
function playerAngleHandler() {
var angle = 90;
if(ball.x + ball.radius <= player.x + 25) {
angle = 35;
} else if(ball.x + ball.radius >= player.x + player.width - 25) {
angle = 135;
} else if(ball.x + ball.radius >= player.x + player.width - 50) {
angle = 120
} else if(ball.x + ball.radius <= player.x + 50 ) {
angle = 50;
} else if(ball.x + ball.radius <= player.x + 75) {
angle = 75;
} else if( ball.x + ball.radius >= player.x + player.width - 75 ) {
angle = 100;
}
return angle;
}
function drawIce() {
ctx.fillStyle = 'rgb(134,214,216)'
ctx.fillRect(0,ctx.canvas.height - Y_OFFSET + player.height + 10, ctx.canvas.width, Y_OFFSET)
}
function setCanvasSize() {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
}
function keyboardEvent(keyCode, keyStatus) {
switch(keyCode) {
case 37:
player.left = keyStatus;
break;
case 39:
player.right = keyStatus;
break;
case 32:
gameStarted = true;
break;
}
}
function attachKeyboardListeners() {
document.addEventListener('keydown', function(e) {
keyboardEvent(e.keyCode, true)
})
document.addEventListener('keyup', function(e) {
keyboardEvent(e.keyCode, false)
})
}
init();
ball.js
// defines player configuration behaviour
const BALL_POSITION_Y = 100;
const RADIUS = 12;
const BALL_SPEED = 10;
function Ball(x = ctx.canvas.width/2, y = ctx.canvas.height - Y_OFFSET - RADIUS, radius = RADIUS, color = 'rgb(100,149,237)', speed = BALL_SPEED) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.speed = speed;
this.drawBall = function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,2*Math.PI);
ctx.fill();
}
// for inital game started
this.moveBallWithPlayer = function(deltaX) {
this.x += deltaX;
}
this.moveBallY = function(flag) {
this.y = this.y + flag;
}
this.moveBallX = function(flag) {
this.x = this.x + flag;
}
}
player.js
// defines player configuration behaviour
const PLAYER_WIDTH = 200;
const Y_OFFSET = 100;
const PLAYER_HEIGHT = 30;
const SPEED = 6;
function Player(x = ctx.canvas.width/2 - PLAYER_WIDTH/2, y = ctx.canvas.height - Y_OFFSET, width = PLAYER_WIDTH, height = PLAYER_HEIGHT, color = 'rgba(0,0,0)') {
this.left = false;
this.right = false;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.movePlayer = function(deltaX) {
this.x += deltaX;
}
this.drawPlayer = function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}

JavaScript - moving object to a new location

I'm writing simple "snake" game and I'm facing this issue:
every tame my snake hits the red circle (apple) , apple should be moved to a new location on the canvas. Right now new apple appears, but the old one does not disappear ( it should) , and also when there are more than 2 apples on the canvas they create a filled figure... it looks like this: ibb.co/nrYdLQ (also shouldn't happen).
The code responsible for moving an apple is this:
if (!this.objectCollide(myApple)) {
this.segments.pop();
} else {
myApple = new block(Math.floor(Math.random() * gameField.width),Math.floor(Math.random() * gameField.height))
};
and I have no idea why It's working like I described above, instead just moving an apple to a new location and removing old one.
Please help.
JSFiddle: https://jsfiddle.net/e1ga0fpm/
full JavaScript code:
var gameField = document.getElementById('gameField');
var ctx = gameField.getContext("2d");
var blockSize = 10;
columnCt = gameField.width / blockSize;
rowsCt = gameField.height / blockSize;
var block = function(x, y) {
this.x = x;
this.y = y;
}
block.prototype.drawBlock = function() {
ctx.fillStyle = "blue";
ctx.fillRect(this.x * blockSize, this.y * blockSize, blockSize,
blockSize);
};
block.prototype.drawApple = function() {
ctx.fillStyle = "red";
ctx.textBaseline = "bottom";
ctx.arc(this.x, this.y, 6, 2 * Math.PI, false);
ctx.fill();
}
var Snake = function() {
this.segments = [new block(20, 20), new block(19, 20), new block(18, 20), new block(17, 20),
new block(16, 20), new block(15, 20), new block(14, 20), new block(13, 20), new block(12, 20),
new block(11, 20), new block(10, 20)
];
this.direction = "right";
}
Snake.prototype.drawSnake = function() {
for (i = 0; i < this.segments.length; i++) {
this.segments[i].drawBlock();
}
}
Snake.prototype.setDirection = function(dir) {
if (this.direction == "left" && dir == "right" || this.direction == "right" && dir == "left" || this.direction == "up" && dir == "down" ||
this.direction == "down" && dir == "up") {
return
} else {
this.direction = dir;
};
};
Snake.prototype.objectCollide = function(obj) {
if (this.segments[0].x == Math.round(obj.x / blockSize) && this.segments[0].y == Math.round(obj.y / blockSize)) {
return true
} else {
return false
}
};
Snake.prototype.move = function() {
var head = this.segments[0];
var newHead;
switch (this.direction) {
case "right":
newHead = new block(head.x + 1, head.y);
break;
case "left":
newHead = new block(head.x - 1, head.y)
break;
case "down":
newHead = new block(head.x, head.y + 1)
break;
case "up":
newHead = new block(head.x, head.y - 1)
break;
}
this.segments.unshift(newHead);
if (!this.objectCollide(myApple)) {
this.segments.pop();
} else {
myApple = new block(Math.floor(Math.random() * gameField.width),Math.floor(Math.random() * gameField.height))
};
var collision = newHead.x >= columnCt || newHead.x <= -1 ||
newHead.y >= rowsCt || newHead.y <= -1;
for (i = 1; i < this.segments.length; i++) {
if (this.segments[i].x == newHead.x && this.segments[i].y == newHead.y) {
collision = true;
break;
};
};
if (collision) {
clearInterval(myFun);
};
};
var mySnake = new Snake()
mySnake.drawSnake();
var myApple = new block(Math.floor(Math.random() * gameField.width),
Math.floor(Math.random() * gameField.height));
var myFun = setInterval(function() {
ctx.clearRect(0, 0, gameField.width, gameField.height);
mySnake.move();
mySnake.drawSnake();
myApple.drawApple();
}, 100)
var directions = {
37: "left",
38: "up",
39: "right",
40: "down"
};
document.onkeydown = function(event) {
var newDirection = directions[event.keyCode]
if (newDirection != undefined) {
mySnake.setDirection(newDirection);
};
Im quite unshure why the apple is not "eaten" however, i might know why it looks so weird:
If you draw to a canvas it looks like a pen. So whenever you draw a new apple, the pen moves to that position, and draws a line. After a few apples, if you call .fill(), this (yet invisible) line, gets filled. So you need to move the pen before you draw:
block.prototype.drawApple = function() {
ctx.fillStyle = "red";
ctx.textBaseline = "bottom";
ctx.moveTo(this.x,this.y);
ctx.arc(this.x, this.y, 6, 2 * Math.PI, false);
ctx.fill();
}
You forgot to beginpath while you draw apple. Also when apple eaten, you have to add new block to snake. Check edited code below.
Here is updated fiddle
block.prototype.drawApple = function() {
ctx.fillStyle = "red";
ctx.textBaseline = "bottom";
ctx.beginPath();
ctx.arc(this.x, this.y, 6, 2 * Math.PI, false);
ctx.fill();
}
var gameField = document.getElementById('gameField');
var ctx = gameField.getContext("2d");
var blockSize = 10;
columnCt = gameField.width / blockSize;
rowsCt = gameField.height / blockSize;
var block = function(x, y) {
this.x = x;
this.y = y;
}
block.prototype.drawBlock = function() {
ctx.fillStyle = "blue";
ctx.fillRect(this.x * blockSize, this.y * blockSize, blockSize,
blockSize);
};
block.prototype.drawApple = function() {
ctx.fillStyle = "red";
ctx.textBaseline = "bottom";
ctx.beginPath();
ctx.arc(this.x, this.y, 6, 2 * Math.PI, false);
ctx.fill();
}
var Snake = function() {
this.segments = [new block(20, 20), new block(19, 20), new block(18, 20), new block(17, 20),
new block(16, 20), new block(15, 20)
];
this.direction = "right";
}
Snake.prototype.drawSnake = function() {
for (i = 0; i < this.segments.length; i++) {
this.segments[i].drawBlock();
}
}
Snake.prototype.setDirection = function(dir) {
if (this.direction == "left" && dir == "right" || this.direction == "right" && dir == "left" || this.direction == "up" && dir == "down" ||
this.direction == "down" && dir == "up") {
return
} else {
this.direction = dir;
};
};
Snake.prototype.objectCollide = function(obj) {
if (this.segments[0].x == Math.round(obj.x / blockSize) && this.segments[0].y == Math.round(obj.y / blockSize)) {
return true
} else {
return false
}
};
Snake.prototype.move = function() {
var head = this.segments[0];
var newHead;
switch (this.direction) {
case "right":
newHead = new block(head.x + 1, head.y);
break;
case "left":
newHead = new block(head.x - 1, head.y)
break;
case "down":
newHead = new block(head.x, head.y + 1)
break;
case "up":
newHead = new block(head.x, head.y - 1)
break;
}
this.segments.unshift(newHead);
if (!this.objectCollide(myApple)) {
this.segments.pop();
} else {
myApple = new block(Math.floor(Math.random() * gameField.width), Math.floor(Math.random() * gameField.height));
this.segments.push(new block(this.segments[0][0], 20))
};
var collision = newHead.x >= columnCt || newHead.x <= -1 ||
newHead.y >= rowsCt || newHead.y <= -1;
for (i = 1; i < this.segments.length; i++) {
if (this.segments[i].x == newHead.x && this.segments[i].y == newHead.y) {
collision = true;
break;
};
};
if (collision) {
clearInterval(myFun);
};
};
var mySnake = new Snake()
mySnake.drawSnake();
var myApple = new block(Math.floor(Math.random() * gameField.width),
Math.floor(Math.random() * gameField.height));
var myFun = setInterval(function() {
ctx.clearRect(0, 0, gameField.width, gameField.height);
mySnake.move();
mySnake.drawSnake();
myApple.drawApple();
}, 100)
var directions = {
37: "left",
38: "up",
39: "right",
40: "down"
};
document.onkeydown = function(event) {
var newDirection = directions[event.keyCode]
if (newDirection != undefined) {
mySnake.setDirection(newDirection);
};
};
canvas {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
border: 5px solid grey;
}
<canvas id="gameField" height="500" width="500">
</canvas>

Categories

Resources