X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=core%2Fsrc%2Fru%2Fdeadsoftware%2Fcavedroid%2Fgame%2FGamePhysics.java;h=d9bf21fe5dec302fad3e1cf984e7d44eae22852e;hb=3d972278cf3a54b6a7b574690ca4b41577464dce;hp=d753b668bc969e6410ba801fe173a594e0d510a7;hpb=59d48c1b28c570755327a8fb0827fa57e7fd3914;p=cavedroid.git diff --git a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java index d753b66..d9bf21f 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java @@ -4,20 +4,46 @@ import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import ru.deadsoftware.cavedroid.CaveGame; +import ru.deadsoftware.cavedroid.MainConfig; import ru.deadsoftware.cavedroid.game.mobs.Mob; -import ru.deadsoftware.cavedroid.game.mobs.Player; -import ru.deadsoftware.cavedroid.game.objects.Drop; - +import ru.deadsoftware.cavedroid.game.mobs.MobsController; +import ru.deadsoftware.cavedroid.game.mobs.player.Player; +import ru.deadsoftware.cavedroid.game.model.block.Block; +import ru.deadsoftware.cavedroid.game.objects.drop.Drop; +import ru.deadsoftware.cavedroid.game.objects.drop.DropController; +import ru.deadsoftware.cavedroid.game.world.GameWorld; + +import javax.annotation.CheckForNull; +import javax.inject.Inject; import java.util.Iterator; -import static ru.deadsoftware.cavedroid.GameScreen.GP; -class GamePhysics { +@GameScope +public class GamePhysics { + + public static final float PL_JUMP_VELOCITY = -133.332f; + public static final float PL_TERMINAL_VELOCITY = 1254.4f; - static final int PL_SPEED = 2; + private final Vector2 gravity = new Vector2(0, 444.44f); - private final Vector2 gravity = new Vector2(0, .9f); + private final GameWorld mGameWorld; + private final MainConfig mMainConfig; + private final MobsController mMobsController; + private final DropController mDropController; + private final GameItemsHolder mGameItemsHolder; + + @Inject + public GamePhysics(GameWorld gameWorld, + MainConfig mainConfig, + MobsController mobsController, + DropController dropController, + GameItemsHolder gameItemsHolder) { + mGameWorld = gameWorld; + mMainConfig = mainConfig; + mMobsController = mobsController; + mDropController = dropController; + mGameItemsHolder = gameItemsHolder; + } /** * Checks if mob should jump @@ -28,17 +54,21 @@ class GamePhysics { int dir = mob.looksLeft() ? 0 : 1; int blX = (int) (mob.getX() + mob.getWidth() * dir - 8 + 16 * dir); int blY = (int) (mob.getY() + mob.getHeight() - 8); - int block = GP.world.getForeMap(blX / 16, blY / 16); + Block block = mGameWorld.getForeMap(blX / 16, blY / 16); - if (checkColl(new Rectangle(blX, mob.getY() - 18, mob.getWidth(), mob.getHeight()))) { - block = 0; + if (checkColl(new Rectangle(blX, mob.getY() - 18, mob.getWidth(), mob.getHeight())) != null) { + return false; } - return (block > 0 && GameItems.getBlock(block).toJump() && - (mob.getY() + mob.getHeight()) - GameItems.getBlock(block).getRect(blX / 16, blY / 16).y > 8); + return (block.toJump() && + (mob.getY() + mob.getHeight()) - block.getRectangle(blX / 16, blY / 16).y > 8); } - private boolean checkColl(Rectangle rect) { + /** + * @return colliding rect or null if no collision + */ + @CheckForNull + private Rectangle checkColl(Rectangle rect) { int minX = (int) ((rect.x + rect.width / 2) / 16) - 4; int minY = (int) ((rect.y + rect.height / 2) / 16) - 4; int maxX = (int) ((rect.x + rect.width / 2) / 16) + 4; @@ -48,222 +78,294 @@ class GamePhysics { minY = 0; } - if (maxY > GP.world.getHeight()) { - maxY = GP.world.getHeight(); + if (maxY > mGameWorld.getHeight()) { + maxY = mGameWorld.getHeight(); } - int block; + Block block; for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { - block = GP.world.getForeMap(x, y); - if (block > 0 && GameItems.getBlock(block).hasCollision()) { - if (Intersector.overlaps(rect, GameItems.getBlock(block).getRect(x, y))) { - return true; + if (!mGameWorld.hasForeAt(x, y)) { + continue; + } + block = mGameWorld.getForeMap(x, y); + if (block.hasCollision()) { + final Rectangle blockRect = block.getRectangle(x, y); + if (Intersector.overlaps(rect, blockRect)) { + return blockRect; } } } } - return false; + return null; } - private int getBlock(Rectangle rect) { - return GP.world.getForeMap((int) (rect.x + rect.width / 2) / 16, + private Block getBlock(Rectangle rect) { + return mGameWorld.getForeMap((int) (rect.x + rect.width / 2) / 16, (int) (rect.y + rect.height / 8 * 7) / 16); } - private void dropPhy(Drop drop) { - if (drop.closeToPlayer() > 0) { - drop.moveToPlayer(); + private Rectangle getShiftedPlayerRect(float shift) { + final Player player = mMobsController.getPlayer(); + return new Rectangle(player.x + shift, player.y, player.width, player.height); + } + + /** + * @return Rectangle representing magneting target for this drop + */ + @CheckForNull + private Rectangle getShiftedMagnetingPlayerRect(Drop drop) { + final Player player = mMobsController.getPlayer(); + + if (!player.inventory.canPickItem(drop)) { + return null; + } + + if (drop.canMagnetTo(player)) { + return getShiftedPlayerRect(0); + } + + final Rectangle shiftedLeft = getShiftedPlayerRect(-mGameWorld.getWidthPx()); + if (drop.canMagnetTo(shiftedLeft)) { + return shiftedLeft; + } + + final Rectangle shiftedRight = getShiftedPlayerRect(mGameWorld.getWidthPx()); + if (drop.canMagnetTo(shiftedRight)) { + return shiftedRight; + } + + return null; + } + + private void pickUpDropIfPossible(Rectangle shiftedPlayerTarget, Drop drop) { + final Player player = mMobsController.getPlayer(); + + if (Intersector.overlaps(shiftedPlayerTarget, drop)) { + player.inventory.pickDrop(drop); + } + } + + private void dropPhy(Drop drop, float delta) { + final Rectangle playerMagnetTarget = getShiftedMagnetingPlayerRect(drop); + final Vector2 dropVelocity = drop.getVelocity(); + + + if (playerMagnetTarget != null) { + final Vector2 magnetVector = new Vector2(playerMagnetTarget.x - drop.x, + playerMagnetTarget.y - drop.y); + magnetVector.nor().scl(Drop.MAGNET_VELOCITY * delta); + dropVelocity.add(magnetVector); } else { - if (drop.getMove().x >= .5f) { - drop.getMove().x -= .5f; - } else if (drop.getMove().x <= -.5f) { - drop.getMove().x += .5f; - } else { - drop.getMove().x = 0; - } - if (drop.getMove().y < 9) { - drop.getMove().y += gravity.y / 4; - } + dropVelocity.y += gravity.y * delta; } - drop.move(); + dropVelocity.x = MathUtils.clamp(dropVelocity.x, -Drop.MAGNET_VELOCITY, Drop.MAGNET_VELOCITY); + dropVelocity.y = MathUtils.clamp(dropVelocity.y, -Drop.MAGNET_VELOCITY, Drop.MAGNET_VELOCITY); + + drop.x += dropVelocity.x * delta; + drop.y += dropVelocity.y * delta; - if (checkColl(drop)) { - drop.getMove().set(0, -1); + if (checkColl(drop) != null) { + dropVelocity.setZero(); do { - drop.move(); - } while (checkColl(drop)); - drop.getMove().setZero(); + drop.y--; + } while (checkColl(drop) != null); + } + + if (playerMagnetTarget != null) { + pickUpDropIfPossible(playerMagnetTarget, drop); } } private void mobXColl(Mob mob) { - if (checkColl(mob)) { - if (mob.canJump() && !mob.isFlyMode()) { - mob.y -= 8; + if (mob.getVelocity().x == 0f) { + return; + } + + @CheckForNull Rectangle collidingRect = checkColl(mob); + + if (collidingRect != null) { + if (mob.canJump() && !mob.isFlyMode() && collidingRect.y >= mob.y + mob.height - 8) { + mob.y = collidingRect.y - mob.height; + return; } - if (checkColl(mob)) { - if (mob.canJump() && !mob.isFlyMode()) { - mob.y += 8; - } + collidingRect = checkColl(mob); + if (collidingRect != null) { int d = 0; - if (mob.getMove().x < 0) { + if (mob.getVelocity().x < 0) { d = 1; - } else if (mob.getMove().x > 0) { + } else if (mob.getVelocity().x > 0) { d = -1; } - mob.x = MathUtils.round(mob.getX()); - - while (checkColl(mob)) { - mob.x += d; + if (d < 0) { + mob.x = collidingRect.x - mob.width; + } else { + mob.x = collidingRect.x + collidingRect.width; } +// mob.x = MathUtils.round(mob.getX()); +// while (checkColl(mob) != null) { +// mob.x += d; +// } + if (mob.canJump()) { mob.changeDir(); } } } - mob.checkWorldBounds(); + mob.checkWorldBounds(mGameWorld); } private void mobYColl(Mob mob) { - if (checkColl(mob)) { + @CheckForNull final Rectangle collidingRect = checkColl(mob); + if (collidingRect != null) { int d = -1; - if (mob.getMove().y < 0) { + if (mob.getVelocity().y < 0) { d = 1; } if (d == -1) { mob.setCanJump(true); mob.setFlyMode(false); - } - mob.y = MathUtils.round(mob.getY()); + int dmg = ((int)Math.max(0f, (((mob.getVelocity().y * mob.getVelocity().y) / (2 * gravity.y)) - 48f) / 16f)); + if (dmg > 0) { + mob.damage(dmg); + } + } - while (checkColl(mob)) { - mob.y += d; + if (d < 0) { + mob.y = collidingRect.y - mob.height; + } else { + mob.y = collidingRect.y + collidingRect.height; } - mob.getMove().y = 0; + +// mob.y = MathUtils.round(mob.getY()); +// +// while (checkColl(mob)) { +// mob.y += d; +// } + + mob.getVelocity().y = 0; } else { - mob.setCanJump(false); + mob.y += 1; + mob.setCanJump(checkColl(mob) != null); + mob.y -= 1; } - if (mob.getY() > GP.world.getHeightPx()) { + if (mob.getY() > mGameWorld.getHeightPx()) { mob.kill(); } } - private void playerPhy(Player player) { - player.y += player.getMove().y; - mobYColl(player); - + private void playerPhy(Player player, float delta) { if (player.isDead()) { return; } - if (GameItems.isFluid(getBlock(player))) { - if (CaveGame.TOUCH && player.getMove().x != 0 && !player.swim && !player.isFlyMode()) { + if (getBlock(player).isFluid()) { + if (mMainConfig.isTouch() && player.getVelocity().x != 0 && !player.swim && !player.isFlyMode()) { player.swim = true; } if (!player.swim) { - if (!player.isFlyMode() && player.getMove().y < 4.5f) { - player.getMove().add(gravity.x / 4, gravity.y / 4); + if (!player.isFlyMode() && player.getVelocity().y < 32f) { + player.getVelocity().y += gravity.y * delta; } - if (!player.isFlyMode() && player.getMove().y > 4.5f) { - player.getMove().add(0, -1f); + if (!player.isFlyMode() && player.getVelocity().y > 32f) { + player.getVelocity().y -= player.getVelocity().y * 32f * delta; } } else { - player.getMove().add(0, -.5f); - if (player.getMove().y < -3) { - player.getMove().y = -3; + player.getVelocity().y += PL_JUMP_VELOCITY * delta; + if (player.getVelocity().y < -player.getSpeed()) { + player.getVelocity().y = -player.getSpeed(); } } } else { - if (!player.isFlyMode() && player.getMove().y < 18) { - player.getMove().add(gravity); + if (!player.isFlyMode() && player.getVelocity().y < PL_TERMINAL_VELOCITY) { + player.getVelocity().y += gravity.y * delta; } } - player.x += player.getMove().x * (player.isFlyMode() ? 1.5f : 1) * - (GameItems.isFluid(getBlock(player)) && !player.isFlyMode() ? .8f : 1); + player.y += player.getVelocity().y * delta; + mobYColl(player); + + player.x += player.getVelocity().x * (player.isFlyMode() ? 1.5f : 1) * + (getBlock(player).isFluid() && !player.isFlyMode() ? .8f : 1) * delta; mobXColl(player); - if (CaveGame.TOUCH && !player.isFlyMode() && player.canJump() && player.getMove().x != 0 && checkJump(player)) { - player.getMove().add(0, -8); + if (mMainConfig.isTouch() && !player.isFlyMode() && player.canJump() && player.getVelocity().x != 0 && checkJump(player)) { + player.jump(); player.setCanJump(false); } } - private void mobPhy(Mob mob) { - if (mob.getType() == Mob.Type.MOB && GameItems.isFluid(getBlock(mob))) { - if (mob.getMove().y > 9) { - mob.getMove().add(0, -.9f); + private void mobPhy(Mob mob, float delta) { + if (mob.getType() == Mob.Type.MOB && getBlock(mob).isFluid()) { + if (mob.getVelocity().y > 32f) { + mob.getVelocity().y -= mob.getVelocity().y * 32f * delta; } - mob.getMove().add(0, -.5f); + mob.getVelocity().y += PL_JUMP_VELOCITY * delta; - if (mob.getMove().y < -3) { - mob.getMove().y = -3; + if (mob.getVelocity().y < -mob.getSpeed()) { + mob.getVelocity().y = -mob.getSpeed(); } - } else if (!mob.isFlyMode() && mob.getMove().y < 18) { - mob.getMove().add(gravity); + } else if (!mob.isFlyMode() && mob.getVelocity().y < PL_TERMINAL_VELOCITY) { + mob.getVelocity().y += gravity.y * delta; } - mob.y += mob.getMove().y; + mob.y += mob.getVelocity().y * delta; mobYColl(mob); if (mob.isDead()) { return; } - mob.x += mob.getMove().x; + mob.x += mob.getVelocity().x * delta; mobXColl(mob); - if (mob.canJump() && mob.getMove().x != 0 && checkJump(mob)) { - mob.getMove().add(0, -8); + if (mob.canJump() && mob.getVelocity().x != 0 && checkJump(mob)) { + mob.jump(); mob.setCanJump(false); } } - void update() { - for (Iterator it = GP.drops.iterator(); it.hasNext(); ) { + void update(float delta) { + Player player = mMobsController.getPlayer(); + + for (Iterator it = mDropController.getIterator(); it.hasNext(); ) { Drop drop = it.next(); - dropPhy(drop); - if (Intersector.overlaps(drop, GP.player)) { - drop.pickUpDrop(GP.player); - } - if (drop.isPickedUp()) { + dropPhy(drop, delta); + if (drop.getPickedUp()) { it.remove(); } } - for (Iterator it = GP.mobs.iterator(); it.hasNext(); ) { + for (Iterator it = mMobsController.getMobs().iterator(); it.hasNext(); ) { Mob mob = it.next(); - mob.ai(); - mobPhy(mob); + mob.ai(mGameWorld, mGameItemsHolder, delta); + mobPhy(mob, delta); if (mob.isDead()) { it.remove(); } } - playerPhy(GP.player); - if (GP.player.isDead()) { - GP.player.respawn(); + playerPhy(player, delta); + player.ai(mGameWorld, mGameItemsHolder, delta); + if (player.isDead()) { + player.respawn(mGameWorld, mGameItemsHolder); } - - GP.renderer.setCamPos(GP.player.getX() + GP.player.getWidth() / 2 - GP.renderer.getWidth() / 2, - GP.player.getY() + GP.player.getHeight() / 2 - GP.renderer.getHeight() / 2); } }