parsing tiled json map into html canvas - javascript

I am trying to make a 2d top view javascript game and i want to make my map using program "tiled" i have made my map and have the exported json but dont know how to parse it into a canvas html tag and i dont know were to start here is my crazy game code
<html>
<body>
</body>
</html>
<script>
// Create the canvas
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function() {
bgReady = true;
};
bgImage.src = "images/newbackground.png";
//hp box
var hpBoxReady = false;
var hpBoxImage = new Image();
hpBoxImage.onload = function() {
hpBoxReady = true;
};
hpBoxImage.src = "images/hpbox.png";
// player image
var playerReady = false;
var playerImage = new Image();
playerImage.onload = function() {
playerReady = true;
};
playerImage.src = "images/char.png";
// enemy image
var enemyReady = false;
var enemyImage = new Image();
enemyImage.onload = function() {
enemyReady = true;
};
enemyImage.src = "images/enemy_idle01.png";
// Game objects
var hpBox = {
restoreHealth: 34,
x: 300,
y: 300
}
var player = {
stamina: 7,
health: 100,
sprintSpeed: 400,
weakSpeed: 150,
speed: 300 // movement in pixels per second
};
var enemy = {
speed: 250,
viewDistance: 40
};
var enemysCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function(e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function(e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a enemy
var reset = function() {
player.x = canvas.width / 2;
player.y = canvas.height / 2;
// Throw the enemy somewhere on the screen randomly
enemy.x = 32 + (Math.random() * (canvas.width - 64));
enemy.y = 32 + (Math.random() * (canvas.height - 64));
};
//w is 87
//a is 65
//s is 83
//d is 68
// Update game objects
var update = function(modifier) {
if (87 in keysDown) { // Player holding up
player.y -= player.speed * modifier;
}
if (83 in keysDown) { // Player holding down
player.y += player.speed * modifier;
}
if (65 in keysDown) { // Player holding left
player.x -= player.speed * modifier;
}
if (68 in keysDown) { // Player holding right
player.x += player.speed * modifier;
}
if (
player.x <= (0)) {
player.health -= 1;
console.log('health decreasing');
}
}
if (
player.y <= (0)) {
player.health -= 1;
console.log('health decreasing');
};
// Are they touching?
if (
player.x <= (enemy.x + 32) &&
enemy.x <= (player.x + 32) &&
player.y <= (enemy.y + 32) &&
enemy.y <= (player.y + 32)
) {
++enemysCaught;
reset();
}
// Draw everything
var render = function() {
if (bgReady) {
context.drawImage(bgImage, 0, 0);
}
if (hpBoxReady) {
context.drawImage(hpBoxImage, hpBox.x, hpBox.y);
}
if (playerReady) {
context.drawImage(playerImage, player.x, player.y);
}
if (enemyReady) {
context.drawImage(enemyImage, enemy.x, enemy.y);
}
// Score
context.fillStyle = "rgb(250, 250, 250)";
context.font = "24px Helvetica";
context.textAlign = "left";
context.textBaseline = "top";
context.fillText("enemys killed: " + enemysCaught, canvas.width / 2, 32);
};
function dieEvent() {
player.health = 100;
}
function updateHealth() {
context.fillStyle = "rgb(255 ,0 ,0)";
context.textAlign = "right";
context.fillText("Health: " + player.health, 1000, 32)
}
function isNearHPBox() {
if (
player.y <= (hpBox.y + enemy.viewDistance + 64) &&
player.y >= (hpBox.y - enemy.viewDistance - 64) &&
player.x <= (hpBox.x + enemy.viewDistance + 64) &&
player.x >= (hpBox.x - enemy.viewDistance - 64)) {
console.log("healing!");
if (player.health <= 100) {
hpBox.restoreHealth = player.health - 100;
player.health += hpBox.restoreHealth;
}
}
}
function moveEnemy() {
if (
player.y <= (enemy.y + enemy.viewDistance + 64) &&
player.y >= (enemy.y - enemy.viewDistance - 64) &&
player.x <= (enemy.x + enemy.viewDistance + 64) &&
player.x >= (enemy.x - enemy.viewDistance - 64)) {
console.log("seen on enemys Y");
var audio = new Audio('sounds/theWanderer_Scream.m4a');
audio.play();
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
}
}
function checkWallCollision() {
if (player.y <= 0) {
console.log("y")
player.y += 64;
}
if (player.x <= 0) {
console.log("x")
player.x += 64;
}
if (enemy.y <= 0) {
console.log("y")
enemy.y += 64;
}
if (enemy.x <= 0) {
console.log("x")
enemy.x += 64;
}
}
function reducedSpeed() {
player.speed = player.weakSpeed;
}
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
context.clearRect(0, 0, canvas.width, canvas.height);
render();
updateHealth();
moveEnemy();
if (player.health <= 20) {
reducedSpeed();
} else {
player.speed = 300;
}
if (player.health <= 0) {
dieEvent();
}
checkWallCollision();
isNearHPBox();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
// Let's play this game!
var then = Date.now();
reset();
main();
</script>
<style>
body {
margin: 0;
padding: 0;
}
</style>
i have tried all the tutorials but cant seem to get it to work so for now i just have a small little background image could sombody please help?

Your question is a bit general. I recommand to enroll Udacity's HTML5 Game Development course I think many part of your question should be answered after watching that course.

Related

Rotate the user character on mouse position

I'm trying to get the character to rotate the character object based on where the mouse is.
So far I got it to rotate incrementally without mouse position. I was checking if it effected my zombie's chasing capabilities.
My script
let player, zombie, mouseX, mouseY;;
let bgCanvas = document.getElementById('backgroundCan');
function startGame() {
document.getElementById("startScreen").style.display = "none";
player = new playerComponent(350, 220);
zombie = new zombieComponent(750, 220);
gameArea.start();
}
let gameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 800;
this.canvas.height = 500;
this.canvas.style = "position: absolute";
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[2]);
this.interval = setInterval(updateArea, 20);
window.addEventListener('keydown', function (e) {
gameArea.keys = (gameArea.keys || []);
gameArea.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
gameArea.keys[e.keyCode] = false;
});
this.canvas.addEventListener("mousemove", function(e){
mouseX = e.clientX - ctx.canvas.offsetLeft;
mouseY = e.clientY - ctx.canvas.offsetTop;
});
this.canvas.addEventListener("mousedown", function(e){
let gShot = new Audio('assets/shot.mp3');
gShot.play();
var mX = e.clientX - ctx.canvas.offsetLeft;
var mY = e.clientY - ctx.canvas.offsetTop;
if(mX >= zombie.x && mX < zombie.x+zombie.w && mY >= zombie.y && mY < zombie.y+zombie.h){
if(zombie.health > 0){
zombie.health += -1;
zombie.speedX += 10;
zombie.newPos();
zombie.update();
}
else {
zombie.status = "dead";
}
}
});
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function playerComponent(x, y){
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.health = 10;
this.status = "alive";
let rotNum = 1;
this.update = function(){
ctx = gameArea.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(rotNum * Math.PI / 180);
playerSprite = new Image();
playerSprite.src = "assets/playerGun.png";
ctx.drawImage(playerSprite, 0, 0);
ctx.restore();
rotNum++;
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function updateArea() {
gameArea.clear();
if(player.status == "alive"){
player.speedX = 0;
player.speedY = 0;
if (gameArea.keys && gameArea.keys[65]) {
if(player.x > 20){
player.speedX = -3;
}
}
if (gameArea.keys && gameArea.keys[68]) {
if(player.x < 740){
player.speedX = 3;
}
}
if (gameArea.keys && gameArea.keys[87]) {
if(player.y > 20){
player.speedY = -3;
}
}
if (gameArea.keys && gameArea.keys[83]) {
if(player.y < 445){
player.speedY = 3;
}
}
player.newPos();
player.update();
}
if(zombie.status == "alive"){
if(zombie.x > player.x){
zombie.speedX = -1;
}
else{
zombie.speedX = 1;
}
if(zombie.y > player.y){
zombie.speedY = -1;
}
else{
zombie.speedY = 1;
}
zombie.newPos();
zombie.update();
}
else{
zombie.update();
}
}
So far, I have the mouse position on the canvas and am able to rotate the character, but I just don't how to connect the two. How should use the mouse position and the character position to rotate towards the mouse? The character is initially facing right (i think?), at least the sprite initially is.
Here's an image illustrating the situation:
You have the mouseY, playerY and mouseX, playerX
Therefore you can calculate the height and base of the triangle,
Thus the angle with
However, since in the second and third quadrants y/x will return an angle in the first and fourth quadrants, you need to use the Math.atan2(y,x) function in Javascript, not Math.atan(y/x). This will give you an angle between -180 and 180 instead of between -90 and 90.
Atan Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
Then all you have to do is rotate based on the angle!
(P.S. Remember that you will have to convert between radians and degrees)

how can I detect collision in a 2D tile game map

I made this basic game where I drew a map and a player, the player can move anywhere but how can I make so that it wont move when its on the tile[1] in the map?
also when I try to check if the player.x is greater than 50 it could go left it works but than if I click 2 keys at once it goes through
const context = document.querySelector("canvas").getContext("2d");
var rgb = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random() + ')';
document.onload = Loop();
var width = 1500;
var height = 800;
function Loop(){
var width = 1500;
var height = 800;
context.canvas.height = height;
context.canvas.width = width;
this.interval = setInterval(Update, 1000/100);
}
const Player = function(x, y, w, h, color) {
this.x = x; this.y = y; this.w = w; this.h = h;
this.speedY = 0; this.speedX = 0;
this.Draw = function(){
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
};
this.Move = function(){
this.x += this.speedX;
this.y += this.speedY;
};
};<code>
var player = new Player(100,100,50, 50, rgb);
var Key = {};
function Update(){
context.clearRect(0, 0, width, height);
Map();
player.Draw();
player.Move();
onkeydown = onkeyup = function(e){
player.speedX = 0;
player.speedY = 0;
e = e || event;
Key[e.keyCode] = e.type == 'keydown';
if(Key[37] || Key[65]) {player.speedX -= 2}
if(Key[38] || Key[87]) {player.speedY -= 2}
if(Key[39] || Key[68]) {player.speedX += 2}
if(Key[40] || Key[83]) {player.speedY += 2}
if(Key[32]) {player.color = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random()*1 + ')';}
};
}
var map = [
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
];
var row = 5;
var column = 5;
function Map(){
for(let y = -1; y < column; y++){
for(let x = -1; x < row; x++){
switch(map[((y*row) + x)]) {
case 0: context.fillStyle = player.color;
break;
case 1: context.fillStyle = "#ffffff";
break;
default: context.fillStyle = "#000000";
}
context.fillRect(x*50, y*50, 50, 50);
}
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
script {
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
function Camera(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
}
Camera.prototype = {
set: function(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
},
pan: function(x,y) {
this.x += x || 0.0;
this.y += y || 0.0;
}
};
var nextID = 0;
function Tile(colour) {
this.id = nextID++;
this.colour = colour || "black";
}
function Map(width,height) {
this.width = width || 1;
this.height = height || 1;
this.map = [];
this.map.length = this.height;
for (var y = 0; y < this.height; ++y) {
this.map[y] = [];
this.map[y].length = width;
for (var x = 0; x < this.width; ++x) {
this.map[y][x] = Math.random() < 0.2 ?
this.TILE_WALL:
this.TILE_GRASS;
}
this.map[y][0] = this.TILE_WALL;
this.map[y][this.width - 1] = this.TILE_WALL;
}
for (var x = 0; x < this.width; ++x) {
this.map[0][x] = this.TILE_WALL;
this.map[this.height - 1][x] = this.TILE_WALL;
}
}
Map.prototype = {
TILE_WIDTH: 32.0,
TILE_HEIGHT: 32.0,
INV_TILE_WIDTH: 0.0,
INV_TILE_HEIGHT: 0.0,
TILE_AIR: new Tile("#00000000"),
TILE_GRASS: new Tile("#00AA00FF"),
TILE_WALL: new Tile("#555555FF"),
set: function(x,y,tile) {
this.map[y][x] = tile;
},
scaleX: function(x) {
return (x * this.INV_TILE_WIDTH) | 0;
},
scaleY: function(y) {
return (y * this.INV_TILE_HEIGHT) | 0;
},
isColliding: function(x,y) {
return x > -1 && x < this.width
&& y > -1 && y < this.height
&& this.map[y][x].id > 1;
},
render: function(ctx,camera) {
for (var y = 0; y < this.height; ++y) {
for (var x = 0; x < this.width; ++x) {
var tile = this.map[y][x];
var _x = x * this.TILE_WIDTH - camera.x;
var _y = y * this.TILE_HEIGHT - camera.y;
ctx.fillStyle = tile.colour;
ctx.fillRect(_x,_y,this.TILE_WIDTH - 1,this.TILE_HEIGHT - 1);
}
}
}
};
Map.prototype.INV_TILE_WIDTH = 1.0 / Map.prototype.TILE_WIDTH;
Map.prototype.INV_TILE_HEIGHT = 1.0 / Map.prototype.TILE_HEIGHT;
function Player(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
this.dx = 0.0;
this.dy = 0.0;
this.isUp = false;
this.isDown = false;
this.isLeft = false;
this.isRight = false;
}
Player.prototype = {
WIDTH: 20.0,
HEIGHT: 20.0,
ACCELERATION: 1.0,
DEACCELERATION: 0.5,
MAX_SPEED: 3.0,
tick: function(map) {
// Movement
if (this.isUp) {
this.dy -= this.ACCELERATION;
if (this.dy < -this.MAX_SPEED) {
this.dy = -this.MAX_SPEED;
}
} else if (this.dy < 0.0) {
this.dy += this.DEACCELERATION;
if (this.dy > 0.0) {
this.dy = 0.0;
}
}
if (this.isDown) {
this.dy += this.ACCELERATION;
if (this.dy > this.MAX_SPEED) {
this.dy = this.MAX_SPEED;
}
} else if (this.dy > 0.0) {
this.dy -= this.DEACCELERATION;
if (this.dy < 0.0) {
this.dy = 0.0;
}
}
if (this.isLeft) {
this.dx -= this.ACCELERATION;
if (this.dx < -this.MAX_SPEED) {
this.dx = -this.MAX_SPEED;
}
} else if (this.dx < 0.0) {
this.dx += this.DEACCELERATION;
if (this.dx > 0.0) {
this.dx = 0.0;
}
}
if (this.isRight) {
this.dx += this.ACCELERATION;
if (this.dx > this.MAX_SPEED) {
this.dx = this.MAX_SPEED;
}
} else if (this.dx > 0.0) {
this.dx -= this.DEACCELERATION;
if (this.dx < 0.0) {
this.dx = 0.0;
}
}
// Collision
if (this.dx !== 0.0) {
var minY = map.scaleY(this.y);
var maxY = map.scaleY(this.y + this.HEIGHT);
var minX = 0;
var maxX = 0;
if (this.dx < 0.0) {
minX = map.scaleX(this.x + this.dx);
maxX = map.scaleX(this.x);
} else {
minX = map.scaleX(this.x + this.WIDTH);
maxX = map.scaleX(this.x + this.WIDTH + this.dx);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.x = this.dx < 0.0 ?
(x + 1) * map.TILE_WIDTH:
x * map.TILE_WIDTH - this.WIDTH - 1;
this.dx = 0.0;
break loop;
}
}
}
}
if (this.dy !== 0.0) {
var minX = map.scaleX(this.x);
var maxX = map.scaleX(this.x + this.WIDTH);
var minY = 0;
var maxY = 0;
if (this.dy < 0.0) {
minY = map.scaleY(this.y + this.dy);
maxY = map.scaleY(this.y);
} else {
minY = map.scaleY(this.y + this.HEIGHT);
maxY = map.scaleY(this.y + this.HEIGHT + this.dy);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.y = this.dy < 0.0 ?
(y + 1) * map.TILE_HEIGHT:
y * map.TILE_HEIGHT - this.HEIGHT - 1;
this.dy = 0.0;
break loop;
}
}
}
}
this.x += this.dx;
this.y += this.dy;
},
render: function(ctx,camera) {
camera.set(this.x,this.y);
ctx.lineWidth = 1;
ctx.strokeStyle = "black";
ctx.fillStyle = "darkred";
ctx.beginPath();
ctx.rect(this.x - camera.x,this.y - camera.y,this.WIDTH,this.HEIGHT);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var camera = null;
var map = null;
var player = null;
// Functions
function onKeyDown(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = true; break;
case "S": player.isDown = true; break;
case "A": player.isLeft = true; break;
case "D": player.isRight = true; break;
}
}
function onKeyUp(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = false; break;
case "S": player.isDown = false; break;
case "A": player.isLeft = false; break;
case "D": player.isRight = false; break;
}
}
function loop() {
// Tick
player.tick(map);
// Render
ctx.fillStyle = "gray";
ctx.fillRect(-canvasWidth >> 1,-canvasHeight >> 1,canvasWidth,canvasHeight);
map.render(ctx,camera);
player.render(ctx,camera);
//
requestAnimationFrame(loop);
}
// Entry point (first to execute)
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
ctx.translate(canvasWidth >> 1,canvasHeight >> 1);
camera = new Camera(0.0,0.0);
map = new Map(10,10);
player = new Player(40.0,40.0);
map.set(1,1,map.TILE_GRASS);
addEventListener("keydown",onKeyDown);
addEventListener("keyup",onKeyUp);
loop();
}
}();
</script>
</body>
</html>
Firstly, looking at your code, there are some things that are missing which is required to implement basic collision detection and those are:
The player's current direction that he/she is moving in. This is important because it allows the function determining the collision detection to distinguish which side it is checking for the collision (Up, down, left, or right) since a player can only collide with one side at a time.
The tile's position and size. This is also very important because like the first point, there is only one side of the tile that the player can collide with and knowing the size and position can determine if it is a collision or not based on the players size and position.
Also, since you mentioned it is a basic game, the implementation below is a basic collision detection. If you were to make a more complex and bigger game, you should try looking into quad trees for more efficient collision detection:
https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374
Now this is the function for detecting collision, for the sake of readability and shortness, p will represent the player object and t would represent the tile object. This function returns whether or not the player is colliding with a tile based on their direction of movement.
function isColliding(p, t){
if (p.direction == 'up') {
return p.y +(p.height/2)-p.speedY< t.y + t.height && p.y > t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'down') {
return p.y + (p.height/2)+p.speedY > t.y && p.y < t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'right') {
return p.x + p.width+p.speedX > t.x && p.x < t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
if (p.direction == 'left') {
return p.x -p.speedX< t.x + t.width && p.x > t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
return false;
}
You would probably want to put this in the player move function to constantly detect for tiles as it is moving. To do that, you'd want to modify your keydown detection so that with each different keydown, it would update the player's direction, here's a simple example:
document.onkeydown = function(event){
if (event.keyCode == 87)
player.up = true;
else if (event.keyCode == 65)
player.left = true;
else if (event.keyCode == 83)
player.down = true;
else if (event.keyCode == 68)
player.right = true;
}
and another simple example for every time the player moves (user presses a keydown):
const Player= function(/*Param stuff*/){
/*Property stuff*/
//tileArray is the array (or object, your choice) of all the current tiles in the map
this.move=function(tileArray){
//Go through all tiles to see if player is colliding with any of them
for(var t in tileArray){
if(this.up){
if(isColliding(this, tileArray[t]){
//functionality for when player collides
}else{
//functionality for when player doesn't collide
}
}
//check if player is going down, left, etc
}
}
}
These are just examples of how to implement the detection. You should use it as a reference to implement it relatively to how your code function because I didn't write it based on what you posted.
PS.
Make sure to also convert the directions to false after the user stops pressing the key.

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);
}
}

