after an animation, page will not reload - javascript

I'm creating a little bike dude that runs across the screen and when the mouse touches it, it is supposed to stop and look at you. its running, turning, and stopping fine, but when it stops the image of him looking at us is not working. Also, when I try to reload the page, it doesn't. I think there is a loop or something preventing it from reloading.
let speed = 5;
let lastspeed = 0;
let counter = 0;
let x = 50;
let y = 100;
let mX = 0;
let mY = 0;
//flipping and animating
function move() {
x += speed;
document.getElementById('riding').style.left=(x + "px");
if (x + document.getElementById('riding').style.width >= window.innerWidth - 100) {
speed = -5;
document.getElementById('riding').style.transform="rotateY(150deg)";
}
if (x <= 0) {
speed = 5;
document.getElementById('riding').style.transform="rotateY(0deg)";
}
if (speed == 0) {
document.getElementById('riding').src="stop.gif"; console.log('hi')
setTimeout(reset, 2000);
}
requestAnimationFrame(move);
}
//mouse move collision detection
window.addEventListener('mousemove', function(e) {
mX = e.clientX;
mY = e.clientY;
if (mX >= x && mX <= x + 100 && mY >= y && mY <= y + 100) {
lastspeed = speed;
if (counter == 0) {
slow();
counter = 1;
}
}
});
//braking it
function slow() {
document.getElementById('riding').src="brake.gif";
do {
if (speed > 0){
speed -= 0.1;
} else if(speed < 0) {
speed += 0.1;
}
}
while (speed !== 0);
}
//reset
function reset() {
document.getElementById('riding').src="riding.gif";
do {
if (lastspeed > 0) {
speed += 0.1;
} else if (lastspeed < 0) {
speed -= 0.1;
}
}
while(speed !== 5 || speed !== -5);
counter = 0;
}
move();
here is my html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h6 id="message">this is working</h6>
<img src="riding.gif" alt="riding" id="riding">
<script src="rider.js"></script>
</body>
</html>
here is my css
body{
margin: 0px;
}
#riding{
width: 50px;
height: 50px;
position: absolute;
top: 100px;
left: 0px;
transform: rotateY(0deg);
}
#message{
position: absolute;
top: 0;
left: 0;
}
let speed = 5;
let lastspeed = 0;
let counter = 0;
let x = 50;
let y = 100;
let mX = 0;
let mY = 0;
//flipping and animating
function move() {
x += speed;
document.getElementById('riding').style.left=(x + "px");
if (x + document.getElementById('riding').style.width >= window.innerWidth - 100) {
speed = -5;
document.getElementById('riding').style.transform="rotateY(150deg)";
}
if (x <= 0) {
speed = 5;
document.getElementById('riding').style.transform="rotateY(0deg)";
}
if (speed == 0) {
document.getElementById('riding').src="stop.gif"; console.log('hi')
setTimeout(reset, 2000);
}
requestAnimationFrame(move);
}
//mouse move collision detection
window.addEventListener('mousemove', function(e) {
mX = e.clientX;
mY = e.clientY;
if (mX >= x && mX <= x + 100 && mY >= y && mY <= y + 100) {
lastspeed = speed;
if (counter == 0) {
slow();
counter = 1;
}
}
});
//braking it
function slow() {
document.getElementById('riding').src="brake.gif";
do {
if (speed > 0){
speed -= 0.1;
} else if(speed < 0) {
speed += 0.1;
}
}
while (speed !== 0);
}
//reset
function reset() {
document.getElementById('riding').src="riding.gif";
do {
if (lastspeed > 0) {
speed += 0.1;
} else if (lastspeed < 0) {
speed -= 0.1;
}
}
while(speed !== 5 || speed !== -5);
counter = 0;
}
move();
body{
margin: 0px;
}
#riding{
width: 50px;
height: 50px;
position: absolute;
top: 100px;
left: 0px;
transform: rotateY(0deg);
}
#message{
position: absolute;
top: 0;
left: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h6 id="message">this is working</h6>
<img src="riding.gif" alt="riding" id="riding">
<script src="rider.js"></script>
</body>
</html>
here are the animation images I am using:

