DEADSOFTWARE

Add my repo for automultibind
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / GameRenderer.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.Color;
6 import com.badlogic.gdx.graphics.GL20;
7 import com.badlogic.gdx.math.Rectangle;
8 import com.badlogic.gdx.math.Vector2;
9 import com.badlogic.gdx.utils.ObjectMap;
10 import com.badlogic.gdx.utils.TimeUtils;
11 import ru.deadsoftware.cavedroid.MainConfig;
12 import ru.deadsoftware.cavedroid.game.input.IGameInputHandler;
13 import ru.deadsoftware.cavedroid.game.input.Joystick;
14 import ru.deadsoftware.cavedroid.game.input.action.KeyboardInputAction;
15 import ru.deadsoftware.cavedroid.game.input.action.MouseInputAction;
16 import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey;
17 import ru.deadsoftware.cavedroid.game.input.handler.mouse.CursorMouseInputHandler;
18 import ru.deadsoftware.cavedroid.game.input.mapper.KeyboardInputActionMapper;
19 import ru.deadsoftware.cavedroid.game.input.mapper.MouseInputActionMapper;
20 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
21 import ru.deadsoftware.cavedroid.game.mobs.player.Player;
22 import ru.deadsoftware.cavedroid.game.objects.TouchButton;
23 import ru.deadsoftware.cavedroid.game.render.IGameRenderer;
24 import ru.deadsoftware.cavedroid.game.ui.TooltipManager;
25 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager;
26 import ru.deadsoftware.cavedroid.game.world.GameWorld;
27 import ru.deadsoftware.cavedroid.misc.Assets;
28 import ru.deadsoftware.cavedroid.misc.Renderer;
29 import ru.deadsoftware.cavedroid.misc.utils.MeasureUnitsUtilsKt;
30 import ru.deadsoftware.cavedroid.misc.utils.RenderingUtilsKt;
32 import javax.annotation.CheckForNull;
33 import javax.inject.Inject;
34 import java.util.ArrayList;
35 import java.util.Comparator;
36 import java.util.List;
37 import java.util.Set;
39 @GameScope
40 public class GameRenderer extends Renderer {
42 private static final float CAMERA_SPEED = 72f;
43 private static final float MAX_CAM_DISTANCE_FROM_PLAYER = 64f;
44 private static final float DRAG_THRESHOLD = 1f;
45 private static final TouchButton nullButton = new TouchButton(null, -1, true);
47 private final MainConfig mMainConfig;
48 private final MobsController mMobsController;
49 private final GameWorld mGameWorld;
50 private final List<IGameRenderer> mRenderers;
51 private final CursorMouseInputHandler mCursorMouseInputHandler;
52 private final MouseInputActionMapper mMouseInputActionMapper;
53 private final KeyboardInputActionMapper mKeyboardInputActionMapper;
54 private final Set<IGameInputHandler<MouseInputAction>> mMouseInputHandlers;
55 private final Set<IGameInputHandler<KeyboardInputAction>> mKeyboardInputHandlers;
56 private final GameWindowsManager mGameWindowsManager;
57 private final TooltipManager mTooltipManager;
59 private final TouchButton mouseLeftTouchButton, mouseRightTouchButton;
61 private final Vector2 mCamCenterToPlayer = new Vector2();
63 private float mTouchDownX, mTouchDownY;
64 private long mCameraDelayMs = 0L;
66 @Inject
67 GameRenderer(MainConfig mainConfig,
68 MobsController mobsController,
69 GameWorld gameWorld,
70 Set<IGameRenderer> renderers,
71 CursorMouseInputHandler cursorMouseInputHandler,
72 MouseInputActionMapper mouseInputActionMapper,
73 KeyboardInputActionMapper keyboardInputActionMapper,
74 Set<IGameInputHandler<MouseInputAction>> mouseInputHandlers,
75 Set<IGameInputHandler<KeyboardInputAction>> keyboardInputHandlers,
76 GameWindowsManager gameWindowsManager,
77 TooltipManager tooltipManager) {
78 super(mainConfig.getWidth(), mainConfig.getHeight());
80 mMainConfig = mainConfig;
81 mMobsController = mobsController;
82 mGameWorld = gameWorld;
83 mRenderers = new ArrayList<>(renderers);
84 mRenderers.sort(Comparator.comparingInt(IGameRenderer::getRenderLayer));
85 mCursorMouseInputHandler = cursorMouseInputHandler;
86 mMouseInputActionMapper = mouseInputActionMapper;
87 mKeyboardInputActionMapper = keyboardInputActionMapper;
88 mMouseInputHandlers = mouseInputHandlers;
89 mKeyboardInputHandlers = keyboardInputHandlers;
90 mGameWindowsManager = gameWindowsManager;
91 mTooltipManager = tooltipManager;
93 mouseLeftTouchButton = new TouchButton(new Rectangle(getWidth() / 2, 0f, getWidth() / 2, getHeight() / 2), Input.Buttons.LEFT, true);
94 mouseRightTouchButton = new TouchButton(new Rectangle(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2), Input.Buttons.RIGHT, true);
96 mMainConfig.setJoystick(new Joystick(mMobsController.getPlayer().getSpeed()));
98 Gdx.gl.glClearColor(0f, .6f, .6f, 1f);
99 }
101 private void updateDynamicCameraPosition(float delta) {
102 Player player = mMobsController.getPlayer();
104 float plTargetX = player.getX() + player.getWidth() / 2;
105 float plTargetY = player.getY() + player.getHeight() / 2;
107 float camCenterX = getCamX() + getWidth() / 2;
108 float camCenterY = getCamY() + getHeight() / 2;
110 float camTargetX, camTargetY;
112 if (player.controlMode == Player.ControlMode.WALK) {
113 camTargetX = plTargetX + Math.min(player.getVelocity().x * 2, getWidth() / 2);
114 camTargetY = plTargetY + player.getVelocity().y;
115 } else {
116 camTargetX = MeasureUnitsUtilsKt.getPx(player.cursorX) + MeasureUnitsUtilsKt.getPx(1) / 2;
117 camTargetY = MeasureUnitsUtilsKt.getPx(player.cursorY) + MeasureUnitsUtilsKt.getPx(1) / 2;
120 Vector2 moveVector = new Vector2(camTargetX - camCenterX, camTargetY - camCenterY);
122 if (player.controlMode == Player.ControlMode.WALK && player.getVelocity().isZero()) {
123 mCameraDelayMs = TimeUtils.millis();
124 mCamCenterToPlayer.x = plTargetX - camCenterX;
125 mCamCenterToPlayer.y = plTargetY - camCenterY;
128 if (TimeUtils.timeSinceMillis(mCameraDelayMs) < 500L && !player.getVelocity().isZero()) {
129 updateStaticCameraPosition(plTargetX - mCamCenterToPlayer.x,
130 camCenterY + moveVector.y * delta * 2);
131 return;
134 float camX = getCamX();
135 float camY = getCamY();
136 float worldWidth = MeasureUnitsUtilsKt.getPx(mGameWorld.getWidth()) - getWidth() / 2;
138 if (moveVector.x >= worldWidth) {
139 camX += mGameWorld.getWidthPx();
140 moveVector.x -= mGameWorld.getWidthPx();
141 } else if (moveVector.x <= -worldWidth) {
142 camX -= mGameWorld.getWidthPx();
143 moveVector.x += mGameWorld.getWidthPx();
146 setCamPos(camX + moveVector.x * delta * 2, camY + moveVector.y * delta * 2);
149 camX = getCamX();
150 camY = getCamY();
152 if (camX + getWidth() / 2 > plTargetX + MAX_CAM_DISTANCE_FROM_PLAYER) {
153 camX = plTargetX + MAX_CAM_DISTANCE_FROM_PLAYER - getWidth() / 2;
156 if (camY + getHeight() / 2 > plTargetY + MAX_CAM_DISTANCE_FROM_PLAYER) {
157 camY = plTargetY + MAX_CAM_DISTANCE_FROM_PLAYER - getHeight() / 2;
160 if (camX + getWidth() / 2 < plTargetX - MAX_CAM_DISTANCE_FROM_PLAYER) {
161 camX = plTargetX - MAX_CAM_DISTANCE_FROM_PLAYER - getWidth() / 2;
164 if (camY + getHeight() / 2 < plTargetY - MAX_CAM_DISTANCE_FROM_PLAYER) {
165 camY = plTargetY - MAX_CAM_DISTANCE_FROM_PLAYER - getHeight() / 2;
168 setCamPos(camX, camY);
171 private void updateStaticCameraPosition(float targetX, float targetY) {
172 setCamPos(targetX - getWidth() / 2, targetY - getHeight() / 2);
175 private void updateStaticCameraPosition() {
176 Player player = mMobsController.getPlayer();
178 updateStaticCameraPosition(player.getX() + player.getWidth() / 2,
179 player.getY() + player.getHeight() / 2);
182 private void updateCameraPosition(float delta) {
183 if (mMainConfig.isUseDynamicCamera()) {
184 updateDynamicCameraPosition(delta);
185 } else {
186 updateStaticCameraPosition();
190 private float transformScreenX(int screenX) {
191 return getWidth() / Gdx.graphics.getWidth() * screenX;
194 private float transformScreenY(int screenY) {
195 return getHeight() / Gdx.graphics.getHeight() * screenY;
198 private void handleMousePosition() {
199 final Rectangle viewport = getCameraViewport();
201 final float screenX = transformScreenX(Gdx.input.getX());
202 final float screenY = transformScreenY(Gdx.input.getY());
204 final MouseInputAction action = new MouseInputAction(
205 screenX,
206 screenY,
207 MouseInputActionKey.None.INSTANCE,
208 viewport);
210 mCursorMouseInputHandler.handle(action);
212 if (!mTooltipManager.getCurrentMouseTooltip().isEmpty()) {
213 RenderingUtilsKt.drawString(spriter, mTooltipManager.getCurrentMouseTooltip(), screenX + 1, screenY + 1, Color.BLACK);
214 RenderingUtilsKt.drawString(spriter, mTooltipManager.getCurrentMouseTooltip(), screenX, screenY, Color.WHITE);
218 private boolean handleMouseAction(@CheckForNull MouseInputAction action) {
219 if (action == null) {
220 return false;
223 boolean anyProcessed = false;
225 for (IGameInputHandler<MouseInputAction> handler : mMouseInputHandlers) {
226 final boolean conditions = handler.checkConditions(action);
227 if (conditions) {
228 anyProcessed = true;
229 handler.handle(action);
230 break;
232 // anyProcessed = anyProcessed || conditions;
234 return anyProcessed;
237 private boolean onMouseActionEvent(int mouseX, int mouseY, int button, boolean touchUp, int pointer) {
238 @CheckForNull MouseInputAction action = mMouseInputActionMapper
239 .map((float) mouseX, (float) mouseY, getCameraViewport(), button, touchUp, pointer);
240 return handleMouseAction(action);
243 @Override
244 public boolean touchUp(int screenX, int screenY, int pointer, int button) {
245 float touchX = transformScreenX(screenX);
246 float touchY = transformScreenY(screenY);
248 final Joystick joy = mMainConfig.getJoystick();
250 if (mMainConfig.isTouch()) {
251 if (joy != null && joy.getActive() && joy.getPointer() == pointer) {
252 return onMouseActionEvent(screenX, screenY, nullButton.getCode(), true, pointer);
255 TouchButton touchedKey = getTouchedKey(touchX, touchY);
256 if (touchedKey.isMouse()) {
257 return onMouseActionEvent(screenX, screenY, touchedKey.getCode(), true, pointer);
258 } else {
259 return keyUp(touchedKey.getCode());
263 return onMouseActionEvent(screenX, screenY, button, true, pointer);
266 private TouchButton getTouchedKey(float touchX, float touchY) {
267 if (mGameWindowsManager.getCurrentWindowType() != GameUiWindow.NONE) {
268 return nullButton;
270 for (ObjectMap.Entry<String, TouchButton> entry : Assets.guiMap) {
271 TouchButton button = entry.value;
272 if (button.getRect().contains(touchX, touchY)) {
273 return button;
277 if (mouseLeftTouchButton.getRect().contains(touchX, touchY)) {
278 return mouseLeftTouchButton;
281 if (mouseRightTouchButton.getRect().contains(touchX, touchY)) {
282 return mouseRightTouchButton;
285 return nullButton;
288 @Override
289 public boolean touchDown(int screenX, int screenY, int pointer, int button) {
290 float touchX = transformScreenX(screenX);
291 float touchY = transformScreenY(screenY);
293 mTouchDownX = touchX;
294 mTouchDownY = touchY;
296 if (mMainConfig.isTouch()) {
297 TouchButton touchedKey = getTouchedKey(touchX, touchY);
298 if (touchedKey.isMouse()) {
299 return onMouseActionEvent(screenX, screenY, touchedKey.getCode(), false, pointer);
300 } else {
301 return keyDown(touchedKey.getCode());
305 return onMouseActionEvent(screenX, screenY, button, false, pointer);
308 @Override
309 public boolean touchDragged(int screenX, int screenY, int pointer) {
310 float touchX = transformScreenX(screenX);
311 float touchY = transformScreenY(screenY);
313 if (Math.abs(touchX - mTouchDownX) < 16 && Math.abs(touchY - mTouchDownY) < DRAG_THRESHOLD) {
314 return false;
317 @CheckForNull MouseInputAction action =
318 mMouseInputActionMapper.mapDragged(screenX, screenY, getCameraViewport(), pointer);
319 return handleMouseAction(action);
322 @Override
323 public boolean scrolled(float amountX, float amountY) {
324 @CheckForNull MouseInputAction action = mMouseInputActionMapper
325 .mapScrolled(Gdx.input.getX(), Gdx.input.getY(), amountX, amountY, getCameraViewport());
326 return handleMouseAction(action);
329 private boolean handleKeyboardAction(int keycode, boolean isKeyDown) {
330 @CheckForNull final KeyboardInputAction action = mKeyboardInputActionMapper
331 .map(keycode, isKeyDown);
333 if (action == null) {
334 return false;
337 boolean anyProcessed = false;
339 for (IGameInputHandler<KeyboardInputAction> handler : mKeyboardInputHandlers) {
340 final boolean conditions = handler.checkConditions(action);
341 if (conditions) {
342 anyProcessed = true;
343 handler.handle(action);
344 break;
348 return anyProcessed;
351 @Override
352 public boolean keyDown(int keycode) {
353 return handleKeyboardAction(keycode, true);
356 @Override
357 public boolean keyUp(int keycode) {
358 return handleKeyboardAction(keycode, false);
361 @Override
362 public void render(float delta) {
363 updateCameraPosition(delta);
365 if (mMainConfig.getJoystick() != null && mMainConfig.getJoystick().getActive()) {
366 mMainConfig.getJoystick().updateState(
367 transformScreenX(Gdx.input.getX(mMainConfig.getJoystick().getPointer())),
368 transformScreenY(Gdx.input.getY(mMainConfig.getJoystick().getPointer()))
369 );
372 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
374 spriter.begin();
375 mRenderers.forEach(iGameRenderer -> iGameRenderer.draw(spriter, shaper, getCameraViewport(), delta));
376 handleMousePosition();
377 spriter.end();