Trouble with adding gravity to 2d platformer - javascript

I am trying to make a 2D platforming game and I am missing an essential part of it, gravity.
I have tried everything from look at questions on this website to looking at online tutorials and you-tube videos.
I really need help with getting gravity into this game as I am out of ideas.
As I said I have already tried looking at multiple tutorials and videos, including this one:
http://www.somethinghitme.com/2013/01/09/creating-a-canvas-platformer-tutorial-part-one/
but this one uses shapes created in canvas rather than images.
I already know that you have to use a velocity function as well as variable for the gravity. Then you have to put this all inside the key handler function so that it can get executed.
//spaceman variables
var sx = canvasWidth / 2; // start the spaceman in the centre
var sy = canvasHeight / 2;
var sdx = 0; // set initial speed to 0
var sdy = 0;
var sspeed = 3; // create a variable for speed
var gravity = 0.2;
var svX = 0;
var svY = (Math.random() * -10) - 5;
//set variables to use for key presses
//these are Boolean variables
//they can only be true or false
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
spaceman2Ready = true;
spacemanReady = false;
leftPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
sdx--;
} else if (e.keyCode == 37) {
spaceman2Ready = false;
spacemanReady = true;
leftPressed = false;
sdx--;
} else if (e.keyCode == 38) {
upPressed = false;
sdx--;
} else if (e.keyCode == 40) {
downPressed = false;
sdx--;
}
}
// add something to "listen" for an event
//an event is keypress, mouse movement, mouse click etc.
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (rightPressed == true) {
sdx = sspeed;
} else if (leftPressed == true) {
sdx = -sspeed;
} else if (upPressed == true) {
sdy = -sspeed;
} else if (downPressed == true) {
sdy = sspeed
}
if (rightPressed == false && leftPressed == false && upPressed == false && downPressed == false) {
sdx = 0;
sdy = 0;
}
sx = sx + sdx;
sy = sy + sdy;
}
if (spacemanReady) {
ctx.drawImage(spacemanImage, sx, sy);
if (spaceman2Ready) {
ctx.drawImage(spaceman2Image, sx, sy);
}
// basically the setTimeout part, but this time its requesting the function that we made at the top
requestAnimationFrame(draw);
}
// this is to get the loop for the animation to start going
window.addEventListener("load",
function() {
draw();
});
< /script>
</body >
</html>/

You should be using gravity to update your position every frame (in the draw function). This would look like:
if(sy > 0){
sdy += gravity
}
I have created a codepen with your game with gravity. I hope this helps!

Related

trigger key after x seconds (key is constantly pressed)

The code works in the following way:
- holding shoot/drop button generate bullet and the bomb that is drawn/shown in canvas,
- it executes all the time in the function draw that refreshes around 60times per second.
Instead I want to set sth as:
- setInterval(shoot, 1000);
- setInterval(drop, 2000);
so it should be like:
- when user presses the key, it creates the bullet/bomb with the interval of 1/2 seconds
- it should all happen without realising the key
Below I provide the sample code:
let left = false;
let up = false;
let right = false;
let down = false;
let shoot = false;
let drop = false;
document.onkeydown = function (e) {
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 39) right = true;
if (e.keyCode == 40) down = true;
if (e.keyCode == 17) shoot = true;
if (e.keyCode == 32) drop = true;
e.preventDefault();
}
document.onkeyup = function (e) {
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 39) right = false;
if (e.keyCode == 40) down = false;
if (e.keyCode == 17) shoot = false;
if (e.keyCode == 32) drop = false;
e.preventDefault();
}
function draw() {
requestAnimationFrame(draw);
if (shoot) {
bullet = new Bullet(player.x - 3, player.y - 3, 6, 10)
bullets.push(bullet);
}
for (i = 0; i < bullets.length; i++) {
bullets[i].show();
bullets[i].move();
}
if (drop) {
bomb = new Bomb(player.x - 8, player.y + 50, 16, 1)
bombs.push(bomb);
}
for (i = 0; i < bombs.length; i++) {
bombs[i].show();
bombs[i].move();
}
}
requestAnimationFrame(draw);
Full code on remote server:
https://stacho163.000webhostapp.com
Is that a way to do it in my code or i have to change the way the buttons work?
If there is a solution without jQuery, that would be great.
e: checked the first tip, but after creating the first single bullet/bomb it's working as it was before.
Thank you for your tips :)
You should set some sort of wait variable, that indicates that the key is currently pressed, and no processing needs to take place:
let dropping = false;
// indicates that the bomb is dropping right now. Do not drop a new bomb
//...
if (e.keyCode == 32) {
drop = true;
dropping = true;
setTimeout(function () { dropping = false; }, 1000);
// if 1 second has passed, reset the dropping variable, to allow another bomb to drop
}
//...
if (drop && !dropping) {
bomb = new Bomb(player.x - 8, player.y + 50, 16, 1)
bombs.push(bomb);
}
This way, your bomb will only drop once every 1 second. Rinse and repeat :)

