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.
Related
I'm trying to figure out how to make the keyboard get disabled after the score equals five. with everything else I'm fine. I got everything else done that I need to get done I'm just having issues with the keyboard, if I could get some help on this it would greatly be appreciated. this is just giving me a hard time so I thought I would get some help.
//Arrow key codes
var UP = 38;
var DOWN = 40;
var RIGHT = 39;
var LEFT = 37;
//Directions
var moveUp = false;
var moveDown = false;
var moveRight = false;
var moveLeft = false;
//Add keyboard listeners
window.addEventListener("keydown", function(event)
{
switch(event.keyCode)
{
case UP:
moveUp = true;
break;
case DOWN:
moveDown = true;
break;
case LEFT:
moveLeft = true;
break;
case RIGHT:
moveRight = true;
break;
}
}, false);
window.addEventListener("keyup", function(event)
{
switch(event.keyCode)
{
case UP:
moveUp = false;
break;
case DOWN:
moveDown = false;
break;
case LEFT:
moveLeft = false;
break;
case RIGHT:
moveRight = false;
break;
}
}, false);
function loadHandler()
{
update();
}
function update()
{
//The animation loop
requestAnimationFrame(update, canvas);
//Up
if(moveUp && !moveDown)
{
cat.vy = -5;
}
//Down
if(moveDown && !moveUp)
{
cat.vy = 5;
}
//Left
if(moveLeft && !moveRight)
{
cat.vx = -5;
}
//Right
if(moveRight && !moveLeft)
{
cat.vx = 5;
}
//Set the cat's velocity to zero if none of the keys are being pressed
if(!moveUp && !moveDown)
{
cat.vy = 0;
}
if(!moveLeft && !moveRight)
{
cat.vx = 0;
}
//Move the cat
cat.x += cat.vx;
cat.y += cat.vy;
//Check for a collision between the cat and the monster
//and change the monster's score when they collide
if(hitTestRectangle(cat, monster) && score < 5)
{
if(!collisionHasOccured)
{
score++;
collisionHasOccured = true;
}
}
else
{
collisionHasOccured = false;
}
if(score === 5)
{
message = " - Game Over!";
}
//Render the sprites
render();
}
function hitTestRectangle(r1, r2)
{
//A variable to determine whether there's a collision
var hit = false;
//Calculate the distance vector
var vx = r1.centerX() - r2.centerX();
var vy = r1.centerY() - r2.centerY();
//Figure out the combined half-widths and half-heights
var combinedHalfWidths = r1.halfWidth() + r2.halfWidth();
var combinedHalfHeights = r1.halfHeight() + r2.halfHeight();
//Check for a collision on the x axis
if(Math.abs(vx) < combinedHalfWidths)
{
//A collision might be occuring.
//Check for a collision on the y axis
if(Math.abs(vy) < combinedHalfHeights)
{
//There's definitely a collision happening
hit = true;
}
else
{
//There's no collision on the y axis
hit = false;
}
}
else
{
//There's no collision on the x axis
hit = false;
}
return hit;
}
function render(event)
{
drawingSurface.clearRect(0, 0, canvas.width, canvas.height);
if(sprites.length !== 0)
{
for(var i = 0; i < sprites.length; i++)
{
var sprite = sprites[i];
drawingSurface.drawImage
(
image,
sprite.sourceX, sprite.sourceY,
sprite.sourceWidth, sprite.sourceHeight,
Math.floor(sprite.x), Math.floor(sprite.y),
sprite.width, sprite.height
);
}
}
drawingSurface.fillText(score + message, monster.x, monster.y - 40);
}
</script>
You just need to add an if statement to your event listeners. ( IF score == 5 ) then don't do anything. You can place the code right above the switch statements.
EDIT
#JasonEnts:
window.addEventListener("keydown", function(event)
{ if (score < 5) {
switch(event.keyCode)
{
case UP:
moveUp = true;
break;
case DOWN:
moveDown = true;
break;
case LEFT:
moveLeft = true;
break;
case RIGHT:
moveRight = true;
break;
}
}
}, false);
I was trying many solutions but none worked.
The problem is where I put the comment.
I trying to do a game which I can change a color of boxes using arrows.
var p = 0;
var d0 = document.getElementById('p1').getAttribute('value');
var d1 = document.getElementById('p2').getAttribute('value');
var arraj = [];
arraj.push(d0, d1);
function change() {
for (var i = 0; i < arraj.length; i++) {
if (arraj[i] == p) {
// and here is the problem
arraj[i].style.backgroundColor = "red";
}
}
}
document.onkeydown = check;
function check(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left
} else if (e.keyCode == '39') {
p++;
change();
// right
}
}
and HTML
<div class='g' id='p1' value="0">bla</div>
<div class='g' id='p2' value="1">bla</div>
This should fix it:
var p = 0;
var d0 = document.getElementById('p1'); // Remove 'getAttribute('value')' here
var d1 = document.getElementById('p2'); // Remove 'getAttribute('value')' here
var arraj = [];
arraj.push(d0, d1);
function change() {
for (var i = 0; i < arraj.length; i++) {
if (arraj[i].getAttribute('value') == p) { // Check for the attribute equality here
arraj[i].style.backgroundColor = "red";
}
}
}
document.onkeydown = check;
function check(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left
} else if (e.keyCode == '39') {
p++;
change();
// right
}
}
Basically the main issue that you're trying to set background color on element's value attribute and not the element itself.
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.
We are using createJS and right now I am struggling with a hit test.
I get this error:
"ss.js:203 Uncaught TypeError: Cannot read property 'x' of undefined
at hitTest (ss.js:203)
at doCollisionChecking (ss.js:215)
at heartBeat (ss.js:238)
at Function.b._dispatchEvent (createjs-2015.11.26.min.js:12)
at Function.b.dispatchEvent (createjs-2015.11.26.min.js:12)
at Function.a._tick (createjs-2015.11.26.min.js:12)
at a._handleTimeout (createjs-2015.11.26.min.js:12)"
I think the problem has to the with the 2 objects x position, but one is a player controlled character and the other object have random x value.
All the hit test example i found always consist of a static object and a moving, but this time they are both moving and i have no idea what to do.
var stage, hero, queue, circle, coin;
var coins = [];
var Score, tekst1, tekst2;
var speed = 3;
var keys = {
u: false,
d: false,
l: false,
r: false
};
var settings = {
heroSpeed: 15
};
function preload() {
"use strict";
stage = new createjs.Stage("ss");
queue = new createjs.LoadQueue(true);
queue.installPlugin(createjs.Sound);
queue.loadManifest([
{
id: 'Vacuum',
src: "img/Vacuum.png"
},
{
id: 'Dust',
src: "img/dust.png"
},
{
id: 'Pickup',
src: "sounds/pickup.mp3"
},
{
id: 'Suger',
src: "sounds/suger.wav"
},
]);
queue.addEventListener('progress', function () {
console.log("hi mom, preloading");
});
queue.addEventListener('complete', setup);
}
function setup() {
"use strict";
window.addEventListener('keyup', fingerUp);
window.addEventListener('keydown', fingerDown);
circle = new createjs.Bitmap("img/Vacuum.png");
circle.width = 40;
circle.height = 90;
stage.addChild(circle);
circle.y = 570;
circle.x = 460;
Score = new createjs.Text("0", "25px Impact", "white");
Score.x = 900;
Score.y = 680;
Score.textBaseline = "alphabetic";
stage.addChild(Score);
tekst1 = new createjs.Text("Score", "25px Impact", "white");
tekst1.x = 740;
tekst1.y = 680;
tekst1.textBaseline = "alphabetic";
stage.addChild(tekst1);
tekst2 = new createjs.Text("Bombs fallin", "40px Impact", "white");
tekst2.x = 10;
tekst2.y = 50;
tekst2.textBaseline = "alphabetic";
stage.addChild(tekst2);
createjs.Ticker.setFPS(30);
createjs.Ticker.addEventListener('tick', heartBeat)
}
function addCoins() {
coin = new createjs.Bitmap("img/dust.png");
coin.x = Math.random() * 900;
coin.width = 36;
coin.height = 50;
coins.push(coin);
stage.addChild(coin);
}
function moveCoins() {
for (var i = 0; i < coins.length; i++) {
coins[i].y += speed;
}
for (var j = 0; j < coins.length; j++) {
if (coins[j].y > 650) {
console.log("hejsa");
stage.removeChild(coins[j]);
coins.splice(j, 1);
}
}
}
function maybeAddCoin() {
var rand = Math.random() * 500;
if (rand < 5) {
addCoins();
}
}
function fingerUp(e) {
"use strict";
//createjs.Sound.stop("Suger")
switch (e.keyCode) {
case 37:
keys.l = false;
break;
case 38:
keys.u = false;
break;
case 39:
keys.r = false;
break;
case 40:
keys.d = false;
break;
}
}
function fingerDown(e) {
"use strict";
switch (e.keyCode) {
case 37:
keys.l = true;
break;
case 38:
keys.u = true;
break;
case 39:
keys.r = true;
break;
case 40:
keys.d = true;
break;
}
}
function moveSlime() {
"use strict";
if (keys.l) {
circle.x -= settings.heroSpeed;
if (circle.x < 0) {
circle.x = 0;
}
if (circle.currentDirection != "left") {
circle.currentDirection = "left";
//createjs.Sound.play("Suger");
keys.u = false;
keys.r = false;
keys.d = false;
}
}
if (keys.r) {
circle.x += settings.heroSpeed;
if (circle.x > 960) {
circle.x = 960;
}
if (circle.currentDirection != "right") {
circle.currentDirection = "right";
//createjs.Sound.play("Suger")
keys.u = false;
keys.l = false;
keys.d = false;
}
}
}
function hitTest(rect1, rect2) {
if (rect1.x >= rect2.x + rect2.width || rect1.x + rect1.width <= rect2.x ||
rect1.y >= rect2.y + rect2.height || rect1.y + rect1.height <= rect2.y)
{
return false;
}
return true;
}
function doCollisionChecking() {
for (var k = coins.length - 1; k >= 0; k--) {
if (hitTest(circle, coin[k])) {
console.log("ramt");
}
}
}
function scoreTimer() {
//Score.text = parseInt(Score.text + 10);
}
function heartBeat(e) {
"use strict";
doCollisionChecking()
maybeAddCoin()
//addCoins()
moveCoins()
scoreTimer()
moveSlime()
stage.update(e);
}
window.addEventListener('load', preload);
Clearly one of your elements is undefined (either circle or coins[k]). I would start with figuring out which one.
Open your debugger.
Turn on "Pause on Exceptions" and re-run your code. When the error happens, your debugger will pause and you can inspect your code
Determine what is undefined. This should shed some light on what is causing the error
One important thing I noticed is that you are looking for rect.width when collision checking. EaselJS elements don't have a width property, so you should instead use getBounds(), which will work with Bitmaps once they are loaded.
// Example
var bounds = rect.getBounds();
var w = bounds.width, h = bounds.height;
Hope that helps!
Here's the problem:
function doCollisionChecking() {
for (var k = coins.length - 1; k >= 0; k--) {
if (hitTest(circle,
coin[k] // your array is coins, not coin
)) {
console.log("ramt");
}
}
}
It might help you in the future to pass arguments through the function instead of relying on global objects. They help you by keeping modifications to your data on tight track. With global variables, anything can modify coins from anywhere and you won't be able to tell what function it is if you have 50+ different functions editing that variable.
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);