Monday, April 14, 2014

Making Breakout for JAVA

This is the game we will be making.

Breakout is a simple paddle-and-ball game developed in the 70s by Steve Wozniak, and designed by Steve Jobs. It features a simple paddle, deflecting a ball into an array of bricks. It is an incredibly simple game, and thus is usually the first or second game, alongside Pong, that is developed when getting accustomed to a new library or language. Since the game uses the same mechanics as Pong, we can reuse much of our earlier Pong code in order to make this game.

An Improved Entity Manager Class

In the last game, Pong, we used a simple Entity Manager that could manage all of our Entities and handle the drawing and logic of each and every one. In this game, the Entity class is not much different save for a few new overloaded constructors and variables that allow us to add color to our blocks individually, while also giving them points.

package _breakout;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

public abstract class Entity {

protected int x;
protected int y;
protected double dx;
protected double dy;
protected int height;
protected int width;
protected float colorRed, colorGreen, colorBlue;
protected int points;
protected static List<Entity> entities = new ArrayList<Entity>();
protected static List<Entity> garbage = new ArrayList<Entity>();
protected Rectangle bounds = new Rectangle();
public Entity(int x, int y, int height, int width) {
entities.add(this);
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.dx = 0;
this.dy = 0;
this.colorRed = 1.0f;
this.colorGreen = 1.0f;
this.colorBlue = 1.0f;
}
public Entity(int x, int y, int height, int width, float colorRed, float colorGreen, float colorBlue) {
entities.add(this);
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.dx = 0;
this.dy = 0;
this.colorRed = colorRed;
this.colorGreen = colorGreen;
this.colorBlue = colorBlue;
}
public Entity(int x, int y, int height, int width, float colorRed, float colorGreen, float colorBlue, int points) {
entities.add(this);
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.dx = 0;
this.dy = 0;
this.colorRed = colorRed;
this.colorGreen = colorGreen;
this.colorBlue = colorBlue;
this.points = points;
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

public double getDx() {
return dx;
}

public void setDx(double dx) {
this.dx = dx;
}

public double getDy() {
return dy;
}

public void setDy(double dy) {
this.dy = dy;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}
public void update(int delta){
}
public void draw(){
}
public void logic(){
}
public void destroy(){
garbage.add(this);
}

public boolean intersect(Entity e) {
return this.bounds.intersects(e.bounds);
}

}

As you can see, we also updated the destroy method. I apologize for the inclusion of an inferior method in the Pong code. Since we didn't use it at all, I didn't notice that it was calling to destroy a list element during an iteration (our update method iterates through the list of entities, so we cannot simply destroy them when we please). In this method, when we call for an entity to be destroyed, it is added to a garbage list of Entities. At the end of every update, the Entity Index checks itself against the garbage list and removes any entities that are queued for removal, then the garbage list is cleared. 

