I am trying to make bullet objects for my HTML game, but they won't get drawn, even though the background (which is drawn the same way before the bullets) works.
<!DOCTYPE html>
<html>
<head>
<title>
Shooter
</title>
<style>
body{
background-color: blue;
}
canvas{
position: absolute;
top: 50px;
left: 50px;
}
h1{
color: yellow;
position: absolute;
top: 0px;
left: 50px;
}
p{
color: red;
position: absolute;
top: 450px;
left: 50px;
}
</style>
</head>
<body onkeydown='getKeyAndMove(event)'>
<h1>
Shooter
</h1>
<canvas width='800' height='400' id='myCanvas'></canvas>
<p>
Use Up and Down to move, Space to shoot. Don't get hit!
</p>
<script>
var start = null;
var playery = 0;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var radius = 1;
var bullets = [null];
var enemies = new Array(null);
function fire(playery, bullets, enemies){
if (bullets[0] === null){
console.log(9)
bullets[0] = {
x:0,
y:playery,
length:50,
height:25,
update: function(enemies){
bullets[0].x += 5;
var maxCount = enemies.length;
/*for (i=0; i<maxCount; i++){
var enemy = enemies[i];
if (enemy.x <= bullets[0].x + bullets[0].length){
if (enemy.x + enemy.length >= bullets[0].x){
if (enemy.y + enemy.height >= bullets[0].y){
if (enemy.y <= bullets[0].y + bulets[0].height){
enemies[i] = null;
bullets[0] = null;
}
}
}
}
}*/
if (bullets[0].x >= 800){
bullets[0] = null;
return;
}
}
};
}
};
function getKeyAndMove(e){
var key_code=e.which||e.keyCode;
switch(key_code){
case 38:
playery -= 5
break;
case 40:
playery += 5
break;
case 32:
console.log(32)
fire(playery, bullets, enemies);
break;
}
};
function step(timestamp){
if (!start) start = timestamp;
var progress = timestamp - start;
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = 'rgb(0, 0, 0)'
ctx.fillRect(1, 1, canvas.width - 2, canvas.height - 2)
var i=0;
var j=0;
for (i=0; i < 800; i++){
for (j=0; j < 400; j++){
if (Math.random() > 0.9999) {
ctx.beginPath();
ctx.arc(i, j, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'white';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = '#FFFFFF';
ctx.stroke();
ctx.closePath();
}
}
}
if (bullets[0] != null){
bullets[0].update(enemies)
console.log(0)
if(bullets[0] != null){
ctx.fillStyle = '#DD0000'
ctx.fillRect(bullets[0].x, bullets[0].y, bullets[0].width, bullets[0].height)
}
}
window.requestAnimationFrame(step)
}
window.requestAnimationFrame(step)
</script>
</body>
</html>
The console shows no errors when I run the code. I have set it to log every frame that there is a bullet, and the log is showing up, the bullet just never appears.
What am I doing wrong?
I accidentally typed width instead of length in line 126. The problem is solved.
Related
I'm coding Snake Game, but I have an issue.
var ctx = document.getElementById('ctx').getContext('2d');
var canvas = document.getElementById('ctx');
var y = [240, 230, 220];
var x = [240, 240, 240];
var xSpeed = 0;
var ySpeed = 0;
function load() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (p = 0; p < x.length; p++) {
ctx.fillStyle = "black";
ctx.fillRect(x[p], y[p], 10, 10);
}
}
function keyDown() {
var key = event.keyCode; /*getting keyCode of pressed key*/
ctx.fillStyle = "black"; /*color of rectangle*/
switch (key) {
case 39: //RIGHT
xSpeed = 10;
ySpeed = 0;
break;
case 37: //LEFT
xSpeed = -10;
ySpeed = 0;
break;
case 38: //UP
xSpeed = 0;
ySpeed = -10;
break;
case 40: //DOWN
xSpeed = 0;
ySpeed = 10;
break;
}
}
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (x[0] >= 490) {
xSpeed = 0;
} else if (y[0] >= 490) {
ySpeed = 0;
}
//console.clear();
y[0] += ySpeed;
x[0] += xSpeed;
for (i = x.lenght; i >= 0; i--) {
y[i] = y[i - 1];
x[i] = x[i - 1];
console.log(i);
}
for (i = 0; i < x.length; i++) {
ctx.fillStyle = "black";
ctx.fillRect(x[i], y[i], 10, 10);
//console.log("y= " + y[i]);
//console.log("x= " + x[i]);
}
//console.log(xSpeed);
//console.log(ySpeed);
}
setInterval(update, 500);
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="#">
<title>The Snake Game</title>
</head>
<style>
#ctx {
position: absolute;
/*it can be fixed too*/
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
/*this to solve "the content will not be cut when the window is smaller than the content":*/
max-width: 100%;
max-height: 100%;
overflow: auto;
}
</style>
<body onkeydown="keyDown()" onload="load()">
<center><canvas id="ctx" width="500" height="500" style="border:1px solid black"></canvas></center>
</body>
<script src="script.js"></script>
</html>
The for loop inside of update function is not loggin, so it looks like it's not working.
for (i = x.lenght; i >= 0; i--) {
y[i] = y[i - 1];
x[i] = x[i - 1];
console.log(i);
}
I don't know what I've done wrong, but I think it's just another one stupid mistake. Please don't criticize me so much, I'm just nooby 14 y.o. programmer.
Thanks in advice,
Tomas ;-)
On a first sight it's just a typing mistake because you wrote x.lenght instead of x.length.
var ctx = document.getElementById('ctx').getContext('2d');
var canvas = document.getElementById('ctx');
var y = [240, 230, 220];
var x = [240, 240, 240];
var xSpeed = 0;
var ySpeed = 0;
function load() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (p = 0; p < x.length; p++) {
ctx.fillStyle = "black";
ctx.fillRect(x[p], y[p], 10, 10);
}
}
function keyDown() {
var key = event.keyCode; /*getting keyCode of pressed key*/
ctx.fillStyle = "black"; /*color of rectangle*/
// Prevent the snake from going in the reverse direction.
switch (key) {
case 39: //RIGHT
if(xSpeed != -10) {
xSpeed = 10;
ySpeed = 0;
}
break;
case 37: //LEFT
if(xSpeed != 10) {
xSpeed = -10;
ySpeed = 0;
}
break;
case 38: //UP
if(ySpeed != 10) {
xSpeed = 0;
ySpeed = -10;
}
break;
case 40: //DOWN
if(ySpeed != -10) {
xSpeed = 0;
ySpeed = 10;
}
break;
}
}
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (x[0] >= 490) {
xSpeed = 0;
} else if (y[0] >= 490) {
ySpeed = 0;
}
if((xSpeed + ySpeed) != 0) {
for(var idx = x.length - 1; idx >= 1; idx--) {
y[idx] = y[idx - 1];
x[idx] = x[idx - 1];
}
}
y[0] += ySpeed;
x[0] += xSpeed;
for (i = 0; i < x.length; i++) {
ctx.fillStyle = "black";
ctx.fillRect(x[i], y[i], 10, 10);
}
}
setInterval(update, 500);
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="#">
<title>The Snake Game</title>
</head>
<style>
#ctx {
position: absolute;
/*it can be fixed too*/
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
/*this to solve "the content will not be cut when the window is smaller than the content":*/
max-width: 100%;
max-height: 100%;
overflow: auto;
}
</style>
<body onkeydown="keyDown()" onload="load()">
<center><canvas id="ctx" width="500" height="500" style="border:1px solid black"></canvas></center>
</body>
<script src="script.js"></script>
</html>
I really liked your code, especially for how simple it is! So I have added a slightly improved version here. These are the issues I noticed:
Spoilers
In the keyDown function, by adding the condition to check previous speed you can prevent the snake from reversing its direction.
In update function you should update the location of x[0] and y[0] only after updating the "tail" elements. Otherwise, you would not have the new location for the x[1] and y[1] element.
Also, you might need to put an if condition for (xSpeed + ySpeed) != 0 around the loop that updates the location of the tail elements. This would help ensure that the snake doesn't jumble up into single element before the user interacts with it.
The "spaceShip" in the following code isn't moving smoothly at the beginning of holding any arrow key down. It moves one step, freezes for a split second, and then moves "smoothly". How can I make it move smoothly right from the beginning, with not "freezing"?
My code:
<!doctype html>
<html>
<head>
<meta http-content="Content-type" charset="utf-8">
<title>Make body move smoothly</title>
<style type="text/css">
body {
}
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="600"></canvas>
<script type="text/javascript">
// Set up requestAnimationFrame and cancelAnimationFrame
(function() {
var lastTime =0;
var vendors=['ms', 'moz', 'webkit', 'o'];
for(var x=0; x<vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame=window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+ 'CancelAnimationFrame'] ||
window[vendors[x] +'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame=function(callback, element) {
var currTime =new Date().getTime();
var timeToCall =Math.max(0, 16 - (currTime - lastTime));
var id =window.setTimeout(function() { callback(currTime+timeToCall); },
timeToCall);
lastTime =currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame=function(id) {
clearTimeout(id);
};
}());
var canvas;
var ctx;
// ship data
var shipPositionX = document.getElementById('canvas').width/2;
var shipPositionY = document.getElementById('canvas').height - 30;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
function init() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
draw();
}
function draw(){
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
requestAnimationFrame(draw);
}
function clear(){
ctx.clearRect(0, 0, document.getElementById('canvas').width, document.getElementById('canvas').height);
}
function createRectangleToCoverCanvas(){
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function moveSpaceShip(event){
switch(event.keyCode){
// left
case 37:
if(shipPositionX - deltaShipPositionX + 15 > 0){
shipPositionX -= deltaShipPositionX;
}
break;
// up
case 38:
if(shipPositionY - deltaShipPositionY + 15 > 0){
shipPositionY -= deltaShipPositionY;
}
break;
// right
case 39:
if(shipPositionX + deltaShipPositionX < document.getElementById('canvas').width){
shipPositionX += deltaShipPositionX;
}
break;
//down
case 40:
if(shipPositionY + deltaShipPositionY < document.getElementById('canvas').height){
shipPositionY += deltaShipPositionY;
}
break;
}
}
window.addEventListener('load', init);
window.addEventListener('keydown', moveSpaceShip, true);
</script>
</body>
</html>
Notice the difference between my code and this example: http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html
See how the example's is smooth, but my "spaceShip" isn't?
Why is it happening and how can I fix it? Is it because the example uses a sprite (but this doesn't seem to make much sense)?
The problem is that you wait for each keydown event to update the ship position.
The keydown event has a delay before it triggers again : the delay you are experiencing at beginning and the jump you face at each redraw.
The solution here is to trigger the movement on keydown and release it on keyup. This way, your ship will move smoothly as soon as you push the button.
// Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility
// If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById()
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ship data
var shipPositionX = canvas.width / 2;
// Just for the snippet height
var shipPositionY = 0;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
//Removed the init() function, since our elements are loaded.
function draw() {
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function createRectangleToCoverCanvas() {
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.fill();
ctx.stroke();
}
// instantiate a variable that will store our animationFrame id, so we can cancel it further
var raf,
// the direction object, with an x and y values
direction = {
x: 0,
y: 0
};
// we can set a speed variable
var speed = 2.5;
function triggerMoveSpaceShip(event) {
switch (event.keyCode) {
// left
case 37:
// update the direction object
direction.x = -speed;
// avoid the scroll in the snippet
event.preventDefault();
break;
// up
case 38:
direction.y = -speed;
event.preventDefault();
break;
// right
case 39:
direction.x = speed;
event.preventDefault();
break;
//down
case 40:
direction.y = speed;
event.preventDefault();
break;
}
// if we haven't initiated the animation yet, and that our direction is not 0, then do it now
if (!raf && (direction.x || direction.y)) moveSpaceShip();
}
function releaseMoveSpaceShip(event) {;
switch (event.keyCode) {
// left
case 37:
//reset this direction
direction.x = 0;
break;
// up
case 38:
direction.y = 0;
break;
// right
case 39:
direction.x = 0;
break;
//down
case 40:
direction.y = 0;
break;
}
if (!direction.x && !direction.y) {
// if none of the directions is set, stop the animation
cancelAnimationFrame(raf);
raf = undefined;
}
}
function moveSpaceShip() {
// declare our animation function
var move = function() {
// update the positions without going out of the screen
// Sorry, this is dirty...
if(direction.x){
if(
(shipPositionX > 0 && shipPositionX < canvas.width-20) ||
(shipPositionX <= 0 && direction.x > 0) ||
(shipPositionX >= canvas.width-20 && direction.x < 0))
shipPositionX += direction.x;
}
if(direction.y){
if(
(shipPositionY > 0 && shipPositionY < canvas.height-20) ||
(shipPositionY <= 0 && direction.y > 0) ||
(shipPositionY >= canvas.width-20 && direction.y < 0))
shipPositionY += direction.y;
}
// finally draw ou ship
draw();
// update our raf id
raf = requestAnimationFrame(move);
};
// let's go !
raf = requestAnimationFrame(move);
}
draw();
window.addEventListener('keydown', triggerMoveSpaceShip, true);
window.addEventListener('keyup', releaseMoveSpaceShip, true);
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
body{
overflow: none;
}
<canvas id="canvas" width="400" height="200"></canvas>
uncommented fiddle
I am trying to change the number of bouncing balls in a simulation. I am passing the required number using Socket.IO, but I'm struggling to change the number of balls. Here is the JavaScript:
var width = 100,
height = 200,
numBalls,
balls;
$(document).ready(function() {
var socket = io();
socket.on('message', function (data) {
console.log(data.count);
numBalls = data.count
});
$('#myCanvas').click(bounce);
// create an array of balls
balls = new Array(numBalls);
for(i = 0 ; i < numBalls ; i++){
balls[i] = new Ball();
}
});
function Ball(){
// random radius
this.radius = Math.floor(Math.random()*(10-5+1))+5;
// random x and y
this.x = Math.floor(Math.random()*(width-this.radius+1))+this.radius;
this.y = Math.floor(Math.random()*(width-this.radius+1))+this.radius;
// random direction, +1 or -1
this.dx = Math.floor(Math.random()*2) * 2 - 1;
this.dy = Math.floor(Math.random()*2) * 2 - 1;
//random colour, r, g or b
var rcol = Math.floor(Math.random()*3);
this.col = rcol==0 ? "red" :
rcol==1 ? "blue" : "green";
}
// draw the balls on the canvas
function draw(){
var canvas = document.getElementById("myCanvas");
// check if supported
if(canvas.getContext){
var ctx=canvas.getContext("2d");
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.globalAlpha = 0.5;
ctx.strokeStyle="black";
// draw each ball
for(i = 0; i < numBalls ; i++){
var ball = balls[i];
ctx.fillStyle=ball.col;
ctx.beginPath();
// check bounds
// change direction if hitting border
if(ball.x<=ball.radius ||
ball.x >= (width-ball.radius)){
ball.dx *= -1;
}
if(ball.y<=ball.radius ||
ball.y >= (height-ball.radius)){
ball.dy *= -1;
}
// move ball
ball.x += ball.dx;
ball.y += ball.dy;
// draw it
ctx.arc(ball.x, ball.y, ball.radius, 0, 2*Math.PI, false);
ctx.stroke();
ctx.fill();
}
}
else{
//canvas not supported
}
}
// calls draw every 10 millis
function bounce(){
setInterval(draw, 10);
}
Let's say newNumBalls is the new number of balls.
If newNumBalls is less than numBalls, you want to remove elements from balls. You can do that by taking a slice of balls and assigning it to balls.
If newNumBalls is greater than numBalls, you want to make new balls and add them to balls. You can do that with push.
The complete logic is this:
if (newNumBalls < numBalls) {
balls = balls.slice(0, newNumBalls);
} else {
for (var i = numBalls; i < newNumBalls; ++i) {
balls.push(new Ball());
}
}
numBalls = newNumBalls;
Below is a snippet that implements this logic.
var width,
height,
numBalls = 10,
balls;
$('#setNumBalls').click(function () {
var newNumBalls = parseInt($('#inputNumBalls').val(), 10);
if (newNumBalls < numBalls) {
balls = balls.slice(0, newNumBalls);
//$('#display').html('Removed ' + (numBalls - newNumBalls) + ' balls');
} else {
for (var i = numBalls; i < newNumBalls; ++i) {
balls.push(new Ball());
}
//$('#display').html('Added ' + (newNumBalls - numBalls) + ' new balls');
}
numBalls = newNumBalls;
});
$(document).ready(function() {
width = $('#myCanvas').width();
height = $('#myCanvas').height();
var canvas = $('#myCanvas')[0];
canvas.width = width;
canvas.height = height;
$('#inputNumBalls').val(numBalls);
// create an array of balls
balls = new Array(numBalls);
for(i = 0 ; i < numBalls ; i++){
balls[i] = new Ball();
}
bounce();
});
function Ball(){
// random radius
this.radius = Math.floor(Math.random()*(10-5+1))+5;
// random x and y
var margin = 2 * this.radius;
this.x = Math.floor(Math.random()*(width-margin))+margin/2;
this.y = Math.floor(Math.random()*(width-margin+1))+margin/2;
// random direction, +1 or -1
this.dx = Math.floor(Math.random()*2) * 2 - 1;
this.dy = Math.floor(Math.random()*2) * 2 - 1;
//random colour, r, g or b
var rcol = Math.floor(Math.random()*3);
this.col = rcol==0 ? "red" :
rcol==1 ? "blue" : "green";
}
// draw the balls on the canvas
function draw(){
var canvas = $('#myCanvas')[0];
// check if supported
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
//clear canvas
ctx.clearRect(0, 0, width, height);
ctx.globalAlpha = 0.5;
ctx.strokeStyle="black";
// draw each ball
for(var i = 0; i < numBalls ; i++){
var ball = balls[i];
ctx.fillStyle = ball.col;
ctx.beginPath();
// check bounds
// change direction if hitting border
if(ball.x <= ball.radius ||
ball.x >= (width - ball.radius)) {
ball.dx *= -1;
}
if(ball.y <= ball.radius ||
ball.y >= (height - ball.radius)) {
ball.dy *= -1;
}
// move ball
ball.x += ball.dx;
ball.y += ball.dy;
// draw it
ctx.arc(ball.x, ball.y, ball.radius, 0, 2*Math.PI, false);
ctx.stroke();
ctx.fill();
}
}
else{
//canvas not supported
}
}
// Calls draw frameRate times a second.
function bounce() {
var frameRate = 60;
setInterval(draw, 1000 / frameRate);
}
body {
font-family: sans-serif;
}
#myCanvas {
float: left;
margin: 0 10px 0 0;
width: 160px;
height: 160px;
border: 1px solid #888;
}
#inputNumBalls {
font-size: 18px;
padding: 5px 8px;
margin: 5px;
text-align: center;
outline: none;
}
.button {
display: inline;
cursor: pointer;
padding: 2px 8px;
border-radius: 5px;
border: 2px solid #888;
}
.button:hover {
background: #ffd;
border-color: #000;
}
#display {
width: 200px;
height: 50px;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<canvas id="myCanvas"> Canvas not supported. </canvas>
<div>
Number of balls:
<input type="text" id="inputNumBalls" size="3" />
<div class="button" id="setNumBalls">Set</div>
<div id="display"></div>
</div>
I am having issues trying to place an image as an object for an "asteroid avoidance" game. I was able to get the game itself to work based on what was written in my book "Foundation: HTML5 Canvas for Games and Entertainment". I want to go one step beyond what was written in the book. I want to replace the triangle shaped ship with that of an image. However, I am unable to figure out where to put the code for this.draw. My professor showed us a way to do it. When I try to implement it into my code it doesn't want to work properly. May I ask for some advice on how to place the image as the ship?
Here is my working code from the book, before I made any this.draw edits:(http://jsbin.com/tukejopofo/1/)
$(document).ready(function() {
var canvas = $("#gameCanvas");
var context = canvas.get(0).getContext("2d");
//canvas dimensions
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
var playGame;
var asteroids;
var numAsteroids;
var player;
var score;
var scoreTimeout;
var arrowUp = 38;
var arrowRight = 39;
var arrowDown = 40;
var arrowLeft = 37;
//game UI
var ui = $("#gameUI");
var uiIntro = $("#gameIntro");
var uiStats = $("#gameStats");
var uiComplete = $("#gameComplete");
var uiPlay = $("#gamePlay");
var uiReset = $(".gameReset");
var uiScore = $(".gameScore");
var soundBackground = $("#gameSoundBackground").get(0);
var soundThrust = $("#gameSoundThrust").get(0);
var soundDeath = $("#gameSoundDeath").get(0);
var Asteroid = function(x, y, radius, vX) {
this.x = x;
this.y = y;
this.radius = radius;
this.vX = vX;
};
var Player = function(x, y) {
this.x = x;
this.y = y;
this.width = 24;
this.height = 24;
this.halfWidth = this.width / 2;
this.halfHeight = this.height / 2;
this.flameLength1 = 20;
this.flameLength2 = 20;
this.vX = 0;
this.vY = 0;
this.moveRight = false;
this.moveUp = false;
this.moveDown = false;
this.moveLeft = false;
};
//Reset and start the game
function startGame() {
//Reset game stats
uiScore.html("0");
uiStats.show();
//set up initial game settings
playGame = false;
asteroids = new Array();
numAsteroids = 10;
score = 0;
player = new Player(150, canvasHeight / 2, 50, 50);
for (var i = 0; i < numAsteroids; i++) {
var radius = 5 + (Math.random() * 10);
var x = canvasWidth + radius + Math.floor(Math.random() * canvasWidth);
var y = Math.floor(Math.random() * canvasHeight);
var vX = -5 - (Math.random() * 5);
asteroids.push(new Asteroid(x, y, radius, vX));
};
$(window).keydown(function(e) {
var keyCode = e.keyCode;
if (!playGame) {
playGame = true;
soundBackground.currentTime = 0;
soundBackground.play();
animate();
timer();
};
if (keyCode == arrowRight) {
player.moveRight = true;
if (soundThrust.paused) {
soundThrust.currentTime = 0;
soundThrust.play();
}
} else if (keyCode == arrowLeft) {
player.moveLeft = true;
} else if (keyCode == arrowUp) {
player.moveUp = true;
} else if (keyCode == arrowDown) {
player.moveDown = true;
}
});
$(window).keyup(function(e) {
var keyCode = e.keyCode;
if (!playGame) {
playGame = true;
animate();
};
if (keyCode == arrowRight) {
player.moveRight = false;
if (keyCode == arrowRight) {
player.moveRight = false;
soundThrust.pause();
}
} else if (keyCode == arrowUp) {
player.moveUp = false;
} else if (keyCode == arrowDown) {
player.moveDown = false;
} else if (keyCode == arrowLeft) {
player.moveLeft = false;
}
});
//start the animation loop
animate();
};
//initialize the game environment
function init() {
uiStats.hide();
uiComplete.hide();
uiPlay.click(function(e) {
e.preventDefault();
uiIntro.hide();
startGame();
});
uiReset.click(function(e) {
e.preventDefault();
uiComplete.hide();
$(window).unbind("keyup");
$(window).unbind("keydown");
soundThrust.pause();
soundBackground.pause();
clearTimeout(scoreTimeout);
startGame();
});
};
function timer() {
if (playGame) {
scoreTimeout = setTimeout(function() {
uiScore.html(++score);
if (score % 5 == 0) {
numAsteroids += 5;
}
timer();
}, 1000);
};
};
//Animation loop that does all the fun stuff
function animate() {
//Clear
context.clearRect(0, 0, canvasWidth, canvasHeight);
var asteroidsLength = asteroids.length;
for (var i = 0; i < asteroidsLength; i++) {
var tmpAsteroid = asteroids[i];
tmpAsteroid.x += tmpAsteroid.vX;
if (tmpAsteroid.x + tmpAsteroid.radius < 0) { //creates bounderies to prevent player from leaving the canvas
tmpAsteroid.radius = 5 + (Math.random() * 10);
tmpAsteroid.x = canvasWidth + tmpAsteroid.radius;
tmpAsteroid.y = Math.floor(Math.random() * canvasHeight);
tmpAsteroid.vX = -5 - (Math.random() * 5);
}
var dX = player.x - tmpAsteroid.x;
var dY = player.y - tmpAsteroid.y;
var distance = Math.sqrt((dX * dX) + (dY * dY));
if (distance < player.halfWidth + tmpAsteroid.radius) { //checks for collision
soundThrust.pause()
soundDeath.currentTime = 0;
soundDeath.play();
//Game over
playGame = false;
clearTimeout(scoreTimeout);
uiStats.hide();
uiComplete.show();
soundBackground.pause();
$(window).unbind("keyup"); //unbinds keys to stop player movement at the end of the game
$(window).unbind("keydown");
};
context.fillStyle = "rgb(255, 255, 255)";
context.beginPath();
context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI * 2, true);
context.fill();
};
player.vX = 0;
player.vY = 0;
if (player.moveRight) {
player.vX = 3;
};
if (player.moveLeft) {
player.vX = -3;
};
if (player.moveUp) {
player.vY = -3;
};
if (player.moveDown) {
player.vY = 3;
};
player.x += player.vX;
player.y += player.vY;
if (player.x - player.halfWidth < 20) {
player.x = 20 + player.halfWidth;
} else if (player.x + player.halfWidth > canvasWidth - 20) {
player.x = canvasWidth - 20 - player.halfWidth;
}
if (player.y - player.halfHeight < 20) {
player.y = 20 + player.halfHeight;
} else if (player.y + player.halfHeight > canvasHeight - 20) {
player.y = canvasHeight - 20 - player.halfHeight;
}
if (player.moveRight) {
context.save();
context.translate(player.x - player.halfWidth, player.y);
if (player.flameLength1 == 20) {
player.flameLength1 = 15;
(player.flameLength2 == 20)
player.flameLength2 = 15;
} else {
player.flameLength1 = 20;
player.flameLength2 = 20;
};
context.fillStyle = "orange";
context.beginPath();
context.moveTo(0, -12);
context.lineTo(-player.flameLength1, -7);
context.lineTo(0, -5);
context.closePath();
context.fill();
context.fillStyle = "orange";
context.beginPath();
context.moveTo(0, 12);
context.lineTo(-player.flameLength2, 7);
context.lineTo(0, 5);
context.closePath();
context.fill();
context.restore();
};
//draw ship
context.fillStyle = "rgb(255, 0, 0)";
context.beginPath();
context.moveTo(player.x + player.halfWidth, player.y);
context.lineTo(player.x - player.halfWidth, player.y - player.halfHeight);
context.lineTo(player.x - player.halfWidth, player.y + player.halfHeight);
context.closePath();
context.fill();
while (asteroids.length < numAsteroids) { //adds asteroids as the difficulty increases
var radius = 5 + (Math.random() * 10)
var x = Math.floor(Math.random() * canvasWidth) + canvasWidth + radius;
var y = Math.floor(Math.random() * canvasHeight);
var vX = -5 - (Math.random() * 5);
asteroids.push(new Asteroid(x, y, radius, vX));
}
if (playGame) {
//run the animation loop again in 33 milliseconds
setTimeout(animate, 24);
};
};
init();
});
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
width: 100%;
}
canvas {
display: block;
}
body {
background: #000;
color: #fff;
font-family: Verdana, Arial, sans-serif;
font-size: 18px;
}
h1 {
font-size: 30px;
}
h6 {
font-size: 15px;
}
p {
margin: 0 20px;
}
a {
color: #fff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a.button {
background: #185da8;
border-radius: 5px;
display: block;
font-size: 30px;
margin: 40px 0 0 350px;
padding: 10px;
width: 200px;
text-align: center;
}
a.button:hover {
background: #2488f5;
color: #fff;
text-decoration: none;
}
#game {
height: 600px;
left: 50%;
margin: -250px 0 0 -500px;
position: relative;
top: 50%;
width: 980px;
}
#gameCanvas {
background: #001022;
border: 5px solid green;
background-image: url(../images/space.jpg);
background-position: center top;
background-repeat: no-repeat;
background-size: cover;
}
#gameUI {
height: 600px;
position: absolute;
width: 980px;
}
#gameIntro,
#gameComplete {
background: rgba(0, 0, 0, 0.5);
margin: 100px 0 0 10px;
padding: 40px 0;
text-align: center;
}
#gameStats {
font-size: 14px;
margin: 20px 0;
}
#gameStats .gameReset {
margin: 20px 20px 0 0;
position: absolute;
right: 0;
top: 0;
}
<body>
<div id="game">
<div id="gameUI">
<div id="gameIntro">
<h1>Debris Fields of Spiral Galaxy</h1>
<h6>A <i>Galaxy Smuggler's Run</i> Game</h6>
<hr>
<p>You are Captain Amadaeus delivering goods to a dependent planet on the other side of a debris field</p>
<p>Click <i>"Play"</i> and then press any key to start.</p>
<p><a id="gamePlay" class="button" href="">Play!</a>
</p>
</div>
<div id="gameStats">
<p><b>Time: </b><span class="gameScore"></span> seconds</p>
<p><a class="gameReset" href="">Reset</a>
</p>
</div>
<div id="gameComplete">
<h1>Game Over!</h1>
<p>You survived for <span class="gameScore"></span> seconds.</p>
<p>Would you like to give it another go?</p>
<p><a class="gameReset button" href="">Play Again?</a>
</p>
</div>
</div>
<canvas id="gameCanvas" width="980" height="600">
</canvas>
<audio id="gameSoundBackground" loop>
<source src="sounds/background.ogg">
<source src="sounds/background.mp3">
</audio>
<audio id="gameSoundThrust" loop>
<source src="sounds/thrust.ogg">
<source src="sounds/thrust.mp3">
</audio>
<audio id="gameSoundDeath">
<source src="sounds/death.ogg">
<source src="sounds/death.mp3">
</audio>
</div>
</body>
and here is my Professor's code for drawing an image:(http://jsbin.com/rapayufafe/1/)
// JS file for the ship
function Ship() {
this.x = 100;
this.y = 100;
this.color = "yellow";
this.fillStyle = "white";
this.vx = 0;
this.vy = 0;
this.ax = 1;
this.ay = 1;
//function "move" that will add velocity to the position of the ship
this.move = function() {
this.x += this.vx;
this.y += this.vy;
}//end move function
//draw the ship
this.draw=function () {
//ship var
var imageObj = new Image();
imageObj.src = "images/ship.png";
//save the current state of the canvas
context.save();
//moving the point of origin (0,0) to the ships x and y coordinates
context.translate(this.x,this.y);
context.lineStyle = this.color;
context.fillStyle = this.fillStyle;
/*context.beginPath();
context.moveTo(25,0);
context.lineTo(-25,25)
context.lineTo(-25,-25)*/
//draw ship
context.drawImage(imageObj,-25,-25,50,50);
context.closePath();
context.stroke();
context.fill();
context.restore();
}//end of draw ship
}//end ship function
/*var asteroidsLength = asteroids.length;
for (var i = 0; i < asteroidsLength; i++) {
var tmpAsteroid = asteroids[i];
context.fillStyle = "gray";
context.beginPath();
context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
};*/
As you can see in your starting code, you have a section looking like this:
//draw ship
context.fillStyle = "rgb(255, 0, 0)";
context.beginPath();
context.moveTo(player.x + player.halfWidth, player.y);
context.lineTo(player.x - player.halfWidth, player.y - player.halfHeight);
context.lineTo(player.x - player.halfWidth, player.y + player.halfHeight);
context.closePath();
context.fill();
Just replace that code with the code for drawing an image.
var imageObj = new Image();
imageObj.src = "images/ship.png";
context.drawImage(imageObj,player.x,player.y);
Although, I'd recommend declaring the imageObj and setting the source at the top of your code where you declare the rest of your variables so that you don't load the image every time you want to draw the ship.
I apologize in advance if what I say makes little to no sense, I am still new to Javascript coding.
I am trying to create a "Asteroid Avoidance" game, using the Javascript code taken from Chapter 9 of "Foundation: HTML5 Canvas for Games and Environment". My issue is I can not get the "player's ship" to move. it seems locked in place in the upper left corner of the screen. I can not figure out how to get the ship to move even though I have variables for the key codes and what to do for the "keyup" and "keydown".
I am not getting any syntax errors, so I am guessing I have code in the wrong place, I am just not sure where. If I may ask, can I get an extra pair of eyes to be able to see where I went wrong?
Here is the jsbin (http://jsbin.com/dunaxakifu/)
$(document).ready(function(){
var canvas = $("#gameCanvas");
var context = canvas.get(0).getContext("2d");
//Canvas Dimension
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
//Game Settings
var playGame;
var asteroids;
var numAsteroids;
var player;
//Scoring
var score;
var scoreTimeout;
//Key codes
var arrowUp = 38;
var arrowRight = 39;
var arrowDown = 40;
//Game UI
var ui = $("#gameUI");
var uiIntro = $("#gameIntro");
var uiStats = $("#gameStats");
var uiComplete = $("#gameComplete");
var uiPlay = $("#gamePlay");
var uiReset = $(".gameReset");
var uiScore = $(".gameScore");
var soundBackground = $("#gameSoundBackground").get(0);
var soundThrust = $("#gameSoundThrust").get(0);
var soundDeath = $("#gameSoundDeath").get(0);
var Asteroid = function(x, y, radius, vX){
this.x = x;
this.y = y;
this.radius = radius;
this.vX = vX;
};
var Player = function(x, y){
this.x = x;
this.y = y;
this.width = 24;
this.height = 24;
this.halfWidth = this.width/2;
this.halfHeight = this.height/2;
this.vX = 0;
this.vY = 0;
this.moveRight = false;
this.moveUp = false;
this.moveDown = false;
this.flameLength = 20;
};
//Reset and start the game
function startGame() {
//Reset game stats
uiScore.html("0");
uiStats.show();
asteroids = new Array();
numAsteroids = 10;
score = 0;
for (var i = 0; i < numAsteroids; i++){
var radius = 5+(Math.random()*10);
var x = canvasWidth+radius+Math.floor(Math.random()*canvasWidth);
var y = Math.floor(Math.random()*canvasHeight);
var vX = -5-(Math.random()*5);
asteroids.push(new Asteroid(x, y, radius, vX));
};
player = new Player(150, canvasHeight/2);
//Set up initial game settings
playGame = false;
//Keyboard events
$(window).keydown(function(e){
var keyCode = e.keyCode;
if (!playGame){
playGame = true;
soundBackground.currentTime = 0;
soundBackground.play();
animate();
timer();
};
if (keyCode == arrowRight){
player.moveRight = true;
} else if (keyCode == arrowUp){
player.moveUp = true;
} else if (keyCode == arrowDown){
player.moveDown = true;
};
if (soundThrust.paused){
soundThrust.currentTime = 0;
soundThrust.play();
};
});
$(window).keyup(function(e){
var keyCode = e.keyCode;
if (keyCode == arrowRight){
player.moveRight = false;
} else if (keyCode == arrowUp){
player.moveUp = false;
} else if (keyCode == arrowDown){
player.moveDown = false;
};
soundThrust.pause();
});
//Start the animation loop
animate();
};
//Initialize the game environment
function init() {
uiStats.hide();
uiComplete.hide();
uiPlay.click(function(e){
e.preventDefault();
uiIntro.hide();
startGame();
});
$(window).unbind("keyup");
$(window).unbind("keydown");
uiReset.click(function(e){
e.preventDefault();
uiComplete.hide();
startGame();
soundThrust.pause();
soundBackground.pause();
clearTimeout(scoreTimeout);
});
};
//Timer
function timer(){
if(playGame){
scoreTimeout = setTimeout(function(){
uiScore.html(++score);
if (score % 5 == 0) {
numAsteroids += 5;
};
timer();
}, 1000);
};
};
//Animation loop that does all the fun stuff
function animate(){
//Clear
context.clearRect(0, 0, canvasWidth, canvasHeight);
var asteroidsLength = asteroids.length;
for (var i = 0; i < asteroidsLength; i++){
var tmpAsteroid = asteroids[i];
var dX = player.x - tmpAsteroid.x;
var dY = player.y - tmpAsteroid.y;
var distance = Math.sqrt((dX*dY)+(dY*dY));
if (distance < player.halfWidth+tmpAsteroid.radius){
soundThrust.pause();
soundDeath.currentTime = 0;
soundDeath.play();
//Game over
playGame = false;
clearTimeout(scoreTimeout);
uiStats.hide();
uiComplete.show();
soundBackground.pause();
$(window).unbind("keyup");
$(window).unbind("keydown");
};
if(tmpAsteroid.x+tmpAsteroid.radius < 0){
tmpAsteroid.radius = 5+(Math.random()*10);
tmpAsteroid.x = canvasWidth+tmpAsteroid.radius;
tmpAsteroid.y = Math.floor(Math.random()*canvasHeight);
tmpAsteroid.vX = -5-(Math.random()*5);
};
tmpAsteroid.x += tmpAsteroid.vX;
context.fillStyle = "rgb(255, 255, 255)";
context.beginPath();
context.arc(tmpAsteroid.x, tmpAsteroid.y, tmpAsteroid.radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
player.vX = 0;
player.vY = 0;
if (player.moveRight){
player.vX = 3;
} else {
player.vX = -3;
};
if (player.moveUp){
player.vy = 3;
};
if (player.moveDown){
player.vy = 3;
};
player.x = player.vX;
player.y = player.vY;
if (player.moveRight){
context.save();
context.translate(player.x-player.halfWidth, player.y);
if (player.flameLength == 20) {
player.flameLength = 15;
} else {
player.flameLength = 20;
};
};
if (player.x-player.halfWidth < 20){
player.x = 20+player.halfWidth;
} else if (player.x+player.halfWidth > canvasWidth-20) {
player.x = canvasWidth-20-player.halfWidth;
}
if (player.y-player.halfHeight < 20){
player.y = 20+player.halfHeight;
} else if (player.y+player.halfHeight > canvasHeight-20) {
player.y = canvasHeight-20-player.halfHeight;
};
context.fillStyle = "orange";
context.beginPath();
context.moveTo(0, -5);
context.lineTo(-player.flameLength, 0);
context.lineTo(0, 5);
context.closePath();
context.fill();
context.restore();
context.fillStyle = "rgb(255, 0, 0)";
context.beginPath();
context.moveTo(player.x+player.halfWidth, player.y);
context.lineTo(player.x-player.halfWidth, player.y-player.halfHeight);
context.lineTo(player.x-player.halfWidth, player.y+player.halfHeight);
context.closePath();
context.fill();
while (asteroids.length < numAsteroids){
var radius = 5+(Math.random()*10);
var x = Math.floor(Math.random()*canvasWidth)+canvasWidth+radius;
var y = Math.floor(Math.random()*canvasHeight);
var vX = -5-(Math.random()*5);
asteroids.push(new Asteroid(x, y, radius, vX));
};
};
if (playGame){
//run the animation loop again in 33 milliseconds
setTimeout(animate, 33);
};
};
init();
});
* {
margin:0;
padding:0;
}
html,body {
height:100%;
width:100%;
}
canvas {
display:block;
}
body{
background:#000;
color:#fff;
font-family:Verdana, Arial, sans-serif;
font-size:18px;
}
h1{
font-size:30px;
}
h6{
font-size:15px;
}
p{
margin:0 20px;
}
a{
color:#fff;
text-decoration:none;
}
a:hover{
text-decoration:underline;
}
a.button{
background:#185da8;
border-radius:5px;
display:block;
font-size:30px;
margin:40px 0 0 270px;
padding:10px;
width:200px;
text-align:center;
}
a.button:hover{
background:#2488f5;
color:#fff;
text-decoration:none;
}
#game{
height:600px;
left:50%;
margin:-300px 0 0 -400px;
position:relative;
top:50%;
width:980px;
}
#gameCanvas{
background:#001022;
border:5px solid green;
background-image:url(../images/space.jpg);
background-position:center top;
background-repeat:no-repeat;
background-size:cover;
}
#gameUI{
height:600px;
position:absolute;
width:980px;
}
#gameIntro, #gameComplete {
background:rgba(0, 0, 0, 0.5);
margin-top: 100px;
padding:40px 0;
text-align:center;
}
#gameStats{
font-size:14px;
margin:20px 0;
}
#gameStats .gameReset{
margin:20px 20px 0 0;
position:absolute;
right:0;
top:0;
}
<!Doctype HTML>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<title>Debris Fields of Spiral Galaxy</title>
<meta charset="utf-8">
<link href="css/game.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="js/jquery-2-1-4min.js"></script>
<script type="text/javascript" src="js/game.js"></script>
</head>
<body>
<div id="game">
<div id="gameUI">
<div id="gameIntro">
<h1>Debris Fields of Spiral Galaxy</h1>
<h6>A <i>Galaxy Smuggler's Run</i> Game</h6>
<p>Click "Play" and then press any key to start.</p>
<p><a id="gamePlay" class="button" href="">Play!</a></p>
</div>
<div id="gameStats">
<p>Time: <span class="gameScore"></span> seconds</p>
<p><a class="gameReset" href="">Reset</a></p>
</div>
<div id="gameComplete">
<h1>Game Over!</h1>
<p>You survived for <span class="gameScore"></span> seconds.</p>
<p><a class="gameReset button" href="">Play Again?</a></p>
</div>
</div>
<canvas id="gameCanvas" width="980" height="600">
</canvas>
<audio id="gameSoundBackground" loop>
<source src="sounds/background.ogg">
<source src="sounds/background.mp3">
</audio>
<audio id="gameSoundThrust" loop>
<source src="sounds/thrust.ogg">
<source src="sounds/thrust.mp3">
</audio>
<audio id="gameSoundDeath">
<source src="sounds/death.ogg">
<source src="sounds/death.mp3">
</audio>
</div>
</body>
</html>
There is a lot of code there, try calling the movement functions directly on the Player object
Player.prototype.moveUp = function() {
this.y++;
}
Player.prototype.moveDown = function() {
this.y--;
}
$(window).keyDown(function(key) {
if(key == x) {
Player.moveUp();
}
else if (key == y) {
Player.moveDown();
}
});
Not sure this will make a difference at all, its just the way I do it :B
Not sure if this is the only problem but in your animation loop you are using player.vY and player.vy (note the difference in upper/lowercase 'Y').
Also in the animation loop player.vy seems to be given the same value for up and down
if (player.moveUp){
player.vy = 3;
};
if (player.moveDown){
player.vy = 3;
};
And I am not sure but I thought I saw if(player.moveDown) (again in the code above) evaluate to true when I hit the right arrow. I didnt look further to see if this was intentional/ desired or the result of hitting arrow down before right arrow and perhaps moveDown was not reset etc.