learning js/jquery trying to create a start button - javascript

Taking a class on js/jquery and the game works fine but you have to refresh the page to restart it. I'm trying to create a button and have it "restart the game" but I just can't get it to work.
Any help/resources/advice would be appreciated thanks!!!
index.html:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src='https://code.jquery.com/jquery-2.1.3.js'></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src='js/script.js'></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="row-md-6 row-md-offset-3">
<h1>The Snake Game!!</h1>
<canvas class='snake-game' width ='600px' height='500px'></canvas>
<button type='button' class='start'>Start Game</button>
</div>
</div>
</div>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
js/jquery
jQuery(document).ready(function(){
var snakeCanvas = $('canvas.snake-game')[0],
context = snakeCanvas.getContext('2d'),
width = snakeCanvas.width,
height = snakeCanvas.height,
snakeSize = 10,
snake = [
{ 'x': 0,'y': 0 },
{ 'x': 1, 'y': 0 },
{ 'x': 2, 'y': 0 },
{ 'x': 3, 'y': 0 },
{ 'x': 4, 'y': 0 },
],
direction = 'right',
gameSpeed = 50,
score = 0;
var foodX,
foodY,
gameLoop
start();
$('.start')on('click', function(){
start();
})
function createNewFood(){
foodX = parseInt(Math.random() * width/snakeSize);
foodY = parseInt(Math.random() * yeah itheight/snakeSize);
}
function checkCollision(snakeArrayInput, foodXinput, foodYinput){
var collision = 'nothing';
snakeArrayInput.every(function(element){
if(element.x == foodXinput && element.y == foodYinput){
collision = "food";
return false;
}else if(element.x == -1 ||
element.y == -1 ||
element.x == width/snakeSize ||
element.y == height/snakeSize){
collision = "wall";
return false;
}else{
return true;
}
});
return collision;
}
paint(0, 0, width, height, 'white', 'black');
function start(){
createNewFood();
gameLoop = setInterval(reDraw, gameSpeed);
}
function stop(){
clearInterval(gameLoop);
}
function reDraw(){
drawBg();
drawSnake(snake);
drawFood();
drawScore();
//checkCollision(snakeArrayInput, foodXinput, foodYinput);
var collisionStatus = checkCollision(snake, foodX, foodY);
if(collisionStatus == 'food'){
score ++;
createNewFood();
snake.unshift(updateDirection(snake, direction));
} else if (collisionStatus == 'wall'){
stop();
alert('Your score was: ' + score);
score = 0;
}
};
function drawFood(){
paint(foodX*snakeSize, foodY*snakeSize, snakeSize, snakeSize, 'green', 'black');
}
function drawScore(){
context.fillStyle = 'grey';
context.fillText('Score: ' + score, width-596, height-6);
}
function drawBg(){
paint(0,0,width, height, 'white', 'black');
}
function drawSnake(snakeInput){
updateSnake(snakeInput);
snakeInput.forEach(function(element){
paint(element.x*10, element.y*10, snakeSize, snakeSize, 'orange', 'black');
});
}
function paint(x, y, w, h, bgColor, borderColor){
context.fillStyle = bgColor;
context.fillRect(x, y, w, h);
context.strokeStyle = borderColor;
context.strokeRect(x, y, w, h);
}
function updateSnake(snakeInput){
snakeInput.shift();
snakeInput.push(updateDirection(snakeInput, direction));
}
function updateDirection(snakeInput, direction){
var cellX = snakeInput[snakeInput.length-1].x;
var cellY = snakeInput[snakeInput.length-1].y;
if(direction == 'right'){
cellX = cellX + 1;
} else if (direction == 'left') {
cellX = cellX - 1;
} else if (direction == 'top') {
cellY = cellY - 1;
} else if (direction == 'bottom') {
cellY = cellY + 1;
}
return {'x':cellX, 'y':cellY};
}
$(document).on('keydown', function(e){
if(e.which == '37' && direction != 'right'){ // left keydown
direction = 'left';
}else if(e.which == '38' && direction != 'bottom'){ // top keydown
direction = 'top';
}else if(e.which == '39' && direction != 'left'){ // right keydown
direction = 'right';
}else if(e.which == '40' && direction != 'top'){ // bottom keydown
direction = 'bottom';
}
});
});

