DEADSOFTWARE

d996cf42989c41a1025b54fb1c1fd2b77e053cf0
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / world / GameWorldFluidsLogicControllerTask.java
1 package ru.deadsoftware.cavedroid.game.world;
3 import com.badlogic.gdx.utils.Timer;
4 import ru.deadsoftware.cavedroid.game.GameScope;
5 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
7 import javax.inject.Inject;
8 import java.util.Arrays;
10 import static ru.deadsoftware.cavedroid.game.GameItems.*;
12 @GameScope
13 public class GameWorldFluidsLogicControllerTask extends Timer.Task {
15 public static final float FLUID_UPDATE_INTERVAL_SEC = 0.1f;
16 private static final int FLUID_STATES = 5;
18 private static final int[] WATER_IDS = {8, 60, 61, 62, 63};
19 private static final int[] LAVA_IDS = {9, 64, 65, 66, 67};
21 private final GameWorld mGameWorld;
22 private final MobsController mMobsController;
24 @Inject
25 GameWorldFluidsLogicControllerTask(GameWorld gameWorld,
26 MobsController mobsController) {
27 mGameWorld = gameWorld;
28 mMobsController = mobsController;
29 }
31 private int getBlockState(int id) {
32 return isWater(id) ? Arrays.binarySearch(WATER_IDS, id) : Arrays.binarySearch(LAVA_IDS, id);
33 }
35 private int getNextBlockState(int id) {
36 if (!isFluid(id)) {
37 return -1;
38 }
39 int state = getBlockState(id);
40 if (state < FLUID_STATES - 1) {
41 return state + 1;
42 }
43 return -1;
44 }
46 private int getNextBlockStateId(int id) {
47 int nextState = getNextBlockState(id);
48 if (nextState == -1) {
49 return 0;
50 }
51 if (isWater(id)) {
52 return WATER_IDS[nextState];
53 }
54 return LAVA_IDS[nextState];
55 }
57 private int id(int x, int y) {
58 return mGameWorld.getForeMap(x, y);
59 }
61 private boolean sameFluid(int thisId, int thatId) {
62 return isFluid(thatId) && isWater(thatId) == isWater(thisId);
63 }
65 private boolean noFluidNearby(int x, int y) {
66 return !isFluid(id(x, y - 1)) &&
67 (!isFluid(id(x - 1, y)) || id(x - 1, y) >= id(x, y)) &&
68 (!isFluid(id(x + 1, y)) || id(x + 1, y) >= id(x, y));
69 }
71 private boolean drainFluid(int x, int y) {
72 if (getBlockState(id(x, y)) > 0) {
73 if (noFluidNearby(x, y)) {
74 mGameWorld.setForeMap(x, y, getNextBlockStateId(id(x, y)));
75 }
76 if (!isFluid(id(x, y))) {
77 mGameWorld.setForeMap(x, y, 0);
78 return true;
79 }
80 }
81 return false;
82 }
84 private void flowFluidTo(int thisId, int x, int y, int nextStateId) {
85 int thatId = id(x, y);
86 if (fluidCanFlowThere(thisId, thatId)) {
87 mGameWorld.setForeMap(x, y, nextStateId);
88 } else if (isWater(thisId) && isLava(thatId)) {
89 if (getBlockState(thatId) > 0) {
90 mGameWorld.setForeMap(x, y, 4); //cobblestone
91 } else {
92 mGameWorld.setForeMap(x, y, 68); //obsidian
93 }
94 } else if (isLava(thisId) && isWater(thatId)) {
95 mGameWorld.setForeMap(x, y, 1); //stone
96 }
97 }
99 private void flowFluid(int x, int y) {
100 int id = id(x, y);
101 if (getBlockState(id) < FLUID_STATES - 1 && getBlock(id(x, y + 1)).hasCollision()) {
102 int nextState = getNextBlockState(id);
103 int nextStateId = getNextBlockStateId(id);
104 if (nextState == 1) {
105 nextStateId++;
107 flowFluidTo(id, x - 1, y, nextStateId);
108 flowFluidTo(id, x + 1, y, nextStateId);
109 } else {
110 flowFluidTo(id, x, y + 1, isWater(id) ? WATER_IDS[1] : LAVA_IDS[1]);
115 private void updateFluids(int x, int y) {
116 if (!isFluid(id(x, y))) {
117 return;
119 if (drainFluid(x, y)) {
120 return;
122 flowFluid(x, y);
125 private void fluidUpdater() {
126 int midScreen = (int) mMobsController.getPlayer().x / 16;
127 for (int y = mGameWorld.getHeight() - 1; y >= 0; y--) {
128 for (int x = 0; x <= mGameWorld.getWidth() / 2; x++) {
129 updateFluids(midScreen + x, y);
130 updateFluids(midScreen - x, y);
135 @Override
136 public void run() {
137 fluidUpdater();