Transparent Color HTML5 Canvas - javascript

I have a simple Pong game made with some Javascript and a Canvas tag.
I set the background color of the canvas tag to be transparent so the background image of the div tag can be displayed under the canvas.
The problem is that when I have it set to transparent it doesn't draw the ball and paddles correctly as if I set the background to a normal hex color. It draws the path of the paddles and the ball and the screen eventually turns the color of the ball.
The Javascript code is:
//canvas
var Width = 988;
var Height = 310;
var canvas = document.getElementById("Pong");
canvas.width = Width;
canvas.height = Height;
canvas.setAttribute('tabindex', 1);
var ctx = canvas.getContext("2d");
var FPS = 1000 / 60;
var BG = {
Color: 'transparent',
Paint: function(){
ctx.fillStyle = this.Color;
ctx.fillRect(0, 0, Width, Height);
}
};
//var Mouse = {X: 0, Y: 0};
var Ball = {
Radius: 6,
Color: '#ffffff',
X: 0,
Y: 0,
VelX: 0,
VelY: 0,
Paint: function(){
ctx.beginPath();
ctx.fillStyle = this.Color;
ctx.arc(this.X, this.Y, this.Radius, 0, Math.PI * 2, false);
ctx.fill();
this.Update();
},
Update: function(){
this.X += this.VelX;
this.Y += this.VelY;
},
Reset: function(){
this.X = Width/2;
this.Y = Height/2;
this.VelX = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
this.VelY = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
}
};
function Paddle(position){
this.Color = '#ffffff';
this.Width = 15;
this.Height = 60;
this.X = 0;
this.Y = Height/2 - this.Height/2;
this.Score = 0;
if(position == 'left')
this.X = 50;
else this.X = 938;
this.Paint = function(){
ctx.fillStyle = this.Color;
ctx.fillRect(this.X, this.Y, this.Width, this.Height);
ctx.fillStyle = this.Color;
ctx.font = "normal 10pt Calibri";
if(position == 'left'){
ctx.textAlign = "left";
ctx.fillText("score: " + Player.Score, 10, 10);
}else{
ctx.textAlign = "right";
ctx.fillText("score: " + Computer.Score, Width - 10, 10);
}
};
this.IsCollision = function () {
if (Ball.X - Ball.Radius > this.Width + this.X || this.X > Ball.Radius * 2 + Ball.X - Ball.Radius)
return false;
if (Ball.Y - Ball.Radius > this.Height + this.Y || this.Y > Ball.Radius * 2 + Ball.Y - Ball.Radius)
return false;
return true;
};
};
window.requestAnimFrame = (function(){
return window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function( callback ){ return window.setTimeout(callback, FPS); }; }
)();
window.cancelRequestAnimFrame = (function() {
return window.cancelAnimationFrame
|| window.webkitCancelRequestAnimationFrame
|| window.mozCancelRequestAnimationFrame
|| window.oCancelRequestAnimationFrame
|| window.msCancelRequestAnimationFrame
|| clearTimeout }
)();
//game
var Computer = new Paddle();
var Player = new Paddle('left');
//event listener
function MouseMove(e){
Player.Y = e.pageY - Player.Height/2;
}
//attache event
canvas.addEventListener("mousemove", MouseMove, true);
function Paint(){
ctx.beginPath();
BG.Paint();
Computer.Paint();
Player.Paint();
Ball.Paint();
}
function Loop(){
init = requestAnimFrame(Loop);
Paint();
if(Player.IsCollision() || Computer.IsCollision()){
Ball.VelX = Ball.VelX * -1;
Ball.VelX += (Ball.VelX > 0 ? 0.5 : -0.5 );
if(Math.abs(Ball.VelX) > Ball.Radius * 1.5)
Ball.VelX = (Ball.VelX > 0 ? Ball.Radius * 1.5 : Ball.Radius * -1.5);
}
if(Ball.Y - Ball.Radius < 0 || Ball.Y + Ball.Radius > Height)
Ball.VelY = Ball.VelY * -1;
if(Ball.X - Ball.Radius <= 0){
Computer.Score++;
Ball.Reset();
}else if(Ball.X + Ball.Radius > Width){
Player.Score++;
Ball.Reset();
}
if(Computer.Score === 10)
GameOver(false);
else if(Player.Score === 10)
GameOver(true);
Computer.Y = (Computer.Y + Computer.Height/2 < Ball.Y ? Computer.Y + Computer.Vel : Computer.Y - Computer.Vel);
};
function GameOver(win){
cancelRequestAnimFrame(init);
BG.Paint();
ctx.fillStyle = "#ffffff";
ctx.font = "bold 40px Calibri";
ctx.textAlign = "center";
ctx.fillText((win ? "A WINNER IS YOU" : "GAME OVER"), Width/2, Height/2);
ctx.font = "normal 16px Calibri";
ctx.fillText("refresh to reply", Width/2, Height/2 + 20);
}
function NewGame(){
Ball.Reset();
Player.Score = 0;
Computer.Score = 0;
Computer.Vel = 1.25;
Loop();
}
NewGame();
I tried simply removing the BG var but it just did the same thing.
Update: I also tried with and without ctx.closePath with no success.

