How do I make the green triangle face towards/look at the tip of the red triangle?
Fiddle
rotation: function() {
enemy.angle = Math.atan2(player.y - enemy.y, player.x - enemy.x) * (180 / Math.PI);
},
green triangle is under enemy.
I use this function but I can tell I am doing it all wrong.
If you can help explain what you did and how you did it, I would be greatful thanks!
You need to add this line to enemy.tick function
enemy.angle = Math.atan2(player.y - this.y, player.x - this.x);
<html>
<head>
<title>Black Friday</title>
</head>
<body>
<style>
</style>
<canvas id="canvas" style="border:2px solid darkred" width="700" height="500"></canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var bounds = canvas.getBoundingClientRect();
var mouseX = 0.0;
var mouseY = 0.0;
var pressingDown = false;
var pressingUp = false;
var pressingLeft = false;
var pressingRight = false;
var player = {
x: 210,
y: 250,
radius: 17.5,
angle: 0.0,
tick: function() {
this.angle = Math.atan2(mouseY - this.y, mouseX - this.x);
},
draw: function() {
context.fillStyle = "darkred";
context.strokeStyle = "black";
context.translate(this.x, this.y);
context.rotate(this.angle);
context.beginPath();
context.moveTo(this.radius, 0.0);
context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
context.lineTo(this.radius, 0.0);
context.fill();
context.stroke();
context.rotate(-this.angle);
context.translate(-this.x, -this.y);
},
updatePlayerPosition: function() {
if (pressingRight)
player.x += 1;
if (pressingLeft)
player.x -= 1;
if (pressingDown)
player.y += 1;
if (pressingUp)
player.y -= 1;
}
}
var bullet = {
x: player.x,
y: player.y,
dx: 0.0,
dy: 0.0,
radius: 5.0,
tick: function() {
this.x += this.dx;
this.y += this.dy;
if (this.x + this.radius < 0.0 || this.x - this.radius > canvas.width || this.y + this.radius < 0.0 || this.y - this.radius > canvas.height) {
this.dx = 0.0;
this.dy = 0.0;
}
},
render: function() {
context.fillStyle = "darkcyan";
context.strokeStyle = "white";
context.beginPath();
context.arc(this.x, this.y, this.radius, 0.0, 2.0 * Math.PI, false);
context.fill();
context.stroke();
}
};
var enemy = {
x: 200,
y: 300,
radius: 17.5,
angle: 0.0,
tick: function() {
enemy.angle = Math.atan2(player.y - this.y, player.x - this.x);
},
draw: function() {
context.fillStyle = "Green";
context.strokeStyle = "darkgreen";
context.translate(this.x, this.y);
context.rotate(this.angle);
context.beginPath();
context.moveTo(this.radius, 0.0);
context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
context.lineTo(this.radius, 0.0);
context.fill();
context.stroke();
context.rotate(-this.angle);
context.translate(-this.x, -this.y);
}
}
function Refresh() {
context.clearRect(0, 0, canvas.width, canvas.height);
bullet.render();
bullet.tick();
player.draw();
player.tick();
player.updatePlayerPosition();
enemy.draw();
enemy.tick();
}
setInterval(Refresh, 0)
window.onmousemove = function(e) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
}
document.onkeydown = function(event) {
if (event.keyCode === 83) //s
pressingDown = true;
else if (event.keyCode === 87) //w
pressingUp = true;
else if (event.keyCode === 65) //a
pressingLeft = true;
else if (event.keyCode === 68) //d
pressingRight = true;
}
document.onkeyup = function(event) {
if (event.keyCode === 83) //s
pressingDown = false;
else if (event.keyCode === 87) //w
pressingUp = false;
else if (event.keyCode === 65) //a
pressingLeft = false;
else if (event.keyCode === 68) //d
pressingRight = false;
}
window.onmousedown = function(e) {
// The mouse pos - the player pos gives a vector
// that points from the player toward the mouse
var x = mouseX - player.x;
var y = mouseY - player.y;
// Using pythagoras' theorm to find the distance (the length of the vector)
var l = Math.sqrt(x * x + y * y);
// Dividing by the distance gives a normalized vector whose length is 1
x = x / l;
y = y / l;
// Reset bullet position
bullet.x = player.x;
bullet.y = player.y;
// Get the bullet to travel towards the mouse pos with a new speed of 10.0 (you can change this)
bullet.dx = x * 10.0;
bullet.dy = y * 10.0;
}
</script>
</body>
</html>
Hope it helps.
Related
I am trying to create a button object which can run a class function (show() in this case) that will change the button's color. The problem is I can only do this by calling show() repeatedly each time the color changes. The result is a ton of buttons being drawn on the screen, but I would like to only draw the button once. Is there a way around this? (Note: I have the button x position increasing to show the buttons being created)
let canvas = document.getElementById("JScanvas"),
c = canvas.getContext("2d");
let mousePosition = {
x: 0,
y: 0
};
// ignore, a few functions I might need for this to run
function buildRect(fillColor, outlineColor, outlineSize, x, y, w, h) {
if (fillColor && outlineColor) {
c.beginPath();
c.rect(x, y, w, h);
c.fillStyle = fillColor;
c.fill();
c.lineWidth = outlineSize;
c.strokeStyle = outlineColor;
c.stroke();
} else if (fillColor && !outlineColor) {
c.beginPath();
c.rect(x, y, w, h);
c.fillStyle = fillColor;
c.fill();
} else if (!fillColor && outlineColor) {
c.beginPath();
c.rect(x, y, w, h);
c.lineWidth = outlineSize;
c.strokeStyle = outlineColor;
c.stroke();
}
}
function write(str, x, y, color, txtSize, font) {
let size = txtSize.toString();
c.font = size + "px" + " " + font;
c.fillStyle = color;
c.fillText(str, x, y);
}
// end of useless functions
class button {
// mouse is {canvs: canvas, mClicked: t/f, mPosition: mousePosition{x, y}}
constructor(name, order, btnColor, x, y, w, h, txtColor, txtSize, m, f) {
this.name = name;
this.order = order;
this.btnColor = btnColor;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.txtColor = txtColor;
this.txtSize = txtSize;
this.m = m;
this.f = f;
//change color when mouse over button
this.m.canvs.addEventListener("mousemove", (event) => {
console.log("hello there");
if (this.x < this.m.mPosition.x && this.m.mPosition.x < this.x + this.w && this.y < this.m.mPosition.y && this.m.mPosition.y < this.y + this.h) {
if (this.btnColor[0] != "grey") {
this.btnColor[0] = "grey";
this.x += 50;
this.show();
} else {
this.btnColor[0] = "red";
this.x += 50;
this.show();
}
}
});
}
show() {
if (!this.btnColor[0] && !this.btnColor[0]) {
buildRect("transparent", false, 1, this.x, this.y, this.w, this.h);
} else if (!this.btnColor[0]) {
buildRect(false, this.btnColor[1], 1, this.x, this.y, this.w, this.h);
} else if (!this.btnColor[1]) {
buildRect(this.btnColor[0], false, 1, this.x, this.y, this.w, this.h);
} else {
buildRect(this.btnColor[0], this.btnColor[1], 1, this.x, this.y, this.w, this.h);
}
c.fillStyle = this.txtColor;
let theString = String(this.txtSize) + "px Arial";
c.font = theString;
let width = Math.round(c.measureText(c.fillText(this.name, -1000, 0)).width);
if (width > this.w) {
let center = this.x + (this.w / 2);
let newSize = this.w / width;
c.font = String(this.txtSize * newSize);
let newWidth = Math.round(newSize * width);
c.textAlign = "center";
c.textBaseline = "middle";
c.fillText(this.name, this.x + (this.w / 2), this.y + (this.h / 2));
} else {
c.textAlign = "center";
c.textBaseline = "middle";
c.fillText(this.name, this.x + (this.w / 2), this.y + (this.h / 2));
}
}
clickButton(mouseX, mouseY) {
if (mouseX >= this.x && mouseX <= this.x + this.w && mouseY >= this.y && mouseY <= this.y + this.h) {
return true;
} else {
return false;
}
}
runf() {
this.f();
}
}
//getting mouse position
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener("mousemove", (evt) => {
let r = getMousePos(canvas, event);
mousePosition.x = r.x, mousePosition.y = r.y;
});
let mouse = {
canvs: canvas,
mClicked: false,
mPosition: mousePosition
};
//button object to call: ("red" is the color of the button I am trying to change to grey)
let cookie = new button("cookie", 1, ["red", false], 50, 100, 150, 50, "black", 30, mouse, 2);
cookie.show();
<!DOCTYPE html>
<html>
<head>
<title>Playground</title>
</head>
<body>
<canvas width="1500" height="1500" id="JScanvas"></canvas>
</body>
</html>
I think you have over complicated your code...
Here is a simple example where we change the color when the mouse is over the rectangle
let canvas = document.getElementById("canvas")
let c = canvas.getContext("2d");
class button {
constructor(color, x, y, w, h) {
this.color = color;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
draw(mouse) {
c.beginPath();
c.rect(this.x, this.y, this.w, this.h);
if (mouse.x >= this.x && mouse.x <= this.x + this.w &&
mouse.y >= this.y && mouse.y <= this.y + this.h) {
c.fillStyle = "gray";
} else {
c.fillStyle = this.color;
}
c.fill();
}
}
function getMousePos(evt) {
if (!evt) return { x: 0, y: 0 }
const rect = canvas.getBoundingClientRect();
return { x: evt.clientX - rect.left, y: evt.clientY - rect.top };
}
let buttons = []
buttons.push(new button("red", 50, 100, 40, 20))
buttons.push(new button("blue", 100, 50, 40, 20))
canvas.addEventListener("mousemove", mainDraw);
function mainDraw(evt) {
let mouse = getMousePos(evt)
c.clearRect(0, 0, canvas.width, canvas.height);
buttons.forEach((btn) => {
btn.draw(mouse)
})
}
mainDraw()
<canvas id="canvas" width="150" height="150"></canvas>
As you can see there is only one addEventListener and it is outside the class button, the logic is simple, we clean the entire canvas and draw everything on every event... that is how games do it, I'm sure that will work for what you are doing too.
I made a little game where there are 3 objects
Player: Can move using WASD
Bullet: Moved by an event listener of click
Enemy: Follows the player like a zombie.
How do I make it so the angle of the zombie is the direction he is moving, Rather than always facing the player object?
Fiddle
tick: function() {
enemy.angle = Math.atan2(player.y - enemy.y, player.x - enemy.x);// * (180 / Math.PI);
},
above is the code I use to make the enemy face the player
I understand what you're trying to ask, but really, right now the zombie is always going directly to player, so it would actually be weird if it looked some other way. What you need to do is to actually make zombie slowly turn and walk on it's own, rather than just reducing euclidean distance between it and the player.
First stem, one that I'll do for you is calculating the rotation. Instead of just getting to the correct angle instantly, we have to slowly turn every tick:
tick: function() {
// 1 degree per tick
const rotationSpeed = (1/180)*Math.PI;
// the angle we want - facing the player
const desiredAngle = Math.atan2(player.y - enemy.y, player.x - enemy.x)
// transition angle will be explained below
enemy.angle = transitionAngle(enemy.angle, desiredAngle,rotationSpeed );
},
This is not as easy as it sounds, because you need to calculate whether it's faster to turn left or right to face the player again. Fortunately this is easy to google once you know what you need. I based my function on this answer:
function transitionAngle(fromAngle, toAngle, speed) {
// normalize the angles to 0-360 range
const rad360 = 2*Math.PI;
fromAngle = fromAngle % rad360;
toAngle = toAngle % rad360;
if (fromAngle < toAngle) {
if (Math.abs(fromAngle - toAngle) < Math.PI)
fromAngle += speed;
else fromAngle -= speed;
}
else {
if (Math.abs(fromAngle - toAngle) < Math.PI)
fromAngle -= speed;
else fromAngle += speed;
}
return fromAngle;
}
With that, the zombie slows slowly, and it already looks a little better.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var bounds = canvas.getBoundingClientRect();
var mouseX = 0.0;
var mouseY = 0.0;
var pressingDown = false;
var pressingUp = false;
var pressingLeft = false;
var pressingRight = false;
var player = {
x: 210,
y: 250,
radius: 17.5,
angle: 0.0,
tick: function() {
this.angle = Math.atan2(mouseY - this.y, mouseX - this.x);
},
draw: function() {
context.fillStyle = "darkred";
context.strokeStyle = "black";
context.translate(this.x, this.y);
context.rotate(this.angle);
context.beginPath();
context.moveTo(this.radius, 0.0);
context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
context.lineTo(this.radius, 0.0);
context.fill();
context.stroke();
context.rotate(-this.angle);
context.translate(-this.x, -this.y);
},
updatePlayerPosition: function() {
if (pressingRight)
player.x += 1;
if (pressingLeft)
player.x -= 1;
if (pressingDown)
player.y += 1;
if (pressingUp)
player.y -= 1;
}
}
var bullet = {
x: player.x,
y: player.y,
dx: 0.0,
dy: 0.0,
radius: 5.0,
tick: function() {
this.x += this.dx;
this.y += this.dy;
if (this.x + this.radius < 0.0 || this.x - this.radius > canvas.width || this.y + this.radius < 0.0 || this.y - this.radius > canvas.height) {
this.dx = 0.0;
this.dy = 0.0;
}
},
render: function() {
context.fillStyle = "darkcyan";
context.strokeStyle = "white";
context.beginPath();
context.arc(this.x, this.y, this.radius, 0.0, 2.0 * Math.PI, false);
context.fill();
context.stroke();
}
};
var enemy = {
x: 200,
y: 300,
radius: 17.5,
angle: 0.0,
tick: function() {
// 1 degree per tick
const rotationSpeed = (1/180)*Math.PI;
const desiredAngle = Math.atan2(player.y - enemy.y, player.x - enemy.x)
enemy.angle = transitionAngle(enemy.angle, desiredAngle,rotationSpeed );
},
draw: function() {
context.fillStyle = "Green";
context.strokeStyle = "darkgreen";
context.translate(this.x, this.y);
context.rotate(this.angle);
context.beginPath();
context.moveTo(this.radius, 0.0);
context.lineTo(-0.5 * this.radius, 0.5 * this.radius);
context.lineTo(-0.5 * this.radius, -0.5 * this.radius);
context.lineTo(this.radius, 0.0);
context.fill();
context.stroke();
context.rotate(-this.angle);
context.translate(-this.x, -this.y);
},
drawEnemy: function(something){
var diffX = player.x - something.x;
var diffY = player.y - something.y
if (diffX > 0)
something.x += .3
else
something.x -= .3;
if (diffY > 0)
something.y += .3
else
something.y -= .3;
}
}
function Refresh() {
context.clearRect(0, 0, canvas.width, canvas.height);
bullet.render();
bullet.tick();
player.draw();
player.tick();
player.updatePlayerPosition();
enemy.draw();
enemy.tick();
enemy.drawEnemy(enemy);
}
setInterval(Refresh, 0)
window.onmousemove = function(e) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
}
document.onkeydown = function(event) {
if (event.keyCode === 83) //s
pressingDown = true;
else if (event.keyCode === 87) //w
pressingUp = true;
else if (event.keyCode === 65) //a
pressingLeft = true;
else if (event.keyCode === 68) //d
pressingRight = true;
}
document.onkeyup = function(event) {
if (event.keyCode === 83) //s
pressingDown = false;
else if (event.keyCode === 87) //w
pressingUp = false;
else if (event.keyCode === 65) //a
pressingLeft = false;
else if (event.keyCode === 68) //d
pressingRight = false;
}
window.onmousedown = function(e) {
// The mouse pos - the player pos gives a vector
// that points from the player toward the mouse
var x = mouseX - player.x;
var y = mouseY - player.y;
// Using pythagoras' theorm to find the distance (the length of the vector)
var l = Math.sqrt(x * x + y * y);
// Dividing by the distance gives a normalized vector whose length is 1
x = x / l;
y = y / l;
// Reset bullet position
bullet.x = player.x;
bullet.y = player.y;
// Get the bullet to travel towards the mouse pos with a new speed of 10.0 (you can change this)
bullet.dx = x * 10.0;
bullet.dy = y * 10.0;
}
function transitionAngle(fromAngle, toAngle, speed) {
// normalize the angles to 0-360 range
const rad360 = 2*Math.PI;
fromAngle = fromAngle % rad360;
toAngle = toAngle % rad360;
if (fromAngle < toAngle) {
if (Math.abs(fromAngle - toAngle) < Math.PI)
fromAngle += speed;
else fromAngle -= speed;
}
else {
if (Math.abs(fromAngle - toAngle) < Math.PI)
fromAngle -= speed;
else fromAngle += speed;
}
return fromAngle;
}
<canvas id="canvas" style="border:2px solid darkred" width="700" height="500"></canvas>
The second part of the job - and I'm leaving that to you - is to make zombie actually walk in the direction it's facing. To do that, assign it a walking speed and then use sin and cos of the zombie's angle multiplied with the speed to get X and Y offsets. Again, google is your friend, just type "move by speed and angle javascript".
I'm making a html5 canvas game and I have a problem with the collision.
The problem is when the ball collides with any platform, the ball gravity should be -1 and go up as the same velocity as the platforms but it only works with the last platform and the left one. How can I fix it? Thanks!
HTML:
<html>
<head>
<title>Falldown</title>
</head>
<body>
<canvas id="canvas" width = "380" height= "640"></canvas>
<script src="beta.js"></script>
</body>
</html>
JS Code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var isMenu = true;
var isPlaying = false;
var testing = true;
var pressingLeft = false;
var pressingRight = false;
var Platforms = [];
var difficulty = 1;
var gravity = 1;
var Player = {
color: "red",
radius: 7.5,
stepY: 1.5,
x: 175,
y: 75
};
function RectCircleColliding(circle, rect) {
var distX = Math.abs(circle.x - rect.x - rect.width / 2);
var distY = Math.abs(circle.y - rect.y - 20 / 2);
if (distX > (rect.width / 2 + circle.radius)) return false;
if (distY > (20 / 2 + circle.radius)) return false;
if (distX <= (rect.width / 2)) return true;
if (distY <= (20 / 2)) return true;
var dx = distX - rect.width / 2;
var dy = distY - 20 / 2;
return (dx * dx + dy * dy <= (circle.radius * circle.radius));
}
function drawBackground() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (isMenu && !isPlaying) {
createText("60px monospace", "white", "FallDown", 45, 130);
createText("34px Arial", "white", "PLAY", 130, 260);
createText("34px Arial", "white", "LEADERBOARD", 50, 340);
createText("34px Arial", "white", "SETTINGS", 90, 420);
} else {
if (testing) {
Platforms = [];
for (var i = 0; i < 13; i++) {
Platforms.push({
"x": 10,
"y": 160 + (i * 70),
"width": (Math.random() * canvas.width) - 60
});
}
testing = false;
}
for (var i in Platforms) {
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);
var totalTest = Platforms[i].width + 60;
ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);
Platforms[i].y -= 1;
if (RectCircleColliding(Player, Platforms[i])) {
gravity = -1;
} else {
gravity = 1;
}
}
detectBorderCollision();
detectPlayerCollision();
drawPlayer();
drawBorder();
if (Platforms.length === 7) Platforms = [];
}
}
function detectBorderCollision() {
if (Player.x > 370 - Player.radius) {
Player.x = 370 - Player.radius;
} else if (Player.x < 3.8 + Player.radius * 2) {
Player.x = 3.8 + Player.radius * 2
}
}
function detectPlayerCollision() {
}
function drawPlayer() {
ctx.beginPath();
ctx.fillStyle = Player.color;
ctx.arc(Player.x, Player.y, Player.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath();
Player.y += gravity;
if (pressingRight) {
Player.x += 2;
} else if (pressingLeft) {
Player.x -= 2;
}
/*
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, 160, 300, 20);
*/
}
function drawBorder() {
ctx.beginPath();
ctx.strokeStyle = "#00ffff";
ctx.lineWidth = 10;
ctx.moveTo(5, 0);
ctx.lineTo(5, 640);
ctx.moveTo(375, 0);
ctx.lineTo(375, 640);
ctx.stroke();
ctx.closePath();
}
function createText(font, color, value, posX, posY) {
ctx.font = font;
ctx.fillStyle = color;
ctx.fillText(value, posX, posY)
}
function isInside(realX, realY, x1, x2, y1, y2) {
return (realX > x1 && realX < x2) && (realY > y1 && realY < y2)
}
function drawGame() {
drawBackground();
}
function startDrawing() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGame();
requestAnimationFrame(startDrawing);
}
function Init() {
requestAnimationFrame(startDrawing);
canvas.addEventListener("click", function(evt) {
var rect = canvas.getBoundingClientRect();
var mouseX = evt.clientX - rect.left;
var mouseY = evt.clientY - rect.top;
if (isMenu && !isPlaying) {
if (isInside(mouseX, mouseY, 115, 230, 220, 270)) {
isPlaying = true;
isMenu = false;
} else if (isInside(mouseX, mouseY, 35, 320, 300, 345)) {
console.log("Leaderboard");
} else if (isInside(mouseX, mouseY, 75, 270, 380, 430)) {
console.log("Settings");
}
}
});
window.addEventListener("keydown", function(evt) {
if (!isMenu && isPlaying) {
if (evt.keyCode === 39) { // right
pressingRight = true;
} else if (evt.keyCode === 37) { // left
pressingLeft = true;
}
}
});
window.addEventListener("keyup", function(evt) {
if (!isMenu && isPlaying) {
if (evt.keyCode === 39) { // right
pressingRight = false;
} else if (evt.keyCode === 37) { // left
pressingLeft = false;
}
}
});
}
Init();
There are so many magic numbers in your code that debugging it is difficult and tedious. Replace all the number literals with identifiers which describe what the values represent.
The following amendment to part of the drawBackground function causes all the collisions with left hand platforms to work, but not perfectly.
var hasCollided;
for (var i in Platforms) {
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);
var totalTest = Platforms[i].width + 60;
ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);
Platforms[i].y -= 1;
if (!hasCollided) {
if (RectCircleColliding(Player, Platforms[i])) {
gravity = -1;
hasCollided = true;
} else {
gravity = 1;
}
}
}
I was wondering how to move the red ball right and left (I already did, but its not working) and also how to move it up and down.
<canvas id="canvas" width="480" height="320"></canvas>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var ball;
var obstacle;
var x = canvas.width / 2;
var y = canvas.height / 2;
var dx = 2;
var dy = -2;
var redballRadius = 10;
var ballRadius = 20;
var rightpressed = false;
var leftpressed = false;
var ballX = (canvas.width - redballDiameter) / 2;
var redballDiameter = redballRadius * 2;
function startGame() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ball = new drawBall(30, 30, 'red', 20, 10);
obstacle = new drawObstacle(40, 30, 'blue', 15, 10);
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
dy = -dy;
}
if(rightpressed && ballX < canvas.width-redballDiameter) {
ballX += 7;
}
else if(leftpressed && ballX > 0) {
ballX -= 7;
}
}
//keyboard controls
document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 39) {
rightpressed = true;
}
else if(e.keyCode == 37) {
leftpressed = true;
}
}
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightpressed = false;
}
else if (e.keyCode == 37) {
leftpressed = false;
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(30, 30, 15, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
function drawObstacle() {
x += dx;
y += dy;
ctx.beginPath();
ctx.arc(x, y, 20, 10, 1 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
}
setInterval(startGame, 10);
I am basically wondering how to move it up down right and left with the keys. Thanks
I took a look at your code. In your life cycle, you are calling drawBall, now sure what you are trying to do with the new there. anyways, I updated the function to use the ballX your key handling logic updates.
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, 30, 15, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
here is the working code pen. http://codepen.io/poda/pen/aNPPEp
move a ball to up, down, right and left.
it would be better to use object than use global variable of x_pos and y_pos of ball
function drawBall() {
this.ball_x = 30;
this.ball_y = 30;
this.draw = function() {
ctx.beginPath();
ctx.arc(this.ball_x, this.ball_y, 15, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
},
this.move = function() {
if(rightpressed && this.ball_x < canvas.width-redballDiameter) {
this.ball_x += 5;
}
else if(leftpressed && this.ball_x > redballDiameter) {
this.ball_x -= 5;
}
else if(uppressed && this.ball_y > redballDiameter) {
this.ball_y -= 5;
}
else if(downpressed && this.ball_y < canvas.height - redballDiameter) {
this.ball_y += 5;
}
},
this.collision = function() {
//stuff
}
}
Here's a fiddle
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.