03 Apr 2012

We finished most of the Robots game last time -- I added a class to wrap up the gameplay logic, and incorporate your new Robot classes. Don't forget to submit your Robot class if you haven't already!

Here is the game logic, which allows for multiple basic levels and restarting. An interesting addition would be to make a way to create more interesting levels, maybe even ones that have more of a puzzle feel than action.

/*
*
*/
package org.ilzd.animation;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

/**
* Implement game logic for robot game, including robot creation and levels.
* @author jlepak
*/
public class RobotGame {
private ArrayList<Character> robots;
private Human human;
private int level;

private static final double MIN_DIST = 50;

// Defines how many robots appear at each level
private static final int START_ROBOTS = 20;
private static final int NEW_ROBOTS = 10;

private int width, height;

RobotGame(int width, int height) {
this.width = width;
this.height = height;
robots = new ArrayList<Character>();
human = new Human(0, 0);
level = 0;
}

public void reset() {
level = 0;
human = new Human(0, 0);
newLevel();
}

public void newLevel() {
level++;
robots.clear();
int posX = width/2;
int posY = height/2;
human.setCenter(posX, posY);

fillRobots(posX, posY);
}

public void fillRobots(int humanX, int humanY) {
Random rand = new Random();
for (int i = 0; i < START_ROBOTS + NEW_ROBOTS * level; i++) {
Point location = randomAwayFrom(humanX, humanY, rand);
int x = (int)location.getX();
int y = (int)location.getY();

// Choose random type for robot
double robotType = rand.nextDouble();
Character newRobot;
if (robotType < 0.2) {
newRobot = new Robot(x, y, human);
} else if (robotType < 0.4) {
newRobot = new OrangeRobot(x, y, human);
} else if (robotType < 0.5) {
newRobot = new TeleportingRobot(x, y, human);
} else if (robotType < 0.6) {
newRobot = new TeleportingRobot2(x, y, human, width, height);
} else if (robotType < 0.7) {
newRobot = new SeekerRobot(x, y, human);
} else {
newRobot = new ExploderBot(x, y, human);
}
}
}

public void update() {
// Tell all pairs of characters to interact
for (Character a : getCharacters()) {
for (Character b : getCharacters()) {
if (a != b)
a.interactWith(b);
}
}
// Update all positions
for (Character a : getCharacters())
a.update();
}

public Point randomAwayFrom(int x, int y, Random rand) {
Point p;
do {
p = new Point(rand.nextInt(width), rand.nextInt(height));
} while (p.distance(x, y) < MIN_DIST);
return p;
}

public void input(double dx, double dy) {
human.setDirection(dx, dy);
}

public boolean levelComplete() {
for (Character c : robots)
if (c.isAlive())
return false;
return true;
}

public boolean gameOver() {
return !human.isAlive();
}

private class CharIterable implements Iterable<Character> {
public Iterator<Character> iterator() {
return new CharIterator();
}
}

private class CharIterator implements Iterator<Character> {

// Track index within robot array; if -1, indicate that
// human should be next.
int index = -1;

public boolean hasNext() {
return index < robots.size();
}

public Character next() {
Character output;
if (index < 0)
output = human;
else
output = robots.get(index);
index++;
return output;
}

public void remove() {}

}

public Iterable<Character> getCharacters() {
return new CharIterable();
}
}


Here are the submitted Robot classes:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.ilzd.animation;

import java.awt.Color;
import java.awt.Graphics2D;

