I am trying to make a simple football penalty game using HTML5/JS Canvas. The aim is to make a game where you control the goal keeper and you have three attempts to save the ball.
I have most of the functionality done, I have a score system and collision detection.
Currently I have a delay on the first attempt. I am however finding difficulty in adding a delay before the ball is shot into the goal in the second and third attempt.
I am using the method requestAnimationFrame() to paint my shapes on my canvas. If there is still attempts available, the ball is positioned to its original location but then there is no delay and fires the ball immediately.
Any advice ? Thanks!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Football</title>
<style>
* { padding: 0; margin: 0; }
canvas { background: #a5bd7b; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
//Sets the original position of the ball
var x = canvas.width/2;
var y = 50;
// Defines values that will be added to the position of x and y values
// List of possible values for the x position
var x_options = [3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0, -0.5, -1, -1.5, -2, -2.5, -3, -3.5];
// Gets a random value from the x_options array
var dx = x_options[Math.floor(Math.random() * x_options.length)];
var dy = 5;
var ballRadius = 10;
// Defines the height and width of the goal
var goal_height = 40;
var goal_width = 200
// Defines the height, width and position of goalie
var goalieHeight = 20;
var goalieWidth = 40;
var goalieX = (canvas.width-goalieWidth)/2;
var goalieY = (canvas.height - goal_height) - 30;
// Set to false by default
var rightPressed = false;
var leftPressed = false;
var goalkeeper_blocked = 0;
var goalkeeper_missed = 0;
var attempts_left = 3;
var attempt1 = true;
var attempt2 = false;
var attempt3 = false;
var footBall = {
shapes : {
ball: function (){
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2, false);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
},
goal : function (){
ctx.beginPath();
ctx.rect((canvas.width - goal_width) / 2 , canvas.height - goal_height, goal_width, goal_height);
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.closePath();
},
goalie : function(){
ctx.beginPath();
ctx.rect(goalieX, goalieY, goalieWidth, goalieHeight);
ctx.fillStyle = "#666666";
ctx.fill();
ctx.closePath();
},
score : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Score: "+goalkeeper_blocked, 8, 20);
},
missed : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Missed: "+goalkeeper_missed, 8, 40);
},
attempts : function(){
ctx.font = "16px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Attempts left: "+attempts_left, canvas.width-110, 20);
}
},
controls : {
keyDownHandler : function (e){
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
},
keyUpHandler : function(e){
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
}
},
calculateScore : function(){
if(goalkeeper_missed > goalkeeper_blocked){
alert("GAME OVER! YOU HAVE LOST!");
document.location.reload();
} else {
alert("GAME OVER! YOU HAVE WON!");
document.location.reload();
}
},
animateBall : function (){
// Sets a delay of 3 second before it shoots
setTimeout(function(){
x += dx;
y += dy;
}, 3000);
},
resetShapePositions : function(){
//Sets the original position of the ball
x = canvas.width/2;
y = 50;
// Sets a new shooting path
dx = x_options[Math.floor(Math.random() * x_options.length)];
dy = 5;
// Resets the goalie to the middle
goalieX = (canvas.width-goalieWidth)/2;
},
draw : function(){
// This ensures that the ball doesn't leave a trail
// Clears the canvas of this shape each frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draws shapes on the canvas
footBall.shapes.ball();
footBall.shapes.goal();
footBall.shapes.goalie();
footBall.shapes.score();
footBall.shapes.missed();
footBall.shapes.attempts();
// adds values to the balls x and y position every frame
footBall.animateBall();
// Ball hits the goal
if(y + dy > canvas.height - goal_height) {
attempts_left--;
goalkeeper_missed++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
} // Ball saved by goalie
else if (x > goalieX && x < goalieX + goalieWidth && y + dy > goalieY - ballRadius){
attempts_left--;
goalkeeper_blocked++;
if (!attempts_left){
footBall.calculateScore();
}
else {
footBall.resetShapePositions();
}
}
// makes paddle move left and right and only within the canvas
if(rightPressed && goalieX < canvas.width-goalieWidth) {
goalieX += 7;
}
else if(leftPressed && goalieX > 0) {
goalieX -= 7;
}
requestAnimationFrame(footBall.draw);
}
}
footBall.draw();
// Defines what functions are fired when keydown or keyup event triggers
document.addEventListener("keydown", footBall.controls.keyDownHandler, false);
document.addEventListener("keyup", footBall.controls.keyUpHandler, false);
</script>
</body>
</html>