06MA4010991AP
Computer Game Design

Week 10

Inheritance

Sometimes we have to write similiar classes. They have same / similar elements and functions, which caused repeatition of codes and efforts. We all know bus, police car and truck are all cars, but how can we tell computer their relationships?

In object-oriented programming, inheritance is a way to form new classes (derived class) using classes that have already been defined (base class). In our example, we can first create a class of car, which contains properties of cars, and extends car into bus / police car / truck by adding extra properties. Inheritance provide a "is - a" relationship where we can say that a bus is a car and a truck is a car. Other than adding features, we can also override elements and functions from the base class. (e.g a bus may contains more wheels than a normal car of 4 wheels)

Example

source



Person a;
Student b;
 
void setup()
{
  a = new Person("John");
  b = new Student("Mary","1234567");
   
  a.printName();
  b.printName();
}



class Person
{
  String name;
   
  Person(String inputName)
  {
    name = inputName;
  }
   
  void printName()
  {
    println("My name is "+name);
  }
}


class Student extends Person
{
  String studentNum;
  Student(String inputName, String inputNum)
  {
    super(inputName);
    studentNum = inputNum;  
  }
   
  void printName()
  {
    super.printName();
    println("and my student number is "+studentNum);  
  }
}

More, a derived class can assign into a base class variable as well.

source



Person[] people;
 
void setup()
{
  people = new Person[2];
   
  people[0] = new Person("Mary");
  people[1] = new Student("Simpson","123");
   
  for(int i=0;i<people.length;i++)
  {
    people[i].printName();  
  }
}

 

ArrayList

A dynamic array is constructed by allocating a fixed-size array and then dividing it into two parts: the first stores the elements of the dynamic array and the second is reserved, or unused. We can then add or remove elements at the end of the dynamic array in constant time by using the reserved space, until this space is completely consumed. The number of elements used by the dynamic array contents is its logical size or size, while the size of the underlying array is called the dynamic array's capacity, which is the maximum possible logical size.

javadoc of ArrayList class

Here are some common functions that we may use frequently:

- add(Object o)
- get(int index)
- set(int index, Object o)
- size()

source



ArrayList people;
 
void setup()
{
  people = new ArrayList();
  people.add(new Person("Mary"));
  people.add(new Person("John"));
   
  printAll();
}
 
void draw()
{
}
 
void printAll()
{
  for(int i=0;i<people.size();i++)
  {
    Person tempPerson = (Person) people.get(i);
    print(tempPerson.name+" ");
  }
  println("");
}
 
void keyPressed()
{
  if(key == '1')
  {
    String name = "name"+(int)random(10);
    people.add(new Person(name));
    printAll();  
  }  
  else if(key == '2')
  {
    if(people.size()>0)
 people.remove(0);  
    printAll();
  }
}



class Person
{
  String name;
   
  Person(String inputName)
  {
    name = inputName;
  }
   
  void printName()
  {
    println("My name is "+name);
  }
}

 

Designing a shooting game

Step 1)
Draw out different elements and find their relationship

We can avoid repetition in enemyB and enemyC from enemyA, as well as the similarity between enemy bullet and player bullet.

 

Step 2)
Implement and test each class, first of all we can write a more simple version which only contains players and random shooting enemy bullets. Did you played this game before?

player only version

source



Player player1;
 
void setup()
{
  size(320,240);  
  smooth();
  initPlayer();
}
 
void draw()
{
  background(0);
  updatePlayer();  
}
 
void initPlayer()
{
   player1 = new Player(width*0.5,height*0.5,'w','s','a','d ');
}
 
void updatePlayer()
{
  player1.draw();  
}
 
void keyPressed()
{
  player1.keyPressed();
}
 
void keyReleased()
{
  player1.keyReleased();
}
 




class Player
{
  float x,y;
  boolean upPressed,downPressed,leftPressed,rightPressed;
  char upButton,downButton,leftButton,rightButton;
   
  float diameter;
  float speed;
 
  Player(float inputX, float inputY, char inputUp, char inputDown, char inputLeft, char inputRight)  
  {
    x = inputX;
    y = inputY;
    upButton = inputUp;
    downButton = inputDown;
    leftButton = inputLeft;
    rightButton = inputRight;
     
    upPressed = false;
    downPressed = false;
    leftPressed = false;
    rightPressed = false;
     
    diameter = 10;
    speed = 2;
  }
   
  void draw()
  {
    if(upPressed)
    {
 y -= speed;
 if(y<diameter/2)
 {
   y = diameter/2;
 }
    }  
    if(downPressed)
    {
 y += speed;
 if(y>height - diameter/2)
 {
   y = height - diameter/2;
 }
    }  
    if(leftPressed)
    {
 x -= speed;
 if(x<diameter/2)
 {
   x = diameter/2;
 }
    }  
    if(rightPressed)
    {
 x += speed;
 if(x>width - diameter/2)
 {
   x = width - diameter/2;
 }
    }  
    fill(255);
    stroke(255,0,0);
    ellipse(x,y,diameter,diameter);
  }
   
