Bomberman

About the Game

Bomberman gameplay screenshot

The original Bomberman was released in 1983 for a selected group of computers in japan, but most people know about the 1985 release for the NES. In the game, you’re a robot who has to find his way through a maze with enemies and find a secret door hidden behind a brick that leads to the next level. While doing this you have to kill enemies with bombs who will kill you on contact. Once you kill all the enemies and enter the door, you go to the next stage. In my version, there’s one level that’s randomized, and there’s only 5 enemies. You can play it at the link below.

Link to the game on greenfoot.org http://www.greenfoot.org/scenarios/11621

Making the Arena

Bomberman arena pic

In the original Bomberman, there was an arena, so to make this arena I used block classes so it fit with the whole theme of the the game. Blocks are structures that can’t be destroyed or walked over. They form the main structure of the map.

The Code for this is easy for the grid blocks because they have a regular pattern, but its harder for the border, because it requires some irregular placement of blocks. This is the code for the Block grid spawning arrangement.

 int worldX = getWidth();
 int worldY = getHeight();
 int countX = 2;
 int countY = 2;
 boolean done = false;
 while (done == false){
    for (int i=2;i<worldX-2 ;i+=2){
       addObject(new Block(),i,countY);
       blockX.add(i);
       blockY.add(countY);
    }
    if (countY>=worldY-4){
    done=true;
    }
    else{
    countY+=2;
    }
 } 

 

 The Bricks

Brick-bigger

Because I chose to randomly spawn bricks instead of having pre-determined levels, I had to make sure that every scenario was playable. Firstly, I had to make sure they couldn’t spawn on top of each other or on top of blocks, so I wrote some pretty simple code for that.

for (int i=0;i<brickCount;i++){
   int randomX = (Greenfoot.getRandomNumber(worldX-2)) + 1;
   int randomY = (Greenfoot.getRandomNumber(worldY-2)) + 1;
   //calls checkXY to check if the selected cell is clear of bricks and blocks.
   if (checkXY(randomX, randomY) == true){
      brickX.add(randomX);
      brickY.add(randomY);
   }
   else{
      i-=1;
   }
}

There is one rare bug that I know of, where a brick will spawn on top of a block. This happens very rarely and I can’t find a reason for it, but i’m pretty sure its not in this segment of code.

 

The Player

BomberMan-bigger

The user is controlled by the WASD keys, and like anything else in this project, moves one cell at a time. The play can die if he is hit by either an enemy or a bomb explosion.  The moving of the man was pretty basic, as I just offset his location by 1. The process to check if he actually can move, however,  is a little more complex. I had to check to see if there was a bomb, brick, or block in any of the 4 directions to determine when and where he can move. I also ran into a problem in the early stages of this project when moving the man, where if i hit for example the “w” and “d” key at the same time, the man would move diagonal, into a block. To fix this I required the “w” and the “s” keys only to register if the “d” and the “a” keys weren’t pressed, that way he can’t move diagonally.

if ((w==true) && (d!=true) && (a!=true)...{
   setLocation(getX(), getY() - 1);
}

if ((s==true) && (d!=true) && (a!=true)...{
   setLocation(getX(), getY() + 1);
}

The Enemies

Enemy-bigger

Even though the enemies in this game are balloon looking creatures. they’re deadly nonetheless. The big problem I had with the enemies is getting the AI to work. it also had to work in any condition, since the levels are random. My Enemy Class is 275 lines of code, which is a lot compared to 146 for the user Class.  Most of it is the AI code, which is still not fully functional, but hey I tried.  So the first part of the AI is checking where the enemy can move.  I have put part of that code below. This code is only for checking left, but the other 3 directions are the same setup.

Actor checkLeft1 = getOneObjectAtOffset(-1,0,Block.class);
Actor checkLeft2 = getOneObjectAtOffset(-1,0,Brick.class);
Actor checkLeft3 = getOneObjectAtOffset(-1,0,Bomb.class);
int num = 0;
if (checkLeft1 != null || checkLeft2 != null || checkLeft3 != null){
   left = true;
   num++;
}
else{
   left=false;
}

The next part is a function called “followPath” which checks to see if the enemy is already moving in a direction. if it is, it will continue to move in that direction if able. Otherwise, it will pick a new direction.  I’m putting another snippet of code below for this function. This checks to see if the enemy is moving right and able to move right.

Actor checkRight1 = getOneObjectAtOffset(1,0,Block.class);
Actor checkRight2 = getOneObjectAtOffset(1,0,Brick.class);
if (pX==x-1){
if ((checkRight1==null) && (checkRight2==null)){
   setLocation(x+1,y);
   pX = x;
   pY = y;
   return true;
}
else{
   return false;
}

If the Enemy is moving right, but it can’t anymore, it returns false. This applies for all directions as well. At this point, the enemy isn’t following a path anymore and it has a certain amount of neighbors, or surrounding objects. The next part checks to see if there are 3 neighbors,and if so it moves in the one direction it can. If there aren’t three neighbors, it then calls a method called “pickDirection”. This, as you might have guessed, picks a direction for the enemy to go. Below is the code for moving left if the user is left of the enemy.

Actor checkLeft1 = getOneObjectAtOffset(-1,0,Block.class);
Actor checkLeft2 = getOneObjectAtOffset(-1,0,Brick.class);

if ((checkLeft1 == null) && (checkLeft2 == null) && (manX<x)){
   pX = x;
   pY = y;
   setLocation(x-1,y);
   done = true;
   break;
}

It checks around itself like this until it finds a way to go. If it can’t, it doesn’t move anywhere.  The last part of the enemy AI is the death. All it does is check to see if it’s hit by a bomb, and if it is, then it goes through a dying animation and removes itself.

 

The Bomb

bomb-bigger

 

The bomb in this game has 2 purposes: Breaking bricks and killing enemies. However, it can also kill the player. The bomb’s blast radius extends 1 block out in all 4 directions from the center. In the bomb’s code, it immediately starts a timer as soon as it’s placed. the variable bombTimer below is the counter.

if (bombTimer>=150){
   Explode();
   getWorld().removeObject(this);
}
else{
   bombTimer++;
}

The method Explode() creates up to 4 objects around it called Left, Right, Up, and Down. It also creates an object called Center, where the bomb was. These are the flames coming out of the bomb and serve to hit the player, enemies or bricks and destroy them.

 

The Door

Door-bigger

The door is the final stage of playing the game. It’s hidden behind one of the many generated bricks. If you find it and all of the enemies are dead, you can enter it and win. To determine this, I found out how many enemies were alive and made an if statement including that.

public void act() {
   if (checkEnemies()==0){
       keyPressed();
   }
}
 
public int checkEnemies(){
   List check = getWorld().getObjects(Enemy.class);
   int size = check.size();
   return size;
}

As you can see, only if there are no enemies in the world can the door actually be opened. Once you win, in my version you just enter a blank room. In the original Bomberman you would move on to the next level. I feel like I did a decent job at recreating Bomberman for the most part.

 

Problems with Timing

One of the biggest problems I faced was timing. I was fixed on using actual time, like milliseconds, to time the animations of the game that it became frustrating after a while. I couldn’t get the whole java timer thing down. I instead switched to counting frames as a timer. It worked pretty well, although in the future I would prefer to use actual time measurements.

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *