Skip to content

Instantly share code, notes, and snippets.

@pschichtel
Last active August 29, 2015 14:24
Show Gist options
  • Save pschichtel/ba77e9c70c1c53a8ff11 to your computer and use it in GitHub Desktop.
Save pschichtel/ba77e9c70c1c53a8ff11 to your computer and use it in GitHub Desktop.
javac ShellPong.java && java -cp . ShellPong; rm ShellPong*.class
public class ShellPong {
private static final int width = 80;
private static final int height = 24;
private static final char CORNER = '+';
private static final char H_WALL = '-';
private static final char V_WALL = '|';
private static final char PADDLE = '#';
private static final char BALL = 'O';
private static final char BLANK = ' ';
private static final int GOAL = 3;
public static void main(String[] args) throws Exception {
final char[][] buf = new char[height][width];
Ball b = new Ball();
b.x = width / 2;
b.y = height / 2;
Paddle p1 = new Paddle();
p1.x = 4;
p1.y = height / 2 - p1.height / 2;
Paddle p2 = new Paddle();
p2.x = -5;
p2.y = height / 2 - p2.height / 2;
int p1Score = 0;
int p2Score = 0;
boolean ballMissed = false;
while (p1Score < GOAL && p2Score < GOAL) {
if (ballMissed) {
b.x = width / 2;
b.y = height / 2;
b.dx = Math.random() > .5 ? 1 : -1;
b.dy = Math.random() > .5 ? 1 : -1;
}
int yp1 = 0;
int yp2 = 0;
toggleRawInput();
while (System.in.available() > 0) {
final int c = System.in.read();
switch (c) {
case 'w':
yp1 = -1;
break;
case 's':
yp1 = 1;
break;
case 'o':
yp2 = -1;
break;
case 'l':
yp2 = 1;
break;
default:
System.out.println("" + c);
}
}
toggleRawInput();
System.out.println("Player 1: " + p1Score + " - Player 2: " + p2Score);
clear(buf);
drawFrame(buf);
updatePaddle(p1, yp1);
drawPaddle(p1, buf);
updatePaddle(p2, yp2);
drawPaddle(p2, buf);
ballMissed = !updateBall(b, buf);
drawBall(b, buf);
draw(buf);
sleep();
if (ballMissed) {
if (b.x < p1.x) {
p2Score++;
} else {
p1Score++;
}
}
}
System.out.println("Player " + (p1Score == GOAL ? "1" : "2") + " won!");
}
private static void updatePaddle(Paddle p, int dy) {
int ny = p.y + dy;
if (ny == 0) {
return;
}
if (ny + height == heightBound(-1)) {
return;
}
p.y = ny;
}
private static void drawPaddle(Paddle p, char[][] buf) {
drawVerticalLine(buf, PADDLE, p.x, p.y, p.y + p.height);
}
public static boolean updateBall(Ball b, char[][] buf) {
int nx = b.x + b.dx;
int ny = b.y + b.dy;
if (nx == b.x && ny == b.y) {
return true;
}
final char nc = get(buf, nx, ny);
if (nc == V_WALL) {
return false;
}
if (nc == H_WALL) {
ny = b.y;
b.dy *= -1;
ny += b.dy;
}
if (nc == PADDLE) {
nx = b.x;
b.dx *= -1;
nx += b.dx;
}
b.x = nx;
b.y = ny;
return true;
}
private static void drawBall(Ball b, char[][] buf) {
drawDot(buf, BALL, b.x, b.y);
}
private static void drawFrame(char[][] buf) {
drawDot(buf, CORNER, 0, 0);
drawDot(buf, CORNER, -1, 0);
drawDot(buf, CORNER, 0, -1);
drawDot(buf, CORNER, -1, -1);
drawHorizontalLine(buf, H_WALL, 1, 0, -2);
drawHorizontalLine(buf, H_WALL, 1, -1, -2);
drawVerticalLine(buf, V_WALL, 0, 1, -2);
drawVerticalLine(buf, V_WALL, -1, 1, -2);
}
private static int widthBound(int x) {
return mod(width + x, width);
}
private static int heightBound(int y) {
return mod(height + y, height);
}
private static void clear(char[][] buf) {
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
buf[y][x] = BLANK;
}
}
}
private static void draw(char[][] buf) {
for (char[] chars : buf) {
System.out.println(chars);
}
}
private static void drawHorizontalLine(char[][] buf, char c, int x, int y, int x2) {
final char[] line = buf[heightBound(y)];
x = widthBound(x);
x2 = widthBound(x2);
final int min = Math.min(x, x2);
final int max = Math.max(x, x2);
for (int i = min; i <= max; ++i) {
line[i] = c;
}
}
private static void drawVerticalLine(char[][] buf, char c, int x, int y, int y2) {
x = widthBound(x);
y = heightBound(y);
y2 = heightBound(y2);
final int min = Math.min(y, y2);
final int max = Math.max(y, y2);
for (int i = min; i <= max; ++i) {
buf[i][x] = c;
}
}
private static void drawDot(char[][] buf, char c, int x, int y) {
buf[heightBound(y)][widthBound(x)] = c;
}
private static char get(char[][] buf, int x, int y) {
return buf[heightBound(y)][widthBound(x)];
}
private static int mod(int a, int b) {
return ((a % b) + b) % b;
}
private static void sleep()
{
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
private static boolean isRaw = false;
private static final String[] RAW_INPUT_COMMAND = {"/bin/sh", "-c", ""};
private static void toggleRawInput() throws Exception {
RAW_INPUT_COMMAND[RAW_INPUT_COMMAND.length - 1] = "stty " + (isRaw ? "sane" : "raw") + " </dev/tty";
isRaw = !isRaw;
Runtime.getRuntime().exec(RAW_INPUT_COMMAND).waitFor();
}
private static class Ball {
public int x = 0;
public int y = 0;
public int dx = 1;
public int dy = 1;
}
private static class Paddle {
public int x = 0;
public int y = 0;
public int height = 5;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment