Don't understand addEventListener behaviour - javascript

I have wrote this code in JavaScript :
window.onload = function() {
var keyboard = new Keyboard();
var gameCanvas = document.getElementById("gameCanvas").getContext("2d");
var player = new Player(gameCanvas, keyboard);
player.Init();
setInterval(function() {
gameCanvas.clearRect(0, 0, 1200, 300);
player.Update();
}, 20);
}
class Player {
constructor(canvas, keyboard) {
this._canvas = canvas;
this._keyboard = keyboard;
this._x = 100;
this._y = 75;
this._dx = 1;
this.dy = 1;
}
Init() {
this.Draw();
}
Update() {
if (this._keyboard.GetIsArrowLeftDown())
this._x -= this._dx;
if (this._keyboard.GetIsArrowRightDown())
this._x += this._dx;
if (this._keyboard.GetIsArrowUpDown())
this._y -= this._dy;
if (this._keyboard.GetIsArrowDownDown())
this._y += this._dy;
this.Draw();
}
Draw() {
this._canvas.beginPath();
this._canvas.arc(this._x, this._y, 50, 0, 2 * Math.PI);
this._canvas.closePath();
this._canvas.strokeStyle = "black";
this._canvas.stroke();
this._canvas.beginPath();
this._canvas.arc(this._x, this._y, 50, 0, 2 * Math.PI);
this._canvas.closePath();
this._canvas.fillStyle = "red";
this._canvas.fill();
}
}
class Keyboard {
constructor() {
this.isArrowLeftDown = false;
this.isArrowRightDown = false;
this.isArrowUpDown = false;
this.isArrowDownDown = false;
window.addEventListener("keyup", keyboard.OnKeyUpEvent);
window.addEventListener("keydown", keyboard.OnKeyDownEvent);
}
OnKeyUpEvent(event) {
if (event.defaultPrevented) {
return;
}
var key = event.key || event.keyCode;
if (key == "ArrowLeft")
this.isArrowLeftDown = false;
if (key == "ArrowRight")
this.isArrowRightDown = false;
if (key == "ArrowUp")
this.isArrowUpDown = false;
if (key == "ArrowDown")
this.isArrowDownDown = false;
}
OnKeyDownEvent(event) {
if (event.defaultPrevented) {
return;
}
var key = event.key || event.keyCode;
if (key == "ArrowLeft")
this.isArrowLeftDown = true;
if (key == "ArrowRight")
this.isArrowRightDown = true;
if (key == "ArrowUp")
this.isArrowUpDown = true;
if (key == "ArrowDown")
this.isArrowDownDown = true;
}
GetIsArrowLeftDown() {
return this.isArrowLeftDown;
}
GetIsArrowRightDown() {
return this.isArrowRightDown;
}
GetIsArrowUpDown() {
return this.isArrowUpDown;
}
GetIsArrowDownDown() {
return this.isArrowDownDown;
}
}
I have a Keyboard object which remembers which keys the user pressed.
Player is an object that draw himself.
I expected that when I press left, the shape would move to the left of the screen. But it's not working as expected.
It seems my keyboard object hasn't the good property values when read by the player object.
What am I missing?