 New Ball Logic

Since the ball is the only entity on the screen that is constantly interacting with different elements on the screen, I decided to add most of the game logic into the ball's logic section. Now, for the initialization, I created two Entity lists: One for the collection of bricks, and one for the brick's own seperate garbage collection:

bricks = new ArrayList<Entity>();
bricksGarbage = new ArrayList<Entity>();

The reason I did this is so the ball would have an easier time checking for collisions on the bricks, since I only have to iterate over the bricks-ball intersections and check if it intersects with any of the stored coordinates in that list. This also means I have to have a seperate garbage list to destroy all of the collision coordinates or the ball would bounce off of random thin air.

//collision detection
for(Entity f : bricks){
if(ball.intersect(f)){
point += f.points;
f.destroy();
bricksGarbage.add(f);
ball.setDy(-dy);
ball.setDx(rand.nextInt(50)>25?(Math.abs(dx) + 0.03):-(Math.abs(dx) + 0.03));
}
        }

An interesting thing here is the ball's new setDx() method. Much like in the original Breakout!, the ball's speed will increase as it collides with more and more bricks, making the game harder as you reach the end. Instead of opting for a completely static Dynamic X like I did with Pong, here we use the Math.abs() function so we can get the current dx and manipulate that instead. We could go back to the Pong-styled setDy(), but this makes it feel like the player has more control over the ball with their paddle.

//bounds control
if(ball.getX() >= 640 || ball.getX() < 0){
ball.setDx(-dx);
} else if(ball.getY() <= 0){
ball.setDy(-dy);
} else if (ball.getY() >= 480){
gameStatus = gameState.WAITING;
playerLives -= 1;
System.out.println("You have " + playerLives + " lives left!");
System.out.println("You also have " + point + " points!");
paddle.setX(640>>1);
paddle.setY(460);
ball.setX((640>>1) + 25);
ball.setY(410);
ball.setDx(0);
}

As you can see here, I have also implemented Game States, which I will be going over in the main method. Here, our ball checks to see if it is past the point of no return. We then deduct a life from the player, print out their stats, then reset the ball and paddle's position while switching the current game state. It is a pretty simple addition.


Brick Creation Method

Because we are doing a brick-breaker game, we're gonna need some bricks. Fortunately, we can do this any number of ways, ranging to overcomplicated to incredibly rudimentary. I decided to go the over-complicated route:

private void createBlocks(){
for(int i = 1; i <= 6; i++){
for(int j = 1; j <= 4; j++){
if(j - 1 == 0){
bricks.add(new Box((100 * i) - 75, 5 + (35 * j), 30, 90, 1.0f, 0.0f, 0.0f, 100));
}
else if (j - 1 == 1){
bricks.add(new Box((100 * i) - 75, 5 + (35 * j), 30, 90, 1.0f, 1.0f, 0.0f, 750));
}
else if (j - 1 == 2){
bricks.add(new Box((100 * i) - 75, 5 + (35 * j), 30, 90, 0.0f, 1.0f, 1.0f, 25));
}
else bricks.add(new Box((100 * i) - 75, 5 + (35 * j), 30, 90, 0.5f, 1.0f, 0.5f, 5));
}
}
}

The first thing you may notice is the ridiculous formula I used to position the bricks. Essentially it can simplified to: (A * i) + X, (B * j) + Y, where X and Y are offsets. The reason I did this is strictly for aesthetic reasons only. I wasn't happy with the way the bricks looked when I used a multi-dimensional array, and I wanted to be able to offset the position of the bricks while still having control over the amount of pixels between each brick and the walls themselves. I literally over-complicated the heck out of this, but sometimes hackish solutions work out in the end.

This method simply loops through 6 columns and 4 rows and creates a new Brick depending on the row that it is in. Higher rows contain more points than lower rows, and each row has their own color of bricks. Like I said before, you can do the same thing using a multidimensional array, so not too much to see here.

Our New Main Game Loop

Since we added in gamestates, we need a way to manage those gamestates. To do that, we use our trusty game loop to manage the different states and key combinations that take us into each one. A game state is simply which point in our game hierarchy our game is currently in. For instance, we could have one level for the menu, the next one would be the overworld, and the third could be the credits screen. Each of these states have different code execution formats and thus we set up and enumerator that allows us to check if we are in any of these states.

//main loop
while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT);
//Input checking
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
Display.destroy();
System.exit(0);
}
if(Keyboard.isKeyDown(Keyboard.KEY_RETURN) 
&& gameStatus == gameState.WAITING){
gameStatus = gameState.PLAYING;
}
//Draw
drawAll(Entity.entities);
//Game State checking
if(gameStatus == gameState.PLAYING){
updateAll(getDelta(), Entity.entities);
}
if(gameStatus == gameState.WAITING 
|| gameStatus == gameState.END){
getDelta();
}
if(bricks.isEmpty() 
&& gameStatus == gameState.PLAYING){
gameStatus = gameState.WIN;
}
if(playerLives == 0 
&& gameStatus == gameState.WAITING){
playerLives--;
gameStatus = gameState.LOSE;
}
if(gameStatus == gameState.LOSE){
System.out.println("You Lose!");
gameStatus = gameState.END;
}
if(gameStatus == gameState.WIN){
System.out.println("You Win! Points: " + point);
gameStatus = gameState.END;
}
Display.update();
Display.sync(60);
}
Entity.entities.clear();
bricks.clear();
Display.destroy();
//destroy display

This isn't too interesting -- we are simply managing the state of our game here. One thing I do want to point out, though, is the fact that we only update our entities when we are playing the game, and if we aren't updating, we are still getting our delta. The reason we do this is because our delta function resets when we call getDelta(), but if we do not call it, then the delta will increasingly rise over time, and the next time we resume gameplay our entities will be all over the place because they technically were updating in the background. This would defeat the whole purpose of using delta, so we make sure to call it in every frame that we do not update.

That is Breakout! ladies and gentlemen. Since we completed Pong, many of the things we learned in that game were brought into this one. Likewise, we can bring many of the Breakout! elements into games such as Space Invaders, which I will covering next time, and even R-Type or Galaga. The Shoot-em'-up genre is heavily based on these mechanics so we could potentially make any shoot-em'-up we wanted to. However, I first want to go over Sprite animation, Audio managing, and improving our game states. So, until next time!

Remember, if you have any questions about the code, please do not be afraid to leave a comment requesting assistance. And as always, the source code can be downloaded from the link below:

Saturday, April 12, 2014

Making Pong for JAVA

