Prevent player from "flying" - javascript

I am currently trying to make an endless runner game, and I've just finished making the jumping mechanics. However, if the player were to hold the up arrow key, or press it before they touched the ground, they are able to mimic the ability to "fly". I am not sure how to prevent them from "flying" if they have not touched the ground yet. If anyone has any ideas, please let me know. My code is below:
let ctx = document.querySelector("canvas").getContext("2d");
// Screen
ctx.canvas.height = 512;
ctx.canvas.width = 512;
// Images
let bg = new Image;
bg.src = "./Background.png";
let fl = new Image;
fl.src = "./Floor.png";
// Player
let y = 256;
let speed = 2.5;
let pl = new Image;
pl.src = "./Idle.png";
pl.onload = function() {
ctx.drawImage(pl, 0, y);
};
// Jumping
let UP = false;
// Ducking
let DOWN = false;
document.onkeydown = function(e) {
if (e.keyCode == 38) UP = true;
if (e.keyCode == 40) DOWN = true;
};
document.onkeyup = function(e) {
if (e.keyCode == 38) UP = false;
if (e.keyCode == 40) DOWN = false;
};
// Frames
function update() {
// Clear
ctx.clearRect(0, 0, 512, 512);
// Background
ctx.drawImage(bg, 0, 0);
// Floor
ctx.drawImage(fl, 0, 384);
ctx.drawImage(fl, 128, 384);
ctx.drawImage(fl, 256, 384);
ctx.drawImage(fl, 384, 384);
// UP
if (UP) {
if (y > 100) {
ctx.drawImage(pl, 0, y -= speed);
} else {
UP = false;
};
} else if (!UP) {
if (y < 256) {
ctx.drawImage(pl, 0, y += speed);
} else {
ctx.drawImage(pl, 0, y);
};
};
// DOWN
if (DOWN) {
pl.src = "./Duck.png";
} else if (!DOWN) {
pl.src = "./Idle.png";
};
};
setInterval(update, 10);

Related

Pause function crashes game

So I am making an endless runner game, and I have made a function that should pause the game when the event runs, yet when I try to play the game, it crashes/doesn't load. Does anyone know why? I also tried an if function instead of a while loop, but when I pressed the P key, nothing happened. Essentially, I want it to freeze everything if the PP Boolean is set to false.
If you want to test it, I have it here: https://aakhilv.js.org/endless-runner/
Here is my code (only the relevant bits):
// Booleans
let UP = false;
let DOWN = false;
let HKD = true;
let PP = true;
// Controls
document.onkeydown = function(e) {
if (HKD && e.keyCode == 38) UP = true;
HKD = false;
if (e.keyCode == 40) DOWN = true;
};
document.onkeyup = function(e) {
if (!e.repeat && e.keyCode == 38) UP = false;
if (e.keyCode == 40) DOWN = false;
};
document.onkeypress = function(e) {
if (e.keyCode == 80 && PP) PP = false;
if (e.keyCode == 80 && !PP) PP = true;
};
// Frames
function update() {
// Clear
ctx.clearRect(0, 0, 512, 512);
// Environment
ctx.drawImage(bg, 0, 0);
ctx.drawImage(fl, 0, 384);
ctx.drawImage(fl, 128, 384);
ctx.drawImage(fl, 256, 384);
ctx.drawImage(fl, 384, 384);
ctx.drawImage(cb, 10, 10);
ctx.drawImage(c, 0.5, 0, c.width / 2, c.height / 2);
ctx.font = "40px Font";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillStyle = "#ae7640";
ctx.fillText(0, 55, 15);
// Enemies
if (mx >= -128) {
ctx.drawImage(m, mx -= speed, 256);
} else if (mx <= 0) {
mx = Math.floor(Math.random() * (1024 - 512) + 512);
};
if (bx >= -256) {
ctx.drawImage(b, bx -= speed, 215);
} else if (bx <= 0) {
bx = Math.floor(Math.random() * (1536 - 512) + 512);
};
if (cx >= -384) {
ctx.drawImage(c, cx -= speed, 280);
} else if (cx <= 0) {
cx = Math.floor(Math.random() * (4608 - 512) + 512);
};
while (Math.abs(mx - bx) < 192) {
mx = Math.floor(Math.random() * (1024 - 512) + 512);
bx = Math.floor(Math.random() * (1536 - 512) + 512);
};
// HKD
if (y == 256) {
HKD = true;
};
// UP
if (UP) {
if (y > 100) {
ctx.drawImage(pl, 0, y -= speed);
} else {
UP = false;
};
} else if (!UP) {
if (y < 256) {
ctx.drawImage(pl, 0, y += speed);
} else {
ctx.drawImage(pl, 0, y);
};
};
// DOWN
if (DOWN) {
pl.src = "./Assets/Duck.png";
} else if (!DOWN) {
pl.src = "./Assets/Idle.png";
};
};
while (PP) {
setInterval(update, 10);
};
The problem might be here -
document.onkeypress = function(e) {
if (e.keyCode == 80 && PP) PP = false;
if (e.keyCode == 80 && !PP) PP = true;
};
Initially PP = true
Now if user presses 'P'
1st if condition would be true and PP would be assigned false;
Now the 2nd condition would be checked, !PP would resolve to true, because of previous if code execution, so PP reverts back to true.
You might want to use if else above, i.e,
document.onkeypress = function(e) {
if (e.keyCode == 80 && PP) PP = false;
else if (e.keyCode == 80 && !PP) PP = true;
};
while (PP) {
setInterval(update, 10);
};
The code above infinitely calls setInterval, which will create infinitely many intervals. Instead, you want to setInterval only once, and then check within update if PP is true and skip the function body if it's false.
function update() {
if(PP){
// Clear
ctx.clearRect(0, 0, 512, 512);
// Environment
ctx.drawImage(bg, 0, 0);
// ...
}
};
setInterval(update, 10);
Other comments on the code: You should name your variables something understandable to others, and you don't need semicolons after the closing "}". Also, if is not a function.

