Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  Basic Game  (Read 81712 times)
0 Members and 2 Guests are viewing this topic.
Offline Gudradain
« Posted 2010-02-06 05:01:53 »

Let's start with basic.

You want to do a game and don't know where to start?

A game is usually compose of the following elements :

- Frame : The window of the game
- Canvas : The rendering surface
- GameLoop : Call the rendering and update methods
- Rendering method : All your drawing here
- Update method : All your game logic here
- Mouse and Key input : Add KeyListener, MouseListener and MouseMotionListener to the canvas

Here is a template that I use for my games. To make your own game, you just have to add your code in the render(Graphics2D g) and update(int deltaTime) methods.

I add a little test so you can run this code directly to see what it does.
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  
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Game implements Runnable{
   
   final int WIDTH = 1000;
   final int HEIGHT = 700;
   
   JFrame frame;
   Canvas canvas;
   BufferStrategy bufferStrategy;
   
   public Game(){
      frame = new JFrame("Basic Game");
     
      JPanel panel = (JPanel) frame.getContentPane();
      panel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
      panel.setLayout(null);
     
      canvas = new Canvas();
      canvas.setBounds(0, 0, WIDTH, HEIGHT);
      canvas.setIgnoreRepaint(true);
     
      panel.add(canvas);
     
      canvas.addMouseListener(new MouseControl());
     
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setResizable(false);
      frame.setVisible(true);
     
      canvas.createBufferStrategy(2);
      bufferStrategy = canvas.getBufferStrategy();
     
      canvas.requestFocus();
   }
   
       
   private class MouseControl extends MouseAdapter{
     
   }
   
   long desiredFPS = 60;
    long desiredDeltaLoop = (1000*1000*1000)/desiredFPS;
   
   boolean running = true;
   
   public void run(){
     
      long beginLoopTime;
      long endLoopTime;
      long currentUpdateTime = System.nanoTime();
      long lastUpdateTime;
      long deltaLoop;
     
      while(running){
         beginLoopTime = System.nanoTime();
         
         render();
         
         lastUpdateTime = currentUpdateTime;
         currentUpdateTime = System.nanoTime();
         update((int) ((currentUpdateTime - lastUpdateTime)/(1000*1000)));
         
         endLoopTime = System.nanoTime();
         deltaLoop = endLoopTime - beginLoopTime;
           
           if(deltaLoop > desiredDeltaLoop){
               //Do nothing. We are already late.
          }else{
               try{
                   Thread.sleep((desiredDeltaLoop - deltaLoop)/(1000*1000));
               }catch(InterruptedException e){
                   //Do nothing
              }
           }
      }
   }
   
   private void render() {
      Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
      g.clearRect(0, 0, WIDTH, HEIGHT);
      render(g);
      g.dispose();
      bufferStrategy.show();
   }
   
   //TESTING
  private double x = 0;
   
   /**
    * Rewrite this method for your game
    */

   protected void update(int deltaTime){
      x += deltaTime * 0.2;
      while(x > 500){
         x -= 500;
      }
   }
   
   /**
    * Rewrite this method for your game
    */

   protected void render(Graphics2D g){
      g.fillRect((int)x, 0, 200, 200);
   }
   
   public static void main(String [] args){
      Game ex = new Game();
      new Thread(ex).start();
   }

}


Here is a game that I made with this code : http://www.gudradain.byethost12.com/geomwar.html

NOTE : If you run the code, you probably realize that the square in the animation glitter a little bit. You can remove that effect by increasing the frame rate of the game (change the variable desiredFPS).

WARNING : If you set a too high FPS (frame per second), you might have problem with the game logic.
Offline Xyle
« Reply #1 - Posted 2010-02-06 06:36:49 »

I will have to say that that is absolutely BEAUTIFUL!!

Very nice tutorial and awesome game to boot!!
Thank you very much for your contribution!!

Life is just a game, learn to play!
------------------------------------------
╬-YellzBellz Games!-╬ Cheesy
Offline markfarrell

Junior Newbie





« Reply #2 - Posted 2010-02-07 16:38:24 »

I got a score over 800,000! Tongue
It just goes to show how to optimize a simple game engine with a dash of creativity and effort.  Grin
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Dreamcatchermatt

Junior Member





« Reply #3 - Posted 2010-04-01 00:04:08 »

EDIT: Ok, I think I have found a good solution. Thanks anyway Smiley

Hi, Gudradain,

I'm new on the forums here, and found the place from a google serch that got me to this tutorial.

