I'm attempting to make a game, and I've got some sprites that will overlap each other. When clearing the sprite's area with clearRect, any sprite behind it will disappear as if the foreground sprite wasn't transparent. However, if I try to save and restore the area behind the sprite using get/putImageData, weird things start to happen. Part of the sprites in various places do not get "undrawn", other parts seem to be broken up and yards away, and other sprites get smeared. Here's a code chunk:
var anim = function()
{
if(gtiming < Date.now() % 1000)
timing = (Date.now() % 1000) - gtiming;
if(stage == 1)
{
ugcnt = ugcnt + timing;
if(mleft == true)
{
acc = acc - 0.25;
}
else if(mright == true)
{
acc = acc + 0.25;
}
else
{
if(acc < 0 || acc > 0) acc = acc / 1.1;
}
if(kyx < 0)
{
kyx = 0;
acc = -acc;
}
else if(kyx > 432)
{
kyx = 432;
acc = -acc;
}
if(kyblk != null)
xbios.putImageData(kyblk, kyx, 155);
kyblk = null;
kyx = kyx + acc;
kyblk = xbios.getImageData(kyx, 155, 208, 245);
xbios.drawImage(kyk[Math.floor(kyf)], 0, 0, 416, 490, kyx, 155, 208, 245);
if(ugcnt > mus[r][1] * 1000)
{
ugcnt = 0;
ugobj.push(new ugnaut(Math.floor(Math.random() * 640), -208, "L"));
}
ugobj.forEach(testug);
kyf = kyf + ((timing / 1000) * (mus[r][1] * 240));
if(kyf > 119)
kyf = kyf - 119;
}
gtiming = Date.now() % 1000;
if(stage > 0)
requestAnimationFrame(anim);
}
function ugnaut(x, y, f)
{
this.x = x;
this.y = y;
this.f = f;
this.fr = 0;
this.blk = null;
this.set=function()
{
if(this.blk != null)
xbios.putImageData(this.blk, this.x, this.y);
this.blk = null;
if(f == "L")
{
this.y++;
this.blk = xbios.getImageData(this.x, this.y, 179, 208);
xbios.drawImage(ugf[this.fr], 0, 0, 179, 208, this.x, this.y, 179, 208);
this.fr++;
if(this.fr > 44) this.fr = 0;
}
}
this.getx = function()
{
return this.x;
}
this.gety = function()
{
return this.y;
}
this.getf = function()
{
return this.f;
}
}
function testug(item, index)
{
if(item.getx() > -180 && item.getx() < 640 && item.gety() > -224 && item.gety() < 400)
{
item.set();
}
else
{
item = null;
ugobj.splice(index, 1);
}
}
For those wondering, yes, I did call the Canvas 2D Context xbios. Just felt like a fun name at the time. Anyways, from my understanding having a this inside the "object" ugnaut the value it holds will be local to that object's instance, and so I assume each ugnaut will hold its own background information in this.blk, but am I wrong? What other methods should I use?
Related
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>
I'm making a game in Phaser which looks like that:
player has to catch the eggs, so the eggs (which are made from gameState.eggs = this.physics.add.group();) have a certain velocity while on the ramp, but then once they're off the ramp, i want to authomatically setVelocity() to one with 0 for x coordinate, instead of just shooting across the screen.
Here's my egg generating function:
function eggGen() {
let num = Math.random();
let xCoord, yCoord, eggDirection, eggAnimation, velocityX
if (num < .5) {
xCoord = 100;
eggDirection = 'eggLeft';
eggAnimation = 'rollingLeft'
velocityX = this.velocityX;
if (num < .25) {
yCoord = 232;
} else {
yCoord = 382;
}
} else {
xCoord = 700;
eggDirection = 'eggRight';
eggAnimation = 'rollingRight';
velocityX = -(this.velocityX)
if (num < .75) {
yCoord = 232;
} else {
yCoord = 382;
}
}
let egg = gameState.eggs.create(xCoord, yCoord, eggDirection).setVelocity(velocityX, this.velocityY).setScale(.6);
if (egg.x > 220 && egg.x < 580) {
egg.setVelocity(0, this.velocityY);
}
egg.anims.play(eggAnimation);
}
the last conditional is what i hoped would do the magic, but it doesn't do anything. To clarify, eggGen function is called inside this.time.addEvent();
Without knowing your code (and assuming arcade physics is used), I would:
Just check in the update function, of the scene, if a egg is "on the ramp" and has a x-velocity of 0
function update(){
// ...
gameState.eggs.getChildren().forEach(egg => {
if(egg.velocity.x > 0 && (egg.x > 220 || egg.x < 580)) {
// ... stop velocity.x or set the whole velocity new
egg.velocity.x = 0;
}
});
// ...
}
Here a mini Demo:
It just covers the basics
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 300,
height: 183,
physics: {
default: 'arcade',
arcade: {
debug: true,
}
},
scene: {
create,
update
},
banner: false
};
let objectGroup;
function create () {
objectGroup = this.physics.add.group();
this.time.addEvent({ delay: 500, callback: createObject, callbackScope: this, loop: true });
}
function createObject(){
let spawnLeft = Phaser.Math.Between(0, 1);
let obj = this.add.rectangle(spawnLeft ? 0 : config.width, 0, 10, 10, 0xff0000);
this.physics.add.existing(obj);
objectGroup.add(obj);
obj.body.setVelocity((spawnLeft ? 1 : -1) * 75, 30);
}
function update(){
if(!objectGroup)
return;
objectGroup.getChildren().forEach(obj =>{
if(obj.body.velocity.x > 0 && (obj.x > 100 && obj.x < 150) || (obj.x > config.width - 150 && obj.x < config.width - 100) ){
// Just to keep the same speed, even after changing direction
let speed = obj.body.velocity.length();
obj.body.velocity.x = 0;
obj.body.velocity.y = speed;
}
});
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
I'm a beginner using p5js and I'm trying to work with classes. I'm making a game where you have to find and click a 'wanted man', from a crowd.
So basically, a randomizer picks between 7 different types of 'civilians', and it's supposed to remove one of the types from the 'civilians' that have been spawned. After removing the 'wanted man', I want to add one wanted man so that there is only one 'wanted man'.
So the code spawns a bunch of random 'civilians', then it will delete all 'wanted man' types in the array, and add only one of them. I think there is a better way to do this though.
My basic desire is to have a crowd of 'civilians' that run around, - one of which is a 'wanted man' - and you would have to find and click that 'wanted man' (kind of like a hunting/assassination game).
This is the code for the sketch.js file:
var civilians = [];
var page = 0;
var man1img;
var man2img;
var man3img;
var man4img;
var man5img;
var man6img;
var aliemanimg;
var w;
var h;
var spawnCount = 14;
var wantedMan;
var randCiv;
function preload() {
man1img = loadImage("man1.png");
man2img = loadImage("man2.png");
man3img = loadImage("man3.png");
man4img = loadImage("man4.png");
man5img = loadImage("man5.png");
man6img = loadImage("man6.png");
aliemanimg = loadImage("alieman.png");
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup() {
createCanvas(windowWidth, windowHeight);
imageMode(CENTER);
// wantedMan = round(random(0, 6));
wantedMan = 0;
for (var i = 0; i < spawnCount; i++) {
randCiv = round(random(0, 6));
w = random(windowWidth);
h = random(windowHeight);
civilians.push(new Civilian(w, h, wantedMan, randCiv));
console.log(wantedMan);
if (civilians[i].isWantedMan()) {
//OVER HERE \/
civilians.splice(i, 1);
}
}
civilians.push(new Civilian(w, h, wantedMan, wantedMan));
}
// page setup
// page 1 : main screen (play, settings, and those stuff)
// page 2 : show chosen civilian
// page 3 : playing
// page 4 : lose
// page 5 : options
function draw() {
background(220, 80, 80);
for (var i = civilians.length - 1; i >= 0; i--) {
civilians[i].update();
civilians[i].show(mouseX, mouseY);
if (civilians[i].clickedOn(mouseX, mouseY)) {
// detect if is right person
console.log("clicked on boi");
if (civilians[i].isWantedMan()) {
console.log("HES WANTED");
} else {
console.log("HES NOT WANTED");
}
}
}
text(round(frameRate()), 20, 20);
//show wanted man
var tempImg = man1img;
if (wantedMan == 1) {
tempImg = man2img;
} else if (wantedMan == 2) {
tempImg = man3img;
} else if (wantedMan == 3) {
tempImg = man4img;
}
if (wantedMan == 4) {
tempImg = man5img;
} else if (wantedMan == 5) {
tempImg = man6img;
} else if (wantedMan == 6) {
tempImg = aliemanimg;
}
image(tempImg, 50, 70, 70, 90);
}
This is the code for the class:
class Civilian {
constructor(x, y, wantedMan, type) {
this.x = x;
this.y = y;
this.w = 47;
this.h = 60;
this.t = {
x: x,
y: y,
};
this.size = 47;
this.moveSpeed = 0.01;
this.moveDist = 20;
this.wantedMan = wantedMan;
this.civilian = type
this.civilianImg = man1img
this.wantedMan = wantedMan
}
update() {
//move target to random position
this.t.x = random(this.t.x - this.moveDist, this.t.x + this.moveDist);
this.t.y = random(this.t.y - this.moveDist, this.t.y + this.moveDist);
//edge detect
if (this.t.x < 0) {
this.t.x += 5;
}
if (this.t.x > width) {
this.t.x -= 5;
}
if (this.t.y < 0) {
this.t.y += 5;
}
if (this.t.y > height) {
this.t.y -= 5;
}
//images position follows target but with easing
this.x += (this.t.x - this.x) * this.moveSpeed;
this.y += (this.t.y - this.y) * this.moveSpeed;
}
show(ex, ey) {
var d = dist(ex, ey, this.x, this.y);
if (d > this.size / 2) {
tint(255, 255, 255);
} else {
tint(0, 255, 0);
}
if(this.civilian == 1) {
this.civilianImg = man2img
} else if(this.civilian == 2) {
this.civilianImg = man3img
} else if(this.civilian ==3) {
this.civilianImg = man4img
} if(this.civilian == 4) {
this.civilianImg = man5img
} else if(this.civilian == 5) {
this.civilianImg = man6img
} else if(this.civilian == 6) {
this.civilianImg = aliemanimg
}
image(this.civilianImg, this.x, this.y, 47, 60);
}
clickedOn(ex, ey) {
var d = dist(ex, ey, this.x, this.y);
return d < this.size / 2 && mouseIsPressed;
}
isWantedMan() {
return this.civilian == this.wantedMan;
}
}
However, whenever I add a .splice(i,1) under the 'for' loop in setup function - to remove the 'wanted man', it shows this error:
"TypeError: Cannot read properties of undefined (reading
'isWantedMan') at /sketch.js:41:22".
isWantedMan() is a function in the Civilian Class, that returns true if the current 'civilian' is wanted. The .splice is supposed to remove a object from the array, when it is a 'wanted man'.
I don't know why this happens. When I replace the .splice code with a console.log() code, then there is no error.
Also there were probably a lot of things that I could have done better in the code.
This may be a lengthy post. I'm having to learn JS on the fly and could be making simple mistakes.
I'm writing a game in JS/html, and am using EasyStar to put in some pathfinding behavior for some entities. I'm using inheritance to give the behavior outlined in Walker4 below to multiple entities, example of one at the bottom:
function Walker4(game, img, Ai, lX, lY) {
this.easyStar = Ai;
this.dX = 0;
this.dY = -1;
this.animation = [];
this.animation["NE"] = null;
this.animation["NW"] = null;
this.animation["SE"] = null;
this.animation["SW"] = null;
this.currAnimation = null;
this.facing = "";
this.img = img;
this.isWalking = false;
this.isFindingPath = false;
this.destX = null;
this.destY = null;
this.path = [];
this.next = null;
this.loadCount = 0;
Entity.call(this, game, lX, lY);
}
Walker4.prototype = new Entity();
Walker4.prototype.constructor = Walker4;
Walker4.prototype.update = function () {
if (this.isFindingPath) return;
if (this.isWalking) this.walkPath();
if (this.destX != null && this.destY != null) {
this.isFindingPath = true;
that = this;
easyStar.findPath(this.x, this.y, this.destX, this.destY, function (path) {
if (path === null) {
console.log("No path :(");
} else {
console.log("Path! The first Point is " + path[0].x + " " + path[0].y);
that.path = path;
that.next = that.path.shift();
that.isWalking = true;
}
});
this.destX = null;
this.destY = null;
this.isFindingPath = false;
easyStar.calculate();
}
Entity.prototype.update.call(this);
}
Walker4.prototype.walkPath = function () {
if (this.path.length == 0) {
if (Math.floor(this.x) == this.next.x && Math.floor(this.y) == this.next.y) {
this.dX = 0;
this.dY = 0;
}
isWalking = false;
return;
}
if (Math.floor(this.x) == this.next.x && Math.floor(this.y) == this.next.y) {
this.next = this.path.shift();
this.dX = setDirection(Math.floor(this.x), this.next.x);
this.dY = setDirection(Math.floor(this.y), this.next.y);
this.currAnimation = this.animation[setFace(this.dX, this.dY)];
}
this.x += this.dX * this.game.clockTick * speed;
this.y += this.dY * this.game.clockTick * speed;
}
Walker4.prototype.draw = function (ctx) {
pt1 = twodtoisoX(this.x, this.y) + 27 - this.currAnimation.frameWidth / 2;
pt2 = twodtoisoY(this.x, this.y) + 10 - this.currAnimation.frameHeight / 2;
ctx.fillRect(pt1, pt2, 5, 5);
//console.log(pt1, pt2);
this.currAnimation.drawFrame(this.game.clockTick, ctx, pt1, pt2);
Entity.prototype.draw.call(this);
}
//Cart Walkers
function eCartMan(game, img, Ai, lX, lY) {
Walker4.call(this, game, img, Ai, lX, lY);
this.animation["NE"] = new Animation(img, 0, 0, 60, 48, 12, aSpeed, 12, true);
this.animation["NW"] = new Animation(img, 0, 1, 60, 48, 12, aSpeed, 12, true);
this.animation["SE"] = new Animation(img, 0, 2, 60, 48, 12, aSpeed, 12, true);
this.animation["SW"] = new Animation(img, 0, 3, 60, 48, 12, aSpeed, 12, true);
this.currAnimation = this.animation["NE"];
}
eCartMan.prototype = new Walker4();
eCartMan.prototype.constructor = eCartMan;
All these entities are added to a list of entities that is updated in a loop each game tick, each having update and draw called respectively. Easy Star seems to give each entity a path, but then only the most recently added entity will actually follow their given path. What am I missing?
Any help appreciated.
Alright, scoped down the problem. Thanks to #HMR for helping.
Ended up a scope issue on that = this;, and that each walker needed its own version of the EasyStar pathfinder. that became global, and opened up all instances of the walkers to modifying each other.
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).