Last active
August 29, 2015 14:01
-
-
Save bartoleo/3392215d144130164a04 to your computer and use it in GitHub Desktop.
GFlappyAsciiBird v1.0 in one groovyscript
This file contains 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
@Grapes( | |
@Grab(group='com.squidpony', module='squidlib', version='1.95.1') | |
) | |
import squidpony.squidgrid.gui.awt.event.SGMouseListener | |
import squidpony.squidgrid.gui.swing.SwingPane | |
import squidpony.squidcolor.SColor | |
import squidpony.squidcolor.SColorFactory | |
import javax.swing.* | |
import javax.swing.event.MouseInputListener | |
import java.awt.* | |
import java.awt.event.ActionEvent | |
import java.awt.event.ActionListener | |
import java.awt.event.KeyEvent; | |
import java.awt.event.KeyListener; | |
import java.awt.event.MouseEvent; | |
import static java.awt.event.KeyEvent.VK_ESCAPE; | |
import static java.awt.event.KeyEvent.VK_UNDEFINED; | |
public class Pipe { | |
public double x | |
public int height | |
public int hole | |
public boolean scored = false | |
public String pipeStart = """\ | |
[=======]""" | |
public String pipeMiddle = """\ | |
| #|""" | |
int width = pipeStart.length() | |
} | |
public class Player { | |
public int x | |
public double y | |
public double dy | |
public String character = """\ | |
_----. | |
C_ D(_o) | |
\\-___==""" | |
public int width = 8 | |
public int height = 3 | |
} | |
public enum GameState { | |
game, | |
gameOver, | |
menu; | |
} | |
class Game { | |
public static int DELAY = 1000 / 60 | |
public static double GRAVITY = 0.035 | |
public static double JUMP = -0.8 | |
public static double SPEED = 0.25 | |
public GameState state = GameState.game | |
public SwingPane display | |
public JFrame frame | |
public Renderer renderer | |
public Player player | |
public int score = 0 | |
public ArrayList<Pipe> pipeList | |
public Game() { | |
// Setup window | |
// Generate map | |
renderer = new Renderer(RenderConfig.screenWidth, RenderConfig.screenHeight) | |
player = new Player() | |
player.x = 10 | |
player.y = 10 | |
player.dy = 0 | |
pipeList = new ArrayList<>() | |
// set up display | |
frame = new JFrame("Groovy Flappy Ascii Bird") | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) | |
frame.setLayout(new BorderLayout()) | |
display = new SwingPane() | |
display.initialize(RenderConfig.screenWidth, RenderConfig.screenHeight, new Font("Ariel", Font.BOLD, 12)) | |
clear(display) | |
frame.add(display, BorderLayout.SOUTH) | |
frame.setVisible(true) | |
frame.pack() | |
frame.setLocationRelativeTo(null) | |
frame.repaint() | |
frame.requestFocusInWindow() | |
CharacterInputListener dil = new CharacterInputListener(this, player) | |
int cellWidth = display.getCellDimension().width | |
int cellHeight = display.getCellDimension().height | |
MouseInputListener mil = new SGMouseListener(cellWidth, cellHeight, dil) | |
display.addMouseListener(mil) //listens for clicks and releases | |
display.addMouseMotionListener(mil) //listens for movement based events | |
frame.addKeyListener(dil) | |
render() | |
this.state = GameState.menu | |
javax.swing.Timer timer = new javax.swing.Timer(DELAY, new ActionListener() { | |
public void actionPerformed(ActionEvent event) { | |
stepSim(); | |
} | |
}); | |
timer.setRepeats(true); | |
timer.start(); | |
} | |
public void render() { | |
clear(display) | |
renderer.render(display: display, game: this, player: player, pipeList: pipeList, score: score) | |
//render stats | |
//MessageLog.render(display, player) | |
//done rendering this frame | |
display.refresh(); | |
} | |
public void clear(SwingPane display) { | |
for (int x = 0; x < RenderConfig.screenWidth; x++) { | |
for (int y = 0; y < RenderConfig.screenHeight; y++) { | |
display.clearCell(x, y) | |
} | |
} | |
display.refresh() | |
} | |
public void stepSim() { | |
if (this.state == GameState.game) { | |
player.dy += GRAVITY | |
player.y += player.dy | |
if (player.y + player.height >= RenderConfig.gameWindowY) { | |
this.state = GameState.gameOver | |
} | |
pipeList.each { | |
it.x -= SPEED | |
if (!it.scored && it.x < player.x) { | |
score++ | |
it.scored = true | |
} | |
if (MathUtils.checkCollide(player.x, player.y as int, player.width, player.height, it.x as int, 0, it.width, it.height) || | |
MathUtils.checkCollide(player.x, player.y as int, player.width, player.height, it.x as int, it.height + it.hole, it.width, RenderConfig.gameWindowY - it.height - it.hole)) { | |
this.state = GameState.gameOver | |
} | |
} | |
pipeList.removeAll { | |
it.x <= -it.width | |
} | |
if (pipeList.size() == 0 || (pipeList.size() == 1 && pipeList.get(0).x < RenderConfig.gameWindowX / 2)) { | |
Pipe pipe | |
pipe = new Pipe() | |
pipe.x = RenderConfig.gameWindowX | |
pipe.hole = MathUtils.getIntInRange(15, 30) | |
pipe.height = MathUtils.getIntInRange(1, RenderConfig.gameWindowY - pipe.hole - 1) | |
pipeList.add(pipe) | |
} | |
} | |
render() | |
} | |
public void jump() { | |
if (this.state == GameState.game) { | |
player.dy = JUMP | |
} else if (this.state == GameState.menu) { | |
this.state = GameState.game | |
} | |
} | |
public void escape() { | |
if (this.state == GameState.game) { | |
this.state = GameState.gameOver | |
} | |
} | |
} | |
class RenderConfig { | |
public static final int gameWindowX = 70 | |
public static final int gameWindowY = 48 | |
//total | |
public static final int screenWidth = 80 | |
public static final int screenHeight = 50 | |
} | |
class Renderer { | |
public int xSize | |
public int ySize | |
public Renderer(int x, int y) { | |
xSize = x | |
ySize = y | |
} | |
/** | |
* @param startx | |
* @param starty | |
*/ | |
public void render(params) { | |
SwingPane display = params.display | |
Player player = params.player | |
ArrayList<Pipe> pipeList = params.pipeList | |
Integer score = params.score | |
int xRange = RenderConfig.gameWindowX | |
int yRange = RenderConfig.gameWindowY | |
xRange.times { x -> | |
display.placeCharacter(x, yRange, '-' as char, SColor.DARK_GRAY) | |
} | |
yRange.times { y -> | |
display.placeCharacter(xRange, y, '|' as char, SColor.DARK_GRAY) | |
} | |
display.placeCharacter(xRange, yRange, '+' as char, SColor.DARK_GRAY) | |
display.placeHorizontalString(xRange + 2, 2, "Score") | |
display.placeHorizontalString(xRange + 2, 4, score.toString()) | |
xRange.times { i -> | |
display.placeCharacter(i, yRange-1, 'm' as char, SColor.GREEN) | |
} | |
int y = player.y | |
int x = player.x | |
player.character.eachLine { | |
y++ | |
x = player.x | |
for (char ch : it.toCharArray()) { | |
x++ | |
display.placeCharacter(x, y, ch, SColorFactory.asSColor(255, 255, 255)); | |
} | |
} | |
pipeList.each { | |
String pipeString | |
for (int i = 1; i < yRange; i++) { | |
if (i < it.height || i > it.height + it.hole) { | |
pipeString = it.pipeMiddle | |
} else if (i == it.height || i == it.height + it.hole) { | |
pipeString = it.pipeStart | |
} else { | |
pipeString = "" | |
} | |
int px = it.x | |
for (char ch : pipeString.toCharArray()) { | |
px++ | |
if (px > 0 && px < xRange) { | |
display.placeCharacter(px, i, ch, SColorFactory.asSColor(255, 255, 255)); | |
} | |
} | |
} | |
} | |
if (params.game.state == GameState.gameOver) { | |
display.placeHorizontalString(xRange / 2 as int, yRange / 2 as int, "GAME OVER") | |
} | |
if (params.game.state == GameState.menu) { | |
display.placeHorizontalString((xRange / 2 - 16) as int, yRange / 2 as int, "Press a key or mouse button to start & jump") | |
} | |
} | |
} | |
/** | |
* A simple input listener. | |
*/ | |
public class CharacterInputListener implements MouseInputListener, KeyListener { | |
Game context; | |
Player player; | |
public CharacterInputListener(Game context, Player player) { | |
this.context = context; | |
this.player = player; | |
} | |
@Override | |
public void mouseClicked(MouseEvent e) { | |
} | |
@Override | |
public void mousePressed(MouseEvent e) { | |
} | |
@Override | |
public void mouseReleased(MouseEvent e) { | |
context.jump(); | |
} | |
@Override | |
public void mouseEntered(MouseEvent e) { | |
//nothing special happens | |
} | |
@Override | |
public void mouseExited(MouseEvent e) { | |
//nothing special happens | |
} | |
@Override | |
public void mouseDragged(MouseEvent e) { | |
// dragged = true; | |
} | |
@Override | |
public void mouseMoved(MouseEvent e) { | |
//nothing special happens | |
} | |
@Override | |
public void keyTyped(KeyEvent e) { | |
} | |
@Override | |
public void keyPressed(KeyEvent e) { | |
//http://forums.codeguru.com/showthread.php?495419-KeyListener-doesn-t-work-on-Windows-OS | |
handleKey(e); | |
} | |
@Override | |
public void keyReleased(KeyEvent e) { | |
} | |
private void handleKey(KeyEvent e) { | |
int code = e.getExtendedKeyCode(); | |
// if ExtendedKeyCode is VK_UNDEFINED (0) use normal keycode | |
if (code == VK_UNDEFINED) { | |
code = e.getKeyCode(); | |
} | |
boolean shift = e.isShiftDown(); | |
switch (code) { | |
//movement | |
case VK_ESCAPE: | |
context.escape(); | |
default: | |
context.jump(); | |
break; | |
} | |
} | |
} | |
class MathUtils { | |
private static Random random | |
public static synchronized init() { | |
if (!random) | |
random = new Random() | |
} | |
/** | |
* @param low inclusive | |
* @param high inclusive | |
* @return | |
*/ | |
public static int getIntInRange(int low, int high) { | |
if (low == high) return low | |
if (!random) init() | |
return random.nextInt(high + 1 - low) + low | |
} | |
public static boolean checkCollide(Integer x, Integer y, Integer oWidth, Integer oHeight, Integer xTwo, Integer yTwo, Integer oTwoWidth, Integer oTwoHeight) { | |
// AABB 1 | |
int x1Min = x; | |
int x1Max = x + oWidth; | |
int y1Max = y + oHeight; | |
int y1Min = y; | |
// AABB 2 | |
int x2Min = xTwo; | |
int x2Max = xTwo + oTwoWidth; | |
int y2Max = yTwo + oTwoHeight; | |
int y2Min = yTwo; | |
// Collision tests | |
if (x1Max < x2Min || x1Min > x2Max) return false; | |
if (y1Max < y2Min || y1Min > y2Max) return false; | |
return true; | |
} | |
} | |
Game game = new Game() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment