9 Replies Latest reply on Aug 20, 2013 4:45 AM by juicy_life

    Movement/Collision Detection

    rfikes4 Level 1

      I am having a hard time trying to figure this one out and was wondering if you can help me?

       

       

      I made a square on the stage and named it "player". Then on my Stage actions for document.keydown I wrote:

       

       

      if (e.which == 40) { //down

                sym.$("player").animate({top: "+=50"},0);

      }

       

       

      if (e.which == 38) { //up

                sym.$("player").animate({top: "-=50"},0);

      }

       

       

      if (e.which == 37) { //left

                sym.$("player").animate({left: "-=50"},0);

      }

       

       

      if (e.which == 39) { //right

                sym.$("player").animate({left: "+=50"},0);

      }

       

       

       

       

      This animates the square to move according to the keys pressed. But the thing is I set the duration time to 0 because I noticed that if I set it to say 1000 and pressed a key multiple times while it is still animating that .animate will stack up and play after the oldest one is finished.

       

       

      Question 1: How do I make it so that while "player" is still animating to the next position pressing a movement key will not queue up to play the next animation?

       

       

      Question 2: Is there a way to make it so that while the key is held it will move in that direction until it is released? (might involve a different library?)

       

       

      Question 3: Is there a way to detect collision so that "player" will not go through another <div>/Symbol, also setting the stage as a boundary? (this illustrates the point http://www.youtube.com/watch?v=Q_VmbMQyXj0)

        • 1. Re: Movement/Collision Detection
          juicy_life Level 1

          Questions 1 & 2: I would use a combination of keydown and keyup events and the setTimeout() function to control the keys pressed over time and the animation duration with symbol variables. For instance, I would set a symbol boolean variable to "true" during the time the animation is running to ignore new keydown events, and set it back to "false" with the setTimeout() function to "hear" key events again. I would set up another variable to "true" at the keydown event and false at the keyup event, and use it to repeat the animation if necessary. In your case, you will need to manage four "pressed key" variables, one for each key.

          1 person found this helpful
          • 2. Re: Movement/Collision Detection
            rfikes4 Level 1

            It doesn't seem to work, everytime I press the key the statement statement gets overridden (unless I did it wrong).

            • 3. Re: Movement/Collision Detection
              juicy_life Level 1

              Keep in mind most code you write won't "stop" the execution to prevent freezing the browser, so you cannot assume things flow sequentially. For instance, the setTimeout() function won't prevent a new event to occur and execute an action function. That's why you must control the action function with symbol variables.

               

              if (e.which == 40) { //down

                        if (symVariable1) {

                                  sym.$("player").animate({top: "+=50"},0);

                        }

              }

               

              If you post the full code you wrote, I'll try to figure out what's missing.

              • 4. Re: Movement/Collision Detection
                rfikes4 Level 1

                I really appreciate your help. I decided to move everything to compositionReady. Here is the right arrow statement:

                 

                var right_down = false;

                 

                $(document).keydown(function(e){

                //           if (right_down == true){

                //           sym.$("player").animate({left: "+=50"},0);  //this doesn't work here

                //      }

                                    if (e.which == 39){

                                              right_down = true;

                                              sym.$("Result").html("right_down");

                                              sym.$("player").animate({left: "+=50"},0); //works here

                                              }

                          }).keyup(function(e){

                                    if (e.which == 39){

                                              right_down = false;

                                              sym.$("Result").html("right_up");

                                              }

                          });

                 

                 

                  //if (right_down == true){

                  //sym.$("player").animate({left: "+=50"},0); //this doesn't work here

                  //}

                 

                 

                But again I only want it to animate while the key is down and keep repeating the animation after a certain amount of time (setTimeout()) and then stop the animation on keyup. Maybe a for/while loop is involved.

                • 5. Re: Movement/Collision Detection
                  YOSHIOKA Ume Level 3

                  Hi,guys.

                   

                  if you want to waiting for finish animate.

                  you can use "complete option" or "not(':animated')" selector.

                  http://api.jquery.com/animate/  http://api.jquery.com/not/

                   

                  Here is complete option sample.

                  //document.compositionReady
                  var keyCodeObj ={
                    40:{top:"+=50"},38:{top:"-=50"},37:{left: "-=50"},39:{left:"+=50"}
                  };
                  function startKeydown(){
                    $(window).on("keydown",move);
                  }
                  function move(evt){
                    if(keyCodeObj[evt.which]){
                      //turn off the keydown temporarily.
                      $(window).off("keydown",move); 
                      //turn on keydown after complete animate.
                      sym.$("player").animate(keyCodeObj[evt.which],{complete:startKeydown});
                    }
                  }
                  startKeydown();
                  

                  btw, now, value of your anim-duration is zero. It's not animation.

                  so, I think using css({top:n,left:n}) is more better than using animate().

                  combined with setInterval, like this.

                  var playerHdl = sym.$("player");
                  //obj of key flag & css
                  var kcObj = {
                    40:{isDown:false,css:{top:"-=10"}},
                    38:{isDown:false,css:{top:"+=10"}},
                    37:{isDown:false,css:{left:"+=10"}},
                    39:{isDown:false,css:{left:"-=10"}}
                  };
                  //func of "main loop"
                  function onTick(){
                    //move
                    $.each(kcObj, function(key, obj){
                      obj.isDown||playerHdl.css(obj.css)
                    });
                  }
                  //change key flag by keydown & keyup
                  $(window)
                    .keydown(function(evt){
                      if(kcObj[evt.which])kcObj[evt.which].isDown=true;
                    })
                    .keyup(function(evt){
                      if(kcObj[evt.which])kcObj[evt.which].isDown=false;
                    });
                  //run the main loop at intervals of 24 FPS.
                  var v = setInterval(onTick,1000/24);
                  

                  thanks.

                  Ume.

                  • 6. Re: Movement/Collision Detection
                    juicy_life Level 1

                    Try this code. I looks good to me.

                     

                    // insert code to be run when the composition is fully loaded here

                     

                    sym.setVariable("animate", "false");

                     

                    var down_down = false;

                    var up_down = false;

                    var right_down = false;

                    var left_down = false;

                     

                    $(document).keydown(function(e){

                              if (sym.getVariable("animate") == "false") {

                                   if (e.which == 40){

                                        down_down = true;

                                        sym.setVariable("animate", true);

                                        sym.$("Result").html("down_down");

                                        sym.$("player").animate({top: "+=50"},1000);

                                        setTimeout(function() {

                                             sym.setVariable("animate", "false");

                                             }, 1000);

                                   }

                                   if (e.which == 38){

                                        up_down = true;

                                        sym.setVariable("animate", true);

                                        sym.$("Result").html("up_down");

                                        sym.$("player").animate({top: "-=50"},1000);

                                        setTimeout(function() {

                                             sym.setVariable("animate", "false");

                                             }, 1000);

                                        }

                                   if (e.which == 39){

                                        right_down = true;

                                        sym.setVariable("animate", true);

                                        sym.$("Result").html("right_down");

                                        sym.$("player").animate({left: "+=50"},1000);

                                        setTimeout(function() {

                                             sym.setVariable("animate", "false");

                                             }, 1000);

                                        }

                                   if (e.which == 37){

                                        left_down = true;

                                        sym.setVariable("animate", true);

                                        sym.$("Result").html("left_down");

                                        sym.$("player").animate({left: "-=50"},1000);

                                        setTimeout(function() {

                                             sym.setVariable("animate", "false");

                                             }, 1000);

                                        }

                                   }

                              }).keyup(function(e){

                                   if (e.which == 40){

                                        down_down = false;

                                        sym.$("Result").html("down_up");

                                   }

                                   if (e.which == 38){

                                        up_down = false;

                                        sym.$("Result").html("up_up");

                                   }

                                   if (e.which == 39){

                                        right_down = false;

                                        sym.$("Result").html("right_up");

                                   }

                                   if (e.which == 37){

                                        left_down = false;

                                        sym.$("Result").html("left_up");

                                   }

                              });

                    • 7. Re: Movement/Collision Detection
                      juicy_life Level 1

                      In fact, you don't even need the keyup event at all. Neither the key variables.

                       

                      // insert code to be run when the composition is fully loaded here

                       

                      sym.setVariable("animate", "false");

                       

                      $(document).keydown(function(e){

                       

                              if (sym.getVariable("animate") == "false") {

                                       if (e.which == 40){

                                                    sym.setVariable("animate", true);

                                                    sym.$("Result").html("down");

                                                    sym.$("player").animate({top: "+=50"},1000);

                                                    setTimeout(function() {

                                                                        sym.setVariable("animate", "false");

                                                                        }, 1000);

                                                    }

                                        if (e.which == 38){

                                                    sym.setVariable("animate", true);

                                                    sym.$("Result").html("up");

                                                    sym.$("player").animate({top: "-=50"},1000);

                                                    setTimeout(function() {

                                                                        sym.setVariable("animate", "false");

                                                                        }, 1000);

                                                    }

                                       if (e.which == 39){

                                                    sym.setVariable("animate", true);

                                                    sym.$("Result").html("right");

                                                    sym.$("player").animate({left: "+=50"},1000);

                                                    setTimeout(function() {

                                                                        sym.setVariable("animate", "false");

                                                                        }, 1000);

                                                    }

                                       if (e.which == 37){

                                                    sym.setVariable("animate", true);

                                                    sym.$("Result").html("left");

                                                    sym.$("player").animate({left: "-=50"},1000);

                                                    setTimeout(function() {

                                                                        sym.setVariable("animate", "false");

                                                                        }, 1000);

                                                    }

                                      }

                              });

                      1 person found this helpful
                      • 8. Re: Movement/Collision Detection
                        rfikes4 Level 1

                        Wow you guys are amazing!! I will write a tutorial on how this is done (making a game with a sprite). Now all I need to do is figure out collision detection. Since I'm not sure how to implement other libraries with edge and use the code I was thinking about setting two variables X and Y and the arrow keys will increase or decrease the X or Y value. This will give a grid coordinate. So I would divide the stage into 50px square shapes and each shape will have an x,y coordinate. Then all I would have to do is set the boundaries in a variable (or perhaps an array) and check if the X,Y matches, if it does no animation will be played, if it doesn't the animation will continue.

                         

                        But my concern is how to make it so that it will not animate if the boundary variable is met, and how to store multiple elements in a variable (or just use separate variables)?

                         

                        ex:

                        sym.setVariable("X", 0);                                             //New code

                        sym.setVariable("Y", 0);                                             //New code

                        sym.setVariable("Coordinates", "X" + "Y");               //New code

                        sym.setVariable("Boundaries",                               //I don't know how to make this work

                         

                        if(e.which == 37 && Coordinates !== Boundary){         //New code

                             sym.setVariable("X", X - 50);                              //New code

                             sym.setVariable("animate", true);

                             sym.$("Result").html("left");

                             sym.$("player").animate({left: "-=50"},1000);

                             setTimeout(function() {

                                  sym.setVariable("animate", "false");

                                  }, 1000);

                             }

                        }

                        • 9. Re: Movement/Collision Detection
                          juicy_life Level 1

                          I would create a logical grid using an array (X) of arrays (Y) and storing "true" only in the allowed coordinates, everything else would be "false" by default. This will help you avoid problems when trying to move outisde your grid definition (I'm thinking in negative values outside the stage). Something like this...

                           

                          var myMap = [ [ true, false, true, true, false] ,  [ false, false, true, false, true] ,  [ true, true, false, true, false] ];

                           

                          you can access the values this way... myMap [x] [y]. In this example, myMap [1] [3] would be "false". Be careful, array indices start with 0.

                           

                          You can store myMap in a symbol variable if you want in "composotion ready".

                           

                          If you want to refine your game, I wouldn't assume a 50px by 50px grid. I would get the size of your sprite (width and height) in "composition ready" and will use those values in the formula. Also, you need to decide what the sprite's initial position in the map will be.

                           

                          Then you need you X and Y symbol variables to store your current position as you said. I would store the values using the grid's coordinate system, not the real pixels, so you can compare without transformation your X and Y with the array indices.

                           

                          It would be nice to build up the array automatically by analyzing the backgound image you will put in the stage to show the boundaries, rather than doing it manually. I'm sure there is a jquery plugin aorund to do it.

                          1 person found this helpful