Canvas is displaying a single object instead of multiple - javascript

I've created a script for a bouncing ball, and I wanted to try to add another ball to make it more interesting. But the code doesn't seem to work and add another ball as I'm trying to do. I want to use the same function to do that because its more compact and flexible.
function startGame() {
GameArea.start();
Ball = new CircComp('red' , window.innerWidth/ 2 , window.innerHeight / 2.5 );
Ball.yAngle = 10;
Ball.xAngle = 10;
Ball.radius = 20;
Ball1 = new CircComp('green' , window.innerWidth/ 2 , window.innerHeight / 2.5 );
Ball1.yAngle = -10;
Ball1.xAngle = -10;
Ball1.radius = 20;
}
var GameArea = {
canvas : canvas = document.querySelector("canvas"),
start : function (){
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function CircComp(color, x , y){
this.x = x;
this.y = y;
context = GameArea.ctx;
this.update = function(){
context.beginPath();
context.fillStyle = color;
context.arc(this.x,this.y,this.radius,0,2*Math.PI);
context.fill();
context.stroke();
}
this.updateGameComp = function(){
GameArea.clear();
this.y += this.yAngle;
this.x += this.xAngle;
if(this.x + this.radius > GameArea.canvas.width){
this.xAngle = -1 * this.xAngle;
}
if(this.y + this.radius > GameArea.canvas.height){
this.yAngle = -1 * this.yAngle;;
}
if(this.x - this.radius < 0){
this.xAngle = -1 * this.xAngle;
}
if(this.y - this.radius < 0){
this.yAngle = -1 * this.yAngle;
}
this.update();
}
}
function updateGameArea(){
Ball.updateGameComp();
Ball1.updateGameComp();
}
<html>
<head>
<meta charset='urf-8'>
<style>
canvas{
border: 0px solid black;
}
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body onload='startGame()'>
<canvas></canvas>
<script src='Pong.js'></script>
</body>
</html>

Both CircComp objects call GameArea.clear() in updateGameComp. You should only clear the canvas once, before drawing anything, probably in updateGameArea.

Related

JS/HTML/CSS animation game -- only select animations freeze

I'm following a tutorial on using vanilla JS/HTML/CSS to create a 2D animation game. I'm currently stuck, however, because some of my "spiders" become stuck in their path, and won't moveā€”and some of them do so out of the screen such that their webs are visible and won't disappear. I went back to the tutorial's code and tried to find any differences in the code, but couldn't find any. I've been playing around with the vertical values, as well as the part where I deal with animation frames, but couldn't fix the bug.
Could someone please help me figure out what I'm doing wrong?
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 800;
class Game {
constructor(ctx, width, height) {
this.ctx = ctx;
this.width = width;
this.height = height;
this.enemies = [];
this.enemyInterval = 400;
this.enemyTimer = 0;
this.enemyTypes = ["worm", "ghost", "spider"];
}
update(deltaTime) {
this.enemies = this.enemies.filter(object => !object.markedForDeletion);
if (this.enemyTimer > this.enemyInterval) {
this.#addNewEnemy();
this.enemyTimer = 0;
} else {
this.enemyTimer += deltaTime;
}
this.enemies.forEach(object => object.update(deltaTime));
}
draw() {
this.enemies.forEach(object => object.draw(this.ctx));
}
#addNewEnemy() {
const randomEnemy = this.enemyTypes[Math.floor(Math.random() * this.enemyTypes.length)];
if (randomEnemy === "worm") this.enemies.push(new Worm(this));
else if (randomEnemy === "ghost") this.enemies.push(new Ghost(this));
else if (randomEnemy === "spider") this.enemies.push(new Spider(this));
// this.enemies.sort(function(a, b) {
// return a.y - b.y;
// });
}
}
class Enemy {
constructor(game) {
this.game = game;
this.markedForDeletion = false;
this.frameX = 0;
this.maxFrame = 5;
this.frameInterval = 100;
this.frameTimer = 0;
}
update(deltaTime) {
this.x -= this.vx * deltaTime;
if (this.x < 0 - this.width) this.markedForDeletion = true;
if (this.frameTimer > this.frameInterval) {
if (this.frameX < this.maxFrame) this.frameX++;
else this.frameX = 0;
this.frameTimer = 0;
} else {
this.frameTimer += deltaTime;
}
}
draw(ctx) {
ctx.drawImage(this.image, this.frameX * this.spriteWidth, 0, this.spriteWidth, this.spriteHeight, this.x, this.y, this.width, this.height);
}
}
class Spider extends Enemy{
constructor() {
super(game);
this.spriteWidth = 310;
this.spriteHeight = 175;
this.width = this.spriteWidth/2;
this.height = this.spriteHeight/2;
this.x = Math.random() * this.game.width;
this.y = 0 - this.height;
this.image = spider;
this.vx = 0;
this.vy = Math.random() * 0.1 + 0.1;
this.maxLength = Math.random() * this.game.height * 0.7;
}
update(deltaTime) {
super.update(deltaTime);
if (this.y < 0 - this.height * 1.5) this.markedForDeletion = true;
this.y += this.vy * deltaTime;
if (this.y > this.maxLength) this.vy *= -1;
}
draw(ctx) {
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, 0);
ctx.lineTo(this.x + this.width/2, this.y + 10);
ctx.stroke();
super.draw(ctx);
}
}
const game = new Game(ctx, canvas.width, canvas.height);
let lastTime = 1;
function animate(timeStamp) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
game.update(deltaTime);
game.draw();
requestAnimationFrame(animate);
}
animate(0);
})
#canvas1 {
border: 3px solid black;
width: 500px;
height: 800px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
img {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enemy Variety</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<img src="images/enemy_worm.png" id="worm">
<img src="images/enemy_ghost.png" id="ghost">
<img src="images/enemy_spider.png" id="spider">
<script src="script.js"></script>
</body>
</html>
Apologies for the current snippet not working. I assume it's because I can't find a way to upload the image with the code, but I'm attaching it here for reference: https://www.frankslaboratory.co.uk/downloads/enemy_spider.png (Warning: this image is only to be used for educational purposes)
In the draw() method inside the Spider class, you must call super.draw() before running other code:
draw(ctx) {
super.draw(ctx);
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, 0);
ctx.lineTo(this.x + this.width/2, this.y + 10);
ctx.stroke();
}

