Created
August 2, 2016 20:47
-
-
Save anonymous/bbdeba52f4aed219cc38cbc1c5ef1833 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.swing.JFrame; | |
import asciiPanel.AsciiPanel; | |
import java.awt.event.KeyEvent; | |
import java.awt.event.KeyListener; | |
import java.util.*; | |
import java.awt.Color; | |
public class EscapeTheTrolls extends JFrame implements KeyListener { | |
public static final int WIDTH = 39; | |
public static final int HEIGHT = 27; | |
public static final double LOS_RADIUS = 6.0; | |
public static final int LASER_LENGTH = 8; | |
public static final int GORE = 4; | |
public static final Color FLOOR_COLOR = new Color(30, 30, 30); | |
private AsciiPanel terminal; | |
private String maze = | |
"#######################################\n" + | |
"#######################################\n" + | |
"## # # # # # ##\n" + | |
"## # ##### # ### ##### ### ### ### # ##\n" + | |
"## # # # # # # # # ##\n" + | |
"###### # ##### ##### ### # # # ##### ##\n" + | |
"## # # # # # # # # # ##\n" + | |
"## # ####### # # ##### ### # ##### # ##\n" + | |
"## # # # # # # # # ##\n" + | |
"## ####### ### ### # ### ##### # ### ##\n" + | |
"## # # # # # # # # ##\n" + | |
"## ### ### # ### # ##### # # # ########\n" + | |
"## # # # # # # # # # # ##\n" + | |
"######## # # # ##### # ### # ### ### ##\n" + | |
"## # # # # # # # # ##\n" + | |
"## ### # ##### ### # ### ### ####### ##\n" + | |
"## # # # # # # # # ##\n" + | |
"## # ##### # ### ##### # # ####### # ##\n" + | |
"## # # # # # # # # # ##\n" + | |
"## ##### # # # ### ##### ##### # ######\n" + | |
"## # # # # # # # # ##\n" + | |
"## # ### ### ### ##### ### # ##### # ##\n" + | |
"## # # # # # ##\n" + | |
"##X####################################\n" + | |
"#######################################\n"; | |
private Random rng = new Random(); | |
private char[][] map; | |
private List<Troll> trolls = new ArrayList<>(); | |
int x; | |
int y; | |
private boolean won = false; | |
private boolean lost = false; | |
private boolean standingOnCorpse = false; | |
private boolean standingOnGibs = false; | |
String statusMsg = ""; | |
private boolean hasLaser = false; | |
private int laser = 0; //number of turns to render laser | |
private int laserAmmo = 0; | |
private int gibs = 0; | |
public EscapeTheTrolls() { | |
super("Escape The Trolls v. 0.01"); | |
terminal = new AsciiPanel(WIDTH, HEIGHT); | |
map = loadMap(); | |
placePlayerRandomly(); | |
placeMiningLaser(); | |
addTrolls(10); | |
add(terminal); | |
pack(); | |
addKeyListener(this); | |
repaint(); | |
} | |
public void placePlayerRandomly() { | |
while (true) { | |
x = rng.nextInt(WIDTH); | |
y = rng.nextInt(HEIGHT); | |
if (map[y][x] == ' ') | |
break; | |
} | |
map[y][x] = '>'; | |
} | |
public void placeMiningLaser() { | |
int c = 0; | |
int r = 0; | |
while (true) { | |
c = rng.nextInt(WIDTH); | |
r = rng.nextInt(HEIGHT); | |
if (map[r][c] == ' ') | |
break; | |
} | |
map[r][c] = 'L'; | |
} | |
//n = how many to add | |
public void addTrolls(int n) { | |
for (int i = 0; i < n; i++) { | |
int tx = 0; | |
int ty = 0; | |
while (true) { | |
tx = rng.nextInt(WIDTH); | |
ty = rng.nextInt(HEIGHT); | |
if (map[ty][tx] == ' ') | |
break; | |
} | |
map[ty][tx] = 'T'; | |
trolls.add(new Troll(tx, ty)); | |
} | |
} | |
public void repaint() { | |
terminal.clear(); | |
displayOutput(terminal); | |
super.repaint(); | |
} | |
public void movePlayer(int x, int y) { | |
char ch = map[this.y + y][this.x + x]; | |
if (ch == ' ' || ch == '%' || ch == 'L' || ch == '*' || ch == '.') { | |
this.x = this.x + x; | |
this.y = this.y + y; | |
if (standingOnCorpse) { | |
map[this.y - y][this.x - x] = '%'; | |
standingOnCorpse = false; | |
} | |
else if (standingOnGibs) { | |
map[this.y - y][this.x - x] = '.'; | |
if (gibs != 0) | |
gibs--; | |
standingOnGibs = false; | |
} | |
else { | |
char g = gibs == 0 ? ' ' : '.'; | |
map[this.y - y][this.x - x] = g; | |
if (gibs != 0) | |
gibs--; | |
} | |
if (ch == '%') { | |
standingOnCorpse = true; | |
gibs = GORE; | |
} | |
if (ch == '.') { | |
standingOnGibs = true; | |
} | |
if (ch == 'L') { | |
hasLaser = true; | |
statusMsg = "You pick up a laser!"; | |
laserAmmo = 2; | |
} | |
} | |
else if (ch == '#') | |
pushWall(this.x + x, this.y + y, x, y); | |
else if (ch == 'T') | |
lost = true; | |
else if (ch == 'X') { | |
won = true; | |
System.out.println("WON"); | |
} | |
char c = '@'; | |
if (x == 1) c = '>'; | |
else if (x == -1) c = '<'; | |
else if (y == 1) c = 'v'; | |
else if (y == -1) c = '^'; | |
map[this.y][this.x] = c; | |
} | |
//from (c, r) toward (x, y) | |
public void pushWall(int c, int r, int x, int y) { | |
char ch = map[r + y][c + x]; | |
if (ch == ' ' || ch == '.') { | |
statusMsg = "You hear a rumble."; | |
map[r][c] = ' '; | |
map[r + y][c + x] = '#'; | |
} | |
else if (ch == 'T') { | |
map[r][c] = ' '; | |
map[r + y][c + x] = '%'; | |
killTroll(c + x, r + y); | |
} | |
} | |
public boolean inBounds(int x, int y) { | |
return x > 1 && x < WIDTH - 2 && y > 1 && y < HEIGHT - 4; | |
} | |
//kill the troll at x, y | |
public void killTroll(int x, int y) { | |
statusMsg = "The troll is smushed."; | |
Troll t = null; | |
for (Troll troll : trolls) | |
if (troll.tx == x && troll.ty == y) | |
t = troll; | |
trolls.remove(t); | |
} | |
public void displayOutput(AsciiPanel term) { | |
if (laser > 0) { | |
laser--; | |
if (laser == 0) { | |
for (int r = 0; r < HEIGHT; r++) | |
for (int c = 0; c < WIDTH; c++) | |
if (map[r][c] == '*') | |
map[r][c] = ' '; | |
} | |
} | |
Color color = Color.WHITE; | |
for (int r = 0; r < HEIGHT - 2; r++) | |
for (int c = 0; c < WIDTH; c++) { | |
char ch = map[r][c]; | |
if (player(ch)) | |
color = Color.YELLOW; | |
else if (ch == 'X') | |
color = Color.MAGENTA; | |
else if (ch == 'T') { | |
for (Troll t : trolls) { | |
if (t.tx == c && t.ty == r) | |
if (t.speed > 0.0D) | |
color = Color.ORANGE; | |
else | |
color = Color.RED; | |
} | |
} | |
else if (ch == '%') | |
color = Color.PINK; | |
else if (ch == '.') | |
color = Color.RED; | |
else if (ch == 'L' || ch == '*') | |
color = Color.CYAN; | |
else | |
color = Color.GRAY; | |
boolean visable = distance(c, r) < LOS_RADIUS; | |
if (visable) { | |
if (ch == '#') | |
term.write(map[r][c], c, r, color, Color.DARK_GRAY); | |
else if (ch == '.' || ch == '%') | |
term.write(map[r][c], c, r, color, new Color(50, 10, 15)); | |
else if (player(ch) && (standingOnGibs || standingOnCorpse || gibs > 0)) | |
term.write(map[r][c], c, r, color, new Color(50, 10, 15)); | |
else | |
term.write(map[r][c], c, r, color, FLOOR_COLOR); | |
} | |
} | |
displayStatusMsg(); | |
term.write("Mining Laser Ammo: " + laserAmmo, 0, 26, Color.CYAN); | |
if (won) { | |
term.writeCenter("YOU WON THE GAME!!!", 10, Color.GREEN); | |
term.writeCenter("Press --[Esc]-- to exit.", 12, Color.GREEN); | |
} | |
else if (lost) { | |
term.writeCenter("You were eaten by a troll...", 10, Color.GREEN); | |
term.writeCenter("Press --[Esc]-- to exit.", 12, Color.GREEN); | |
} | |
} | |
public void displayStatusMsg() { | |
terminal.write(statusMsg, 0, 25); | |
} | |
public double distance(int x, int y) { | |
return Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.y - y, 2)); | |
} | |
public boolean player(char c) { | |
return c == '>' || c == '<' || c == '^' || c == 'v'; | |
} | |
public void keyPressed(KeyEvent e) { | |
switch (e.getKeyCode()) { | |
case KeyEvent.VK_UP: if (!won && !lost) movePlayer(0, -1); break; | |
case KeyEvent.VK_DOWN: if (!won && !lost) movePlayer(0, 1); break; | |
case KeyEvent.VK_LEFT: if (!won && !lost) movePlayer(-1, 0); break; | |
case KeyEvent.VK_RIGHT: if (!won && !lost) movePlayer(1, 0); break; | |
case KeyEvent.VK_SPACE: | |
if (!won && !lost && hasLaser && laserAmmo > 0) { | |
int dx = 0; | |
int dy = 0; | |
laser = 2; | |
switch (map[y][x]) { | |
case '>': dx = 1; | |
break; | |
case '<': dx = -1; | |
break; | |
case '^': dy = -1; | |
break; | |
case 'v': dy = 1; | |
break; | |
} | |
if (dy == 0) { | |
for (int c = x + dx; c != x + LASER_LENGTH * dx; c += dx) { | |
if (inBounds(c, y)) { | |
if (map[y][c] == 'T') { | |
killTroll(c, y); | |
statusMsg = "The troll is vaporized."; | |
} | |
map[y][c] = '*'; | |
} | |
} | |
} | |
else if (dx == 0) { | |
for (int r = y + dy; r != y + LASER_LENGTH * dy; r += dy) { | |
if (inBounds(x, r)) { | |
if (map[r][x] == 'T') { | |
killTroll(x, r); | |
statusMsg = "The troll is vaporized."; | |
} | |
map[r][x] = '*'; | |
} | |
} | |
} | |
laserAmmo -= 1; | |
} | |
break; | |
case KeyEvent.VK_ESCAPE: System.exit(0); break; | |
} | |
if (!won && !lost) | |
for (Troll t : trolls) { | |
t.move(); | |
if (Math.random() < t.speed) | |
t.move(); | |
} | |
repaint(); | |
} | |
public void keyReleased(KeyEvent e) {} | |
public void keyTyped(KeyEvent e) {} | |
public char[][] loadMap() { | |
char[][] map = new char[HEIGHT][WIDTH]; | |
int r = 0; | |
int c = 0; | |
for (char ch : maze.toCharArray()) { | |
if (c >= WIDTH) | |
c = 0; | |
if (r >= HEIGHT) | |
break; | |
else if (ch == '\n') | |
r++; | |
else { | |
map[r][c] = ch; | |
c++; | |
} | |
} | |
return map; | |
} | |
public static void main(String[] args) { | |
EscapeTheTrolls window = new EscapeTheTrolls(); | |
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
window.setLocationRelativeTo(null); | |
window.setVisible(true); | |
} | |
private class Troll { | |
int tx; | |
int ty; | |
double speed = 0.0D; | |
Troll(int x, int y) { | |
tx = x; | |
ty = y; | |
} | |
//am I close to the player? | |
boolean close() { | |
return distance(tx, ty) < 6.0; | |
} | |
boolean canSeePlayer() { | |
boolean canSee = false; | |
if (x == tx) { | |
int dir = y > ty ? 1 : -1; | |
for (int r = ty + dir; r != y; r += dir) { | |
if (map[r][x] == '#') { | |
return false; | |
} | |
} | |
return true; | |
} | |
else if (y == ty) { | |
int dir = x > tx ? 1 : -1; | |
for (int c = tx + dir; c != x; c += dir) { | |
if (map[y][c] == '#') { | |
return false; | |
} | |
} | |
return true; | |
} | |
return canSee; | |
} | |
//moving aimlessly for when the player is not nearby | |
void shuffle() { | |
int dx = 0; | |
int dy = 0; | |
int randomDir = Math.random() > 0.5 ? 1 : -1; | |
if (rng.nextInt(100) > 50) | |
dx = randomDir; | |
else | |
dy = randomDir; | |
char ch = map[ty + dy][tx + dx]; | |
if (ch == ' ') { | |
if (ch == '%'){ // && close()) { | |
//statusMsg = "The troll is a cannibal!"; | |
speed += 0.1; | |
} | |
map[ty][tx] = ' '; | |
map[ty + dy][tx + dx] = 'T'; | |
tx = tx + dx; | |
ty = ty + dy; | |
} | |
else if (player(ch)) | |
lost = true; | |
} | |
//Player spotted! Run 'em down. | |
void chase() { | |
if (x == tx) { | |
int dir = y > ty ? 1 : -1; | |
char ch = map[ty + dir][tx]; | |
if (player(ch)) | |
lost = true; | |
else if (ch != '#') { | |
if (ch == '%') { | |
statusMsg = "The troll is a cannibal!"; | |
speed += 0.1; | |
} | |
map[ty][tx] = ' '; | |
map[ty + dir][tx] = 'T'; | |
ty = ty + dir; | |
} | |
} | |
else if (y == ty) { | |
int dir = x > tx ? 1 : -1; | |
char ch = map[ty][tx + dir]; | |
if (player(ch)) | |
lost = true; | |
else if (ch != '#') { | |
if (ch == '%') { | |
statusMsg = "The troll is a cannibal!"; | |
speed += 0.1; | |
} | |
map[ty][tx] = ' '; | |
map[ty][tx + dir] = 'T'; | |
tx = tx + dir; | |
} | |
} | |
else | |
shuffle(); | |
} | |
void move() { | |
if (close() && canSeePlayer()) { | |
statusMsg = "The troll roars at you!"; | |
chase(); | |
} | |
else | |
shuffle(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment