DEADSOFTWARE

291311a68077622850ed90b533622ccf30ab6557
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / GameInput.java
1 package ru.deadsoftware.cavedroid.game;
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;
19 import javax.inject.Inject;
21 import static ru.deadsoftware.cavedroid.game.GameItems.*;
23 @GameScope
24 public class GameInput {
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;
32 private ControlMode mControlMode;
34 private boolean mKeyDown;
35 private boolean mTouchedDown;
36 private boolean mDragging;
38 private int mKeyDownCode;
39 private int mTouchDownBtn;
40 private float mTouchDownX;
41 private float mTouchDownY;
42 private long mTouchDownTime;
44 private int mCurX;
45 private int mCurY;
46 private int mCreativeScroll;
47 private int mBlockDamage;
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;
59 mPlayer = mMobsController.getPlayer();
61 mControlMode = mMainConfig.isTouch() ? ControlMode.WALK : ControlMode.CURSOR;
62 }
64 private boolean checkSwim() {
65 return GameItems.isFluid(mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY()));
66 }
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 }
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 }
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;
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;
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;
131 mBlockDamage = 0;
135 private boolean isNotAutoselectable(int x, int y) {
136 return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMapBlock(x, y).hasCollision());
139 private void checkCursorBounds() {
140 if (mCurY < 0) {
141 mCurY = 0;
142 } else if (mCurY >= mGameWorld.getHeight()) {
143 mCurY = mGameWorld.getHeight() - 1;
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);
155 public void moveCursor(GameRenderer gameRenderer) {
156 int pastX = mCurX;
157 int pastY = mCurY;
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++;
165 if (isNotAutoselectable(mCurX, mCurY)) {
166 mCurX += mPlayer.looksLeft() ? 1 : -1;
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;
173 final int tmpY = (int) (Gdx.input.getY() * (mMainConfig.getHeight() /
174 Gdx.graphics.getHeight()) + gameRenderer.getCamY());
175 mCurY = tmpY / 16;
177 if (tmpX < 0) {
178 mCurX--;
181 final double a = tmpX - mPlayer.x;
182 final double b = tmpY - mPlayer.y;
184 mPlayer.headRotation = (float) Math.atan(b / a) * MathUtils.radDeg;
187 if (pastX != mCurX || pastY != mCurY) {
188 mBlockDamage = 0;
191 checkCursorBounds();
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));
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;
218 private void pressLMB() {
219 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
220 mPlayer.startHitting();
222 if ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMapBlock(mCurX, mCurY).getHp() >= 0) ||
223 (!mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.hasBackAt(mCurX, mCurY) &&
224 mGameWorld.getBackMapBlock(mCurX, mCurY).getHp() >= 0)) {
225 if (mPlayer.gameMode == 0) {
226 mBlockDamage++;
227 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
228 if (mBlockDamage >= mGameWorld.getForeMapBlock(mCurX, mCurY).getHp()) {
229 mGameWorld.destroyForeMap(mCurX, mCurY);
230 mBlockDamage = 0;
232 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
233 if (mBlockDamage >= mGameWorld.getBackMapBlock(mCurX, mCurY).getHp()) {
234 mGameWorld.destroyBackMap(mCurX, mCurY);
235 mBlockDamage = 0;
238 } else {
239 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
240 mGameWorld.placeToForeground(mCurX, mCurY, 0);
241 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
242 mGameWorld.placeToBackground(mCurX, mCurY, 0);
244 mTouchedDown = false;
246 } else {
247 mTouchedDown = false;
252 private boolean insideHotbar(float x, float y) {
253 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
254 return y < hotbar.getRegionHeight() &&
255 Range.open(mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2,
256 mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2).contains(x);
259 private void holdMB() {
260 if (mTouchDownBtn == Input.Buttons.RIGHT) {
261 useItem(mCurX, mCurY, mPlayer.inventory[mPlayer.slot], true);
262 mTouchedDown = false;
263 } else {
264 if (insideHotbar(mTouchDownX, mTouchDownY)) {
265 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
266 mTouchedDown = false;
271 public void keyDown(int keycode) {
272 mKeyDown = true;
273 mKeyDownCode = keycode;
274 switch (keycode) {
275 case Input.Keys.A:
276 case Input.Keys.D:
277 case Input.Keys.W:
278 case Input.Keys.S:
279 case Input.Keys.SPACE:
280 case Input.Keys.CONTROL_LEFT:
281 wasdPressed(keycode);
282 break;
284 case Input.Keys.ALT_LEFT:
285 if (mMainConfig.isTouch()) {
286 mControlMode = mControlMode == ControlMode.WALK ? ControlMode.CURSOR : ControlMode.WALK;
288 break;
290 case Input.Keys.E:
291 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
292 switch (mPlayer.gameMode) {
293 case 0:
294 //TODO survival inv
295 break;
296 case 1:
297 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
298 break;
300 } else {
301 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
303 break;
305 case Input.Keys.G:
306 mMobsController.addMob(Pig.class, mCurX * 16, mCurY * 16);
307 break;
309 case Input.Keys.Q:
310 mGameWorld.placeToForeground(mCurX, mCurY, 8);
311 break;
313 case Input.Keys.ESCAPE:
314 case Input.Keys.BACK:
315 GameSaver.save(mMainConfig, mDropController, mMobsController, mGameWorld);
316 mMainConfig.getCaveGame().quitGame();
317 break;
319 case Input.Keys.F1:
320 mMainConfig.setShowInfo(!mMainConfig.isShowInfo());
321 break;
323 case Input.Keys.M:
324 mMainConfig.setShowMap(!mMainConfig.isShowMap());
325 break;
329 public void keyUp(int keycode) {
330 switch (keycode) {
331 case Input.Keys.A:
332 case Input.Keys.D:
333 mPlayer.getVelocity().x = 0;
334 if (mMainConfig.isTouch() && mPlayer.swim) {
335 mPlayer.swim = false;
337 break;
339 case Input.Keys.W:
340 case Input.Keys.S:
341 case Input.Keys.SPACE:
342 case Input.Keys.CONTROL_LEFT:
343 if (mPlayer.isFlyMode()) {
344 mPlayer.getVelocity().y = 0;
346 if (mPlayer.swim) {
347 mPlayer.swim = false;
349 break;
353 public void touchDown(float touchX, float touchY, int button) {
354 mTouchDownTime = TimeUtils.millis();
355 mTouchedDown = true;
356 mTouchDownBtn = button;
357 mTouchDownX = touchX;
358 mTouchDownY = touchY;
361 public void touchUp(float screenX, float screenY, int button) {
362 if (mDragging) {
363 mDragging = false;
364 return;
367 if (mMainConfig.isTouch() && mKeyDown) {
368 keyUp(mKeyDownCode);
369 mKeyDown = false;
371 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
372 TextureRegion creative = Assets.textureRegions.get("creative");
373 if (mTouchedDown) {
374 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && insideCreativeInv(screenX, screenY)) {
375 int ix = (int) (screenX - (mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 + 8)) / 18;
376 int iy = (int) (screenY - (mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 + 18)) / 18;
377 int item = mCreativeScroll * 8 + (ix + iy * 8);
378 if (ix >= 8 || ix < 0 || iy < 0 || iy >= 5) {
379 item = -1;
381 if (item >= 0 && item < GameItems.getItemsSize()) {
382 System.arraycopy(mPlayer.inventory, 0, mPlayer.inventory, 1, 8);
383 mPlayer.inventory[0] = item;
385 } else if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY)) {
386 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
387 } else if (screenY < hotbar.getRegionHeight() &&
388 screenX > mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2 &&
389 screenX < mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2) {
390 mPlayer.slot = (int) ((screenX - (mMainConfig.getWidth() / 2 - hotbar.getRegionWidth() / 2)) / 20);
391 } else if (button == Input.Buttons.RIGHT) {
392 useItem(mCurX, mCurY,
393 mPlayer.inventory[mPlayer.slot], false);
394 } else if (button == Input.Buttons.LEFT) {
395 mBlockDamage = 0;
398 mTouchedDown = false;
401 public void touchDragged(float screenX, float screenY) {
402 if (Math.abs(screenX - mTouchDownX) < 16 && Math.abs(screenY - mTouchDownY) < 16) {
403 return;
406 mDragging = true;
407 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && Math.abs(screenY - mTouchDownY) > 16) {
408 if (insideCreativeInv(screenX, screenY)) {
409 mCreativeScroll -= (screenY - mTouchDownY) / 16;
410 mTouchDownX = screenX;
411 mTouchDownY = screenY;
412 if (mCreativeScroll < 0) {
413 mCreativeScroll = 0;
415 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
416 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
422 public void scrolled(float amountX, float amountY) {
423 switch (mMainConfig.getGameUiWindow()) {
424 case NONE:
425 mPlayer.slot += (int) amountY;
426 if (mPlayer.slot < 0) {
427 mPlayer.slot = 8;
429 if (mPlayer.slot > 8) {
430 mPlayer.slot = 0;
432 break;
433 case CREATIVE_INVENTORY:
434 mCreativeScroll += (int) amountY;
435 if (mCreativeScroll < 0) {
436 mCreativeScroll = 0;
438 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
439 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
441 break;
445 public int getKeyDownCode() {
446 return mKeyDownCode;
449 public boolean isKeyDown() {
450 return mKeyDown;
453 int getBlockDamage() {
454 return mBlockDamage;
457 int getCurX() {
458 return mCurX;
461 int getCurY() {
462 return mCurY;
465 int getCreativeScroll() {
466 return mCreativeScroll;
469 public ControlMode getControlMode() {
470 return mControlMode;
473 public void setControlMode(ControlMode controlMode) {
474 mControlMode = controlMode;
477 void update() {
478 if (mTouchedDown && mTouchDownBtn == Input.Buttons.LEFT) {
479 pressLMB();
480 } else {
481 mPlayer.stopHitting();
483 if (mTouchedDown && TimeUtils.timeSinceMillis(mTouchDownTime) > 500) {
484 holdMB();