Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Clunky Sprite Movement  (Read 1634 times)
0 Members and 1 Guest are viewing this topic.
Offline Z-Man
« Posted 2011-01-30 16:41:47 »

Hi all, I am brand new to programming games in Java and this is my very first attempt. This game that I am currently working on follows a really nice tutorial that I found to help get me started. I have however taken what is in the tutorial and expanded on it somewhat. The problem I am having is that the movement of my craft sprite is very clunky and I am not sure how to fix it. I am also not sure that my method of continuous fire is a very good idea. My method of movement is a combination of checking for a key press and a boolean to try and eliminate the clunkyness but it doesn't work very well. My method of firing is to create a new Thread that fires every few seconds depending on what FIRE_SPEED is set to, until canFire is false. canFire is true while the space bar is held down and, false when the space bar is released.

Craft Movement:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
   public void move()
   {
      x += dx;
      y += dy;
   }

   public void keyPressed(KeyEvent e)
   {

      int key = e.getKeyCode();
      long currTime = System.currentTimeMillis();

      if(key == KeyEvent.VK_SPACE && !canFire)
      {
         canFire = true;
         new Fire().start();
      }

      if(key == KeyEvent.VK_LEFT || moveLeft)
      {
         moveLeft = true;
         dx = -1;
      }

      if(key == KeyEvent.VK_RIGHT || moveRight)
      {
         moveRight = true;
         dx = 1;
      }

      if(key == KeyEvent.VK_UP ||  moveUp)
      {
         moveUp = true;
         dy = -1;
      }

      if(key == KeyEvent.VK_DOWN || moveDown)
      {
         moveDown = true;
         dy = 1;
      }
   }

   public void keyReleased(KeyEvent e)
   {
      int key = e.getKeyCode();

      if(key == KeyEvent.VK_SPACE)
      {
         canFire = false;
      }

      if(key == KeyEvent.VK_LEFT)
      {
         moveLeft = false;
         dx = 0;
      }

      if(key == KeyEvent.VK_RIGHT)
      {
         moveRight = false;
         dx = 0;
      }

      if(key == KeyEvent.VK_UP)
      {
         moveUp = false;
         dy = 0;
      }

      if(key == KeyEvent.VK_DOWN)
      {
         moveDown = false;
         dy = 0;
      }
   }


Firing:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
   public void fire()
   {
      missiles.add(new Missile(x + CRAFT_SIZE,y + CRAFT_SIZE / 2));
   }

      if(key == KeyEvent.VK_SPACE && !canFire)
      {
         canFire = true;
         new Fire().start();
      }

   class Fire extends Thread
   {
      @Override
      public void run()
      {
         while(canFire)
         {
            long curr = System.currentTimeMillis();
            while(curr - lastShot < FIRE_SPEED)
               curr = System.currentTimeMillis();
            fire();
            lastShot = System.currentTimeMillis();
         }
      }
   }
Offline ReBirth
« Reply #1 - Posted 2011-01-31 02:23:45 »

call your move() every tiem a key pressed. I think there is no need for boolean variabel.
1  
2  
3  
4  
5  
if(key == KeyEvent.VK_LEFT)
   {
      dx = -1;
      move();
   }

now the firing. how do you update the display (when call repaint() method)? if you use run() by Runnable or actionPerformed() by Timer then no need to create a thread for firing. When spacebar is pressed, set boolean to true and call fire() that add bullet object to a list, repaint. if boolean still true add again. To set interval between bullet launched, add boolean variabel that allow a bullet to be fired.
1  
2  
3  
 boolean a;
int delta; //space between bullets
a = lastBullet.Y > (craft.y + delta);

Offline dishmoth
« Reply #2 - Posted 2011-02-01 09:54:27 »

My method of movement is a combination of checking for a key press and a boolean to try and eliminate the clunkyness but it doesn't work very well. My method of firing is to create a new Thread
Most games use a 'game loop' that advances the game entities and redraws them many times per second ('active rendering').  I'm assuming that that's how your game is set up.  If your game loop runs at a fixed frame rate (e.g., 30 updates per second, or as near to that as possible) then the coding is generally easier.