How to stop key input from blocking the movement of an object drawn on the canvas?

So i have a simple html5 canvas render loop and I'm handling keydown and keyup.
A rectangle drawn on the screen can move left,right, up and down.
The problem is when you move left and right in succession, the rectangle seems to stop for a very long time, like it's being interrupted and I just want it to have a more smooth transition towards the opposite direction.
Even just changing any direction causes the rectangle to stop.
here's the Jsfiddle: https://jsfiddle.net/NeuroTypicalCure/sq6czebr/39/
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
key: null,
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
direction: null,
speed: 5
}
// start
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(input.key === 'w'){
player.direction = input.directions.up;
}
if(input.key === 's'){
player.direction = input.directions.down;
}
if(input.key === 'a'){
player.direction = input.directions.left;
}
if(input.key === 'd'){
player.direction = input.directions.right;
}
// keyup -> speed 0 // else -> speed 5
if(input.key === null){
player.speed = 0;
}else{
player.speed = 5;
}
player.x += Math.cos(player.direction*Math.PI)*player.speed;
player.y += Math.sin(player.direction*Math.PI)*player.speed;
ctx.fillRect(player.x,player.y,50,50);
requestAnimationFrame(draw);
}
function handleKeyDown(e){
e.preventDefault();
input.key = e.key
}
function handleKeyUp(e){
e.preventDefault();
input.key = null;
}
window.addEventListener('keydown',handleKeyDown);
window.addEventListener('keyup',handleKeyUp);
Your problem lies with the fact that you can hold multiple keys at the same time, your logic should reflect that. i.e.:
https://jsfiddle.net/danfoord1/cr84xh2n/19/
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
keys: [],
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
directions: [],
speed: 5
}
const directions = {
'w': 1.5,
's': 0.5,
'a': 1,
'd': 2
};
// start
draw();
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// keyup -> speed 0 // else -> speed 5
if (input.keys.length === 0) {
player.speed = 0;
} else {
player.speed = 5;
}
player.directions = input.keys.map(k => directions[k]);
player.directions.forEach(d => {
player.x += Math.cos(d * Math.PI) * player.speed;
player.y += Math.sin(d * Math.PI) * player.speed;
});
ctx.fillRect(player.x, player.y, 50, 50);
requestAnimationFrame(draw);
}
function handleKeyDown(e) {
e.preventDefault();
if (input.keys.indexOf(e.key) === -1) {
input.keys.push(e.key);
}
}
function handleKeyUp(e) {
e.preventDefault();
if (input.keys.indexOf(e.key) > -1) {
input.keys.splice(input.keys.indexOf(e.key), 1);
}
}
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
The problem with your code lies in your handling of keyup events:
function handleKeyUp(e){
e.preventDefault();
input.key = null;
}
You're basically reseting input.key whenever a key is released, no matter if it's a different key than the one that initiated the move. So if you press two keys and then release one, it will reset input.key (until your computer sent another keydown event - if you're still holding down the key). This can be fixed with a simple check if the keyup event belongs to the current input.key.
function handleKeyUp(e){
e.preventDefault();
if (e.key === input.key) input.key = null;
}
Here's a code snippet:
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
key: null,
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
direction: null,
speed: 5
}
// start
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(input.key === 'w'){
player.direction = input.directions.up;
}
if(input.key === 's'){
player.direction = input.directions.down;
}
if(input.key === 'a'){
player.direction = input.directions.left;
}
if(input.key === 'd'){
player.direction = input.directions.right;
}
// keyup -> speed 0 // else -> speed 5
if(input.key === null){
player.speed = 0;
}else{
player.speed = 5;
}
player.x += Math.cos(player.direction*Math.PI)*player.speed;
player.y += Math.sin(player.direction*Math.PI)*player.speed;
ctx.fillRect(player.x,player.y,50,50);
requestAnimationFrame(draw);
}
function handleKeyDown(e){
e.preventDefault();
input.key = e.key
}
function handleKeyUp(e){
e.preventDefault();
if (e.key === input.key) input.key = null;
}
window.addEventListener('keydown',handleKeyDown);
window.addEventListener('keyup',handleKeyUp);
canvas{
border: 1px solid aqua;
}
<!DOCTYPE html>
<html>
<body>
<canvas id="c"></canvas>
</body>
</html>

