DEADSOFTWARE

2bf6e7d096ab17912d6794841661a212841c1988
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / GameInput.java
1 package ru.deadsoftware.cavedroid.game;
2
3 import com.badlogic.gdx.Gdx;
4 import com.badlogic.gdx.Input;
5 import com.badlogic.gdx.graphics.g2d.TextureRegion;
6 import com.badlogic.gdx.math.MathUtils;
7 import com.badlogic.gdx.utils.TimeUtils;
8 import com.google.common.collect.Range;
9 import ru.deadsoftware.cavedroid.MainConfig;
10 import ru.deadsoftware.cavedroid.game.mobs.Mob;
11 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
12 import ru.deadsoftware.cavedroid.game.mobs.Pig;
13 import ru.deadsoftware.cavedroid.game.mobs.Player;
14 import ru.deadsoftware.cavedroid.game.objects.DropController;
15 import ru.deadsoftware.cavedroid.game.world.GameWorld;
16 import ru.deadsoftware.cavedroid.misc.Assets;
17 import ru.deadsoftware.cavedroid.misc.ControlMode;
18
19 import javax.inject.Inject;
20
21 import static ru.deadsoftware.cavedroid.game.GameItems.*;
22
23 @GameScope
24 public class GameInput {
25
26 private final MainConfig mMainConfig;
27 private final GameWorld mGameWorld;
28 private final DropController mDropController;
29 private final MobsController mMobsController;
30 private final Player mPlayer;
31
32 private ControlMode mControlMode;
33
34 private boolean mKeyDown;
35 private boolean mTouchedDown;
36 private boolean mDragging;
37
38 private int mKeyDownCode;
39 private int mTouchDownBtn;
40 private float mTouchDownX;
41 private float mTouchDownY;
42 private long mTouchDownTime;
43
44 private int mCurX;
45 private int mCurY;
46 private int mCreativeScroll;
47 private int mBlockDamage;
48
49 @Inject
50 public GameInput(MainConfig mainConfig,
51 GameWorld gameWorld,
52 DropController dropController,
53 MobsController mobsController) {
54 mMainConfig = mainConfig;
55 mGameWorld = gameWorld;
56 mDropController = dropController;
57 mMobsController = mobsController;
58
59 mPlayer = mMobsController.getPlayer();
60
61 mControlMode = mMainConfig.isTouch() ? ControlMode.WALK : ControlMode.CURSOR;
62 }
63
64 private boolean checkSwim() {
65 return GameItems.isFluid(mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY()));
66 }
67
68 private void goUpwards() {
69 if (checkSwim()) {
70 mPlayer.swim = true;
71 } else if (mPlayer.canJump()) {
72 mPlayer.jump();
73 } else if (!mPlayer.isFlyMode() && mPlayer.gameMode == 1) {
74 mPlayer.setFlyMode(true);
75 mPlayer.getVelocity().y = 0;
76 } else if (mPlayer.isFlyMode()) {
77 mPlayer.getVelocity().y = -mPlayer.getSpeed();
78 }
79 }
80
81 @SuppressWarnings("IntegerDivisionInFloatingPointContext")
82 private boolean insideCreativeInv(float screenX, float screenY) {
83 TextureRegion creative = Assets.textureRegions.get("creative");
84 return (screenX > mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 &&
85 screenX < mMainConfig.getWidth() / 2 + creative.getRegionWidth() / 2 &&
86 screenY > mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 &&
87 screenY < mMainConfig.getHeight() / 2 + creative.getRegionHeight() / 2);
88 }
89
90 private void wasdPressed(int keycode) {
91 if (mControlMode == ControlMode.WALK || !mMainConfig.isTouch()) {
92 switch (keycode) {
93 case Input.Keys.A:
94 mPlayer.getVelocity().x = -mPlayer.getSpeed();
95 mPlayer.setDir(Mob.Direction.LEFT);
96 if (mMainConfig.isTouch() && checkSwim()) {
97 mPlayer.swim = true;
98 }
99 break;
100 case Input.Keys.D:
101 mPlayer.getVelocity().x = mPlayer.getSpeed();
102 mPlayer.setDir(Mob.Direction.RIGHT);
103 if (mMainConfig.isTouch() && checkSwim()) {
104 mPlayer.swim = true;
105 }
106 break;
107 case Input.Keys.W:
108 case Input.Keys.SPACE:
109 goUpwards();
110 break;
111 case Input.Keys.S:
112 case Input.Keys.CONTROL_LEFT:
113 mPlayer.getVelocity().y = mPlayer.getSpeed();
114 break;
115 }
116 } else {
117 switch (keycode) {
118 case Input.Keys.A:
119 mCurX--;
120 break;
121 case Input.Keys.D:
122 mCurX++;
123 break;
124 case Input.Keys.W:
125 mCurY--;
126 break;
127 case Input.Keys.S:
128 mCurY++;
129 break;
130 }
131 mBlockDamage = 0;
132 }
133 }
134
135 private boolean isNotAutoselectable(int x, int y) {
136 return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMapBlock(x, y).hasCollision());
137 }
138
139 private void checkCursorBounds() {
140 if (mCurY < 0) {
141 mCurY = 0;
142 } else if (mCurY >= mGameWorld.getHeight()) {
143 mCurY = mGameWorld.getHeight() - 1;
144 }
145
146 if (mControlMode == ControlMode.CURSOR) {
147 if (mCurX * 16 + 8 < mPlayer.getX() + mPlayer.getWidth() / 2) {
148 mPlayer.setDir(Mob.Direction.LEFT);
149 } else {
150 mPlayer.setDir(Mob.Direction.RIGHT);
151 }
152 }
153 }
154
155 public void moveCursor(GameRenderer gameRenderer) {
156 int pastX = mCurX;
157 int pastY = mCurY;
158
159 if (mControlMode == ControlMode.WALK && mMainConfig.isTouch()) {
160 mCurX = mPlayer.getMapX() + (mPlayer.looksLeft() ? -1 : 1);
161 mCurY = mPlayer.getUpperMapY();
162 for (int i = 0; i < 2 && isNotAutoselectable(mCurX, mCurY); i++) {
163 mCurY++;
164 }
165 if (isNotAutoselectable(mCurX, mCurY)) {
166 mCurX += mPlayer.looksLeft() ? 1 : -1;
167 }
168 } else if (!mMainConfig.isTouch()) {
169 final int tmpX = (int) (Gdx.input.getX() * (mMainConfig.getWidth() /
170 Gdx.graphics.getWidth()) + gameRenderer.getCamX());
171 mCurX = tmpX / 16;
172
173 final int tmpY = (int) (Gdx.input.getY() * (mMainConfig.getHeight() /
174 Gdx.graphics.getHeight()) + gameRenderer.getCamY());
175 mCurY = tmpY / 16;
176
177 if (tmpX < 0) {
178 mCurX--;
179 }
180
181 final double a = tmpX - mPlayer.x;
182 final double b = tmpY - mPlayer.y;
183
184 mPlayer.headRotation = (float) Math.atan(b / a) * MathUtils.radDeg;
185 }
186
187 if (pastX != mCurX || pastY != mCurY) {
188 mBlockDamage = 0;
189 }
190
191 checkCursorBounds();
192 }
193
194 private void useItem(int x, int y, int id, boolean bg) {
195 String key = getItem(id).isBlock() ? getBlockKey(id) : getItemKey(id);
196 if (id > 0) {
197 if (getItem(id).isBlock()) {
198 if (!bg) {
199 mGameWorld.placeToForeground(x, y, getBlockIdByItemId(id));
200 } else {
201 mGameWorld.placeToBackground(x, y, getBlockIdByItemId(id));
202 }
203 } else {
204 switch (key) {
205 case "bucket_water":
206 mGameWorld.placeToForeground(x, y, getBlockId("water"));
207 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
208 break;
209 case "bucket_lava":
210 mGameWorld.placeToForeground(x, y, getBlockId("lava"));
211 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
212 break;
213 }
214 }
215 }
216 }
217
218 private void pressLMB() {
219 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE) &&
220 ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMapBlock(mCurX, mCurY).getHp() >= 0) ||
221 (!mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.hasBackAt(mCurX, mCurY) &&
222 mGameWorld.getBackMapBlock(mCurX, mCurY).getHp() >= 0))) {
223 if (mPlayer.gameMode == 0) {
224 mBlockDamage++;
225 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
226 if (mBlockDamage >= mGameWorld.getForeMapBlock(mCurX, mCurY).getHp()) {
227 mGameWorld.destroyForeMap(mCurX, mCurY);
228 mBlockDamage = 0;
229 }
230 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
231 if (mBlockDamage >= mGameWorld.getBackMapBlock(mCurX, mCurY).getHp()) {
232 mGameWorld.destroyBackMap(mCurX, mCurY);
233 mBlockDamage = 0;
234 }
235 }
236 } else {
237 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
238 mGameWorld.placeToForeground(mCurX, mCurY, 0);
239 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
240 mGameWorld.placeToBackground(mCurX, mCurY, 0);
241 }
242 mTouchedDown = false;
243 }
244 }
245 }
246
247 private boolean insideHotbar(float x, float y) {
248 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
249 return y < hotbar.getRegionHeight() &&
250 Range.open(mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2,
251 mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2).contains(x);
252 }
253
254 private void holdMB() {
255 if (mTouchDownBtn == Input.Buttons.RIGHT) {
256 useItem(mCurX, mCurY, mPlayer.inventory[mPlayer.slot], true);
257 mTouchedDown = false;
258 } else {
259 if (insideHotbar(mTouchDownX, mTouchDownY)) {
260 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
261 mTouchedDown = false;
262 }
263 }
264 }
265
266 public void keyDown(int keycode) {
267 mKeyDown = true;
268 mKeyDownCode = keycode;
269 switch (keycode) {
270 case Input.Keys.A:
271 case Input.Keys.D:
272 case Input.Keys.W:
273 case Input.Keys.S:
274 case Input.Keys.SPACE:
275 case Input.Keys.CONTROL_LEFT:
276 wasdPressed(keycode);
277 break;
278
279 case Input.Keys.ALT_LEFT:
280 if (mMainConfig.isTouch()) {
281 mControlMode = mControlMode == ControlMode.WALK ? ControlMode.CURSOR : ControlMode.WALK;
282 }
283 break;
284
285 case Input.Keys.E:
286 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
287 switch (mPlayer.gameMode) {
288 case 0:
289 //TODO survival inv
290 break;
291 case 1:
292 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
293 break;
294 }
295 } else {
296 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
297 }
298 break;
299
300 case Input.Keys.G:
301 mMobsController.addMob(Pig.class, mCurX * 16, mCurY * 16);
302 break;
303
304 case Input.Keys.Q:
305 mGameWorld.placeToForeground(mCurX, mCurY, 8);
306 break;
307
308 case Input.Keys.ESCAPE:
309 case Input.Keys.BACK:
310 GameSaver.save(mMainConfig, mDropController, mMobsController, mGameWorld);
311 mMainConfig.getCaveGame().quitGame();
312 break;
313
314 case Input.Keys.F1:
315 mMainConfig.setShowInfo(!mMainConfig.isShowInfo());
316 break;
317
318 case Input.Keys.M:
319 mMainConfig.setShowMap(!mMainConfig.isShowMap());
320 break;
321 }
322 }
323
324 public void keyUp(int keycode) {
325 switch (keycode) {
326 case Input.Keys.A:
327 case Input.Keys.D:
328 mPlayer.getVelocity().x = 0;
329 if (mMainConfig.isTouch() && mPlayer.swim) {
330 mPlayer.swim = false;
331 }
332 break;
333
334 case Input.Keys.W:
335 case Input.Keys.S:
336 case Input.Keys.SPACE:
337 case Input.Keys.CONTROL_LEFT:
338 if (mPlayer.isFlyMode()) {
339 mPlayer.getVelocity().y = 0;
340 }
341 if (mPlayer.swim) {
342 mPlayer.swim = false;
343 }
344 break;
345 }
346 }
347
348 public void touchDown(float touchX, float touchY, int button) {
349 mTouchDownTime = TimeUtils.millis();
350 mTouchedDown = true;
351 mTouchDownBtn = button;
352 mTouchDownX = touchX;
353 mTouchDownY = touchY;
354 }
355
356 public void touchUp(float screenX, float screenY, int button) {
357 if (mDragging) {
358 mDragging = false;
359 return;
360 }
361
362 if (mMainConfig.isTouch() && mKeyDown) {
363 keyUp(mKeyDownCode);
364 mKeyDown = false;
365 }
366 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
367 TextureRegion creative = Assets.textureRegions.get("creative");
368 if (mTouchedDown) {
369 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && insideCreativeInv(screenX, screenY)) {
370 int ix = (int) (screenX - (mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 + 8)) / 18;
371 int iy = (int) (screenY - (mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 + 18)) / 18;
372 int item = mCreativeScroll * 8 + (ix + iy * 8);
373 if (ix >= 8 || ix < 0 || iy < 0 || iy >= 5) {
374 item = -1;
375 }
376 if (item >= 0 && item < GameItems.getItemsSize()) {
377 System.arraycopy(mPlayer.inventory, 0, mPlayer.inventory, 1, 8);
378 mPlayer.inventory[0] = item;
379 }
380 } else if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY)) {
381 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
382 } else if (screenY < hotbar.getRegionHeight() &&
383 screenX > mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2 &&
384 screenX < mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2) {
385 mPlayer.slot = (int) ((screenX - (mMainConfig.getWidth() / 2 - hotbar.getRegionWidth() / 2)) / 20);
386 } else if (button == Input.Buttons.RIGHT) {
387 useItem(mCurX, mCurY,
388 mPlayer.inventory[mPlayer.slot], false);
389 } else if (button == Input.Buttons.LEFT) {
390 mBlockDamage = 0;
391 }
392 }
393 mTouchedDown = false;
394 }
395
396 public void touchDragged(float screenX, float screenY) {
397 if (Math.abs(screenX - mTouchDownX) < 16 && Math.abs(screenY - mTouchDownY) < 16) {
398 return;
399 }
400
401 mDragging = true;
402 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && Math.abs(screenY - mTouchDownY) > 16) {
403 if (insideCreativeInv(screenX, screenY)) {
404 mCreativeScroll -= (screenY - mTouchDownY) / 16;
405 mTouchDownX = screenX;
406 mTouchDownY = screenY;
407 if (mCreativeScroll < 0) {
408 mCreativeScroll = 0;
409 }
410 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
411 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
412 }
413 }
414 }
415 }
416
417 public void scrolled(float amountX, float amountY) {
418 switch (mMainConfig.getGameUiWindow()) {
419 case NONE:
420 mPlayer.slot += (int) amountY;
421 if (mPlayer.slot < 0) {
422 mPlayer.slot = 8;
423 }
424 if (mPlayer.slot > 8) {
425 mPlayer.slot = 0;
426 }
427 break;
428 case CREATIVE_INVENTORY:
429 mCreativeScroll += (int) amountY;
430 if (mCreativeScroll < 0) {
431 mCreativeScroll = 0;
432 }
433 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
434 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
435 }
436 break;
437 }
438 }
439
440 public int getKeyDownCode() {
441 return mKeyDownCode;
442 }
443
444 public boolean isKeyDown() {
445 return mKeyDown;
446 }
447
448 int getBlockDamage() {
449 return mBlockDamage;
450 }
451
452 int getCurX() {
453 return mCurX;
454 }
455
456 int getCurY() {
457 return mCurY;
458 }
459
460 int getCreativeScroll() {
461 return mCreativeScroll;
462 }
463
464 public ControlMode getControlMode() {
465 return mControlMode;
466 }
467
468 public void setControlMode(ControlMode controlMode) {
469 mControlMode = controlMode;
470 }
471
472 void update() {
473 if (mTouchedDown && mTouchDownBtn == Input.Buttons.LEFT) {
474 pressLMB();
475 }
476 if (mTouchedDown && TimeUtils.timeSinceMillis(mTouchDownTime) > 500) {
477 holdMB();
478 }
479 }
480
481 }