Plants-vs-Zombies-2

Deffme – 2D Terrain Protection Game

At this stage I can’t say I have done much – Uni, work, life :), but I have something:

First of all I have spent about half an hour on thinking how to write this game, mechanic and engine..

so the idea of game is pretty similar to famous “Plants vs Zombie”

2D game, we can place “tower/flower/anything that shoot” on a map, and there is horde of evil things trying to bypass our things – lets be clear at this stage this can be anything.. that’s just matter of sprites/sounds. hope that will be enough.. but if not – changing to 3D should be fairly easy anyway.

Our “things” can shoot bullet goes from left to the right and horde is going from right to the left.
every object at the map has life points.

My game is future proof and I have thought about different types of objects – eg slowing down bullets, faster enemies, more life points – upgrades etc,

lets remember about simple rule – everything on a map has to move with some speed.. and we need to make that the same for all devices – delta time :)

I am thinking about adding some sort of currency – sun, gold, points,tokens – whatever that will allow player to buy upgrades or new things and place it on the map

anyway.. lets see some code!

well first of all we need container for a game Рwhere we can specifies rendered and start a game - pretty standard opening for Android Development:

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
package android.deffme;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class Main extends Activity {
/** Called when the activity is first created. */

private GLSurfaceView glSurface;

/**
* Initiate the OpenGL View and set our own
* Renderer (@see Lesson02.java)
*/

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//Create an Instance with this Activity
glSurface = new GLSurfaceView(this);
//Set our own Renderer
glSurface.setRenderer(new Game());
//Set the GLSurface as View to this Activity
setContentView(glSurface);
}

/**
* Remember to resume the glSurface
*/

@Override
protected void onResume() {
super.onResume();
glSurface.onResume();
}

/**
* Also pause the glSurface
*/

@Override
protected void onPause() {
super.onPause();
glSurface.onPause();
}

}

As we can see nothing really special is happening here..
surface declaration, overrides for onCreate, onResume, onPouse.. simple.

now Game class:

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
package android.deffme;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;

public class Game implements Renderer {

Map map;

Game()
{

map = new Map(3,6);
}

@Override
public void onDrawFrame(GL10 gl) {
//Clear Screen And Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();             //Reset The Current Modelview Matrix

gl.glTranslatef(-0.5f, -1f, -2.0f); //Move down 1.2 Unit And Into The Screen 6.0

map.update();
map.draw(gl);

}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
if(height == 0) {                   //Prevent A Divide By Zero By
height = 1;                   //Making Height Equal One
}

gl.glViewport(0, 0, width, height);    //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION);   //Select The Projection Matrix
gl.glLoadIdentity();                //Reset The Projection Matrix

//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);

gl.glMatrixMode(GL10.GL_MODELVIEW);    //Select The Modelview Matrix
gl.glLoadIdentity();                //Reset The Modelview Matrix
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
gl.glShadeModel(GL10.GL_SMOOTH);          //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);  //Black Background
gl.glClearDepthf(1.0f);                //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST);          //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL);        //The Type Of Depth Testing To Do

//Really Nice Perspective Calculations
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}

}

game class is container for a map; however in future it will keep player score, states, and other like that functions.

what we have here:
viewport set up, clearing, drawing – all OpenGL ES stuff.. not much yet here.

Map Class

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
package android.deffme;

import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

public class Map {

   /*
    * Map is an array of 3 by 5 elements
    */

   
   ArrayList<Deff> deff;
   ArrayList<Enemy> enemy;
   
   
   private boolean[][] used;
   int x;
   int y;
   
   Map(int x, int y)
   {
      this.x= x;
      this.y = y;
     
      used = new boolean[x][y];
      resetTable();
     
      deff = new ArrayList<Deff>();
      enemy = new ArrayList<Enemy>();
     
   }
   
   
   void draw(GL10 gl)
   {
      for(int i=0; i<x; i++)
      {
         for(int j =0; j<y; j++)
         {
            Claster c = new Claster(i, j);
            c.draw(gl);
         }
      }
     
     
      for(int i=0; i<deff.size(); i++)
      {
         deff.get(i).draw(gl);
      }
     
      for(int i=0; i<enemy.size(); i++)
      {
         deff.get(i).draw(gl);
      }
   }
   
   void update()
   {
     
   }
   
   
   void addEnemy(Enemy e)
   {
      enemy.add(e);
   }
   
   void removeEnemy(Enemy e)
   {
      enemy.remove(e);
   }
   
   void addDeff(Deff d)
   {
      deff.add(d);
   }
   
   void removeDeff(Deff d)
   {
      deff.remove(d);
   }
   
   void resetTable()
   {
      for(int i = 0; i<this.x-1; i++)
      {
         for(int j = 0; j<this.y-1; j++)
         {
            used[this.x-1][this.y-1] = false;
         }
      }  
   }
   
}

Here we have actual Map Class where we store all units – Deff – our defense and Enemy – enemies.
used array is for storing data if we have planted tower on [x][y] position.. simple.
ArrayList is very useful in this case.