This is the game we will be creating


Pong. It's a pretty simple game -- you have two paddles, the player controls one of them and the AI controls the other, all in a game of don't-miss. It is usually the first or second game you would make after learning the fundamentals of a language or library (sometimes Tic-Tac-Toe is first). Using LWJGL doesn't make coding this game much easier, since the focus is primarily on the logic in this one. It does, however, make setting up the screen and drawing things a whole lot quicker.

LWJGL and OpenGL Initialization

When I program in JAVA, I usually add in comments to set up a simple template for me to follow, so all I have to do is fill in the blanks. It helps me remember what the initialization code is for the library I'm using and things like that. The order is as follows:

//import - this is where you would statically/import all the libraries you need
//display - Display.setDisplayMode etc would go here
//ogl - setting glMatrixMode 
//main loop - our main game loop
//destroy display - destroy our display
main - this is where we call our game loop by invoking new Main()

Fleshed out, it would look something like this:

//import
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.LWJGLException;

public class Game(){
    //display
    try{
        Display.setDisplayMode(new DisplayMode(HEIGHT, WIDTH));
        Display.setTitle("Game");
        Display.create();
    } catch(LWJGLException e){
        e.printStackTrace();
    }
    //ogl
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, HEIGHT, WIDTH, 0, 1, -1);
    glMatrixMode(GL_MODELVIEW);

    //main loop
    while(!Display.isCloseRequested()){
        
        glClear(GL_COLOR_BUFFER_BIT);

        Display.update();
        Display.sync(FPS);
    }
    Display.destroy();
    //destroy display

    public static void main(String args[]){
        new Game();
    }

}


Pretty straightforward.

Managing Entities in our game - the Entity Class


For Pong, the first important thing we need to do is set up a simple way that we can handle all the objects. From drawing them to the screen, to updating their x and y position, it would be nice if we could make a superclass that manages this for us. This is where the Entity class comes in:

package _pong;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