Some issues:
In the Player constructor you assign 1 to the dy property, but it is later referenced as _dy, so you should add the underscore here.
In the Keyboard constructor you use keyboard, but that is undefined; you intended this.
In those same lines you pass a reference to the OnKeyUpEvent and OnKeyDownEvent methods. But when they are called, they do not pass the current value of this, so you should bind(this) to make that happen.
Here is the corrected code:
window.onload = function() {
var keyboard = new Keyboard();
var gameCanvas = document.getElementById("gameCanvas").getContext("2d");
var player = new Player(gameCanvas, keyboard);
player.Init();
setInterval(function() {
gameCanvas.clearRect(0, 0, 1200, 300);
player.Update();
}, 20);
}
class Player {
constructor(canvas, keyboard) {
this._canvas = canvas;
this._keyboard = keyboard;
this._x = 100;
this._y = 75;
this._dx = 1;
this._dy = 1; /// add the underscore
}
Init() {
this.Draw();
}
Update() {
if (this._keyboard.GetIsArrowLeftDown())
this._x -= this._dx;
if (this._keyboard.GetIsArrowRightDown())
this._x += this._dx;
if (this._keyboard.GetIsArrowUpDown())
this._y -= this._dy;
if (this._keyboard.GetIsArrowDownDown())
this._y += this._dy;
this.Draw();
}
Draw() {
this._canvas.beginPath();
this._canvas.arc(this._x, this._y, 50, 0, 2 * Math.PI);
this._canvas.closePath();
this._canvas.strokeStyle = "black";
this._canvas.stroke();
this._canvas.beginPath();
this._canvas.arc(this._x, this._y, 50, 0, 2 * Math.PI);
this._canvas.closePath();
this._canvas.fillStyle = "red";
this._canvas.fill();
}
}
class Keyboard {
constructor() {
this.isArrowLeftDown = false;
this.isArrowRightDown = false;
this.isArrowUpDown = false;
this.isArrowDownDown = false;
window.addEventListener("keyup", this.OnKeyUpEvent.bind(this)); // use this and bind
window.addEventListener("keydown", this.OnKeyDownEvent.bind(this));
}
OnKeyUpEvent(event) {
if (event.defaultPrevented) {
return;
}
var key = event.key || event.keyCode;
if (key == "ArrowLeft")
this.isArrowLeftDown = false;
if (key == "ArrowRight")
this.isArrowRightDown = false;
if (key == "ArrowUp")
this.isArrowUpDown = false;
if (key == "ArrowDown")
this.isArrowDownDown = false;
}
OnKeyDownEvent(event) {
if (event.defaultPrevented) {
return;
}
var key = event.key || event.keyCode;
if (key == "ArrowLeft")
this.isArrowLeftDown = true;
if (key == "ArrowRight")
this.isArrowRightDown = true;
if (key == "ArrowUp")
this.isArrowUpDown = true;
if (key == "ArrowDown")
this.isArrowDownDown = true;
}
GetIsArrowLeftDown() {
return this.isArrowLeftDown;
}
GetIsArrowRightDown() {
return this.isArrowRightDown;
}
GetIsArrowUpDown() {
return this.isArrowUpDown;
}
GetIsArrowDownDown() {
return this.isArrowDownDown;
}
}
<canvas id="gameCanvas"></canvas>
NB: You can detect such errors since they are reported in the console.

Related

How to turning Javascript snake correctly?

