DEADSOFTWARE

3da4e2e10c44b28e88bfb0236878acab48c15de6
[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.utils.TimeUtils;
7 import com.google.common.collect.Range;
8 import ru.deadsoftware.cavedroid.MainConfig;
9 import ru.deadsoftware.cavedroid.game.mobs.Mob;
10 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
11 import ru.deadsoftware.cavedroid.game.mobs.Pig;
12 import ru.deadsoftware.cavedroid.game.mobs.Player;
13 import ru.deadsoftware.cavedroid.game.objects.DropController;
14 import ru.deadsoftware.cavedroid.game.world.GameWorld;
15 import ru.deadsoftware.cavedroid.misc.Assets;
16 import ru.deadsoftware.cavedroid.misc.ControlMode;
18 import javax.inject.Inject;
20 import static ru.deadsoftware.cavedroid.game.GameItems.*;
22 @GameScope
23 public class GameInput {
25 private final MainConfig mMainConfig;
26 private final GameWorld mGameWorld;
27 private final DropController mDropController;
28 private final MobsController mMobsController;
29 private final Player mPlayer;
31 private ControlMode mControlMode;
33 private boolean mKeyDown;
34 private boolean mTouchedDown;
35 private boolean mDragging;
37 private int mKeyDownCode;
38 private int mTouchDownBtn;
39 private float mTouchDownX;
40 private float mTouchDownY;
41 private long mTouchDownTime;
43 private int mCurX;
44 private int mCurY;
45 private int mCreativeScroll;
46 private int mBlockDamage;
48 @Inject
49 public GameInput(MainConfig mainConfig,
50 GameWorld gameWorld,
51 DropController dropController,
52 MobsController mobsController) {
53 mMainConfig = mainConfig;
54 mGameWorld = gameWorld;
55 mDropController = dropController;
56 mMobsController = mobsController;
58 mPlayer = mMobsController.getPlayer();
60 mControlMode = mMainConfig.isTouch() ? ControlMode.WALK : ControlMode.CURSOR;
61 }
63 private boolean checkSwim() {
64 return GameItems.isFluid(mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY()));
65 }
67 private void goUpwards() {
68 if (checkSwim()) {
69 mPlayer.swim = true;
70 } else if (mPlayer.canJump()) {
71 mPlayer.getVelocity().add(0, -180);
72 } else if (!mPlayer.isFlyMode() && mPlayer.gameMode == 1) {
73 mPlayer.setFlyMode(true);
74 mPlayer.getVelocity().y = 0;
75 } else if (mPlayer.isFlyMode()) {
76 mPlayer.getVelocity().y = -GamePhysics.PL_SPEED;
77 }
78 }
80 @SuppressWarnings("IntegerDivisionInFloatingPointContext")
81 private boolean insideCreativeInv(float screenX, float screenY) {
82 TextureRegion creative = Assets.textureRegions.get("creative");
83 return (screenX > mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 &&
84 screenX < mMainConfig.getWidth() / 2 + creative.getRegionWidth() / 2 &&
85 screenY > mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 &&
86 screenY < mMainConfig.getHeight() / 2 + creative.getRegionHeight() / 2);
87 }
89 private void wasdPressed(int keycode) {
90 if (mControlMode == ControlMode.WALK || !mMainConfig.isTouch()) {
91 switch (keycode) {
92 case Input.Keys.A:
93 mPlayer.getVelocity().x = -GamePhysics.PL_SPEED;
94 mPlayer.setDir(Mob.Direction.LEFT);
95 if (mMainConfig.isTouch() && checkSwim()) {
96 mPlayer.swim = true;
97 }
98 break;
99 case Input.Keys.D:
100 mPlayer.getVelocity().x = GamePhysics.PL_SPEED;
101 mPlayer.setDir(Mob.Direction.RIGHT);
102 if (mMainConfig.isTouch() && checkSwim()) {
103 mPlayer.swim = true;
105 break;
106 case Input.Keys.W:
107 case Input.Keys.SPACE:
108 goUpwards();
109 break;
110 case Input.Keys.S:
111 case Input.Keys.CONTROL_LEFT:
112 mPlayer.getVelocity().y = GamePhysics.PL_SPEED;
113 break;
115 } else {
116 switch (keycode) {
117 case Input.Keys.A:
118 mCurX--;
119 break;
120 case Input.Keys.D:
121 mCurX++;
122 break;
123 case Input.Keys.W:
124 mCurY--;
125 break;
126 case Input.Keys.S:
127 mCurY++;
128 break;
130 mBlockDamage = 0;
134 private boolean isNotAutoselectable(int x, int y) {
135 return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMapBlock(x, y).hasCollision());
138 private void checkCursorBounds() {
139 if (mCurY < 0) {
140 mCurY = 0;
141 } else if (mCurY >= mGameWorld.getHeight()) {
142 mCurY = mGameWorld.getHeight() - 1;
145 if (mControlMode == ControlMode.CURSOR) {
146 if (mCurX * 16 + 8 < mPlayer.getX() + mPlayer.getWidth() / 2) {
147 mPlayer.setDir(Mob.Direction.LEFT);
148 } else {
149 mPlayer.setDir(Mob.Direction.RIGHT);
154 public void moveCursor(GameRenderer gameRenderer) {
155 int pastX = mCurX;
156 int pastY = mCurY;
158 if (mControlMode == ControlMode.WALK && mMainConfig.isTouch()) {
159 mCurX = mPlayer.getMapX() + (mPlayer.looksLeft() ? -1 : 1);
160 mCurY = mPlayer.getUpperMapY();
161 for (int i = 0; i < 2 && isNotAutoselectable(mCurX, mCurY); i++) {
162 mCurY++;
164 if (isNotAutoselectable(mCurX, mCurY)) {
165 mCurX += mPlayer.looksLeft() ? 1 : -1;
167 } else if (!mMainConfig.isTouch()) {
168 final int tmpX = (int) (Gdx.input.getX() * (mMainConfig.getWidth() /
169 Gdx.graphics.getWidth()) + gameRenderer.getCamX());
170 mCurX = tmpX / 16;
172 mCurY = (int) (Gdx.input.getY() * (mMainConfig.getHeight() /
173 Gdx.graphics.getHeight()) + gameRenderer.getCamY()) / 16;
174 if (tmpX < 0) {
175 mCurX--;
179 if (pastX != mCurX || pastY != mCurY) {
180 mBlockDamage = 0;
183 checkCursorBounds();
186 private void useItem(int x, int y, int id, boolean bg) {
187 String key = getItem(id).isBlock() ? getBlockKey(id) : getItemKey(id);
188 if (id > 0) {
189 if (getItem(id).isBlock()) {
190 if (!bg) {
191 mGameWorld.placeToForeground(x, y, getBlockIdByItemId(id));
192 } else {
193 mGameWorld.placeToBackground(x, y, getBlockIdByItemId(id));
195 } else {
196 switch (key) {
197 case "bucket_water":
198 mGameWorld.placeToForeground(x, y, getBlockId("water"));
199 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
200 break;
201 case "bucket_lava":
202 mGameWorld.placeToForeground(x, y, getBlockId("lava"));
203 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
204 break;
210 private void pressLMB() {
211 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE) &&
212 ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMapBlock(mCurX, mCurY).getHp() >= 0) ||
213 (!mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.hasBackAt(mCurX, mCurY) &&
214 mGameWorld.getBackMapBlock(mCurX, mCurY).getHp() >= 0))) {
215 if (mPlayer.gameMode == 0) {
216 mBlockDamage++;
217 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
218 if (mBlockDamage >= mGameWorld.getForeMapBlock(mCurX, mCurY).getHp()) {
219 mGameWorld.destroyForeMap(mCurX, mCurY);
220 mBlockDamage = 0;
222 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
223 if (mBlockDamage >= mGameWorld.getBackMapBlock(mCurX, mCurY).getHp()) {
224 mGameWorld.destroyBackMap(mCurX, mCurY);
225 mBlockDamage = 0;
228 } else {
229 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
230 mGameWorld.placeToForeground(mCurX, mCurY, 0);
231 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
232 mGameWorld.placeToBackground(mCurX, mCurY, 0);
234 mTouchedDown = false;
239 private boolean insideHotbar(float x, float y) {
240 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
241 return y < hotbar.getRegionHeight() &&
242 Range.open(mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2,
243 mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2).contains(x);
246 private void holdMB() {
247 if (mTouchDownBtn == Input.Buttons.RIGHT) {
248 useItem(mCurX, mCurY, mPlayer.inventory[mPlayer.slot], true);
249 mTouchedDown = false;
250 } else {
251 if (insideHotbar(mTouchDownX, mTouchDownY)) {
252 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
253 mTouchedDown = false;
258 public void keyDown(int keycode) {
259 mKeyDown = true;
260 mKeyDownCode = keycode;
261 switch (keycode) {
262 case Input.Keys.A:
263 case Input.Keys.D:
264 case Input.Keys.W:
265 case Input.Keys.S:
266 case Input.Keys.SPACE:
267 case Input.Keys.CONTROL_LEFT:
268 wasdPressed(keycode);
269 break;
271 case Input.Keys.ALT_LEFT:
272 if (mMainConfig.isTouch()) {
273 mControlMode = mControlMode == ControlMode.WALK ? ControlMode.CURSOR : ControlMode.WALK;
275 break;
277 case Input.Keys.E:
278 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
279 switch (mPlayer.gameMode) {
280 case 0:
281 //TODO survival inv
282 break;
283 case 1:
284 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
285 break;
287 } else {
288 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
290 break;
292 case Input.Keys.G:
293 mMobsController.addMob(Pig.class, mCurX * 16, mCurY * 16);
294 break;
296 case Input.Keys.Q:
297 mGameWorld.placeToForeground(mCurX, mCurY, 8);
298 break;
300 case Input.Keys.ESCAPE:
301 case Input.Keys.BACK:
302 GameSaver.save(mMainConfig, mDropController, mMobsController, mGameWorld);
303 mMainConfig.getCaveGame().quitGame();
304 break;
306 case Input.Keys.F1:
307 mMainConfig.setShowInfo(!mMainConfig.isShowInfo());
308 break;
310 case Input.Keys.M:
311 mMainConfig.setShowMap(!mMainConfig.isShowMap());
312 break;
316 public void keyUp(int keycode) {
317 switch (keycode) {
318 case Input.Keys.A:
319 case Input.Keys.D:
320 mPlayer.getVelocity().x = 0;
321 if (mMainConfig.isTouch() && mPlayer.swim) {
322 mPlayer.swim = false;
324 break;
326 case Input.Keys.W:
327 case Input.Keys.S:
328 case Input.Keys.SPACE:
329 case Input.Keys.CONTROL_LEFT:
330 if (mPlayer.isFlyMode()) {
331 mPlayer.getVelocity().y = 0;
333 if (mPlayer.swim) {
334 mPlayer.swim = false;
336 break;
340 public void touchDown(float touchX, float touchY, int button) {
341 mTouchDownTime = TimeUtils.millis();
342 mTouchedDown = true;
343 mTouchDownBtn = button;
344 mTouchDownX = touchX;
345 mTouchDownY = touchY;
348 public void touchUp(float screenX, float screenY, int button) {
349 if (mDragging) {
350 mDragging = false;
351 return;
354 if (mMainConfig.isTouch() && mKeyDown) {
355 keyUp(mKeyDownCode);
356 mKeyDown = false;
358 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
359 TextureRegion creative = Assets.textureRegions.get("creative");
360 if (mTouchedDown) {
361 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && insideCreativeInv(screenX, screenY)) {
362 int ix = (int) (screenX - (mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 + 8)) / 18;
363 int iy = (int) (screenY - (mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 + 18)) / 18;
364 int item = mCreativeScroll * 8 + (ix + iy * 8);
365 if (ix >= 8 || ix < 0 || iy < 0 || iy >= 5) {
366 item = -1;
368 if (item >= 0 && item < GameItems.getItemsSize()) {
369 System.arraycopy(mPlayer.inventory, 0, mPlayer.inventory, 1, 8);
370 mPlayer.inventory[0] = item;
372 } else if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY)) {
373 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
374 } else if (screenY < hotbar.getRegionHeight() &&
375 screenX > mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2 &&
376 screenX < mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2) {
377 mPlayer.slot = (int) ((screenX - (mMainConfig.getWidth() / 2 - hotbar.getRegionWidth() / 2)) / 20);
378 } else if (button == Input.Buttons.RIGHT) {
379 useItem(mCurX, mCurY,
380 mPlayer.inventory[mPlayer.slot], false);
381 } else if (button == Input.Buttons.LEFT) {
382 mBlockDamage = 0;
385 mTouchedDown = false;
388 public void touchDragged(float screenX, float screenY) {
389 mDragging = true;
390 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && Math.abs(screenY - mTouchDownY) > 16) {
391 if (insideCreativeInv(screenX, screenY)) {
392 mCreativeScroll -= (screenY - mTouchDownY) / 16;
393 mTouchDownX = screenX;
394 mTouchDownY = screenY;
395 if (mCreativeScroll < 0) {
396 mCreativeScroll = 0;
398 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
399 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
405 public void scrolled(float amountX, float amountY) {
406 switch (mMainConfig.getGameUiWindow()) {
407 case NONE:
408 mPlayer.slot += (int) amountY;
409 if (mPlayer.slot < 0) {
410 mPlayer.slot = 8;
412 if (mPlayer.slot > 8) {
413 mPlayer.slot = 0;
415 break;
416 case CREATIVE_INVENTORY:
417 mCreativeScroll += (int) amountY;
418 if (mCreativeScroll < 0) {
419 mCreativeScroll = 0;
421 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
422 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
424 break;
428 public int getKeyDownCode() {
429 return mKeyDownCode;
432 public boolean isKeyDown() {
433 return mKeyDown;
436 int getBlockDamage() {
437 return mBlockDamage;
440 int getCurX() {
441 return mCurX;
444 int getCurY() {
445 return mCurY;
448 int getCreativeScroll() {
449 return mCreativeScroll;
452 public ControlMode getControlMode() {
453 return mControlMode;
456 public void setControlMode(ControlMode controlMode) {
457 mControlMode = controlMode;
460 void update() {
461 if (mTouchedDown && mTouchDownBtn == Input.Buttons.LEFT) {
462 pressLMB();
464 if (mTouchedDown && TimeUtils.timeSinceMillis(mTouchDownTime) > 500) {
465 holdMB();