So a couple problems. Floating point error.
How to deal with floating point number precision in JavaScript?
0.1 is one of those numbers that will cause that problem.
I've gone and dealt with quick and dirty by using Math.abs and comparing difference to < 0.01.
The other problem is your use of lastSpeed. mouseover might sometimes occur at a speed of 0, which causes the loop to get stuck forever, and would cause the direction to be wrong. So I've added a || so that it will ignore 0 speed.
Your 0.1 easing should probably be placed in a rAF loop, as it is right now a blocking operation, so it doesn't function as you intend it to. And/or a timeout loop.
And an idea that you might want to consider is to use a CSS transition to do the easing slowdown for you.
let speed = 5;
let lastspeed = 0;
let counter = 0;
let x = 50;
let y = 100;
let mX = 0;
let mY = 0;
//flipping and animating
function move() {
x += speed;
document.getElementById('riding').style.left=(x + "px");
if (x + document.getElementById('riding').style.width >= window.innerWidth - 100) {
speed = -5;
document.getElementById('riding').style.transform="rotateY(150deg)";
}
if (x <= 0) {
speed = 5;
document.getElementById('riding').style.transform="rotateY(0deg)";
}
if (speed == 0) {
document.getElementById('riding').src="stop.gif";
setTimeout(reset, 2000);console.log('hi');
}
else requestAnimationFrame(move);
}
//mouse move collision detection
window.addEventListener('mousemove', function(e) {
mX = e.clientX;
mY = e.clientY;
if (mX >= x && mX <= x + 100 && mY >= y && mY <= y + 100) {
lastspeed = speed || lastspeed;
if (counter == 0) {
slow();
counter = 1;
}
}
});
//braking it
function slow() {
document.getElementById('riding').src="brake.gif";
do {
if (speed > 0){
speed -= 0.1;
} else if(speed < 0) {
speed += 0.1;
}
}
while (Math.abs(speed)>0.01);
speed=0;
}
//reset
function reset() {
document.getElementById('riding').src="riding.gif";
do {
if (lastspeed > 0) {
speed += 0.1;
} else if (lastspeed < 0) {
speed -= 0.1;
}console.log(lastspeed,speed);
}
while(5-Math.abs(speed) > 0.01);
move();
counter = 0;
}
move();
body{
margin: 0px;
}
#riding{
width: 50px;
height: 50px;
position: absolute;
top: 100px;
left: 0px;
transform: rotateY(0deg);
}
#message{
position: absolute;
top: 0;
left: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h6 id="message">this is working</h6>
<img src="riding.gif" alt="riding" id="riding">
<script src="rider.js"></script>
</body>
</html>

Related

JavaScript Snake Game with two Snakes (Local Mutiplayer)