snake game crashes after eating several times with TypeError variable undefined

It's been few days that I've been learning JavaScript. So I'm completely new to this.
This is my code for snake game and it isn't complete yet but I've run into a problem. I'm not completely sure that if it's a logical error or not.
After eating the food several times, the game crashes with
TypeError: snakeBody[l] is undefined.
Screenshot of the error is here.
The entire code is given below:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
canvas {
background: #080d16;
border: 5px solid green;
padding: 0;
}
</style>
</head>
<body>
<canvas id="mycan" class="mycan" width="1860" height="920"></canvas>
<script>
var canvas = document.getElementById('mycan');
var ctx = canvas.getContext('2d');
var snakeSize = 20;
var snakeX = 100;
var snakeY = 100;
var foodX = 310;
var foodY = 310;
var foodSize = 10;
var dx = 20;
var dy = 20;
var leftPressed = false;
var rightPressed = true;
var topPressed = false;
var bottomPressed = false;
var snakeBody = [{x:snakeX,y:snakeY},{x:snakeX-20,y:snakeY}];
var z = 0;
//keypress event listner
document.addEventListener('keypress', keyHandler, false);
//keypress event handler function
function keyHandler(e) {
if (e.keyCode == 37) {
leftPressed = true;
rightPressed = false;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 38) {
leftPressed = false;
rightPressed = false;
topPressed = true;
bottomPressed = false;
} else if (e.keyCode == 39) {
leftPressed = false;
rightPressed = true;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 40) {
leftPressed = false;
rightPressed = false;
topPressed = false;
bottomPressed = true;
}
}
//draw food
function food() {
ctx.beginPath();
ctx.arc(foodX, foodY, foodSize, 0, Math.PI * 2);
ctx.fillStyle = "pink";
ctx.fill();
ctx.closePath();
}
//draw snake
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
function tail() {
if ((snakeX + dx / 2 > foodX - foodSize && snakeX + dx / 2 < foodX + foodSize) && (snakeY + dy / 2 > foodY - foodSize && snakeY + dy / 2 < foodY + foodSize)) {
foodX = (Math.floor(Math.random() * 88) + 1) * 20 + 10;
foodY = (Math.floor(Math.random() * 45) + 1) * 20 + 10;
z++;
if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y < snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y + 20
};
} else if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y > snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y - 20
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x > snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x - 20,
y: snakeBody[snakeBody.length - 1].y
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x < snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x + 20,
y: snakeBody[snakeBody.length - 1].y
};
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
snake();
food();
tail();
if (rightPressed && snakeX + dx < canvas.width) {
snakeX += dx;
} else if (leftPressed && snakeX > 0) {
snakeX += -dx;
} else if (topPressed && snakeY > 0) {
snakeY += -dy;
} else if (bottomPressed && snakeY + dy < canvas.height) {
snakeY += dy;
}
}
setInterval(draw, 80);
</script>
</body>
</html>
You have error in algorithm - your snakeBody put/pops elements and you miss some "corner cases" when use indexes in this array - the problem is not with JS but with algorithm - debug it and also use "triangle" in chrome konsole on left side of error to see more details (stacktrace)
I check and run your code more than once. This error does not appear for me. It is good for you to check the values in snake function and then use them. Modify your snake function to this
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
if(snakeBody && snakeBody[l] && snakeBody[l].hasOwnProperty('x') && snakeBody[l].hasOwnProperty('y')) {
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
}
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
As you can see, snakeBody has no indexes 24 and 25. But this condition satisfy this.