Javascript Canvas Flashing When Drawing Frames

Been having issues with this for a couple days, not sure why the text I'm rendering on the canvas is flashing so much. I'm using the requestAnimationFrame() function, but its still flickering.
What I want to have happen is for the text to move smoothly and they remove themselves from the array when they move completely off screen.
var canvas = document.getElementById("myCanvas");
var c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var w = canvas.width;
var h = canvas.height;
var texts = [];
window.addEventListener("load", init);
function init() {
draw();
mainLoop();
}
function mainLoop() {
texts.push(createText("wow", "blue"));
texts.push(createText("wow", "green"));
texts.push(createText("wow", "red"));
setTimeout(function() { mainLoop(); }, 100);
}
function Text(x, y, vx, vy, varText, theColor){
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = theColor;
this.draw = function() {
drawStroked(varText, this.x, this.y, this.color);
}
}
function drawStroked(text, x, y, color) {
c.font = "30px bold Comic Sans MS";
c.strokeStyle = 'black';
c.lineWidth = 8;
c.strokeText(text, x, y);
c.fillStyle = color;
c.fillText(text, x, y);
}
function createText(varText, color) {
var x = (Math.random() * w / 2 ) + w/4;
var y = (Math.random() * h / 2) + h/2;
var vx = (Math.random() * .5) - .25
var vy = -(Math.random() * 3) - 1
return new Text(x, y, vx, vy, varText, color);
}
function draw() {
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(var i = 0;i < texts.length; i++) {
var currentText = texts[i];
currentText.x += currentText.vx;
currentText.y += currentText.vy;
currentText.draw();
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i, 1);
}
}
requestAnimationFrame(draw);
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<title>Game Screen</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
The flickering you are seeing results from your looping code, where you skip elements of the array when deleting elements (Element 3 needs to be deleted? You call splice(3, 1) and then continue with the loop at index 4. Since the array shifts when you call splice, you should process element 3 again).
The imho easiest way to fix this is to iterate backwards over the array. Please note that iterating backwards is less CPU cache efficient (because every array access leads to a cache miss), so another fix would be
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i--, 1); // decrement i after accessing and deleting
}
var canvas = document.getElementById("myCanvas");
var c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var w = canvas.width;
var h = canvas.height;
var texts = [];
window.addEventListener("load", init);
function init() {
draw();
mainLoop();
}
function mainLoop() {
texts.push(createText("wow", "blue"));
texts.push(createText("wow", "green"));
texts.push(createText("wow", "red"));
setTimeout(function() { mainLoop(); }, 100);
}
function Text(x, y, vx, vy, varText, theColor){
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = theColor;
this.draw = function() {
drawStroked(varText, this.x, this.y, this.color);
}
}
function drawStroked(text, x, y, color) {
c.font = "30px bold Comic Sans MS";
c.strokeStyle = 'black';
c.lineWidth = 8;
c.strokeText(text, x, y);
c.fillStyle = color;
c.fillText(text, x, y);
}
function createText(varText, color) {
var x = (Math.random() * w / 2 ) + w/4;
var y = (Math.random() * h / 2) + h/2;
var vx = (Math.random() * .5) - .25
var vy = -(Math.random() * 3) - 1
return new Text(x, y, vx, vy, varText, color);
}
function draw() {
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(var i = texts.length - 1;i >= 0; i--) {
var currentText = texts[i];
currentText.x += currentText.vx;
currentText.y += currentText.vy;
currentText.draw();
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i, 1);
}
}
requestAnimationFrame(draw);
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<title>Game Screen</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>