Make variable return true only when the user holds the key down

I'm recreating the classic pong game in Javascript and I have a loop that updates the game state then redraws the whole game.
Setting the height of the game:
var leftHeight = 225;
var rightHeight = 225;
the paddle state and the key to change their state:
var keyWPressed = false;
var keySPressed = false;
var keyArrowUpPressed = false;
var keyArrowDownPressed = false;
window.addEventListener('keydown', function (evt) {
if (evt.keyCode === 87) {
keyWPressed = true;
keySPressed = false; // the player can hold down both keys at once, but
// we want the last pressed key to take precedence
} else if (evt.keyCode === 83) {
keySPressed = true;
keyWPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 38) { // up arrow
keyArrowUpPressed = true;
keyArrowDownPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 40) { // down arrow
keyArrowDownPressed = true;
keyArrowUpPressed = false; // last keypress takes precedence
} else if (evt.keyCode === 82) { // 'r'
// when a player has won, hitting 'r' resets the game
if (winner) {
restartGame();
}
}
});
updating the paddle state and looping the game:
function update(){
if (keyWPressed && leftHeight != 0){
leftHeight = leftHeight - 5;
}else if (keySPressed && leftHeight != 450){
leftHeight = leftHeight + 5;
}
if (keyArrowUpPressed && rightHeight != 0){
rightHeight = rightHeight - 5;
}else if (keyArrowDownPressed && rightHeight != 450){
rightHeight = rightHeight + 5;
}
}
function gameloop(){
update();
draw();
window.requestAnimationFrame(gameloop);
}
the problem is, whenever I press a key, for example, the W key, the paddle moves up at a single press when what I really want is for it to move only when the player is pressing and holding on to the W key.

When I run my window.onload function, I get unexpected token illegal

Please help, when I run my Window.onload()=dank(); function, I get the error message, unexpected token illegal.
<html>
<style>
</style>
<body background="background.jpg">
<canvas id="canvas" width="1300" height="630"></canvas>
<script>
var canvas=document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var H=canvas.height;
var W=canvas.width;
var x=10;
var y=15;
var rightPressed=false;
var leftPressed=false;
var upPressed=false;
var downPressed=false;
var heroX=20;
var heroY=20;
//this is where the error is
Function not working correctly
Window.onload()=dank();
function dank(){
alert("How to play: move your hero using the arrow keys, and collect colored balls for powerups and points!
Get the highest score you can without touching a monster, which makes you start over!
Collect the colored balls for more and better special powerups.");
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
This is the main game function
function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
var heroImage=new Image();
heroImage.onload=function(){
ctx.drawImage(heroImage , heroX, heroY);
}
heroImage.src="hero.jpg";
dope();
}
function keyDownHandler(e) {
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
else if(e.keyCode == 40) {
downPressed = true;
}
else if(e.keyCode == 38) {
upPressed = true;
}
}
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
else if(e.keyCode == 40) {
downPressed = false;
}
else if(e.keyCode == 38) {
upPressed = false;
}
}
function dope(){
if(rightPressed) {
heroX += 7;
}
else if(leftPressed) {
heroX -= 7;
}
else if(upPressed){
heroY -= 7
}
else if(downPressed){
heroY +=7;
}
}
setInterval(draw, 10);
</script>
</body>
</html>
Javascript strings cannot span multiple lines.
try this instead of "Window.onload()=dank();":
window.addEventListener('load',dank);
Shouldn't it be:
Window.onload=dank();
function dank(){
alert("How to play:");
}
I tried to execute the not working function but just came across an issue
On using Window.onload()=dank()
I am encountering
Window.onload is not a function
So I changed it to Window.onload=dank() and it is working. Also as pointed out in previous answer javascript cannot span multiple lines. But you can change the alert text to this
alert("How to play: move your hero using the arrow keys, and collect colored balls for powerups and points!" +
"Get the highest score you can without touching a monster, which makes you start over!" +
"Collect the colored balls for more and better special powerups.")
WORKING MODEL

keydown hold delay. Javascript