  void keyPressed()
  {
    if(key == upButton)
    {
 upPressed = true;  
    }
    else if(key == downButton)
    {
 downPressed = true;  
    }
    else if(key == leftButton)
    {
 leftPressed = true;  
    }
    else if(key == rightButton)
    {
 rightPressed = true;  
    }
  }
   
  void keyReleased()
  {
    if(key == upButton)
    {
 upPressed = false;  
    }
    else if(key == downButton)
    {
 downPressed = false;  
    }
    else if(key == leftButton)
    {
 leftPressed = false;  
    }
    else if(key == rightButton)
    {
 rightPressed = false;  
    }
  }
}
 


 

player and bullets, where using bullet array and all bullets from top

source



Bullet[] bullets;
Player player1;
float lastMillis;
 
void setup()
{
  size(320,240);  
  smooth();
  lastMillis = millis();
  initPlayer();
  initBullet();
}
 
void draw()
{
  background(0);
  updatePlayer();
  updateBullet();  
}
 
void initPlayer()
{
   player1 = new Player(width*0.5,height*0.8,'w','s','a','d ');
}
 
void updatePlayer()
{
  player1.draw();  
}
 
void initBullet()
{
  bullets = new Bullet[200];
  for(int i=0;i<bullets.length;i++)
  {
    bullets[i] = new Bullet(random(0,width),0,random(0,[colo r=#996600]radians[/color](360)),1.2);  
  }
}
 
void updateBullet()
{
  for(int i=0;i<bullets.length;i++)
  {
    bullets[i].draw();
     
    if(bullets[i].hitTest(player1) == true)
    {
 println((millis()-lastMillis)*0.001 + " seconds");
 lastMillis = millis();
 initPlayer();
 initBullet();  
    }
     
    if(bullets[i].outOfBound() == true)
    {
 bullets[i] = new Bullet(random(0,width),0,radians([color =#996600]random[/color](0,180)),bullets[i].speed);  
    }
  }  
}
 
void keyPressed()
{
  player1.keyPressed();
}
 
void keyReleased()
{
  player1.keyReleased();
}



class Bullet
{
  float x,y;
  float angle;  
  float speed;
   
  float diameter;
   
  Bullet(float inputX, float inputY, float inputAngle, float inputSpeed)
  {
    x = inputX;
    y = inputY;
    angle = inputAngle;  
    speed = inputSpeed;
     
    diameter = 5;
  }
   
  void draw()
  {
 x += cos(angle) * speed;
 y += sin(angle) * speed;
 speed += 0.0003;
 
 fill(255,255,0);
 stroke(255,0,0);
 ellipse(x,y,diameter,diameter);
  }
   
  boolean hitTest(float inputX, float inputY, float inputDiameter)
  {
    float distance = dist(inputX, inputY,x,y);
    if(distance<(diameter + inputDiameter)/2)
    {
 return true;
    }
    else return false;
  }
   
  boolean hitTest(Player inputPlayer)
  {
    return hitTest(inputPlayer.x,inputPlayer.y,inputPlayer.diameter);  
  }
   
  boolean outOfBound()
  {
    if(x< -100 || x>width + 100 || y< -100 || y> height+100)
    {
 return true;
    }  
    else return false;
  }
}



class Player
{
  float x,y;
  boolean upPressed,downPressed,leftPressed,rightPressed;
  char upButton,downButton,leftButton,rightButton;
   
  float diameter;
  float speed;
 
  Player(float inputX, float inputY, char inputUp, char inputDown, char inputLeft, char inputRight)  
  {
    x = inputX;
    y = inputY;
    upButton = inputUp;
    downButton = inputDown;
    leftButton = inputLeft;
    rightButton = inputRight;
     
    upPressed = false;
    downPressed = false;
    leftPressed = false;
    rightPressed = false;
     
    diameter = 10;
    speed = 2;
  }
   
  void draw()
  {
    if(upPressed)
    {
 y -= speed;
 if(y<diameter/2)
 {
   y = diameter/2;
 }
    }  
    if(downPressed)
    {
 y += speed;
 if(y>height - diameter/2)
 {
   y = height - diameter/2;
 }
    }  
    if(leftPressed)
    {
 x -= speed;
 if(x<diameter/2)
 {
   x = diameter/2;
 }
    }  
    if(rightPressed)
    {
 x += speed;
 if(x>width - diameter/2)
 {
   x = width - diameter/2;
 }
    }  
    fill(255);
    stroke(255,0,0);
    ellipse(x,y,diameter,diameter);
  }
   
  void keyPressed()
  {
    if(key == upButton)
    {
 upPressed = true;  
    }
    else if(key == downButton)
    {
 downPressed = true;  
    }
    else if(key == leftButton)
    {
 leftPressed = true;  
    }
    else if(key == rightButton)
    {
 rightPressed = true;  
    }
  }
   
  void keyReleased()
  {
    if(key == upButton)
    {
 upPressed = false;  
    }
    else if(key == downButton)
    {
 downPressed = false;  
    }
    else if(key == leftButton)
    {
 leftPressed = false;  
    }
    else if(key == rightButton)
    {
 rightPressed = false;  
    }
  }
}
 


 

bullets from all directions and increasing number of bullets (make use of arraylist)

source



ArrayList bullets;
Player player1;
float lastMillis;
 
int startBulletNumber = 50;
 
void setup()
{
  size(320,240);  
  smooth();
  lastMillis = millis();
  initPlayer();
  initBullet();
}
 
void draw()
{
  background(0);
  updatePlayer();
  updateBullet();  
}
 
void initPlayer()
{
   player1 = new Player(width/2,height/2,'w','s','a','d ');
}
 
void updatePlayer()
{
  player1.draw();  
}
 
void initBullet()
{
  bullets = new ArrayList();
  for(int i=0;i<startBulletNumber;i++)
  {
    bullets.add( new Bullet() );  
  }
}
 
void updateBullet()
{
  if(frameCount%50 == 0)
  {
    bullets.add( new Bullet() );  
  }
   
  for(int i=0;i<bullets.size();i++)
  {
    Bullet tempBullet = (Bullet)bullets.get(i);
    tempBullet.draw();
     
    if(tempBullet.hitTest(player1) == true)
    {
 println((millis()-lastMillis)*0.001 + " seconds");
 lastMillis = millis();
 initPlayer();
 initBullet();  
    }
     
    if(tempBullet.outOfBound() == true)
    {
 bullets.set(i, new Bullet());
    }
  }  
}
 
void keyPressed()
{
  player1.keyPressed();
}
 
void keyReleased()
{
  player1.keyReleased();
}



class Bullet
{
  float x,y;
  float angle;  
  float speed;
   
  float diameter;
   
  Bullet(float inputX, float inputY, float inputAngle, float inputSpeed)
  {
    x = inputX;
    y = inputY;
    angle = inputAngle;  
    speed = inputSpeed;
     
    diameter = 5;
  }
   
  Bullet()
  {
    int side = floor(random(4));
    if(side == 0) // top
    {
 y = -10;
 x = random(0,width);
 angle = radians(random(0,180));
    }  
    if(side == 1) //botton
    {
 y = height + 10;
 x = random(0,width);
 angle = radians(random(-180,0));
    }
    if(side == 2) // left
    {
 x = -10;
 y = random(0,height);
 angle = radians(random(-90,90));
    }
    if(side == 3) // right
    {
 x = width + 10;
 y = random(0,height);
 angle = radians(random(90,270));
    }
    speed = 1.2;
    diameter = 5;
  }
   
  void draw()
  {
 x += cos(angle) * speed;
 y += sin(angle) * speed;
 //speed += 0.0003;
 
 fill(255,255,0);
 stroke(255,0,0);
 ellipse(x,y,diameter,diameter);
  }
   
  boolean hitTest(float inputX, float inputY, float inputDiameter)
  {
    float distance = dist(inputX, inputY,x,y);
    if(distance<(diameter + inputDiameter)/2)
    {
 return true;
    }
    else return false;
  }
   
  boolean hitTest(Player inputPlayer)
  {
    return hitTest(inputPlayer.x,inputPlayer.y,inputPlayer.diameter);  
  }
   
  boolean outOfBound()
  {
    if(x< -100 || x>width + 100 || y< -100 || y> height+100)
    {
 return true;
    }  
    else return false;
  }
}



class Player
{
  float x,y;
  boolean upPressed,downPressed,leftPressed,rightPressed;
  char upButton,downButton,leftButton,rightButton;
   
  float diameter;
  float speed;
 
  Player(float inputX, float inputY, char inputUp, char inputDown, char inputLeft, char inputRight)  
  {
    x = inputX;
    y = inputY;
    upButton = inputUp;
    downButton = inputDown;
    leftButton = inputLeft;
    rightButton = inputRight;
     
    upPressed = false;
    downPressed = false;
    leftPressed = false;
    rightPressed = false;
     
    diameter = 10;
    speed = 2;
  }
   
  void draw()
  {
    if(upPressed)
    {
 y -= speed;
 if(y<diameter/2)
 {
   y = diameter/2;
 }
    }  
    if(downPressed)
    {
 y += speed;
 if(y>height - diameter/2)
 {
   y = height - diameter/2;
 }
    }  
    if(leftPressed)
    {
 x -= speed;
 if(x<diameter/2)
 {
   x = diameter/2;
 }
    }  
    if(rightPressed)
    {
 x += speed;
 if(x>width - diameter/2)
 {
   x = width - diameter/2;
 }
    }  
    fill(255);
    stroke(255,0,0);
    ellipse(x,y,diameter,diameter);
  }
   
  void keyPressed()
  {
    if(key == upButton)
    {
 upPressed = true;  
    }
    else if(key == downButton)
    {
 downPressed = true;  
    }
    else if(key == leftButton)
    {
 leftPressed = true;  
    }
    else if(key == rightButton)
    {
 rightPressed = true;  
    }
  }
   
  void keyReleased()
  {
    if(key == upButton)
    {
 upPressed = false;  
    }
    else if(key == downButton)
    {
 downPressed = false;  
    }
    else if(key == leftButton)
    {
 leftPressed = false;  
    }
    else if(key == rightButton)
    {
 rightPressed = false;  
    }
  }
}

 

adding enemies and player bullets

source