From 3fdc2291218f6d3903ce923563d1e12051690c37 Mon Sep 17 00:00:00 2001 From: fredboy Date: Wed, 17 Apr 2024 19:12:51 +0700 Subject: [PATCH] Refactor drop and its physics --- .../cavedroid/game/GamePhysics.java | 80 ++++++++--- .../cavedroid/game/GameRenderer.java | 57 +++++++- .../cavedroid/game/mobs/Player.java | 11 ++ .../cavedroid/game/objects/Drop.java | 127 ------------------ .../cavedroid/game/objects/Drop.kt | 38 ++++++ 5 files changed, 163 insertions(+), 150 deletions(-) delete mode 100644 core/src/ru/deadsoftware/cavedroid/game/objects/Drop.java create mode 100644 core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt diff --git a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java index e3ceb53..cd900d8 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java @@ -12,6 +12,7 @@ import ru.deadsoftware.cavedroid.game.objects.Drop; import ru.deadsoftware.cavedroid.game.objects.DropController; import ru.deadsoftware.cavedroid.game.world.GameWorld; +import javax.annotation.CheckForNull; import javax.inject.Inject; import java.util.Iterator; @@ -94,32 +95,72 @@ public class GamePhysics { (int) (rect.y + rect.height / 8 * 7) / 16); } + 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 (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.pickUpDrop(drop); + } + } + private void dropPhy(Drop drop, float delta) { - int dropToPlayer = drop.closeToPlayer(mGameWorld, mMobsController.getPlayer()); + final Rectangle playerMagnetTarget = getShiftedMagnetingPlayerRect(drop); + final Vector2 dropVelocity = drop.getVelocity(); + - if (dropToPlayer > 0) { - drop.moveToPlayer(mGameWorld, mMobsController.getPlayer(), dropToPlayer, delta); + 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.getVelocity().x >= 300f) { - drop.getVelocity().x = 300f; - } else if (drop.getVelocity().x <= -300f) { - drop.getVelocity().x = -300f; - } else { - drop.getVelocity().x = 0; - } - if (drop.getVelocity().y < PL_TERMINAL_VELOCITY) { - drop.getVelocity().y += gravity.y * delta; - } + dropVelocity.y += gravity.y * delta; } - drop.move(delta); + 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.getVelocity().set(0, -1); + dropVelocity.setZero(); do { - drop.move(1); + drop.y--; } while (checkColl(drop)); - drop.getVelocity().setZero(); + } + + if (playerMagnetTarget != null) { + pickUpDropIfPossible(playerMagnetTarget, drop); } } @@ -276,10 +317,7 @@ public class GamePhysics { for (Iterator it = mDropController.getIterator(); it.hasNext(); ) { Drop drop = it.next(); dropPhy(drop, delta); - if (Intersector.overlaps(drop, player)) { - drop.pickUpDrop(player); - } - if (drop.isPickedUp()) { + if (drop.getPickedUp()) { it.remove(); } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java b/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java index 66058c4..c18ee53 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java @@ -3,8 +3,10 @@ package ru.deadsoftware.cavedroid.game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack; @@ -15,15 +17,17 @@ import ru.deadsoftware.cavedroid.game.mobs.Player; import ru.deadsoftware.cavedroid.game.objects.Block; import ru.deadsoftware.cavedroid.game.objects.Drop; import ru.deadsoftware.cavedroid.game.objects.DropController; +import ru.deadsoftware.cavedroid.game.objects.Item; import ru.deadsoftware.cavedroid.game.world.GameWorld; import ru.deadsoftware.cavedroid.misc.ControlMode; import ru.deadsoftware.cavedroid.misc.Renderer; +import ru.deadsoftware.cavedroid.misc.utils.SpriteUtilsKt; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import javax.inject.Inject; -import static ru.deadsoftware.cavedroid.misc.Assets.guiMap; -import static ru.deadsoftware.cavedroid.misc.Assets.textureRegions; +import static ru.deadsoftware.cavedroid.misc.Assets.*; @GameScope public class GameRenderer extends Renderer { @@ -122,6 +126,32 @@ public class GameRenderer extends Renderer { } } + private Rectangle getShiftedRectRespectfulToViewPort(final Rectangle rect, final float shift) { + return new Rectangle(rect.x + shift - getCamX(), rect.y - getCamY(), rect.width, rect.height); + } + + @CheckForNull + private Rectangle getDrawingRectIfInsideViewport(final Rectangle rectangle) { + final Rectangle viewportRect = new Rectangle(0, 0, getWidth(), getHeight()); + + final Rectangle notShifted = getShiftedRectRespectfulToViewPort(rectangle, 0); + if (Intersector.overlaps(viewportRect, notShifted)) { + return notShifted; + } + + final Rectangle shiftedLeft = getShiftedRectRespectfulToViewPort(rectangle, -mGameWorld.getWidthPx()); + if (Intersector.overlaps(viewportRect, shiftedLeft)) { + return shiftedLeft; + } + + final Rectangle shiftedRight = getShiftedRectRespectfulToViewPort(rectangle, mGameWorld.getWidthPx()); + if (Intersector.overlaps(viewportRect, shiftedRight)) { + return shiftedRight; + } + + return null; + } + private void drawMob(Mob mob, float delta) { float mobDrawX = mob.getX() - getCamX(); float mobDrawY = mob.getY() - getCamY(); @@ -138,6 +168,29 @@ public class GameRenderer extends Renderer { } private void drawDrop(Drop drop) { + if (drop.getId() <= 0) { + return; + } + + @CheckForNull final Rectangle drawingRect = getDrawingRectIfInsideViewport(drop); + + if (drawingRect == null) { + return; + } + + final Item item = GameItems.getItem(drop.getId()); + @CheckForNull final Block block = GameItems.getBlock(GameItems.getItemKey(drop.getId())); + @CheckForNull final Sprite sprite = item.isBlock() + ? block.getTexture() + : item.getSprite(); + + if (sprite == null) { + return; + } + + sprite.setPosition(drawingRect.x, drawingRect.y); + sprite.setSize(drawingRect.width, drawingRect.height); + sprite.draw(spriter); } @SuppressWarnings("IntegerDivisionInFloatingPointContext") diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java index 10a1885..1f42039 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import ru.deadsoftware.cavedroid.game.objects.Drop; import ru.deadsoftware.cavedroid.game.world.GameWorld; import ru.deadsoftware.cavedroid.misc.Assets; import ru.deadsoftware.cavedroid.misc.utils.SpriteUtilsKt; @@ -30,6 +31,16 @@ public class Player extends Mob { mVelocity.setZero(); } + public void pickUpDrop(Drop drop) { + for (int i = 0; i < inventory.length; i++) { + if (inventory[i] == 0 || inventory[i] == drop.getId()) { + inventory[i] = drop.getId(); + drop.setPickedUp(true); + break; + } + } + } + private Vector2 getSpawnPoint(GameWorld gameWorld) { int y; for (y = 0; y < gameWorld.getHeight(); y++) { diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.java b/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.java deleted file mode 100644 index 9e4e570..0000000 --- a/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.java +++ /dev/null @@ -1,127 +0,0 @@ -package ru.deadsoftware.cavedroid.game.objects; - -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.game.world.GameWorld; -import ru.deadsoftware.cavedroid.game.mobs.Player; - -import java.io.Serializable; - -public class Drop extends Rectangle implements Serializable { - - private final int id; - private final Vector2 velocity; - private boolean pickedUp = false; - - Drop(float x, float y, int id) { - super(x, y, 8, 8); - this.id = id; - this.velocity = new Vector2(0, -1); - } - - public Vector2 getVelocity() { - return velocity; - } - - public int closeToPlayer(GameWorld gameWorld, Player player) { - boolean[] c = new boolean[3]; - - c[0] = Intersector.overlaps(new Rectangle(player.getX() - 16, - player.getY() - 16, player.getWidth() + 32, player.getHeight() + 32), this); - c[1] = Intersector.overlaps(new Rectangle((player.getX() + gameWorld.getWidthPx()) - 16, - player.getY() - 16, player.getWidth() + 32, player.getHeight() + 32), this); - c[2] = Intersector.overlaps(new Rectangle((player.getX() - gameWorld.getWidthPx()) - 16, - player.getY() - 16, player.getWidth() + 32, player.getHeight() + 32), this); - - for (int i = 0; i < 3; i++) { - if (c[i]) { - return i + 1; - } - } - - return 0; - } - - public void moveToPlayer(GameWorld gameWorld, Player player, int ctp, float delta) { - if (ctp > 0) { - float px = player.getX(); - float py = player.getY(); - - switch (ctp) { - case 2: - px += gameWorld.getWidthPx(); - break; - case 3: - px -= gameWorld.getWidthPx(); - break; - } - - float dx = 0, dy = 0; - - if (px + player.getWidth() < x + 4) { - dx = -300f; - } else if (px > x + 4) { - dx = 300f; - } - - if (py + player.getHeight() < y + 4) { - dy = -300f; - } else if (py > y + 4) { - dy = .300f; - } - - velocity.add(dx * delta, dy * delta); - - if (velocity.x > 300f) { - velocity.x = 300f; - } else if (velocity.x < -300f) { - velocity.x = -300f; - } - - if (velocity.y > 300f) { - velocity.y = 300f; - } else if (velocity.y < -300f) { - velocity.y = -300f; - } - } - } - - public void pickUpDrop(Player pl) { - for (int i = 0; i < pl.inventory.length; i++) { - if (pl.inventory[i] == 0 || pl.inventory[i] == id) { - pl.inventory[i] = id; - pickedUp = true; - break; - } - } - } - - private void checkWorldBounds() { -// if (x + 8 > world.getWidthPx()) { -// x -= world.getWidthPx(); -// } else if (x < 0) { -// x += world.getWidthPx(); -// } - } - - public void move(float delta) { - x += velocity.x * delta; - y += velocity.y * delta; - checkWorldBounds(); - y = MathUtils.round(y); - } - - public int getId() { - return id; - } - - public boolean isPickedUp() { - return pickedUp; - } - - public void setPickedUp(boolean pickedUp) { - this.pickedUp = pickedUp; - } -} diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt b/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt new file mode 100644 index 0000000..accd972 --- /dev/null +++ b/core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt @@ -0,0 +1,38 @@ +package ru.deadsoftware.cavedroid.game.objects + +import com.badlogic.gdx.math.Intersector +import com.badlogic.gdx.math.Rectangle +import com.badlogic.gdx.math.Vector2 + +class Drop( + x: Float, + y: Float, + val id: Int, +) : Rectangle(x, y, DROP_SIZE, DROP_SIZE) { + + val velocity = getInitialVelocity() + var pickedUp = false + + fun canMagnetTo(rectangle: Rectangle): Boolean { + val magnetArea = getMagnetArea() + return Intersector.overlaps(magnetArea, rectangle) + } + + private fun getMagnetArea(): Rectangle { + return Rectangle( + /* x = */ x - MAGNET_DISTANCE, + /* y = */ y - MAGNET_DISTANCE, + /* width = */ width + MAGNET_DISTANCE * 2, + /* height = */ height + MAGNET_DISTANCE * 2, + ) + } + + companion object { + private const val MAGNET_DISTANCE = 16f + + const val MAGNET_VELOCITY = 128f + const val DROP_SIZE = 8f + + private fun getInitialVelocity(): Vector2 = Vector2(0f, -1f) + } +} -- 2.29.2