I'm building a 2D js pacman with a key/door for second level. The idea is to have an ability to get to next level after grabbing the key. The grid is updated once pacman gets to the door. Game data is an array with two grids in it. What is the best way to redraw the gird?
Also can anybody suggest good resources for creating ghosts? Thank you in advance.
level change logic
let level = 0;
let grid = gameData[0]
function levelChange() {
console.log(grid[pacman.y][pacman.x] === grid[door.y][door.x])
if (grid[pacman.y][pacman.x] === grid[door.y][door.x]) {
grid = gameData[1];
level += 1;
}
console.log(level)
console.log(grid)
}
let map;
let pacman = {
x: 6,
y: 4,
direction: 'right'
};
let door = {
x: 11,
y: 8,
}
drawing grid
function drawMap() {
map = document.createElement('div');
// console.log(grid)
let tiles = createTiles(grid);
tiles.forEach(tile => {
map.appendChild(tile);
});
document.getElementById('body').appendChild(map)
// document.body.appendChild(map);
}
calling the level change
function setupKeyboardControls() {
document.addEventListener('keydown', function (e) {
// console.log(e.keyCode);
if (e.keyCode === 37) {
moveLeft();
} else if (e.keyCode === 38) {
moveUp();
} else if (e.keyCode === 39) {
moveRight();
} else if (e.keyCode === 40) {
moveDown();
}
eraseMap();
drawMap();
screenScore();
doorUnlock();
levelChange();
});
}
function main() {
drawMap();
setupKeyboardControls();
}
main();
just had to move drawMap/eraseMap to the bottom of setupKeyboardControls()
Related
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 :)
I am having a problem when I move my key controls mainly the arrows on the keyboard. If the viewpoint is small enough it also moves the screen up and down because of the vertical side bar and the tetris piece at the same time. And I want the pieces to only move when I press the arrows. I am a novice at Js and I am not sure where to start to solve the problem, suggestions to where to start to look at?
Here is my Js script
document.addEventListener("keydown", CONTROL);
function CONTROL(event) {
if (event.keyCode == 37) {
p.moveLeft();
dropStart = Date.now();
}
else if (event.keyCode == 38) {
p.rotate();
}
else if (event.keyCode == 39) {
p.moveRight();
dropStart = Date.now();
}
else if (event.keyCode == 40) {
p.moveDown(0);
}
}
Arrow keys moving the browser window is a default browser behavior.
Use event.preventDefault()
To listen only to arrow keys use if (k >= 37 && k <= 40) {, or the opposite: if (k < 37 || k > 40) return;
const p = { // JUST FOR THIS DEMO. You use Piece.prototype
moveLeft() { console.log("LEFT"); },
rotate() { console.log("ROTATE"); },
moveRight() { console.log("RIGHT"); },
moveDown() { console.log("DOWN"); },
};
document.addEventListener("keydown", CONTROL);
function CONTROL(event) {
const k = event.keyCode;
if (k < 37 || k > 40) return; // Do nothing if was not an arrow key. Else Do:
event.preventDefault(); // Prevent browser scroll on arrows
if(k == 37 || k == 39) dropStart = Date.now(); // Only for left or right
return {
37: p.moveLeft,
38: p.rotate,
39: p.moveRight,
40: p.moveDown
}[k]();
}
html, body {min-height: 100%;}
so the problem here is that is that it's sensing each key individually (I've had the same problem so you need a keymap to keep track off ALL the keys pressed like so:
var keys = [];
function keysPressed(e) {
keys[e.keyCode] = true;
}
function keysReleased(e) {
keys[e.keyCode] = false;
}
if(keys[37] === true){
//do stuff here
}
if(keys[38] === true){
//do stuff here
}
You may also want to use the proper identifier "==="
I'm making a game in which a player character moves left and right.
Since simply using an onKeyDown eventListener had my character move in a choppy fashion, and with a slight delay, I tried using requestAnimationFrame to call the movement function as often as possible, as suggested by another answer(How can I move my JS objects smoothly using keyboard input?)
however, that has changed nothing.
Here is my Javascript Code
var NodoCampo = document.getElementById("campo");
var NodoGiocatore = null;
var Left = false;
var Right = false;
var FRAMERATE = 20;
//cache giocatore
var LARG_GIOCATORE = 30;
var ALT_GIOCATORE = 30;
var X_GIOCATORE = 300;
var Y_GIOCATORE = 1100;
var VEL_GIOCATORE = 10;
function mostra_giocatore() {
if (NodoGiocatore === null) {
NodoGiocatore = document.createElement('div');
NodoGiocatore.setAttribute ('id', 'player');
NodoCampo.appendChild (NodoGiocatore);
}
NodoGiocatore.style.marginLeft = (X_GIOCATORE - LARG_GIOCATORE) + 'px';
NodoGiocatore.style.marginTop = (Y_GIOCATORE - ALT_GIOCATORE) + 'px';
}
function muovi() {
if (Left) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
else if (Right) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function stop() {
Left = false;
Right = false;
}
function interfaccia(e) {
//freccia sinstra
if (e.keyCode === 37) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
//freccia destra
else if (e.keyCode === 39) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function inizia() {
mostra_giocatore();
requestAnimationFrame(muovi);
}
window.document.onkeypress = interfaccia;
window.document.onkeyup = stop;
Your choppy movement is likely a result of the amount you are moving the player on each frame with VEL_GIOCATORE. Try reducing this amount to observe smoother movement.
The delay you are experiencing is likely due to your operating system or browsers individual settings on how key presses should repeat. You can work around this by implementing your own key tracking -- it looks like you've started to experiment with this. Track the state of your left and right keys by updating a boolean value in onkeydown and onkeyup event listeners.
var keys = {
left: false,
right: false
};
window.document.onkeydown = function (e) {
if (e.keyCode === 37) {
keys.left = true;
} else if (e.keyCode === 39) {
keys.right = true;
}
window.document.onkeyup = function (e) {
if (e.keyCode === 37) {
keys.left = false;
} else if (e.keyCode === 39) {
keys.right = false;
}
Then, in your muovi function, check the state of these variables to determine if you should update the position of the player.
I'm trying to make my sprite be able to move left or right. It can jump, but not move. I have tried different approaches, but I'm clearly missing something.
I'm using p5.js and its addon p5.play.js.
Here's my code:
p5.prototype.print = p5.prototype.println;
var asterisk;
var platform;
var GRAVITY = 1;
var JUMP = 15;
function setup() {
createCanvas(800, 600);
asterisk = createSprite(30, 200, 20, 60);
//if defined, the collider will be used for mouse events
asterisk.setCollider("circle", 0,0,33);
platform = createSprite(200, 585, 500, 20);
}
function draw() {
background(51);
asterisk.velocity.y += GRAVITY;
if(asterisk.collide(platform)) {
asterisk.velocity.y = 0;
}
if(keyWentDown("UP_ARROW") || mouseWentDown(LEFT)){
asterisk.velocity.y = -JUMP;
}
function keyReleased() {
if (key != ' '){
asterisk.setDir(0);
}
}
function keyPressed(){
if (keyCode === RIGHT_ARROW){
asterisk.setDir(1);
}else if (keyCode === LEFT_ARROW){
asterisk.setDir(-1);
}
}
drawSprites();
}
I am creating a Canvas game of 'Snake'. Using your arrow keys, you can move the snake around.
What I'm working on is clearing an interval when a different arrow key is pressed. I am trying to make use of both setInterval and clearInterval. Here is one of the four such functions I have.
https://jsfiddle.net/2q1svfod/2/
function moveUp() {
if (direction != "up") {
incrementScore();
}
direction = "up";
if (direction == "up") {
var goUp = setInterval(function() {
ctx.lineTo(headX, headY - 10);
ctx.stroke();
headY -= 10;
}, 1000);
}
else {
clearInterval(goUp);
}
}
The objective is to avoid crashing into the walls, which will result in losing the game, and your score will be reset. I'd like to prevent players from repeatedly tapping on a key to get extra points, so I only increase their score once per direction.
As long as the direction stays the same, I want the interval to keep running. That's why I declared the goUp interval inside this conditional.
If the direction has changed, I clear that interval. However, two intervals are now going on at the same time instead of 1.
Does anyone know where I'm going wrong here?
This is one implementation (out of many) you might consider.
var currentInput = {
left: false,
up: false,
right: false,
down: false
};
function getKey(keyCode) {
if (keyCode === 37) {
return 'left';
} else if (keyCode === 38) {
return 'up';
} else if (keyCode === 39) {
return 'right';
} else if (keyCode === 40) {
return 'down';
}
}
function onKeyDown(event) {
var key = getKey(event.keyCode);
currentInput[key] = true;
}
function onKeyUp(event) {
var key = getKey(event.keyCode);
currentInput[key] = false;
}
document.addEventListener('keydown', onKeyDown, false)
document.addEventListener('keyup', onKeyUp, false)
function update() {
requestAnimationFrame(update);
if (currentInput.left) {
// move snake left
} else if (currentInput.right) {
// etc.
}
}
// Kick off the event loop
requestAnimationFrame(update);
I managed to find a solution, but I'm not too thrilled I had to resort to using global variables.
It looks something like this
function moveUp() {
if (direction != "up") {
incrementScore();
}
direction = "up";
clearInterval(goRight);
upArrow();
}
function upArrow() {
if (direction == "up") {
goUp = setInterval(function() {
ctx.lineTo(headX, headY - 10);
ctx.stroke();
headY -= 10;
}, 1000);
}
}
It works and I'm able to change directions. But I don't like using globals.
Here's the updated fiddle
https://jsfiddle.net/2q1svfod/6/