Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (498)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
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  
  Your first game! (adventure/rpg like)  (Read 26418 times)
0 Members and 2 Guests are viewing this topic.
Offline elamre

JGO Coder


Medals: 17
Projects: 1


hitar!


« Posted 2012-02-21 16:24:04 »

[size=14pt]Introduction[/size]
Dynamic
This will be a dynamic tutorial, meaning that I will keep changing and editing it on the demand of the users. So this tutorial will probably never finish (Unless I'm getting bored of writing it). Also, this tutorial will probably never be totally finished.
I'm not perfect
I'm not perfect, like almost everybody. First of all, I'll probably have a large amount of spelling mistakes, and grammar incorrectness. Second, my code might be obsolete and badly written. But at least I can assure you that it will work! If you see anything that I could've done different, then please say so! So that I can change the tutorial to a better version
Coverage
I will cover a few aspects of a basic adventure/RPG game. Of course the aspects can be used in almost every game!

[size=14pt]Basic thoughts [/size]
Classes & Roles
The first thing i mostly do when designing a game, is thinking of a data-flow. Why? Because while doing this it will give you a much better vision what you should do, how you want the data to go, and the most important bit, what classes you will need. Ive made a simple one quickly (Also, my paint skills are medal worthy! :p

With send image, i more mean retrieve image. Now we can prepare our classes. As you can see we need a couple of classes:

Main
This class will basically start the whole process. The engine will keep running in the background. Meaning that we will have to make it a threat (multithreading). However we need to start this thread from some place, we will start the thread in the main (you could also do it in the engine class itself, but I like it a bit more ordered. So go ahead, make a new class, and call it main. Now be sure to generate the Main(arg) function with it as well! If, for some reason, you cant generate the Main, copy and paste mine(this is my entire main class):
1  
2  
3  
4  
5  
6  
 public class Main{
     public static void main(String [] args){
        System.out.println("Application, started!");
      }
}
 

Now we’ve got our first class. But in order to start our engine class, we first have to make it multithread compatible. Ill cover this in the next class.

Engine
This class will make sure everything will get updated every tick. And will make sure that the screen will render when its necesary. First of all, engine is a name not used often for this purpose)because an engine could be anything, it could be the engine of a car. Or used for inheritance (being the superclass). So let’s give it a different name, Game would fit for this purpose. So go ahead and make a new class, called Game. First we will have to make it multithreading in some way, there are multiple ways of doing this. You can either extend your class with the class Thread, so you can use its functinos trough inheritance. Or you can implement Runnable. I will go for runnable, there is however no difference between these two(as far as im concerned). So what you have to do now is implement Runnable. Your class should now look something like this:
1  
2  
Public class Game implements Runnable{
}

Now because we implemented runnable, we have a new function to use. Namely run(). This function will have to be a loop, which will update the game according to its game-state. Now for the time being, make It an endless ‘while’ loop, with an println function in it. Just for testing purposes. It should be along the lines of:
1  
2  
3  
4  
5  
6  
public class Game implements Runnable{
public void run(){
    while(true)
    System.out.println(" While ! ");
}
}

But now we have to start the thread. If you look back to our dataflow, you see that this will be the purpose of my main class. You can start an object of a class really easily! All we have to do is declare our object, and then execute the run() function. The execution of the run function is done a little bit different, instead of using: object.run(); we will use object.start(). This will start the thread and the whole process. You should have this now:
1  
2  
3  
4  
5  
6  
 public class Main{
     public static void main(String [] args){
         Game ex = new Game();               //Creates new object of type Game, and name it ex.
        new Thread(ex).start();            //Start this so called ex object.
     }
}

Now as you start your application, it will automaticly start the game thread. Which will keep printing out messages as you can see. This is the first step of our tutorial. I will explain what we will do here later on.

Player
This class will be the player, it will react on Key presses (move in the right direction) and it will check for collisions. It will update every tick from the engine. How we will do these things I shall explain later. Before we make our player class, let’s think for a moment what we need in it. First of all we need to be able to retrieve the location of the player (x,y) for drawing purposes. Secondly we need an update function which will move the player, if it has to be moved, which will attack, if it has to attack, and which will check if the player is actually still alive. Thirdly we need 4 functions which can set the directions.
So our class will look like this:
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  
public class Player {
   //variables which we will use
  private int x, y;
   private boolean  left, right, up, down;

   
   public void update() {
   //In this function we will do the required checking and updates
   }
   
   //These 4 functions are able to set the direction
  public void setLeft (boolean newLeft  ){
      left  = newLeft;
   }public void setUp   (boolean newUp   ){
      up    = newUp;  
   }public void setDown (boolean newDown ){
      down  = newDown;
   }public void setRight(boolean newRight){
      right = newRight;
   }
   //This function will return X as an int.
  public int getX(){
      return x;
   }
   //And this function will return Y as an int.
  public int getY(){
      return y;
   }
}

Now we’ve got the basics. But the player wont move with this just yet. For that we need a move function. So lets do this, we will make a simple move function. We will make it private, since there is no need for other classes to acces it, and i twill be of type void ofcourse, since there is nothing to return in this function.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
   //In this function we will do the required checking and updates
  public void update() {
      move();
    }
   //This function will move the player according to its direction
  public void move(){
      if(left){
         x--;
      }if(right){
         x++;
      }if(up){
         y--;
      }if(down){
         y++;
      }
   }

This will work, will be very buggy, but it will work. I’ll explain a more advanced movement system later on, which wont be very buggy.
 
Instances
This class will contain the arrayLists to objects. Why? Because we have to retrieve information about our objects somewhere, but at the same time we’ll also need to add new objects to the same arrayList. So we will have to make them static. But we don’t only need arrayLists. We also need to add our player here. Lets do that first. First of all, create a class and name it Instances. You’ll end up with something like this:
1  
2  
public class Instances {
}
Now we have our class. Lets add our first object to it! We want to add the player first. This can be done very easily with the following line:
1  
   public static Player player = new Player();

You should add this line in the body of your instances class.

Now we can acces it from anywhere we want. All we have to do is: Instances.player.[function here];.
Later on I will explain what more objects we need in this class, and how we have to handle that. But for now this is enough.

Input Manager
This class will handle the input. We want to make our player move, as soon as we hit the up arrow on the keyboard. But how is this done? Don’t worry! Java has a lot of functions and classes build in already. It even has a class which will handle key input! All we have to do if check if the key input is being pressed or released. And what key this might be. So lets go and make our ButtonHandler class! First in order to use the easy functions, we will have to inherite the java class “KeyAdapter” and we will have to import 2 headers. Your class should now look like this:
1  
2  
3  
4  
5  
6  
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class ButtonHandler extends KeyAdapter {
               
    }
Now i like it to have some debugging in it as well, so i added a constructor, with a simple System.out.println(“”); in it. So go ahead and add the following to your class:
1  
2  
3  
    public ButtonHandler() {
       System.out.println(" Button handler initialised! ");
}

Now as soon as we make an object from this class, a message will pop up in our eclipse.
Now in order to make use of our KeyAdapter, we will have to add 3 functions. 2 of the 3 we will use. Add the following functions:
1  
2  
3  
4  
5  
6  
7  
8  
9  
   public void keyTyped(KeyEvent arg0) {
   //This one we wont use. Its unreliable for making a game handler      
  }
    //This function will be used as soon as a key is released. they KeyEvent key we can use to determine what key we just released
   public void keyReleased(KeyEvent key) {
    }
  //This function will be used as soon as a key is pressed.
   public void keyPressed(KeyEvent key) {
    }

Now in order to determine what kind of key we just pressed/released, we will need a couple of statements. Or we could use the switch statement. I prefer to use the switch statement because your program will look much more organised then. Basicaly if we press the left arrow key, then the keycode from ‘key’ from KeyEvent will be equal to VK_LEFT. So we need something along the lines of:
1  
2  
3  
If(key.getKeyCode == VK_LEFT){
Instances.player.setLeft(true);
}

And in the key release function it would be:
1  
2  
3  
If(key.getKeyCode == VK_LEFT){
Instances.player.setLeft(false);
}

So this brings us to the following code:
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  
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class ButtonHandler extends KeyAdapter {

    public ButtonHandler() {
       System.out.println(" Button handler initialised! ");
               
    }
  //This function will be used as soon as a key is released.
   public void keyPressed(KeyEvent key) {
       
              switch (key.getKeyCode()) {
                        case KeyEvent.VK_UP:
                           Instances.player.setUp(true);
                             break;
                        case KeyEvent.VK_DOWN:
                           Instances.player.setDown(true);
                            break;
                        case KeyEvent.VK_LEFT:
                           Instances.player.setLeft(true);
                            break;
                        case KeyEvent.VK_RIGHT:
                           Instances.player.setRight(true);
                            break;
              }
    }  
    //This function will be used as soon as a key is released. they KeyEvent key we can use to determine what key we just released
   public void keyReleased(KeyEvent key) {
        switch (key.getKeyCode()) {
           case KeyEvent.VK_UP:
              Instances.player.setUp(false);
              System.out.println(" Released UP!");
                break;
           case KeyEvent.VK_DOWN:
              System.out.println(" Released DOWN!");
              Instances.player.setDown(false);
               break;
           case KeyEvent.VK_LEFT:
              System.out.println(" Released LEFT!");
              Instances.player.setLeft(false);
               break;
           case KeyEvent.VK_RIGHT:
              System.out.println(" Released RIGHT!");
              Instances.player.setRight(false);
               break;
        }
    }
   
   
   public void keyTyped(KeyEvent key) {
     
   }
}

However, we still need to make the object somewhere. We will do this as soon as our screen is getting initialized. I will cover this in the next class.


 Draw
Ok, most of the basic game play is done. But now we want to draw it to the screen! First of all we need to make the class. So go ahead and make a new class and call it Draw. Also make a constructor in it, we will use this for setting up everything. It should be like this:
1  
2  
3  
4  
public class Draw{
   Draw(){
              }
}

Now we will prepare our screen so that we can draw on it. We will do this in Java2D. But you can of course also follow another tutorial for this which will cover other libraries. I wont cover much of the drawing, since its library based. So instead i will post some code and comment it (Unless people really want me to explain in detail). This is what my Draw class looks like(taken from another tutorial on this site, i believe written by either ra4king or riven. props to them! Smiley ):
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  
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;

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


public class Draw{
   JFrame frame;
   Canvas canvas;

   BufferStrategy bufferStrategy;

   private int WIDTH = 640;
   private int HEIGHT = 480;

   Draw(){
      //Makes a new window, with the name " Basic 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);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
                             //this will make the frame not re-sizable
     frame.setResizable(false);
      frame.setVisible(true);
                             //this will add the canvas to our frame
     panel.add(canvas);
      canvas.createBufferStrategy(2);
      bufferStrategy = canvas.getBufferStrategy();
                            //This will make sure the canvas has focus, so that it can take input from mouse/keyboard
     canvas.requestFocus();
                             //this will set the background to black
     canvas.setBackground(Color.black);
      // This will add our buttonhandler to our program
     canvas.addKeyListener(new ButtonHandler());
      }
   void render() {
      Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
      g.clearRect(0, 0, WIDTH, HEIGHT);
      render(g);
      g.dispose();
      bufferStrategy.show();
   }
   protected void render(Graphics2D g){
      //Here we will render everything
  }
}

Now we want to draw a rectangle on the place where our player is. Why a rectangle? Because this is easy to set up, easy to draw and easy for debugging. Later in this tutorial i will explain how to work with images. Java2d has a fairly easy function to draw a rectangle, namely the following:
1  
g.fillRect(X position, Y position, Length, Height)

For this example we will use a fixed length and height, we will set it to 15. Now we also need to give it a color. That can be done by:
1  
g.setColor(Color.white)

Now we need to draw it at the player's x and y coordinates. How can we do this...?
Remember that we made the player in the Instances class static? we can easily aces it from anywhere now. All we have to do is:
1  
Instances.player.getX();

and
1  
Instances.player.getY();

So lets go ahead and do that. your render(Graphics2D g) should end up looking like this:
1  
2  
3  
4  
   protected void render(Graphics2D g){
      g.setColor(Color.white);
      g.fillRect(Instances.player.getX(), Instances.player.getY(), 15, 15);
   }
Now this is done. Lets move on and make sure everything will get updated! Smiley

Game-Loops
So we have got our classes now. But now we have to make sure the player gets updated every once in a while. For now, lets do it VERY simple and VERY wrong. This code wont serve well, at all. In my next update I will cover a good game loop, which is stable, efficient and which will have the same effect on all computers, fast or slow.
Remember that we made our Game class? Now go back to there. In the run you'll find a while(1) System.out.println(“Thread”);
But instead of printing a line to the console, we want to move our player! Remember that our Instances class has a static Player object? we will update this one every 10 milliseconds. It is actually fairly easy. All you have to do is change:
1  
2  
3  
4  
public void run(){
    while(true)
    System.out.println(" While ! ");
}
into:
1  
2  
3  
4  
5  
6  
7  
public void run(){
    while(true){
    Instances.player.update();
    try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
   }
   
}
Now this is VERY inefficient. Also you will see that it wont work! you wont see the player moving. This is because we also have to draw everything on the screen. For this we will have to make an object of type Draw. this is easily done by adding this in the Game class:
1  
Draw drawing = new Draw();

Now the last thing we have to do, is actually make it render once in 10 seconds as well. This is easily done by adding the following line to our while loop:
1  
drawing.render();
. Our final run function will look like this:
1  
2  
3  
4  
5  
6  
7  
8  
public void run(){
    while(true){
    Instances.player.update();
    drawing.render();
    try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
   }
   
}


If enough people comment on this (so that i actually know that people want to know how it goes on) then I'll have the next part done on Friday! Smiley
 Also, don't forget to give me a nice medal if this helped you!
And many thanks for JGO. where i learned a lot about this, and got some code off as well.
Future ideas to implement in the tutorial (i already have written code for this, but its not very efficient. So ill make more efficient code for this):

[size=14pt]Map [/size]
Drawing a map
Readying from a text file
Map Manager
setting up the map, map manager etc

My projects:
Tower Defence!]http://www.java-gaming.org/topics/iconified/25690/view.html]Tower Defence! [lll.......] 30%!
Lightsnakerider! [llllll....] 60%!
Offline Regenuluz
« Reply #1 - Posted 2012-02-21 19:47:42 »

Well go on, make it! I know I'd read it and try it out! So go go go! Cheesy
Offline elamre

JGO Coder


Medals: 17
Projects: 1


hitar!


« Reply #2 - Posted 2012-02-21 19:56:44 »

Yes im working hard on it Smiley.

My projects:
Tower Defence!]http://www.java-gaming.org/topics/iconified/25690/view.html]Tower Defence! [lll.......] 30%!
Lightsnakerider! [llllll....] 60%!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline elamre

