Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Game movement problems (event.keyCode, setTimeout)

  1. #1
    Join Date
    Sep 2008
    Posts
    26
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default Game movement problems (event.keyCode, setTimeout)

    Hello,
    sorry if this has been discussed before, but I browsed through the forum and did not find an answer.
    I learned javascript about 8 years ago, and never really used it since then. Many things have changed, and using php and actionscript have not helped to remember much :-)

    Basicly I want to create a small game engine, either a RPG or Point&Click adventure. While I did find some premade demos and projects (such as this), the controls usualy have the typical key-down delay.

    Basicly I started a bit simpler by modifying this:
    "moving image" demo

    I tried to avoid the key-down-delay by triggering a "loop" when the key gets pressed the first time untill it gets released again.
    It works up to the point I insert if...event.keyCode. Then the key action will only be performed once.

    Code:
    <script type="text/javascript"> 
    var i=1 
    
    function goPic(){ 
    
       if(event.keyCode=="68") 
          {i++;} 
       else if(event.keyCode=="65") 
          {i--;} 
    
    document.getElementById('myimage').style.position="relative"; 
    document.getElementById('myimage').style.left=i; 
    timer=setTimeout("goPic()",10); 
    
    //test 
    //document.getElementById('myinput').value="=?="+i+"_"+Math.random(4); 
    } 
    
    function stopPic() 
    {clearTimeout(timer);} 
    
    </script> 
    </head> 
    
    <body onkeydown="goPic()" onkeyup="stopPic()" onunload="stopPic()"> 
    
    <input id="myinput"  />w=87, a=65, s=83, d=68, 
    <br /> 
    
    <img id="myimage" src="smiley.gif" width="32" height="32" />

    If I replace
    Code:
       if(event.keyCode=="68") 
          {i++;} 
       else if(event.keyCode=="65") 
          {i--;}
    with a simple
    Code:
    i++;
    it will repeat as long as the key is pressed just fine.

    Can anyone point out to me what I am doing wrong?
    (Or has a link to a sample?)

    Thank you very much!

  2. #2
    Join Date
    Feb 2008
    Location
    Cebu City Philippines
    Posts
    1,160
    Thanks
    17
    Thanked 277 Times in 275 Posts

    Default

    Hope this helps:
    Code:
    <script type="text/javascript"> 
    var i=1;
    function goPic(e){ 
    	keynum=(window.event)?e.keyCode:e.which;
       if(keynum===68) 
          i++;
       else if(keynum===65) 
          i--;
    document.getElementById('myimage').style.position="relative"; 
    document.getElementById('myimage').style.left=i+'px'; 
    // timer=setTimeout("goPic()",10); 
    
    //test 
    //document.getElementById('myinput').value="=?="+i+"_"+Math.random(4); 
    } 
    
    function stopPic() 
    {clearTimeout(timer); }
    
    </script>
    Learn how to code at 02geek

    The more you learn, the more you'll realize there's much more to learn
    Ray.ph!

  3. #3
    Join Date
    Feb 2008
    Location
    Cebu City Philippines
    Posts
    1,160
    Thanks
    17
    Thanked 277 Times in 275 Posts

    Default

    You might also find it useful to set a maxlength attribute:
    Code:
    <input id="myinput"  maxlength="1" />w=87, a=65, s=83, d=68,
    Hope that helps.
    Learn how to code at 02geek

    The more you learn, the more you'll realize there's much more to learn
    Ray.ph!

  4. #4
    Join Date
    Sep 2008
    Posts
    26
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    Hello,
    thank you for the quick reply!
    Unfortunaly nothing happens when I replace my script with the one you provided (using opera and safari as I am not on my own computer at the moment).

    As for the input's maxlength: I only use the input field for testing so it is not a problem :-)

    keynum=(window.event)?e.keyCode:e.which;

    is completely new to me, so I will read up on it and hopefully find the error/what I did wrong this time :-)

  5. #5
    Join Date
    Feb 2008
    Location
    Cebu City Philippines
    Posts
    1,160
    Thanks
    17
    Thanked 277 Times in 275 Posts

    Default

    Please accept my apology, I miss to instruct you to add an event keyword:
    Code:
    <body onkeydown="goPic(event)" onkeyup="stopPic()" onunload="stopPic()">
    Learn how to code at 02geek

    The more you learn, the more you'll realize there's much more to learn
    Ray.ph!

  6. The Following User Says Thank You to rangana For This Useful Post:

    schorhr (09-19-2008)

  7. #6
    Join Date
    Sep 2008
    Posts
    26
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    Thanks, the initial problem remains though.
    As long the key is down the picture is suppose to keep moving.
    timer=setTimeout("goPic()",10);
    does not work though as long the if...else statements are inside the function?

    Right now the picture will move one pixel and stop.

    Sorry for the confusion, I might just be missing something here.

  8. #7
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    All browsers I tested would repeat the motion without a timeout, except for Opera. Opera also was the only one that would not respond to the event at all if it was assigned in the body tag. This is tested and works in FF, IE, Opera, and Safari 3 Win:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    
    <script type="text/javascript"> 
    var i=0; 
    
    function goPic(e){
    e = e || window.event;
    var k = e.keyCode || e.which;
    
    i = k == 68? i + 1 : k == 65? i - 1 : i;
    
    document.getElementById('myimage').style.position = "relative"; 
    document.getElementById('myimage').style.left = i + 'px';
    
    if(window.opera){
    goPic.spoof = {keyCode : k};
    goPic.timer = setTimeout(function(){goPic(goPic.spoof);}, 20);
    };
    
    //test 
    //document.getElementById('myinput').value = i; 
    };
    
    function stopPic(){
    if(goPic.timer)
    clearTimeout(goPic.timer);
    };
    
    document.onkeydown = goPic;
    if(window.opera)
    document.onkeyup = stopPic;
    </script> 
    </head> 
    
    <body> 
    
    <input id="myinput">w=87, a=65, s=83, d=68, 
    <br> 
    
    <img id="myimage" src="smiley.gif" width="32" height="32" alt="pic">
    </body>
    </html>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  9. #8
    Join Date
    Sep 2008
    Posts
    26
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    Thanks for testing it!
    Strange that it performs so much differently on Opera 9.5 (mac) and Safari 1.3.2 (mac).

    Right before reading your reply I got it to work by sending the keycode when calling the function from the body tag:

    onkeydown="starttimer(event.keyCode)"

    Code:
    <html>
    <head>
    <script type="text/javascript">
    
    var i=1;
    
    function starttimer(foo)
    
    {
    	if(foo==65)
    	{i--;}
    	else if(foo==68)
    	{i++;}
    
    document.getElementById('myimage').style.position="relative";
    document.getElementById('myimage').style.left=+i;
    
           ////document.getElementById('bla').value="_"+foo+"_"+var1;
    
    bar=foo; //if I try to use starttimer(foo) it will not work?
    
    timer=setTimeout("starttimer(bar)",10);
    }
    
    function stoptimer(){clearTimeout(timer);}
    
    </script>
    </head>
    <body onkeydown="starttimer(event.keyCode)" onkeyup="stoptimer()">
    
    <img id="myimage" src="smiley.gif" width="32" height="32" />
    
    <input id="bla"/>
    
    </body>
    </html>
    This results in odd behavor when pressing another key. I suppose the function is called again then.

    I still do not understand why the function will not be called again by settimeout when I use if...event.keyCode?
    At least this Opera-Version is rather up to date.
    Safari 1.3.2 (mac) will show the same problem when I use your script: The image will move one pixel then stop.
    The script I just posted works in 1.3.2 though.

    Usualy I would update the browsers, but as this is not my computer I work with what is installed.

    Anyway, this is really confusing me. I was trying all evening yesturday to figure out why if...event.keyCode would result in moving the image into the correct direction but settimeout would not execute anymore. I must be missing something. From all other programming/scripting languages I know I would expect it to function as long as the syntax is correct (which seemed to be the case, as the image was moved by 1 pixel)


    I will now try to implement your solutions, especially skipping the use of onkey... in the body-tag.
    Thank you very much if you (or anyone) knows a tutorial/guide page where a sample movement script is explained step by step please let me know; Especially lines such as
    i = k == 68? i + 1 : k == 65? i - 1 : i;
    are still a little cryptic to me, and I want to understand what I am using ;-)

  10. #9
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Well, older Safari must not apply typematic repeat to the event. That's the issue with Opera. So, it could be determined at what version of Safari it started applying typematic repeat to the onkeydown event, and testing for that, lump it in with Opera for code branching in my approach.

    Better still would be to find a way of detecting whether or not any given browser supports typematic repeat on its onkeydown event. However, I am not aware of any way to reliably determine that, but I will look around a bit (there may actually be a property for that, or a way of figuring it out with the code).
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  11. #10
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    This seems to do the trick. I decided to just not use typematic repeat for any browser, that way they all can follow the path I originally set out for Opera. However, with them all following that path, things got both a little simpler, and a little more complex:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    
    <script type="text/javascript"> 
    
    function goPic(e){
    
    if(goPic.running) return;
    goPic.running = true;
    
    e = e || window.event;
    
    var goPic2 = function(){
    goPic.i = k == 68? goPic.i + 1 : k == 65? goPic.i - 1 : goPic.i;
    document.getElementById('myimage').style.left = goPic.i + 'px';
    goPic.timer = setTimeout(goPic2, 20);
    }, k = e.keyCode || e.which;
    
    document.getElementById('myimage').style.position = "relative"; 
    goPic2();
    
    //test
    //document.getElementById('myinput').value = goPic.i; 
    };
    
    goPic.i = 0;
    
    goPic.stopPic = function(){
    goPic.running = false;
    clearTimeout(goPic.timer);
    };
    
    document.onkeydown = goPic;
    document.onkeyup = goPic.stopPic;
    
    </script> 
    </head> 
    
    <body> 
    
    <input id="myinput">w=87, a=65, s=83, d=68, 
    <br> 
    
    <img id="myimage" src="smiley.gif" width="32" height="32" alt="pic">
    </body>
    </html>
    Notes: I also changed the code to expose only one global variable (goPic). This could also probably be done without exposing any globals, but that would make it a bit more complicated to integrate it into certain other types of code.

    Added Later:

    Code:
    i = k == 68? i + 1 : k == 65? i - 1 : i;
    is just shorthand for:

    Code:
    if(k == 68)
    i = i + 1;
    else if (k == 65)
    i = i - 1;
    else
    i = i;
    Last edited by jscheuer1; 09-19-2008 at 03:43 PM. Reason: add info
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  12. The Following User Says Thank You to jscheuer1 For This Useful Post:

    schorhr (09-19-2008)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •