0

I'm having a problem with easelJS, I have a function that listens for keyboard input but it does not update the variables according to the keys i hit. I placed a console.log inside the different cases and it logs fine but for some reason it does update variables. I think I may not be understanding how it works. here is my code

            function handleKeyDown(event) {
                switch(event.keyCode) {
                    case 16:
                        sonicSpeed = 15;
                        sonicState = 2;
                        console.log("Shift Key Pressed");
                        break;
                    case 65:
                        sonicState = 1;
                        sonicDirectionXN = true;
                        break;
                    case 68:
                        sonicState = 1;
                        sonicDirectionXP = true;
                        break;
                    case 87:
                        sonicState = 1;
                        sonicDirectionYN = true;
                        break;
                    case 83:
                        sonicState = 1;
                        sonicDirectionYP = true;
                        break;
                }
            }

            if (sonicState == 0) {
                var sonic1 = new createjs.Sprite(spriteSheet1);
            }
            else if (sonicState == 1) {
                var sonic1 = new createjs.Sprite(spriteSheet2);
            }
            else if (sonicState == 2) {
                var sonic1 = new createjs.Sprite(spriteSheet3);
            }
Jeff
  • 19
  • 1
  • 1
  • 6
  • 1
    Is there a reason your `if (sonicState == 0)` condition is outside of the function? – AJ Richardson May 21 '15 at 21:45
  • yes, this is only the beginning of the code and I want to make sure it updates future movement only with the ticker, otherwise I'd place it inside the function – Jeff May 21 '15 at 21:48
  • Ok. It looks like you have some kind of scope issue, although I need to see more of your code before I can offer a proper solution. – AJ Richardson May 21 '15 at 21:51
  • that's literally the only code that matters, the rest is positioning on the canvas and declaring the sprite sheets – Jeff May 21 '15 at 21:53
  • I worked with ocanvas before this and had the same issue actually, somebody answered my question but I never fully understood what it meant, something about the keyboard listener being a future event or something, does that help at all? – Jeff May 21 '15 at 21:55
  • Of course you can use the sonicState variable in the ticker or somewhere else to create your Sprite objects, just keep in mind the asynchronous nature. I found a fiddle where someone made a similar game you're trying to do, maybe this will help: http://jsfiddle.net/jamestyner/8qE5d/embedded/result,js,html,css/ (also, did you use document.onkeydown = handleKeyDown ?). Good luck! – Georgios Dimitriadis May 22 '15 at 05:29
  • thank you very much, and yes I did use document.onkeydown = handleKeyDown – Jeff May 22 '15 at 12:32

2 Answers2

1

I don't see your entire code, but by the looks of it, you're having problem with the javascript asynchronous nature. Your handleKeyDown logic doesn't have time to complete before you run your if statements, hence you don't get the correct results. Try to create your Sprite objects directly within the handleKeyDown listener instead to make it synchronous;

function handleKeyDown(event) {
    switch(event.keyCode) {
        case 16:
            sonicSpeed = 15;
            sonic1 = new createjs.Sprite(spriteSheet3);
            break;
        case 65:
            sonic1 = new createjs.Sprite(spriteSheet2);
            sonicDirectionXN = true;
            break;
        case 68:
            sonic1 = new createjs.Sprite(spriteSheet2);
            sonicDirectionXP = true;
            break;
        case 87:
            sonic1 = new createjs.Sprite(spriteSheet2);
            sonicDirectionYN = true;
            break;
        case 83:
            sonic1 = new createjs.Sprite(spriteSheet2);
            sonicDirectionYP = true;
            break;
        default: // This is my quess for your sonicstate === 0
            sonic1 = new createjs.Sprite(spriteSheet1);
    }
}
  • is there no other way around this? because I'm planning on adding movement code into the if statements and if I do that it'll update every time keyDown is activated instead of every time the ticker ticks – Jeff May 21 '15 at 21:59
  • just tried this, it isn't working either. It still logs the key being pressed though when I place a console.log in it – Jeff May 21 '15 at 22:13
1

Why it's not working