Initializing a possibly infinite array?

I'm attempting to make sand fall from the mouse (i've changed the x and y of the sand to be the center of the canvas for testing purposes.)
I'm having some issues with one of my functions. drawSand() will not run - I believe it's because sandObj[] can't be initialized before hand, but i'm uncertain. i've tried initializing it by just limiting the array to 200 elements but that didn't seem to help any. I've added some booleans to test to see if the function is finishing and draw is the only one that isn't (besides the drawPaintTool, it's not enabled on purpose) Any help / criticism would be helpful!
"use strict";
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballX = 0;
var ballY = 0;
var ballRadius = 20;
var sandObj = [];
var sandActive = false;
var sandAmount = 10;
var sandX = 10;
var sandY = 0;
var testDrawPaintToolFunction = false;
var testPaintToolFunction = false;
var testDrawSandFunction = false;
var testMoveSandFunction = false;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
sandAmountDisplay();
paintTool();
moveSand();
drawSand();
}
function drawPaintTool() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "white";
ctx.fill();
ctx.closePath();
testDrawPaintToolFunction = true;
}
function paintTool() {
if (sandActive == true) {
sandAmount++;
}
testPaintToolFunction = true;
}
function drawSand() {
for (var i = 0; i < sandAmount; i++) {
sandObj = {
x: canvas.width / 2,
y: canvas.height / 2
};
ctx.beginPath();
ctx.rect(sandObj[i].x, sandObj[i].y, 5, 5);
ctx.fillStyle = "blue";
ctx.fill();
ctx.closePath();
}
testDrawSandFunction = true;
}
function moveSand() {
testMoveSandFunction = true;
}
function sandAmountDisplay() {
ctx.font = "16px Arial";
ctx.fillStyle = "black";
ctx.fillText("Sand Amount: " + sandAmount, 8, 20);
ctx.fillText("Sand Active: " + sandActive, 8, 40);
ctx.fillText("drawPaintTool: " + testDrawPaintToolFunction, 8, 60);
ctx.fillText("PaintTool: " + testPaintToolFunction, 8, 80);
ctx.fillText("drawSand: " + testDrawSandFunction, 8, 100);
ctx.fillText("moveSand: " + testMoveSandFunction, 8, 120);
}
document.addEventListener("mousemove", mouseMoveHandler, false);
document.addEventListener("mousedown", mouseDownHandler);
document.addEventListener("mouseup", mouseUpHandler);
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft + ballRadius / 2;
var relativeY = e.clientY - canvas.offsetTop + ballRadius / 2;
if (relativeX > 0 && relativeX < canvas.width) {
ballX = relativeX - ballRadius / 2;
}
if (relativeY > 0 && relativeY < canvas.height) {
ballY = relativeY - ballRadius / 2;
}
}
function mouseDownHandler() {
sandActive = true;
}
function mouseUpHandler() {
sandActive = false;
}
setInterval(draw, 10);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Gamedev Canvas Workshop</title>
<style>
* {
padding: 0;
margin: 15;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<script src="sand.js">
</script>
</body>
</html>
so to just help out some, because if I comment the code I would most likely have to write a larger paragraph just to get this posted, i'm going to explain the drawSand function. So the for loop used is for re-drawing all the sand everytime it's called - however, i've had to set the x and y here because I couldn't think of a way to initialize something that could continuously spawn sand. I'm lost to be honest.
EDIT: Also the sandAmount is changing constantly which is most likely the problem with something like this. when the mouse is held down the sandAmount goes up - which is what paintTool is for.
Inside of this function:
function drawSand() {
for (var i = 0; i < sandAmount; i++) {
sandObj = {
x: canvas.width / 2,
y: canvas.height / 2
};
ctx.beginPath();
ctx.rect(sandObj[i].x, sandObj[i].y, 5, 5);
ctx.fillStyle = "blue";
ctx.fill();
ctx.closePath();
}
testDrawSandFunction = true;
}
...you are assigning a new object value to sandObj, which was previously an array. You are accessing it as an array with sandObj[i]... further down, so I'm guessing that was a mistake on your part. Perhaps you meant to do:
sandObj[i] = {
x: canvas.width / 2,
y: canvas.height / 2
};
...rather than:
sandObj = {
x: canvas.width / 2,
y: canvas.height / 2
};

Canvas mouseover

I'm having a canvas on which i have created dynamically some rectangles and when you hover over them i need to show an username that's stored, i tried to do it like this but i didn't got the result that i desired. The rectangles are not html elements so i can't use classes or ids.
This is the code that i tried:
canvas.addEventListener('mouseover', (evt)=>{
mousePos = onMousePos(canvas,evt);
for(let i=0;i<rectArray.length;i++)
if(ctx.isPointInPath(mousePos.x,mousePos.y))
console.log(rectArray[i].username);
});
The onMousePos function checks the that the mouse is inside of an hexagon and i use the same function for mouseup, mousedown and mousemove and it works.
EDIT the onMousePos is this:
function onMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
if (history && timeline) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (timeline && history === false) {
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (history && timeline === false) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top)
};
}
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
};
}
<!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;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
/*
Constructor function
when called with new, everything attached to the 'this' keyword
becomes a new member of the new object
*/
function ToolTip(text) {
this.text = text;
}
/*
Constructor prototype, a collection
of values & functions that are shared across all instances,
use for constant values and member functions
*/
ToolTip.prototype = {
TEXT_SIZE: 15,
TEXT_FONT: "15px Arial",
TEXT_COLOUR: "#FFFFFFFF",
BOX_BORDER_COLOUR: "#000000FF",
BOX_BACKGROUND_COLOUR: "#990000FF",
render: function(ctx,x,y) {
ctx.fillStyle = this.BOX_BACKGROUND_COLOUR;
ctx.strokeStyle = this.BOX_BORDER_COLOUR;
ctx.font = this.TEXT_FONT;
ctx.beginPath();
ctx.rect(
x,
y - this.TEXT_SIZE,
ctx.measureText(this.text).width,
this.TEXT_SIZE
);
ctx.fill();
ctx.stroke();
ctx.fillStyle = this.TEXT_COLOUR;
ctx.fillText(this.text,x,y - 2);
}
};
function Rectangle(x,y,width,height,name) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.tooltip = new ToolTip(name);
}
Rectangle.prototype = {
BORDER_COLOUR: "#000000FF",
BACKGROUND_COLOR: "#0000AAFF",
contains: function(x,y) {
return x > this.x && x < this.x + this.width
&& y > this.y && y < this.y + this.height;
},
render: function(ctx) {
ctx.strokeStyle = this.BORDER_COLOUR;
ctx.fillStyle = this.BACKGROUND_COLOR;
ctx.beginPath();
ctx.rect(this.x,this.y,this.width,this.height);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 150;
var canvasHeight = 150;
var canvas = null;
var ctx = null;
var rectangles = null;
// Functions
function onMouseMove(e) {
var bounds = canvas.getBoundingClientRect();
var x = e.clientX - bounds.left;
var y = e.clientY - bounds.top;
draw();
for (var i = 0; i < rectangles.length; ++i) {
var rectangle = rectangles[i];
if (rectangle.contains(x,y)) {
rectangle.tooltip.render(ctx,x,y);
return;
}
}
}
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
for (var i = 0; i < rectangles.length; ++i) {
rectangles[i].render(ctx);
}
}
// Entry Point
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.onmousemove = onMouseMove;
ctx = canvas.getContext("2d");
rectangles = [
new Rectangle(10,10,25,25,"User 1"),
new Rectangle(45,10,25,25,"User 2"),
new Rectangle(80,10,25,25,"User 3"),
new Rectangle(115,10,25,25,"User 4"),
new Rectangle(10,45,25,25,"User 5"),
new Rectangle(45,45,25,25,"User 6"),
new Rectangle(80,45,25,25,"User 7"),
new Rectangle(115,45,25,25,"User 8"),
new Rectangle(10,80,25,25,"User 9"),
new Rectangle(45,80,25,25,"User 10"),
new Rectangle(80,80,25,25,"User 11"),
new Rectangle(115,80,25,25,"User 12"),
new Rectangle(10,115,25,25,"User 13"),
new Rectangle(45,115,25,25,"User 14"),
new Rectangle(80,115,25,25,"User 15"),
new Rectangle(115,115,25,25,"User 16")
];
draw();
}
}();
</script>
</body>
</html>