how to changes the background time in html canvas AI

enter image description here this is a picture of AI gaming project.
My problem is this.in this project has two times.one is daytime and night time.
this project works successfully.but I need instead of changes color of daytime and night time change a picture. I have day time and night time picture how will I insert those I tried many ways but I couldn't please help someone to do this
window.onload = init();
function init()
{
cs = document.getElementById("canvas3");
ctx = cs.getContext("2d"); // set context as 2D
ctx.rect(10,50,900,700);
ctx.fill();
// Coordinates and speed of player
var x1 = 580;
var y1 = 200;
var SPEED = 5;
// initialize visibility duration count
var count = 0;
//initialize time of day
timeofday = "Day Time";
hourcount = 0;
// initialize enemy state
EnemyCanSee = false;
enemyCOLOR = "green";
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e){
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
//create a player to control
function player(x1, y1)
{
//ctx.fillStyle = "green";
//ctx.fillRect(x1, y1, 40, 40);
var demoImage = new Image(); // make image object
demoImage.src = "player.jpg"; // set image path
ctx.drawImage(demoImage, x1, y1, 40, 40);
}
function drawObstacle()
{
var demoImage = new Image(); // make image object
demoImage.src = "wall.jpg"; // set image path
ctx.drawImage(demoImage, 500, 150, 50, 200);
}
function drawEnemy()
{
ctx.beginPath();
ctx.arc(100,230,50,0,2*Math.PI,false);
ctx.fillStyle= enemyCOLOR;
ctx.fill();
}
function drawDungeonDoor()
{
var demoImage = new Image(); // make image object
demoImage.src = "door.jpg"; // set image path
ctx.drawImage(demoImage, 300, 250, 50, 60);
}
function clear()
{
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.beginPath();
ctx.rect(0, 0, 800, 500);
ctx.closePath();
ctx.fill();
}
function drawStuff()
{
if (timeofday == "Night Time")
{
ctx.fillStyle = "black";
ctx.rect(10,50,900,700);
ctx.fill();
}
player(x1,y1);
drawObstacle();
drawDungeonDoor();
drawEnemy();
ctx.fillStyle = "red";
ctx.font = "20px Arial";
ctx.fillText(timeofday, 100, 70);
}
function checkVisibility()
{
if ((y1<150)|| (y1>350)||(x1<500))
EnemyCanSee = true;
else
EnemyCanSee = false;
}
function shootPlayer()
{
ctx.lineWidth = 5;
ctx.strokeStyle = 'yellow';
ctx.moveTo(100,230);
ctx.lineTo(x1,y1);
ctx.stroke();
var demoImage = new Image(); // make image object
demoImage.src = "explode.jpg"; // set image path
ctx.drawImage(demoImage, x1-50, y1-50, 160, 160);
}
function updateStuff()
{
if (hourcount>240) //12 hours scaled up to 1200
timeofday = "Night Time";
if (hourcount>480) //12 hours scaled up to 1200
{
timeofday = "Day Time";
hourcount = 0;
}
checkVisibility();
// control the ninja using arrow keys
if (38 in keysDown && y1>0)
{
y1 = y1-SPEED;
}
if (40 in keysDown && y1<460)
{
y1 = y1+SPEED;
}
if (37 in keysDown && x1>0)
{
x1 = x1-SPEED;
}
if (39 in keysDown && x1<600)
{
x1 = x1+SPEED;
}
if (EnemyCanSee == true && timeofday == "Day Time")
{
enemyCOLOR = "red";
count = count + 1;
}
else
{
enemyCOLOR = "green";
count = 0;
}
if (count > 60) //player was visible for few seconds
{
shootPlayer();
}
}
function GameLoop()
{ clear();
updateStuff();
drawStuff();
hourcount = hourcount+1;
setTimeout(GameLoop, 1000 / 50);
}
GameLoop();
}
if (timeofday == "Night Time")
{
ctx.fillStyle = "black";
ctx.rect(10,50,900,700);
ctx.fill();
}
there is no else condition for day time
you can also use image with condition using
var background = new Image();
background.src = "http://i.imgur.com/yf6d9SX.jpg";
background.onload = function(){
ctx.drawImage(background,0,0);
}