Im programing a Snake Webgame with HTML, CSS and JavaScript and im implementing Multiple Gamemodes, one should be a Local Multiplayer where one Person is playing with Arrow keys and the Other Person with WASD.
But I got the problem, that I dont know how to Summon a Second Snake. I tried to just copy the Summon Code and rename the variables. But that didn't work, no matter what I tryed.
The code is 90% made by myself, but because of some JavaScript beginner issues I needed some help by the web.
Can someone may tell me how I can summon a Second snake? I just need the "how to" Summon.
let canvas = document.getElementById('game');
let ctx = canvas.getContext('2d');
let grid = 10;
let count = 0;
//Scores
let Score = 0;
let HighScore = 0;
let Alive = true;
//Snake Speed
let Speed = 15;
//Snake Base Stats
let snake = {
x: 200,
y: 200,
dx: grid,
dy: 0,
cells: [],
maxCells: 4
};
//First Apple Spawn
let apple = {
x: 320,
y: 320
};
//Random Int for Apple Spawn
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function loop() {
requestAnimationFrame(loop);
//Tic speed
if (++count < Speed) {
return;
}
count = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height);
snake.x += snake.dx;
snake.y += snake.dy;
//Automatic Movement
if (snake.x < 0) {
snake.x = canvas.width - grid;
} else if (snake.x >= canvas.width) {
snake.x = 0;
}
if (snake.y < 0) {
snake.y = canvas.height - grid;
} else if (snake.y >= canvas.height) {
snake.y = 0;
}
snake.cells.unshift({
x: snake.x,
y: snake.y
});
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}
//Apple Color
ctx.fillStyle = 'gold';
ctx.fillRect(apple.x, apple.y, grid - 1, grid - 1);
//Snake Color
ctx.fillStyle = 'white';
snake.cells.forEach(function(cell, index) {
//Snake Color
ctx.fillRect(cell.x, cell.y, grid - 1, grid - 1);
//Snake Eat Apple
if (cell.x === apple.x && cell.y === apple.y) {
snake.maxCells++;
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
SnakeScore();
}
//Snake Dies
for (var i = index + 1; i < snake.cells.length; i++) {
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
SummonSnake();
Alive = false;
SnakeScore();
}
}
});
}
//Arrow Key Movement
document.addEventListener('keydown', function(e) {
if (e.which === 37 && snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
} else if (e.which === 38 && snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
} else if (e.which === 39 && snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
} else if (e.which === 40 && snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
});
requestAnimationFrame(loop);
//Score
function SnakeScore() {
if (Alive === true) {
Score++;
document.getElementById("Score").innerHTML = Score;
} else if (Alive === false) {
Score = 0;
document.getElementById("Score").innerHTML = Score;
Alive = true;
}
if (Score > HighScore) {
SnakeHighscore();
}
}
//Highscore
function SnakeHighscore() {
HighScore = Score;
document.getElementById("Highscore").innerHTML = HighScore;
}
//Snake Summon Stats
function SummonSnake() {
snake.x = 200;
snake.y = 200;
snake.cells = [];
snake.maxCells = 4;
snake.dx = grid;
snake.dy = 0;
}
//Gamemodes
function GameMode() {
value = document.getElementById('valueGames').value;
if (value === "E") {
Speed = 15;
Score = 0;
document.getElementById("Score").innerHTML = Score;
SummonSnake();
} else if (value === "M") {
Speed = 10;
Score = 0;
document.getElementById("Score").innerHTML = Score;
SummonSnake();
} else if (value === "H") {
Speed = 5;
Score = 0;
document.getElementById("Score").innerHTML = Score;
SummonSnake();
} else if (value === "Multiplayer") {
}
}
body {
display: flex;
align-items: center;
justify-content: center;
background-image: url('https://wallpapercave.com/wp/wp3493594.png');
}
canvas {
width: 403px;
height: 403px;
border: 2px solid rgb(255, 213, 0);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#ScoreCSS {
margin-right: 50px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="main.css">
<meta charset="UTF-8">
<title>Snake NICEEE</title>
</head>
<body>
<!-- Scores -->
<h1 id="ScoreCSS">Score: <a id="Score">0</a></h1>
<h1>Highscore: <a id="Highscore">0</a></h1>
<!-- Canvas (Game Field)-->
<canvas id="game" width="400" height="400"></canvas>
<!-- Dropdown for GameModes -->
<select id="valueGames" onchange="GameMode()">
<option value="E" selected>Easy</option>
<option value="M">Middle</option>
<option value="H">Hard</option>
<option value="Multiplayer">Multiplayer</option>
</select>
</body>
</html>
This should get you started. I created a second snake object and moved the alive property to the snake. Then I added functions to draw/move the snake and passed the snake object to those functions so you don't have as much duplicate code in order to handle multiple snakes. (Theoretically, you could add more than 2 snakes this way by creating new snake objects and then adding moveSnake(snake3, canvas); etc).
You'll need to add the event listeners for WASD as well as "dead" game logic in Multiplayer mode, because presumably the game will pause somehow and show the winner and the high score.
let canvas = document.getElementById('game');
let ctx = canvas.getContext('2d');
let grid = 10;
let count = 0;
//Scores
let Score = 0;
let HighScore = 0;
let Speed = 15;
//Snake Base Stats
let snake = {
x: 200,
y: 200,
dx: grid,
dy: 0,
cells: [],
maxCells: 4,
alive: true, // moved the global var here
active: true, // added this in order to track multiple snakes being active
color: 'white' // moved this here to define it per-snake
};
let snake2 = {
x: 200,
y: 200,
dx: grid,
dy: 0,
cells: [],
maxCells: 4,
alive: true,
active: false,
color: 'red'
};
// keep track of active snakes
let snakes = [
snake
];
//First Apple Spawn
let apple = {
x: 320,
y: 320,
color: 'gold'
};
//Random Int for Apple Spawn
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function loop() {
requestAnimationFrame(loop);
//Tic speed
if (++count < Speed) {
return;
}
count = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height);
moveSnakes(snakes, canvas);
//Apple Color
ctx.fillStyle = apple.color;
ctx.fillRect(apple.x, apple.y, grid - 1, grid - 1);
drawSnakes(snakes, ctx, apple);
}
//Arrow Key Movement
document.addEventListener('keydown', function(e) {
if (e.which === 37 && snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
} else if (e.which === 38 && snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
} else if (e.which === 39 && snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
} else if (e.which === 40 && snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
});
//TODO: add movement for snake2
requestAnimationFrame(loop);
function moveSnakes(snakes, canvas) {
snakes.forEach(function(snake) {
if (!snake.active) {
return;
}
snake.x += snake.dx;
snake.y += snake.dy;
if (snake.x < 0) {
snake.x = canvas.width - grid;
} else if (snake.x >= canvas.width) {
snake.x = 0;
}
if (snake.y < 0) {
snake.y = canvas.height - grid;
} else if (snake.y >= canvas.height) {
snake.y = 0;
}
snake.cells.unshift({
x: snake.x,
y: snake.y
});
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}
});
}
function drawSnakes(snakes, ctx, apple) {
snakes.forEach(function(snake) {
if (!snake.active) {
return;
}
//Snake Color
ctx.fillStyle = snake.color;
snake.cells.forEach(function(cell, index) {
//Snake Color
ctx.fillRect(cell.x, cell.y, grid - 1, grid - 1);
//Snake Eat Apple
if (cell.x === apple.x && cell.y === apple.y) {
snake.maxCells++;
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
SnakeScore(snake);
}
//Snake Dies
for (var i = index + 1; i < snake.cells.length; i++) {
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
SummonSnake(snake);
snake.alive = false;
SnakeScore();
}
}
});
});
}
//Score
function SnakeScore(snake) {
if (snake.alive) {
Score++;
document.getElementById("Score").innerHTML = Score;
} else if (!snake.alive) {
Score = 0;
document.getElementById("Score").innerHTML = Score;
snake.alive = true;
}
if (Score > HighScore) {
SnakeHighscore();
}
}
//Highscore
function SnakeHighscore() {
HighScore = Score;
document.getElementById("Highscore").innerHTML = HighScore;
}
//Snake Summon Stats
function SummonSnake(snake, y) {
snake.x = 200;
snake.y = y;
snake.cells = [];
snake.maxCells = 4;
snake.dx = grid;
snake.dy = 0;
}
function activateSnakes(numberOfSnakes) {
if (numberOfSnakes === 1) {
SummonSnake(snake, 200);
snakes = [snake];
snake2.active = false;
} else if (numberOfSnakes === 2) {
SummonSnake(snake, 180);
SummonSnake(snake2, 220);
snakes = [snake, snake2];
snake2.active = true;
}
}
//Gamemodes
function GameMode() {
value = document.getElementById('valueGames').value;
if (value === "E") {
Speed = 15;
activateSnakes(1);
} else if (value === "M") {
Speed = 10;
activateSnakes(1);
} else if (value === "H") {
Speed = 5;
activateSnakes(1);
} else if (value === "Multiplayer") {
Speed = 5;
activateSnakes(2);
}
Score = 0;
document.getElementById("Score").innerHTML = Score;
}
GameMode();
body {
display: flex;
align-items: center;
justify-content: center;
background-image: url('https://wallpapercave.com/wp/wp3493594.png');
}
canvas {
width: 403px;
height: 403px;
border: 2px solid rgb(255, 213, 0);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#ScoreCSS {
margin-right: 50px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="main.css">
<meta charset="UTF-8">
<title>Snake NICEEE</title>
</head>
<body>
<!-- Scores -->
<h1 id="ScoreCSS">Score: <a id="Score">0</a></h1>
<h1>Highscore: <a id="Highscore">0</a></h1>
<!-- Canvas (Game Field)-->
<canvas id="game" width="400" height="400"></canvas>
<!-- Dropdown for GameModes -->
<select id="valueGames" onchange="GameMode()">
<option value="E">Easy</option>
<option value="M">Middle</option>
<option value="H">Hard</option>
<option value="Multiplayer" selected>Multiplayer</option>
</select>
</body>
</html>

Pong ball - high speed results in ball not colliding - Javascript

I'm making a pong ball game in javascript. When the velocity is low, the game works fine and the ball will collide with the paddle. However, when the velocity gets high, the ball will "teleport" through the paddle, because the ball's position is updated this way:
update(delta, playerPad, aiPad) {
this.x += this.direction.x * this.velocity * delta;
this.y += this.direction.y * this.velocity * delta;
}
How can I solve this issue? This caused the game to be unplayable at high speed. Below is my coding snippet
const INIT_VELOCITY = 0.3;
const INCREMENT_VELOCITY = 0.000;
const PI = Math.PI;
class Ball {
constructor(ballElem) {
this.ball = ballElem;
this.reset();
}
get x() {
return parseFloat(getComputedStyle(this.ball).getPropertyValue("--x"));
}
get y() {
return parseFloat(getComputedStyle(this.ball).getPropertyValue("--y"));
}
set x(value) {
this.ball.style.setProperty("--x", value);
}
set y(value) {
this.ball.style.setProperty("--y", value);
}
reset() {
this.x = 50;
this.y = 50;
this.velocity = INIT_VELOCITY;
//setting the direction of the ball
// let angle = Math.random() * 2 * PI;
let angle = 2*PI;
// while (
// (angle > PI / 3 && angle < (2 * PI) / 3) ||
// (angle > (4 * PI) / 3 && angle < (5 * PI) / 3)
// ) {
// angle = Math.random() * 2 * PI;
// }
this.direction = {
x: Math.cos(angle),
y: Math.sin(angle),
};
}
rect() {
return this.ball.getBoundingClientRect();
}
update(delta, playerPad, aiPad) {
this.x += this.direction.x * this.velocity * delta;
this.y += this.direction.y * this.velocity * delta;
this.velocity += INCREMENT_VELOCITY;
const rect = this.rect();
if (rect.top <= 0) {
this.direction.y *= -1;
this.y = 0 + (this.rect().height / 2 / innerHeight) * 100;
}
if (rect.bottom >= innerHeight) {
this.direction.y *= -1;
this.y = ((innerHeight - this.rect().height / 2) / innerHeight) * 100;
}
if(this.isColliding(rect,playerPad.rect())){
this.direction.x *= -1;
this.x = ( playerPad.rect().right + rect.width / 2 ) / innerWidth * 100;
}
if(this.isColliding(rect,aiPad.rect())){
this.direction.x *= -1;
this.x = ( aiPad.rect().left - rect.width / 2 ) / innerWidth * 100;
}
if (rect.left <= 0) {
this.reset();
}
if (rect.right >= innerWidth) {
this.reset();
}
}
isColliding(rect1, rect2) {
// console.log("collision");
return rect1.right >= rect2.left
&& rect1.left <= rect2.right
&& rect1.bottom >= rect2.top
&& rect1.top <= rect2.bottom
}
}
class Paddle {
constructor(padElem){
this.pad = padElem;
}
get y(){
return getComputedStyle(this.y).getPropertyValue("--y");
}
set y(value){
this.pad.style.setProperty("--y",value);
}
rect(){
return this.pad.getBoundingClientRect();
}
}
const ball = new Ball(document.querySelector("#ball"));
const playerPad = new Paddle(document.querySelector("#player-pad"));
const aiPad = new Paddle(document.querySelector("#ai-pad"));
let lastTime = 0;
function update(time){
const delta = time - lastTime;
lastTime = time;
ball.update(delta,playerPad,aiPad);
aiPad.y = ball.y;
requestAnimationFrame(update);
}
requestAnimationFrame(update);
document.addEventListener("mousemove",e=>{
playerPad.y = e.y / innerHeight * 100;
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--paddle-color: white;
--ball-color: white;
}
body {
background-color: black;
overflow: hidden;
}
#ball {
--x: 50;
--y: 50;
position: absolute;
top: calc(var(--y)*1vh);
left: calc(var(--x)*1vw);
transform: translate(-50%,-50%);
width: calc(1vw + 1rem);
height: calc(1vw + 1rem);
background-color: var(--ball-color);
border-radius: 50%;
}
.paddle {
--y: 50;
position: absolute;
width: 5px;
height: 15vh;
background-color: var(--paddle-color);
border-radius: 2rem;
top: calc(var(--y)*1vh);
transform: translate(0,-50%);
}
#player-pad {
left: 4px;
}
#ai-pad {
right: 4px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pong Ball Clone</title>
<link href="./index.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="ball"></div>
<div class="paddle" id="player-pad"></div>
<div class="paddle" id="ai-pad"></div>
<script src="./script.js" type="module"></script>
</body>
</html>