Claster Class – I need to change that but not sure how yet.

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
package android.deffme;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Claster {

   /** The buffer holding the vertices */
   private FloatBuffer vertexBuffer;
   int x,y;
   /** The initial vertex definition */
   private float vertices[] = {
         -1.0f, -1.0f, 0.0f, //Bottom Left
         1.0f, -1.0f, 0.0f,   //Bottom Right
         -1.0f, 1.0f, 0.0f,   //Top Left
         1.0f, 1.0f, 0.0f  //Top Right
                     };
   public Claster(int x, int y) {
      //
      this.x = x;
      this.y = y;
      float tVertices[] = {
            (x*0.25f), ((y+1)*0.25f-0.01f), 0.0f, //Bottom Left
            ((x+1)*0.25f-0.01f), ((y+1)*0.25f-0.01f), 0.0f,    //Bottom Right
            (x*0.25f), (y*0.25f), 0.0f,   //Top Left
            ((x+1)*0.25f-0.01f), (y*0.25f), 0.0f   //Top Right
                        };
     
      this.vertices = tVertices;
      ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
      byteBuf.order(ByteOrder.nativeOrder());
      vertexBuffer = byteBuf.asFloatBuffer();
      vertexBuffer.put(vertices);
      vertexBuffer.position(0);
   }
   public void draw(GL10 gl) {
      //Set the face rotation
      gl.glFrontFace(GL10.GL_CW);
     
      //Point to our vertex buffer
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
     
      //Enable vertex buffer
      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
     
      //Draw the vertices as triangle strip
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
     
      //Disable the client state before leaving
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
   }
}

this is class that draws our background for a map – I need to spend little bit more time on designing this one because I do not really like it.

Object Class

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
package android.deffme;

import javax.microedition.khronos.opengles.GL10;

public class Object {
   
   /*
    * object is any element on a map
    */

   
   float posX;
   float posY;
   int mLife;
   float speedPerSec;
   
     
   Object(float x, float y, int life, float speed)
   {
     
      setLife(life);
      setPosX(x);
      setPosY(y);
      setSpeedPerSec(speed);
     
   }
   
   void updatePosition(float delta_time, boolean left)
   {
      int help = 0;
      if(left)
      {
         help = -1;
      } else {
         help = 1;
         
      }
      //simple case they are going only on one direction
      this.posX = this.posX + help* this.speedPerSec * delta_time ;
         
     
   }
   
   
   float getSpeedPerSec ()
   {
      return this.speedPerSec;
   }
   
   void setSpeedPerSec(float speed)
   {
      this.speedPerSec = speed;
   
   }
   
   void setLife(int l)
   {
      this.mLife = l;
     
   }
   
   int getLife()
   {
      return this.mLife;
     
   }
   
   void setPosX(float x)
   {
      this.posX = x;
     
   }

   float getPosX()
   {
      return this.posX;
   }
   
   float getPosY()
   {
      return this.posY;
   }
   
   void setPosY(float y)
   {
      this.posY = y;
     
   }
   
   
   void draw(GL10 gl)
   {     
   
   }
   
}

as I said everything on a map is an object..

we can extends Object class by

Def:

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
package android.deffme;

import java.util.ArrayList;

public class Deff extends Object {

   
   int shotsPerSec;
   ArrayList<Bullet> bullets;
   
   Deff(float x, float y, int life, int shotsPerSec) {
      super(x, y, life, 0);
      // TODO Auto-generated constructor stub
      setShotsPerSec(shotsPerSec);
      bullets = new ArrayList<Bullet>();
   }
   
   void setShotsPerSec(int shots)
   {
      this.shotsPerSec = shots;
     
   }
   
   int getShotsPerSec()
   {
      return this.shotsPerSec;
   }
   
   void shoot()
   {
      Bullet obj = new Bullet(this.posX, this.posY);
      bullets.add(obj);
     
   }
   
   void removeBullet(Bullet bullet)
   {
      bullets.remove(bullet);
   }
   
}

or Enemy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package android.deffme;

public class Enemy extends Object {

   Enemy(float x, float y, int life, float speed) {
      super(x, y, life, speed);
      // TODO Auto-generated constructor stub
     
   }

   void update(float delta_time)
   {
      this.updatePosition(delta_time, true);
   }
}

our towers can as well shoot so we need a wee bullet class – bullet is as well an object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package android.deffme;

public class Bullet extends Object  {

   static float bSpeed = 10;
   
   Bullet(float x, float y) {
     
      super(x, y, 100, bSpeed);
      // TODO Auto-generated constructor stub
   }
   
   void update(float delta_time)
   {
      this.updatePosition(delta_time, false);
   }
   
}

I just want to mention that I am still learning this stuff so if anyone will spot some errors or know better solution – please leave a comment or droop me an email :)

4 thoughts on “Deffme – 2D Terrain Protection Game

  1. Lukasz you have a small error. You forgot to put the “public before the Object constructor.”

    P.S. Have you worked further with this project?

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>