DEADSOFTWARE

Mobs controller to kotlin
[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.Intersector;
7 import com.badlogic.gdx.math.MathUtils;
8 import com.badlogic.gdx.utils.TimeUtils;
9 import com.google.common.collect.Range;
10 import ru.deadsoftware.cavedroid.MainConfig;
11 import ru.deadsoftware.cavedroid.game.mobs.Mob;
12 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
13 import ru.deadsoftware.cavedroid.game.mobs.Pig;
14 import ru.deadsoftware.cavedroid.game.mobs.Player;
15 import ru.deadsoftware.cavedroid.game.objects.DropController;
16 import ru.deadsoftware.cavedroid.game.world.GameWorld;
17 import ru.deadsoftware.cavedroid.misc.Assets;
18 import ru.deadsoftware.cavedroid.misc.ControlMode;
20 import javax.inject.Inject;
22 import static ru.deadsoftware.cavedroid.game.GameItems.*;
24 @GameScope
25 public class GameInput {
27 private final MainConfig mMainConfig;
28 private final GameWorld mGameWorld;
29 private final DropController mDropController;
30 private final MobsController mMobsController;
31 private final Player mPlayer;
33 private ControlMode mControlMode;
35 private boolean mKeyDown;
36 private boolean mTouchedDown;
37 private boolean mDragging;
39 private int mKeyDownCode;
40 private int mTouchDownBtn;
41 private float mTouchDownX;
42 private float mTouchDownY;
43 private long mTouchDownTime;
45 private int mCurX;
46 private int mCurY;
47 private int mCreativeScroll;
48 private int mBlockDamage;
50 @Inject
51 public GameInput(MainConfig mainConfig,
52 GameWorld gameWorld,
53 DropController dropController,
54 MobsController mobsController) {
55 mMainConfig = mainConfig;
56 mGameWorld = gameWorld;
57 mDropController = dropController;
58 mMobsController = mobsController;
60 mPlayer = mMobsController.getPlayer();
62 mControlMode = mMainConfig.isTouch() ? ControlMode.WALK : ControlMode.CURSOR;
63 }
65 private boolean checkSwim() {
66 return GameItems.isFluid(mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY()));
67 }
69 private void goUpwards() {
70 if (checkSwim()) {
71 mPlayer.swim = true;
72 } else if (mPlayer.canJump()) {
73 mPlayer.jump();
74 } else if (!mPlayer.isFlyMode() && mPlayer.gameMode == 1) {
75 mPlayer.setFlyMode(true);
76 mPlayer.getVelocity().y = 0;
77 } else if (mPlayer.isFlyMode()) {
78 mPlayer.getVelocity().y = -mPlayer.getSpeed();
79 }
80 }
82 @SuppressWarnings("IntegerDivisionInFloatingPointContext")
83 private boolean insideCreativeInv(float screenX, float screenY) {
84 TextureRegion creative = Assets.textureRegions.get("creative");
85 return (screenX > mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 &&
86 screenX < mMainConfig.getWidth() / 2 + creative.getRegionWidth() / 2 &&
87 screenY > mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 &&
88 screenY < mMainConfig.getHeight() / 2 + creative.getRegionHeight() / 2);
89 }
91 private void wasdPressed(int keycode) {
92 if (mControlMode == ControlMode.WALK || !mMainConfig.isTouch()) {
93 switch (keycode) {
94 case Input.Keys.A:
95 mPlayer.getVelocity().x = -mPlayer.getSpeed();
96 mPlayer.setDir(Mob.Direction.LEFT);
97 if (mMainConfig.isTouch() && checkSwim()) {
98 mPlayer.swim = true;
99 }
100 break;
101 case Input.Keys.D:
102 mPlayer.getVelocity().x = mPlayer.getSpeed();
103 mPlayer.setDir(Mob.Direction.RIGHT);
104 if (mMainConfig.isTouch() && checkSwim()) {
105 mPlayer.swim = true;
107 break;
108 case Input.Keys.W:
109 case Input.Keys.SPACE:
110 goUpwards();
111 break;
112 case Input.Keys.S:
113 case Input.Keys.CONTROL_LEFT:
114 mPlayer.getVelocity().y = mPlayer.getSpeed();
115 break;
117 } else {
118 switch (keycode) {
119 case Input.Keys.A:
120 mCurX--;
121 break;
122 case Input.Keys.D:
123 mCurX++;
124 break;
125 case Input.Keys.W:
126 mCurY--;
127 break;
128 case Input.Keys.S:
129 mCurY++;
130 break;
132 mBlockDamage = 0;
136 private boolean isNotAutoselectable(int x, int y) {
137 return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMapBlock(x, y).hasCollision());
140 private void checkCursorBounds() {
141 if (mCurY < 0) {
142 mCurY = 0;
143 } else if (mCurY >= mGameWorld.getHeight()) {
144 mCurY = mGameWorld.getHeight() - 1;
147 if (mControlMode == ControlMode.CURSOR) {
148 if (mCurX * 16 + 8 < mPlayer.getX() + mPlayer.getWidth() / 2) {
149 mPlayer.setDir(Mob.Direction.LEFT);
150 } else {
151 mPlayer.setDir(Mob.Direction.RIGHT);
156 public void moveCursor(GameRenderer gameRenderer) {
157 int pastX = mCurX;
158 int pastY = mCurY;
160 if (mControlMode == ControlMode.WALK && mMainConfig.isTouch()) {
161 mCurX = mPlayer.getMapX() + (mPlayer.looksLeft() ? -1 : 1);
162 mCurY = mPlayer.getUpperMapY();
163 for (int i = 0; i < 2 && isNotAutoselectable(mCurX, mCurY); i++) {
164 mCurY++;
166 if (isNotAutoselectable(mCurX, mCurY)) {
167 mCurX += mPlayer.looksLeft() ? 1 : -1;
169 } else if (!mMainConfig.isTouch()) {
170 final int tmpX = (int) (Gdx.input.getX() * (mMainConfig.getWidth() /
171 Gdx.graphics.getWidth()) + gameRenderer.getCamX());
172 mCurX = tmpX / 16;
174 final int tmpY = (int) (Gdx.input.getY() * (mMainConfig.getHeight() /
175 Gdx.graphics.getHeight()) + gameRenderer.getCamY());
176 mCurY = tmpY / 16;
178 if (tmpX < 0) {
179 mCurX--;
182 final double a = tmpX - mPlayer.x;
183 final double b = tmpY - mPlayer.y;
185 mPlayer.headRotation = (float) Math.atan(b / a) * MathUtils.radDeg;
188 if (pastX != mCurX || pastY != mCurY) {
189 mBlockDamage = 0;
192 checkCursorBounds();
195 private void useItem(int x, int y, int id, boolean bg) {
196 String key = getItem(id).isBlock() ? getBlockKey(id) : getItemKey(id);
197 if (id > 0) {
198 if (getItem(id).isBlock()) {
199 if (!bg) {
200 mGameWorld.placeToForeground(x, y, getBlockIdByItemId(id));
201 } else {
202 mGameWorld.placeToBackground(x, y, getBlockIdByItemId(id));
204 } else {
205 switch (key) {
206 case "bucket_water":
207 mGameWorld.placeToForeground(x, y, getBlockId("water"));
208 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
209 break;
210 case "bucket_lava":
211 mGameWorld.placeToForeground(x, y, getBlockId("lava"));
212 mPlayer.inventory[mPlayer.slot] = getItemId("bucket_empty");
213 break;
219 private void hitMobs() {
220 final Player player = mMobsController.getPlayer();
221 mMobsController.getMobs().forEach((mob) -> {
222 if (Intersector.overlaps(mob, player)) {
223 mob.damage(5);
224 mob.jump();
226 });
229 private void pressLMB() {
230 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
231 mPlayer.startHitting();
233 if ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMapBlock(mCurX, mCurY).getHp() >= 0) ||
234 (!mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.hasBackAt(mCurX, mCurY) &&
235 mGameWorld.getBackMapBlock(mCurX, mCurY).getHp() >= 0)) {
236 if (mPlayer.gameMode == 0) {
237 mBlockDamage++;
238 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
239 if (mBlockDamage >= mGameWorld.getForeMapBlock(mCurX, mCurY).getHp()) {
240 mGameWorld.destroyForeMap(mCurX, mCurY);
241 mBlockDamage = 0;
243 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
244 if (mBlockDamage >= mGameWorld.getBackMapBlock(mCurX, mCurY).getHp()) {
245 mGameWorld.destroyBackMap(mCurX, mCurY);
246 mBlockDamage = 0;
249 } else {
250 if (mGameWorld.hasForeAt(mCurX, mCurY)) {
251 mGameWorld.placeToForeground(mCurX, mCurY, 0);
252 } else if (mGameWorld.hasBackAt(mCurX, mCurY)) {
253 mGameWorld.placeToBackground(mCurX, mCurY, 0);
255 mTouchedDown = false;
257 } else {
258 hitMobs();
259 mTouchedDown = false;
264 private boolean insideHotbar(float x, float y) {
265 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
266 return y < hotbar.getRegionHeight() &&
267 Range.open(mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2,
268 mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2).contains(x);
271 private void holdMB() {
272 if (mTouchDownBtn == Input.Buttons.RIGHT) {
273 useItem(mCurX, mCurY, mPlayer.inventory[mPlayer.slot], true);
274 mTouchedDown = false;
275 } else {
276 if (insideHotbar(mTouchDownX, mTouchDownY)) {
277 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
278 mTouchedDown = false;
283 public void keyDown(int keycode) {
284 mKeyDown = true;
285 mKeyDownCode = keycode;
286 switch (keycode) {
287 case Input.Keys.A:
288 case Input.Keys.D:
289 case Input.Keys.W:
290 case Input.Keys.S:
291 case Input.Keys.SPACE:
292 case Input.Keys.CONTROL_LEFT:
293 wasdPressed(keycode);
294 break;
296 case Input.Keys.ALT_LEFT:
297 if (mMainConfig.isTouch()) {
298 mControlMode = mControlMode == ControlMode.WALK ? ControlMode.CURSOR : ControlMode.WALK;
300 break;
302 case Input.Keys.E:
303 if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) {
304 switch (mPlayer.gameMode) {
305 case 0:
306 //TODO survival inv
307 break;
308 case 1:
309 mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY);
310 break;
312 } else {
313 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
315 break;
317 case Input.Keys.G:
318 mMobsController.addMob(new Pig(mCurX * 16, mCurY * 16));
319 break;
321 case Input.Keys.Q:
322 mGameWorld.placeToForeground(mCurX, mCurY, 8);
323 break;
325 case Input.Keys.ESCAPE:
326 case Input.Keys.BACK:
327 GameSaver.save(mMainConfig, mDropController, mMobsController, mGameWorld);
328 mMainConfig.getCaveGame().quitGame();
329 break;
331 case Input.Keys.F1:
332 mMainConfig.setShowInfo(!mMainConfig.isShowInfo());
333 break;
335 case Input.Keys.M:
336 mMainConfig.setShowMap(!mMainConfig.isShowMap());
337 break;
341 public void keyUp(int keycode) {
342 switch (keycode) {
343 case Input.Keys.A:
344 case Input.Keys.D:
345 mPlayer.getVelocity().x = 0;
346 if (mMainConfig.isTouch() && mPlayer.swim) {
347 mPlayer.swim = false;
349 break;
351 case Input.Keys.W:
352 case Input.Keys.S:
353 case Input.Keys.SPACE:
354 case Input.Keys.CONTROL_LEFT:
355 if (mPlayer.isFlyMode()) {
356 mPlayer.getVelocity().y = 0;
358 if (mPlayer.swim) {
359 mPlayer.swim = false;
361 break;
365 public void touchDown(float touchX, float touchY, int button) {
366 mTouchDownTime = TimeUtils.millis();
367 mTouchedDown = true;
368 mTouchDownBtn = button;
369 mTouchDownX = touchX;
370 mTouchDownY = touchY;
373 public void touchUp(float screenX, float screenY, int button) {
374 if (mDragging) {
375 mDragging = false;
376 return;
379 if (mMainConfig.isTouch() && mKeyDown) {
380 keyUp(mKeyDownCode);
381 mKeyDown = false;
383 TextureRegion hotbar = Assets.textureRegions.get("hotbar");
384 TextureRegion creative = Assets.textureRegions.get("creative");
385 if (mTouchedDown) {
386 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && insideCreativeInv(screenX, screenY)) {
387 int ix = (int) (screenX - (mMainConfig.getWidth() / 2 - creative.getRegionWidth() / 2 + 8)) / 18;
388 int iy = (int) (screenY - (mMainConfig.getHeight() / 2 - creative.getRegionHeight() / 2 + 18)) / 18;
389 int item = mCreativeScroll * 8 + (ix + iy * 8);
390 if (ix >= 8 || ix < 0 || iy < 0 || iy >= 5) {
391 item = -1;
393 if (item >= 0 && item < GameItems.getItemsSize()) {
394 System.arraycopy(mPlayer.inventory, 0, mPlayer.inventory, 1, 8);
395 mPlayer.inventory[0] = item;
397 } else if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY)) {
398 mMainConfig.setGameUiWindow(GameUiWindow.NONE);
399 } else if (screenY < hotbar.getRegionHeight() &&
400 screenX > mMainConfig.getWidth() / 2 - (float) hotbar.getRegionWidth() / 2 &&
401 screenX < mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2) {
402 mPlayer.slot = (int) ((screenX - (mMainConfig.getWidth() / 2 - hotbar.getRegionWidth() / 2)) / 20);
403 } else if (button == Input.Buttons.RIGHT) {
404 useItem(mCurX, mCurY,
405 mPlayer.inventory[mPlayer.slot], false);
406 } else if (button == Input.Buttons.LEFT) {
407 mBlockDamage = 0;
410 mTouchedDown = false;
413 public void touchDragged(float screenX, float screenY) {
414 if (Math.abs(screenX - mTouchDownX) < 16 && Math.abs(screenY - mTouchDownY) < 16) {
415 return;
418 mDragging = true;
419 if (mMainConfig.checkGameUiWindow(GameUiWindow.CREATIVE_INVENTORY) && Math.abs(screenY - mTouchDownY) > 16) {
420 if (insideCreativeInv(screenX, screenY)) {
421 mCreativeScroll -= (screenY - mTouchDownY) / 16;
422 mTouchDownX = screenX;
423 mTouchDownY = screenY;
424 if (mCreativeScroll < 0) {
425 mCreativeScroll = 0;
427 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
428 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
434 public void scrolled(float amountX, float amountY) {
435 switch (mMainConfig.getGameUiWindow()) {
436 case NONE:
437 mPlayer.slot += (int) amountY;
438 if (mPlayer.slot < 0) {
439 mPlayer.slot = 8;
441 if (mPlayer.slot > 8) {
442 mPlayer.slot = 0;
444 break;
445 case CREATIVE_INVENTORY:
446 mCreativeScroll += (int) amountY;
447 if (mCreativeScroll < 0) {
448 mCreativeScroll = 0;
450 if (mCreativeScroll > GameProc.MAX_CREATIVE_SCROLL) {
451 mCreativeScroll = GameProc.MAX_CREATIVE_SCROLL;
453 break;
457 public int getKeyDownCode() {
458 return mKeyDownCode;
461 public boolean isKeyDown() {
462 return mKeyDown;
465 int getBlockDamage() {
466 return mBlockDamage;
469 int getCurX() {
470 return mCurX;
473 int getCurY() {
474 return mCurY;
477 int getCreativeScroll() {
478 return mCreativeScroll;
481 public ControlMode getControlMode() {
482 return mControlMode;
485 public void setControlMode(ControlMode controlMode) {
486 mControlMode = controlMode;
489 void update() {
490 if (mTouchedDown && mTouchDownBtn == Input.Buttons.LEFT) {
491 pressLMB();
492 } else {
493 mPlayer.stopHitting();
495 if (mTouchedDown && TimeUtils.timeSinceMillis(mTouchDownTime) > 500) {
496 holdMB();