Skip to content

Commit

Permalink
multiple level structure and some polish.
Browse files Browse the repository at this point in the history
  • Loading branch information
angian00 committed Jan 20, 2022
1 parent 00155c2 commit f52e668
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 80 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](http:https://keepachangelog.com/).
## [Unreleased] - yyyy-mm-dd
...

## [0.5] - 2022-01-20
### Added
- multiple level structure
- small flash animation on newly added tiles
- highlight on mouse over clickable tile

### Changed
- Pipes can be overwritten if still empty of water

### Fixed
- crossing water paths in CROSS pipes
- removed duplicate stage.addActor()


## [0.4] - 2022-01-19
### Added
- water drawing
Expand Down
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ A clone of the old DOS game [Pipes -- aka PipeMania](https://www.freegameempire.
## Milestones


### v0.5
- levels
- overwriting pipes
### v0.6
- animations and polish:
- small flash on newly added tiles
- show better which tile is next
- show better which tile is next in preview
- small countdown on level start
- end-level message
- levels > 1
- speed increase inside level
- stats tuning by observing original game

### v0.7
- original logo
- original sound

### v0.8
- porting to web
- publishing (on itch.io?)
Binary file added core/assets/tile_border.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 4 additions & 22 deletions core/src/com/angian/libgdx/pipes/GameBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,6 @@ public GameBoard(LevelScreen ls, float x, float y, Stage s) {

}


public int countPipes() {
int nTiles = 0;

for (Actor a: getChildren()) {
if (!(a instanceof Tile))
continue;

Tile gtc = (Tile) a;
if (gtc.getPipe() != null)
nTiles ++;
}

return nTiles;
}



public PathItem followPipe(GridPoint2 fromPos, Direction fromDirection) {
Pipe fromPipe = getPipe(fromPos);
if (fromPipe == null)
Expand Down Expand Up @@ -116,16 +98,16 @@ private boolean isSourceValid(int i, int j, PipeType type) {
if (!type.isSource())
return false;

if (i == 0 && type == PipeType.SOURCE_LEFT)
if (i < 2 && type == PipeType.SOURCE_LEFT)
return false;

if (i == (N_TILES_X-1) && type == PipeType.SOURCE_RIGHT)
if (i >= (N_TILES_X-2) && type == PipeType.SOURCE_RIGHT)
return false;

if (j == 0 && type == PipeType.SOURCE_DOWN)
if (j < 2 && type == PipeType.SOURCE_DOWN)
return false;

if (j == (N_TILES_Y-1) && type == PipeType.SOURCE_UP)
if (j >= (N_TILES_Y-2) && type == PipeType.SOURCE_UP)
return false;

return true;
Expand Down
6 changes: 3 additions & 3 deletions core/src/com/angian/libgdx/pipes/LevelLayout.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ public class LevelLayout {
public static final int TILE_PREVIEW_PADDING = 20;

public static final Rectangle TIMER = new Rectangle(135, 380, 20, 500);
public static final Color TIMER_COLOR = Color.ORANGE;
public static final Color WATER_COLOR = Color.CYAN;


public static final int PIPE_INSIDE_SIZE = 30;
public static final int PIPE_BEND_RADIUS = 15;
public static final int PIPE_INSIDE_SIZE = 30 - 4;
public static final int PIPE_BEND_RADIUS = 15 - 2;
public static final int PIPE_BEND_STRAIGHT_LEN = 50;


Expand Down
31 changes: 31 additions & 0 deletions core/src/com/angian/libgdx/pipes/LevelParams.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.angian.libgdx.pipes;

public class LevelParams {
public float waterStartTime;
public float waterStartSpeed; //px per second
public int scoreFactor;
public int distance2win;

private LevelParams(float _waterStartTime, float _waterStartSpeed, int _scoreFactor, int _distance2win) {
waterStartTime = _waterStartTime;
waterStartSpeed = _waterStartSpeed;
scoreFactor = _scoreFactor;
distance2win = _distance2win;
}

public static LevelParams get(int level) {
if (level <= 0)
return null;

if (level == 1)
return new LevelParams(20, 20, 100, 5);

if (level == 2)
return new LevelParams(15, 30, 120, 7);

if (level == 3)
return new LevelParams(10, 40, 150, 9);

return new LevelParams(5, 60, 200, 11);
}
}
93 changes: 60 additions & 33 deletions core/src/com/angian/libgdx/pipes/LevelScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@
public class LevelScreen extends BaseScreen {
private static final int N_NEXT_TILES = 5;

//TODO: vary with level
//private static final float waterStartTime = 20; //in seconds, time before water starts
private static final float waterStartTime = 5;
private static final float waterSpeed = 20; //px per second
private static final int scoreFactor = 100;
private static final int distance2win = 5;
//
private final int nLevel;
private final LevelParams params;
private final int startScore;

private GameBoard board;
private Label levelLabel;
Expand All @@ -28,15 +24,28 @@ public class LevelScreen extends BaseScreen {
private WaterTimer waterTimer;
private Water water;

private int nLevel = 1;
private int nAddedTiles = 0;
private int score = 0;
private int nWaterTiles = 0;
private int score;
private Runnable clickCallback;


private List<PipeType> nextPipes;

private Label textOverlay;


public LevelScreen() {
this(1, 0);
}

public LevelScreen(int _level, int _startScore) {
nLevel = _level;
startScore = _startScore;

params = LevelParams.get(nLevel);
}


@Override
protected void initialize() {
BaseActor gameBackground = new BaseActor(0, 0, mainStage);
Expand All @@ -46,23 +55,23 @@ protected void initialize() {
Rectangle boardRect = LevelLayout.standard2gdxCoords(LevelLayout.BOARD);
board = new GameBoard(this, boardRect.x, boardRect.y, mainStage);

levelLabel = new Label("level: 1", Styles.labelStyle);
levelLabel = new Label("level: x", Styles.labelStyle);
levelLabel.setAlignment(LevelLayout.TEXT_LEVEL_ALIGN);
Rectangle labelRect = LevelLayout.standard2gdxCoords(LevelLayout.TEXT_LEVEL);
levelLabel.setPosition(labelRect.x, labelRect.y);
levelLabel.setWidth(labelRect.width);
levelLabel.setHeight(labelRect.height);
mainStage.addActor(levelLabel);

scoreLabel = new Label("score: 0", Styles.labelStyle);
scoreLabel = new Label("score: x", Styles.labelStyle);
scoreLabel.setAlignment(LevelLayout.TEXT_SCORE_ALIGN);
labelRect = LevelLayout.standard2gdxCoords(LevelLayout.TEXT_SCORE);
scoreLabel.setPosition(labelRect.x, labelRect.y);
scoreLabel.setWidth(labelRect.width);
scoreLabel.setHeight(labelRect.height);
mainStage.addActor(scoreLabel);

distanceLabel = new Label("distance: " + distance2win, Styles.labelStyle);
distanceLabel = new Label("distance: x", Styles.labelStyle);
distanceLabel.setAlignment(LevelLayout.TEXT_DISTANCE_ALIGN);
labelRect = LevelLayout.standard2gdxCoords(LevelLayout.TEXT_DISTANCE);
distanceLabel.setPosition(labelRect.x, labelRect.y);
Expand All @@ -77,7 +86,6 @@ protected void initialize() {
Tile tilePreview = new Tile(mainStage);
tilePreview.setPosition(previewRect.x + 5, previewRect.y + 10 + (LevelLayout.TILE_SIZE + LevelLayout.TILE_PREVIEW_PADDING) * i);
pipePreviews.add(tilePreview);
//mainStage.addActor(tilePreview);
}

nextPipes = new ArrayList<>();
Expand All @@ -88,43 +96,38 @@ protected void initialize() {


Rectangle timerRect = LevelLayout.standard2gdxCoords(LevelLayout.TIMER);
waterTimer = new WaterTimer(waterStartTime, timerRect, mainStage);
waterTimer.setColor(LevelLayout.TIMER_COLOR);
//mainStage.addActor(waterTimer);
waterTimer = new WaterTimer(timerRect, mainStage);
waterTimer.setColor(LevelLayout.WATER_COLOR);


textOverlay = new Label("", Styles.labelStyle);
textOverlay.setFontScale(4.0f);
textOverlay = new Label("", Styles.titleStyle);
textOverlay.setColor(Color.ORANGE);
textOverlay.setVisible(false);
uiTable.add(textOverlay).center();
}

@Override
protected void update(float dt) {
int nAddedTilesNew = board.countPipes();
if (nAddedTilesNew > nAddedTiles) {
nAddedTiles = nAddedTilesNew;
if (!waterTimer.isStarted()) {
waterTimer.start(params.waterStartTime);

//spawn new tile
nextPipes.remove(0);
nextPipes.add(PipeType.randomPlayableType());
updatePipePreview();
levelLabel.setText("level: " + nLevel);
scoreLabel.setText("score: " + startScore);
distanceLabel.setText("distance: " + params.distance2win);
}

if (waterTimer.isExpired() && water == null) {
//instantiate water
System.out.println("Water is starting!");
water = new Water(waterSpeed, board, mainStage);
//mainStage.addActor(water);
water = new Water(params.waterStartSpeed, board, mainStage);
}

if (water != null) {
int nWaterTiles = water.getPath().size() - 1;
score = nWaterTiles * scoreFactor;
nWaterTiles = water.getPath().size() - 1;
score = startScore + nWaterTiles * params.scoreFactor;
scoreLabel.setText("score: " + score);

int distance2go = distance2win - nWaterTiles;
int distance2go = params.distance2win - nWaterTiles;
if (distance2go < 0)
distance2go = 0;
distanceLabel.setText("distance: " + distance2go);
Expand All @@ -135,9 +138,33 @@ protected void update(float dt) {
}
}

public void spawnPipe() {
nextPipes.remove(0);
nextPipes.add(PipeType.randomPlayableType());
updatePipePreview();
}

private void endLevel() {
textOverlay.setText("Game over");
textOverlay.setVisible(true);
if (nWaterTiles < params.distance2win) {
textOverlay.setText("Game over");
//textOverlay.setSubtitle("Click to restart");
clickCallback = () -> PipesGame.setActiveScreen(new MenuScreen());
textOverlay.setVisible(true);
} else {
textOverlay.setText("Level complete");
//textOverlay.setSubtitle("Click to proceed to next level");
clickCallback = () -> PipesGame.setActiveScreen(new LevelScreen(nLevel + 1, score));
textOverlay.setVisible(true);
}
}

public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if (clickCallback != null) {
clickCallback.run();
return true;
} else {
return false;
}
}

private void updatePipePreview() {
Expand Down
23 changes: 22 additions & 1 deletion core/src/com/angian/libgdx/pipes/Pipe.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.angian.libgdx.pipes;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;

import java.util.HashMap;
import java.util.Map;

public class Pipe extends BaseActor {
private final PipeType type;
private final Map<Direction, Boolean> validDirections;
private WaterInPipe waterInPipe;
private final Map<Direction, WaterInPipe> waterMap = new HashMap<>(); //NB: only CROSS pipes have >1 waterInPipe children


public Pipe(PipeType t, Stage s) {
super(s);
setOpacity(0.0f);

type = t;
validDirections = new HashMap<>();
Expand Down Expand Up @@ -122,11 +126,28 @@ public Direction followPipe(Direction inDir) {


public void setWaterLevel(float waterLevel, Direction from, Direction to) {
WaterInPipe waterInPipe = waterMap.get(from);

if (waterInPipe == null) {
waterInPipe = new WaterInPipe(this, from, to, getStage());
waterMap.put(from, waterInPipe);
this.addActor(waterInPipe);
}

waterInPipe.setWaterLevel(waterLevel);
}

public boolean hasWater() {
return (waterMap.size() > 0);
}

public void flashIn() {
float duration = 0.25f;

Action flashOut = Actions.parallel(
Actions.color(Color.WHITE, duration),
Actions.fadeIn(duration)
);
addAction(flashOut);
}
}
10 changes: 7 additions & 3 deletions core/src/com/angian/libgdx/pipes/Styles.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

public class Styles {
public static Label.LabelStyle labelStyle;
public static Label.LabelStyle titleStyle;

static {
initStyles();
Expand All @@ -22,10 +23,13 @@ private static void initStyles() {
fontParameters.minFilter = Texture.TextureFilter.Linear;
fontParameters.magFilter = Texture.TextureFilter.Linear;

BitmapFont customFont;
customFont = fontGenerator.generateFont(fontParameters);

BitmapFont customFont = fontGenerator.generateFont(fontParameters);
labelStyle = new Label.LabelStyle();
labelStyle.font = customFont;

fontParameters.size = 3 * LevelLayout.TEXT_FONT_SIZE;
customFont = fontGenerator.generateFont(fontParameters);
titleStyle = new Label.LabelStyle();
titleStyle.font = customFont;
}
}
Loading

0 comments on commit f52e668

Please sign in to comment.