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 ru
.deadsoftware
.cavedroid
.MainConfig
;
8 import ru
.deadsoftware
.cavedroid
.game
.mobs
.Mob
;
9 import ru
.deadsoftware
.cavedroid
.game
.mobs
.MobsController
;
10 import ru
.deadsoftware
.cavedroid
.game
.mobs
.Player
;
11 import ru
.deadsoftware
.cavedroid
.game
.objects
.Drop
;
12 import ru
.deadsoftware
.cavedroid
.game
.objects
.DropController
;
13 import ru
.deadsoftware
.cavedroid
.game
.world
.GameWorld
;
15 import javax
.annotation
.CheckForNull
;
16 import javax
.inject
.Inject
;
17 import java
.util
.Iterator
;
21 public class GamePhysics
{
23 public static final float PL_SPEED
= 69.072f;
24 public static final float PL_JUMP_VELOCITY
= -133.332f;
25 public static final float PL_TERMINAL_VELOCITY
= 1254.4f;
27 private final Vector2 gravity
= new Vector2(0, 444.44f);
29 private final GameWorld mGameWorld
;
30 private final MainConfig mMainConfig
;
31 private final MobsController mMobsController
;
32 private final DropController mDropController
;
35 public GamePhysics(GameWorld gameWorld
,
36 MainConfig mainConfig
,
37 MobsController mobsController
,
38 DropController dropController
) {
39 mGameWorld
= gameWorld
;
40 mMainConfig
= mainConfig
;
41 mMobsController
= mobsController
;
42 mDropController
= dropController
;
46 * Checks if mob should jump
48 * @return true if mob should jump
50 private boolean checkJump(Mob mob
) {
51 int dir
= mob
.looksLeft() ?
0 : 1;
52 int blX
= (int) (mob
.getX() + mob
.getWidth() * dir
- 8 + 16 * dir
);
53 int blY
= (int) (mob
.getY() + mob
.getHeight() - 8);
54 int block
= mGameWorld
.getForeMap(blX
/ 16, blY
/ 16);
56 if (checkColl(new Rectangle(blX
, mob
.getY() - 18, mob
.getWidth(), mob
.getHeight()))) {
60 return (block
> 0 && GameItems
.getBlock(block
).toJump() &&
61 (mob
.getY() + mob
.getHeight()) - GameItems
.getBlock(block
).getRectangle(blX
/ 16, blY
/ 16).y
> 8);
64 private boolean checkColl(Rectangle rect
) {
65 int minX
= (int) ((rect
.x
+ rect
.width
/ 2) / 16) - 4;
66 int minY
= (int) ((rect
.y
+ rect
.height
/ 2) / 16) - 4;
67 int maxX
= (int) ((rect
.x
+ rect
.width
/ 2) / 16) + 4;
68 int maxY
= (int) ((rect
.y
+ rect
.height
/ 2) / 16) + 4;
74 if (maxY
> mGameWorld
.getHeight()) {
75 maxY
= mGameWorld
.getHeight();
79 for (int y
= minY
; y
< maxY
; y
++) {
80 for (int x
= minX
; x
< maxX
; x
++) {
81 block
= mGameWorld
.getForeMap(x
, y
);
82 if (block
> 0 && GameItems
.getBlock(block
).hasCollision()) {
83 if (Intersector
.overlaps(rect
, GameItems
.getBlock(block
).getRectangle(x
, y
))) {
93 private int getBlock(Rectangle rect
) {
94 return mGameWorld
.getForeMap((int) (rect
.x
+ rect
.width
/ 2) / 16,
95 (int) (rect
.y
+ rect
.height
/ 8 * 7) / 16);
98 private Rectangle
getShiftedPlayerRect(float shift
) {
99 final Player player
= mMobsController
.getPlayer();
100 return new Rectangle(player
.x
+ shift
, player
.y
, player
.width
, player
.height
);
104 * @return Rectangle representing magneting target for this drop
107 private Rectangle
getShiftedMagnetingPlayerRect(Drop drop
) {
108 final Player player
= mMobsController
.getPlayer();
110 if (drop
.canMagnetTo(player
)) {
111 return getShiftedPlayerRect(0);
114 final Rectangle shiftedLeft
= getShiftedPlayerRect(-mGameWorld
.getWidthPx());
115 if (drop
.canMagnetTo(shiftedLeft
)) {
119 final Rectangle shiftedRight
= getShiftedPlayerRect(mGameWorld
.getWidthPx());
120 if (drop
.canMagnetTo(shiftedRight
)) {
127 private void pickUpDropIfPossible(Rectangle shiftedPlayerTarget
, Drop drop
) {
128 final Player player
= mMobsController
.getPlayer();
130 if (Intersector
.overlaps(shiftedPlayerTarget
, drop
)) {
131 player
.pickUpDrop(drop
);
135 private void dropPhy(Drop drop
, float delta
) {
136 final Rectangle playerMagnetTarget
= getShiftedMagnetingPlayerRect(drop
);
137 final Vector2 dropVelocity
= drop
.getVelocity();
140 if (playerMagnetTarget
!= null) {
141 final Vector2 magnetVector
= new Vector2(playerMagnetTarget
.x
- drop
.x
,
142 playerMagnetTarget
.y
- drop
.y
);
143 magnetVector
.nor().scl(Drop
.MAGNET_VELOCITY
* delta
);
144 dropVelocity
.add(magnetVector
);
146 dropVelocity
.y
+= gravity
.y
* delta
;
149 dropVelocity
.x
= MathUtils
.clamp(dropVelocity
.x
, -Drop
.MAGNET_VELOCITY
, Drop
.MAGNET_VELOCITY
);
150 dropVelocity
.y
= MathUtils
.clamp(dropVelocity
.y
, -Drop
.MAGNET_VELOCITY
, Drop
.MAGNET_VELOCITY
);
152 drop
.x
+= dropVelocity
.x
* delta
;
153 drop
.y
+= dropVelocity
.y
* delta
;
155 if (checkColl(drop
)) {
156 dropVelocity
.setZero();
159 } while (checkColl(drop
));
162 if (playerMagnetTarget
!= null) {
163 pickUpDropIfPossible(playerMagnetTarget
, drop
);
167 private void mobXColl(Mob mob
) {
168 if (checkColl(mob
)) {
169 if (mob
.canJump() && !mob
.isFlyMode()) {
173 if (checkColl(mob
)) {
174 if (mob
.canJump() && !mob
.isFlyMode()) {
180 if (mob
.getVelocity().x
< 0) {
182 } else if (mob
.getVelocity().x
> 0) {
186 mob
.x
= MathUtils
.round(mob
.getX());
188 while (checkColl(mob
)) {
198 mob
.checkWorldBounds(mGameWorld
);
201 private void mobYColl(Mob mob
) {
202 if (checkColl(mob
)) {
205 if (mob
.getVelocity().y
< 0) {
210 mob
.setCanJump(true);
211 mob
.setFlyMode(false);
214 mob
.y
= MathUtils
.round(mob
.getY());
216 while (checkColl(mob
)) {
220 mob
.getVelocity().y
= 0;
226 // dmg = max(0, (h - 48) / 32) - half of blocks fallen starting from 3 blocks height
227 // int dmg = ((int)Math.max(0f, (((mob.getVelocity().y * mob.getVelocity().y) / (2 * gravity.y)) - 48f) / 16f));
228 // if (dmg > 0) System.out.println("Damage: " + dmg);
232 mob
.setCanJump(checkColl(mob
));
236 if (mob
.getY() > mGameWorld
.getHeightPx()) {
241 private void playerPhy(Player player
, float delta
) {
242 if (player
.isDead()) {
246 if (GameItems
.isFluid(getBlock(player
))) {
247 if (mMainConfig
.isTouch() && player
.getVelocity().x
!= 0 && !player
.swim
&& !player
.isFlyMode()) {
251 if (!player
.isFlyMode() && player
.getVelocity().y
< 32f) {
252 player
.getVelocity().y
+= gravity
.y
* delta
;
254 if (!player
.isFlyMode() && player
.getVelocity().y
> 32f) {
255 player
.getVelocity().y
-= player
.getVelocity().y
* 32f * delta
;
258 player
.getVelocity().y
+= PL_JUMP_VELOCITY
* delta
;
259 if (player
.getVelocity().y
< -PL_SPEED
) {
260 player
.getVelocity().y
= -PL_SPEED
;
264 if (!player
.isFlyMode() && player
.getVelocity().y
< PL_TERMINAL_VELOCITY
) {
265 player
.getVelocity().y
+= gravity
.y
* delta
;
269 player
.y
+= player
.getVelocity().y
* delta
;
272 player
.x
+= player
.getVelocity().x
* (player
.isFlyMode() ?
1.5f : 1) *
273 (GameItems
.isFluid(getBlock(player
)) && !player
.isFlyMode() ?
.8f : 1) * delta
;
277 if (mMainConfig
.isTouch() && !player
.isFlyMode() && player
.canJump() && player
.getVelocity().x
!= 0 && checkJump(player
)) {
278 player
.getVelocity().y
= PL_JUMP_VELOCITY
;
279 player
.setCanJump(false);
283 private void mobPhy(Mob mob
, float delta
) {
284 if (mob
.getType() == Mob
.Type
.MOB
&& GameItems
.isFluid(getBlock(mob
))) {
285 if (mob
.getVelocity().y
> 32f) {
286 mob
.getVelocity().y
-= mob
.getVelocity().y
* 32f * delta
;
289 mob
.getVelocity().y
+= PL_JUMP_VELOCITY
* delta
;
291 if (mob
.getVelocity().y
< -PL_SPEED
) {
292 mob
.getVelocity().y
= -PL_SPEED
;
294 } else if (!mob
.isFlyMode() && mob
.getVelocity().y
< PL_TERMINAL_VELOCITY
) {
295 mob
.getVelocity().y
+= gravity
.y
* delta
;
298 mob
.y
+= mob
.getVelocity().y
* delta
;
305 mob
.x
+= mob
.getVelocity().x
* delta
;
308 if (mob
.canJump() && mob
.getVelocity().x
!= 0 && checkJump(mob
)) {
309 mob
.getVelocity().y
= PL_JUMP_VELOCITY
;
310 mob
.setCanJump(false);
314 void update(float delta
) {
315 Player player
= mMobsController
.getPlayer();
317 for (Iterator
<Drop
> it
= mDropController
.getIterator(); it
.hasNext(); ) {
318 Drop drop
= it
.next();
319 dropPhy(drop
, delta
);
320 if (drop
.getPickedUp()) {
325 for (Iterator
<Mob
> it
= mMobsController
.getIterator(); it
.hasNext(); ) {
327 mob
.ai(mGameWorld
, delta
);
334 playerPhy(player
, delta
);
335 if (player
.isDead()) {
336 player
.respawn(mGameWorld
);