public abstract class Entity {

protected int x;
protected int y;
protected double dx;
protected double dy;
protected int height;
protected int width;
protected static List<Entity> entities = new ArrayList<Entity>();
protected Rectangle bounds = new Rectangle();

public Entity(int x, int y, int height, int width) {
entities.add(this);
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.dx = 0;
this.dy = 0;

}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

public double getDx() {
return dx;
}

public void setDx(double dx) {
this.dx = dx;
}

public double getDy() {
return dy;
}

public void setDy(double dy) {
this.dy = dy;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public void update(int delta){

}

public void draw(){

}

public void logic(){

}

public void destroy(){
entities.remove(this);
}

public boolean intersect(Entity e) {
return this.bounds.intersects(e.bounds);
}


}

As you can see, this class doesn't really house anything fancy other than a bunch of getters and setters. The most interesting thing here that I will point out is the Entity Index at the top. That ArrayList will allow us to invoke Global methods on our Entities -- things like drawing and updating, which would be a pain to do for each individual entity in a game with many more objects. Getting this down now will help you much in the future when managing multiple entities on the screen. Essentially what it does is add the entity that has been created to a global list of entities. Anytime we want to do something involving every Entity, all we have to do is iterate over this list. You'll see how handy this is pretty soon.

Sub-Entity Classes: the Box Class

Normally, Entity is too broad a class if you have multiple entities on your screen that each behave differently. If we wanted to make a Sphere Entity and a Block Entity, it would be difficult creating them by calling a new Entity. Instead what we do is create Sub-classes that inherit from the Entity superclass. These sub-classes will each behave differently. but will all derive from the Entity class so they can be managed like any other Entity.

private class Box extends Entity{
public Box(int x, int y, int height, int width){
super(x, y, height, width);
}
public void update(int delta){
logic();
super.x +=  dx * delta;
super.y +=  dy * delta;
//bounds.setBounds(x, y, width, height);
return;
}
public void draw(){
glColor3f(0.9f, 0.7f, 0);
glRecti(x, y, x + width,y + height);
}

Again, really simple stuff here. We create a Box sub-class that extends the Entity superclass. The only way that Boxes differ from a generic Entity is the way that they are drawn to the screen and how they are updated. If you recall in the Entity class we have no method body for update() and draw(). These methods must be overriden by a subclass. 

In our update() method, we take as input an integer called delta, which may confuse some who have not seen it before. Motion interpolation is a technique that allows us to smoothly render objects to the screen by making use of a dynamic variable called a Delta. To perform this trick, the computer needs a variable that changes by a constant interval over a range of time. This is why many later games used what is called a System Clock that is ever-changing over a constant interval of time. By measuring the amount of time it takes to complete 1 cycle in the main loop, we can use that and base all of our update values on that time, thus updating the game as smoothly as the System Clock updates it's time. 

You will also notice a call to a method called logic(). This method is even more specific to each individual Box entity. It is the most specific Entity method we have, and one which we have created for this purpose.

Creating Box Entities: the Box, the Paddle, and the Opponent

This is where our logic() method will do nearly all of the work. We begin by creating the boxes themselves by instantiating some new Boxes. After that, we open up an Anonymous Class after our calls and override the logic() method.

ball = new Box(640>>1, 480>>1, 4, 4){
@Override
public void logic(){
//collision detection
//top half of paddle
if(ball.intersect(paddle)){
if(ball.y <= paddle.y +(paddle.height/2) 
&& ball.y >= paddle.y){
ball.setDx(-1 * ball.dx);
ball.setDy(-0.4);
} else if(ball.y <= (paddle.y) + paddle.height
&& ball.y >= paddle.y +(paddle.height/2)){
ball.setDx(-1 * ball.dx);
ball.setDy(0.4);
} else {
ball.setDx(-1 * ball.dx);
ball.setDy(-0.4);
};
}
if(ball.intersect(opponent)){
if(ball.y <= opponent.y + (opponent.height/2) 
&& ball.y >= opponent.y){
ball.setDx(-1 * ball.dx);
ball.setDy(-0.4);
} else if(ball.y <= (opponent.y) +opponent.height
&& ball.y >= opponent.y +(opponent.height/2)){
ball.setDx(-1 * ball.dx);
ball.setDy(0.4);
} else {
ball.setDx(-1 * ball.dx);
ball.setDy(-0.4);
};
}
//bounds control
if(ball.y > 480 || ball.y < 0){
ball.dy *= -1;
}
else if (ball.x > 640 || ball.x < 0){
ball.dx *= -1;
}
//speed control
if(dy > 1){
dy = 1;
} else if (dy < -1){
dy = -1;
}
}
};
paddle = new Box(20, 10, 60, 5){
@Override
public void logic(){
if(Keyboard.isKeyDown(Keyboard.KEY_S)){
setDy(0.5);
}
else if (Keyboard.isKeyDown(Keyboard.KEY_W)){
setDy(-0.5);
}
else setDy(0);
}
};
opponent = new Box(610, 10, 60, 5){
@Override
public void logic(){
if(ball.getY() >= y+(height/2)){
dy = 0.4;
}
else if (ball.getY() <= y+(height/2)){
dy = -0.4;
}
else dy = 0;
}
};

I know it's a bit compact, but you can always review the source code directly. Anyhow, you can see the paddle and opponent Entities are pretty small. They only contain the code that moves them up and down and it's pretty lazily done, I admit. But the ball class - now that's a monster! The reason for that is the collision detection that checks if the ball has hit the upper or lower half of the paddles themselves. Essentially, the math works like this:

If the ball's Y position is greater than the top of the paddle, but less than the middle of the paddle, then fling that sucker upwards. However, if it is greater than the middle of the paddle, and less than the bottom of the paddle, then send it flying downwards. 

Simple, no? I added a few checks that I could afterwards should I decide to edit anything in there including the bounds control, which ensures the ball is always on the screen, and the speed control, which ensures the ball is never going too fast in one direction or the other.

The Incredibly Simple Main Loop

while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT);
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
Display.destroy();
System.exit(0);
}
line.draw();
paddle.draw();
ball.draw();
opponent.draw();
updateAll(getDelta(), Entity.entities);
Display.update();
Display.sync(60);
}

That, ladies and gentlemen, is Pong! In our main loop, we simply draw all of the Entities, and then we call our updateAll function utilizing the Entity Index I mentioned earlier. In future projects, I decided to also revamp the draw() method into a drawAll() method that does essentially the same thing, but I tried not to edit anything in my old code. For completion's sake, here is the updateAll() method:

private void updateAll(int delta, List<Entity> l){
for(Entity f : l){
f.bounds.setBounds(f.x, f.y, f.width, f.height);
f.update(delta);
}
}

If you need to see the source code, here is the link to it:


If you have any issues with the code that you need help with, leave a comment, I will answer it as soon as I can.

Hello and Welcome to my Blog!

Hello, my name is Nausicai and I am a game designer and computer programmer. In my spare time, I like to recreate older video games and analyze what design elements went into them. Sometimes I make games for fun, or maybe if I have a little extra time, I put more effort into the games I make. My favorite games include JRPGs and Action-Adventure games, because I am huge fan of exploration and story exposition. I also love Rhythm and Bullet Hell games for mobile and handhelds.

I will usually post source code for the games I write up, as well as answer any questions pertaining to the source itself. I program in Java using the LWJGL, but not exclusively.