Snake is moving and turning correctly, when it has only one part, after add another part it doesn't like a snake;
I think my problem is in forEach method of full_snake div.
How to write the coordinates of each child in full_snake during the turn so that only the first child moves and the rest follow in its footsteps.
Directions work with this code, but all children have the same coordinates in the turn functions.
How to solve this?
This's my code:
class Snake {
snake_box = document.getElementById('snakeBox');
full_snake = document.getElementById('snake');
snakeLength = [];
snake;
x = 0;
y = 0
snakeMoveLeft;
snakeLeft = false;
snakeMoveRight;
snakeRight = true;
snakeMoveUp;
snakeUp = false;
snakeMoveDown;
snakeDown = false;
constructor() {
this.snakeLength.push('',);
this._createSnake();
this._moveSnake();
}
_createSnake() {
for (let i = 0; i < this.snakeLength.length; i++) {
this.snake = document.createElement('div');
this.snake.style.width = '1rem';
this.snake.style.height = '1rem';
this.snake.style.position = 'absolute';
this.snake.style.backgroundColor = 'green';
this.snake.style.marginLeft = '.1rem';
}
this.full_snake.appendChild(this.snake);
}
_moveSnake() {
this.full_snake.style.left = this.x + 'px';
this.full_snake.style.top = this.y + 'px';
this.snakeMoveLeft = setInterval(() => {
this.x += 20;
this.full_snake.style.left = this.x + 'px';
}, 500);
}
_turnLeft() {
this.snakeLeft = true;
this.snakeRight = false;
this.snakeUp = false;
this.snakeDown = false;
clearInterval(this.snakeMoveUp);
clearInterval(this.snakeMoveDown)
this.snakeMoveLeft = setInterval(() => {
this.full_snake.childNodes.forEach(e => {
this.x -= 20;
e.style.left = this.x + 'px';
})
}, 500);
}
_turnRight() {
this.snakeRight = true;
this.snakeLeft = false;
this.snakeUp = false;
this.snakeDown = false;
clearInterval(this.snakeMoveDown)
clearInterval(this.snakeMoveUp);
this.snakeMoveRight = setInterval(() => {
this.full_snake.childNodes.forEach(e => {
this.x += 20;
e.style.left = this.x + 'px';
})
}, 500);
}
_turnUp() {
this.snakeUp = true;
this.snakeLeft = false;
this.snakeRight = false;
this.snakeDown = false;
clearInterval(this.snakeMoveRight);
clearInterval(this.snakeMoveLeft);
this.snakeMoveUp = setInterval(() => {
this.full_snake.childNodes.forEach(e => {
this.y -= 20;
e.style.top = this.y + 'px';
})
}, 500);
}
_turnDown() {
this._createSnake();
this.snakeDown = true;
this.snakeUp = false;
this.snakeLeft = false;
this.snakeRight = false;
clearInterval(this.snakeMoveLeft);
clearInterval(this.snakeMoveRight)
this.snakeMoveDown = setInterval(() => {
this.y += 20;
this.full_snake.style.top = this.y + 'px';
}, 500)
}
_move() {
document.addEventListener('keydown', e => {
if (e.key === 'ArrowUp') {
if (this.snakeLeft === true || this.snakeRight === true) {
this._turnUp();
}
}
});
document.addEventListener('keydown', e => {
if (e.key === 'ArrowDown') {
if (this.snakeLeft === true || this.snakeRight === true) {
this._turnDown();
}
}
})
document.addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') {
if (this.snakeLeft === false && this.snakeRight === false) {
this._turnLeft();
}
}
});
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight') {
if (this.snakeLeft === false && this.snakeRight === false) {
this._turnRight();
}
}
})
}
}
new Snake()._move();

JavaScript page causes computer to become unresponsive

I am completely new to JavaScript so please be patient with me
I have been following a tutorial to display images from a folder in JavaScript but when I add the script that iterates it causes the computer viewing the page to lock up completely
The following in inside my tags:
var canvas = document.getElementById("canvas");
var graphics_context = canvas.getContext("2d");
var rightPressed = false;
var leftPressed = false;
var currentpage = 0;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if ((e.key == "Right" || e.key == "ArrowRight") && !rightPressed) {
rightPressed = true;
currentpage++;
}
else if ((e.key == "Left" || e.key == "ArrowLeft") && !leftPressed) {
leftPressed = true;
currentpage--;
}
}
function keyUpHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
}
else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
function draw() {
var img = new Array();
for(let i = 0; true; i++) {
try {
var image = new Image();
image.src = "img/" + i + ".jpg";
img[i] = image;
}
catch(err) {
break;
}
}
if(currentpage <= 0)
currentpage = 0;
if(currentpage >= img.length)
currentpage = img.length - 1;
ctx.drawImage(img[currentpage], 0, 0, 800, 800);
}
setInterval(draw, 10);
I do realise that reading from a folder in a loop is incredibly inefficient but I really don't see how it would cause my entire PC to lock up (it is a separate PC to the one running the page)
Any help is appreciated!

Cocos2d Animation inside a Sprite Object

