Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (522)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (590)
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  
  Trouble getting started  (Read 3109 times)
0 Members and 1 Guest are viewing this topic.
Offline jparril1

Junior Devvie





« Posted 2011-01-18 01:43:55 »

Hey everyone,

       So you have all given me some help before getting started using Java for games, but I feel like Im hitting a huge wall. All of the resources Ive used seem like they are not writing for a beginner. I have Killer Game Programming and it just has been a bunch of code with little explanation. I am not a beginner programmer, but I am a total newbie to graphics and games. I feel like I am not learning the basic game framework from the resources I have used. I went through Kev's Space Invaders tutorial over at his website cokeandcode, but I found myself getting lost in the complex parts. I am not an idiot, but is it impossible to find some sort of step by step intro that explains how to build a simple game from nothing? Ive created quite advanced applications for my CS classes, so I know Im not just a terrible programmer, I am just having a lot of trouble understanding the basics here.. such as loading images, painting to the screen, getting input, updating, etc. I thought I would stick with the basic JAva2d stuff because it would be better for me then diving into something like LWJGL, but I cant even seem to grasp this! It seems like every tutorial I read is a completely different approach. Just something as simple as loading a saved image to the screen has been done in so many ways... one book uses Image, another uses ImageIcon, another uses VolatileImage, another uses Sprite, etc, etc.. and thats just to load an image! Not to mention the method for painting and updating is so different and hard to grasp from one tutorial to the next, some are using Jpanels, others use Canvases, etc.

        All I want to do is make something very basic like pong or whatever. If I can make that and TOTALLY understand whats happening throughout the code, and I can write it on my own without the guide, Im sure I can build off of that to make things more complex. I just feel like my brain is mush when I read these books and tutorials, nothing is clicking and Im becoming unbelievably frustrated. Ive always been a pretty good programmer but I feel totally useless at this. Can anyone lend a word of advice or whatever?
Offline avm1979
« Reply #1 - Posted 2011-01-18 02:07:38 »

It sounds like you're looking for "the right way" to do 2d in java, and that's a source of frustration.  But as usual in the real world, there isn't one - there are many different ways, which are good or bad depending on what your goals are.

For something basic like pong, you'll have to:
1) draw stuff on the screen (note I didn't say load images - you can get away with simple shapes for this)
2) process input in some way
3) use some kind of timer to base your game logic off of, and update the game world

As long as you find and understand *a* way to do all three of the above, you'll be off to a good start.  Don't worry about whether it's a particularly good way - that'll become more clear as you get more experience.  Usually you'll just run into some limitation of the way you're doing it and then switch to a different way that fits your needs better.  No need to try to understand it all at once.

Best of luck to you!

Offline SwampChicken
« Reply #2 - Posted 2011-01-18 04:47:23 »

Agreed. Break it down into smaller projects.

- project 1. display a jframe.
- project 2. draw something in a frame (a box?)
- project 3. draw the box in a frame and make it move over a period of time (animate)
- project 4. draw multiples boxes in the same frame and move them around over time.
- project 5. draw a box in a frame & control it's movement via user input (key/mouse?)
- project 6. stitch the above projects together to get a crude game working.



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

Junior Devvie





« Reply #3 - Posted 2011-01-18 05:39:21 »

thanks to the both of you. So I managed to put this bit together tonight.  if you keep the part where I paint paddle 1 commented out, it works fine, but if I un-comment it, the rectangle never gets painted. I don't understand why. If the ball paints and repaints with no problem, I don't see why the rectangle shouldn't. I also get some strange errors when I try to paint the rectangle, but not always.. any ideas? Also, am I doing anything here that can be done better or different? Thanks

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  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
package pong;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;

public class Game extends JFrame implements Runnable {

   private Rectangle paddleOne;
   private Rectangle paddleTwo;
   private int ballXPosition;
   private int ballYPosition;
   private int ballRadius;
   private int ballXSpeed;
   private int ballYSpeed;
   Thread aThread;

