So I'm trying to make a pong game in JavaScript. I've tried lots of stuff, but whatever I do won't get the ball to move.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() { Game.update(); Game.draw(); };
Game.fps = 50;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
I can't get the ball to move. Any Ideas? Also, what the neater way of classes? Is there a different way to do it than with functions?
Maybe like
class Apple {
function draw() {
//draw here
}
}
You are always drawing the ball in the same place, dead-center:
ctx.rect(canvas.width/2 - 10, canvas.height/2 - 10, 20, 20);
You're updating this.x and this.y elsewhere, but not using them. Try:
ctx.rect(this.x, this.y, 20, 20);
Now you have the problem of knowing when to stop moving, but that's a separate question.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() { Game.update(); Game.draw(); };
Game.fps = 50;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
<canvas id="myCanvas" height="300px" width="300px" />
I got your ball moving. you had just forgot to set the position to this.x and this.y in the draw function.
you'll notice it leaves a streak. So you'll need to either (1) clear everything and redraw everything on each frame, or (2), keep an oldx and oldy and draw white over oldx oldy before drawing black at x and y. Happy coding.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var Game = {};
var Player = function(x, y) {
this.x = x;
this.y = y;
}
Player.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 80);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
}
var Ball = function(x, y, diam) {
this.x = x;
this.y = y;
this.diam = diam;
this.xvel = 5;
this.yvel = 5;
}
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 20);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
Ball.prototype.moveBall = function() {
this.x = this.x + this.xvel;
this.y = this.y + this.yvel;
};
var p1 = new Player(20, canvas.height/2 - 40);
var p2 = new Player(canvas.width-20-20, canvas.height/2 - 40);
var ball = new Ball(canvas.width/2 - 10, canvas.height/2 - 10, 20);
Game.draw = function() { p1.draw(); p2.draw(); ball.draw(); };
Game.update = function() { ball.moveBall(); };
Game.run = function() {console.log("hi"); Game.update(); Game.draw(); };
Game.fps = 5;
Game._intervalId = setInterval(Game.run, 1000 / Game.fps);
#myCanvas{width:200px;height:200px}
<canvas id="myCanvas"></canvas>
Here's a good html canvas game instructions that follows the style you're doing pretty well:
http://www.html5rocks.com/en/tutorials/canvas/notearsgame/
Related
im pretty new at canvas, but im trying to draw a falling object. First im trying to just draw an object, but its not working. How can i just draw an object (and if you could be so nice but not necessary to let me know how i can make it move)? Or what am I doing wrong here? Code:
let c, ctx;
window.onload = function(){
c = document.getElementById("boom");
ctx = c.getContext("2d");
c.width = window.innerwidth;
c.height = window.innerHeight;
setup();
draw();
};
function draw(){
//window.requestAnimationFrame(draw);
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = "red";
ctx.fillRect(100, 100, 100, 100);
regen.push(new regen(this.x, this.y, this.w, this.h, this.color));
};
function setup(){
}
function regen(x, y, w, h, color){
this.x = 100;
this.y = 100;
this.width = 20;
this.height = 40;
this.color = "blue";
//this.xSpeed = 4;
//this.ySpeed = 4;
this.draw = function(){
//this.update = function(){
//this.x += this.xSpeed;
//this.y += this.ySpeed;
//}
}
}
function getRndFloat(min, max) {
return Math.random() * (max - min + 1) + min;
}
You got typo in innerwidth: it must be innerWidth. But you got undefined and your canvas has no width
I have a html5 canvas that I'm drawing circles with. These circles need images in the center of them, but also need to update. With the help of this SO question
I have come up with this code to draw everything:
var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");
var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");
function Circle(x, y, radius, color, name) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.name = name;
this.draw = function () {
var MiddleImage = new Image();
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.drawImage(MiddleImage, this.x - MiddleImage.width / 2, this.y - MiddleImage.height / 2);
MiddleImage.src = "/Images/" + this.name + ".png";
}
this.update = function () {
this.x += 1;
this.draw();
}
this.update();
}
This isn't drawing the image like I hope it would, but if I take it out this method like below, it does work?
function drawCircle() {
var MiddleImage = new Image();
MiddleImage.onload = function () {
var X = c.width - eighthWidth;
var Y = 200;
ctx.beginPath();
ctx.arc(X, Y, eighthWidth / 2.5, 0, 2 * Math.PI);
ctx.clip;
ctx.fillStyle = Color1;
ctx.fill();
ctx.closePath();
ctx.drawImage(MiddleImage, X - MiddleImage.width / 2, Y - MiddleImage.height / 2);
};
BankImage.src = "/Images/1.png";
requestAnimationFrame(drawCircle);
}
I have also tried using the Image.onLoad method, as I have copied the working method into the new loop.
The console is showing no errors.
You can see a JSFiddle here
The problem you're having is that you're loading the image within the draw function at every frame and not waiting for it to be loaded.
I've tweaked your code slightly so it will load and attach the image to your circle as you wish.
var c = document.getElementById('canvas');
c.width = window.innerWidth;
c.height = 400;
var ctx = c.getContext("2d");
var eighthWidth = c.width / 8;
var Color1 = "#9c9c9b";
var Color2 = "#9c9c9b";
var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");
var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");
function Circle(x, y, radius, color, name) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.name = name;
this.image = new Image();
this.image.src = "https://www.gstatic.com/webp/gallery3/1.png";
var _this = this;
this.image_loaded = false;
this.image.addEventListener('load', function() {
_this.image_loaded = true;
} );
this.draw = function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.save();
ctx.clip();
ctx.drawImage(this.image, this.x - this.image.width / 2, this.y - this.image.height / 2);
ctx.restore();
}
this.update = function() {
//if(!this.image_loaded) return;
this.x += 1;
this.draw();
}
}
function animate() {
ctx.clearRect(0, 0, window.innerWidth, 400);
Circle1.update();
Circle2.update();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas" style="width:100%;"></canvas>
Is this what you want?
I am making a game. I want the player to not go outside the circular game region. the player should not cross the red circular line. It should remain inside and could move along the boundary.
I have written a simple function for collision detection between circles. I have found a bug in it too. I am getting a console.log() message of outside even if I am inside the game area.
It's happening when the player is at [x < 0]. Help me out please.
var Game = (function(window) {
var canvas = document.getElementById("game"),
ctx = canvas.getContext("2d");
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight;
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
var ROCK = "rock",
PAPER = "paper",
SCISSOR = "scissor";
var BG_IMAGE = document.getElementById("bg");
// this is the game area Radius
var GAME_R = 500;
var offsetX = 0,
offsetY = 0;
var player;
// circle collision detection
function checkCollision(x1, y1, r1, x2, y2, r2) {
var x = x1-x2;
var y = y1-y2;
var d = Math.hypot(x, y);
return d < r1 + r2;
}
function start() {
player = new Entity();
addEventListener("mousemove", function(e) {
var angle = Math.atan2(e.clientY - SCREEN_HEIGHT/2, e.clientX - SCREEN_WIDTH/2);
player.setAngle(angle);
}, true);
animLoop();
}
function update() {
offsetX = player.x - SCREEN_WIDTH/2;
offsetY = player.y - SCREEN_HEIGHT/2;
player.update();
}
function draw() {
ctx.save();
ctx.translate(-offsetX, -offsetY);
// bg
ctx.fillStyle = ctx.createPattern(BG_IMAGE, "repeat");
ctx.fillRect(offsetX, offsetY, SCREEN_WIDTH, SCREEN_HEIGHT);
// game area border
ctx.beginPath();
ctx.arc(0, 0, GAME_R, 0, Math.PI * 2);
ctx.closePath();
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.stroke();
// player
player.draw();
ctx.restore();
}
function gameLoop() {
update();
// here
if(checkCollision(player.x, player.y, player.x, 0, 0, GAME_R)) {
console.log("inside");
} else {
console.log("outside");
}
draw();
}
function animLoop() {
window.requestAnimationFrame(animLoop);
gameLoop();
}
// player
function Entity() {
var self = {
x: 0,
y: 0,
r: 50,
entityType: PAPER,
angle: 0,
speed: 5
}
self.setSpeed = function(speed) {
this.speed = speed;
}
self.setAngle = function(angle) {
this.angle = angle;
}
self.update = function() {
this.x += this.speed * Math.cos(this.angle);
this.y += this.speed * Math.sin(this.angle);
}
self.draw = function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fillStyle = "grey";
ctx.fill();
ctx.fillStyle = "#fff";
ctx.font = "30px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.entityType, this.x, this.y);
}
return self;
}
start();
})(window);
<canvas id="game"></canvas>
<div style="display: none;">
<img id="bg" src="https://i.imgur.com/9qjEwiz.png">
</div>
This will check if the inner Circle inside the outer
function checkCollision(cxInner, cyInner, rInner, cxOuter, cyOuter, rOuter) {
return Math.sqrt(Math.pow(cxInner-cxOuter, 2) + Math.pow(cyInner-cyOuter, 2)) < rOuter - rInner;
}
complete code:
var Game = (function(window) {
var canvas = document.getElementById("game"),
ctx = canvas.getContext("2d");
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight;
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
var ROCK = "rock",
PAPER = "paper",
SCISSOR = "scissor";
var BG_IMAGE = document.getElementById("bg");
// this is the game area Radius
var GAME_R = 500;
var offsetX = 0,
offsetY = 0;
var player;
// circle collision detection
function checkCollision(cxInner, cyInner, rInner, cxOuter, cyOuter, rOuter) {
return Math.sqrt(Math.pow(cxInner-cxOuter, 2) + Math.pow(cyInner-cyOuter, 2)) < rOuter - rInner;
}
function start() {
player = new Entity();
addEventListener("mousemove", function(e) {
var angle = Math.atan2(e.clientY - SCREEN_HEIGHT/2, e.clientX - SCREEN_WIDTH/2);
player.setAngle(angle);
}, true);
animLoop();
}
function update() {
offsetX = player.x - SCREEN_WIDTH/2;
offsetY = player.y - SCREEN_HEIGHT/2;
player.update();
}
function draw() {
ctx.save();
ctx.translate(-offsetX, -offsetY);
// bg
ctx.fillStyle = ctx.createPattern(BG_IMAGE, "repeat");
ctx.fillRect(offsetX, offsetY, SCREEN_WIDTH, SCREEN_HEIGHT);
// game area border
ctx.beginPath();
ctx.arc(0, 0, GAME_R, 0, Math.PI * 2);
ctx.closePath();
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.stroke();
// player
player.draw();
ctx.restore();
}
function gameLoop() {
update();
// here
if(!checkCollision(player.x, player.y, player.r, 0, 0, GAME_R)) {
player.back();
}
draw();
}
function animLoop() {
window.requestAnimationFrame(animLoop);
gameLoop();
}
// player
function Entity() {
var self = {
x: 0,
y: 0,
r: 50,
entityType: PAPER,
angle: 0,
speed: 5
};
self.setSpeed = function(speed) {
this.speed = speed;
};
self.setAngle = function(angle) {
this.angle = angle;
};
self.update = function() {
this.x += this.speed * Math.cos(this.angle);
this.y += this.speed * Math.sin(this.angle);
};
self.back = function() {
this.x -= this.speed * Math.cos(this.angle);
this.y -= this.speed * Math.sin(this.angle);
};
self.draw = function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fillStyle = "grey";
ctx.fill();
ctx.fillStyle = "#fff";
ctx.font = "30px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.entityType, this.x, this.y);
};
return self;
}
start();
})(window);
<canvas id="game"></canvas>
<div style="display: none;">
<img id="bg" src="https://i.imgur.com/9qjEwiz.png">
</div>
I am trying to detect if two balls are intersecting on a HTML5 canvas.
I need a function called intersect as a part of a constructor object called Ball.
This function will take one Ball object as an argument and return true if the two balls on the canvas are touching/ intersecting. and false otherwise.
I cant figure out how to pass in a new instance of a ball to the intersect function and then compare it to another ball on the canvas.
The function I'm working on the is the final function intersect at the end of the Ball Object.
Please see below for the code i have so far.
Any help would be greatly appreciated.
<!DOCTYPE html>
<hmtl>
<head>
<meta charset="UTF-8">
<title>Canvas</title>
<style type="text/css">
canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvasOne" ></canvas>
<script type="text/javascript">
// Gets a handle to the element with id canvasOne.
var canvas = document.getElementById("canvasOne");
// Set the canvas up for drawing in 2D.
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
function Ball(xpos,ypos,r) {
this.xpos = xpos;
this.ypos = ypos;
this.r = r;
this.move = function(addx,addy){
this.xpos = this.xpos + addx;
this.ypos = this.ypos + addy;
};
this.resize = function(setr){
this.r = setr;
};
this.draw = function(){
for (var i = 0; i < 7; i++) {
ctx.beginPath();
ctx.moveTo(ball.xpos, ball.ypos);
ctx.arc(ball.xpos, ball.ypos, ball.r, i*(2 * Math.PI / 7), (i+1)*(2 * Math.PI / 7));
ctx.lineWidth = 2;
ctx.strokeStyle = '#444';
ctx.stroke();
}
ctx.beginPath();
ctx.moveTo(ball.xpos, ball.ypos);
ctx.arc(ball.xpos,ball.ypos,ball.r-10,0,2*Math.PI);
ctx.lineWidth = 2;
ctx.strokeStyle = '#444';
ctx.stroke();
};
this.rotate = function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Move registration point to the center of the canvas
ctx.translate(ball.xpos, ball.ypos);
// Rotate 1 degree
ctx.rotate(Math.PI / 180);
// Move registration point back to the top left corner of canvas
ctx.translate(-ball.xpos, -ball.ypos);
ball.draw();
ctx.restore();
};
this.contains = function(x, y){
this.x = this.x;
this.y = this.y;
if(Math.sqrt((x-ball.xpos)*(x-ball.xpos) + (y-ball.ypos)*(y-ball.ypos)) <= ball.r)
{
return true;
}else{
return false;
}
};
this.intersect = function(){
this.ball1 = this.ball1;
var distance = (ball.xpos * ball.xpos) + (ball.ypos *ball.ypos);
if(distance <= (ball.r + ball.r)*(ball.r + ball.r)){
return true;
}else{
return false;
}
};
}
var ball = new Ball(100,100,100);
ball.draw();
</script>
</body>
</html>
First off, if you aren't going to use the this keyword in your class, then why make it a class?
You can setup your intersect to take a Ball as a parameter. From here you can calculate the collision between this and the parameter Ball.
You distance function was off, as it only looked on the this object, and i fixed the this problem in your code:
var canvas = document.body.appendChild(document.createElement("canvas"));
// Set the canvas up for drawing in 2D.
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
function Ball(xpos, ypos, r) {
this.xpos = xpos;
this.ypos = ypos;
this.r = r;
this.move = function(addx, addy) {
this.xpos = this.xpos + addx;
this.ypos = this.ypos + addy;
};
this.resize = function(setr) {
this.r = setr;
};
this.draw = function() {
for (var i = 0; i < 7; i++) {
ctx.beginPath();
ctx.moveTo(this.xpos, this.ypos);
ctx.arc(this.xpos, this.ypos, this.r, i * (2 * Math.PI / 7), (i + 1) * (2 * Math.PI / 7));
ctx.lineWidth = 2;
ctx.stroke();
}
ctx.beginPath();
ctx.moveTo(this.xpos, this.ypos);
ctx.arc(this.xpos, this.ypos, this.r - 10, 0, 2 * Math.PI);
ctx.lineWidth = 2;
ctx.stroke();
};
this.rotate = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Move registration point to the center of the canvas
ctx.translate(this.xpos, this.ypos);
// Rotate 1 degree
ctx.rotate(Math.PI / 180);
// Move registration point back to the top left corner of canvas
ctx.translate(-this.xpos, -this.ypos);
this.draw();
ctx.restore();
};
this.contains = function(x, y) {
this.x = this.x;
this.y = this.y;
if (Math.sqrt((x - this.xpos) * (x - this.xpos) + (y - this.ypos) * (y - this.ypos)) <= this.r) {
return true;
} else {
return false;
}
};
//put "ball" as a paremeter
//ball will be the foreign Ball to test intersection against
this.intersect = function(ball) {
var productX = this.xpos - ball.xpos;
var productY = this.ypos - ball.ypos;
var distance = Math.sqrt(productX * productX + productY * productY);
if (distance <= (this.r + ball.r)) {
return true;
} else {
return false;
}
};
}
var ball1 = new Ball(100, 100, 100);
var ball2 = new Ball(240, 140, 40);
function update(evt) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (evt !== void 0) {
ball2.xpos = evt.offsetX;
ball2.ypos = evt.offsetY;
}
//Pass the ball as an argument to the method
ctx.strokeStyle = ball1.intersect(ball2) ? "red" : '#444';
ball1.draw();
ball2.draw();
}
update();
canvas.onmousemove = update;
I cant figure out how to pass in a new instance of a ball to the
intersect function
Well to pass anything really it should have an argument.
this.intersect = function(otherball){
// then compare the two ball objects
Then...
var ball1 = new Ball(100,100,100);
var ball2 = new Ball(100,100,100);
ball1.draw();
ball2.draw();
console.log(ball1.intersect(ball2));
I am trying to move the arcs along the x-axis, but it's giving an error that x is not defined in the update function. Are the variables not properly placed or some reference is missing??
Code
<canvas id="myCanvas"></canvas>
<script>
var myCanvas = document.getElementById("myCanvas");
var c = myCanvas.getContext("2d");
var redArc = new Circle(50, 60, 10, "red");
var greenArc = new Circle(80, 60, 15, "green");
var blueArc = new Circle(120, 60, 20, "blue");
function Circle(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function() {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
c.fillStyle = this.color;
c.fill();
}
this.update = function() {
redArc.x += 1;
greenArc.x += 1;
blueArc.x += 1;
this.draw();
}
this.update();
}
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, myCanvas.clientWidth, myCanvas.clientHeight);
redArc.update();
greenArc.update();
blueArc.update();
}
animate();
How do I go about fixing it? Any suggestions
Thanks!!
Replace your update method with the following :
this.update = function() {
this.x += 1;
this.draw();
}
you should be using this.x , not the variable names.
var myCanvas = document.getElementById("myCanvas");
var c = myCanvas.getContext("2d");
var redArc = new Circle(50, 60, 10, "red");
var greenArc = new Circle(80, 60, 15, "green");
var blueArc = new Circle(120, 60, 20, "blue");
function Circle(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function() {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
c.fillStyle = this.color;
c.fill();
}
this.update = function() {
this.x += 1;
this.draw();
}
this.update();
}
function animate() {
c.clearRect(0, 0, myCanvas.clientWidth, myCanvas.clientHeight);
redArc.update();
greenArc.update();
blueArc.update();
requestAnimationFrame(animate);
}
animate();
<canvas id="myCanvas"></canvas>