In a Cocos2d-x V 3.81 project, I am trying to animate a sprite inside an object which extends Sprite, but it does not seem to do anything. Is it even possible to have an animated sprite inside such a node, or does it have to extend Layer to have animation?
var Player = cc.Sprite.extend ({
ctor: function () {
this._super(res.Player_png);
this.UP = false;
this.DOWN = false;
this.LEFT = false;
this.RIGHT = false;
this.ACTION = false;
this.speed = 5;
cc.spriteFrameCache.addSpriteFrame(res.Player_Left_plist);
var leftFrames = [];
for(var i = 0; i < 4; i++)
{
var str = "Left" + i + ".png";
var frame = cc.spriteFrameCache.getSpriteFrame(str);
leftFrames.push(frame);
}
this.leftAnim = new cc.Animation(leftFrames, 0.3);
this.runLeft = new cc.repeatForever(new cc.Animate(this.leftAnim));
this.state = "nothing";
this.nothing = "nothing";
this.scheduleUpdate();
cc.eventManager.addListener (
cc.EventListener.create ({
event: cc.EventListener.KEYBOARD ,
onKeyPressed: function(key, event)
{
if(key == 87) this.UP = true;
else if(key == 65) this.LEFT = true;
else if(key == 83) this.DOWN = true;
else if(key == 68) this.RIGHT = true;
else if (key == 69 || key == 32) this.ACTION = true;
}.bind(this),
onKeyReleased: function(key, event)
{
if(key == 87) this.UP = false;
else if(key == 65) this.LEFT = false;
else if(key == 83) this.DOWN = false;
else if(key == 68) this.RIGHT = false;
else if (key == 69 || key == 32) this.ACTION = false;
}.bind(this)
}),this);
return true;
},
update:function(dt) {
if(this.UP)
{
this.y += this.speed;
this.runAction(this.runLeft);
}
else if(this.DOWN)
{
this.y -= this.speed;
}
if(this.LEFT)
{
this.x -= this.speed;
this.runAction(this.runLeft);
}
else if(this.RIGHT)
{
this.x += this.speed;
}
}
});
I think the problem is this line:
cc.spriteFrameCache.addSpriteFrame(res.Player_Left_plist);
It should read
cc.spriteFrameCache.addSpriteFrames(res.Player_Left_plist);
where SpriteFrames is plural. The method without an 's' on the end is used to load a single cc.SpriteFrame object into the cache, after you've created that SpriteFrame manually. the method WITH an 's' on the end is the one that takes a URL for a plist to load a whole spritesheet at once.
http://www.cocos2d-x.org/reference/html5-js/V3.8/symbols/cc.spriteFrameCache.html
This code works for you outside the sprite class? For example in a regular sprite?
I think this is wrong but I have not tested it:
this.leftAnim = new cc.Animation(leftFrames, 0.3);
this.runLeft = new cc.repeatForever(new cc.Animate(this.leftAnim));
With your code what I'd do:
var leftAnim = new cc.Animation();
for(var i = 0; i < 4; i++)
{
var str = "Left" + i + ".png";
var frame = cc.spriteFrameCache.getSpriteFrame(str);
leftAnim.addSpriteFrame(frame);
}
leftAnim.setDelayPerUnit(0.08);
this.runAction(cc.animate(leftAnim)); //or this.runAction(cc.animate(leftAnim).repeatForever());
Hope it helps
The pluralization was largely the problem.
For those curious, here is the block of functional code:
You are correct. Thank you very much. For those interested, this is the block of functional code:
cc.spriteFrameCache.addSpriteFrames(res.playerRun_plist);
var i,f;
var frames=[];
for (i=1; i <= 4; i++) {
f=cc.spriteFrameCache.getSpriteFrame("playerRun"+i+".png");
frames.push(f);
}
var playerRunAnim = new cc.Animation(frames, 0.1);
this.playerAction = new cc.RepeatForever(new cc.Animate(playerRunAnim));
this.runAction(this.playerAction);

Paper.JS - Can´t resize rectangle after it reaches minimum size

