Reputation: 27
So, I'm trying to code a game where there is a ball that chases the player, and currently I'm coding the player physics. For some reason, as the player walks back and forth, it gets faster and faster, but I can't figure out why. I think it might have something to do with me multiplying the physicsX variable by .85, but I can't figure out how that would affect it. Here is my code-
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var baseX = 100;
var baseY = 50;
var physicsY = 0;
var physicsX = 0;
function coronavirus() {
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(50, 50, 5, 0, 2 * Math.PI, false);
ctx.fill();
}
function ground() {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(0, 140, screen.width, 10);
ctx.fill();
}
function person() {
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.arc(baseX, baseY, 5, 0, 2 * Math.PI, false); //head
ctx.stroke();
ctx.moveTo(baseX, baseY + 5); //body
ctx.lineTo(baseX, baseY + 20);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //left leg
ctx.lineTo(baseX - 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //right leg
ctx.lineTo(baseX + 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX - 5, baseY + 10); //arms
ctx.lineTo(baseX + 5, baseY + 10);
ctx.stroke();
}
function personHitbox() {
ctx.beginPath();
ctx.strokeStyle = "black"
ctx.rect(baseX - 5, baseY - 5, 10, 32);
ctx.stroke();
}
function personTouchingGround() {
var personHitbox = {y: baseY - 5, height: 32}
var ground = {y: 140}
if (personHitbox.y + personHitbox.height < ground.y) {
touchingGround = false;
} else {
touchingGround = true;
}
}
function personMoving() {
if (touchingGround == false) {
physicsY++;
baseY = baseY + physicsY;
}
physicsX = 0;
window.addEventListener('keydown', (e) => {
if (e.key == "ArrowRight") {
physicsX = physicsX + 0.001;
}
if (e.key == "ArrowLeft") {
physicsX = physicsX - 0.001;
}
physicsX = physicsX * 0.85
baseX = baseX + physicsX;
});
}
function gameloop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
new coronavirus();
new person();
new personHitbox();
new personTouchingGround();
new personMoving();
new ground();
requestAnimationFrame(gameloop);
}
gameloop();
canvas {
width: 100%;
height: 100%;
margin: 0%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<canvas id="canvas"></canvas>
<script src="script.js"></script>
</body>
</html>
Upvotes: 0
Views: 292
Reputation: 353
The playerX variable only decreases by 15% (0.15) every time a key is pressed. To fix this, simply move that line outside of the keypress event listener into the game loop (just somewhere where it'll be run on each iteration of the loop).
Edit: As @user120242 mentioned, the event listener should be moved outside of the loop too. However, my slightly modified solution preserves (I believe intended) horizontal velocity. The only problem is that there's a delay in the keypress with both solutions, which you can refer to How to fix delay in javascript keydown for.
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var baseX = 100;
var baseY = 50;
var physicsY = 0;
var physicsX = 0;
//move this outside
window.addEventListener('keydown', (e) => {
if (e.key == "ArrowRight") {
physicsX += 5;
}
if (e.key == "ArrowLeft") {
physicsX -= 5;
}
});
function coronavirus() {
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(50, 50, 5, 0, 2 * Math.PI, false);
ctx.fill();
}
function ground() {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(0, 140, screen.width, 10);
ctx.fill();
}
function person() {
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.arc(baseX, baseY, 5, 0, 2 * Math.PI, false); //head
ctx.stroke();
ctx.moveTo(baseX, baseY + 5); //body
ctx.lineTo(baseX, baseY + 20);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //left leg
ctx.lineTo(baseX - 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //right leg
ctx.lineTo(baseX + 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX - 5, baseY + 10); //arms
ctx.lineTo(baseX + 5, baseY + 10);
ctx.stroke();
}
function personHitbox() {
ctx.beginPath();
ctx.strokeStyle = "black"
ctx.rect(baseX - 5, baseY - 5, 10, 32);
ctx.stroke();
}
function personTouchingGround() {
var personHitbox = {
y: baseY - 5,
height: 32
}
var ground = {
y: 140
}
if (personHitbox.y + personHitbox.height < ground.y) {
touchingGround = false;
} else {
touchingGround = true;
}
}
function personMoving() {
if (touchingGround == false) {
physicsY++;
baseY += physicsY;
}
//physicsX = 0; remove this line of code
//moving the line here will guarantee physicsX decreases on each
//iteration of the loop.
physicsX *= 0.85;
baseX += physicsX;
}
function gameloop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
new coronavirus();
new person();
new personHitbox();
new personTouchingGround();
new personMoving();
new ground();
requestAnimationFrame(gameloop);
}
gameloop();
<canvas id="canvas"></canvas>
Also, using += can simplify your code. For example:
playerX = playerX + 15;
is the same as playerX += 15;
Upvotes: 0
Reputation: 15268
Two issues:
You keep adding to physicsX, so the amount of distance it moves keeps increasing. Just keep physicsX constant to move the same amount. (Actually doesn't, because every animation frame you are setting PhysicsX = 0, but the logic is wrong. When you fix the real error, this causes the unit not to move properly.)
Move the 'keydown' event binding outside personMoving() so it only executes once. Your event listener binding is being executed every time you call personMoving(), so it is binding 'key' event over and over again, and then you get 'key' event triggered more and more over time.
So after 100 animation frames each keypress will trigger the baseX and PhysicsX adding code 100 times.
You should only bind the key event once.
I've also used Math.abs and *-1 for right left movement.
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var baseX = 100;
var baseY = 50;
var physicsY = 0;
var physicsX = 0;
function coronavirus() {
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(50, 50, 5, 0, 2 * Math.PI, false);
ctx.fill();
}
function ground() {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(0, 140, screen.width, 10);
ctx.fill();
}
function person() {
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.arc(baseX, baseY, 5, 0, 2 * Math.PI, false); //head
ctx.stroke();
ctx.moveTo(baseX, baseY + 5); //body
ctx.lineTo(baseX, baseY + 20);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //left leg
ctx.lineTo(baseX - 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX, baseY + 20); //right leg
ctx.lineTo(baseX + 3, baseY + 27);
ctx.stroke();
ctx.moveTo(baseX - 5, baseY + 10); //arms
ctx.lineTo(baseX + 5, baseY + 10);
ctx.stroke();
}
function personHitbox() {
ctx.beginPath();
ctx.strokeStyle = "black"
ctx.rect(baseX - 5, baseY - 5, 10, 32);
ctx.stroke();
}
function personTouchingGround() {
var personHitbox = {
y: baseY - 5,
height: 32
}
var ground = {
y: 140
}
if (personHitbox.y + personHitbox.height < ground.y) {
touchingGround = false;
} else {
touchingGround = true;
}
}
function personMoving() {
if (touchingGround == false) {
physicsY++;
baseY = baseY + physicsY;
}
}
physicsX = 10;
window.addEventListener('keydown', (e) => {
if (e.key == "ArrowRight") {
physicsX = Math.abs(physicsX);
}
if (e.key == "ArrowLeft") {
physicsX = Math.abs(physicsX)*-1;
}
// physicsX = physicsX * 0.85
baseX = baseX + physicsX;
// put this console.log in your original code to see what I mean
// console.log(baseX)
});
function gameloop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
new coronavirus();
new person();
new personHitbox();
new personTouchingGround();
new personMoving();
new ground();
requestAnimationFrame(gameloop);
}
gameloop();
<canvas id="canvas"></canvas>
Upvotes: 2