JGO Coder


Medals: 17
Projects: 1


hitar!


« Reply #3 - Posted 2012-02-21 21:16:51 »

Ok, basics are covered (real basics). Im curious what people come with! So if you made anything after following this tut, post a screenshot of it! Wink
Also if there are any requests, i'll gladly take them! Smiley

My projects:
Tower Defence!]http://www.java-gaming.org/topics/iconified/25690/view.html]Tower Defence! [lll.......] 30%!
Lightsnakerider! [llllll....] 60%!
Offline Crisiszone

Senior Newbie





« Reply #4 - Posted 2012-02-21 23:04:45 »

Keep up the good work! This is fantastic and very helpful Tongue
Offline sproingie

JGO Kernel


Medals: 202



« Reply #5 - Posted 2012-02-21 23:13:28 »

I hate to be the mean negative downer guy but if you're going to post tutorial code, you should be writing proper multithreaded code, and you're doing stuff like drawing from outside the EDT.   Then there's other stuff like catching all exceptions and just printing their stack trace and continuing on. 

At this point, I have to say DO NOT RECOMMEND as a tutorial goes.  If you're going to evolve code to eventually be correct, this isn't the board to do it in.
Online Riven
« League of Dukes »

JGO Overlord


Medals: 799
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2012-02-21 23:33:10 »