The keyPressed()/keyReleased() functions should only be used to record the current state of the keyboard (e.g., as booleans leftKeyPressed, fireKeyPressed, etc.).  You shouldn't modify the game entities (positions, bullets, etc.) from within those functions.  They run in a different thread to the rest of the game loop, and your game entities will behave strangely if the threads aren't synchronized.  Instead, each game entity gets a turn to move during the 'advance' stage of the game loop, and you can use the values of leftKeyPressed, etc. then.

Don't create extra threads for timing things like firing.  It's easier and more reliable to add a simple counter to one of the game entities.  In this case, the ship could have a variable timeUntilNextBullet that decreases every time the ship is updated to reflect the time that has passed since the last update. (You can measure time in seconds or milli-seconds, or if your game uses a fixed frame rate you can just count the number of frames.)  When the counter is zero (or less than zero) the ship can fire a new bullet, and reset the counter to the delay until the next bullet.

Hope that helps...
Simon

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Gingerious

Junior Duke


Medals: 2



« Reply #3 - Posted 2011-09-28 19:38:01 »

I was going to start a new topic for this, but this seems like a good place to put this issue even though it's an old topic, so bumping for great justice.

I'm having an issue that I can't quite pin down, and it's keeping my player from being able to move along the x and y axis at the same time while firing.  Basically, it's like this: if the up arrow key is pressed and the left arrow key is pressed, then the space key being pressed doesn't register.  If the space and left arrow keys are pressed, then the up arrow key doesn't register.  If the space and up arrow keys are pressed, then the left arrow key doesn't register.

I can press any combination of up/right/space, down/right/space, or down/left/space.  It only seems to be the combination of up/left/space that's causing problems.

Here's my key events:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
public void keyReleased(KeyEvent k) {
      int keyCode = k.getKeyCode();
        switch (keyCode) {
         case KeyEvent.VK_LEFT:
            keyLeftPressed = false;
            break;
         case KeyEvent.VK_RIGHT:
            keyRightPressed = false;
            break;
         case KeyEvent.VK_UP:
            keyUpPressed = false;
            break;
         case KeyEvent.VK_DOWN:
            keyDownPressed = false;
            break;
         case KeyEvent.VK_SPACE:
            keySpacePressed = false;
         break;
      }
   }
    public void keyTyped(KeyEvent k) {keyPressed(k);}
    public void keyPressed(KeyEvent k) {
      int keyCode = k.getKeyCode();
        switch (keyCode) {
         case KeyEvent.VK_LEFT:
            keyLeftPressed = true;
            break;
         case KeyEvent.VK_RIGHT:
            keyRightPressed = true;
            break;
         case KeyEvent.VK_UP:
            keyUpPressed = true;
            break;
         case KeyEvent.VK_DOWN:
            keyDownPressed = true;
            break;
         case KeyEvent.VK_SPACE:
               keySpacePressed = true;
            break;
         case KeyEvent.VK_ENTER:
            showBoundingBox = !showBoundingBox;
            break;
      }
   }


Here's the method that handles movement by changing player velocity:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
public void handleMovement(){
     
      if(keyUpPressed && keyDownPressed){
         player.setVelocity(new Point((int)player.velocity().getX(), 0));
      }else if(keyUpPressed && player.position().getY() > 31){
         player.setVelocity(new Point((int)player.velocity().getX(), -3));
      }else if(keyDownPressed && player.position().getY() < 430){
         player.setVelocity(new Point((int)player.velocity().getX(), 3));
      } else {
         player.setVelocity(new Point((int)player.velocity().getX(), 0));
      }
     
      if(keyLeftPressed && keyRightPressed){
         player.setVelocity(new Point(0, (int)player.velocity().getY()));
      }else if(keyLeftPressed && player.position().getX() > 9){
         player.setVelocity(new Point(-3,(int)player.velocity().getY()));
      }else if(keyRightPressed && player.position().getX() < 609){
         player.setVelocity(new Point(3, (int)player.velocity().getY()));
      } else {
         player.setVelocity(new Point(0, (int)player.velocity().getY()));
      }  
   }
 

Let me know if any additional information is needed.

Also, as a side note, is there any way to keep code from displaying in impossibly small font?  Thanks!
Offline aazimon
« Reply #4 - Posted 2011-09-28 20:20:33 »