So the operating system has a delay when you hold down a key. It will execute the command once, delay, then repeat. I tried to bypass this with setting a variable to true or false based on when the key has "keydown" and "Keyup." I am not sure why it is not working though. I am not sure if I am forgetting about something, but If someone could explain why my code is still not fixing the issue.
Variables
var keyPressed = {Kleft: 37, Kright: 39, Kup: 38, Kdown: 40, Kspace: 32};
key = {K37: false, K39: false, K38: false, K40: false, K32: false};
detect for key being pressed
//to detect multiple keys being pressed
$(document).keydown(function(e) {
if(keyPressed.Kleft) //left arrow
{
console.log('test');
key.K37 = true;
airplane.performAction();
}
if(keyPressed.Kright) //right arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kup) //up arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kdown) //down arrow
{
key.K37 = true;
// airplane.performAction();
}
if(keyPressed.Kspace) //space key
{
key.K37 = true;
bullet = new Bullet({x: airplane.position.x+32, y: airplane.position.y-12}, bullets_total++); //create a new bullet
bullets.push(bullet); //store the bullet in the bullets array
}
}).keyup(function(e) {
key.K37 = false; //testing just one key for now
console.log('ehhlo');
// console.log(key['K'+toString(e)]);
// key['K'+toString(e)] = false;
});
the executed function on Keypress
function MyAirplane()
{
this.performAction = function(action)
{
if(key.K37 === true){
console.log('left');
this.position.x -= 10;
}
if(key.K37 == true){
this.position.x += 10;
}
if(key.K37 == true){
this.position.y -= 10;
}
if(key.K37 == true){
this.position.y += 10;
}
}
}
Just an idea, try not automatically calling performAction.
//to detect multiple keys being pressed
$(document).keydown(function(e) {
if(keyPressed.Kleft) //left arrow
{
key.K37 = true;
}
if(keyPressed.Kright) //right arrow
{
key.K37 = true;
}
if(keyPressed.Kup) //up arrow
{
key.K37 = true;
}
if(keyPressed.Kdown) //down arrow
{
key.K37 = true;
}
if(keyPressed.Kspace) //space key
{
key.K37 = true;
bullet = new Bullet({x: airplane.position.x+32, y: airplane.position.y-12}, bullets_total++); //create a new bullet
bullets.push(bullet); //store the bullet in the bullets array
}
}).keyup(function(e) {
key.K37 = false; //testing just one key for now
console.log('ehhlo');
// console.log(key['K'+toString(e)]);
// key['K'+toString(e)] = false;
});
And create an event timer:
function MyAirplane()
{
this.performAction = function(action)
{
if(key.K37 === true){
console.log('left');
this.position.x -= 10;
}
if(key.K37 == true){
this.position.x += 10;
}
if(key.K37 == true){
this.position.y -= 10;
}
if(key.K37 == true){
this.position.y += 10;
}
}
// 60 frames per second event checker.
var eventLoop = setInterval(this.performAction.bind(this), 1000 / 60);
}

How to move an element in javascript automatically with while loop?

I am making a Snake game so I'm trying to move my snake. It is moving with keys but it should move automatically on the screen. I tried doing that with while loops like in the code below but because of break; I have to press a key every time I want it to move. How can I make it move automatically? I tried removing break; an using an if statement but I didn't succeed.
Any other solutions or something else?
I'm new to programming so any advices would be helpful.
var main = function() {
var i = 0;
var j = 0;
$(document).keyup(function(event) {
var e = event.which;
while(i == 1) {
$('.snake').animate({left: '+=10px'}, 10);
break;
}
while(i == 2) {
$('.snake').animate({left: '-=10px'}, 10);
break;
}
while(i == 3) {
$('.snake').animate({top: '-=10px'}, 10);
break;
}
while(i == 4) {
$('.snake').animate({top: '+=10px'}, 10);
break;
}
//Which key is preesed
//D
if(e == 68) {
i = 1;
}
//A
else if(e == 65) {
i = 2;
}
//W
else if(e == 87) {
i = 3;
}
//S
else if(e == 83) {
i = 4;
}
//Any other key
else {
i = 0;
}
});
};
$(document).ready(main);
I think you just have to organize a little bit your code.
First. You must put your code inside a function. You really don't need a while. You can use a simple if.
function move(i) {
if(i == 1) {
$('.snake').animate({left: '+=10px'}, 10);
break;
}
if(i == 2) {
$('.snake').animate({left: '-=10px'}, 10);
break;
}
if(i == 3) {
$('.snake').animate({top: '-=10px'}, 10);
break;
}
if(i == 4) {
$('.snake').animate({top: '+=10px'}, 10);
break;
}
}
Now you have to change the event, using keydown instead of keyup
function main() {
var interval;
$(document).keydown(function(event) {
if(interval) clearInterval(interval); // Clear the previous interval
var e = event.which;
var i;
//Which key is pressed
//D
if(e == 68) {
i = 1;
}
//A
else if(e == 65) {
i = 2;
}
//W
else if(e == 87) {
i = 3;
}
//S
else if(e == 83) {
i = 4;
}
//Any other key
else {
i = 0;
}
interval = setInterval(function() {
move(i)
},1000); // repeat every 1 second
});
}
$(document).ready(main);

Categories

Resources