Skip to content

Commit

Permalink
Add Race game
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalibo committed Jan 4, 2017
1 parent 030e76e commit 34dd857
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ launch game

##### View

![](docs/img/sR35V1.gif) ![](docs/img/IFREtC.gif)
![](docs/img/sR35V1.gif) ![](docs/img/IFREtC.gif) ![](docs/img/bUdlw7.gif)

- Board panel `capacity [20x10]`
- Preview panel `capacity [4x4]`
Expand All @@ -39,3 +39,4 @@ launch game

### Games
- `0001` Snake
- `0002` Race
Binary file added docs/img/bUdlw7.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/main/java/com/github/vitalibo/brickgame/Run.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
import com.github.vitalibo.brickgame.core.ui.BrickGameFrame;
import com.github.vitalibo.brickgame.game.Game;
import com.github.vitalibo.brickgame.game.Menu;
import com.github.vitalibo.brickgame.game.race.RaceGame;
import com.github.vitalibo.brickgame.game.snake.SnakeGame;

public class Run {

static {
@SuppressWarnings("unchecked")
Class<? extends Game>[] GAMES = new Class[]{
SnakeGame.class
SnakeGame.class,
RaceGame.class
};
Menu.setGames(GAMES);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public void run() {

if (--countdown < 0) {
this.kill();
// TODO : fix NullPointerException
finalize.accept(this);
return;
}
Expand Down
88 changes: 88 additions & 0 deletions src/main/java/com/github/vitalibo/brickgame/game/race/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.github.vitalibo.brickgame.game.race;

import com.github.vitalibo.brickgame.core.Controllable;
import com.github.vitalibo.brickgame.core.GameException;
import com.github.vitalibo.brickgame.game.Point;
import com.github.vitalibo.brickgame.game.Shape;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Delegate;

import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Car implements List<Point>, Controllable {

private static final Shape CAR = Shape.of(3, 0x2, 0x7, 0x2, 0x5);
private static final Random random = new Random();

@Delegate
private final List<Point> car;

@Override
public void doDown() {
forEach(Point::doDown);
}

@Override
public void doLeft() {
if (get(0).getX() < 4) {
return;
}

IntStream.range(0, 3)
.forEach(i -> this.forEach(Point::doLeft));
}

@Override
public void doRight() {
if (get(0).getX() > 5) {
return;
}

IntStream.range(0, 3)
.forEach(i -> this.forEach(Point::doRight));
}

@Override
public void doUp() {
throw new UnsupportedOperationException("doUp");
}

@Override
public void doRotate() {
throw new UnsupportedOperationException("doRotate");
}

public void verifyCrash(List<Car> cars) {
Optional<Point> point = cars.stream()
.flatMap(Car::stream)
.filter(this::contains)
.findFirst();

if (point.isPresent()) {
throw new GameException(point.get(), "car crashed");
}
}

public static Car init() {
return on(Point.of(17, 3));
}

public static Car generate() {
return on(Point.of(-3, random.nextBoolean() ? 3 : 6));
}

public static Car on(Point point) {
List<Point> points = CAR.apply(point)
.peek(p -> p.doMove(-1, -1))
.collect(Collectors.toList());

return new Car(points);
}

}
120 changes: 120 additions & 0 deletions src/main/java/com/github/vitalibo/brickgame/game/race/RaceGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package com.github.vitalibo.brickgame.game.race;

import com.github.vitalibo.brickgame.core.Context;
import com.github.vitalibo.brickgame.core.GameException;
import com.github.vitalibo.brickgame.game.Game;
import com.github.vitalibo.brickgame.util.CanvasTranslator;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

public class RaceGame extends Game {

@Getter
private Car car;
@Getter
private List<Car> cars;
@Getter
private Road road;

public RaceGame(Context context) {
super(context);
setUp();
}

private void setUp() {
score.set(0);
life.set(3);
}

@Override
public void init() {
car = Car.init();
cars = new ArrayList<>();
cars.add(Car.generate());
road = Road.init();

kernel.job(this, 300 - speed.get() * 18, job -> onMove());
}

private void onMove() {
cars.forEach(Car::doDown);
road.doDown();

if (road.getTraffic() % 9 == 0) {
cars.add(Car.generate());

if (cars.size() > 3) {
cars.remove(0);
}
}

score.inc(10);
repaint();

try {
car.verifyCrash(cars);
} catch (GameException e) {
crash(e.getPoint());
}

verifyLevelUp();
}

@Override
public void doDown() {
}

@Override
public void doLeft() {
car.doLeft();

repaint();
try {
car.verifyCrash(cars);
} catch (GameException e) {
crash(e.getPoint());
}
}

@Override
public void doRight() {
car.doRight();

repaint();
try {
car.verifyCrash(cars);
} catch (GameException e) {
crash(e.getPoint());
}
}

@Override
public void doUp() {
onMove();
}

@Override
public void doRotate() {
onMove();
}

private void verifyLevelUp() {
if (road.getTraffic() < 1000) {
return;
}

kernel.forEach((s, job) -> job.kill());
speed.inc();
init();
}

private void repaint() {
boolean[][] from = CanvasTranslator.from(
car.stream(), cars.stream().flatMap(Car::stream), road.stream());

board.draw(from);
}

}
47 changes: 47 additions & 0 deletions src/main/java/com/github/vitalibo/brickgame/game/race/Road.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.vitalibo.brickgame.game.race;

import com.github.vitalibo.brickgame.core.GameException;
import com.github.vitalibo.brickgame.game.Point;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Delegate;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Road implements List<Point> {

@Delegate
private final List<Point> points;
@Getter
private int traffic;

public void doDown() {
for (Point point : this) {
point.doDown();
try {
point.verify();
} catch (GameException e) {
point.setY(0);
}
}

traffic++;
}

public static Road init() {
List<Point> points = IntStream.range(0, 20)
.filter(i -> i % 4 != 0)
.mapToObj(i -> Stream.of(Point.of(i, 0), Point.of(i, 9)))
.flatMap(stream -> stream)
.collect(Collectors.toList());

return new Road(new CopyOnWriteArrayList<>(points));
}

}
84 changes: 84 additions & 0 deletions src/test/java/com/github/vitalibo/brickgame/game/race/CarTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.github.vitalibo.brickgame.game.race;

import com.github.vitalibo.brickgame.core.GameException;
import com.github.vitalibo.brickgame.game.Point;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CarTest {

private Car car;

@BeforeMethod
public void setUp() {
car = Car.on(Point.of(5, 5));
}

@Test
public void testDown() {
Point point = representLikePoint(car);

car.doDown();
Point npoint = representLikePoint(car);

Assert.assertEquals(npoint.getY() - point.getY(), 1);
Assert.assertEquals(npoint.getX(), point.getX());
}

@Test
public void testLeft() {
Point point = representLikePoint(car);

car.doLeft();
Point npoint = representLikePoint(car);

Assert.assertEquals(npoint.getY(), point.getY());
Assert.assertEquals(npoint.getX() - point.getX(), -3);
}

@Test
public void testRight() {
Point point = representLikePoint(car);

car.doRight();
Point npoint = representLikePoint(car);

Assert.assertEquals(npoint.getY(), point.getY());
Assert.assertEquals(npoint.getX() - point.getX(), 3);
}

@Test(expectedExceptions = GameException.class)
public void testCarCrashed() {
car.verifyCrash(Collections.singletonList(car));
}

@Test
public void testVerifyPassed() {
List<Car> cars = IntStream.range(0, 3)
.mapToObj(i -> Car.generate())
.collect(Collectors.toList());

car.verifyCrash(cars);

Assert.assertTrue(true);
}

private static Point representLikePoint(Car car) {
return Point.of(max(car, Point::getY), max(car, Point::getX));
}

private static int max(Car car, Function<Point, Integer> function) {
return car.stream()
.map(function)
.max(Integer::compareTo)
.orElseThrow(AssertionError::new);
}

}
Loading

0 comments on commit 34dd857

Please sign in to comment.