Reputation: 419
I am trying to work on the mechanics for a game I want to work on, however I don't have much experience with this area of programming. I have gotten a circle to move smoothly left and right with the A and D keys using requestAnimationFrame(), however I have absolutely no clue what the best approach would be to make the circle "jump" so to speak.
I want the ball to be able to move upwards when W is pressed until a certain height is reached, and then begin to fall down to the ground at a certain rate. I also want to retain the ability for the ball to move left and right while jumping. I'm not exactly sure how to go about this as I have little experience with request animation frame(), I've tried cancelling the current animation frame and calling a new one within a jump function but that doesn't seem to work at all.
Here is my code so far:
var canvas,
ctx,
westX = 300,
westY = 400,
velX = 0,
velY = 0,
speed = 3,
jumpSpeed = 2,
friction = 0.98,
keys = [],
jumping = false;
window.onload = function(){
canvas = document.getElementById("gameCanvas");
ctx = canvas.getContext("2d");
drawLevel(); //intial level draw
}
function drawLevel() {
move();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#c3c3d5";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(westX,westY,8,0,Math.PI*2,true);
ctx.fill();
if (!keys[87] && !keys[32])
requestAnimationFrame(drawLevel);
if (keys[87] || keys[32])
{
jump();
}
}
Character Movement:
//moves character
function move()
{
//requestAnimationFrame(move);
if (keys[65]) { //if a is pressed
if (velX > -speed) {
velX--;
}
}
if (keys[68]) { //if d is pressed
if (velX < speed) {
velX++;
}
}
velX*= friction;
westX += velX;
//checks if character is at the edge
if (westX >= canvas.width-8)
{
westX = canvas.width-8;
} else if (westX <= 8)
{
westX = 8;
}
}
Attempt at jump function:
function jump()
{
requestAnimationFrame(jump)
if (velY > -jumpSpeed) {
velY--;
}
velY*= friction;
westY += velY;
}
document.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
Also, here is a codepen link to show what I have working so far: https://codepen.io/shanetorres/pen/OvRdjq?editors=1010
Any help or suggestions would be greatly appreciated!
Upvotes: 0
Views: 11691
Reputation: 261
You're on the right track, but the pieces are not arranged correctly.
Divide the character control in two phases: movement calculation, and animation. Think in kinematics: The character's next position is driven by its actual position vector and its current velocity vector.
In the first phase, movement calculation, you alter only the velocity. Left/right modify the horizontal component of the speed, and the jump and gravity modify the vertical component. You want full air control, so both are independent (otherwise, altering the horizontal velocity manipulation would be conditioned by the vertical position, i.e., not jumping/falling). Ignore inertia for the moment (I think that's a better name than friction IMHO). The horizontal velocity velX
is either maxVelX
, -maxVelX
, or 0
, depending on whether right, left, or none/both are pressed. The vertical velocity velY
is 0
if y is below or exactly a given value (i.e., the floor); when on the floor, pressing jump will set velY
to velJump
, and you decrease this value a certain amount every frame (i.e., gravity. Remember that it's an acceleration, i.e., velocity over time). When the character's y
is below the floor level, you set velY
to 0
and y
to the floor level.
Once you have the movement calculated, you apply it to the position (i.e., animate it): x += velX; y += velY;
This is the second phase of the character control.
Once you have this running, you can add inertia. Horizontal velocity is increased/decreased every frame until its "target" velocity is reached. I'd remove the vertical inertia/movement dampening unless you want your player to get stuck on the air or fall like a feather. However, it's usually a good idea to limit the falling speed to a hard limit if there's a lot of verticality in your game.
This is, of course, an over-simplistic approach to physics (common in most platforming/arcade games). For realistic or more elaborate approaches, I'd consider a 2D physics engine and using forces instead of just velocities.
Upvotes: 1
Reputation: 85
Do you specifically want to program the physics yourself or is building the game itself your primary goal? If you're not too interested in programming the physics, I'd recommend that you look into Phaser.io framework for writing the game. It has physics libraries included, there are tons of tutorials and it's just a good tool to for building HTML games.
Upvotes: 0