barriers = new ArrayList<>();
+
+ /**
+ * Starts the program
+ */
+ public static void main(String[] args) {
+ JFrame f = new JFrame(NAME);
+ f.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent windowEvent) {
+ System.exit(0);
+ }
+ });
+ SpaceInvaders game = new SpaceInvaders();
+ f.add(game);
+ game.init();
+ f.pack();
+ f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH);
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ f.setSize(screenSize.width - 100, screenSize.height - 100);
+ f.setVisible(true);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ updateObjects(g);
+ delay(DELAY);
+ repaint();
+ }
+
+ /**
+ * Initializes the game by loading and positioning {@link org.codecentral.spaceinvaders.objects.GameObject}s
+ */
+ private void init() {
+ addKeyListener(player); // Lets player respond to keyboard input
+ player = new Player(getWidth() / 2, getHeight() - 100);
+ placeAliens();
+ placeBarriers();
+ }
+
+ private void updateObjects(Graphics g) {
+ player.onDraw(g);
+ for (Alien alien : aliens) {
+ alien.move();
+ alien.onDraw(getGraphics());
+ }
+ barriers.forEach(barrier -> barrier.onDraw(g));
+ // TODO: Use callback to handle collisions
+ }
+
+ private void placeBarriers() {
+ for (int i = 0; i < DEFAULT_BARRIER_COUNT; i++) {
+ barriers.add(new Barrier(200 + 300 * i, 700));
+ }
+ }
+
+ private void placeAliens() {
+ aliens.addAll(Stream.generate(() -> new Alien(100, 350)).limit(DEFAULT_ALIEN_COUNT)
+ .collect(Collectors.toList()));
+ // TODO: Populate the aliens with some loops
+ }
+
+ private static void delay(int n) {
+ long startDelay = System.currentTimeMillis();
+ long endDelay = 0;
+ while (endDelay - startDelay < n) {
+ endDelay = System.currentTimeMillis();
+ }
+ }
+
+ @Override
+ public boolean mouseMove(Event e, int x, int y) {
+ return InputHandler.mouseUpdate(x, y);
+ }
+
+ @Override
+ public boolean mouseDrag(Event e, int x, int y) {
+ return InputHandler.mouseUpdate(x, y);
+ }
+
+ @Override
+ public boolean mouseDown(Event e, int x, int y) {
+ return InputHandler.mouseChange(e, true);
+ }
+
+ @Override
+ public boolean mouseUp(Event e, int x, int y) {
+ return InputHandler.mouseChange(e, false);
+ }
+
+ @Override
+ public boolean keyDown(Event e, int key) {
+ return InputHandler.keyChange(e, key, true);
+ }
+
+ @Override
+ public boolean keyUp(Event e, int key) {
+ return InputHandler.keyChange(e, key, false);
+ }
+}
+
diff --git a/src/org/codecentral/spaceinvaders/objects/Alien.java b/src/org/codecentral/spaceinvaders/objects/Alien.java
new file mode 100644
index 0000000..60f190f
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/Alien.java
@@ -0,0 +1,45 @@
+package org.codecentral.spaceinvaders.objects;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+/**
+ * An alien enemy that moves towards the player.
+ *
+ * @version 1.0.0
+ */
+public class Alien extends GameObject {
+
+ private static final int DEFAULT_WIDTH = 500;
+
+ private static final int DEFAULT_HEIGHT = 500;
+
+ /**
+ * Creates a new alien at the given coordinates.
+ *
+ * @param x The initial x coordinate, starting from the left of screen
+ * @param y The initial y coordinate, starting from the top of the screen
+ */
+ public Alien(int x, int y) {
+ super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ @Override
+ public void onDraw(Graphics g) {
+ g.setColor(Color.WHITE);
+ g.fillRect(getX(), getY(), 31, 30);
+ g.fillRect(getX(), getX() + 40, 31, 30);
+ g.fillRect(getX(), getY() + 80, 31, 30);
+ g.fillRect(getX(), getY() + 120, 31, 30);
+ g.fillRect(getX(), getY() + 160, 31, 30);
+ // TODO: Draw properly
+ }
+
+ /**
+ * Moves this alien right until collision, down, left until collision, and repeats.
+ */
+ public void move() {
+ /* TODO: Make a loop that checks for boundaries and keeps moving until it collides
+ with them */
+ }
+}
diff --git a/src/org/codecentral/spaceinvaders/objects/Barrier.java b/src/org/codecentral/spaceinvaders/objects/Barrier.java
new file mode 100644
index 0000000..cae4e5e
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/Barrier.java
@@ -0,0 +1,38 @@
+package org.codecentral.spaceinvaders.objects;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+/**
+ * A barrier that blocks {@link Rocket}s from passing.
+ *
+ * @version 1.0.0
+ */
+public class Barrier extends GameObject {
+
+ private static final int DEFAULT_WIDTH = 70;
+
+ private static final int DEFAULT_HEIGHT = 100;
+
+ /**
+ * Creates a new barrier at the given x and y coordinates.
+ *
+ * @param x The initial x coordinate, starting from the left of screen
+ * @param y The initial y coordinate, starting from the top of the screen
+ */
+ public Barrier(int x, int y) {
+ super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ @Override
+ public void onUpdate() {
+
+ }
+
+ @Override
+ public void onDraw(Graphics g) {
+ g.setColor(Color.GREEN);
+ g.fillRect(getX(), getY(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ g.fillRect(getX() + DEFAULT_WIDTH, getY(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+}
diff --git a/src/org/codecentral/spaceinvaders/objects/CollisionDetector.java b/src/org/codecentral/spaceinvaders/objects/CollisionDetector.java
new file mode 100644
index 0000000..d6176aa
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/CollisionDetector.java
@@ -0,0 +1,26 @@
+package org.codecentral.spaceinvaders.objects;
+
+/**
+ * A listener that takes action when a collision between two {@link GameObject}s is about to occur.
+ */
+public interface CollisionDetector {
+
+ /**
+ * Checks if two {@link GameObject}s are touching (adjacent) or are intersecting each other.
+ *
+ * @return Whether or not the first game object is intersecting the second
+ */
+ default boolean checkCollision(GameObject first, GameObject second) {
+ double firstX = first.getX();
+ double firstY = first.getY();
+ return (second.getX() + second.getWidth() > firstX &&
+ second.getY() + second.getHeight() > firstY &&
+ second.getX() < firstX + first.getWidth() &&
+ second.getY() < firstY + first.getHeight());
+ }
+
+ /**
+ * @see #checkCollision(GameObject, GameObject)
+ */
+ boolean checkCollision(GameObject object);
+}
diff --git a/src/org/codecentral/spaceinvaders/objects/GameObject.java b/src/org/codecentral/spaceinvaders/objects/GameObject.java
new file mode 100644
index 0000000..1f6d30c
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/GameObject.java
@@ -0,0 +1,97 @@
+package org.codecentral.spaceinvaders.objects;
+
+import java.awt.Graphics;
+import java.awt.Point;
+import java.util.Objects;
+
+/**
+ * The base class for all displayable on-screen components.
+ */
+abstract class GameObject implements CollisionDetector {
+
+ private Point position;
+
+ private int width;
+ private int height;
+
+ public GameObject(int x, int y, int width, int height) {
+ this(new Point(x, y), width, height);
+ }
+
+ public GameObject(Point position, int width, int height) {
+ this.position = position;
+ this.width = width;
+ this.height = height;
+ }
+
+ public int getX() {
+ return (int) position.getX();
+ }
+
+ public int getY() {
+ return (int) position.getY();
+ }
+
+ public void setX(double x) {
+ position.setLocation(x, getY());
+ }
+
+ public void setY(double y) {
+ position.setLocation(getX(), y);
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Updates game logic and prepare for a redraw.
+ */
+ public void onUpdate() {
+
+ }
+
+ /**
+ * Redraws currently displayed graphics.
+ */
+ public abstract void onDraw(Graphics g);
+
+ @Override
+ public boolean checkCollision(GameObject object) {
+ return checkCollision(this, object);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getX(), getY());
+ }
+
+ /**
+ * Returns true if the given object has the same X and Y coordinates as this.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof GameObject)) {
+ return false;
+ }
+ GameObject object = (GameObject) o;
+ return (object.getX() == getX()) && (object.getY() == getY());
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[x=" + getX() + ",y=" + getY() + "]";
+ }
+}
\ No newline at end of file
diff --git a/src/org/codecentral/spaceinvaders/objects/Player.java b/src/org/codecentral/spaceinvaders/objects/Player.java
new file mode 100644
index 0000000..ca33173
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/Player.java
@@ -0,0 +1,55 @@
+package org.codecentral.spaceinvaders.objects;
+
+import java.awt.Graphics;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+/**
+ * A ship that that moves according to keyboard inputs.
+ *
+ * This ship responds to left, right, "A", and "D" inputs.
+ *
+ * @version 1.0.0
+ */
+public class Player extends GameObject implements KeyListener {
+
+ private static final int DEFAULT_WIDTH = 128;
+
+ private static final int DEFAULT_HEIGHT = 128;
+
+ /**
+ * Creates a new player at the given x and y coordinates.
+ *
+ * @param x The initial x coordinate, starting from the left of screen
+ * @param y The initial y coordinate, starting from the top of the screen
+ */
+ public Player(int x, int y) {
+ super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ @Override
+ public void onUpdate() {
+
+ }
+
+ @Override
+ public void onDraw(Graphics g) {
+
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ // TODO: Respond to KeyEvents
+ switch (e.getKeyChar()) {
+ }
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+
+ }
+}
diff --git a/src/org/codecentral/spaceinvaders/objects/Rocket.java b/src/org/codecentral/spaceinvaders/objects/Rocket.java
new file mode 100644
index 0000000..400d36d
--- /dev/null
+++ b/src/org/codecentral/spaceinvaders/objects/Rocket.java
@@ -0,0 +1,48 @@
+package org.codecentral.spaceinvaders.objects;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+/**
+ * An upwards-moving projectile launched from a {@link Player}.
+ */
+public class Rocket extends GameObject {
+
+ private static final int DEFAULT_WIDTH = 100;
+
+ private static final int DEFAULT_HEIGHT = 30;
+
+ /**
+ * The amount of pixels to move every time {@link #move()} is called.
+ */
+ private int speed = 10;
+
+ /**
+ * Creates a new rocket at the given coordinates.
+ *
+ * @param x The initial x coordinate, starting from the left of screen
+ * @param y The initial y coordinate, starting from the top of the screen
+ */
+ public Rocket(int x, int y) {
+ super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ @Override
+ public void onDraw(Graphics g) {
+ g.setColor(Color.WHITE);
+ g.drawRect(getX(), getY(), 3, 10);
+ }
+
+ public void move() {
+ // TODO: Check for collisions
+ setY(getY() + speed); // Simply move upwards
+ }
+
+ void setSpeed(int speed) {
+ this.speed = speed;
+ }
+
+ int getSpeed() {
+ return speed;
+ }
+}