(temporary) moved to this board, after discussing it with elamre

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline elamre

JGO Coder


Medals: 17
Projects: 1


hitar!


« Reply #7 - Posted 2012-02-22 10:12:59 »

I hate to be the mean negative downer guy but if you're going to post tutorial code, you should be writing proper multithreaded code, and you're doing stuff like drawing from outside the EDT.   Then there's other stuff like catching all exceptions and just printing their stack trace and continuing on. 

At this point, I have to say DO NOT RECOMMEND as a tutorial g.oes.  If you're going to evolve code to eventually be correct, this isn't the board to do it in.


Hmm that was a bit harsh, you could have said it differenty. But oh well.
On your responce, thanks for the feedback anyway. I talked to Riven and he moved it out of the tutorial section.
However, there is a reason why you are not learning complicated math at your first school, little steps at first. This was meant to be a tutorial on the basics of the basics. Sure i can go ahead and write complicated code. But people wont understand the basics then. Yeah i could have done it better then only printing the stack. But since i wanted to expand that part to a more advanced part, it seemed not necesary to me at the moment. Sure i couldve used a swing worker or something in that direction, for the 0,1 times it goes wrong.
But youve made your point.

My projects:
Tower Defence!]http://www.java-gaming.org/topics/iconified/25690/view.html]Tower Defence! [lll.......] 30%!
Lightsnakerider! [llllll....] 60%!
Offline sproingie

