1 package ru
.deadsoftware
.cavedroid
.game
;
3 import com
.badlogic
.gdx
.math
.Intersector
;
4 import com
.badlogic
.gdx
.math
.MathUtils
;
5 import com
.badlogic
.gdx
.math
.Rectangle
;
6 import com
.badlogic
.gdx
.math
.Vector2
;
7 import org
.jetbrains
.annotations
.Nullable
;
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
.player
.Player
;
12 import ru
.deadsoftware
.cavedroid
.game
.model
.block
.Block
;
13 import ru
.deadsoftware
.cavedroid
.game
.model
.item
.InventoryItem
;
14 import ru
.deadsoftware
.cavedroid
.game
.objects
.drop
.Drop
;
15 import ru
.deadsoftware
.cavedroid
.game
.objects
.drop
.DropController
;
16 import ru
.deadsoftware
.cavedroid
.game
.world
.GameWorld
;
18 import javax
.inject
.Inject
;
19 import java
.util
.Iterator
;
23 public class GamePhysics
{
25 public static final float PL_JUMP_VELOCITY
= -133.332f;
26 public static final float PL_TERMINAL_VELOCITY
= 1254.4f;
28 private final Vector2 gravity
= new Vector2(0, 444.44f);
30 private final GameWorld mGameWorld
;
31 private final MainConfig mMainConfig
;
32 private final MobsController mMobsController
;
33 private final DropController mDropController
;
34 private final GameItemsHolder mGameItemsHolder
;
37 public GamePhysics(GameWorld gameWorld
,
38 MainConfig mainConfig
,
39 MobsController mobsController
,
40 DropController dropController
,
41 GameItemsHolder gameItemsHolder
) {
42 mGameWorld
= gameWorld
;
43 mMainConfig
= mainConfig
;
44 mMobsController
= mobsController
;
45 mDropController
= dropController
;
46 mGameItemsHolder
= gameItemsHolder
;
50 * Checks if mob should jump
52 * @return true if mob should jump
54 private boolean checkJump(Mob mob
) {
55 int dir
= mob
.looksLeft() ?
0 : 1;
56 int blX
= (int) (mob
.getX() + mob
.getWidth() * dir
- 8 + 16 * dir
);
57 int blY
= (int) (mob
.getY() + mob
.getHeight() - 8);
58 Block block
= mGameWorld
.getForeMap(blX
/ 16, blY
/ 16);
60 if (checkColl(new Rectangle(blX
, mob
.getY() - 18, mob
.getWidth(), mob
.getHeight())) != null) {
64 return (block
.toJump() &&
65 (mob
.getY() + mob
.getHeight()) - block
.getRectangle(blX
/ 16, blY
/ 16).y
> 8);
69 * @return colliding rect or null if no collision
72 private Rectangle
checkColl(Rectangle rect
) {
73 int minX
= (int) ((rect
.x
+ rect
.width
/ 2) / 16) - 4;
74 int minY
= (int) ((rect
.y
+ rect
.height
/ 2) / 16) - 4;
75 int maxX
= (int) ((rect
.x
+ rect
.width
/ 2) / 16) + 4;
76 int maxY
= (int) ((rect
.y
+ rect
.height
/ 2) / 16) + 4;
82 if (maxY
> mGameWorld
.getHeight()) {
83 maxY
= mGameWorld
.getHeight();
87 for (int y
= minY
; y
< maxY
; y
++) {
88 for (int x
= minX
; x
< maxX
; x
++) {
89 if (!mGameWorld
.hasForeAt(x
, y
)) {
92 block
= mGameWorld
.getForeMap(x
, y
);
93 if (block
.hasCollision()) {
94 final Rectangle blockRect
= block
.getRectangle(x
, y
);
95 if (Intersector
.overlaps(rect
, blockRect
)) {
105 private Block
getBlock(Rectangle rect
) {
106 return mGameWorld
.getForeMap((int) (rect
.x
+ rect
.width
/ 2) / 16,
107 (int) (rect
.y
+ rect
.height
/ 8 * 7) / 16);
110 private Rectangle
getShiftedPlayerRect(float shift
) {
111 final Player player
= mMobsController
.getPlayer();
112 return new Rectangle(player
.x
+ shift
, player
.y
, player
.width
, player
.height
);
116 * @return Rectangle representing magneting target for this drop
119 private Rectangle
getShiftedMagnetingPlayerRect(Drop drop
) {
120 final Player player
= mMobsController
.getPlayer();
122 if (!player
.inventory
.canPickItem(drop
)) {
126 if (drop
.canMagnetTo(player
)) {
127 return getShiftedPlayerRect(0);
130 final Rectangle shiftedLeft
= getShiftedPlayerRect(-mGameWorld
.getWidthPx());
131 if (drop
.canMagnetTo(shiftedLeft
)) {
135 final Rectangle shiftedRight
= getShiftedPlayerRect(mGameWorld
.getWidthPx());
136 if (drop
.canMagnetTo(shiftedRight
)) {
143 private void pickUpDropIfPossible(Rectangle shiftedPlayerTarget
, Drop drop
) {
144 final Player player
= mMobsController
.getPlayer();
146 if (Intersector
.overlaps(shiftedPlayerTarget
, drop
)) {
147 player
.inventory
.pickDrop(drop
);
151 private void dropPhy(Drop drop
, float delta
) {
152 final Rectangle playerMagnetTarget
= getShiftedMagnetingPlayerRect(drop
);
153 final Vector2 dropVelocity
= drop
.getVelocity();
156 if (playerMagnetTarget
!= null) {
157 final Vector2 magnetVector
= new Vector2(playerMagnetTarget
.x
- drop
.x
,
158 playerMagnetTarget
.y
- drop
.y
);
159 magnetVector
.nor().scl(Drop
.MAGNET_VELOCITY
* delta
);
160 dropVelocity
.add(magnetVector
);
162 dropVelocity
.y
+= gravity
.y
* delta
;
165 dropVelocity
.x
= MathUtils
.clamp(dropVelocity
.x
, -Drop
.MAGNET_VELOCITY
, Drop
.MAGNET_VELOCITY
);
166 dropVelocity
.y
= MathUtils
.clamp(dropVelocity
.y
, -Drop
.MAGNET_VELOCITY
, Drop
.MAGNET_VELOCITY
);
168 drop
.x
+= dropVelocity
.x
* delta
;
169 drop
.y
+= dropVelocity
.y
* delta
;
171 if (checkColl(drop
) != null) {
172 dropVelocity
.setZero();
175 } while (checkColl(drop
) != null);
178 if (playerMagnetTarget
!= null) {
179 pickUpDropIfPossible(playerMagnetTarget
, drop
);
183 private void mobXColl(Mob mob
) {
184 if (mob
.getVelocity().x
== 0f) {
188 @Nullable Rectangle collidingRect
= checkColl(mob
);
190 if (collidingRect
!= null) {
191 if (mob
.canJump() && !mob
.isFlyMode() && collidingRect
.y
>= mob
.y
+ mob
.height
- 8) {
192 mob
.y
= collidingRect
.y
- mob
.height
;
196 collidingRect
= checkColl(mob
);
198 if (collidingRect
!= null) {
201 if (mob
.getVelocity().x
< 0) {
203 } else if (mob
.getVelocity().x
> 0) {
208 mob
.x
= collidingRect
.x
- mob
.width
;
210 mob
.x
= collidingRect
.x
+ collidingRect
.width
;
213 // mob.x = MathUtils.round(mob.getX());
214 // while (checkColl(mob) != null) {
224 mob
.checkWorldBounds(mGameWorld
);
227 private void mobYColl(Mob mob
) {
228 @Nullable final Rectangle collidingRect
= checkColl(mob
);
229 if (collidingRect
!= null) {
232 if (mob
.getVelocity().y
< 0) {
237 mob
.setCanJump(true);
238 mob
.setFlyMode(false);
240 int dmg
= ((int)Math
.max(0f, (((mob
.getVelocity().y
* mob
.getVelocity().y
) / (2 * gravity
.y
)) - 48f) / 16f));
247 mob
.y
= collidingRect
.y
- mob
.height
;
249 mob
.y
= collidingRect
.y
+ collidingRect
.height
;
253 // mob.y = MathUtils.round(mob.getY());
255 // while (checkColl(mob)) {
259 mob
.getVelocity().y
= 0;
263 mob
.setCanJump(checkColl(mob
) != null);
267 if (mob
.getY() > mGameWorld
.getHeightPx()) {
272 private void playerPhy(Player player
, float delta
) {
273 if (player
.isDead()) {
277 if (getBlock(player
).isFluid()) {
278 if (mMainConfig
.isTouch() && player
.getVelocity().x
!= 0 && !player
.swim
&& !player
.isFlyMode()) {
282 if (!player
.isFlyMode() && player
.getVelocity().y
< 32f) {
283 player
.getVelocity().y
+= gravity
.y
* delta
;
285 if (!player
.isFlyMode() && player
.getVelocity().y
> 32f) {
286 player
.getVelocity().y
-= player
.getVelocity().y
* 32f * delta
;
289 player
.getVelocity().y
+= PL_JUMP_VELOCITY
* delta
;
290 if (player
.getVelocity().y
< -player
.getSpeed()) {
291 player
.getVelocity().y
= -player
.getSpeed();
295 if (!player
.isFlyMode() && player
.getVelocity().y
< PL_TERMINAL_VELOCITY
) {
296 player
.getVelocity().y
+= gravity
.y
* delta
;
300 player
.y
+= player
.getVelocity().y
* delta
;
303 player
.x
+= player
.getVelocity().x
* (player
.isFlyMode() ?
1.5f : 1) *
304 (getBlock(player
).isFluid() && !player
.isFlyMode() ?
.8f : 1) * delta
;
308 if (mMainConfig
.isTouch() && !player
.isFlyMode() && player
.canJump() && player
.getVelocity().x
!= 0 && checkJump(player
)) {
310 player
.setCanJump(false);
314 private void mobPhy(Mob mob
, float delta
) {
315 if (mob
.getType() == Mob
.Type
.MOB
&& getBlock(mob
).isFluid()) {
316 if (mob
.getVelocity().y
> 32f) {
317 mob
.getVelocity().y
-= mob
.getVelocity().y
* 32f * delta
;
320 mob
.getVelocity().y
+= PL_JUMP_VELOCITY
* delta
;
322 if (mob
.getVelocity().y
< -mob
.getSpeed()) {
323 mob
.getVelocity().y
= -mob
.getSpeed();
325 } else if (!mob
.isFlyMode() && mob
.getVelocity().y
< PL_TERMINAL_VELOCITY
) {
326 mob
.getVelocity().y
+= gravity
.y
* delta
;
329 mob
.y
+= mob
.getVelocity().y
* delta
;
336 mob
.x
+= mob
.getVelocity().x
* delta
;
339 if (mob
.canJump() && mob
.getVelocity().x
!= 0 && checkJump(mob
)) {
341 mob
.setCanJump(false);
345 void update(float delta
) {
346 Player player
= mMobsController
.getPlayer();
348 for (Iterator
<Drop
> it
= mDropController
.getIterator(); it
.hasNext(); ) {
349 Drop drop
= it
.next();
350 dropPhy(drop
, delta
);
351 if (drop
.getPickedUp()) {
356 for (Iterator
<Mob
> it
= mMobsController
.getMobs().iterator(); it
.hasNext(); ) {
358 mob
.ai(mGameWorld
, mGameItemsHolder
, mMobsController
, delta
);
361 for (InventoryItem invItem
: mob
.getDrop(mGameItemsHolder
)) {
362 mDropController
.addDrop(mob
.x
, mob
.y
, invItem
);
369 playerPhy(player
, delta
);
370 player
.ai(mGameWorld
, mGameItemsHolder
, mMobsController
, delta
);
371 if (player
.isDead()) {
372 for (InventoryItem invItem
: player
.inventory
.getItems()) {
373 mDropController
.addDrop(player
.x
, player
.y
, invItem
);
375 player
.inventory
.clear();
376 player
.respawn(mGameWorld
, mGameItemsHolder
);