I´ve created a small script based on HitTest example from paperjs.org. The idea is to have a Rectangle and be able to move and resize it. It is almost working but, when I resize it to the minimum size I´ve specified (10x10), for some reason, I´m not able to resize it anymore, even if I release drag event and try again.
var hitOptions = {
segments: true,
stroke: true,
fill: true,
tolerance: 1
};
project.currentStyle = {
fillColor: 'green',
strokeColor: 'black'
};
var rect_a = new Path.Rectangle(new Point(50, 50), 50);
var segment, path, hitType;
var clickPos = null;
var movePath = false;
var minHeight = 10;
var minWidth = 10;
function onMouseDown(event) {
segment = path = null;
var hitResult = project.hitTest(event.point, hitOptions);
if (!hitResult)
return;
hitType = hitResult.type;
if (event.modifiers.shift) {
if (hitResult.type == 'segment') {
hitResult.segment.remove();
};
return;
}
if (hitResult) {
path = hitResult.item;
if (hitResult.type == 'segment') {
segment = hitResult.segment;
}
}
movePath = hitResult.type == 'fill';
if (movePath) {
project.activeLayer.addChild(hitResult.item);
}
clickPos = checkHitPosition(event);
}
function onMouseMove(event) {
changeCursor(event);
project.activeLayer.selected = false;
if (event.item)
event.item.selected = true;
}
function onMouseDrag(event) {
if (hitType == "stroke" || hitType == "segment") {
resizeRectangle(path, event);
} else {
path.position += event.delta;
}
}
function resizeRectangle(path, event) {
switch(clickPos) {
case "SE" :
resizeBottom(path, event);
resizeRight(path, event);
break;
case "NE" :
resizeTop(path, event);
resizeRight(path, event);
break;
case "SW" :
resizeBottom(path, event);
resizeLeft(path, event);
break;
case "NW" :
resizeTop(path, event);
resizeLeft(path, event);
break;
case "S" :
resizeBottom(path, event);
break;
case "N" :
resizeTop(path, event);
break;
case "E" :
resizeRight(path, event);
break;
case "W" :
resizeLeft(path, event);
break;
}
}
function resizeTop(path, event) {
if(path.bounds.height >= minHeight) {
path.bounds.top += event.delta.y;
}
}
function resizeBottom(path, event) {
if(path.bounds.height >= minHeight) {
path.bounds.bottom += event.delta.y;
}
}
function resizeLeft(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.left += event.delta.x;
}
}
function resizeRight(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.right += event.delta.x;
}
}
function checkHitPosition(event) {
var hitResult = project.hitTest(event.point, hitOptions);
var clickPosition = null;
if (hitResult) {
if (hitResult.type == 'stroke' || hitResult.type == 'segment') {
var bounds = hitResult.item.bounds;
var point = hitResult.point;
if (bounds.top == point.y) {
clickPosition = "N";
}
if (bounds.bottom == point.y) {
clickPosition = "S";
}
if (bounds.left == point.x) {
clickPosition = "W";
}
if (bounds.right == point.x) {
clickPosition = "E";
}
if (bounds.top == point.y && bounds.left == point.x) {
clickPosition = "NW";
}
if (bounds.top == point.y && bounds.right == point.x) {
clickPosition = "NE";
}
if (bounds.bottom == point.y && bounds.left == point.x) {
clickPosition = "SW";
}
if (bounds.bottom == point.y && bounds.right == point.x) {
clickPosition = "SE";
}
} else {
clickPosition = "C";
}
}
return clickPosition;
};
function changeCursor(event) {
var hitPosition = checkHitPosition(event);
if(hitPosition == null ) {
document.body.style.cursor = "auto";
} else {
if (hitPosition == "C") {
document.body.style.cursor = "all-scroll";
} else {
document.body.style.cursor = hitPosition + "-resize";
}
}
}
The problem is that the code shrinks the rectangle below the minimum sizes (minWidth and minHeight). You can add a line
console.log(path.bounds.width, path.bounds.height)
at the bottom of resizeRectangle to see how the rectangle becomes smaller than minWidth and minHeight.
Then when each resizeXYZZY function is called the check if(path.bounds.height >= minHeight) (or width) fails and no change is made so the rectangle can't be made larger again.
To fix it, the resizeTop function needs to work differently:
var adj = min(event.delta.y, path.bounds.height-minHeight);
path.bounds.top += adj;
And the corresponding changes should be made for resizeBottom, Left, and Right.
This avoids setting the rectangle to be smaller than the minimum and also removes any check that prevents it from growing again.