Why does my animation teleport to the bottom left at the end

I am trying to make an animation of a circle bouncing around in a square. Currently when ever the animation reaches the last section of the script it warps to the bottom left. If any one knows why it is warping or a simpler way to write this animation let me know. Thank you for your time.
function myMove() {
var elem = document.getElementById("color");
var pos = 286;
var num = 0;
var id = setInterval(frame, 10);
function frame() {
if (num >= 183 && num < 512) {
pos--;
num++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
} else if (pos < 469 && num < 183) {
pos++;
num++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
} else if (pos == 140 || num >= 512 && num < 918) {
pos++;
num++;
elem.style.top = pos / 2 + 'px';
elem.style.left = pos + 'px';
} else if (pos <= 140 || num >= 918 && num < 929) {
pos--;
num++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
.square {
height: 500px;
width: 500px;
background-color: white;
border-style: solid;
border-width: 2px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.circle {
height: 100px;
width: 100px;
background-color: #555;
border-radius: 50%;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div class="square"></div>
<div class="circle" id="color"></div>
This is how I would do it:
I commented my code with the steps I took.
I moved the circle into the square and changed the position to be relative to let css handle the rest.
var timer;
function myMove() {
var circle = document.getElementById("circle");
var square = document.getElementById("square");
var posx = 0, posy = 0;
var squarew = square.clientWidth, squareh = square.clientHeight;
// moved timer to outer scope to clear it evertime the button is clicked
if (timer) clearInterval(timer);
timer = setInterval(frame, 10);
// made the circle configurable to be able to change the size of it
var circleRadius = 50;
circle.style.height = circleRadius * 2 + 'px';
circle.style.width = circleRadius * 2 + 'px';
// this is how fast the ball is going to move (in pixels)
var distance = 10;
// fire off in a random direction
var randomDirection = Math.random(0, 100);
// get the velocity in the x direction and y direction
var vy = distance * Math.sin(randomDirection);
var vx = distance * Math.cos(randomDirection);
function frame() {
// if i hit any edge of the box
if (posy + vy <= 0) {
// reverse the direction
vy *= -1;
}
if (posy + vy >= squareh - circleRadius * 2) {
// reverse the direction
vy *= -1;
}
if (posx + vy <= 0) {
// reverse the direction
vx *= -1;
}
if (posx + vy >= squarew - circleRadius * 2) {
// reverse the direction
vx *= -1;
}
// keep track of the position
posx += vx;
posy += vy;
// apply it to the circle
circle.style.top = posy + 'px';
circle.style.left = posx + 'px';
}
}
#square {
height: 500px;
width: 500px;
background-color: white;
border-style: solid;
border-width: 2px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#circle {
background-color: #555;
border-radius: 50%;
position: relative;
top: 0;
left: 0;
}
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="square">
<div id="circle"></div>
</div>

Why JS animation is stuck?

I want the box to traverse the inside of the container from left to right, then down, then right to left and finally back up to the original position. The examples I found all include extra array pos = [180,180]. I don't understand why do I need it when my IF conditions seem to cover all positions.
window.onload = function() {
var t = setInterval(slide, 5);
pos1 = [0, 0];
var box = document.getElementById('sqr');
function slide() {
if (pos1[0] < 180 && pos1[1] < 180) {
pos1[0]++;
box.style.left = pos1[0] + "px";
} else if (pos1[0] >= 180 && pos1[1] < 180) {
pos1[1]++;
box.style.top = pos1[1] + "px";
} else if (pos1[0] >= 180 && pos1[1] >= 180) {
pos1[0]--;
box.style.left = pos1[0] + "px";
} else if (pos1[0] <= 0 && pos1[1] >= 180) {
pos1[1]--;
box.style.top = pos1[1] + "px";
}
}
}
#contain {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
}
#sqr {
position: absolute;
width: 20px;
height: 20px;
background-color: blue;
}
<div id="contain">
<div id="sqr"></div>
</div>
Once the box gets to the maximum X and Y positions, the program is still checking to make sure the box hasn't reached the maximum yet, which causes the all IF conditions to fail. You could do it by checking for Y=0 for the first "leg", X=MAX for the next, Y=MAX for the next, and then X=0 for the last, but instead of that, you can set a "state" which has 4 values to determine which "leg" of the animation is being run, and then just run it for 180 iterations each.
window.onload = function() {
var t = setInterval(slide, 5);
pos1 = [0, 0];
var box = document.getElementById('sqr');
state = 0;
iterations = 0;
function slide() {
if (iterations >= 180) {state = (state + 1) % 4; iterations = 0;}
if (state === 0) pos1[0]++;
else if (state == 1) pos1[1]++;
else if (state == 2) pos1[0]--;
else if (state == 3) pos1[1]--;
iterations++;
box.style.left = pos1[0] + "px";
box.style.top = pos1[1] + "px";
}
}
#contain {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
}
#sqr {
position: absolute;
width: 20px;
height: 20px;
background-color: blue;
}
<div id="contain">
<div id="sqr"></div>
</div>
window.onload = function() {
var t = setInterval(slide, 5);
var box = document.getElementById('sqr');
var left = 0,
top = 0;
function slide() {
var pos1 = [parseInt(box.style.left || 0), parseInt(box.style.top || 0)]
console.log(pos1);
if (pos1[0] == 0 && pos1[1] == 0) { //Top left, go right
left = 1;
top = 0;
} else if (pos1[0] == 180 && pos1[1] == 0) { //Top right, go down
left = 0;
top = 1;
} else if (pos1[0] == 180 && pos1[1] == 180) { //Bottom right, go left
left = -1;
top = 0;
} else if (pos1[0] == 0 && pos1[1] == 180) { //Bottom left, go up
left = 0;
top = -1;
}
box.style.left = (parseInt(box.style.left || 0) + left) + "px";
box.style.top = (parseInt(box.style.top || 0) + top) + "px";
}
}
#contain {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
}
#sqr {
position: absolute;
width: 20px;
height: 20px;
background-color: blue;
}
<div id="contain">
<div id="sqr"></div>
</div>
Here's my take on it. React according to the position of the element, when it reaches a corner, change directions. This makes things easier, since we do not rely on actual positions to know where to go next step...
It is because, when animation gets to pos1 = [180, 180], it executes:
else if (pos1[0] >= 180 && pos1[1] >= 180) {
pos1[0]--;
box.style.left = pos1[0] + "px";
}
And then pos1 = [179, 180], which is not covered by the code.
I suggest using something like that:
var direction = 0; //0 - right, 1 - down, 2 - left, 3 - up
function slide() {
if (pos1[0] < 180 && pos1[1] = 0) {
direction = 0;
} else if (pos1[0] = 180 && pos1[1] < 180) {
direction = 1;
} else if (pos1[0] > 0 && pos1[1] = 180) {
direction = 2;
} else if (pos1[0] = 0 && pos1[1] > 0) {
direction = 3;
}
switch(direction){
case 0:
pos1[0]++;
break;
case 1:
pos1[1]++;
break;
case 2:
pos1[0]--;
break;
case 3:
pos1[1]--;
break;
}
box.style.left = pos1[0] + "px";
box.style.top = pos1[1] + "px";
}
I'm not usually a fan of doing someone's homework for them, but I got intrigued as to what would make it work and couldn't help myself. shrugs
The if statements have been tailored to be more explicit with what they need. This of course was achieved by following the methods suggested to you by #j08691, by just adding a console.log(pos1); at the top of each if section.
This is just for reference, in fact, #Salketer has managed to post before me and it looks a lot cleaner than this. The real answer is in the comments by #j08691
window.onload = function() {
var t = setInterval(slide, 5),
pos1 = [0, 0],
box = document.getElementById('sqr');
function slide() {
if (pos1[0] < 180 && pos1[1] === 0) {
console.log(pos1);
pos1[0]++;
box.style.left = pos1[0] + "px";
} else if (pos1[0] === 180 && pos1[1] < 180) {
console.log(pos1);
pos1[1]++;
box.style.top = pos1[1] + "px";
} else if ((pos1[0] <= 180 && pos1[0] >= 1) && pos1[1] === 180) {
console.log(pos1);
pos1[0]--;
box.style.left = pos1[0] + "px";
} else if (pos1[0] === 0 && pos1[1] <= 180) {
console.log(pos1);
pos1[1]--;
box.style.top = pos1[1] + "px";
}
}
}
#contain {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
}
#sqr {
position: absolute;
width: 20px;
height: 20px;
background-color: blue;
}
<div id="contain">
<div id="sqr"></div>
</div>