I have been playing around with the code for your game loop, and have started working on a basic space RTS where you pilot a space ship around a solar system. At the moment its only a very rudimentary graphics and physics engine based around your code.

I have been up all night implimenting a 2D camera class using AffineTransform that alows zooming and scrolling the map. This works fine programaticaly (i can lock the camera to a moving object in the game world) but i cannot for the life of me figure out how to get mouse input to work (for manual click and drag/wheel zooming).

I muss confess, i'm new to the Java game scene, having come from a few years experience with XNA/C# game programing, and am a little uncerten how all the mouse event listening works in Java.

I would be verry greatfull if you could explain what the MouseControl class is sposed to do, and how to use this to detect dragging and wheel events, and maybe keyPresses?

Thankyou very much for an already fantastic tutorial!

Once i have something close to ready i'll post screenshots and a demo.

Matt Taylor

Offline imorio

Junior Newbie





« Reply #4 - Posted 2010-09-04 16:56:24 »

My question: how do you get all those moving parts move over the screen so efficiently? In my (tower defence) game I used the following way way to get the monsters moving:

When I need a new monster, I make an instance of the monster class. That starts a swing-timer. Every time that generates an action event, the integer "steps" goes up by one. The path they need to take is set out pizel by pixel into an arrayList. Because the monster class extends JPanel, it can then paint itself based on those coordinates (arrayList.get(steps)). The JPanel is added to a JLayeredPane and repainted each time the timer generates an action event.

For one monster, this works fine, however at 3 monsters it gets to slow to be practical. Your game consists of 50+ moving parts, how do you do that?
Offline Gudradain
« Reply #5 - Posted 2010-09-07 04:03:21 »

My question: how do you get all those moving parts move over the screen so efficiently? In my (tower defence) game I used the following way way to get the monsters moving:

When I need a new monster, I make an instance of the monster class. That starts a swing-timer. Every time that generates an action event, the integer "steps" goes up by one. The path they need to take is set out pizel by pixel into an arrayList. Because the monster class extends JPanel, it can then paint itself based on those coordinates (arrayList.get(steps)). The JPanel is added to a JLayeredPane and repainted each time the timer generates an action event.

For one monster, this works fine, however at 3 monsters it gets to slow to be practical. Your game consists of 50+ moving parts, how do you do that?

Lot of problems here.

First, in a game you only really need 1 timer, just one. This timer send event to all your game object in the update method.
Second, you only need 1 drawing surface in a game. Don't make a lot of JPanel. That bring up next point
Third, dont make monster extends JPanel. Make Monster a class of his own and use Graphics2D class to draw your monster. The Monster class should only contain information about where the monster is, what it can do and how to draw it.

