DEADSOFTWARE

Refactor drop and its physics
authorfredboy <fredboy@protonmail.com>
Wed, 17 Apr 2024 12:12:51 +0000 (19:12 +0700)
committerfredboy <fredboy@protonmail.com>
Wed, 17 Apr 2024 12:12:51 +0000 (19:12 +0700)
core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java
core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java
core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java
core/src/ru/deadsoftware/cavedroid/game/objects/Drop.java [deleted file]
core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt [new file with mode: 0644]

index e3ceb531cb3a37c4ac9aec5adf5b6c83152dc838..cd900d873dc1398e6b41ea492be77a87feaca25a 100644 (file)
@@ -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<Drop> 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();
             }
         }
index 66058c4a2c3dfa53e457ba4fd2a83e88c2bb96bd..c18ee5393ce9482fa245a2e246585b268c2cb054 100644 (file)
@@ -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")
index 10a1885681723d5b13c34644dd4535cd55cc26ab..1f42039bfec7bd2969ec002bdacc4c9ee8ae4386 100644 (file)
@@ -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 (file)
index 9e4e570..0000000
+++ /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 (file)
index 0000000..accd972
--- /dev/null
@@ -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)
+    }
+}