How to update text written on canvas

When I try to change the scoreboard using the computerCount variable (as you can see in my if statement in the update function for the ball variable) the other numbers aren't shown properly. Keep in mind that at first 0 works properly.
JSFiddle format - You can change code by going at top right corner that says "Edit" in JSFiddle.
Code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pong</title>
<!-- Basic styling, centering the canvas -->
<style>
canvas{
position: absolute;
margin: auto;
top:60px;
bottom:0;
right:0;
left:0;
}
#scoreBoard{
position: absolute;
margin: auto;
top:0;
bottom:640px;
right:720px;
left:20px;
}
</style>
</head>
<body>
<canvas id = "scoreBoard" width="500" height = "100"></canvas>
<script>
var WIDTH = 700
var HEIGHT = 600
var pi = Math.PI
var canvas
var ctx
var keystate
var upArrow = 38;
var downArrow = 40;
var computerCount = 0;
var playerCount = 0;
var player = {
x: null,
y: null,
width: 20,
height: 100,
/**
* Update the position depending on pressed keys
*/
update: function() {
if(keystate[upArrow]){
this.y-=7;
}
if(keystate[downArrow]){
this.y+=7;
}},
/**
* Draw the player paddle to the canvas
*/
draw: function() {
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
/**
* The ai paddle
*
* #type {Object}
*/
var ai = {
x: null,
y: null,
width: 20,
height: 100,
/**
* Update the position depending on the ball position
*/
update: function() {
var desty = ball.y-(this.height - ball.side)*0.5
this.y += (desty-this.y)*0.2;
},
draw: function() {
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
/**
* The ball object
*
* #type {Object}
*/
var ball = {
x: null,
y: null,
vel:null,
side: 20,
speed:5,
update: function() {
this.x += this.vel.x;
this.y += this.vel.y;
if(0>this.y || this.y+this.side>HEIGHT){
var offset = this.vel.y<0 ? 0-this.y : HEIGHT-(this.y+this.side);
this.y+=2*offset
this.vel.y*=-1;
}
var AABBIntersect = function(ax, ay, aw, ah, bx, by, bw, bh) {
return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
};
var pdle = this.vel.x<0 ? player : ai;
if(AABBIntersect(pdle.x,pdle.y,pdle.width,pdle.height, this.x, this.y, this.side, this.side)){
this.x = pdle===player ? player.x + player.width : ai.x - this.side;
var n = (this.y+this.side-pdle.y)/(pdle.height+this.side)
var phi = 0.25*pi*(2*n - 1) // pi/4 = 45
this.x = pdle===player ? player.x+player.width : ai.x - this.side;
var n = (this.y+this.side - pdle.y)/(pdle.height+this.side);
var phi = 0.25*pi*(2*n - 1); // pi/4 = 45
this.vel.x = (pdle===player ? 1 : -1)*this.speed*Math.cos(phi);
this.vel.y = this.speed*Math.sin(phi);
}
if(ball.x<0){
computerCount =+1;
ball.x = (WIDTH - ball.side) / 2;
ball.y = (HEIGHT - ball.side) / 2;
}
},
// reset the ball when ball outside of the canvas in the
draw: function() {
ctx.fillRect(this.x, this.y, this.side, this.side);
}
}
function score(){
}
/**
* Starts the game
*/
function main() {
// create, initiate and append game canvas
canvas = document.createElement("canvas");
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas2 = document.createElement("canvas");
canvas2.setAttribute("id", "scoreBoard");
canvas2.width = 200;
canvas2.height = 100;
ctx2 = canvas2.getContext("2d");
document.body.appendChild(canvas2);
keystate = {};
document.addEventListener("keydown" , function(event){
keystate[event.keyCode] = true;
})
document.addEventListener("keyup" , function(event){
delete keystate[event.keyCode];
})
init();
var loop = function() {
update();
draw();
window.requestAnimationFrame(loop, canvas);
};
window.requestAnimationFrame(loop, canvas);
}
/**
* Initatite game objects and set start positions
*/
function init() {
player.x = player.width;
player.y = (HEIGHT - player.height) / 2;
ai.x = WIDTH - (player.width + ai.width);
ai.y = (HEIGHT - ai.height) / 2;
ball.x = (WIDTH - ball.side) / 2;
ball.y = (HEIGHT - ball.side) / 2;
ball.vel = {
x:ball.speed,
y: 0
}
}
/**
* Update all game objects
*/
function update() {
ball.update();
player.update();
ai.update();
}
function draw(){
ctx.fillStyle = "black"
ctx.fillRect(0,0,WIDTH,HEIGHT)
ctx.save();
ctx2.fillStyle = "red"
ctx2.fillText(String(computerCount),100,100)
ctx2.fillText("VS",120,100)
ctx2.fillText(String(playerCount),175,100)
ctx2.font = "bold 40px monaco"
ctx.fillStyle = "white"
ball.draw();
player.draw();
ai.draw();
var w=4;
var x= (WIDTH-w)*0.5;
var y=2;
var step = HEIGHT/20;
while(y<HEIGHT){
ctx.fillRect(x,y+step*0.25,w,step*0.5)
y+=step;
}
ctx.restore();
}
// start and run the game
main();
</script>
</body>
</html>
You have two problems:
When you draw a number, you do not erase the previous number that is already printed. That is, when the score becomes 1, you render 1 on top of already rendered 0. The easiest way to address it is to do fillRect and draw a black rectangle on top of the previously written score before you draw a new score.
When you fix that, you will notice that your score never goes above 1. The reason is a typo in the code that increments it, replace
computerCount =+1;
with
computerCount += 1;
Mentioned by #Ishamael, line 139's computer count needs to be changed to computerCount += 1; //After this if statement add if the player scores.
In line 221,
function draw(){
ctx.fillStyle = "black";
ctx.fillRect(0,0,WIDTH,HEIGHT);
ctx.save();
ctx2.fillStyle = "black";
ctx2.fillRect(0,0,WIDTH, 100);
ctx2.save();
ctx2.fillStyle = "red";
ctx2.font = "bold 40px monaco";
ctx2.fillText(String(computerCount),100,100);
ctx2.fillText("VS",120,100);
ctx2.fillText(String(playerCount),175,100);
ctx2.save();
ctx.fillStyle = "white";
. . .
}
remember your semicolons and set text style before writing. I also added the repaint to erase the previous scoreboard.

Categories

Resources