DEADSOFTWARE

43fc1641033616ec6645795ead6daed286dc82e3
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / world / GameWorld.java
1 package ru.deadsoftware.cavedroid.game.world;
3 import com.badlogic.gdx.utils.Disposable;
4 import com.badlogic.gdx.utils.Timer;
5 import kotlin.Pair;
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 @GameScope
19 public class GameWorld implements Disposable {
21 private static final int UPDATE_RANGE = 16;
23 private final DropController mDropController;
24 private final MobsController mMobsController;
26 private final Timer mGameFluidsTimer;
27 private final GameFluidsThread mGameFluidsThread;
29 private final int mWidth;
30 private final int mHeight;
31 private final int[][] mForeMap;
32 private final int[][] mBackMap;
34 private boolean mShouldUpdate;
35 private int mUpdateX;
36 private int mUpdateY;
38 @Inject
39 public GameWorld(DropController dropController,
40 MobsController mobsController,
41 @CheckForNull int[][] foreMap,
42 @CheckForNull int[][] backMap) {
43 mDropController = dropController;
44 mMobsController = mobsController;
46 boolean isNewGame = foreMap == null || backMap == null;
48 if (isNewGame) {
49 final WorldGeneratorConfig config = WorldGeneratorConfig.Companion.getDefault();
50 mWidth = config.getWidth();
51 mHeight = config.getHeight();
52 Pair<int[][], int[][]> maps = new GameWorldGenerator(config).generate();
53 mForeMap = maps.getFirst();
54 mBackMap = maps.getSecond();
55 mMobsController.getPlayer().respawn(this);
56 } else {
57 mForeMap = foreMap;
58 mBackMap = backMap;
59 mWidth = mForeMap.length;
60 mHeight = mForeMap[0].length;
61 }
63 mGameFluidsThread = new GameFluidsThread(this, mMobsController);
65 mGameFluidsTimer = new Timer();
66 mGameFluidsTimer.scheduleTask(mGameFluidsThread, 0, GameFluidsThread.FLUID_UPDATE_INTERVAL_SEC);
67 }
69 public int getWidth() {
70 return mWidth;
71 }
73 public int getHeight() {
74 return mHeight;
75 }
77 public float getWidthPx() {
78 return mWidth * 16f;
79 }
81 public float getHeightPx() {
82 return mHeight * 16f;
83 }
85 public int[][] getFullForeMap() {
86 return mForeMap;
87 }
89 public int[][] getFullBackMap() {
90 return mBackMap;
91 }
93 private int transformX(int x) {
94 x = x % getWidth();
95 if (x < 0) {
96 x = getWidth() - Math.abs(x);
97 }
98 return x;
99 }
101 private int getMap(int x, int y, int layer) {
102 int map = 0;
103 try {
104 x = transformX(x);
105 map = (layer == 0) ? mForeMap[x][y] : mBackMap[x][y];
106 } catch (ArrayIndexOutOfBoundsException ignored) {
108 return map;
111 private void setMap(int x, int y, int layer, int value) {
112 try {
113 x = transformX(x);
114 if (layer == 0) {
115 mForeMap[x][y] = value;
116 } else {
117 mBackMap[x][y] = value;
119 } catch (ArrayIndexOutOfBoundsException ignored) {
123 public boolean hasForeAt(int x, int y) {
124 return getMap(x, y, 0) != 0;
127 public boolean hasBackAt(int x, int y) {
128 return getMap(x, y, 1) != 0;
131 public int getForeMap(int x, int y) {
132 return getMap(x, y, 0);
135 public Block getForeMapBlock(int x, int y) {
136 return GameItems.getBlock(getMap(x, y, 0));
139 public void setForeMap(int x, int y, int id) {
140 setMap(x, y, 0, id);
143 public int getBackMap(int x, int y) {
144 return getMap(x, y, 1);
147 public Block getBackMapBlock(int x, int y) {
148 return GameItems.getBlock(getMap(x, y, 1));
151 public void setBackMap(int x, int y, int id) {
152 setMap(x, y, 1, id);
155 private void placeSlab(int x, int y, int value) {
156 switch (value) {
157 case 51:
158 setForeMap(x, y, 52);
159 break;
160 case 53:
161 setForeMap(x, y, 21);
162 break;
163 case 54:
164 setForeMap(x, y, 5);
165 break;
166 case 55:
167 setForeMap(x, y, 4);
168 break;
169 case 56:
170 setForeMap(x, y, 28);
171 break;
172 case 58:
173 setForeMap(x, y, 57);
174 break;
178 public void placeToForeground(int x, int y, int value) {
179 if (!hasForeAt(x, y) || value == 0 || !GameItems.getBlock(getForeMap(x, y)).hasCollision()) {
180 setForeMap(x, y, value);
181 } else if (GameItems.isSlab(value) && getForeMap(x, y) == value) {
182 placeSlab(x, y, value);
184 mUpdateX = x - 8;
185 mUpdateY = y - 8;
186 mShouldUpdate = true;
189 public void placeToBackground(int x, int y, int value) {
190 if (value == 0 || (getBackMap(x, y) == 0 && GameItems.getBlock(value).hasCollision()) &&
191 (!GameItems.getBlock(value).isTransparent() || value == 18)) {
192 setBackMap(x, y, value);
196 public void destroyForeMap(int x, int y) {
197 Block block = GameItems.getBlock(getForeMap(x, y));
198 if (block.hasDrop()) {
199 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop()));
201 placeToForeground(x, y, 0);
204 public void destroyBackMap(int x, int y) {
205 Block block = GameItems.getBlock(getBackMap(x, y));
206 if (block.hasDrop()) {
207 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop()));
209 placeToBackground(x, y, 0);
212 private void updateBlock(int x, int y) {
213 if (getForeMap(x, y) == 10) {
214 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
215 setForeMap(x, y, 0);
216 mMobsController.addMob(new FallingSand(x * 16, y * 16));
217 updateBlock(x, y - 1);
221 if (getForeMap(x, y) == 11) {
222 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
223 setForeMap(x, y, 0);
224 mMobsController.addMob(new FallingGravel(x * 16, y * 16));
225 updateBlock(x, y - 1);
229 if (hasForeAt(x, y) && getForeMapBlock(x, y).requiresBlock()) {
230 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
231 destroyForeMap(x, y);
232 updateBlock(x, y - 1);
236 if (getForeMap(x, y) == 2) {
237 if (hasForeAt(x, y - 1) && (getForeMapBlock(x, y - 1).hasCollision() ||
238 GameItems.isFluid(getForeMap(x, y - 1)))) {
239 setForeMap(x, y, 3);
244 public void update() {
245 if (mShouldUpdate) {
246 for (int y = mUpdateY; y < mUpdateY + UPDATE_RANGE; y++) {
247 for (int x = mUpdateX; x < mUpdateX + UPDATE_RANGE; x++) {
248 updateBlock(x, y);
251 mShouldUpdate = false;
255 @Override
256 public void dispose() {
257 mGameFluidsThread.cancel();