This is because you don't clear the canvas at the start of each frame. With a solid-colour background this doesn't matter, but with transparent you must do this:
ctx.clearRect(0,0,canvas.width,canvas.height);

You need to clear the canvas on every draw. Canvas keeps the content that has been drawn on it.
Having a transparent canvas isn't a good idea anyway. Transparency makes things slower as it has to be recomputed every time you draw anything to the canvas. Try drawing an image into it using the image draw functions. You might find that it can use the GPU to do the image composition.

Related

Creating a Circle upon clicking anywhere in the canvas - Javascript/Canvas

The current code I have has 3 balls that are moving within the canvas but I also would like to add code where clicking on the canvas will display another circle (stationary). I tried the below code but currently stuck with the error I'm receiving. I think it's got something to do with the draw(c1) function but unsure how to have it fixed.
<div id="butDiv">
<input type='button' id='Begin' value='Start'>
<input type='button' id='resetCanvas' value='Reset'>
</div>
<canvas id='canvas1' onclick="draw()"></canvas>
<script>
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
const width = canvas.width = 1050;
const height = canvas.height = 500;
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
let rq;
function random(min, max) {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
}
class Ball{
constructor(x, y, velX, velY, color, size){
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.color = color;
this.size = size;
}
draw(){
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
update(){
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if ((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if ((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if ((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
}
}
let balls = [];
const loop = () => {
while (balls.length < 3) {
let size = 35;
let ball = new Ball(
random(0 + size,width - size), random(0 + size,height - size),15,15,'yellow',size);
balls.push(ball);
}
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
balls.forEach((i,a)=>{
i.draw();
i.update();
})
rq = requestAnimationFrame(loop);
}
function getCursorPosition(canvas, c1) {
// Gets click position
rect = canvas.getBoundingClientRect();
console.log('getcursorpos');
return {
x: c1.clickX - rect.left,
y: c1.clickY - rect.top
};
}
function draw(c1) {
getCursorPosition(canvas,c1);
var pos = getCursorPosition(canvas, c1);
var clickX = pos.x;
var clickY = pos.y;
var size1 = Math.floor((Math.Random() * 3) + 1);
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(clickX, clickY, size1, 0, 2 * Math.PI);
ctx.fill();
}
document.getElementById('butDiv').addEventListener('click', (e)=> {
const tgt = e.target;
if (tgt.id === "Begin") {
if (tgt.value === "Start") {
loop()
tgt.value = "Pause";
}else {
cancelAnimationFrame(rq)
tgt.value = "Start";
}
}else if (tgt.id === "resetCanvas") {
cancelAnimationFrame(rq)
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
}
})
I have a solution for you, I wrote everything you'll need in /* */ comments.
However it will only work if the game is stopped or paused, because when your game is running your canvas is always refreshing and you don't save the new dots, hence they will disappear on the next frame.
<div id="butDiv">
<input type='button' id='Begin' value='Start'>
<input type='button' id='resetCanvas' value='Reset'>
</div>
<canvas id='canvas1' onclick="draw()"></canvas>
<script>
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
const width = canvas.width = 1050;
const height = canvas.height = 500;
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
let rq;
/* otherwise it wont be passed */
canvas.onclick = (event) => {draw(event)};
function random(min, max) {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
}
class Ball{
constructor(x, y, velX, velY, color, size){
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.color = color;
this.size = size;
}
draw(){
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
update(){
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if ((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if ((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if ((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
}
}
let balls = [];
const loop = () => {
while (balls.length < 3) {
let size = 35;
let ball = new Ball(
random(0 + size,width - size), random(0 + size,height - size),15,15,'yellow',size);
balls.push(ball);
}
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
balls.forEach((i,a)=>{
i.draw();
i.update();
})
rq = requestAnimationFrame(loop);
}
function getCursorPosition(canvas, c1) {
// Gets click position
rect = canvas.getBoundingClientRect();
/* clickX and Y does not exist use clientX and Y */
return {
x: c1.offsetX,
y: c1.offsetY
};
}
function draw(c1) {
/* Why would you call it twice? */
//getCursorPosition(canvas,c1);
var pos = getCursorPosition(canvas, c1);
var clickX = pos.x;
var clickY = pos.y;
/* you had a typo here Random -> random */
var size1 = Math.floor((Math.random() * 3) + 1);
ctx.fillStyle = "black";
ctx.beginPath();
console.log(clickX, clickY, size1);
ctx.arc(clickX, clickY, size1, 0, 2 * Math.PI);
ctx.fill();
}
document.getElementById('butDiv').addEventListener('click', (e)=> {
const tgt = e.target;
if (tgt.id === "Begin") {
if (tgt.value === "Start") {
loop()
tgt.value = "Pause";
}else {
cancelAnimationFrame(rq)
tgt.value = "Start";
}
}else if (tgt.id === "resetCanvas") {
cancelAnimationFrame(rq)
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
}
})
</script>
Edited version where it displays the dots even if the balls are moving:
<div id="butDiv">
<input type='button' id='Begin' value='Start'>
<input type='button' id='resetCanvas' value='Reset'>
</div>
<canvas id='canvas1' onclick="draw()"></canvas>
<script>
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
const width = canvas.width = 1050;
const height = canvas.height = 500;
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
let rq;
/* otherwise it wont be passed */
canvas.onclick = (event) => {draw(event)};
function random(min, max) {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
}
class Ball{
constructor(x, y, velX, velY, color, size){
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.color = color;
this.size = size;
}
draw(){
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
update(){
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if ((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if ((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if ((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
}
}
// dot class - sorry for thinking that the dot was a ball object, my memory is converges to 0 :(
class Dot{
constructor(x, y, color, size){
this.x = x;
this.y = y;
this.color = color;
this.size = size;
}
draw(){
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
}
let dots = [];
let balls = [];
const loop = () => {
while (balls.length < 3) {
let size = 35;
let ball = new Ball(
random(0 + size,width - size), random(0 + size,height - size),15,15,'yellow',size);
balls.push(ball);
}
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
balls.forEach((i,a)=>{
i.draw();
i.update();
})
// this is the suff that draws the dots, if you want them drawn under the balls just paste this to the behinning of the loop function
dots.forEach(dot => {
dot.draw();
});
rq = requestAnimationFrame(loop);
}
function getCursorPosition(canvas, c1) {
// Gets click position
rect = canvas.getBoundingClientRect();
/* clickX and Y does not exist use clientX and Y */
return {
x: c1.offsetX,
y: c1.offsetY
};
}
function draw(c1) {
/* Why would you call it twice? */
//getCursorPosition(canvas,c1);
var pos = getCursorPosition(canvas, c1);
/*var clickX = pos.x;
var clickY = pos.y;*/
/* you had a typo here Random -> random */
var size1 = Math.floor((Math.random() * 3) + 1);
dots.push(new Dot(pos.x, pos.y, "black", size1));
/*ctx.fillStyle = "black";
ctx.beginPath();
console.log(clickX, clickY, size1);
ctx.arc(clickX, clickY, size1, 0, 2 * Math.PI);
ctx.fill();*/
}
document.getElementById('butDiv').addEventListener('click', (e)=> {
const tgt = e.target;
if (tgt.id === "Begin") {
if (tgt.value === "Start") {
loop()
tgt.value = "Pause";
}else {
cancelAnimationFrame(rq)
tgt.value = "Start";
}
}else if (tgt.id === "resetCanvas") {
cancelAnimationFrame(rq)
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
}
})
</script>

How do I place an image over top of canvas ball in javascript/html

I am trying to put an image inplace of where my current canvas ball is. I have a bouncing ball that uses real physics when bouncing. I want to put an image of a ball instead of using the 2d canvas ball. I've tried placing an image in but it just bricks my program, would I be ableto add the image overtop of the canvas ball and be able to keep all the same physics I have applied to the canvas ballHow could I achieve this?
<script src="script.js"></script>
<canvas id="canvas" height="1080" width="1920">3D Ball</canvas>
<script>
var width = 1410;
var height = 800;
var canvas = ctx = false;
var frameRate = 1/40;
var frameDelay = frameRate * 1000;
var loopTimer = false;
var ball = {
position: {x: width/2, y: 0},
velocity: {x: 10, y: 0},
mass: 0.1,
radius: 15,
restitution: -0.7
};
var Cd = 0.47;
var snd = new Audio("bounce.mp3");
var rho = 1.22;
var A = Math.PI * ball.radius * ball.radius / (10000);
var ag = 9.81;
var mouse = {x: 0, y: 0, isDown: false};
var msg = "physics ball";
function getMousePosition(e) {
mouse.x = e.pageX - canvas.offsetLeft;
mouse.y = e.pageY - canvas.offsetTop;
}
var mouseDown = function(e) {
if (e.which == 1) {
getMousePosition(e);
mouse.isDown = true;
ball.position.x = mouse.x;
ball.position.y = mouse.y;
}
}
var mouseUp = function(e) {
if (e.which == 1) {
mouse.isDown = false;
ball.velocity.y = (ball.position.y - mouse.y) /10;
ball.velocity.x = (ball.position.x - mouse.x) / 10;
}
}
var setup = function() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
canvas.onmousemove = getMousePosition;
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
ctx.fillStyle = 'red';
ctx.strokeStyle = '#000000';
loopTimer = setInterval(loop, frameDelay);
}
var loop = function() {
if ( ! mouse.isDown) {
var Fx = -0.5 * Cd * A * rho * ball.velocity.x * ball.velocity.x * ball.velocity.x / Math.abs(ball.velocity.x);
var Fy = -0.5 * Cd * A * rho * ball.velocity.y * ball.velocity.y * ball.velocity.y / Math.abs(ball.velocity.y);
Fx = (isNaN(Fx) ? 0 : Fx);
Fy = (isNaN(Fy) ? 0 : Fy);
var ax = Fx / ball.mass;
var ay = ag + (Fy / ball.mass);
ball.velocity.x += ax*frameRate;
ball.velocity.y += ay*frameRate;
ball.position.x += ball.velocity.x*frameRate*100;
ball.position.y += ball.velocity.y*frameRate*100;
}
if (ball.position.y > height - ball.radius){
snd.play();
}
if (ball.velocity.x == 0 && ball.velocity.y == 0) {
snd.pause();
}
if (ball.position.y > height - ball.radius) {
ball.velocity.y *= ball.restitution;
ball.position.y = height - ball.radius;
}
if (ball.position.x > width - ball.radius) {
ball.velocity.x *= ball.restitution;
ball.position.x = width - ball.radius;
}
if (ball.position.x < ball.radius) {
ball.velocity.x *= ball.restitution;
ball.position.x = ball.radius;
}
ctx.clearRect(0,0,width,height);
ctx.save();
ctx.translate(ball.position.x, ball.position.y);
ctx.beginPath();
ctx.arc(0, 0, ball.radius, 0, Math.PI*2, true);
ctx.fill();
ctx.closePath();
ctx.restore();
ctx.fillStyle = "blue";
ctx.font = "20px Arial";
ctx.fillText(msg, 1300,20);
if (mouse.isDown) {
ctx.beginPath();
ctx.moveTo(ball.position.x, ball.position.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
ctx.closePath();
}
}
setup();
</script>
instead of:
ctx.translate(ball.position.x, ball.position.y);
ctx.beginPath();
ctx.arc(0, 0, ball.radius, 0, Math.PI*2, true);
ctx.fill();
ctx.closePath();
try something like:
ctx.drawImage(document.getElementById("ball_img", ball.position.x, ball.position.y)
And in your html you should have, something like:
<img id="ball_img" src="your_ball_img.png">
You could presumably scale this img using css to fit the radius.
Haven't tested it though.

Speed of object does not change (javascript, html canvas)

I have created an enemy object so I can make multiple ones at once. I have the parameters for the object to take an x, y, speed of x, and speed of y. No matter what I put in the speed the red square (enemy) never moves.
var c,
ctx,
cWidth,
cHeight,
xCenter,
yCenter,
iBack,
Player,
enemy1,
scale = 40,
speed = scale / 3;
// Controll initialization
var keyState = {};
window.addEventListener('keydown',function(e){
keyState[e.keyCode || e.which] = true;
},true);
window.addEventListener('keyup',function(e){
keyState[e.keyCode || e.which] = false;
},true);
// Initial function to set canvas variables and start loop
function init() {
c = document.getElementById('canvas');
ctx = c.getContext('2d');
cWidth = c.width;
cHeight = c.height;
xCenter = cWidth / 2;
yCenter = cHeight / 2;
iBack = new Image(50, 50);
iBack.src = 'pics/background1.jpg';
Player =
{
playerX: xCenter - (scale / 2),
playerY: yCenter - (scale / 2),
speed: speed,
draw: function() {
ctx.beginPath();
ctx.rect(Player.playerX, Player.playerY, scale, scale);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
},
checkInput: function() {
if (keyState[65]) {
// A key
Player.playerX = Player.playerX - Player.speed;
} else if (keyState[68]) {
// D key
Player.playerX = Player.playerX + Player.speed;
} else if(keyState[87]) {
// W key
Player.playerY = Player.playerY - Player.speed;
} else if(keyState[83]) {
// S key
Player.playerY = Player.playerY + Player.speed;
}
}
};
// Enemy object
function Enemy(x, y, speedX, speedY)
{
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.draw = function () {
ctx.beginPath();
ctx.rect(this.x + this.speedX, this.y + this.speedY, scale, scale);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
};
}
enemy1 = new Enemy(0, (cHeight / 2) - (scale / 2), 10, 10);
setInterval(draw, 60);
}
function draw() {
// Input
Player.checkInput();
// Draw Background
//ctx.drawImage(iBack, 0, 0, cWidth, cHeight);
ctx.beginPath();
ctx.rect(0, 0, cWidth, cHeight);
ctx.fillStyle = 'white';
ctx.fill();
ctx.stroke();
ctx.closePath();
// Draw Player
Player.draw();
// Draw Enemy
enemy1.draw();
// Collision
playerCollision();
}
function playerCollision() {
// Collision with walls
if (Player.playerX <= 0) {
Player.playerX = 0;
} else if (Player.playerX + scale >= cWidth) {
Player.playerX = cWidth - scale;
} else if (Player.playerY <= 0) {
Player.playerY = 0;
} else if (Player.playerY + scale >= cHeight) {
Player.playerY = cHeight - scale;
}
// Collsion with enemys
}
You don't have anything that causes the enemies x value to change. You're just drawing it with x + speed, but that won't make it move. That'll always just draw it one out.
Normally in your setInterval(), instead of calling draw() directly, make a function named something like run() which should do some work before calling draw() to show the changes from that work.
In run(), you should do something for each enemy like enemy.x += enemy.speed. Then, when you draw, each frame they'll move by speed.

Unable to draw to canvas

I have a project where I have to create a block breaking game in canvas, but for some reason the code has stopped drawing in the canvas and I haven't been able to find a solution to the problem.
//global variable
//setting the canvas state
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//Boolean variables for each stage of the game
var startscreen = true;
var gameplaying = false;
var Game_over = false;
//Setting the ball position and size
var ball_x = canvas.width / 2;
var ball_y = canvas.height - 30;
var ballRadius = 5;
//Setting the ball movement
var dx = 2;
var dy = -2;
//PLayer paddle size
var p_height = 10;
var p_width = 100;
//Player paddle start position
var Paddlex = (canvas.width - p_width) / 2;
var Paddley = canvas.height - p_height;
//making sure the paddle doesnt move on its own
var paddleright = false;
var paddleleft = false;
//Set up the target blocks
var brickRowCount = 5;
var brickColumnCount = 13;
var brickWidth = 24;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var rowColours = ["#2294B2", "#FF3175", "#17CEFF", "#CCBF27", "#B2A507"];
var bricks = [];
for (c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (r = 0; r < brickRowCount; r++) {
bricks[c][r] = {
x: 0,
y: 0,
status: 1
};
}
}
//setting the event listeners to detect keypresses
document.addEventListener("Keydown", keyDownHandler, false);
document.addEventListener("Keyup", keyUpHandler, false);
//Detecting the key press
function keyDownHandler(e) {
if (e.keyCode == 39) {
paddleright = true;
}
if (e.keyCode == 37) {
paddleleft = true;
}
}
//Detecting the Key press has stopped
function keyUpHandler(e) {
if (e.keyCode == 39) {
paddleright = false;
}
if (e.keyCode == 37) {
paddleleft = false;
} else if (e.keyCode == 13) {
startscreen = false;
gameplaying = true;
Game_over = false;
}
}
//drawing the ball
function ball() {
ctx.beginPath();
ctx.arc(ball_x, ball_y, ballRadius, 0, Math.pi * 2);
ctx.fillstyle = "red";
ctx.fill();
ctx.closePath();
}
//drawing player paddle
function paddle() {
ctx.beginPath();
ctx.rect(Paddlex, Paddley, p_width, p_height);
ctx.fillstyle = "green";
ctx.fill();
ctx.closePath();
}
//Drawing the blocks
function drawBricks() {
for (c = 0; c < brickColumnCount; c++) {
for (r = 0; r < brickRowCount; r++) {
ctx.fillstyle = rowColours[r];
if (bricks[c][r].status === 1) {
var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fill();
ctx.closePath();
}
}
}
}
//drawing the above functions to the screen
function draw() {
//Startscreen and main menu
if (startscreen) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
//Set background colour
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
gradient.addcolorstop(0, 'blue');
gradient.addcolorstop(0, 'orange');
ctx.fillstyle = gradient;
ctx.fillRect(0, 0, 500, 500);
//Welcome title
ctx.font = '20px verdana';
ctx.fillstyle = "white";
ctx.fillText("Block Breaker", 50, 50);
//Welcome tagline
ctx.fillText("Break some blocks", 50, 100);
//Rules of play text
ctx.fillText("How to play:", 80, 200);
ctx.fillText("To play, move the paddle", 80, 280);
ctx.fillText("with the left and right arrow keys", 80, 310);
ctx.fillText("Press ENTER to begin.", 80, 250);
// Call key up function
keyUpHandler();
}
//Game play
if (gameplaying) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
//calling the ball, paddle and blocks in the draw function
ball();
paddle();
drawBricks();
//bounce off the walls
if (ball_x + dx > canvas.width - ballRadius || ball_x + dx < ballRadius) {
console.log("Ball bounced off the side");
sx = -dx;
}
//if the ball hits the top
if (ball_y + dy < ballRadius) {
console.log("Ball bounced off the top");
}
//If the ball hits the bottom
if (ball_y + dy > canvas.height - ballRadius) {
//If the ball hits the player1 paddle
if (ball_y + dy > Paddley && ball_x > Paddlex && ball_x < Paddlex + p_width) {
console.log("Ball hit the player paddle");
dy = -dy;
}
//the ball hits the base
else if (ball_y + dy > canvas.height) {
console.log("Ball hit the bottom of the screen");
gameplaying = false;
Game_over = true;
}
}
}
//Gameover screen
if (Game_over) {
var gradient = ctx.createLinearGradient(0, 0, 0, 170);
gradient.addcolorstop(0, "blue");
gradient.addcolorstop(0, "orange");
ctx.fillstyle = gradient;
ctx.fillRect(0, 0, 500, 500);
//Welcome title
ctx.font = '20px verdana';
ctx.fillstyle = "white";
ctx.fillText("Game Over", 50, 50);
//Main Text body
ctx.fillText("Press Enter to return tot the main menu", 80, 200);
//Reload the game
function keyUpHandler(e) {
if (e.keyCode == 13) {
startscreen = true;
Game_over = false;
}
}
}
//If the ball hits a block
if (ball_x)
//Movement speed of the paddle
if (paddleright && Paddlex < canvas.width - p_width) {
Paddlex += 5;
} else if (paddleleft && Paddlex > 0) {
Paddlex -= 5;
}
ball_x += dx;
ball_y += dy;
//Setting the framerate
setInterval(draw, 10);
}
<canvas id="canvas"></canvas>
move the following line down two lines (so it is not inside draw())
setInterval(draw, 10);
Also, I would strongly encourage you to change 10 to (1000 / FPS), where FPS is frames per second. You probably won't be able to finish executing draw() within 10ms thus creating a drag on the CPU

Getting mouse position within canvas

I am trying to modified this effect to work within my canvas. However, I can't seem to get the mouse position to work properly. The hover area isn't contained to my canvas.
Here's a CSSdeck of how i tried to implement it: http://cssdeck.com/labs/ukktjtis
Effect:
function hoverText(){
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
keyword = "MacroPlay Games",
imageData,
density = 3,
mouse = {},
hovered = false,
colors = ["0,120,232", "8,200,255", "30,140,255"],
minDist = 20,
bounceFactor = 0.7;
var W = window.innerWidth, H = window.innerHeight;
canvas.width = W;
canvas.height = H;
document.addEventListener("mousemove", function(e) {
mouse.x = e.pageX-50;
mouse.y = e.pageY+200;
}, false);
// Particle Object
var Particle = function() {
this.w = Math.random() * 10.5;
this.h = Math.random() * 10.5;
this.x = -W;
this.y = -H;
this.free = false;
this.vy = -5 + parseInt(Math.random() * 10) / 2;
this.vx = -4 + parseInt(Math.random() * 8);
// Color
this.a = Math.random();
this.color = colors[parseInt(Math.random()*colors.length)];
this.setPosition = function(x, y) {
this.x = x;
this.y = y;
};
this.draw = function() {
ctx.fillStyle = "rgba("+this.color+","+this.a+")";
ctx.fillRect(this.x, this.y, this.w, this.h);
}
};
var particles = [];
// Draw the text
function drawText() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "#000000";
ctx.font = "100px 'Arial', sans-serif";
ctx.textAlign = "center";
ctx.fillText(keyword, W/2, H/2);
}
// Clear the canvas
function clear() {
ctx.clearRect(0, 0, W, H);
}
// Get pixel positions
function positionParticles() {
// Get the data
imageData = ctx.getImageData(0, 0, W, W);
data = imageData.data;
// Iterate each row and column
for (var i = 0; i < imageData.height; i += density) {
for (var j = 0; j < imageData.width; j += density) {
// Get the color of the pixel
var color = data[((j * ( imageData.width * 4)) + (i * 4)) - 1];
// If the color is black, draw pixels
if (color == 255) {
particles.push(new Particle());
particles[particles.length - 1].setPosition(i, j);
}
}
}
}
drawText();
positionParticles();
// Update
function update() {
clear();
for(i = 0; i < particles.length; i++) {
var p = particles[i];
if(mouse.x > p.x && mouse.x < p.x + p.w && mouse.y > p.y && mouse.y < p.y + p.h)
hovered = true;
if(hovered == true) {
var dist = Math.sqrt((p.x - mouse.x)*(p.x - mouse.x) + (p.y - mouse.y)*(p.y - mouse.y));
if(dist <= minDist)
p.free = true;
if(p.free == true) {
p.y += p.vy;
p.vy += 0.15;
p.x += p.vx;
// Collision Detection
if(p.y + p.h > H) {
p.y = H - p.h;
p.vy *= -bounceFactor;
// Friction applied when on the floor
if(p.vx > 0)
p.vx -= 0.1;
else
p.vx += 0.1;
}
if(p.x + p.w > W) {
p.x = W - p.w;
p.vx *= -bounceFactor;
}
if(p.x < 0) {
p.x = 0;
p.vx *= -0.5;
}
}
}
ctx.globalCompositeOperation = "lighter";
p.draw();
}
}
(function animloop(){
requestAnimFrame(animloop);
update();
})();
}
It's highly advised you use jquery (or some js lib) to avoid cross-browser issues like getting the mouse position.
You can easily get the mouse position in any browser using jquery like this:
// get the position of the canvas relative to the web page
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
// then in the mouse handler, get the exact mouse position like this:
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousedown stuff here
}
// tell the browser to send mousedown events to the handleMouseDown function
$("#canvas").mousedown(function(e){handleMouseDown(e);});
I personally prefer a library like hammer.js. I've use it for all my projects - check it out, it's pretty good.

Categories

Resources