Move multiple elements on canvas and also clear the rect

I have a problem where i have 2 object for example and i did some moving stuff using the keyboard events. Now the problem is that i don't know when to clear the canvas so i can keep multiple instances of them and also to move them individually.
const canvas = document.getElementById('canvas-game');
const context = canvas.getContext('2d');
// Set Canvas To Whole Screen
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
// Player
class Player {
constructor(xPosition = 0, yPosition = 0, height = 25, width = 25) {
this.xPosition = xPosition;
this.yPosition = yPosition;
this.height = height;
this.width = width;
this.moveEvents = this.moveEvents.bind(this);
}
draw() {
// this.clear();
let { xPosition, yPosition, height, width} = this;
context.beginPath();
context.rect(xPosition, yPosition, height, width);
context.closePath();
context.fill();
// Bind Events
this.initEvents();
}
initEvents() {
canvas.addEventListener('keydown', this.moveEvents);
}
clear() {
context.clearRect(0, 0, canvas.height, canvas.width);
}
moveEvents(event) {
let keyPressed = event.keyCode;
if (keyPressed === 38 || keyPressed === 87) {
this.yPosition -= 5;
} else if (keyPressed === 40 || keyPressed === 83) {
this.yPosition += 5;
} else if (keyPressed === 37 || keyPressed === 65) {
this.xPosition -= 5;
} else if (keyPressed === 39 || keyPressed === 68) {
this.xPosition += 5;
}
this.draw();
}
}
// Enemy
class Enemy extends Player {
constructor() {
super();
}
}
function update(...components) {
components.forEach((item) => {
item.draw();
});
}
function init() {
let player = new Player(100, 100);
let player2 = new Player(200, 200);
update(player, player2);
}
init();
It works as it is but it leaves the trail while updating. Many thanks.
Demo Here: jsFiddle
move the clear function out of the Player class (and into the same context as update) since it shouldn't be responsible for clearing the global canvas
call clear in the update function before the draw calls of the players e.g.
function update(...components) {
clear();
components.forEach((item) => {
item.draw();
});
}
replace the draw call from the moveEvents function with the global update function as you want to redraw the whole scene again after each move (as you need to clear the whole canvas)

Remove background in canvas game

I am trying to learn JavaScript and found this tutorial:
http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/
But i can not figure out how to remove the background from the game.
Any help with removing the background would be appreciated! :)
Code that affects the background:
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "images/background.png";
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
The whole JavaScript file:
http://www.lostdecadegames.com/demos/simple_canvas_game/js/game.js
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "images/background.png";
// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
heroReady = true;
};
heroImage.src = "images/hero.png";
// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
monsterReady = true;
};
monsterImage.src = "images/monster.png";
// Game objects
var hero = {
speed: 256 // movement in pixels per second
};
var monster = {};
var monstersCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a monster
var reset = function () {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
};
// Update game objects
var update = function (modifier) {
if (38 in keysDown) { // Player holding up
hero.y -= hero.speed * modifier;
}
if (40 in keysDown) { // Player holding down
hero.y += hero.speed * modifier;
}
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed * modifier;
}
if (39 in keysDown) { // Player holding right
hero.x += hero.speed * modifier;
}
// Are they touching?
if (
hero.x <= (monster.x + 32)
&& monster.x <= (hero.x + 32)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)
) {
++monstersCaught;
reset();
}
};
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (heroReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
}
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
};
// The main game loop
var main = function () {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
render();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
// Let's play this game!
var then = Date.now();
reset();
main();
Just empty the image source:
bgImage.src='';
Then...
bgImage.onload will never execute,
bgReady will always be false,
if (bgReady){ ctx.drawImage(bgImage, 0, 0); } will never execute,
Your background will remain transparent!

Categories

Resources