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
.*;
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
;
46 private int mCreativeScroll
;
47 private int mBlockDamage
;
50 public GameInput(MainConfig mainConfig
,
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
;
64 private boolean checkSwim() {
65 return GameItems
.isFluid(mGameWorld
.getForeMap(mPlayer
.getMapX(), mPlayer
.getLowerMapY()));
68 private void goUpwards() {
71 } else if (mPlayer
.canJump()) {
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();
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);
90 private void wasdPressed(int keycode
) {
91 if (mControlMode
== ControlMode
.WALK
|| !mMainConfig
.isTouch()) {
94 mPlayer
.getVelocity().x
= -mPlayer
.getSpeed();
95 mPlayer
.setDir(Mob
.Direction
.LEFT
);
96 if (mMainConfig
.isTouch() && checkSwim()) {
101 mPlayer
.getVelocity().x
= mPlayer
.getSpeed();
102 mPlayer
.setDir(Mob
.Direction
.RIGHT
);
103 if (mMainConfig
.isTouch() && checkSwim()) {
108 case Input
.Keys
.SPACE
:
112 case Input
.Keys
.CONTROL_LEFT
:
113 mPlayer
.getVelocity().y
= mPlayer
.getSpeed();
135 private boolean isNotAutoselectable(int x
, int y
) {
136 return (!mGameWorld
.hasForeAt(x
, y
) || !mGameWorld
.getForeMapBlock(x
, y
).hasCollision());
139 private void checkCursorBounds() {
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
);
150 mPlayer
.setDir(Mob
.Direction
.RIGHT
);
155 public void moveCursor(GameRenderer gameRenderer
) {
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
++) {
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());
173 final int tmpY
= (int) (Gdx
.input
.getY() * (mMainConfig
.getHeight() /
174 Gdx
.graphics
.getHeight()) + gameRenderer
.getCamY());
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
) {
194 private void useItem(int x
, int y
, int id
, boolean bg
) {
195 String key
= getItem(id
).isBlock() ?
getBlockKey(id
) : getItemKey(id
);
197 if (getItem(id
).isBlock()) {
199 mGameWorld
.placeToForeground(x
, y
, getBlockIdByItemId(id
));
201 mGameWorld
.placeToBackground(x
, y
, getBlockIdByItemId(id
));
206 mGameWorld
.placeToForeground(x
, y
, getBlockId("water"));
207 mPlayer
.inventory
[mPlayer
.slot
] = getItemId("bucket_empty");
210 mGameWorld
.placeToForeground(x
, y
, getBlockId("lava"));
211 mPlayer
.inventory
[mPlayer
.slot
] = getItemId("bucket_empty");
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) {
227 if (mGameWorld
.hasForeAt(mCurX
, mCurY
)) {
228 if (mBlockDamage
>= mGameWorld
.getForeMapBlock(mCurX
, mCurY
).getHp()) {
229 mGameWorld
.destroyForeMap(mCurX
, mCurY
);
232 } else if (mGameWorld
.hasBackAt(mCurX
, mCurY
)) {
233 if (mBlockDamage
>= mGameWorld
.getBackMapBlock(mCurX
, mCurY
).getHp()) {
234 mGameWorld
.destroyBackMap(mCurX
, mCurY
);
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;
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;
264 if (insideHotbar(mTouchDownX
, mTouchDownY
)) {
265 mMainConfig
.setGameUiWindow(GameUiWindow
.CREATIVE_INVENTORY
);
266 mTouchedDown
= false;
271 public void keyDown(int keycode
) {
273 mKeyDownCode
= keycode
;
279 case Input
.Keys
.SPACE
:
280 case Input
.Keys
.CONTROL_LEFT
:
281 wasdPressed(keycode
);
284 case Input
.Keys
.ALT_LEFT
:
285 if (mMainConfig
.isTouch()) {
286 mControlMode
= mControlMode
== ControlMode
.WALK ? ControlMode
.CURSOR
: ControlMode
.WALK
;
291 if (mMainConfig
.checkGameUiWindow(GameUiWindow
.NONE
)) {
292 switch (mPlayer
.gameMode
) {
297 mMainConfig
.setGameUiWindow(GameUiWindow
.CREATIVE_INVENTORY
);
301 mMainConfig
.setGameUiWindow(GameUiWindow
.NONE
);
306 mMobsController
.addMob(Pig
.class, mCurX
* 16, mCurY
* 16);
310 mGameWorld
.placeToForeground(mCurX
, mCurY
, 8);
313 case Input
.Keys
.ESCAPE
:
314 case Input
.Keys
.BACK
:
315 GameSaver
.save(mMainConfig
, mDropController
, mMobsController
, mGameWorld
);
316 mMainConfig
.getCaveGame().quitGame();
320 mMainConfig
.setShowInfo(!mMainConfig
.isShowInfo());
324 mMainConfig
.setShowMap(!mMainConfig
.isShowMap());
329 public void keyUp(int keycode
) {
333 mPlayer
.getVelocity().x
= 0;
334 if (mMainConfig
.isTouch() && mPlayer
.swim
) {
335 mPlayer
.swim
= false;
341 case Input
.Keys
.SPACE
:
342 case Input
.Keys
.CONTROL_LEFT
:
343 if (mPlayer
.isFlyMode()) {
344 mPlayer
.getVelocity().y
= 0;
347 mPlayer
.swim
= false;
353 public void touchDown(float touchX
, float touchY
, int button
) {
354 mTouchDownTime
= TimeUtils
.millis();
356 mTouchDownBtn
= button
;
357 mTouchDownX
= touchX
;
358 mTouchDownY
= touchY
;
361 public void touchUp(float screenX
, float screenY
, int button
) {
367 if (mMainConfig
.isTouch() && mKeyDown
) {
371 TextureRegion hotbar
= Assets
.textureRegions
.get("hotbar");
372 TextureRegion creative
= Assets
.textureRegions
.get("creative");
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) {
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
) {
398 mTouchedDown
= false;
401 public void touchDragged(float screenX
, float screenY
) {
402 if (Math
.abs(screenX
- mTouchDownX
) < 16 && Math
.abs(screenY
- mTouchDownY
) < 16) {
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) {
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()) {
425 mPlayer
.slot
+= (int) amountY
;
426 if (mPlayer
.slot
< 0) {
429 if (mPlayer
.slot
> 8) {
433 case CREATIVE_INVENTORY
:
434 mCreativeScroll
+= (int) amountY
;
435 if (mCreativeScroll
< 0) {
438 if (mCreativeScroll
> GameProc
.MAX_CREATIVE_SCROLL
) {
439 mCreativeScroll
= GameProc
.MAX_CREATIVE_SCROLL
;
445 public int getKeyDownCode() {
449 public boolean isKeyDown() {
453 int getBlockDamage() {
465 int getCreativeScroll() {
466 return mCreativeScroll
;
469 public ControlMode
getControlMode() {
473 public void setControlMode(ControlMode controlMode
) {
474 mControlMode
= controlMode
;
478 if (mTouchedDown
&& mTouchDownBtn
== Input
.Buttons
.LEFT
) {
481 mPlayer
.stopHitting();
483 if (mTouchedDown
&& TimeUtils
.timeSinceMillis(mTouchDownTime
) > 500) {