I don't see anything in the code you posted. Have you tried logging the key events?

If you mean the small print on Java-gaming.org, its Internet Explorer. Try using a different browser like Firefox.
Offline Z-Man
« Reply #5 - Posted 2011-09-28 20:33:48 »

Lol I don't know why I never replied to Rebirth and dishmoth on the original post... sorry about that.

@Gingerious
1  
 public void keyTyped(KeyEvent k) {keyPressed(k);}

This is the only line that jumps out at me and I'm not entirely sure that it's the culprit. I don't think this line is particularly useful though since "KEY_TYPED is only generated if a valid Unicode character could be generated." and your keyPressed() and keyReleased() methods are already handling everything.

its Internet Explorer. Try using a different browser like Firefox.
You should also just not use IE... cause it's terrible Tongue
Offline Gingerious

Junior Duke


Medals: 2



« Reply #6 - Posted 2011-09-28 21:12:27 »

I agree, IE is terrible.  But I was at work when I posted this and I can't use any other browser. Sad

I've commented out the contents of the keytyped event (not sure why it's even there in the first place, actually) and that didn't change the behavior. Aazimon, I did put this line in the handleMovement function:

1  
if(keySpacePressed && keyUpPressed && keyLeftPressed){System.out.println("up/left/space pressed");}


And it very seldom fired off.  I had to hold space and spam button presses on up and left to get anything to print out.  If I hold the buttons, "up/left/space pressed" never prints out.
Offline philfrei
« Reply #7 - Posted 2011-09-29 00:26:53 »

I use the "Change Zoom Level" (bottom right corner) on IE.

[EDIT: Ah, the strangenesses of how keyboards are implemented! The two posts following this one are correct.]

I'm wondering where you call your "fire" command, and if it interacts with how you call your "movement" command. There are no tests of the keySpacePressed boolean in any of the sample code you displayed.

For testing purposes, do follow aazimon's advice and log events or post state. You can have a System.out.println("pressed:" + keyCode); and another for "released" prior to the switch statements. You could also have a state dump at the start of the movement section.

But one last note, the code seems kind of overdone. You are making two new Points for every movement change? Why not something like the following:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
    int newXvel = 0;
    int newYvel = 0;
    int currentX = player.position.getX();
    int currentY = player.position.getY();
    if (keyLeftPressed && currentX > 9) newXvel -= 3;
    if (keyRightPressed && currentX < 609) newXvel += 3;
    if (keyUpPressed && currentY > 31) newYvel -= 3;
    if (keyDownPressed && currentY < 430) newYvel += 3;

    player.setVelocity(new Point(newXvel, newYvel));


NOT that this should affect the original question, if the error is occurring in how these routines are called.

"It's after the end of the world! Don't you know that yet?"
Offline gbeebe
« Reply #8 - Posted 2011-09-29 02:19:12 »

@Gingerious, you can't hold up, left, and space in any game.... go ahead, try it.     Try using W A S D instead.
Offline dishmoth
« Reply #9 - Posted 2011-09-29 06:30:07 »

you can't hold up, left, and space in any game.... go ahead, try it.     Try using W A S D instead.

It's a well-known limitation of keyboard hardware.  Some keyboards will let you get away with it, some won't.  It's not a problem with Java, and I couldn't see anything wrong with your code.

Last time this issue came up, someone posted a link that explained how keyboards work.  I'm too lazy to go looking for that post, but you could do a bit of searching if you're interested.

Anecdotal evidence suggests that the Cursor keys and (as gbeebe says) the WASD keys are most likely to be unaffected, and also 'special' keys like Ctrl, Shift and Space.

Simon

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Gingerious

Junior Duke


Medals: 2



« Reply #10 - Posted 2011-09-29 16:53:54 »

Oh wow.  I changed the movement buttons to WASD and that fixed the problem.  I didn't know keyboards carried such a random limitation.  Thanks guys!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (45 views)
2014-10-16 15:22:06

Norakomi (34 views)
2014-10-16 15:20:20

lcass (38 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (68 views)
2014-10-14 00:35:47

TehJavaDev (60 views)
2014-10-14 00:32:37

BurntPizza (73 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45

BurntPizza (87 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!