1 package ru
.deadsoftware
.cavedroid
.game
.world
;
3 import com
.badlogic
.gdx
.utils
.TimeUtils
;
4 import ru
.deadsoftware
.cavedroid
.game
.mobs
.MobsController
;
6 import java
.util
.Arrays
;
7 import java
.util
.TimerTask
;
9 import static ru
.deadsoftware
.cavedroid
.game
.GameItems
.*;
11 class GameFluidsThread
extends TimerTask
{
13 public static final int FLUID_UPDATE_INTERVAL_MS
= 100;
14 private static final int FLUID_STATES
= 5;
16 private static final int[] WATER_IDS
= {8, 60, 61, 62, 63};
17 private static final int[] LAVA_IDS
= {9, 64, 65, 66, 67};
19 private long mFluidLastUpdateTimestamp
= 0;
21 private final GameWorld mGameWorld
;
22 private final MobsController mMobsController
;
24 private final Thread mMainThread
;
26 GameFluidsThread(GameWorld gameWorld
,
27 MobsController mobsController
,
29 mGameWorld
= gameWorld
;
30 mMobsController
= mobsController
;
31 mMainThread
= mainThread
;
34 private int getBlockState(int id
) {
35 return isWater(id
) ? Arrays
.binarySearch(WATER_IDS
, id
) : Arrays
.binarySearch(LAVA_IDS
, id
);
38 private int getNextBlockState(int id
) {
42 int state
= getBlockState(id
);
43 if (state
< FLUID_STATES
- 1) {
49 private int getNextBlockStateId(int id
) {
50 int nextState
= getNextBlockState(id
);
51 if (nextState
== -1) {
55 return WATER_IDS
[nextState
];
57 return LAVA_IDS
[nextState
];
60 private int id(int x
, int y
) {
61 return mGameWorld
.getForeMap(x
, y
);
64 private boolean sameFluid(int thisId
, int thatId
) {
65 return isFluid(thatId
) && isWater(thatId
) == isWater(thisId
);
68 private boolean noFluidNearby(int x
, int y
) {
69 return !isFluid(id(x
, y
- 1)) &&
70 (!isFluid(id(x
- 1, y
)) || id(x
- 1, y
) >= id(x
, y
)) &&
71 (!isFluid(id(x
+ 1, y
)) || id(x
+ 1, y
) >= id(x
, y
));
74 private boolean drainFluid(int x
, int y
) {
75 if (getBlockState(id(x
, y
)) > 0) {
76 if (noFluidNearby(x
, y
)) {
77 mGameWorld
.setForeMap(x
, y
, getNextBlockStateId(id(x
, y
)));
79 if (!isFluid(id(x
, y
))) {
80 mGameWorld
.setForeMap(x
, y
, 0);
87 private void flowFluidTo(int thisId
, int x
, int y
, int nextStateId
) {
88 int thatId
= id(x
, y
);
89 if (fluidCanFlowThere(thisId
, thatId
)) {
90 mGameWorld
.setForeMap(x
, y
, nextStateId
);
91 } else if (isWater(thisId
) && isLava(thatId
)) {
92 if (getBlockState(thatId
) > 0) {
93 mGameWorld
.setForeMap(x
, y
, 4); //cobblestone
95 mGameWorld
.setForeMap(x
, y
, 68); //obsidian
97 } else if (isLava(thisId
) && isWater(thatId
)) {
98 mGameWorld
.setForeMap(x
, y
, 1); //stone
102 private void flowFluid(int x
, int y
) {
104 if (getBlockState(id
) < FLUID_STATES
- 1 && getBlock(id(x
, y
+ 1)).hasCollision()) {
105 int nextState
= getNextBlockState(id
);
106 int nextStateId
= getNextBlockStateId(id
);
107 if (nextState
== 1) {
110 flowFluidTo(id
, x
- 1, y
, nextStateId
);
111 flowFluidTo(id
, x
+ 1, y
, nextStateId
);
113 flowFluidTo(id
, x
, y
+ 1, isWater(id
) ? WATER_IDS
[1] : LAVA_IDS
[1]);
118 private void updateFluids(int x
, int y
) {
119 if (!isFluid(id(x
, y
))) {
122 if (drainFluid(x
, y
)) {
128 private void fluidUpdater() {
129 int midScreen
= (int) mMobsController
.getPlayer().x
/ 16;
130 for (int y
= mGameWorld
.getHeight() - 1; y
>= 0; y
--) {
131 for (int x
= 0; x
<= mGameWorld
.getWidth() / 2; x
++) {
132 updateFluids(midScreen
+ x
, y
);
133 updateFluids(midScreen
- x
, y
);
138 private boolean timeToUpdate() {
139 if (TimeUtils
.timeSinceMillis(mFluidLastUpdateTimestamp
) >= FLUID_UPDATE_INTERVAL_MS
) {
140 mFluidLastUpdateTimestamp
= TimeUtils
.millis();