The problem is that the code is not executing in the order you think it is. As Felix Kling pointed out in your other question, the code inside your handleKeyDown function does not execute immediately; it executes when a key is pressed. Here is the actual order of execution (assuming no optimizations by the browser):

  1. handleKeyDown function is created (but NOT executed).
  2. sonic1 sprite is created based on the value of sonicState (which is ALWAYS 0 at this point because handleKeyDown has not run).
  3. User presses a key.
  4. handleKeyDown executes and changes the sonicState. Nothing else happens because the function ends after the switch statement. Execution stops at the end of the function.

One way to fix it

It looks like you are trying to change the animation sequence based on the key that was pressed. You should be able to accomplish this with a single SpriteSheet; somthing like this:

var sonicSpriteSheet = new SpriteSheet({
    images: [myImage],             // You can also use multiple images.
    frames: {width:50, height:50}, // Substitue 50 with your actual frame size.
    animations: {
        sonicState0: [0, 9],       // These are the start and end frame numbers.
        sonicState1: [10, 19],     // Substitute with the actual frame numbers
        sonicState2: [20, 29]      // for your images.
    }
});

Then you can use gotoAndPlay to set which animation is playing. This allows you to re-use the same sprite instead of creating a new sprite every time.

var sonic1 = new createjs.Sprite(sonicSpriteSheet);

function handleKeyDown(event) {
    var sonicState = sonic1.currentAnimation;
    switch(event.keyCode) {
        case 16:
            sonicSpeed = 15;
            sonicState = "sonicState2";
            console.log("Shift Key Pressed");
            break;
        case 65:
            sonicState = "sonicState1";
            sonicDirectionXN = true;
            break;
        case 68:
            sonicState = "sonicState1";
            sonicDirectionXP = true;
            break;
        case 87:
            sonicState = "sonicState1";
            sonicDirectionYN = true;
            break;
        case 83:
            sonicState = "sonicState1";
            sonicDirectionYP = true;
            break;
    }
    if (sonicState != sonic1.currentAnimation) {
        sonic1.gotoAndPlay(sonicState);
    }
}

Since gotoAndPlay is inside the handleKeyDown function, it will execute after you change the sonicState.

Edit - Another way to fix it

If you want to use separate sprites for each animation, then you need to remove the old sprite and add a new one when you change animations.

var sonic0 = new createjs.Sprite(spriteSheet0);
var sonic1 = new createjs.Sprite(spriteSheet1);
var sonic2 = new createjs.Sprite(spriteSheet2);
var sonicState = 0;
stage.addChild(sonic0);

function handleKeyDown(event) {
    var newSonicState = sonicState;
    switch(event.keyCode) {
        case 16:
            sonicSpeed = 15;
            newSonicState = 2;
            break;
        case 65:
            newSonicState = 1;
            sonicDirectionXN = true;
            break;
        case 68:
            newSonicState = 1;
            sonicDirectionXP = true;
            break;
        case 87:
            newSonicState = 1;
            sonicDirectionYN = true;
            break;
        case 83:
            newSonicState = 1;
            sonicDirectionYP = true;
            break;
    }

    if (newSonicState != sonicState) {
        // Remove the old sprite
        stage.removeChild(sonic0, sonic1, sonic2);

        // Add the new sprite
        switch (newSonicState) {
            case 0:
                stage.addChild(sonic0);
                break;
            case 1:
                stage.addChild(sonic1);
                break;
            case 2:
                stage.addChild(sonic2);
                break;
        }
    }
}
Community
  • 1
  • 1
AJ Richardson
  • 6,610
  • 1
  • 49
  • 59
  • your solution is the closest I've gotten to getting this working, but I still have a few problems. 1 - I want the ticker to be the main thing controlling my animations and 2 - I can't control the framerate of the different animations with your method . . . or can I? – Jeff May 22 '15 at 12:29
  • You can specify a relative speed for each animation sequence if you want - see the [SpriteSheet documentation](http://createjs.com/Docs/EaselJS/classes/SpriteSheet.html). I'm not sure what you mean by controlling your animations with the ticker - if you are using sprites, they will be controlled by themselves. – AJ Richardson May 23 '15 at 02:13