8

I am working on a little HTML/JavaScript/CSS3 project for fun. I'm basically trying to make a wheel that rolls around in the browser window. To control the wheel I'm using keyup and keydown events for the cursor keys (left and right turn the wheel and up and down roll it forward or backward).

I've got it working pretty well so far, but there are two major glitches. Say I want to roll the wheel forward and without stopping I want to turn it a little to the right, then I would keep the up key pressed and press the right cursor key. When I do this there's a pause in the movement before it registers both events and keeps rolling.

That's one of the problems, the main problem is that, once I've performed the previous action and then wheel is at a desirable angle, if I let go of the right cursor key the browser registers both keys as released and the wheel comes to a stand still. Here is a jsFiddle of what it looks like: http://jsfiddle.net/UKqwu/1/. I know the code is a mess but it's a work in progress/learning experience and I've only been programming for a month or so.

Anyways thanks for any help. It only works in Chrome at the moment as far is I know. Haven't really been bothered fixing compatibility issues at this stage.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
jrl589
  • 125
  • 7
  • But in jQuery you could use the bind function I believe, but not sure how to implement that. – Shawn31313 Jul 29 '12 at 19:12
  • @Shawn31313: I don't think that will solve anything; it would merely be an unneeded wrapper here. @jrl589: Did you try `setInterval` with `move`? Since you have an object of key flags, simply running it continiously should work, although it may not be very efficient. – pimvdb Jul 29 '12 at 19:23
  • @ pimvdb setInterval? sorry if im a bit dense but today is my first attempt at using js so im not really familiar with the libraries and functions yet. – jrl589 Jul 29 '12 at 19:27
  • 3
    @jrl589: Like this: http://jsfiddle.net/UKqwu/2/. Basically you have `move` executed every 100ms to update the object according to the current keys state. The execution is independent of key presses; it's always done (so it doesn't lock when the overlapping issue occurs). – pimvdb Jul 29 '12 at 19:31
  • @ pimvdb i tried using the setTimeout () function but either it didn't work or i wasn't using it in the proper context. – jrl589 Jul 29 '12 at 19:31
  • @pimbdb: awesome thanks for the help, now i just have to figure out a way to get it running smoothly with the setInterval function. – jrl589 Jul 29 '12 at 19:34
  • You can try speeding up the setInterval. 50ms seemed to work pretty good. – Shawn31313 Jul 29 '12 at 20:08
  • Dead code: for (var key in keys) {if (key == 1) {key = 1;}} – Victor Aug 01 '12 at 09:46

3 Answers3

1

So, what is happening is essentially a limitation built in by your operating system, but there is a simple work-around. First I'll explain the limitation, and then the work-around.

If you were to (in a text box) hold down the "j" button, first one "j" would appear, and then after a short delay many "j"s would appear "jjjjjjjjjjjjjjjjjjjj"

This is the same problem your experiencing. The event fires once, waits for a moment, and then fires many more times.

The solution, however is simple. Instead of having your wheel move when the events are fired... have it update constantly, and separately keep track of what keys are up or down.

The Key Handler would look something like this...

function KeyHandler() {
  this.left = false;
  this.right= false;
  ...
  function onKeyDown(e) {
    if (e.keyCode == 37) {
      this.left = true;
    }
    ...
  }
  function onKeyUp(e) {
    if (e.keyCode == 37) {
      this.left = false;
    }
    ...
  }
}

(you'd attach the key handler to the body or whatever element you wish)

Your wheel would have an update function that looked like...

wheel.update = function() {
  // the wheel is turning left
  if (wheel.keyhandler.left) {
    // make the appropriate adjustments
  }
}

and then the game would have something like this...

wheel = new Wheel;
setInterval(function() {
  wheel.update();
},100);

That way your wheel will always be updating based on the current state of the keys, and you wont have to rely on the limitations of events that are firing. :)

zconnelly13
  • 272
  • 1
  • 4
  • 11
  • FYI: `setInterval(func, interval)` executes `func` every `interval` milliseconds. This implementation should be much smoother. – Jesse Hallett Aug 07 '12 at 01:25
0

Here's a snippet of a simple game I once wrote

//key codes
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_A = 65;
var KEY_D = 68;
var KEY_SPACE = 32;

var keys = {};

function onKeyDown(e)
{
    e = e || window.event;
    var key = window.event.keyCode || e.which; // ie

    keys[key] = true;
}

function onKeyUp(e)
{
    var key = window.event.keyCode || e.which; // ie

    delete keys[key];
}

This keeps track of all current key states. Then your game "tick" is on a setTimeout() rather than moving on key events and checks for appropriate keys.

function gameTick()
{
    // update paddle angles
if (keys[KEY_LEFT])
    {
        // move left
    }

if (keys[KEY_RIGHT])
    {
        // move right
    }
}

Here's the game;

Chad Schouggins
  • 3,440
  • 2
  • 23
  • 29
0

the problem you are facing is because your code is meant to detect single key press while your game needs 2 key press detection.

put this line in loop over size of e. that will set all pressed keys as 1. currently its detecting only one key press and processing for one at a time.

keys[e.keyCode] = 1;

check out this thread and u might get what you need. though its jquery, it might help conceptually. m also working on this with js... if anything new comes up will share...

Detect multiple keys on single keypress event in jQuery

your code and concept is cool if you are really one month old in programming.

Community
  • 1
  • 1