Monster VS Doty Exercise
Copy the 3 classes from the “Code Listing” section to the template project. You’ll notice a few things about this program:
- The monster can be controlled by the arrow keys on the keyboard. Make sure you understand how the run animation is called.
- If you press the “S” key, the swipe animation will run and a ball will fly out of the monster.
- You notice also that you only get 1 ball, if you examine the Game class, you’ll see that the same Ball object is used over and over again.
Exercise 1
Your challenge is to create a list of balls in game, instead of just 1 ball. Then, make it possible for the monster to fire multiple balls. The potential balls that can be fired is unlimited.
HINT: For this exercise, do not worry about removing the balls from the list or the environment.
Exercise 2
Create a Doty class and place a few Doty objects in the room, the constructor for Game looks like this:
public Game()
{
// Initial monster location
m = new Monster(5,1,1);
balls = new ArrayList<Ball>();
dotys = new ArrayList<Doty>();
dotys.add(new Doty(1, 1, 3));
dotys.add(new Doty(8, 1, 6));
dotys.add(new Doty(4, 1, 8));
}
Make it so that the balls that the monster fire will be able to eliminate the various dotys.
Code Listing
Game class
// Import the Env class to work with the 3D Environment
import env3d.Env;
import org.lwjgl.input.Keyboard;
/**
* Game class, the main controller class
*/
public class Game
{
// This game controlls exactly 1 Doty object
private Monster m;
private Ball b;
/**
* Put the doty at default location
*/
public Game()
{
// Initial monster location
m = new Monster(5,1,1);
// Initial ball location - hidden
b = new Ball(100, 0, 0);
}
/**
* The play method is the main entry point of the entire
* game. It contains some setup code and a game loop
*/
public void play()
{
// Initial setup code
boolean finished;
finished = false;
Env env;
// Create the environment. This next line will cause a
// blank window to appear
env = new Env();
// Add objects to the environment
env.addObject(m);
env.addObject(b);
// Camera control. We fix the camera and
// not allow users to change it.
env.setCameraXYZ(5,5,13);
env.setCameraPitch(-25);
env.setDefaultControl(false);
// The main game loop
while (finished == false)
{
// --- Process user input ---
// Keyboard input
// Track a complete key press (key up)
int key = env.getKey();
// Track a key down only
int keyDown = env.getKeyDown();
if (key == Keyboard.KEY_ESCAPE) {
finished = true;
} else if (key == Keyboard.KEY_S) {
m.swipe();
b.setDir(m.getRotateY());
b.setXYZ(m.getX(), m.getY(), m.getZ());
}
// Use key down to move the monster
if (keyDown == Keyboard.KEY_RIGHT) {
m.moveX(0.1);
} else if (keyDown == Keyboard.KEY_LEFT) {
m.moveX(-0.1);
} else if (keyDown == Keyboard.KEY_UP) {
m.moveZ(-0.1);
} else if (keyDown == Keyboard.KEY_DOWN) {
m.moveZ(0.1);
} else if (keyDown == Keyboard.CHAR_NONE) {
if (m.getState().equals("run")) {
m.idle();
}
}
// --- finish user input ---
// Change the object state
m.move();
b.move();
// Update display
env.advanceOneFrame();
}
// Cleanup code
env.exit();
}
}
Monster class
import java.util.ArrayList;
/**
* A monster with various states
*
*/
public class Monster
{
private double x;
private double y;
private double z;
private String texture;
private String model;
private double scale;
private double rotateX;
private double rotateY;
private double rotateZ;
// Keeps tract of the current frame
private int frame;
// Keeps track of the monster's current state
private String state;
// Lists to keep track of all the models
private ArrayList<String> idleModels;
private ArrayList<String> swipeModels;
private ArrayList<String> runModels;
/**
* Constructor for objects of class Monster
*/
public Monster(double x, double y, double z)
{
// initialise instance variables
this.x = x;
this.y = y;
this.z = z;
texture = "models/Boss/boss.jpg";
scale = 1;
rotateY = 0;
frame = 0;
// Start state
state = "idle";
loadModels();
model = idleModels.get(0);
}
/**
* Load all the models into the proper ArrayList
*/
public void loadModels()
{
idleModels = new ArrayList<String>();
idleModels.add("models/Boss/Idle/bossidle00.obj");
idleModels.add("models/Boss/Idle/bossidle01.obj");
idleModels.add("models/Boss/Idle/bossidle02.obj");
idleModels.add("models/Boss/Idle/bossidle03.obj");
idleModels.add("models/Boss/Idle/bossidle04.obj");
idleModels.add("models/Boss/Idle/bossidle05.obj");
idleModels.add("models/Boss/Idle/bossidle06.obj");
idleModels.add("models/Boss/Idle/bossidle07.obj");
idleModels.add("models/Boss/Idle/bossidle08.obj");
idleModels.add("models/Boss/Idle/bossidle09.obj");
idleModels.add("models/Boss/Idle/bossidle10.obj");
idleModels.add("models/Boss/Idle/bossidle11.obj");
idleModels.add("models/Boss/Idle/bossidle12.obj");
idleModels.add("models/Boss/Idle/bossidle13.obj");
idleModels.add("models/Boss/Idle/bossidle14.obj");
idleModels.add("models/Boss/Idle/bossidle15.obj");
idleModels.add("models/Boss/Idle/bossidle16.obj");
idleModels.add("models/Boss/Idle/bossidle17.obj");
idleModels.add("models/Boss/Idle/bossidle18.obj");
idleModels.add("models/Boss/Idle/bossidle19.obj");
swipeModels = new ArrayList<String>();
swipeModels.add("models/Boss/Swipe/bossswipe00.obj");
swipeModels.add("models/Boss/Swipe/bossswipe01.obj");
swipeModels.add("models/Boss/Swipe/bossswipe02.obj");
swipeModels.add("models/Boss/Swipe/bossswipe03.obj");
swipeModels.add("models/Boss/Swipe/bossswipe04.obj");
swipeModels.add("models/Boss/Swipe/bossswipe05.obj");
swipeModels.add("models/Boss/Swipe/bossswipe06.obj");
swipeModels.add("models/Boss/Swipe/bossswipe07.obj");
swipeModels.add("models/Boss/Swipe/bossswipe08.obj");
swipeModels.add("models/Boss/Swipe/bossswipe09.obj");
swipeModels.add("models/Boss/Swipe/bossswipe10.obj");
swipeModels.add("models/Boss/Swipe/bossswipe11.obj");
swipeModels.add("models/Boss/Swipe/bossswipe12.obj");
swipeModels.add("models/Boss/Swipe/bossswipe13.obj");
swipeModels.add("models/Boss/Swipe/bossswipe14.obj");
swipeModels.add("models/Boss/Swipe/bossswipe15.obj");
swipeModels.add("models/Boss/Swipe/bossswipe16.obj");
swipeModels.add("models/Boss/Swipe/bossswipe17.obj");
swipeModels.add("models/Boss/Swipe/bossswipe18.obj");
swipeModels.add("models/Boss/Swipe/bossswipe19.obj");
swipeModels.add("models/Boss/Swipe/bossswipe20.obj");
swipeModels.add("models/Boss/Swipe/bossswipe21.obj");
swipeModels.add("models/Boss/Swipe/bossswipe22.obj");
swipeModels.add("models/Boss/Swipe/bossswipe23.obj");
swipeModels.add("models/Boss/Swipe/bossswipe24.obj");
swipeModels.add("models/Boss/Swipe/bossswipe25.obj");
swipeModels.add("models/Boss/Swipe/bossswipe26.obj");
swipeModels.add("models/Boss/Swipe/bossswipe27.obj");
swipeModels.add("models/Boss/Swipe/bossswipe28.obj");
swipeModels.add("models/Boss/Swipe/bossswipe29.obj");
runModels = new ArrayList<String>();
runModels.add("models/Boss/Run/bossrun00.obj");
runModels.add("models/Boss/Run/bossrun01.obj");
runModels.add("models/Boss/Run/bossrun02.obj");
runModels.add("models/Boss/Run/bossrun03.obj");
runModels.add("models/Boss/Run/bossrun04.obj");
runModels.add("models/Boss/Run/bossrun05.obj");
runModels.add("models/Boss/Run/bossrun06.obj");
runModels.add("models/Boss/Run/bossrun07.obj");
runModels.add("models/Boss/Run/bossrun08.obj");
runModels.add("models/Boss/Run/bossrun09.obj");
runModels.add("models/Boss/Run/bossrun10.obj");
runModels.add("models/Boss/Run/bossrun11.obj");
runModels.add("models/Boss/Run/bossrun12.obj");
runModels.add("models/Boss/Run/bossrun13.obj");
runModels.add("models/Boss/Run/bossrun14.obj");
runModels.add("models/Boss/Run/bossrun15.obj");
runModels.add("models/Boss/Run/bossrun16.obj");
runModels.add("models/Boss/Run/bossrun17.obj");
runModels.add("models/Boss/Run/bossrun18.obj");
runModels.add("models/Boss/Run/bossrun19.obj");
runModels.add("models/Boss/Run/bossrun20.obj");
runModels.add("models/Boss/Run/bossrun21.obj");
runModels.add("models/Boss/Run/bossrun22.obj");
runModels.add("models/Boss/Run/bossrun23.obj");
runModels.add("models/Boss/Run/bossrun24.obj");
runModels.add("models/Boss/Run/bossrun25.obj");
runModels.add("models/Boss/Run/bossrun26.obj");
runModels.add("models/Boss/Run/bossrun27.obj");
runModels.add("models/Boss/Run/bossrun28.obj");
runModels.add("models/Boss/Run/bossrun29.obj");
}
/**
* The move method is called every frame.
* It's purpose is to check the different state and
* mutate monster accordingly
*/
public void move()
{
frame++;
if (state.equals("idle")) {
idleAction();
} else if (state.equals("swipe")) {
swipeAction();
} else if (state.equals("run")) {
runAction();
}
}
/**
* Change the state to idle
*/
public void idle()
{
frame = 0;
state = "idle";
}
/**
* Change the state to swipe
*/
public void swipe()
{
frame = 0;
state = "swipe";
}
/**
* Load the correct model when monster is idle
*/
public void idleAction()
{
if (frame < idleModels.size()) {
model = idleModels.get(frame);
} else {
frame = 0;
}
}
/**
* Load the correct model when monster is swiping
*/
public void swipeAction()
{
if (frame < swipeModels.size()) {
model = swipeModels.get(frame);
} else {
idle();
}
}
/**
* Load the correct model when monster is running
*/
public void runAction()
{
if (frame < runModels.size()) {
model = runModels.get(frame);
} else {
idle();
}
}
/**
* Move monster in the x direction, change model as needed
*/
public void moveX(double delta)
{
if (!state.equals("run")) {
state = "run";
frame = 0;
}
x += delta;
if (delta < 0) {
rotateY = -90;
} else {
rotateY = 90;
}
}
/**
* Move monster in the z direction, change model as needed
*/
public void moveZ(double delta)
{
if (!state.equals("run")) {
state = "run";
frame = 0;
}
z += delta;
if (delta < 0) {
rotateY = 180;
} else {
rotateY = 0;
}
}
/**
* Accessor for x, y, z, and rotateY, and state
*/
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public double getZ()
{
return z;
}
public double getRotateY()
{
return rotateY;
}
public String getState()
{
return state;
}
}
Ball class
public class Ball
{
private double x, y, z, scale;
private double dir;
/**
* Constructor for objects of class Ball
*/
public Ball(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
scale = 0.2f;
}
public void setXYZ(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public double getZ()
{
return z;
}
/**
* Set the direction of the ball
*/
public void setDir(double angle)
{
dir = angle;
}
/**
* Move the ball based on it's direction
*/
public void move()
{
if (dir == -90) {
x -= 0.1;
} else if (dir == 90) {
x += 0.1;
} else if (dir == 180) {
z -= 0.1;
} else if (dir == 0) {
z += 0.1;
}
}
}