Lab 10 - Game of Life
A relatively famous computer science simluation is a cellular automation program called The Game of Life.
In this assignment, you will use Java interfaces to implement a modified version of this simulator.
Assignment
Part I - Become Familiar With the Code:
-
Download the existing source code for this project.
-
Make sure you are able to compile and run the existing program.
When you first open the program in IntelliJ, if you can't see the code, click on the Project tab on the right side of the screen, then expand the
src
andprove02
folders. -
Examine the .java files to make sure you understand the purpose of each:
Game.java - This file contains the
main()
method. It initializes theList
ofCreature
objects, and then creates theWorld
.World.java - This class creates the GUI, handles GUI events such as resizing and repaiting, and kicks off the background thread for updating the state of the
Creature
instances.Creature.java - Contains the abstract base class from which all
Creature
subclasses must inherit.Movable.java - Contains the definition of the
Movable
interface. This interface should be implemented by all subclasses ofCreature
that can move.Aggressor.java - Contains the definition of the
Aggressor
interface. This interface should be implemented by all subclasses ofCreature
that can attack other creatures.Aware.java - Contains the definition of the
Aware
interface. This interface should be implemented by all subclasses ofCreature
that can sense and react to other creatures around them.Plant.java - A subclass of
Creature
that does nothing but provide food for other creatures. Instances of thePlant
class are represented in the game by green circles. Plants start with one health point.Animal.java - A subclass of
Creature
that implements theMovable
andAggressor
interfaces. Instances of theAnimal
class are represented in the game by red squares. They move in random directions and if they land on a plant, they will eat it.Animal
instances start with one health point and gain a health point for every plant they eat. Animals inflict one point of damage when they attack.Shape.java - An enum that contains possible creature shapes.
CreatureHandler.java - This class coordinates the behavior of each
Creature
instance. The key method in this class is theupdateCreatures()
method, which is called by theWorld
class every time the update loop runs. This method will iterate through aList
ofCreature
instances, determine which behaviors they implement, and signal theCreature
instance to carry out those behaviors.
Part II - Create a Zombie:
Your first task is to create a new Zombie creature based on existing behaviors.
It will start out by moving from left to right across the screen, devouring anything it comes in contact with, except for plants.
Create a new file called
Zombie.java
. That file should contain apublic
class definition for theZombie
class.The
Zombie
class should be a subclass ofCreature
and should implement theMovable
andAggressor
interfaces.Instances of the
Zombie
class should always move from left to right.Instances of the
Zombie
class should attack any creature they land on, as long as it isn't an instance of thePlant
class. They should inflict 10 points of damage when they attack.Instances of the
Zombie
class should be represented as blue squares.Modify the
Game
class to add 10Zombie
instances to theList
ofCreature
objects created at the start of the simulation.
Part III - Create a Wolf:
Your next task is to create a Wolf creature based on existing behaviors. Wolves start out by moving in a random direction, searching for something to eat.
If a wolf senses an animal nearby, it will decide to move in that direction as soon as possible. If it lands on an animal, it will eat it. Wolves will not eat or purposefully move towards zombies or plants.
Create a new file called
Wolf.java
. That file should contain apublic
class definition for theWolf
class.The
Wolf
class should be a subclass ofCreature
and should implement theMovable
,Aware
, andAggressor
interfaces.When the
move()
function is called on aWolf
instance, it should move in its preferred direction. When it is first created, it's preferred direction should be random.When the
senseNeighbors()
function is called, theWolf
instance should change its preferred direction to be in the direction of the firstAnimal
instance it sees. When checking for nearby animals, it should first check in the direction it's already moving. If noAnimal
instance is there, it should search in a clockwise pattern starting at the top.So, if the
Wolf
is moving left, it should first check the creature provided in theleft
parameter ofsenseNeighbors()
, followed byabove
, thenright
, thenbelow
.Instances of the
Wolf
class should attack anyAnimal
instances they land on, but should not attackPlant
orZombie
instances. Wolves should inflict 5 points of damage when they attack.Instances of the
Wolf
class should be represented as gray squares.Modify the
Game
class to add 10Wolf
instances to theList
ofCreature
objects created at the start of the simulation.
Part IV Give Wolves a New Behavior:
Your next task is to allow wolves the ability to spawn baby wolves.
Every time a wolf eats another animal, it should gain the ability to spawn a new wolf on its next turn.
The newly spawned wolf should be created in the square directly to the left of its parent. After spawning a new wolf, the parent should lose the ability to spawn new wolves until the next time it eats an animal.
Create a new
interface
calledSpawner
. This interface should define a single method:public Creature spawnNewCreature();
Update the
Wolf
class so that it implements this new behavior.Modify the
CreatureHandler
class so that it handles theSpawner
behavior. It should handle this behavior in a similar way to how it handles the other behaviors.Spawner
behaviors should be handled afterAggressor
behaviors.This part will be tricky, and will require you to do some research on your own, a pattern that will continue throughout the course.
Remember, wolves can only spawn once they've eaten something, and once they've spawned a new creature they lose their spawning ability until they eat again.
Bonus Points
Invent a new creature that implements a mix of existing or new behaviors.
Some possibilities include: a flying creature that swoops down on zombies, a zombie-eating plant, or a wolf-zombie that hunts down other wolves and turns them into zombies.
Regardless of what you do, make sure you follow these design guidelines:
Each distinct behavior (flying, hunting, etc...) should be in its own interface.
Make sure you create separate files for any new interfaces you create, as well as any new creature subclasses you create.
Make sure you modify the
CreatureHandler
class to incorporate any new behaviors in the update loop.Make sure you modify the
Game
class to instantiate some of your new creatures at the start of the simulation.If you want to use a shape other than a solid circle or square, add the shape option to the
Shape
enum, and add the necessary drawing code to thepaint()
method of theWorld
class. You can find additional drawing methods in the official Java docs for the Graphics class.
Submission
To submit your assignment, follow the instructions for code submission. Make sure you submit your entire project so that both Java files are included.