Oh by the way, there is way more than 50 moving part in this game. Every line of the explosion is a class equivalent to a monster (... ok this must not be the most efficient way, but so far I didn't get any lag complaint).

Hope it helps.

N.B. Drawing on canvas is suppose to be accelerated (by graphics card?!?). Anyway, not sure if it does any difference as Swing component are suppose to be accelerated too.
Offline Master

Junior Newbie





« Reply #6 - Posted 2011-02-10 18:56:46 »

This is a great template but I am not sure it counts as a tutorial since nothing is explained. If someone could go back through the op's code and explain it line by line this would probably make a perfect intro tutorial to gaming.
Offline IronclawsBt

Junior Member


Medals: 1



« Reply #7 - Posted 2011-02-10 19:15:10 »

Maybe this should be moved to "Shared Code".

It's not what you know, it's what other people think you know.
Just hope you don't get quizzed on it.
Game engine design tutorials
Offline Gudradain
« Reply #8 - Posted 2011-03-10 20:08:09 »

This is a great template but I am not sure it counts as a tutorial since nothing is explained. If someone could go back through the op's code and explain it line by line this would probably make a perfect intro tutorial to gaming.

Is your goal actually a game or just try to make a good game loop for a couple of week and then give up on game programming? Ok sorry if I sound a bit harsh but something similar happens to me.

I waste a lot of time trying to make a good game loop. First I went with a JPanel and I just let the repaint() method to be called from time to time (not a good idea). Next I tried to use a Timer object with the repaint(). Didn't really work either. Finally I decide to look around on the forum I saw that many person were using a while(true) loop. So I guess that was not so bad. Unfortunately, there was no place that a specified game loop was propose without having many variation of it. So I wonder, why is there so many variations? Is one better than another? So I decide to try everyone I see and research about every methods (on this forum, on other forum, on google, etc). In the process I also learn about double buffering (drawing to an image before switching it to the screen in one step) and how it improved your rendering.

All of that was a lenghty process and I basically lost 2-3 months doing so just to realize that most of the methods I encounter were excellent or good enough and that I would have saved a lot of time just picking one and getting started in game programming rather than try to understand everything for no particular reason. Maybe it's just because I'm really stubborn.

Anyway I put this tutorial up this way because I figured that most people only want to get started as soon as possible and really the only thing you really need to start coding your game is an update(deltaTime) method, a render(Graphics2D) and some knowledge about Mouse and keyboard input (check java tutorial for that). The rest is basically your imagination.

Well there is a few technical trick you might need to learn in the way but we have a very good forum for that (Newbie & Debugging Questions)
Offline dah01

Junior Member


Medals: 7



« Reply #9 - Posted 2011-03-15 03:06:38 »

Man, what you described is exactly what I've gone through.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline miga

Junior Member


Medals: 2
Projects: 1



« Reply #10 - Posted 2011-04-28 03:25:24 »

Thanks for sharing this code with us. Very good reference. I have a bit of question.

1  
2  
3  
4  
5  
6  
 protected void update(int deltaTime){
        x += deltaTime * 0.2;
        while(x > 500){
            x -= 500;
        }
    }


Could someone explain me what is this deltaTime for?

Miga's Hobby Programming - http://www.migapro.com
Offline ReBirth
« Reply #11 - Posted 2011-04-28 06:23:48 »

The deltaTime is used to know how far update (move, lifespan of an entity etc) should be done on this loop. Each loop takes some amount of time but our update must still go on so we need to update based on deltaTime of previous loop.

Offline zoto

Senior Member


Medals: 4



« Reply #12 - Posted 2011-04-28 06:42:05 »

Quote
Could someone explain me what is this deltaTime for?
It is the number of milliseconds that have elapsed since the last update.
Offline miga

Junior Member


Medals: 2
Projects: 1



« Reply #13 - Posted 2011-04-28 07:33:45 »

Thanks for the replies.

I have been trying to calculate FPS using this game loop. I call this method at the end of while loop. For instance, when I set the FPS to 60, it calculates between 62 and 65. Am I still doing this correctly?

1  
2  
3  
4  
5  
6  
7  
8  
9  
public void calcFPS(){
      ++frameCount;
      long now = System.nanoTime();
      if (now - base >= 1000000000L){
         frameRate = (float)(frameCount * 1000000000L) / (float)(now - base);
         frameCount = 0;
         base = System.nanoTime();
      }
   }

Miga's Hobby Programming - http://www.migapro.com
Offline Gingerious

Junior Member


Medals: 2



« Reply #14 - Posted 2011-10-25 21:32:46 »

I've extended your game class, but I'm having trouble understanding how to access the MouseControl nested class.  I think this is just my limited understanding of java, but if a nested class is declared private, I don't understand how i access it from the derived class.  I'm not supposed to modify it in the superclass, right?  That would defeat the purpose of deriving it in the first place.

Halp? Sad
Offline h3ckboy

JGO Coder


Medals: 5



« Reply #15 - Posted 2011-10-25 21:34:19 »

I may be wrong,b ut I don't think that you are supposed to extend, when I took a quick look, it seems like u should use that code directly and just change it to suite ur needs.
Offline Gingerious

Junior Member


Medals: 2



« Reply #16 - Posted 2011-10-25 21:55:35 »

His update() and render(g) methods say to override them in a subclass, so it looks like it's meant to be extended.

EDIT: Although the more i look at it, the more I think you are right.  It doesn't seem like it needs to be derived from.  I'll give it a try without a subclass and see if that works better or not.
Offline Gingerious

Junior Member


Medals: 2



« Reply #17 - Posted 2011-10-26 18:24:57 »

Sorry for double-post.

I stopped trying to derive a class from your Game class, but that nested class still gets me.  I've put system print lines in the MouseControl class to see when an event is being registered, and it doesn't look like it's ever getting there.  What am I missing?

Here's the code that I've changed/added:

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  
private class MouseControl extends MouseAdapter{
     
      public boolean mouseLeftPressed, mouseRightPressed;
     
      public void MouseClicked(MouseEvent e){}
      public void MouseDragged(MouseEvent e){}
      public void MouseEntered(MouseEvent e){}
      public void MouseExited(MouseEvent e){}
      public void MouseMoved(MouseEvent e){}
      public void MousePressed(MouseEvent e){
         switch(e.getButton()) {
            case MouseEvent.BUTTON1:
               mouseLeftPressed = true;
               System.out.println("mouseLeftPressed");
               break;
            case MouseEvent.BUTTON2:
               mouseRightPressed = true;
               System.out.println("mouseRightPressed");
               break;
         }
      }
      public void MouseReleased(MouseEvent e){
         switch(e.getButton()) {
            case MouseEvent.BUTTON1:
               mouseLeftPressed = false;
               System.out.println("mouseLeftReleased");
               break;
            case MouseEvent.BUTTON2:
               mouseRightPressed = false;
               System.out.println("mouseRightReleased");
               break;
         }
      }
      public void MouseWheelMoved(MouseEvent e){}
     
   }
Offline h3ckboy

JGO Coder


Medals: 5



« Reply #18 - Posted 2011-10-26 18:30:19 »

hmm, I've never used mouseAdapter, but in any event did you add it to the frame? like there should be a method in your game class where u add it. for a mouse listener is is something like addListener(whatever class implements the listener). but you use adaper for some reason so it may be different
Offline Gingerious

Junior Member


Medals: 2



« Reply #19 - Posted 2011-10-26 18:44:33 »

It's added to the canvas in the Game() method in the original code, but not to the frame.
Offline Gudradain
« Reply #20 - Posted 2011-10-26 21:26:33 »

I may be wrong,b ut I don't think that you are supposed to extend, when I took a quick look, it seems like u should use that code directly and just change it to suite ur needs.

No you are exactly right. You should use that directly it gives more flexibility and it's easier. I should have put the comment rewrite this method to suit your need.
Offline Gingerious

Junior Member


Medals: 2



« Reply #21 - Posted 2011-10-26 22:55:26 »

Gudradain, any thoughts on why those mouse click events aren't firing off?
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #22 - Posted 2011-10-26 23:14:45 »

Those methods start with lower case 'm' Tongue Grin

Offline Gingerious

Junior Member


Medals: 2



« Reply #23 - Posted 2011-10-26 23:44:37 »

 Huh

 Undecided

 Cranky

 Angry

Online Riven
« League of Dukes »

JGO Overlord


Medals: 743
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #24 - Posted 2011-10-26 23:55:32 »

if you add the @Override annotation, the compiler will warn you in this case.

1  
2  
@Override
public void MousePressed(MouseEvent e){}

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Gudradain
« Reply #25 - Posted 2011-10-27 05:06:41 »

lol it's always funny to find a stupid error Smiley
Offline philfrei
« Reply #26 - Posted 2011-10-27 10:10:09 »

@Gingerious

Great sketch!
I laughed so hard at your post I started crying.

It really hit close to home. Thank you!


"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline Gingerious

Junior Member


Medals: 2



« Reply #27 - Posted 2011-10-27 15:57:35 »

Yeah, I found that sketch online and it fits in so many situations.

After changing the Ms to ms, everything worked just fine and I could access the booleans I created using an instance of the class that I've added to the canvas.  Thanks guys!
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #28 - Posted 2011-10-27 22:17:24 »

@philfrei
That sketch is actually quite a popular meme online Wink

@Gingerious
ROLFMAO at your post, glad to help Smiley

EDIT: Adding another option to Riven's post, you could just implement MouseListener instead of extending MouseAdapter and it would have told you about missing methods Cheesy

Offline h3ckboy

JGO Coder


Medals: 5



« Reply #29 - Posted 2011-10-28 07:13:23 »

yeah, I am iwht ra4king, I've always used listener. Another good thing about it, is if you need to extend something else, cuase if you're extending MouseAdapter ur stuck iwth just htat. Although in the code u ahve there it looks like it won't matter, but some other time it might Smiley.

I think that all programmers should have that meme with them at all times, cause I cant count the number of times I've spent hours looking for a bug, and like found that I mispelled something, or like I accidentally put a semicolon where is shouldn't be.
Pages: [1] 2
  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.

pw (22 views)
2014-07-24 01:59:36

Riven (20 views)
2014-07-23 21:16:32

Riven (17 views)
2014-07-23 21:07:15

Riven (20 views)
2014-07-23 20:56:16

ctomni231 (48 views)
2014-07-18 06:55:21

Zero Volt (44 views)
2014-07-17 23:47:54

danieldean (35 views)
2014-07-17 23:41:23

MustardPeter (38 views)
2014-07-16 23:30:00

Cero (53 views)
2014-07-16 00:42:17

Riven (52 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!