Jump to content
Sign in to follow this  
Mercenary

[TUT] Java Game Programming

Recommended Posts

Hello there

So I'm guessing that most likely, people would like to create a game with Java.
This isn't the easiest of things to, so I'll introduce you to JLWGL and Slick.
This library is short for Java Light Weight Gaming Library.

These are simple but very powerful libraries.

You can get them here:

[url]http://www.lwjgl.org/[/url]
[url]http://www.slick2d.org/[/url]

LWJGL is also used in Minecraft, as an example of what you can do with it.

You use the library by adding it to your Eclipse (Or your IDE) resources.
In Eclipse you do it like this:

You rightclick your project folder, and select properties.

You then proceed to click Java Build Path.

In Libraries, you click add external Jar and browse to lwjgl_util.jar and lwjgl.jar.
You'll also import slick.jar and slick-util.jar

And you're done.

Now, there's lots of tutorials on the sites of the libraries themselves, but they can be a little confusing for beginners.

I have made a main class for you to use,

[code]
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;


public class Game extends StateBasedGame {

public static final String gameName = "Java Game";
public static final int menu = 0;
public static final int play = 1;
public static final int xsize = 1280;
public static final int ysize = 720;
public static AppGameContainer frame;

public Game(String gameName) {
super(gameName);
this.addState(new Menu(menu));
this.addState(new Play(play));
}

public static void main(String[] args) {
try {
frame = new AppGameContainer(new Game(gameName));
frame.setDisplayMode(xsize, ysize, false);
frame.setVSync(true);
frame.setResizable(false);
frame.setIcons(new String[] {"res/icon32.png", "res/icon32.png", "res/icon16.png"} );
frame.setShowFPS(false);
frame.start();
} catch(SlickException e) {
e.printStackTrace();
}
}

public void initStatesList(GameContainer gc) throws SlickException {
this.getState(menu).init(gc, this);
this.getState(play).init(gc, this);
this.enterState(menu);
}

}
[/code]

(Conventions are gone due to the forums, sorry)

The icons lead to the project folder, in a folder names res, it'll look for the same names, the numbers in it stand for how big they are (32x32 or 16x16).

Let's perform an autopsy on the code I made:

[code]
public class Game extends StateBasedGame {
[/code]

This extends StateBasedGame so we can use the states from the Slick library, this needs the imports above this code.

[code]

public static final String gameName = "Java Game";
public static final int menu = 0;
public static final int play = 1;
public static final int xsize = 1280;
public static final int ysize = 720;
public static AppGameContainer frame;
[/code]

gameName defines the name of our game, as it suggests. This String will be used when naming our frame.

meny and play are ints to make it easier to see which gamestate we are going to, so when you see menu or play, it'll return that Integer.

xsize and ysize define the size of our frame.

public static AppGameContainer frame; this'll just tell our program to use an AppGameContainer whis we refer to as frame, that'll be our frame, of course.

[code]

public static void main(String[] args) {
try {
frame = new AppGameContainer(new Game(gameName));
frame.setDisplayMode(xsize, ysize, false);
frame.setVSync(true);
frame.setResizable(false);
frame.setIcons(new String[] {"res/icon32.png", "res/icon32.png", "res/icon16.png"} );
frame.setShowFPS(false);
frame.start();
} catch(SlickException e) {
e.printStackTrace();
}
}
[/code]

this is the first piece of code that gets called after initializing our variables,
I surrounded this in a try/catch because if anything goes wrong, it'll be able to tell us what.

frame = new AppGameContainer(new Game(gameName));
This tells the program that the frame we defined earlier, has to create a new appegamecontainer, which creates a new Game with our gameName.

frame.setDisplayMode(xsize, ysize, false);
This gives our frame a size, these sizes were defined earlier. The boolean stands for fullscreen or not.

frame.setVSync(true);
This isn't necessary, but useful. This will lock our frames per seconds to around 30, that's as much as the human eye should be able to see so it shouldn't matter, just increase performance.

frame.setResizable(false);
This explains itself, we won't be able to resize the window.

frame.setIcons(new String[] {"res/icon32.png", "res/icon32.png", "res/icon16.png"} );
The default Icons would be Slick's icons, you can replace this by creating your own.

frame.setShowFPS(false);
This is also optional, it just hides our FPS.

frame.start();
After setting everything we need up, it's time to start our frame up, without this, nothing would happen.

[code]
public Game(String gameName) {
super(gameName);
this.addState(new Menu(menu));
this.addState(new Play(play));
}
[/code]

this is called in the first line of our main, change Game to whatever your file is called, that's why it does not have void, string, integer, boolean or anything.

super(gameName); this has to be there, otherwise you'll get an error that the super constructor is undefined. (Names our game)


this.addState(new Menu(menu));
this.addState(new Play(play));
This adds 2 states of our game, the menu, and the play state. This NEEDS a class named Menu and a class named Play in this case. notice how menu and play are here, this refers to the integers we defined earlier.

[code]

public void initStatesList(GameContainer gc) throws SlickException {
this.getState(menu).init(gc, this);
this.getState(play).init(gc, this);
this.enterState(menu);
}[/code]

This, as it says, inits our states and assigns it to the gamecontainer.
So once again, our integers menu and play are called.

this makes the game aware that these states are there and loads them.

this.enterState(menu);
this will get us directly to the menu state (0).

Creating a state class

[code]
public class Menu extends BasicGameState {

Image play;
Image exit;
public String mouse;

public Menu(int state) {

}

@Override
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
play = new Image("res/menu/playNow.PNG");
exit = new Image("res/menu/exitGame.PNG");
}

@Override
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {



g.drawString("Java Game", 560, 50);
play.draw(495, 100);
exit.draw(495, 170);
g.drawString("Mouse coordinates: " + mouse, 50, 62);


}

@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
Input input = gc.getInput();
int xpos = input.getMouseX();
int ypos = input.getMouseY();

if(!Mouse.isInsideWindow()) {
mouse = "No input";
} else {
mouse = "x: " + xpos + ", y: " + ypos;
}

if((xpos > 495 && xpos < 705) && (ypos > 100 && ypos < 150)) {
if(input.isMouseButtonDown(0)) {
sbg.enterState(1);
}
}

if((xpos > 495 && xpos < 705) && (ypos > 170 && ypos < 220)) {
if(input.isMouseButtonDown(0)) {
System.exit(0);
}
}

}

