1 package ru
.deadsoftware
.cavedroid
.game
.world
;
3 import com
.badlogic
.gdx
.utils
.Disposable
;
4 import com
.badlogic
.gdx
.utils
.TimeUtils
;
6 import ru
.deadsoftware
.cavedroid
.game
.GameItems
;
7 import ru
.deadsoftware
.cavedroid
.game
.GameScope
;
8 import ru
.deadsoftware
.cavedroid
.game
.mobs
.FallingGravel
;
9 import ru
.deadsoftware
.cavedroid
.game
.mobs
.FallingSand
;
10 import ru
.deadsoftware
.cavedroid
.game
.mobs
.MobsController
;
11 import ru
.deadsoftware
.cavedroid
.game
.model
.world
.generator
.WorldGeneratorConfig
;
12 import ru
.deadsoftware
.cavedroid
.game
.objects
.Block
;
13 import ru
.deadsoftware
.cavedroid
.game
.objects
.DropController
;
15 import javax
.annotation
.CheckForNull
;
16 import javax
.inject
.Inject
;
18 import java
.util
.Timer
;
21 public class GameWorld
implements Disposable
{
23 private static final int DEFAULT_WIDTH
= 1024;
24 private static final int DEFAULT_HEIGHT
= 256;
25 private static final int UPDATE_RANGE
= 16;
27 private final DropController mDropController
;
28 private final MobsController mMobsController
;
30 private final Timer mGameFluidsTimer
;
31 private final GameFluidsThread mGameFluidsThread
;
33 private final int mWidth
;
34 private final int mHeight
;
35 private final int[][] mForeMap
;
36 private final int[][] mBackMap
;
38 private boolean mShouldUpdate
;
43 public GameWorld(DropController dropController
,
44 MobsController mobsController
,
45 @CheckForNull int[][] foreMap
,
46 @CheckForNull int[][] backMap
) {
47 mDropController
= dropController
;
48 mMobsController
= mobsController
;
50 boolean isNewGame
= foreMap
== null || backMap
== null;
53 mWidth
= DEFAULT_WIDTH
;
54 mHeight
= DEFAULT_HEIGHT
;
55 Pair
<int[][], int[][]> maps
= new GameWorldGenerator(WorldGeneratorConfig
.Companion
.getDefaultWithSeed(TimeUtils
.millis())).generate();
56 mForeMap
= maps
.getFirst();
57 mBackMap
= maps
.getSecond();
58 mMobsController
.getPlayer().respawn(this);
62 mWidth
= mForeMap
.length
;
63 mHeight
= mForeMap
[0].length
;
66 mGameFluidsThread
= new GameFluidsThread(this, mMobsController
, Thread
.currentThread());
68 mGameFluidsTimer
= new Timer();
69 mGameFluidsTimer
.scheduleAtFixedRate(mGameFluidsThread
, 0, GameFluidsThread
.FLUID_UPDATE_INTERVAL_MS
);
72 public int getWidth() {
76 public int getHeight() {
80 public float getWidthPx() {
84 public float getHeightPx() {
88 public int[][] getFullForeMap() {
92 public int[][] getFullBackMap() {
96 private int transformX(int x
) {
99 x
= getWidth() - Math
.abs(x
);
104 private int getMap(int x
, int y
, int layer
) {
108 map
= (layer
== 0) ? mForeMap
[x
][y
] : mBackMap
[x
][y
];
109 } catch (ArrayIndexOutOfBoundsException ignored
) {
114 private void setMap(int x
, int y
, int layer
, int value
) {
118 mForeMap
[x
][y
] = value
;
120 mBackMap
[x
][y
] = value
;
122 } catch (ArrayIndexOutOfBoundsException ignored
) {
126 public boolean hasForeAt(int x
, int y
) {
127 return getMap(x
, y
, 0) != 0;
130 public boolean hasBackAt(int x
, int y
) {
131 return getMap(x
, y
, 1) != 0;
134 public int getForeMap(int x
, int y
) {
135 return getMap(x
, y
, 0);
138 public Block
getForeMapBlock(int x
, int y
) {
139 return GameItems
.getBlock(getMap(x
, y
, 0));
142 public void setForeMap(int x
, int y
, int id
) {
146 public int getBackMap(int x
, int y
) {
147 return getMap(x
, y
, 1);
150 public Block
getBackMapBlock(int x
, int y
) {
151 return GameItems
.getBlock(getMap(x
, y
, 1));
154 public void setBackMap(int x
, int y
, int id
) {
158 private void placeSlab(int x
, int y
, int value
) {
161 setForeMap(x
, y
, 52);
164 setForeMap(x
, y
, 21);
173 setForeMap(x
, y
, 28);
176 setForeMap(x
, y
, 57);
181 public void placeToForeground(int x
, int y
, int value
) {
182 if (!hasForeAt(x
, y
) || value
== 0 || !GameItems
.getBlock(getForeMap(x
, y
)).hasCollision()) {
183 setForeMap(x
, y
, value
);
184 } else if (GameItems
.isSlab(value
) && getForeMap(x
, y
) == value
) {
185 placeSlab(x
, y
, value
);
189 mShouldUpdate
= true;
192 public void placeToBackground(int x
, int y
, int value
) {
193 if (value
== 0 || (getBackMap(x
, y
) == 0 && GameItems
.getBlock(value
).hasCollision()) &&
194 (!GameItems
.getBlock(value
).isTransparent() || value
== 18)) {
195 setBackMap(x
, y
, value
);
199 public void destroyForeMap(int x
, int y
) {
200 Block block
= GameItems
.getBlock(getForeMap(x
, y
));
201 if (block
.hasDrop()) {
202 mDropController
.addDrop(transformX(x
) * 16 + 4, y
* 16 + 4, GameItems
.getItemId(block
.getDrop()));
204 placeToForeground(x
, y
, 0);
207 public void destroyBackMap(int x
, int y
) {
208 Block block
= GameItems
.getBlock(getBackMap(x
, y
));
209 if (block
.hasDrop()) {
210 mDropController
.addDrop(transformX(x
) * 16 + 4, y
* 16 + 4, GameItems
.getItemId(block
.getDrop()));
212 placeToBackground(x
, y
, 0);
215 private void updateBlock(int x
, int y
) {
216 if (getForeMap(x
, y
) == 10) {
217 if (!hasForeAt(x
, y
+ 1) || !getForeMapBlock(x
, y
+ 1).hasCollision()) {
219 mMobsController
.addMob(FallingSand
.class, x
* 16, y
* 16);
220 updateBlock(x
, y
- 1);
224 if (getForeMap(x
, y
) == 11) {
225 if (!hasForeAt(x
, y
+ 1) || !getForeMapBlock(x
, y
+ 1).hasCollision()) {
227 mMobsController
.addMob(FallingGravel
.class, x
* 16, y
* 16);
228 updateBlock(x
, y
- 1);
232 if (hasForeAt(x
, y
) && getForeMapBlock(x
, y
).requiresBlock()) {
233 if (!hasForeAt(x
, y
+ 1) || !getForeMapBlock(x
, y
+ 1).hasCollision()) {
234 destroyForeMap(x
, y
);
235 updateBlock(x
, y
- 1);
239 if (getForeMap(x
, y
) == 2) {
240 if (hasForeAt(x
, y
- 1) && (getForeMapBlock(x
, y
- 1).hasCollision() ||
241 GameItems
.isFluid(getForeMap(x
, y
- 1)))) {
247 public void update() {
249 for (int y
= mUpdateY
; y
< mUpdateY
+ UPDATE_RANGE
; y
++) {
250 for (int x
= mUpdateX
; x
< mUpdateX
+ UPDATE_RANGE
; x
++) {
254 mShouldUpdate
= false;
259 public void dispose() {
260 mGameFluidsTimer
.cancel();