Problem: The color of block should be grey, but instead inherits the color-property of ball which is red. block2 should be blue, but inherits the color of block which is grey. How do I fix this problem? I have just started to learn how to program so i do not have much experience with things like this:/
Code:
function Player(x, y, w, h, color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dy = 3;
this.draw = function() {
c.fillRect(this.x, this.y, this.w, this.h);
c.fillStyle = this.color;
c.stroke();
c.closePath();
};
this.update = function() {
if (keyW === true) {
block.y -= block.dy;
}
if (keyS === true) {
block.y += block.dy;
}
if (arrowUp === true) {
block2.y -= block2.dy;
}
if (arrowDown === true) {
block2.y += block2.dy;
}
if (this.y + this.h > canvas.height) {
this.y = canvas.height - this.h;
}
if (this.y < 0) {
this.y = 0;
}
this.draw();
};
}
block = new Player(10, (canvas.height / 2) - 50, 250, 100, "grey");
block2 = new Player(canvas.width - 30, (canvas.height / 2) - 50, 20, 100, "blue");
function Ball(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.dx = 3;
this.dy = 0;
this.draw = function() {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
c.fillStyle = this.color;
c.fill();
c.closePath();
};
this.update = function() {
this.x -= this.dx;
if (this.y + this.radius > canvas.height) {
this.y = canvas.height - this.radius;
}
if (this.y - this.radius < 0) {
this.y = this.radius;
}
if (this.x + this.radius > canvas.width) {
this.dx = -this.dx;
}
if (this.x - this.radius < 0) {
this.dx = -this.dx;
}
this.draw();
};
}
ball = new Ball(canvas.width / 2 - 50, canvas.height / 2, 10, "red");
You are filling a rect inside Player update method before changing the color, so it uses previous fillStyle value which is red.
Instead of:
c.fillRect(x, y, w, h);
c.fillStyle = this.color;
Do:
c.fillStyle = this.color;
c.fillRect(x, y, w, h);
Related
Can you help with the code? I'm creating a parkour game and everything went well but I got stuck on it: as the cube will stand on the floor. Here is my js code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//Налаштування
var width = canvas.width;
var height = canvas.height;
var gameOver = function() {
clearInterval(intervalId);
ctx.font = "60px Caurier";
ctx.textAlign = "cener";
ctx.textBaseline = "middle";
ctxfillText("GAME OVER", width / 2, height / 2);
};
var cicle = function(x, y, radius, fillCircle) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
}; //Людина
//намалювати
function Draw() {
this.x = 10;
this.y = 10;
}
Draw.prototype.draw = function() {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + 50, this.y);
ctx.lineTo(this.x + 50, this.y + 50);
ctx.lineTo(this.x, this.y + 50);
ctx.lineTo(this.x, this.y);
ctx.fill();
}
Draw.prototype.move = function() {
if (this.x < 0) {
this.x = 0;
} else if (this.x > 1250) {
this.x = 1250;
}
if (this.y < 0) {
this.y = 0;
} else if (this.y > 450) {
this.y = 450;
}
while (this.y < 450) {
this.y++;
}
}
Draw.prototype.setDirection = function(direction) {
if (direction === "left") {
this.x = this.x - 10;
} else if (direction === "right") {
this.x = this.x + 10;
} else if (direction === "up") {
this.y = this.y - 150;
}
}
var person = new Draw;
var keyActions = {
37: "left",
38: "up",
39: "right"
};
$("body").keydown(function(event) {
var direction = keyActions[event.keyCode];
person.setDirection(direction);
});
setInterval(function() {
ctx.clearRect(0, 0, 1300, 500);
person.draw();
person.move();
//карта
var floor = ctx.strokeStyle = "LimeGreen";
ctx.lineWidth = 4;
ctx.strokeRect(0, 312, 1300, 362);
}, 30);
body {
background-color: rgb(44, 235, 225);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>parcur</title>
</head>
<body>
<canvas id="canvas" width="1300" height="500"></canvas>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
</body>
</html>
I tried a lot but it didn't work out. For example, I tried this: first the code checks whether the cube and the floor are in the same coordinates, if so it reflects, if not, then no.I want the cube to be able to walk on the floor which is painted green, and not pass through it.
This question already has answers here:
Flickering images in canvas animation
(2 answers)
Closed 1 year ago.
I try to make an animation using the following code:
var obst = new Obstacle(x, y)
obst.build()
function animate() {
ctx.clearRect(0, 0, innerWidth, innerHeight);
requestAnimationFrame(animate);
obst.update(-1, 0)
player1.build();
}
but obst var doesn't appear (but player1 appears)
class for obst:
class Obstacle {
constructor(x, y) {
this.x = x;
this.y = y;
}
build() {
var img = new Image();
img.src = 'assests/obst.png';
img.onload = () => {
ctx.drawImage(img, this.x, this.y, 60, 60);
}
}
update(x, y) {
this.x += x;
this.y += y;
this.build()
}
}
When I run the code without clearrect() syntax it shows as it should be.
Full code:
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, innerWidth, innerHeight);
obst.update(-1, 0)
player1.build();
}
class Player {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
build() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
ctx.fillStyle = this.color;
ctx.fill();
}
update(x, y) {
this.x += x
this.y += y
this.build()
}
}
class Obstacle {
constructor(x, y) {
this.x = x;
this.y = y;
}
build() {
var img = new Image();
img.src = 'assests/obst.png';
img.onload = () => {
ctx.drawImage(img, this.x, this.y, 60, 60);
}
}
update(x, y) {
this.x += x;
this.y += y;
this.build()
}
}
var obst = new Obstacle(canvas.width, canvas.height / 2 - 30)
obst.build()
var player1 = new Player(canvas.width / 2, canvas.height / 2, 30, 'blue');
player1.build();
animate();
The async task of loading the image should be removed from the update loop. Have the objects follow a pattern where building and updating / drawing are independent, and where building is async and happens once...
class Obstacle {
constructor(x, y) {
this.x = x;
this.y = y;
}
// don't use the object until this promise resolves
async build() {
var img = new Image();
img.src = 'assests/obst.png';
return new Promise(resolve => img.onload = resolve)
}
// call the method that draws current state "draw"
draw() {
ctx.drawImage(img, this.x, this.y, 60, 60);
}
// call the method that updates current state and draws "update"
update(x, y) {
this.x += x;
this.y += y;
this.draw()
}
}
class Player {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
// for symmetry, and maybe someday player will need to do async work here
async build() {
return Promise.resolve();
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
ctx.fillStyle = this.color;
ctx.fill();
}
update(x, y) {
this.x += x
this.y += y
this.draw()
}
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, innerWidth, innerHeight);
obst.update(-1, 0)
player1.update(0, 1);
}
async function play() {
const obst = new Obstacle(canvas.width, canvas.height / 2 - 30)
await obst.build();
const player1 = new Player(canvas.width / 2, canvas.height / 2, 30, 'blue');
await player1.build();
animate();
}
play()
I'm creating a javascript game where I need a collision between the ball and rectangle to trigger a reset of the game. For now I just have an alert there for testing purposes. I'm having trouble getting the collision detection working.
This is what I've got so far but it isn't working
function startGame() {
keeper = new obstacle(40, 20, "#666", 130, 180);
theBall = new component("#000", 80, 10);
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 300;
this.canvas.height = 250;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function(e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function(e) {
myGameArea.key = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(color, x, y, type) {
this.type = type;
this.speed = 1.5;
this.angle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.beginPath();
ctx.arc(this.x, this.y, 10, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.fill();
ctx.restore();
}
this.newPos = function() {
this.x -= this.speed * Math.sin(this.angle);
this.y += this.speed * Math.cos(this.angle);
}
}
function obstacle(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.collideWith = function(theBall){
var collide = true;
var myTop =this.y;
var theBallBottom = theBall.y + (theBall.radius)
if (myTop < theBallBottom)
{
collide = false;
}
return collide;
}
}
function updateGameArea() {
if (keeper.crashWith(theBall)) {
alert("Collision");
} else {
myGameArea.clear();
theBall.newPos();
theBall.update();
keeper.speedX = 0;
keeper.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {keeper.speedX = -1; }
if (myGameArea.key && myGameArea.key == 39) {keeper.speedX = 1; }
keeper.newPos();
keeper.update();
}
}
The game can be found here http://alexhollingsworth.co.uk/game.php
You named your method collideWith, but you are calling it crashWith in the update method. Plus this will only detect collision on y axis, but I assume this is intended.
I made an if statement that can detect collisions in JavaScript, here it is:
if circle x < rect x + circle width && circle x + rect width > rect x && circle y < rect y + circle height && rect height + circle y > rect y {
This works by putting the ball into an 'imaginary box', then senses if any of the edges of the 'imaginary box' come in contact with any of the edges of the rectangle. I hope this helped.
I'm trying to make particles that accelerate using JavaScript and the HTML5 Canvas, but I cannot get them to accelerate, they just move at a constant speed. Does anyone know why?
document.addEventListener("DOMContentLoaded", init);
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
angle = Math.random() * (2 * Math.PI);
pArray = [];
for (i = 0; i<25; i++) {
angle = Math.random() * (2*Math.PI);
pArray[i] = new Particle(Math.cos(angle), Math.sin(angle));
}
setInterval(loop, 50);
}
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (x = 0; x < pArray.length; x++) {
pArray[x].draw();
}
}
function Particle(xVel, yVel) {
this.xVel = xVel;
this.yVel = yVel;
this.x = canvas.width/2;
this.y = canvas.height/2;
this.draw = function() {
this.x += xVel;
this.y -= yVel;
this.yVel += 1;
ctx.beginPath();
ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);
ctx.fillStyle = "rgb(0, 255, 0)";
ctx.fill();
}
}
Your draw function is using the yVel passed to the constructor.
try with this.y += this.yVel;
It looks like your draw function is using the xVel and yVel from the constructor instead of from the particle instance. Try changing this.y += yVel to this.y += this.yVel.
You can create extra variable with name speed and then speed up the balls like this:
function Particle(xVel, yVel) {
this.xVel = xVel;
this.yVel = yVel;
this.speed = 1;
this.x = canvas.width/2;
this.y = canvas.height/2;
this.draw = function() {
this.x += this.speed * this.xVel;
this.y += this.speed * this.yVel;
this.speed++;
ctx.beginPath();
ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);
ctx.fillStyle = "rgb(0, 255, 0)";
ctx.fill();
}
}
Here is example on jsfiddle https://jsfiddle.net/3nnm2omm/
I've created a little bouncing boxes demo in javascript using the canvas. Each box (for want of a better word) class handles it's own updates and rendering. However, my problem lies in clearing the canvas before drawing the next frame. It clears fine when the boxes are moving but leaves artifacts behind after it hits a wall. Here's a fiddle - https://jsfiddle.net/dzuvL7ph/1/
Here's my code;
function init(){
window.box1 = new Box(50, 'red', 0, 0);
window.box2 = new Box(50, 'blue', 400, 20);
requestAnimationFrame(update);
}
function update() {
window.box1.update();
window.box2.update();
requestAnimationFrame(update);
requestAnimationFrame(render);
}
function render() {
window.box1.render();
window.box2.render();
}
// -------------------------------------------------------------------------------------------------------
// --
// -------------------------------------------------------------------------------------------------------
var Box = function(dimensions, color, x, y){
this.width = dimensions;
this.height = dimensions;
this.x = x;
this.y = y;
this.velocityX = 10;
this.velocityY = 10;
this.color = color;
this.context = document.getElementById('canvas').getContext('2d');
this.update = function(){
this.x += this.velocityX;
this.y += this.velocityY;
this.collisionCheck();
};
this.render = function(){
this.context.fillStyle = this.color;
this.context.clearRect(this.x - this.velocityX, this.y - this.velocityY, this.width, this.height);
this.context.fillRect(this.x, this.y, this.width, this.height);
};
this.collisionCheck = function(){
if(this.y > 600 - this.height || this.y < 0)
this.velocityY *= -1;
if(this.x > 800 - this.width || this.x < 0)
this.velocityX *= -1;
};
};
I assume it's to do with this.context.clearRect(this.x - this.velocityX, this.y - this.velocityY, this.width, this.height); but I can't figure out what I'm doing wrong.
It's a little weird you're doing a cleanup for each box. Normally, you'd wipe the whole canvas on each frame: https://jsfiddle.net/yb58fd47/
WHY it happens
Your update function checks for collisions, which can in turn reverse the speed component(s). But, your render function relies on that speed component to accurately represent the last speed. If you don't want to clear the whole canvas, you can keep track of the previous actual speed the box had (I added velocityXLast and velocityYLast):
function init(){
window.box1 = new Box(50, 'red', 0, 0);
window.box2 = new Box(50, 'blue', 120, 20);
requestAnimationFrame(update);
}
function update() {
window.box1.update();
window.box2.update();
requestAnimationFrame(update);
requestAnimationFrame(render);
}
function render() {
window.box1.render();
window.box2.render();
}
// -------------------------------------------------------------------------------------------------------
// --
// -------------------------------------------------------------------------------------------------------
var Box = function(dimensions, color, x, y){
this.width = dimensions;
this.height = dimensions;
this.x = x;
this.y = y;
this.velocityX = 10;
this.velocityY = 10;
this.color = color;
this.context = document.getElementById('canvas').getContext('2d');
this.update = function(){
this.x += this.velocityX;
this.y += this.velocityY;
this.velocityXLast = this.velocityX;
this.velocityYLast = this.velocityY;
this.collisionCheck();
};
this.render = function(){
this.context.fillStyle = this.color;
this.context.clearRect(this.x - this.velocityXLast, this.y - this.velocityYLast, this.width, this.height);
this.context.fillRect(this.x, this.y, this.width, this.height);
};
this.collisionCheck = function(){
if(this.y > 150 - this.height || this.y < 0)
this.velocityY *= -1;
if(this.x > 400 - this.width || this.x < 0)
this.velocityX *= -1;
};
};
init();
canvas {border: 1px solid black}
<canvas id="canvas" width="400" height="150"></canvas>