@Override
public int getID() {

return 0;
}

}[/code]

This is a basic state, which we called Menu in our Game class.

[code]
public class Menu extends BasicGameState {
[/code]

This extends the BasicGameState so we can use things from that class.

[code]
Image play;
Image exit;
public String mouse;
[/code]

the first 2 are images.
The third line will be used to determine our mouse's coordinates on the screen. (Will come in handy to place images).


[code]
public Menu(int state) {

}
[/code]

This is necessary to tell our game class, that the Menu state is located here.

[code]
@Override
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
play = new Image("res/menu/playNow.PNG");
exit = new Image("res/menu/exitGame.PNG");
}
[/code]

this loads our images.
The images I used are here:

[img]http://i.imgur.com/jXmbDHZ.png[/img]

[img]http://i.imgur.com/EwIWXAc.png[/img]

[code]
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {
[/code]

this creates a constant loop to update the graphics.

[code]
g.drawString("Java Game", 560, 50);
play.draw(495, 100);
exit.draw(495, 170);
g.drawString("Mouse coordinates: " + mouse, 50, 62);
[/code]

The first line draws the text "Java Game" onto our screen at the coordinates 560;50.

The next two lines draw our images, which we defined in the init.

The next one displays our mouse String.

[code]
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
[/code]

this also creates a loop, but behind the scenes.
This will update code that won't directly be drawn on the screen.

[code]
if(!Mouse.isInsideWindow()) {
mouse = "No input";
} else {
mouse = "x: " + xpos + ", y: " + ypos;
}
[/code]

This updates our mouse string to our mouse's coordinates.

[code]
if((xpos > 495 && xpos < 705) && (ypos > 100 && ypos < 150)) {
if(input.isMouseButtonDown(0)) {
sbg.enterState(1);
}
}

if((xpos > 495 && xpos < 705) && (ypos > 170 && ypos < 220)) {
if(input.isMouseButtonDown(0)) {
System.exit(0);
}
}
[/code]

If you click within these coordinates, the code in the if statement gets executed, on our play, it goes to state 1 (which is play)
on the exit, it'll stop the program.

[code]public int getID() {

return 0;
}[/code]

this is VERY important, it returns which ID this state has, so other states can refer to it.

I won't cover the play state since it uses the exact same things as our Menu state.

I hope you learned from this :)

Credits;
JLWGL
Slick2D
I, for writing this tutorial. (Also known as Worldofwar or Chaosdevil)

Share this post


Link to post
Share on other sites
its LWJGL not JLWGL

Share this post


Link to post
Share on other sites
Good job so far, this will be useful to this community's audience and background (gaming, java).

However, I noticed a couple improvements worth suggesting:
[code]
public static final String gameName = "Java Game";
public static final int menu = 0;
public static final int play = 1;
public static final int xsize = 1280;
public static final int ysize = 720;
public static AppGameContainer frame;
[/code]

In general, constants should be capitalized. This makes constants very apparent in your code, and the more readability the better. So "gameName" should probably be something like "GAMENAME" or even "GAME_NAME". Also, always be mindful of your naming. Take the extra 2 or 3 seconds to think of a non-ambiguous descriptive name. A good principle to follow is that should be able to look at your code and know what's going on without having to dig around. So, something like "xsize" could more appropriately be named "GAME_WIDTH" or "FRAME_WIDTH" (the fact that I don't know which it is kind of makes my point).

Also, "public static" always smells bad if "final" doesn't immediately follow. You should encapsulate data whenever possible, and a large part of that is not exposing the innards of your objects. A general rule of thumb for this is to never expose a field unless it is constant. Not only does this help make your code more modular in that you have objects and operations on them, but it also prevents fields from being modified by the caller and causing unexpected behaviors in your code. Also, this gives you some more flexibility in that you can now have code execute on access and modification of a field.

Related to above:
[code]
Image play;
Image exit;
[/code]

Should probably be:
[code]
private Image playImage;
private Image exitImage;
[/code]

And if you need to access or modify them outside of this object then provide a getter/setter, but only as needed. In other words, don't provide a setter for a field that you don't intend to be modified.

The general idea comes down to eliminating any possible behaviors that aren't intended. Only expose what is necessary for the object to serve its intended purpose.



Also, since this is a tutorial I think I have the right to be picky about code format ;). You just need to insert some tabs (or 4 spaces if you want to be that guy) that were probably lost on copy and paste.



Anyway, Just some constructive suggestions I thought would help. Awesome tutorial so far and hope to see you contribute more :). Edited by Trey

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×