DEADSOFTWARE

60a34e14353704bc0c76d52b505efa80cb9f7b58
[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.TimeUtils;
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.objects.Block;
12 import ru.deadsoftware.cavedroid.game.objects.DropController;
14 import javax.annotation.CheckForNull;
15 import javax.inject.Inject;
16 import java.sql.Time;
17 import java.util.Timer;
19 @GameScope
20 public class GameWorld implements Disposable {
22 private static final int DEFAULT_WIDTH = 1024;
23 private static final int DEFAULT_HEIGHT = 256;
24 private static final int UPDATE_RANGE = 16;
26 private final DropController mDropController;
27 private final MobsController mMobsController;
29 private final Timer mGameFluidsTimer;
30 private final GameFluidsThread mGameFluidsThread;
32 private final int mWidth;
33 private final int mHeight;
34 private final int[][] mForeMap;
35 private final int[][] mBackMap;
37 private boolean mShouldUpdate;
38 private int mUpdateX;
39 private int mUpdateY;
41 @Inject
42 public GameWorld(DropController dropController,
43 MobsController mobsController,
44 @CheckForNull int[][] foreMap,
45 @CheckForNull int[][] backMap) {
46 mDropController = dropController;
47 mMobsController = mobsController;
49 boolean isNewGame = foreMap == null || backMap == null;
51 if (isNewGame) {
52 mWidth = DEFAULT_WIDTH;
53 mHeight = DEFAULT_HEIGHT;
54 Pair<int[][], int[][]> maps = GameWorldGenerator.INSTANCE.generate(mWidth, mHeight, TimeUtils.millis());
55 mForeMap = maps.getFirst();
56 mBackMap = maps.getSecond();
57 mMobsController.getPlayer().respawn(this);
58 } else {
59 mForeMap = foreMap;
60 mBackMap = backMap;
61 mWidth = mForeMap.length;
62 mHeight = mForeMap[0].length;
63 }
65 mGameFluidsThread = new GameFluidsThread(this, mMobsController, Thread.currentThread());
67 mGameFluidsTimer = new Timer();
68 mGameFluidsTimer.scheduleAtFixedRate(mGameFluidsThread, 0, GameFluidsThread.FLUID_UPDATE_INTERVAL_MS);
69 }
71 public int getWidth() {
72 return mWidth;
73 }
75 public int getHeight() {
76 return mHeight;
77 }
79 public float getWidthPx() {
80 return mWidth * 16f;
81 }
83 public float getHeightPx() {
84 return mHeight * 16f;
85 }
87 public int[][] getFullForeMap() {
88 return mForeMap;
89 }
91 public int[][] getFullBackMap() {
92 return mBackMap;
93 }
95 private int transformX(int x) {
96 x = x % getWidth();
97 if (x < 0) {
98 x = getWidth() - Math.abs(x);
99 }
100 return x;
103 private int getMap(int x, int y, int layer) {
104 int map = 0;
105 try {
106 x = transformX(x);
107 map = (layer == 0) ? mForeMap[x][y] : mBackMap[x][y];
108 } catch (ArrayIndexOutOfBoundsException ignored) {
110 return map;
113 private void setMap(int x, int y, int layer, int value) {
114 try {
115 x = transformX(x);
116 if (layer == 0) {
117 mForeMap[x][y] = value;
118 } else {
119 mBackMap[x][y] = value;
121 } catch (ArrayIndexOutOfBoundsException ignored) {
125 public boolean hasForeAt(int x, int y) {
126 return getMap(x, y, 0) != 0;
129 public boolean hasBackAt(int x, int y) {
130 return getMap(x, y, 1) != 0;
133 public int getForeMap(int x, int y) {
134 return getMap(x, y, 0);
137 public Block getForeMapBlock(int x, int y) {
138 return GameItems.getBlock(getMap(x, y, 0));
141 public void setForeMap(int x, int y, int id) {
142 setMap(x, y, 0, id);
145 public int getBackMap(int x, int y) {
146 return getMap(x, y, 1);
149 public Block getBackMapBlock(int x, int y) {
150 return GameItems.getBlock(getMap(x, y, 1));
153 public void setBackMap(int x, int y, int id) {
154 setMap(x, y, 1, id);
157 private void placeSlab(int x, int y, int value) {
158 switch (value) {
159 case 51:
160 setForeMap(x, y, 52);
161 break;
162 case 53:
163 setForeMap(x, y, 21);
164 break;
165 case 54:
166 setForeMap(x, y, 5);
167 break;
168 case 55:
169 setForeMap(x, y, 4);
170 break;
171 case 56:
172 setForeMap(x, y, 28);
173 break;
174 case 58:
175 setForeMap(x, y, 57);
176 break;
180 public void placeToForeground(int x, int y, int value) {
181 if (!hasForeAt(x, y) || value == 0 || !GameItems.getBlock(getForeMap(x, y)).hasCollision()) {
182 setForeMap(x, y, value);
183 } else if (GameItems.isSlab(value) && getForeMap(x, y) == value) {
184 placeSlab(x, y, value);
186 mUpdateX = x - 8;
187 mUpdateY = y - 8;
188 mShouldUpdate = true;
191 public void placeToBackground(int x, int y, int value) {
192 if (value == 0 || (getBackMap(x, y) == 0 && GameItems.getBlock(value).hasCollision()) &&
193 (!GameItems.getBlock(value).isTransparent() || value == 18)) {
194 setBackMap(x, y, value);
198 public void destroyForeMap(int x, int y) {
199 Block block = GameItems.getBlock(getForeMap(x, y));
200 if (block.hasDrop()) {
201 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop()));
203 placeToForeground(x, y, 0);
206 public void destroyBackMap(int x, int y) {
207 Block block = GameItems.getBlock(getBackMap(x, y));
208 if (block.hasDrop()) {
209 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop()));
211 placeToBackground(x, y, 0);
214 private void updateBlock(int x, int y) {
215 if (getForeMap(x, y) == 10) {
216 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
217 setForeMap(x, y, 0);
218 mMobsController.addMob(FallingSand.class, x * 16, y * 16);
219 updateBlock(x, y - 1);
220 }
223 if (getForeMap(x, y) == 11) {
224 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
225 setForeMap(x, y, 0);
226 mMobsController.addMob(FallingGravel.class, x * 16, y * 16);
227 updateBlock(x, y - 1);
231 if (hasForeAt(x, y) && getForeMapBlock(x, y).requiresBlock()) {
232 if (!hasForeAt(x, y + 1) || !getForeMapBlock(x, y + 1).hasCollision()) {
233 destroyForeMap(x, y);
234 updateBlock(x, y - 1);
238 if (getForeMap(x, y) == 2) {
239 if (hasForeAt(x, y - 1) && (getForeMapBlock(x, y - 1).hasCollision() ||
240 GameItems.isFluid(getForeMap(x, y - 1)))) {
241 setForeMap(x, y, 3);
246 public void update() {
247 if (mShouldUpdate) {
248 for (int y = mUpdateY; y < mUpdateY + UPDATE_RANGE; y++) {
249 for (int x = mUpdateX; x < mUpdateX + UPDATE_RANGE; x++) {
250 updateBlock(x, y);
253 mShouldUpdate = false;
257 @Override
258 public void dispose() {
259 mGameFluidsTimer.cancel();