JGO Kernel


Medals: 202



« Reply #8 - Posted 2012-02-22 16:24:03 »

I know, it was a bit harsh, I just felt I had to make it clear to everyone else while it was in the tutorial section, since the EDT stuff is a big no-no, and active rendering in general in swing is iffy at best (swing already has a render loop of its own).  So I kept it short, and short meant brusque.  Sorry about that   Emo

I do hope you keep at it and turn the code into a solid tutorial once the kinks are ironed out.  I just think the tutorial section and article format is not a good place for that sort of thing (actually I'm not sure I see the point in the Article format in SMF at all, but maybe that's just me)
Offline Regenuluz
« Reply #9 - Posted 2012-02-29 17:47:09 »

When's the map stuff coming up? (That's the part I find the most interesting, tbh.)

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

Senior Member


Medals: 7


Indie Games FTW!


« Reply #10 - Posted 2012-03-03 21:18:17 »

I felt that joining this community was a good idea.
I know I was right!

Keep it up, great work!

Offline D34thSt4lker

Junior Newbie





« Reply #11 - Posted 2013-04-12 14:45:59 »

I know this is kind of old, but is there going to be a continuation on this?
Offline HeroesGraveDev

JGO Kernel


Medals: 254
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #12 - Posted 2013-04-12 21:13:11 »

I know this is kind of old, but is there going to be a continuation on this?

I doubt it.

Offline D34thSt4lker

Junior Newbie





« Reply #13 - Posted 2013-04-15 06:06:04 »

That really sucks... Was looking forward to seeing more tutorials on this...
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.

BurntPizza (20 views)
2014-09-21 02:42:18

BurntPizza (14 views)
2014-09-21 01:30:30

moogie (14 views)
2014-09-21 00:26:15

UprightPath (25 views)
2014-09-20 20:14:06

BurntPizza (27 views)
2014-09-19 03:14:18

Dwinin (42 views)
2014-09-12 09:08:26

Norakomi (73 views)
2014-09-10 13:57:51

TehJavaDev (97 views)
2014-09-10 06:39:09

Tekkerue (49 views)
2014-09-09 02:24:56

mitcheeb (70 views)
2014-09-08 06:06:29
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

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!