4

I am new to java and programming in general,and i am trying to write a little shooting game with a spaceship and aliens, but having a lot of trouble with the graphics. It seems that I am mixing a lot of different kind of components.

How should I do it right?
- Should I use Swing JFrame and then add it a Graphics object?
- Should I make a panel first and add the graphics on to it instead?
- Or maybe should I use a canvas instead of a JPanel?

There are a lot of options, and searching the net for answers makes me very confused. Some advise to use the paint() method while others demonstrates code while using the paintComponent()...

What is the preferred way in the right order for the graphics to be laid and what classes should I use?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user2030118
  • 155
  • 3
  • 14

4 Answers4

5

For serious gaming, don't use Swing but rather other more game-specific GUI libraries such as the LWJGL. For simple Games, Swing is OK, but be sure to read the graphics tutorials first as your assumptions on how to draw may need to be changed (I know mine were). For instance you would not use a Graphics class field but would usually draw passively in a JComponent's paintComponent method.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
5

For simple games, Swing is fine and you can rely on the followings:

  1. Use Swing and forget about AWT. You will get far better results with a lot less code.
  2. Use Swing Timer to pace your game
  3. For each of your components, extends JComponent or JPanel and override paintComponent. In paintComponent perform only drawing operations (do not update your model or modify the state of your component).
  4. Whenever when you want to draw something, modify your components state and then invoke repaint()
  5. To handle layers, you can always use JLayeredPane
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • any good basic starting guide you can recommend? starting from the basic of how to create jframe, jpanel and move from there? – user2030118 Feb 02 '13 at 23:59
  • @user2030118 The tutorial of Sun/Oracle are pretty good. Simple, straightforward and quite easy to understand. http://docs.oracle.com/javase/tutorial/uiswing/components/index.html and http://docs.oracle.com/javase/tutorial/uiswing/painting/index.html are good places to start with in your situation. – Guillaume Polet Feb 03 '13 at 00:22
2

I can see the sense of using a game API as suggested by @Hovercraft, but feel that many simple games can do without it.

I agree with the first 2 points of @Guillaume, but would tend to go in a different direction after that.

Let us assume the game:

  1. Is a fixed size (i.e. non-resizable).
  2. Has no components appearing over it.

In that case, I would tend to do the rendering in a BufferedImage that is displayed in a label.

Answers to specific questions

Should I use Swing JFrame and than add it a Graphics object?

That would not compile. So ..no.

Should I make a panel first and add the graphics on to it instead?

That is basically what Guillaume is suggesting, though I prefer using an image as the canvas on which to paint.

Or maybe should I use a canvas instead of a JPanel?

If by 'canvas' you mean java.awt.Canvas then no.
If you mean a java.awt.image.BufferedImage then yes.

Some advise to use the paint() method while others demonstrates code while using the paintComponent()...

This is a common confusion since there is so much old and bad code out there in the World Wild Web.

The only components that overriding paint(Graphics) would work with are components of the AWT & Swing top-level containers such as JFrame, JApplet or JWindow.

  • AWT is last millennium's GUI component toolkit. We should use Swing this millennium.
  • It is unusual for an entire GUI to be custom painted. Instead it might be added as the major component amongst others that report player health, lives remaining, score etc. For that (and other) reasons, it is better to render to a 'non top-level container' which would leave us looking at doing custom painting in a JComponent or JPanel.

For custom painting in an extended panel or component, override paintComponent(Graphics). That is the correct way to do custom painting for those components.

Other tips

Each object of the game (e.g. Ship, Enemy, Missile) should know how to draw itself. Keep a reference to each of the game elements in the painting routine, and simply call gameElement.paint(Graphics) (or Graphics2D) on the instance of graphics it is painting.

If the game elements are drawn from Java-2D based Shape instances, or if a Shape can be defined from the existing sprite images, collision detection becomes simple. For details see:

  1. This answer to Get mouse detection with a dynamic shape
  2. This answer to Collision detection with complex shapes
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

I had to implement a lost-vikings like game for a course project and not having a single idea how to do it, had the exact same questions in mind.

I ended up writing methods that are responsible for drawing different elements(i.e., one to draw enemies, one for missiles, etc...), and then called them in paint() method. I called repaint() method in my main loop to redraw everything.

I am not sure if this is a good practice, but it worked. You can check the code here, though, I must warn you that it is a "damn, i must get it done" project. You should specifically have a look at GameFrame.java.

Ayberk
  • 410
  • 10
  • 21
  • 1
    Was this a Swing project? If so, then you've used a bad practice as you should almost never call `paint(...)` directly in a Swing GUI (exceptions for printing and for creating a BufferedImage of a component). Instead we usually call `repaint()` to ask the JVM to repaint the portion of the component that needs it. – Hovercraft Full Of Eels Feb 02 '13 at 23:38
  • Edit: yes yours is a Swing project. Please delete this answer as it is a dangerous suggestion. – Hovercraft Full Of Eels Feb 02 '13 at 23:40
  • @HovercraftFullOfEels Pardon my mistake. I did call repaint(), not paint(). Going to fix that now. – Ayberk Feb 02 '13 at 23:40
  • Thanks for clarifying this. It's a subtle point but an important one. Down-vote deleted, up-vote given in its place. – Hovercraft Full Of Eels Feb 02 '13 at 23:41
  • 2
    If I may just add that you should prefer overriding paintComponent instead of paint. – Guillaume Polet Feb 03 '13 at 00:55