How to clear image right into next html canvas games?

I made a game, a race car game. The code is:
index.html
<!DOCTYPE html>
<html>
<head>
<title> Race car </title>
<link rel="stylesheet" type="text/css" href="style.css">
<script>
var ctx;
//save the parameters to variables for easier clearing
var x_Car = 30,
y_Car = 95,
width_Car = 110,
height_Car = 55,
imgCar = new Image();
imgCar.src = "cars/race-car.png";
var nrMonsters = 0,
imgMonster = new Image();
imgMonster.src = "Monster/yellow_monster.png";
var width_Monster = 100;
var height_Monster = 20;
var x_Monster = 50;
var y_Monster = 5;
var speed = 1;
// function drawMonster() {
// ctx.drawImage(imgMonster, x_Monster, y_Monster, width_Monster, height_Monster);
// }
function drawCar() {
ctx.drawImage(imgCar, x_Car, y_Car, width_Car, height_Car);
}
function rand() {
var left = 50;
var right = 150;
var z;
var random = Math.random();
if (random > 0.5) {
z = right;
} else {
z = left;
}
return z;
}
valX = rand();
function draw(x, y) {
//ctx.save();
if (valX == 50 && x_Car > 75) {
ctx.clearRect(x + 5, -5, 150, 150); // 95 cu 150
} else if (valX == 50) {
ctx.clearRect(x + 5, y, 150, 10);
} else if (valX == 150 && x_Car < 32){
ctx.clearRect(x + 150, -5, 260, 150); // 95 cu 150
} else if (valX == 150) {
ctx.clearRect(x + 150, y, 260, 10);
}
ctx.drawImage(imgMonster, valX, y, width_Monster, height_Monster);
ctx.restore();
y += speed;
if (y == y_Car && x_Car < 32 && valX == 50
|| y == y_Car && x_Car > 75 && valX == 150
|| y > y_Car && y < y_Car + height_Car && x_Car < 32 && valX == 50
|| y > y_Car && y < y_Car + height_Car && x_Car > 75 && valX == 150) {
window.location.href = "you_lost_the_game.html";
// alert("You lost the game");
}
var loopTimer = setTimeout("draw(" + x + ", " + y + ")", 20);
if (y == 150 && nrMonsters < 15
|| y == 160 && nrMonsters >= 15) {
valX = rand();
nrMonsters++;
console.log(nrMonsters);
document.getElementById("numarObstacole").innerHTML = nrMonsters;
if (nrMonsters == 5
|| nrMonsters == 10
|| nrMonsters == 20
|| nrMonsters == 25) {
// || nrMonsters == 20 || nrMonsters == 27) {
speed += 1;
} else if (nrMonsters == 15) {
speed += 1;
}
draw(0, 0);
if (nrMonsters == 25) {
window.location.href = "win.html";
}
}
}
function init() {
ctx = document.getElementById("canvas").getContext("2d");
// audio
// myAudio = new Audio('http://static1.grsites.com/archive/sounds/cars/cars002.wav');
myAudio = new Audio("Sounds/Get low NFS.mp3");
myAudio.addEventListener("ended", function() {
this.currentTime = 0;
this.play();
}, false);
myAudio.play();
//draw wall
draw(0, 0);
drawCar();
function moveRight() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
x_Car = x_Car + 120;
if(x_Car > 220){
x_Car -= 120;
drawCar();
} else {
drawCar();
}
}
function moveLeft() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
x_Car = x_Car-120;
if (x_Car < 20) {
x_Car += 120;
drawCar();
} else {
drawCar();
}
}
function moveUp() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
y_Car = y_Car-20;
drawCar();
}
function moveDown() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
y_Car = y_Car + 20;
drawCar();
}
window.addEventListener("keypress", checkKeyPressed, false);
function checkKeyPressed(e) {
if (e.charCode == "97" || e.charCode == 027) {
moveLeft();
}
if (e.charCode == "100" || e.charCode== 026) {
moveRight();
}
if (e.charCode == "119" || e.charCode== 024) {
moveUp();
}
if (e.charCode == "115" || e.charCode== 025) {
moveDown();
}
}
}
function moveRight() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
x_Car = x_Car + 120;
if (x_Car > 220) {
x_Car -= 120;
drawCar();
} else {
drawCar();
}
}
function moveLeft() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
x_Car = x_Car - 120;
if(x_Car < 20) {
x_Car += 120;
drawCar();
} else {
drawCar();
}
}
function moveUp() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
y_Car = y_Car - 20;
drawCar();
}
function moveDown() {
ctx.clearRect(x_Car, y_Car, width_Car, height_Car);
y_Car = y_Car + 20;
drawCar();
}
window.addEventListener("keypress", checkKeyPressed, false);
function checkKeyPressed(e) {
if (e.charCode == "97") {
moveLeft();
}
if (e.charCode == "100") {
moveRight();
}
if (e.charCode == "119") {
moveUp();
}
if (e.charCode == "115") {
moveDown();
}
}
</script>
</head>
<body onLoad="init();">
<div id="moveButons">
<table>
<tr>
<td></td>
<td>
<input class="button" id="up" type="button" value="Move Up" onclick="moveUp()"/>
</td>
<td></td>
</tr>
<tr>
<td>
<input class="button" id="left" type="button" value="Move Left" onclick="moveLeft()"/>
</td>
<td></td>
<td>
<input class="button" id="right" type="button" value="Move Right" onclick="moveRight()"/>
</td>
</tr>
<tr>
<td></td>
<td>
<input class="button" id="down" type="button" value="Move Down" onclick="moveDown()"/>
</td>
<td></td>
</tr>
</table>
</div>
<p class="numarObstacole">
Ai trecut peste <span id="numarObstacole"> 0 </span> obstacole
</p>
<canvas id="canvas">
Your browser doesn't support the HTML5 element canvas.
</canvas>
</body>
</html>
style.css
* {
margin: 0;
padding: 0;
}
body {
background-color: yellow;
}
#canvas {
background: white;
margin-left: 50%;
position: absolute;
left: -206px;
width: 412px;
height: 100%;
background-image: url("street/street (2).jpg");
background-position: 0px 0px;
background-repeat: repeat-y;
-webkit-animation: animatedBackground 5s linear infinite;
-moz-animation: animatedBackground 5s linear infinite;
animation: animatedBackground 5s linear infinite;
}
#moveButons {
position: absolute;
left: 20px;
top: 50px;
}
#-webkit-keyframes animatedBackground {
from { background-position: 0 100%; }
to { background-position: 0 0; }
}
#-moz-keyframes animatedBackground {
from { background-position: 0 100%; }
to { background-position: 0 0; }
}
#keyframes animatedBackground {
from { background-position: 0 100%; }
to { background-position: 0 0; }
}
#lostGame {
text-align: center;
color: red;
margin-top: 175px;
}
#win {
text-align: center;
color: blue;
margin-top: 175px;
}
#canvas_lost {
width: 320px;
height: 240px;
background: url("Joker/the-joker-laughing-1.jpg");
margin-left: 50%;
position: absolute;
left: -160px;
}
#canvas_win {
width: 320px;
height: 240px;
background: url("Joker/joker.gif");
margin-left: 50%;
position: absolute;
left: -160px;
}
.button {
color: blue;
font-size: 17px;
text-align: center;
background: #6BA7FA;
width: 100px;
}
.numarObstacole {
position: absolute;
color: #1F1;
background: silver;
font-size: 20px;
font-family: Serif;
}
#numarObstacole {
color: blue;
font-size: 22px;
font-family: sans-serif;
}
win.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<title> Win </title>
<script>
function init() {
var canvas = document.getElementById("canvas_win");
var ctx = canvas.getContext("2d");
var myAudio = new Audio("Sounds/Fireworks Finale.mp3");
myAudio.addEventListener("ended", function() {
this.currentTime = 0;
this.play();
}, false);
myAudio.play();
var otherAudio = new Audio("Sounds/Audience_Applause.mp3");
otherAudio.addEventListener("ended", function() {
this.currentTime = 0;
this.play();
}, false);
otherAudio.play()
}
</script>
</head>
<body onLoad="init();">
<h1 id="win"> You win </h1>
<canvas id="canvas_win">
Your browser doesn't support the HTML5 element canvas.
</canvas>
</body>
</html>
you_lost_the_game.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<title> You lost the game </title>
<script>
function init() {
var canvas = document.getElementById("canvas_lost");
var ctx = canvas.getContext("2d");
var myAudio = new Audio("Sounds/hahaha-Peter_De_Lang.mp3");
myAudio.addEventListener("ended", function() {
this.currentTime = 0;
this.play();
}, false);
myAudio.play();
}
</script>
</head>
<body onLoad="init();">
<h1 id="lostGame"> You lost the game </h1>
<canvas id="canvas_lost">
Your browser doesn't support the HTML5 element canvas.
</canvas>
</body>
</html>
The problem is with the monster image.
When this image comes to the car image with a bigger speed, it leaves behind some "trail".
How can I solve it?
The answer
I believe your issue is with your clearing with clearRect. Instead of carefully finding specific places to clear the canvas (i.e. ctx.clearRect(x + 150, -5, 260, 150);), you should just up and do:
// Get <canvas> on a variable
var canvas = document.getElementById("canvas");
// ctx is still the same
var ctx = canvas.getContext("2d");
function draw(x, y) {
// Clears everything on the canvas on every loop
ctx.clearRect(0, 0, canvas.width, canvas.height);
...
That way, any "trail" left by the car or by the monster will be cleared on every frame.
Now, for coding suggestions:
Instead of adding an event listener for when an audio ends, simply turn the loop property to true. Here's some code:
// Your current code
var myAudio = new Audio("Sounds/---.mp3");
myAudio.addEventListener("ended", function() {
this.currentTime = 0;
this.play();
}, false);
myAudio.play();
// Some smaller and more efficient code
var myAudio = new Audio("Sounds/---.mp3");
myAudio.loop = true; // Restarts the audio every time it reaches the end
myAudio.play();
This code doesn't make much sense:
if (nrMonsters == 5
|| nrMonsters == 10
|| nrMonsters == 20
|| nrMonsters == 25) {
// || nrMonsters == 20 || nrMonsters == 27) {
speed += 1;
} else if (nrMonsters == 15) {
speed += 1;
}
If something do this otherwise do the same thing? Here's a quick fix:
if (nrMonsters == 5
|| nrMonsters == 10
|| nrMonsters == 15
|| nrMonsters == 20
|| nrMonsters == 25) {
speed += 1;
}
You don't need this else here:
// From the moveRight() function
if (x_Car > 220) {
x_Car -= 120;
drawCar();
} else {
drawCar();
}
You see, if you're going to drawCar() anyway, you don't need to put it inside the if. Here's better code:
if (x_Car > 220) {
x_Car -= 120;
}
drawCar();
You shouldn't have those leading zeroes:
// From the checkKeyPressed() function
if (e.charCode == "97" || e.charCode == 027) { ... }
That 027 (and some subsequent numbers with leading a 0) gets treated as a base 8 number. I'm pretty sure it wasn't your intention to have an octal number there, but if that's the case, then the proper formatting is prepeding it with 0o instead of simply a zero.
var binal = 0b10; // (0b)10 in base 2 is equal to 2 in decimal
var octal = 0o10; // (0o)10 in base 8 is equal to 8 in decimal
var hexal = 0x10; // (0x)10 in base 16 is equal to 16 in decimal
That's all that I found. I wish you good luck with your game! Cheers!

Categories

Resources