moving an object using Keydown Events

I'm trying to move a box in the canvas, all the functions work fine, but as soon as i press down on any of the 4 keys the box disappears, I can tell it is because i have a ctx.ClearRect after pressing any of the 4 keys, i managed to stop it from dispersing, the problem is now it does not move or disappear and the cosole does not show any errors so I am stuck again.
any help would be really really helpful, thank you.
function Player (row,col) {
this.isUpKey = false;
this.isRightKey = false;
this.isDownKey = false;
this.isLeftKey = false;
this.row = row;
this.col = col;
this.color = "#f00";
}
var players = new Array();
function drawPlayer() {
players[players.length] = new Player(2,2);
for (var p = 0; p < players.length; p++) {
ctxPlayer.fillStyle = players[p].color;
ctxPlayer.fillRect(players[p].row*25, players[p].col*25, 25, 25);
}
}
function doKeyDown(e){
if (e.keyCode == 87) {
ClearPlayer();
Player.isUpKey = true;
Player.col = Player.col - 1;
}
if (e.keyCode == 83) {
ClearPlayer();
Player.isDownKey = true;
Player.col = Player.col + 1;
}
if (e.keyCode == 65) {
ClearPlayer();
Player.isLeftKey = true;
Player.row = Player.row - 1;
}
if (e.keyCode == 68) {
ClearPlayer();
Player.isRightKey = true;
Player.row = Player.row + 1;
}
}
function ClearPlayer() {
ctxPlayer.clearRect(0,0,canvasWidth,canvasHeight);
}
I created a plnkr with an example of what I think you are trying to do:
// Code goes here
function Player(row, col) {
this.isUpKey = false;
this.isRightKey = false;
this.isDownKey = false;
this.isLeftKey = false;
this.row = row;
this.col = col;
this.color = "#f00";
}
var players = [];
var ctxPlayer;
var currentPlayer;
window.onload = function()
{
ctxPlayer = document.getElementById('c').getContext('2d');
currentPlayer = players[players.length] = new Player(2, 2);
setInterval(render, 25);
}
window.onkeypress = doKeyDown;
function render()
{
ClearPlayer();
drawPlayer();
}
function drawPlayer() {
for (var p = 0; p < players.length; p++) {
ctxPlayer.fillStyle = players[p].color;
ctxPlayer.fillRect(players[p].row * 25, players[p].col * 25, 25, 25);
}
}
function doKeyDown(e) {
console.log(e);
if (e.keyCode == 97) {
currentPlayer.isUpKey = true;
--currentPlayer.row;
}
if (e.keyCode == 100) {
currentPlayer.isDownKey = true;
++currentPlayer.row;
}
if (e.keyCode == 119) {
currentPlayer.isLeftKey = true;
--currentPlayer.col;
}
if (e.keyCode == 115) {
currentPlayer.isRightKey = true;
++currentPlayer.col;
}
}
function ClearPlayer() {
ctxPlayer.clearRect(0, 0, 600, 400);
}
http://plnkr.co/edit/XejZKCkshNiihdy8ui1u?p=preview
First I introduced a render function to call clear and draw. This render function will get called every 25 ms after the window has loaded.
Then you created a new Player every draw-call. I changed it so that one player is created onload. The key-events are respective to this player-object.
Last I changed the key-events for my testing purposes, but they should work with yours too.
Keep in mind that the plnkr is just a quick example on how it works. You probably need to adjust it to your needs.

Categories