/**
* Implement simple robot that follows a target.
*
* @author Tim
*/
public class ExploderBot extends CharacterBase {
// Who robot is following

private Character target;
private int frame = 0;
private int explodeSize = 0;
private int blinkCounter = 0;
private boolean colorSwap = true;
// Speed of character
private static final double RATE = 0.5;

public ExploderBot(int x0, int y0, Character target) {
super(x0, y0);
this.target = target;
}

@Override
public double getDiameter() {
if (isAlive()) {
return DEFAULT_DIAM;
} else {
return explodeSize;
}
}

public void update() {

if (!isAlive() && frame == 30) {
return;
}
double x0 = getX();
double y0 = getY();
double x1 = target.getX();
double y1 = target.getY();

// This will blink 10 times a second.
if (blinkCounter == 5) {
colorSwap = !colorSwap;
} else {
}

// Once "Dead" it will start counting
if (!isAlive() && frame < 30) {
frame++;
}
// This will enlarge size in relation to frame count.
if (!isAlive()) {
if (frame != 30) {
explodeSize = frame * 2;
} else {
explodeSize = (int) DEFAULT_DIAM;
}
}

// Compute vector of length RATE from current location to target.
if (!isAlive()) {
return;
}
double dx = x1 - x0;
double dy = y1 - y0;
double len = Math.sqrt(dx * dx + dy * dy);
double vecX = RATE * dx / len;
double vecY = RATE * dy / len;
// Update based on direction vector
setCenter(x0 + vecX, y0 + vecY);
}

@Override
public Color getColor() {
if (isAlive()) {
return Color.ORANGE;
} else if (frame < 30) {
if (colorSwap == true) {
return Color.YELLOW;
} else {
return Color.RED;
}
} else {
return Color.GRAY;
}
}
}
//@Override
//    public Color getColor() {
//        if (isAlive()) {
//            if (colorSwap == true) {
//                return Color.YELLOW;
//            } else {
//                return Color.RED;
//            }
//        } else if (frame < 30) {
//            return Color.RED;
//        } else {
//            return Color.GRAY;
//        }
//    }
//}

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.ilzd.animation;
import java.awt.Color;

/**
*
* @author Shamaila
*/
public class OrangeRobot extends Robot {
public OrangeRobot (int x0, int y0, Character target) {
super(x0, y0, target);
}

@Override
public double getDiameter() {
return DEFAULT_DIAM*2;
}

@Override
public Color getColor() {
if (isAlive())
return Color.ORANGE;
else
return Color.GRAY;
}

}

package org.ilzd.animation;

import java.awt.Color;
import java.util.Random;
import java.util.ArrayList;

/**
* @author Robert
*/
public class TeleportingRobot extends CharacterBase{

//Number collisions it takes to kill
private int lives;

private Character target;

private static final double RATE = 0.6;

public TeleportingRobot(int x0, int y0, Character target) {
super(x0, y0);
this.target = target;
lives = 3;
}
@Override
public void update() {
if (!isAlive())
return;
double x0 = getX();
double y0 = getY();
double x1 = target.getX();
double y1 = target.getY();

// Compute vector of length RATE from current location to target.
double dx = x1 - x0;
double dy = y1 - y0;
double len = Math.sqrt(dx * dx + dy * dy);
double vecX = RATE * dx / len;
double vecY = RATE * dy / len;
// Update based on direction vector
setCenter(x0 + vecX, y0 + vecY);
}
@Override
public Color getColor() {
if(isAlive())
return Color.CYAN;
else
return Color.GRAY;
}

public void interactWith(Character c) {
if(collidesWith(c)) {
lives--;
if(lives > 0)
teleport();
else
die();
}
}

public void teleport() {
Random gen = new Random();
setCenter(gen.nextInt(500),gen.nextInt(500));
}
}

package org.ilzd.animation;

import java.awt.Color;
import java.util.Random;

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author rclausen
*/
public class TeleportingRobot2 extends Robot {

private int deaths = 5;

private int width, height;

public TeleportingRobot2(int x0, int y0, Character target, int width, int height){
super(x0, y0, target);
this.width = width;
this.height = height;
}

public void die() {
Random rand = new Random();
deaths--;
setCenter(rand.nextInt(width), rand.nextInt(height));
if (deaths <= 0){
super.die();
}
}

@Override
public Color getColor() {
if (isAlive())
return Color.MAGENTA;
else
return Color.GRAY;
}
}

package org.ilzd.animation;
import java.awt.Color;
import java.awt.Graphics2D;

/**
* Implement simple robot that follows a target.
* @author James
*/
public class SeekerRobot extends CharacterBase {
// Who robot is following
private Character target;
public boolean pro = true;

// Speed of character
private static final double RATE = .75;

public SeekerRobot(int x0, int y0, Character target) {
super(x0, y0);
this.target = target;
;
}

public void update() {

if (!isAlive())
return;

double x0 = getX();
double y0 = getY();
double x1 = target.getX();
double y1 = target.getY();

// Compute vector of length RATE from current location to target.
double dx = x1 - x0;
double dy = y1 - y0;
double len = Math.sqrt(dx * dx + dy * dy);

if (len > 50.0)
return;

pro = false;
double vecX = RATE * dx / len;
double vecY = RATE * dy / len;
// Update based on direction vector
setCenter(x0 + vecX, y0 + vecY);

}

@Override
public Color getColor() {
if (isAlive() && pro)
return Color.pink;
else if (isAlive() && !pro)
return Color.red;
else
return Color.GRAY;
}

}