Moving character around on canvas but keping the character in the middle of the screen

I am making a 2d game in JavaScript but my character can only move around the length of the screen so I was wondering if there was a way to make the canvas move but my character stay on the middle of the screen?
This is what I am trying to get it to work like, this is how terrible the game is right now, just because I was trying out a few game mechanics.
Here is my code for the test game
var audio = new Audio('billischill.ddns.net/gameQuest/sounds/theServerRoom.mp3');
audio.play();
// Create the canvas
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function() {
bgReady = true;
};
bgImage.src = "billischill.ddns.net/gameQuest/images/gamemap.png";
//computer
var computerReady = false;
var computerImage = new Image();
computerImage.onload = function() {
computerReady = true;
};
computerImage.src ="billischill.ddns.net/gameQuest/images/computer1.png";
//hp box
var hpBoxReady = false;
var hpBoxImage = new Image();
hpBoxImage.onload = function() {
hpBoxReady = true;
};
hpBoxImage.src = "billischill.ddns.net/gameQuest/images/hpbox.png";
// player image
var playerReady = false;
var playerImage = new Image();
playerImage.onload = function() {
playerReady = true;
};
playerImage.src = "billischill.ddns.net/gameQuest/images/char.png";
// enemy image
var enemyReady = false;
var enemyImage = new Image();
enemyImage.onload = function() {
enemyReady = true;
};
enemyImage.src = "billischill.ddns.net/gameQuest/images/enemy_idle01.png";
var computer = {
wifi: true,
x: 399,
y: 200
}
// Game objects
var hpBox = {
restoreHealth: 34,
x: 300,
y: 300
}
var player = {
hackingSkill : 10,
stamina: 7,
health: 100,
sprintSpeed: 400,
weakSpeed: 150,
speed: 300 // movement in pixels per second
};
var enemy = {
speed: 250,
viewDistance: 40
};
var enemysCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function(e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function(e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a enemy
var reset = function() {
player.x = canvas.width / 2;
player.y = canvas.height / 2;
// Throw the enemy somewhere on the screen randomly
enemy.x = 32 + (Math.random() * (canvas.width - 64));
enemy.y = 32 + (Math.random() * (canvas.height - 64));
};
//w is 87
//a is 65
//s is 83
//d is 68
// Update game objects
var update = function(modifier) {
if (87 in keysDown) { // Player holding up
player.y -= player.speed * modifier;
}
if (83 in keysDown) { // Player holding down
player.y += player.speed * modifier;
}
if (65 in keysDown) { // Player holding left
player.x -= player.speed * modifier;
}
if (68 in keysDown) { // Player holding right
player.x += player.speed * modifier;
}
if (
player.x <= (0)) {
player.health -= 1;
console.log('health decreasing');
}
}
if (
player.y <= (0)) {
player.health -= 1;
console.log('health decreasing');
};
// Are they touching?
if (
player.x <= (enemy.x + 32) &&
enemy.x <= (player.x + 32) &&
player.y <= (enemy.y + 32) &&
enemy.y <= (player.y + 32)
) {
++enemysCaught;
reset();
}
// Draw everything
var render = function() {
if (bgReady) {
context.drawImage(bgImage, 0, 0);
}
if (computerReady) {
context.drawImage(computerImage, computer.x, computer.y);
}
if (hpBoxReady) {
context.drawImage(hpBoxImage, hpBox.x, hpBox.y);
}
if (playerReady) {
context.drawImage(playerImage, player.x, player.y);
}
if (enemyReady) {
context.drawImage(enemyImage, enemy.x, enemy.y);
}
// Score
};
function dieEvent() {
player.health = 100;
}
function updateHealth() {
context.fillStyle = "white";
context.textAlign = "left";
context.fillText("Health: " + player.health, 30, 32);
context.fillStyle="#FF0000";
context.fillRect(10,10,(player.health/100)*140,25);
context.stroke();
}
function updateHackerSkill(){
context.fillStyle = "green";
context.textAlign = "left";
context.fillText("Health: " + player.hackerSkill, 30, 32);
context.fillStyle="#FF0000";
context.fillRect(10,10,(player.hackerSkill/100)*1,45);
context.stroke();
}
function isNearComputer() {
if (player.y <= (computer.y + enemy.viewDistance + 23) &&
player.y >= (computer.y - enemy.viewDistance) &&
player.x <= (computer.x + enemy.viewDistance + 32) &&
player.x >= (computer.x - enemy.viewDistance)) {
console.log("near computer");
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
context.stroke();
context.fillStyle = "green";
context.font = "24px Helvetica";
context.textAlign = "left";
context.textBaseline = "top";
context.fillText("Welcome to uOS v1.0 " , 20 ,10);
window.setTimeout(500);
context.fillText("user$> " , 20 ,35);
}
}
function isNearHPBox() {
if (
player.y <= (hpBox.y + enemy.viewDistance + 64) &&
player.y >= (hpBox.y - enemy.viewDistance - 64) &&
player.x <= (hpBox.x + enemy.viewDistance + 64) &&
player.x >= (hpBox.x - enemy.viewDistance - 64)) {
console.log("healing!");
if (player.health <= 100) {
hpBox.restoreHealth = player.health - 100;
player.health += hpBox.restoreHealth;
}
}
}
function moveEnemy() {
if (
player.y <= (enemy.y + enemy.viewDistance + 64) &&
player.y >= (enemy.y - enemy.viewDistance - 64) &&
player.x <= (enemy.x + enemy.viewDistance + 64) &&
player.x >= (enemy.x - enemy.viewDistance - 64)) {
console.log("seen on enemys Y");
var audio = new Audio('sounds/theWanderer_Scream.m4a');
audio.play();
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
}
}
function checkWallCollision() {
if (player.y <= 0) {
console.log("y")
player.y += 64;
}
if (player.x <= 0) {
console.log("x")
player.x += 64;
}
if (enemy.y <= 0) {
console.log("y")
enemy.y += 64;
}
if (enemy.x <= 0) {
console.log("x")
enemy.x += 64;
}
}
// function updateMouseCoords(){
// document.onmousemove = function(e){
// cursorX = e.pageX;
// cursorY = e.pageY;
// context.fillStyle = "green";
// context.font = "24px Helvetica";
// context.textAlign = "left";
// context.textBaseline = "top";
// context.fillText("x" + cursorX + "y" + cursorY , 20 ,10);
//
// }
// }
// function drawViewLine(){
// var cursorX;
// var cursorY;
// context.beginPath();
// context.moveTo(player.x,player.y);
// context.lineTo(cursorX,cursorY);
// context.stroke();
// console.log("drawing line")
// }
function reducedSpeed() {
player.speed = player.weakSpeed;
}
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
context.clearRect(0, 0, canvas.width, canvas.height);
render();
updateHealth();
moveEnemy();
if (player.health <= 20) {
reducedSpeed();
} else {
player.speed = 300;
}
if (player.health <= 0) {
dieEvent();
}
checkWallCollision();
isNearHPBox();
isNearComputer();
//updateMouseCoords();
//drawViewLine();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
// Let's play this game!
var then = Date.now();
reset();
main();
body {
margin: 0;
padding: 0;
}
<html>
<body>
<canvas id="canvas">
</canvas>
</body>
</html>

Categories

Resources