   public Game() {

      setSize(640, 480);
      setTitle("Pong... Almost");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setResizable(false);
      setVisible(true);

      paddleOne = new Rectangle(0, 0, 5, 25);
      paddleTwo = new Rectangle(this.getWidth() - 5, 0, 5, 25);
      ballXPosition = this.getWidth() / 2;
      ballYPosition = this.getHeight() / 2;
      ballRadius = 15;
      ballXSpeed = 2;
      ballYSpeed = 2;

   }

   public void paint(Graphics g) {

      // background
      g.setColor(Color.gray);
      g.fillRect(0, 0, 640, 480);
     
      //ball
      g.setColor(Color.blue);
      g.fillOval(ballXPosition, ballYPosition, ballRadius * 2, ballRadius * 2);

      //paddle 1
      //g.setColor(Color.red);
      //g.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);

   }

   public void run() {

      //loop to constantly repaint the screen
      while(true) {

         /* Collision detections between the ball and all four walls*/
         if(ballXPosition > this.getWidth() - (ballRadius * 2)) {

            ballXSpeed = -2;
         }
         else if(ballXPosition < 0) {

            ballXSpeed = 2;
         }
         if(ballYPosition > this.getHeight() - (ballRadius * 2)) {

            ballYSpeed = -2;
         }
         else if(ballYPosition < ballRadius * 2) {

            ballYSpeed = 2;
         }

         ballXPosition += ballXSpeed;
         ballYPosition += ballYSpeed;

         repaint();

         try {
            Thread.sleep(20);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
package pong;

public class GameDriver {
   
   public static void main(String[] args) {
     
      Game gameTest = new Game();
      gameTest.run();
     
   }

}
Offline loom_weaver

JGO Coder


Medals: 17



« Reply #4 - Posted 2011-01-18 07:20:29 »

I can see your paddle.  The only problem is that it's so small (0, 0, 5, 25) that you can barely see it in the top left corner.

Another thing I would read up on is passive vs active rendering.  Passive rendering uses the Event Dispatch Thread closely associated with Java Swing etc.  It kind of sucks having to learn about this stuff right away but I noticed you spawned a new thread.  Combining passive rendering with with threading without fully understanding what's going on will likely have you running into many hard to detect concurrency errors.

To be safe for now use a Timer instead of a new thread.

ps. the bouncing ball looks good... you're off to a good start!
Offline bigwavejake

Innocent Bystander





« Reply #5 - Posted 2011-01-18 13:28:40 »

I've found this site to be helpful when I started learning how to do 2d games:

http://zetcode.com/tutorials/javagamestutorial/
Offline jparril1

Junior Devvie





« Reply #6 - Posted 2011-01-18 15:51:20 »

loom weaver - thanks! Its so weird, my rectangle was being drawn completely off screen. I thought drawing it at 0, 0 would make it visible but I had to shift it quite a bit. Anyway it works so thanks a lot. And I am going to change the Thread and use a timer instead to repaint every 20ms.

bigwavejake - thanks so much, that seems like a solid tutorial

So reacting to key presses is confusing me, I added an inner keyadapter class, but Im sure Im doing it wrong because nothing is working:

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  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
package pong;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.Timer;

import javax.swing.JFrame;

public class Game extends JFrame {

   private Rectangle paddleOne;
   private Rectangle paddleTwo;
   private int ballXPosition;
   private int ballYPosition;
   private int ballRadius;
   private int ballXSpeed;
   private int ballYSpeed;
   Timer gameTimer;

   public Game() {

      setSize(640, 480);
      setTitle("Pong... Almost");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      addKeyListener(null);
      setResizable(false);
      setVisible(true);

      paddleOne = new Rectangle(5, 75, 15, 80);
      paddleTwo = new Rectangle(this.getWidth() - 20, 75, 15, 80);
      ballXPosition = this.getWidth() / 2;
      ballYPosition = this.getHeight() / 2;
      ballRadius = 15;
      ballXSpeed = 2;
      ballYSpeed = 2;

   }

   public void paint(Graphics g) {

      // background
      g.setColor(Color.gray);
      g.fillRect(0, 0, 640, 480);

      //ball
      g.setColor(Color.blue);
      g.fillOval(ballXPosition, ballYPosition, ballRadius * 2, ballRadius * 2);

      //paddle 1
      g.setColor(Color.red);
      g.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);

      //paddle2
      g.fillRect(paddleTwo.x, paddleTwo.y, paddleTwo.width, paddleTwo.height);

   }

   public void run() {

      //loop to constantly repaint the screen
      while(true) {

         /* Collision detections between the ball and all four walls*/
         if(ballXPosition > this.getWidth() - (ballRadius * 2)) {

            ballXSpeed = -2;
         }
         else if(ballXPosition < 0) {

            ballXSpeed = 2;
         }
         if(ballYPosition > this.getHeight() - (ballRadius * 2)) {

            ballYSpeed = -2;
         }
         else if(ballYPosition < ballRadius * 2) {

            ballYSpeed = 2;
         }

         ballXPosition += ballXSpeed;
         ballYPosition += ballYSpeed;

         repaint();

         try {
            Thread.sleep(20);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private class KeyListener extends KeyAdapter {

      public void KeyPressed(KeyEvent e) {

         int key = e.getKeyCode();

         if (key == KeyEvent.VK_UP) {

            paddleOne.y -= 5;
         }

         if (key == KeyEvent.VK_DOWN) {

            paddleOne.y += 5;
         }
      }
   }
}


Can you guys help me out
Offline aazimon
« Reply #7 - Posted 2011-01-18 17:09:09 »

You need to make your Game class to listen for key events. Take this class as an example. It's pretty is pretty simple. In your frame's constructor add: addKeyListener(new Listener());

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;

public class Frame extends JFrame {

    public Frame(String title) {
        super(title);
       
        addKeyListener(new Listen());
    }

    public class Listen implements KeyListener {
       public void keyPressed(KeyEvent e) {
      System.out.println("Key Pressed");
      // TODO Auto-generated method stub
       }

       public void keyReleased(KeyEvent e) {
      // TODO Auto-generated method stub
       }

       public void keyTyped(KeyEvent e) {
      // TODO Auto-generated method stub
       }
    }
}
Offline jparril1

Junior Devvie





« Reply #8 - Posted 2011-01-18 17:28:36 »

Ahh thanks.. it works! Ok next problem is that it doesnt seem to be able to detect simultaneous key presses. If Im holding the up arrow and moving the right paddle up, I am unable to detect a "W" press to move the left paddle up at the same time. If I hold them both, one will start moving only when I release the other. I tried making two separate inner class KeyListeners... one for the first paddle and one for the second, and just adding them both to my constructor but that isnt working either. Any ideas?
Offline loom_weaver

JGO Coder


Medals: 17



« Reply #9 - Posted 2011-01-18 17:35:04 »

Check out KEY_DOWN vs KEY_PRESSED events.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jparril1

Junior Devvie





« Reply #10 - Posted 2011-01-18 18:08:12 »

Ok so Im still working out getting the keys to work simultaneously, but heres what I have so far. Would you guys mind running it and letting me know if the collisions are looking ok? Since the window is decorated, I seem to be losing pixels on the top of the frame, so I had to use some weird numbers in my collisions to make it seem like the ball was hitting the walls and the paddles stopped at the edges. If I assumed that the edge that I could see was the actual border of the Frame, the objects would just go off of the screen. any critiques?? By the way I added a ball velocity as a constant, so you can just change the value of BALL_VELOCITY at the beginning to make it easier to change the ball speed. Sometimes its easier to see the collisions at a low speed, so you can just speed it up if its too slow.

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  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
package pong;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import java.util.Timer;

import javax.swing.JFrame;

public class Game extends JFrame {

   private final int BALL_VELOCITY;
   private Rectangle paddleOne;
   private Rectangle paddleTwo;
   private int ballXPosition;
   private int ballYPosition;
   private int ballRadius;
   private int ballXSpeed;
   private int ballYSpeed;
   Timer gameTimer;

   public Game() {

      setSize(640, 480);
      setTitle("Pong... Almost");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      addKeyListener(new PaddleOneKeyListen());
      addKeyListener(new PaddleTwoKeyListen());
      setResizable(false);
      setVisible(true);

      paddleOne = new Rectangle(5, 75, 15, 80);
      paddleTwo = new Rectangle(this.getWidth() - 20, 75, 15, 80);
      ballXPosition = this.getWidth() / 2;
      ballYPosition = this.getHeight() / 2;
      ballRadius = 15;
     
      BALL_VELOCITY = 2;
      ballXSpeed = BALL_VELOCITY;
      ballYSpeed = BALL_VELOCITY;
     

   }

   public void paint(Graphics g) {

      // background
      g.setColor(Color.gray);
      g.fillRect(0, 0, 640, 480);

      //ball
      g.setColor(Color.blue);
      g.fillOval(ballXPosition, ballYPosition, ballRadius * 2, ballRadius * 2);

      //paddle 1
      g.setColor(Color.red);
      g.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);

      //paddle2
      g.fillRect(paddleTwo.x, paddleTwo.y, paddleTwo.width, paddleTwo.height);

   }

   public void run() {

      //loop to constantly repaint the screen
      while(true) {
         
         //collision detection between the ball and paddles
         if ((paddleOne.x + 15) >= ballXPosition &&
               paddleOne.y <= ballYPosition && paddleOne.y + paddleOne.height >= ballYPosition) {
           
            ballXSpeed = BALL_VELOCITY;
         }
         
         if (paddleTwo.x <= (ballXPosition + (ballRadius * 2)) &&
               paddleTwo.y <= ballYPosition && paddleTwo.y + paddleTwo.height >= ballYPosition) {
           
            ballXSpeed = -(BALL_VELOCITY);
         }

         /* Collision detections between the ball and all four walls*/
         if(ballXPosition > this.getWidth() - (ballRadius * 2)) {

            ballXSpeed = -(BALL_VELOCITY);
         }
         else if(ballXPosition < 0) {

            ballXSpeed = BALL_VELOCITY;
         }
         if(ballYPosition > this.getHeight() - (ballRadius * 2)) {

            ballYSpeed = -(BALL_VELOCITY);
         }
         else if(ballYPosition < ballRadius * 2) {

            ballYSpeed = BALL_VELOCITY;
         }

         ballXPosition += ballXSpeed;
         ballYPosition += ballYSpeed;

         repaint();

         try {
            Thread.sleep(20);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private class PaddleOneKeyListen implements KeyListener {

     
      @Override
     
      public void keyPressed(KeyEvent e) {

         int key = e.getKeyCode();

         //paddle one movement
         if (key == KeyEvent.VK_W && paddleOne.y >= 30) {

            paddleOne.y -= 10;
         }

         if (key == KeyEvent.VK_S && paddleOne.y < 395 ) {

            paddleOne.y += 10;
         }
      }

      @Override
      public void keyReleased(KeyEvent arg0) {
         // TODO Auto-generated method stub

      }

      @Override
      public void keyTyped(KeyEvent arg0) {
         // TODO Auto-generated method stub

      }
   }
   
   private class PaddleTwoKeyListen implements KeyListener {


      @Override
      public void keyPressed(KeyEvent e) {

         int key = e.getKeyCode();

         //paddle two movement
         if (key == KeyEvent.VK_UP && paddleTwo.y >= 30) {

            paddleTwo.y -= 10;
         }

         if (key == KeyEvent.VK_DOWN && paddleTwo.y != 395) {

            paddleTwo.y += 10;
         }
      }

      @Override
      public void keyReleased(KeyEvent arg0) {
         // TODO Auto-generated method stub

      }

      @Override
      public void keyTyped(KeyEvent arg0) {
         // TODO Auto-generated method stub

      }
   }
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
package pong;

public class GameDriver {
   
   public static void main(String[] args) {
     
      Game gameTest = new Game();
      gameTest.run();
     
   }

}
Offline SimonH
« Reply #11 - Posted 2011-01-18 19:10:34 »

Don't add more than one key listener!
Have global variables for the actions you want. Like;
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  
    boolean goLeft=false;
    boolean goRight=false;

    addKeyListener(new myKeyListener());

    while (gameRunning)
    {
        if (goLeft  && paddleOne.y >= 30)
        {
                paddleOne.y -= 10;
        }
        ... etc...
    }

    private class myKeyListener implements KeyListener {
         public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            if (key == KeyEvent.VK_W) {
                goLeft=true;
            }
            if (key == KeyEvent.VK_E) {
                goRight=true;
            }
            ... other keys
        }
 
        @Override
        public void keyReleased(KeyEvent arg0) {
            if (key == KeyEvent.VK_W) {
                goLeft=false;
            }
            if (key == KeyEvent.VK_E) {
                goRight=false;
            }
             ... other keys
        }
 
        @Override
        public void keyTyped(KeyEvent arg0) {
            // TODO Auto-generated method stub
 
        }
    }

Get the idea? The booleans separate the game logic from the key events.

People make games and games make people
Offline jparril1

Junior Devvie





« Reply #12 - Posted 2011-01-18 21:12:38 »

Gotcha, thanks!

Im still working out how to get it to respond to simultaneous key presses so that two people can play against each other. Ill post updated code when I get to it.
Offline Captain Awesome

Junior Devvie


Medals: 2


Hi


« Reply #13 - Posted 2011-01-18 21:38:28 »

Gotcha, thanks!

Im still working out how to get it to respond to simultaneous key presses so that two people can play against each other. Ill post updated code when I get to it.

What I like to do is the following:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
private boolean[] keys = new boolean [525];
    @Override
    public void keyTyped(KeyEvent e) {
       
    }

    @Override
    public void keyPressed(KeyEvent e) {
        keys[e.getKeyCode()] = true;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keys[e.getKeyCode()] = false;
    }


If I want to check if a key is pressed down I just do the following:

1  
2  
3  
if(keys[KeyEvent.VK_UP]) {
            //Do stuff here
        }


If the key has been pressed (in this case the up arrowkey), the boolean at that index will be true which means the code inside the block will run.
However if the key has been released the boolean in that index will be false.

Not saying it's the best method, just how I do it Smiley
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #14 - Posted 2011-01-18 21:57:37 »

In a similar vein, you can also use a set instead of an array.

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  
TreeSet<Integer> buttonsPressed;

void keyPressed(KeyEvent e)
{
    buttonsPressed.add(new Integer(e.getKeyCode()));
}

void keyReleased(KeyEvent e)
{
    buttonsPressed.remove(new Integer(e.getKeyCode()));
}

void doButtonStuff()
{
    //Process all of the presses
    for (Iterator<Integer> i = buttonsPressed.iterator(); i.hasNext();)
    {
        doButtonThing(i.next().intValue());
    }

    //Or check for just one
    if (buttonsPressed.contains(new Integer(KeyEvent.VK_SPACE)))
    {
        doSpaceThing();
    }
}


Doing it without an array is:
- (maybe) slightly more memory efficient
- much slower accessing and adding elements
- significantly slower checking whether many individual buttons are down
- faster at checking against all buttons that are down
- easier to see exactly how many buttons are being pressed

Honestly in most situations I think it's easier just to use arrays like Captain Awesome suggested, but this option can work better depending on what you want to do. BTW, I used a TreeSet because it enforces uniqueness (you can't add the same button multiple times), and because it's automatically sorted doing a contains() check is much faster than in a list. Still, a typical user will only press like 4 buttons at once maximum, so none of these micro-optimizations really matter in the end.

See my work:
OTC Software
Offline aazimon
« Reply #15 - Posted 2011-01-18 22:56:01 »

With the multiple keys being pressed, something goofy goes on. Like posted, you need to use a boolean to keep track of what keys are being pressed. Here's a simple example. Each loop, you need to check if the key is pressed (true) or not.

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  
public class Frame extends JFrame {
    private boolean wPress = false;
    private boolean ePress = false;

    public Frame(String title) {
        super(title);
       
        addKeyListener(new Listen());
    }

    public void paint(Graphics g) {
        super.paint(g);
        if (wPress) {
            System.out.println("W press");
        }
        if (ePress) {
            System.out.println("E press");
        }
    }
   
    public void run() {
   //loop to constantly repaint the screen
   while(true) {        
       repaint();
       try {
      Thread.sleep(20);
       } catch (InterruptedException e) {
          //
       }
   }
    }
   
    public class Listen implements KeyListener {
       public void keyPressed(KeyEvent e) {
      if (e.getKeyCode() == KeyEvent.VK_W) {
          wPress = true;
      }
      if (e.getKeyCode() == KeyEvent.VK_E) {
          ePress = true;
      }
       }

       public void keyReleased(KeyEvent e) {
      if (e.getKeyCode() == KeyEvent.VK_W) {
          wPress = false;
      }
      if (e.getKeyCode() == KeyEvent.VK_E) {
          ePress = false;
      }
       }

       public void keyTyped(KeyEvent e) {
      // TODO Auto-generated method stub
       }
    }
}

Offline jparril1

Junior Devvie





« Reply #16 - Posted 2011-01-19 23:17:29 »

I see what you guys are saying. Can anyone explain why exactly it works when having the keylistener set a boolean instead of directly changing the paddles position? Like I said it totally doesnt recognize two keys being held down when I do it my way, so why does it work using booleans? Just trying to understand whats happening Smiley
Offline aazimon
« Reply #17 - Posted 2011-01-19 23:36:59 »

I'm not sure what's happening. I have noticed that when you press a second key down, the first key pressed no longer fires a key event. It appears to be more part of the OS then JAVA. When you bring up a text editor and press and hold one key then type another, the stops printing out the first key.
Offline jparril1

Junior Devvie





« Reply #18 - Posted 2011-01-19 23:43:36 »

Just wanted to update... I changed my code to use booleans like youve suggested. The performance increased by at least 500% lol. The paddles are now super responsive its ridiculous. I might actually have to turn down their speed. Thank you so much! Why the hell does that make such a huge difference??

Heres what Ive done so far. Added scores and all that. I NEED to use double buffering because the flickering is killing me! Any critiques??

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  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
233  
234  
235  
236  
237  
238  
239  
package pong;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;

import javax.swing.JFrame;

public class Game extends JFrame {

   
   private static final long serialVersionUID = 1L;
   
   private Rectangle paddleOne;
   private Rectangle paddleTwo;
   private int ballXPosition;
   private int ballYPosition;
   private final int BALL_VELOCITY;
   private final int BALL_RADIUS;
   private int ballXSpeed;
   private int ballYSpeed;
   Timer gameTimer;
   
   int playerOneScore;
   int playerTwoScore;
   
   //booleans for key presses
   private boolean wPressed;
   private boolean sPressed;
   private boolean upPressed;
   private boolean downPressed;

   public Game() {

      setSize(640, 480);
      setTitle("Pong... Almost");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      addKeyListener(new KeyListen());

      setResizable(false);
      setVisible(true);
     
      playerOneScore = 0;
      playerTwoScore = 0;

      paddleOne = new Rectangle(5, 75, 15, 80);
      paddleTwo = new Rectangle(this.getWidth() - 20, 75, 15, 80);
      ballXPosition = this.getWidth() / 2;
      ballYPosition = this.getHeight() / 2;
      BALL_RADIUS = 10;
     
      BALL_VELOCITY = 8;
      ballXSpeed = BALL_VELOCITY;
      ballYSpeed = BALL_VELOCITY;
     
      wPressed = false;
      sPressed = false;
      upPressed = false;
      downPressed = false;
     

   }

   public void paint(Graphics g) {

      // background
      g.setColor(Color.black);
      g.fillRect(0, 0, 640, 480);

      //ball
      g.setColor(Color.green);
      g.fillOval(ballXPosition, ballYPosition, BALL_RADIUS * 2, BALL_RADIUS * 2);

      //paddle 1
      g.setColor(Color.green);
      g.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);

      //paddle2
      g.fillRect(paddleTwo.x, paddleTwo.y, paddleTwo.width, paddleTwo.height);
     
      //score
      g.setFont(new Font("Arial Bold", Font.PLAIN, 40));
      g.drawString(Integer.toString(playerOneScore), 250, 75);
      g.drawString(Integer.toString(playerTwoScore), 350, 75);

   }

   public void run() {

      //loop to constantly repaint the screen
      while(true) {
         
         //collision detection between the ball and paddles
         if ((paddleOne.x + 15) >= ballXPosition &&
               paddleOne.y <= ballYPosition && paddleOne.y + paddleOne.height >= ballYPosition) {
           
            ballXSpeed = BALL_VELOCITY;
         }
         
         if (paddleTwo.x <= (ballXPosition + (BALL_RADIUS * 2)) &&
               paddleTwo.y <= ballYPosition && paddleTwo.y + paddleTwo.height >= ballYPosition) {
           
            ballXSpeed = -(BALL_VELOCITY);
         }

         /* Collision detections between the ball and all four walls*/
         if(ballXPosition > this.getWidth() - (BALL_RADIUS * 2)) {

            ballXSpeed = -(BALL_VELOCITY);
           
            playerOneScore++;
         }
         else if(ballXPosition < 0) {

            ballXSpeed = BALL_VELOCITY;
           
            playerTwoScore++;
         }
         if(ballYPosition > this.getHeight() - (BALL_RADIUS * 2)) {

            ballYSpeed = -(BALL_VELOCITY);
         }
         else if(ballYPosition < BALL_RADIUS * 2) {

            ballYSpeed = BALL_VELOCITY;
         }

         ballXPosition += ballXSpeed;
         ballYPosition += ballYSpeed;
         
         //moving paddles
         if (wPressed) {
            paddleOne.y -= 10;
         }
         if (sPressed) {
            paddleOne.y += 10;
         }
         if (upPressed){
            paddleTwo.y -= 10;
         }
         if (downPressed) {
            paddleTwo.y += 10;
         }

         repaint();
         
         //set all key presses to false if paddles are going off screen.. fix this its sloppy!
         if (paddleOne.y <= 30) {
            wPressed = false;
         }
         if (paddleOne.y > 395 ) {
            sPressed = false;
         }
         if (paddleTwo.y <= 30) {
            upPressed = false;
         }
         if (paddleTwo.y > 395) {
            downPressed = false;
         }
         
         
         try {
            Thread.sleep(20);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private class KeyListen implements KeyListener {

      @Override
      public void keyPressed(KeyEvent e) {

         int key = e.getKeyCode();

         //paddle one move
         if (key == KeyEvent.VK_W && paddleOne.y >= 30) {

            wPressed = true;
         }

         if (key == KeyEvent.VK_S && paddleOne.y < 395 ) {

            sPressed = true;
         }
         //paddle two move
         if (key == KeyEvent.VK_UP && paddleTwo.y >= 30) {

            upPressed = true;
         }

         if (key == KeyEvent.VK_DOWN && paddleTwo.y < 395) {

            downPressed = true;
         }
      }

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

         //paddle one stop
         if (key == KeyEvent.VK_W) {

            wPressed = false;
         }

         if (key == KeyEvent.VK_S) {

            sPressed = false;
         }
         //paddle two stop
         if (key == KeyEvent.VK_UP) {

            upPressed = false;
         }

         if (key == KeyEvent.VK_DOWN) {

            downPressed = false;
         }

      }

      @Override
      public void keyTyped(KeyEvent arg0) {
         // TODO Auto-generated method stub

      }
   }
   
   
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
package pong;

public class GameDriver {
   
   public static void main(String[] args) {
     
      Game gameTest = new Game();
      gameTest.run();
     
   }

}
Offline aazimon
« Reply #19 - Posted 2011-01-20 16:13:25 »

For what your trying to accomplish. This is fine. Going forward you may want to look at extracting out pieces of the code so you can easily re-use it. Ways to do this varies drastically.
Offline kappa
« League of Dukes »

JGO Kernel


Medals: 78
Projects: 15


★★★★★


« Reply #20 - Posted 2011-01-20 16:19:43 »

You could start with the LWJGL Basics tutorial series found here. The current 4 parts should get you to Pong level in a simple and concise manner.

Thereafter I recommend you jump to Slick2D, its the best 2d java games library at the moment and is probably the most well documented (see its wiki) not to forget its really helpful community.

Going down the Swing/Java2D/AWT road eventually leads to a dead end as those libraries just aren't designed for games.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #21 - Posted 2011-01-20 16:57:50 »

I'm guessing your speed difference is because you used to be adjusting the paddle's position from within keyPressed, and now you're doing it within your game loop. Your game loop appears to fire every 20ms - the EDT (Event Dispatch Thread, which is what calls keyPressed etc.) must be firing less often than that. To get something similar, you can increase the length of your Thread.sleep(), or you can just move your paddle by less distance every time, which is what I would recommend because a 20ms delay is already only 50fps.

The difference between the booleans and the way you were doing it before is that the OS will only fire an event for the most recent key. Because you're storing every key you've ever seen, you get to jump over this hurdle by remembering what was pressed independently of the OS.

See my work:
OTC Software
Offline Gudradain
« Reply #22 - Posted 2011-01-20 17:32:46 »

Going down the Swing/Java2D/AWT road eventually leads to a dead end as those libraries just aren't designed for games.

Really? I don't really see how this can be true. It's best to avoid as much as possible Swing/AWT but Java2D is good enough.
Offline kappa
« League of Dukes »

JGO Kernel


Medals: 78
Projects: 15


★★★★★


« Reply #23 - Posted 2011-01-20 19:11:20 »

Really? I don't really see how this can be true. It's best to avoid as much as possible Swing/AWT but Java2D is good enough.

Given that Java2D has improved in the last few releases but its still factors slower then what the OpenGL bindings can do and pretty much impossible to pull of a modern looking game with it. Also don't forget about input and sound which are also pretty important for games.
Offline Gudradain
« Reply #24 - Posted 2011-01-20 19:24:05 »

Its factors slower then what the OpenGL bindings can do and pretty much impossible to pull of a modern looking game with it.

Because of lighting? or something else?
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.

trollwarrior1 (29 views)
2014-11-22 12:13:56

xFryIx (71 views)
2014-11-13 12:34:49

digdugdiggy (50 views)
2014-11-12 21:11:50

digdugdiggy (44 views)
2014-11-12 21:10:15

digdugdiggy (38 views)
2014-11-12 21:09:33

kovacsa (62 views)
2014-11-07 19:57:14

TehJavaDev (67 views)
2014-11-03 22:04:50

BurntPizza (64 views)
2014-11-03 18:54:52

moogie (80 views)
2014-11-03 06:22:04

CopyableCougar4 (80 views)
2014-11-01 23:36:41
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!