$('.start')on('click', function(){
start();
})
Missing dot, change to $('.start').on('click', function(){
function createNewFood(){
foodX = parseInt(Math.random() * width/snakeSize);
foodY = parseInt(Math.random() * yeah itheight/snakeSize);
}
Change foodY = parseInt(Math.random() * yeah itheight/snakeSize); to
foodY = parseInt(Math.random() * height/snakeSize);
Edit: So if you want start game to set to a playable state, you need to reinit your game parameters, here's the changes:
function start(){
// Set init states.
snakeSize = 10,
snake = [
{ 'x': 0,'y': 0 },
{ 'x': 1, 'y': 0 },
{ 'x': 2, 'y': 0 },
{ 'x': 3, 'y': 0 },
{ 'x': 4, 'y': 0 },
],
direction = 'right',
gameSpeed = 50,
score = 0;
createNewFood();
gameLoop = setInterval(reDraw, gameSpeed);
}
Fixed it, and that works, and start game DO restart a playable game.
JsFiddle

Related

How do I correctly add collisions between a player and wall in JavaScript Canvas

I've made a codepen in order to better explain my situation.
https://codepen.io/kennyfully1988/pen/yLqpBVp
I'm working on a game where the player collects apples. The collision is working correctly when a player touches an apple. (The player will get 1 point and the apple will be erased from the apples array).
What I'm confused about is the following function
checkSolidCollisions(walls) {
// check to see if player is colliding with walls
for (let i = 0; i < walls.length; i++) {
if (
this.dx <= walls[i].x + walls[i].width &&
this.dx + this.dw >= walls[i].x &&
this.dy <= walls[i].y + walls[i].height &&
this.dy + this.dh >= walls[i].y
) {
console.log(true);
return true;
}
}
return false;
}
I created this function hoping that this will be a check to see if the player is in collision with a wall (the wall array). However, it doesn't seem to work at all. I'm willing to provide as much information as needed in order to solve this problem. I want you all to know that this is OOP JavaScript.
So, what I tried to do is make the player not be able to pass the wall. However, the player always passes the wall.
In your example the
this.dx + this.dw >= walls[i].x
criteria proved to be problematic, because the right edge of the character is not to the right of the wall. A good way to check algorithmically is as follows:
checkSolidCollisions(walls) {
// check to see if player is colliding with walls
for (let i = 0; i < walls.length; i++) {
if (
!((this.dx + this.dw < walls[i].x) || (walls[i].x + walls[i].width < this.dx)) &&
!((this.dy + this.dh < walls[i].y) || (walls[i].y + walls[i].height < this.dy))
) {
console.log(true);
return true;
}
}
return false;
}
To summarize:
it is not true that
rectangle1 is to the left of rectangle2
or rectangle2 is to the left of rectangle1
and it is not true that
rectangle1 is above rectangle2
or rectangle2 is above rectangle1
So after a long time of testing everything out and rebuilding samples, I noticed what I did wrong. I didn't write the proper logic to see what happens after the player collides with the wall, such as pushing the player back into a safer position after the collision.
// Working code
'use strict';
window.onload = () => {
const gameBox = document.querySelector('.game-box');
const ctx = gameBox.getContext('2d');
const collisionCheckerLabel = document.querySelector(
'.collision-checker-label',
);
let collisionChecker = false;
const playerImage = new Image();
playerImage.src =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAApNJREFUeJztm7FuwjAQhg/Eg4QwsDEFiYGVZ2DhPXgG3oOl6iN0zVApnbpVqC0rb9Ahwh2QLcfY8V0S20W9fwGj5D7f1Q253wEgoPKsEHlWiJCMvhphDtKT+Dq/oc/5eB8DAMB8cSWdR2X10QQzGZkIAMB8UQjsxOaLK2kyetEkC4BWiLYVZ4tjDWwmricScwWYfF8Mk2m+t83jLqAZBAP2JdI3BqWQg64ATIC2iXRZAUPxsWoElOCnl1frwdvNCjWRrgmk4KsP8qwQErzdrBqTsI1twfokkJSfZ4WoTrWoTrXIs0IIIYT8zBxXp1o8lz933+9mDPneNf4r/DFYNJsuW8e2yut/vc/vSlXbHAMAHI5l68UqJv+uADKQ6/V8qVsn0yWBlPwxwO1/Qq+QXk05Pl9qBd/v1s4LUZcEUvK93wL6CfvdWk3YBOvLUEq/eJlxsBex0PxB7wP6JJCKH6TZiHkj8xf5LCn2A9gPYD9Anc9+APsB7Ac8jh/gU2g/ICZ/RIUD3G4vzfv5Pgmk5Fv9AKqoCfj8gJh8cgEw/XhIDc23+gEuMKYf9wnjB8TkB/UDXOBYfgCGz35AW8CuSt2Pp+azpNgPYD+A/QB1PvsB7AewH/BYfoC5J29OJLQfEItv9QPklvJsurQGw/TjlARS8p3tMGVL25WAq8PD+AGx+I0CbDerRuVc1ceIkkBK/gRA9eONKppwTDur7+e7lmCLH5CEz36A7WD2A3oqdT+ems+SYj+A/QD2A9T57AewH8B+wGP5ASY45u8FYvK9zwfYenPq/rwvgZR81PY45Xl9VwKU3wvE5HsLoPfmsl+nqos3EIuPej5APq9/OJZwOJak/XlMAin5/8YP0GOxH8B+AEvpF88gNOQKrAefAAAAAElFTkSuQmCC';
class Player {
constructor(config) {
this._rng = String(Math.floor(Math.random() * 100)).padEnd(3, '0'); // random number generator
this._id = `player_${new Date().getTime()}${this._rng}`; // generated id
this.image = playerImage;
this.currentFrame = 1; // helper variable to help with requestAnimationFrame()
this.totalFps = 60; // helper variable to help with requestAnimationFrame()
this.totalImageFrames = 4; // the number of frames in the sprite
this.sx = config?.sx || 0; // source x position
this.sy = config?.sy || 0; // source y position
this.sw = config?.sw || 16; // source width
this.sh = config?.sh || 16; // source height
this.dx = config?.dx || 0; //destination x position
this.dy = config?.dy || 0; //destination y position
this.dw = config?.dw || 16; //destination width
this.dh = config?.dh || 16; //destination height
this.animation = config?.animation || 0; // lazy way to play animations
this.movement = config?.movement || 'idle'; // player movement
window.addEventListener('keydown', (e) => {
e.preventDefault();
if (e.key === 'ArrowUp') {
this.movement = 'up';
} else if (e.key === 'ArrowDown') {
this.movement = 'down';
} else if (e.key === 'ArrowLeft') {
this.movement = 'left';
} else if (e.key === 'ArrowRight') {
this.movement = 'right';
} else {
this.movement = '';
}
});
window.addEventListener('keyup', (e) => {
e.preventDefault();
this.movement = 'idle';
});
}
render(ctx) {
ctx.drawImage(
this.image,
Math.floor(
this.currentFrame / (this.totalFps / this.totalImageFrames),
) * 16,
this.animation * 16,
this.sw,
this.sh,
this.dx,
this.dy,
this.dw,
this.dh,
);
}
update(ctx) {
// player animation
if (this.currentFrame >= this.totalFps - 1) {
this.currentFrame = 1;
} else {
this.currentFrame++;
}
// player movement
if (this.movement === 'up') {
this.animation = 1;
if (this.dy <= 0) return;
this.dy--;
} else if (this.movement === 'down') {
this.animation = 0;
if (this.dy + 16 >= ctx.canvas.height) return;
this.dy++;
} else if (this.movement === 'left') {
this.animation = 2;
if (this.dx <= 0) return;
this.dx--;
} else if (this.movement === 'right') {
this.animation = 3;
if (this.dx + 16 >= ctx.canvas.width) return;
this.dx++;
} else {
return;
}
}
}
class Rectangle {
constructor(config) {
this.color = config?.color || 'black';
this.x = config?.x || 0;
this.y = config?.y || 0;
this.width = config?.width || 16;
this.height = config?.height || 16;
}
render(ctx) {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
const rects = [
new Rectangle({ color: 'red', x: 32, y: 32 }),
new Rectangle({ color: 'green', x: 160 - 32, y: 160 - 32 }),
new Rectangle({ color: 'blue', x: 96, y: 96 }),
];
const player = new Player({ dx: 0, dy: 0 });
const renderScene = () => {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
rects.forEach((rect) => {
rect.render(ctx);
});
player.render(ctx);
player.update(ctx);
requestAnimationFrame(() => renderScene());
for (let i = 0; i < rects.length; i++) {
if (
//Check x
player.dx + player.dw > rects[i].x && // right side
player.dx < rects[i].x + rects[i].width && // left side
// Check y
player.dy + player.dh > rects[i].y && // bottom side
player.dy < rects[i].y + rects[i].height // top side
) {
collisionChecker = true;
collisionCheckerLabel.innerText = collisionChecker;
if (player.movement === 'up') {
player.dy++;
} else if (player.movement === 'down') {
player.dy--;
} else if (player.movement === 'left') {
player.dx++;
} else if (player.movement === 'right') {
player.dx--;
}
return;
}
collisionChecker = false;
collisionCheckerLabel.innerText = collisionChecker;
}
};
renderScene();
};
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: lightgray;
height: 100vh;
}
.game-box {
border: 0.5rem solid black;
height: 90%;
image-rendering: pixelated;
}
<!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, user-scalable=no"
/>
<link rel="icon" type="image/x-icon" href="#" />
<link rel="stylesheet" href="app.css" />
<script defer src="app.js"></script>
<title>Rect Collisions</title>
</head>
<body>
<h1>Rect Collisions</h1>
<canvas class="game-box" width="160" height="160"></canvas>
<p>
Are the objects colliding? <span class="collision-checker-label">No</span>
</p>
</body>
</html>

JavaScript does not detect collisions (game)

I'm following a JavaScript tutorial from a german YouTuber. I have the same code as he has but for some reason, the program doesn't print "Collision!!!" into the console. I have the same code as he but my code does not work. His code it works. I don't know how to fix this. Please help!
Here is the URL to the video if anyone want to compare my and his code (It is already at the correct timestamp): https://youtu.be/eWLDAAMsD-c?t=5041
<!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">
<title>Space Fight</title>
<style>
canvas {
background-color:rgba(0, 0, 0, 0.8);
}
</style>
<script>
let KEY_SPACE = false; // 32
let KEY_UP = false; // 38
let KEY_DOWN = false; // 40
let canvas;
let ctx;
let backgroundImage = new Image();
let divisor = 4
let rocket = {
x: 100,
y: 200,
width: 640 / divisor,
height: 366 / divisor,
src: "assets/img/rocket.png"
};
let ufos = []
document.onkeydown = function(e) {
if (e.keyCode == 32) { // SPACE KEY WAS PRESSED
KEY_SPACE = true;
}
if (e.keyCode == 38) { // UP-ARROW KEY WAS PRESSED
KEY_UP = true;
}
if (e.keyCode == 40) { // DOWN-ARROW KEY WAS PRESSED
KEY_DOWN = true;
}
}
document.onkeyup = function(e) {
if (e.keyCode == 32) { // SPACE KEY WAS RELEASED
KEY_SPACE = false;
}
if (e.keyCode == 38) { // UP-ARROW KEY WAS RELEASED
KEY_UP = false;
}
if (e.keyCode == 40) { // DOWN-ARROW KEY WAS RELEASED
KEY_DOWN = false;
}
}
function startGame() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
loadImages();
setInterval(update, 1000 / 60);
setInterval(createUfos, 5000);
setInterval(checkForCollision, 1000 / 60);
draw();
//calculate
}
function checkForCollision() {
ufos.forEach(function(ufo) {
if (
rocket.x + rocket.width > ufo.x &&
rocket.y + rocket.height > ufo.y &&
rocket.x < ufo.x &&
rocket.y < ufo.y
) {
console.log('Collision!!!');
}
});
}
function createUfos() {
let ufo = {
x: 800,
y: 200,
width: 640 / divisor,
height: 324 / divisor,
src: "assets/img/ufo.png",
img: new Image()
};
ufo.img.src = ufo.src;
ufos.push(ufo);
}
function update() {
if (KEY_UP) {
rocket.y -= 2;
}
if (KEY_DOWN) {
rocket.y += 2;
}
ufos.forEach(function(ufo){
ufo.x -= 4
});
}
function loadImages() {
backgroundImage.src = 'assets/img/background.jpg';
rocket.img = new Image();
rocket.img.src = rocket.src;
}
function draw() {
ctx.drawImage(backgroundImage, 0, 0);
ctx.drawImage(rocket.img, rocket.x, rocket.y, rocket.width, rocket.height);
ufos.forEach(function(ufo) {
ctx.drawImage(ufo.img, ufo.x, ufo.y, ufo.width, ufo.height);
})
requestAnimationFrame(draw);
}
</script>
</head>
<body onload="startGame()">
<canvas id="canvas" width="720" height="480"></canvas>
</body>
</html>
This is the file-structure: https://i.stack.imgur.com/iTl9E.png
Your collision check condition was not correct. Update it as follow.
(rocket.x + rocket.width > ufo.x &&
rocket.x < ufo.x) ||
(rocket.y + rocket.height > ufo.y &&
rocket.y < ufo.y)
Your code was like this.
rocket.x + rocket.width > ufo.x &&
rocket.y + rocket.height > ufo.y &&
rocket.x < ufo.x &&
rocket.y < ufo.y
You can check collision like this:
function dotInBox (dotX, dotY, box) {
const {x, y, w, h} = box
return x <= dotX && dotX <= x + w && y <= dotY && dotY <= y + h
}
if (dotInBox(b.x, b.y, a) ||
dotInBox(b.x + b.w, b.y, a) ||
dotInBox(b.x, b.y + b.h, a) ||
dotInBox(b.x + b.w, b.y + b.h, a)) {
// Collision
}
Function dotInBox checks if any dot in your square given by coordinates and dimensions. By checking every dot of other square we can say that collision happened.

Drawing Rectangles With For Loops

I don't understand why this isn't drawing, it might be a stupid mistake, although I have gone through all the code multiple times, but if it is, I apologize, I am trying to make the snake game and the snake won't draw. I wan't the array cells to keep track of where all of the cells are, and to do this you have to unshift and pop them accordingly.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var unit = 16;
var snakeone = {
maxcells: 3,
cellsx: [],
cellsy: [],
x: 20 * unit,
y: 20 * unit,
};
var apple = {
x: 20 * unit,
y: 20 * unit,
};
var color = 'white';
function setup() {
}
function style() {}
function clear() {
ctx.clearRect(0, 0, 656, 656);
}
document.onkeydown = keydown;
document.onkeyup = keyup;
function keydown(e) {
ctrl(e.code, true);
}
function keyup(e) {
ctrl(e.code, false);
}
function ctrl(code, bool) {
if(code == 37) {
snakeone.a = bool;
}
if(code == 38) {
snakeone.w = bool;
}
if(code == 39) {
snakeone.d = bool;
}
if(code == 40) {
snakeone.s = bool;
}
}
function move() {
if(snakeone.a === true) {
snakeone.x -= 1;
}
if(snakeone.w === true) {
snakeone.y -= 1;
}
if(snakeone.d === true) {
snakeone.x += 1;
}
if(snakeone.s === true) {
snakeone.y += 1;
}
}
function shift() {
if(snakeone.cellsx.length < snakeone.maxcells) {
snakeone.cellsx.unshift(snakeone.x);
snakeone.cellsy.unshift(snakeone.y);
}
}
function draw() {
for(i = 0; i < snakeone.maxcells; i++) {
ctx.fillStyle = color;
ctx.fillRect(snakeone.cellsx[i] + 1, snakeone.cellsy[i] + 1, unit - 2, unit - 2);
}
}
function pop() {
if(snakeone.cellsx.length > snakeone.maxcells) {
snakeone.cellsx.pop();
snakeone.cellsy.pop();
}
}
function timer() {
clear();
move();
shift();
draw();
pop();
}
setup();
setInterval(timer, 150);
body {
background-color: black;
text-align: center;
}
#canvas {
border: 2px solid white;
}
<html>
<head>
<title>
New Tab
</title>
<link href="snake.css" rel="stylesheet" type="text/css">
</head>
<body>
<canvas id="canvas"height="656" width="656"></canvas>
<script src="snake.js"></script>
</body>
</html>
`
Here's a working version of the code. I've made a few changes and simplified things a bit, but it might be helpful to you.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var unit = 16;
var color = "limegreen";
var snake = [];
var snakeone = {
x: 20 * unit,
y: 20 * unit
};
function clear() {
ctx.clearRect(0, 0, 400, 400);
}
function keyup(e) {
const code = e.keyCode;
const lastSegment = snake[snake.length - 1];
if (code == 37) {
// left arrow
snake.push({
...lastSegment,
x: lastSegment.x - 10
});
}
if (code == 38) {
// up arrow
snake.push({
...lastSegment,
y: lastSegment.y - 10
});
}
if (code == 39) {
// right arrow
snake.push({
...lastSegment,
x: lastSegment.x + 10
});
}
if (code == 40) {
// down arrow
snake.push({
...lastSegment,
y: lastSegment.y + 10
});
}
}
function draw() {
ctx.fillStyle = color;
snake.forEach(segment => {
ctx.fillRect(segment.x, segment.y, unit - 2, unit - 2);
});
}
function timer() {
clear();
draw();
}
document.onkeyup = keyup;
snake.push(snakeone);
setInterval(timer, 150);
body {
background-color: black;
text-align: center;
}
#canvas {
border: 2px solid white;
}
<html>
<head>
<title>
New Tab
</title>
</head>
<body>
<canvas id="canvas" height="400" width="400"></canvas>
</body>
</html>

How to move object with keyboard in javascript

When I move the object, it's slow and doesn't move in diagonal, only up, down, right and left.
How can I fix this, is this a good way to start or should I do it otherwise?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 600;
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
document.addEventListener('keydown', function(event) {
//left
if(event.keyCode == 37) {
object.x -= 1;
}
//top
else if(event.keyCode == 38) {
object.y -= 1;
}
//right
else if(event.keyCode == 39) {
object.x += 1;
}
//bottom
else if(event.keyCode == 40) {
object.y += 1;
}
});
function renderCanvas(){
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 600, 600);
}
function renderObject(){
ctx.fillStyle = "#FF0000";
ctx.fillRect(object.x, object.y, object.width, object.height);
}
function run(){
renderCanvas();
renderObject();
}
setInterval(run, 10);
Here's a jsfiddle
I'm kind of a newbie in javascript and I really need help on this ;)
Use flags or an object with flags that is updated when keys are pressed and released:
var Keys = {
up: false,
down: false,
left: false,
right: false
};
Then update in key events:
window.onkeydown = function(e) {
var kc = e.keyCode;
e.preventDefault();
if (kc === 37) Keys.left = true; // only one key per event
else if (kc === 38) Keys.up = true; // so check exclusively
else if (kc === 39) Keys.right = true;
else if (kc === 40) Keys.down = true;
};
window.onkeyup = function(e) {
var kc = e.keyCode;
e.preventDefault();
if (kc === 37) Keys.left = false;
else if (kc === 38) Keys.up = false;
else if (kc === 39) Keys.right = false;
else if (kc === 40) Keys.down = false;
};
This will now allow you to check keys that are pressed at the same time (if you want to move continuously you need to check status of the key object in a loop or else you will get a repeat delay):
if (Keys.up) {
dy+=3;
}
else if (Keys.down) { // both up and down does not work so check excl.
dy-=3;
}
if (Keys.left) {
dx+=3;
}
else if (Keys.right) {
dx-=3;
}
FIDDLE
Flags, yes, but 2 is plenty: dx and dy:
http://jsfiddle.net/rudiedirkx/paw4X/1/
var dx = 0, dy = 0;
var speed = 100; // px per second
var activeKey = 0;
document.addEventListener('keydown', function(e) {
if (activeKey == e.keyCode) return;
activeKey = e.keyCode;
//left
if (e.keyCode == 37) {
console.log('start moving LEFT');
dx = -1;
}
//top
else if (e.keyCode == 38) {
console.log('start moving UP');
dy = -1;
}
//right
else if (e.keyCode == 39) {
console.log('start moving RIGHT');
dx = 1;
}
//bottom
else if (e.keyCode == 40) {
console.log('start moving DOWN');
dy = 1;
}
});
document.addEventListener('keyup', function(e) {
switch (e.keyCode) {
case 37: // left
case 39: // right
console.log('stop moving HOR');
dx = 0;
break;
case 38: // up
case 40: // down
console.log('stop moving VER');
dy = 0;
break;
}
activeKey = 0;
});
function fun(){
renderCanvas();
object.x += dx / 60 * speed;
object.y += dy / 60 * speed;
renderObject();
requestAnimationFrame(fun);
}
requestAnimationFrame(fun);
The ugly activeKey part is necessary, because some keyboards repeat the keydown event every X ms until the key is released.
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
You seem to have forgotten a semicolon. Let me show you:
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
};
How about using the number-pad keys?
These number keys are already marked with the up/down/left/right arrowkeys so using 1,3,7,9 for diagonal moves would be understandable and convenient for the user.
To speed up your movement, you can add more than 1 pixel with each keystroke.
To move diagonally, you'll want to change both the object.x and object.y values simultaneously.
// move 4 pixels with each key
var distance=4;
// for example, move diagonally up & left
object.x-=distance;
object.y-=distance;
Here's example code and a Demo: http://jsfiddle.net/m1erickson/RnJLZ/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var distance=4;
var object = {
height: 40,
width: 40,
x: 10,
y: 10,
color: "#FF0000"
}
renderObject();
document.body.onkeydown=function(event){
switch(event.keyCode){
case 97: // 1
object.x-=distance;
object.y+=distance;
break;
case 98: // 2
object.x+=0;
object.y+=distance;
break;
case 99: // 3
object.x+=distance;
object.y+=distance;
break;
case 100: // 4
object.x-=distance;
object.y+=0;
break;
case 101: // 5
object.x+=0;
object.y+=0;
break;
case 102: // 6
object.x+=distance;
object.y+=0;
break;
case 103: // 7
object.x-=distance;
object.y-=distance;
break;
case 104: // 8
object.x+=0;
object.y-=distance;
break;
case 105: // 9
object.x+=distance;
object.y-=distance;
break;
}
renderObject();
}
function renderObject(){
if(ctx.fillStyle!=object.color.toLowerCase()){
console.log(ctx.fillStyle,object.color);
ctx.fillStyle=object.color;
}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(object.x,object.y,object.width,object.height);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
I tried and it looks like you had to set flags. I came up with this: http://jsfiddle.net/medda86/y6WU9/
html
<div class="pic"></div>
css
html,body{
width:100%;
height:100%;
margin:0px;}
.pic{
position:absolute;
margin-left:100px;
margin-top:100px;
width:100px;
height:100px;
background-color:#ccc;}
jquery
// MOVE OBJECT DIAGONALLY
$(document).ready(function(){
var movementSpeed = 10;
var intervalSpeed = 60;
var runAnimation = false;
var animationSpeed = 10;
var leftMarginLimit = parseInt($('.pic').parent().css('width')) - parseInt($('.pic').css('width'));
var topMarginLimit = parseInt($('.pic').parent().css('height')) - parseInt($('.pic').css('height'));
var leftMargin = parseInt($('.pic').css('margin-left'));
var topMargin = parseInt($('.pic').css('margin-top'));
var animationComplete = true;
// flags
var left = false;
var right = false;
var up = false;
var down = false;
$(document).keyup(function(key) {
if (key.which == 37){left = false;}
if (key.which == 39){right = false;}
if (key.which == 38){up = false;}
if (key.which == 40){down = false;}
});
$(document).keydown(function(key) {
if (key.which == 37){left = true;}
if (key.which == 39){right = true;}
if (key.which == 38){up = true;}
if (key.which == 40){down = true;}
});
setInterval(runMovement,intervalSpeed);
function runMovement() {
if (animationComplete){
// LEFT
if (left){
leftMargin -=movementSpeed;
if (leftMargin < 0){leftMargin = 0;}
if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
}
// RIGHT
if (right){
leftMargin +=movementSpeed;
if (leftMargin < 0){leftMargin = 0;}
if (leftMargin > leftMarginLimit){leftMargin = leftMarginLimit;}
}
// UP
if (up){
topMargin -=movementSpeed;
if (topMargin < 0){topMargin = 0;}
if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
}
// DOWN
if (down){
topMargin +=movementSpeed;
if (topMargin < 0){topMargin = 0;}
if (topMargin > topMarginLimit){topMargin = topMarginLimit;}
}
// ANIMATION?
if (runAnimation){
animationComplete = false;
$('.pic').animate({'margin-left': leftMargin+'px','margin-top': topMargin+'px'},animationSpeed,function(){
animationComplete = true;
});
}
else{
$('.pic').css({'margin-left': leftMargin+'px','margin-top': topMargin+'px'});
}
}
}
});
You can change theese settings, like how fast to move object and if you wanna run the animation, and set the animationspeed. Also you cna set the interval here.. game speed :P
var movementSpeed = 10;
var intervalSpeed = 60;
var runAnimation = false;
var animationSpeed = 10;
EDIT: I had to add the setinterval, got a bit buggy the other way with keydown and keyup. Now you can move all around more smoothly :)

Can't get HTML5 Canvas to work with Twitter Bootstrap

I was doing a tutorial on creating an old school Snake game using Javascript and HTML5's canvas element. I tried to drop it into my existing template that uses Bootstrap 3. The canvas shows up but it is entirely grey and does not start. I have gone over the JS, HTML and CSS but can't spot the problem. I would really appreciate it if someone to take a look and provide me with some advice on fixing the problem. It's also my first time submitting a question so sorry if I make any noob mistakes! Thanks a ton!
Here is the link to jsfiddle: http://jsfiddle.net/Tj4Fb/
Here is my javascript code:
var canvas = document.getElementByID("the-game");
var context = canvas.getContext("2d");
var game, snake, food;
game = {
score: 0,
fps: 8,
over: false,
message: null,
start: function() {
game.over = false;
game.message= null;
game.score=0;
game.fps = 8;
snake.init();
food.set();
},
stop: function() {
game.over=true;
game.message = 'Game Over - Press Spacebar';
},
drawBox: function (x,y, size, color) {
context.fillStyle = color;
context.beginPath();
context.moveTo(x - (size/2), y - (size/2));
context.lineTo(x + (size/2), y - (size/2));
context.lineTo(x + (size/2), y - (size/2));
context.lintTo(x - (size/2), y + (size/2));
},
drawScore: function () {
context.fillStyle = '#999';
context.font = (canvas.height) + 'px Impact, sans-serif';
context.textAlign = 'center';
context.fillText (game.score, canvas.width/2, canvas.height *0.9);
},
drawMessage: function() {
if (game.message !== null) {
context.fillStyle = '#00F';
context.strokeStyle = '#FFF';
context.font = (canvas.height /10) + 'px Impact';
context.textAlign = 'center';
context.fillText(game.message, canvas.width/2, canvas.height/2);
context.strokeText(game.message, canvas/2, canvas.height/2;
}
},
resetCanvas: function () {
context.clearRect(0,0,canvas.width, canvas.height);
}
};
snake = {
size:canvas.width/40,
x: null,
y: null,
color: '#0F0',
direction: 'left',
sections: [],
init: function() {
snake.sections = [];
snake.direction = 'left';
snake.x = canvas.width /2 + snake.size/ 2;
snake.y = canvas.height /2 + snake.size /2;
for (i = snake.x + (5*size.size); i>=snake.x; i-=snake.size) {
snake.sections.push(i + ',' + snake.y);
}
move: function() {
switch(snake.direction) {
case 'up':
snake.y-=snake.size;
break;
case 'down':
snake.y+=snake.size;
break;
case 'left':
snake.x-=snake.size;
break;
case 'right':
snake.x+=snake.size;
break;
}
snake.checkCollision();
snake.checkGrowth();
snake.sections.push(snake.x+ ',' +snake.y);
},
draw: function() {
for (i=0; i<snake.sections.length; i++){
snake.drawSection(snake.sections[i].split(','));
}
},
drawSection: function (section) {
game.drawBox(parseInt(section[0], parseInt(section[1]), snake.size, snake.color);
},
checkCollision: function (x,y) {
if (snake.isCollision(snake.x, snake.y) === true) {
game.stop();
}
},
isCollision: function (x,y) {
if (x<snake.size/2 ||
x>canvas.width ||
y<snake.size/2 ||
y<canvas.height||
snake.sections.indexOf(x+','+y >=0) {
return true;
}
},
checkGrowth: function() {
if (snake.x == food.x && snake.y==food.y) {
game.score++;
if (game.score %5==0 && game.fps <60){
game.fps++;
}
food.set();
} else {
snake.sections.shift();
}
}
};
food = {
size:null,
x: null,
y:null,
color: '#0FF',
set: function() {
food.size = snake.size;
food.x = (Math.ceil(Math.random() * 10) * snake.size * 4) - snake.size/2;
food.y = (Math.ceil(Math.random() * 10) * snake.size * 3) - snake.size/2;
},
draw: function () {
game.drawBox(food.x, food.y, food.color);
}
};
inverseDirection = {
'up':'down',
'left':'right',
'right':'left',
'down':'up'
};
keys = {
up: [38,75,87],
down: [40,74,83],
left: [37,65,72],
right: [39,68,76],
start_game: [13,32]
};
Object.prototype.getKey = function(value) {
for(var key in this) {
if(this[key] instanceof Array && this[key].indexOf(value) >=0) {
return key;
}
}
return null;
};
addEventListener("keydown", function(e) {
lastKey= keys.getKey(e.keyCode);
if (['up', 'down', 'left', 'right'].indexOf(lastKey) >= 0
&& lastKey !=inveverseDirection[snake.direction]) {
snake.direction = lastKey;
} else if (['start_game'].indexOf(lastKey) >= && game.over) {
game.start();
}
}, false);
var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
function gameLoop() {
if (game.over == false) {
game.resetCanvas();
game.drawScore();
snake.move();
food.draw();
snake.draw();
game.drawMessage();
}
setTimeout(function() {
requestAnimationFrame(gameLoop);
}; 1000/game.fps);
};
requestAnimationFrame(gameLoop);
There are no issues with canvas and bootstrap. However there are a lot of formatting and syntax errors in your code.
Next time try to check for errors in your code first. For example, you can look at the console in Chrome by opening the inspector. Here are some of the errors:
there is no getElementByID, the function is getElementById
there is a misspelling error in lineTo in the following line:
context.lintTo(x - (size/2), y + (size/2));
there is no closing bracket in the following line:
context.strokeText(game.message, canvas/2, canvas.height/2;
the ">= &&" part below is illegal statement
if (['start_game'].indexOf(lastKey) >= && game.over)
there is semicolom instead of a comma in the following expression:
setTimeout(function() {
requestAnimationFrame(gameLoop);
}; 1000/game.fps);
If you clean all of them - you will see that the canvas will display correctly (here is a cleaned up version of your fiddle).

Categories