From 05cac5026b557f65323fc0d3f362f31c44fccffd Mon Sep 17 00:00:00 2001 From: adi Date: Mon, 6 Apr 2026 01:09:43 +0300 Subject: [PATCH 1/2] fixed placing and removing object when editing --- src/com/monkey/gui/editor/MapEditorLogic.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/com/monkey/gui/editor/MapEditorLogic.java b/src/com/monkey/gui/editor/MapEditorLogic.java index 4b3f098..9d8354b 100644 --- a/src/com/monkey/gui/editor/MapEditorLogic.java +++ b/src/com/monkey/gui/editor/MapEditorLogic.java @@ -60,13 +60,39 @@ public void mousePressed(MouseEvent e) { } public void addObject(String type, int x, int y) { - // Your logic for adding a Banana, Stone, or Turtle to the lists - System.out.println("Added " + type + " at " + x + ", " + y); + switch (type) { + case "Banana": + engine.bananas.add(new com.monkey.core.Banana(x, y)); + break; + case "Stone": + engine.stones.add(new com.monkey.core.Stone(x, y)); + break; + case "River": + engine.rivers.add(new com.monkey.core.River(x, y)); + break; + case "Turtle": + // Automatically assign the next available ID to the turtle (T0, T1, T2...) + int newId = 0; + for (Turtle t : engine.turtles) { + if (t.id >= newId) newId = t.id + 1; + } + engine.turtles.add(new Turtle(x, y, newId, 0, 0)); + break; + case "Spawn": + engine.monkeyX = x; + engine.monkeyY = y; + // Update the starting location so the monkey resets here! + engine.saveInitialState(); + break; + } } public void removeObject(int x, int y) { - // Your logic for looping through lists and removing objects at X, Y - System.out.println("Removed object at " + x + ", " + y); + // Remove anything within 20 pixels of the right-click + engine.bananas.removeIf(b -> Math.hypot(b.x - x, b.y - y) < 20); + engine.stones.removeIf(s -> Math.hypot(s.x - x, s.y - y) < 20); + engine.rivers.removeIf(r -> Math.hypot(r.x - x, r.y - y) < 20); + engine.turtles.removeIf(t -> Math.hypot(t.x - x, t.y - y) < 20); } public Object getGameObjectAt(int x, int y) { From 28942cd752e5fcb37fcb4eec617ff211b0e20971 Mon Sep 17 00:00:00 2001 From: adi Date: Mon, 6 Apr 2026 01:32:29 +0300 Subject: [PATCH 2/2] upgrade the use of ITerrain.java --- .../monkey/animation/AnimationManager.java | 4 +- src/com/monkey/animation/TurtleAnimation.java | 9 +- src/com/monkey/core/ITerrain.java | 7 +- src/com/monkey/core/River.java | 6 ++ src/com/monkey/core/Stone.java | 7 +- src/com/monkey/design/TerrainDesign.java | 22 ++--- src/com/monkey/engine/CollisionChecker.java | 95 +++++++++++++------ src/com/monkey/gui/game/GameRenderer.java | 4 +- 8 files changed, 99 insertions(+), 55 deletions(-) diff --git a/src/com/monkey/animation/AnimationManager.java b/src/com/monkey/animation/AnimationManager.java index 5c9abb8..891a9a0 100644 --- a/src/com/monkey/animation/AnimationManager.java +++ b/src/com/monkey/animation/AnimationManager.java @@ -43,11 +43,11 @@ public static void smoothStep(GameEnginePanel engine, double totalDist, int fram double nextX = engine.monkeyX + dx; double nextY = engine.monkeyY + dy; - if (CollisionChecker.isStoneCollision(engine, nextX, nextY)) { + if (CollisionChecker.isSolidCollision(engine, nextX, nextY)) { break; } - if (CollisionChecker.isWaterCollision(engine, nextX, nextY)) { + if (CollisionChecker.isDeadlyCollision(engine, nextX, nextY)) { throw new RuntimeException("Monkey fell in the water!"); } diff --git a/src/com/monkey/animation/TurtleAnimation.java b/src/com/monkey/animation/TurtleAnimation.java index d800702..5e16012 100644 --- a/src/com/monkey/animation/TurtleAnimation.java +++ b/src/com/monkey/animation/TurtleAnimation.java @@ -28,25 +28,22 @@ public void actionPerformed(java.awt.event.ActionEvent e) { double nextX = turtle.x + dx; double nextY = turtle.y + dy; - // 1. Turtle going on land fails the level if (CollisionChecker.isTurtleLandCollision(engine, nextX, nextY)) { throw new RuntimeException("Turtle walked onto land!"); } - // 2. Check Monkey Collisions if (monkeyOnBoard) { double nextMonkeyX = engine.monkeyX + dx; double nextMonkeyY = engine.monkeyY + dy; - // --- CHANGED: Monkey hits stone while riding? Stop moving gently. --- - if (CollisionChecker.isStoneCollision(engine, nextMonkeyX, nextMonkeyY)) { + if (CollisionChecker.isSolidCollision(engine, nextMonkeyX, nextMonkeyY)) { ((Timer) e.getSource()).stop(); latch.countDown(); return; } // Monkey falls in water (shouldn't happen on a turtle, but just in case) - if (CollisionChecker.isWaterCollision(engine, nextMonkeyX, nextMonkeyY)) { + if (CollisionChecker.isDeadlyCollision(engine, nextMonkeyX, nextMonkeyY)) { throw new RuntimeException("Monkey fell in the water!"); } @@ -54,7 +51,6 @@ public void actionPerformed(java.awt.event.ActionEvent e) { engine.monkeyY = nextMonkeyY; } - // Safely apply move turtle.x = nextX; turtle.y = nextY; @@ -67,7 +63,6 @@ public void actionPerformed(java.awt.event.ActionEvent e) { latch.countDown(); } } catch (RuntimeException ex) { - // Deadly obstacle hit (water/land)! Stop the animation and signal failure. hitDeadlyObstacle[0] = true; ((Timer) e.getSource()).stop(); latch.countDown(); diff --git a/src/com/monkey/core/ITerrain.java b/src/com/monkey/core/ITerrain.java index 2c4ef96..dfbf806 100644 --- a/src/com/monkey/core/ITerrain.java +++ b/src/com/monkey/core/ITerrain.java @@ -1,9 +1,14 @@ package com.monkey.core; +import java.awt.Color; + public interface ITerrain extends IGameObject { boolean isSolid(); // True for Stones (monkey can't walk through) boolean isDeadly(); // True for Rivers (monkey drowns) -} + Color getColor(); // The color used to draw the terrain + + int getSize(); // The radius/thickness of the terrain +} \ No newline at end of file diff --git a/src/com/monkey/core/River.java b/src/com/monkey/core/River.java index 19fe69b..76a55c5 100644 --- a/src/com/monkey/core/River.java +++ b/src/com/monkey/core/River.java @@ -1,5 +1,7 @@ package com.monkey.core; +import java.awt.Color; + public class River extends GameObject implements ITerrain { public River(double x, double y) { super(x, y); } @@ -9,4 +11,8 @@ public class River extends GameObject implements ITerrain { @Override public boolean isSolid() { return false; } @Override public boolean isDeadly() { return true; } + + @Override public Color getColor() { return new Color(52, 152, 219); } + + @Override public int getSize() { return 50; } } diff --git a/src/com/monkey/core/Stone.java b/src/com/monkey/core/Stone.java index e1d20c8..5cc3457 100644 --- a/src/com/monkey/core/Stone.java +++ b/src/com/monkey/core/Stone.java @@ -1,6 +1,7 @@ package com.monkey.core; -import java.awt.*; +import java.awt.Color; +import java.awt.Rectangle; public class Stone extends GameObject implements ITerrain { @@ -14,4 +15,8 @@ public Stone(double x, double y) { @Override public boolean isSolid() { return true; } @Override public boolean isDeadly() { return false; } + + @Override public Color getColor() { return new Color(100, 100, 100); } + + @Override public int getSize() { return 45; } } diff --git a/src/com/monkey/design/TerrainDesign.java b/src/com/monkey/design/TerrainDesign.java index e9a6d62..47e2438 100644 --- a/src/com/monkey/design/TerrainDesign.java +++ b/src/com/monkey/design/TerrainDesign.java @@ -1,32 +1,27 @@ package com.monkey.design; import com.monkey.core.GameObject; +import com.monkey.core.ITerrain; import java.awt.BasicStroke; -import java.awt.Color; import java.awt.Graphics2D; import java.util.List; public class TerrainDesign { - public static void drawRivers(Graphics2D g2, List rivers) { - drawConnected(g2, rivers, new Color(52, 152, 219), 50); - } - - public static void drawStones(Graphics2D g2, List stones) { - drawConnected(g2, stones, new Color(100, 100, 100), 45); - } + public static void drawTerrain(Graphics2D g2, List objects) { + if (objects.isEmpty()) return; - // Generic logic to connect adjacent objects - private static void drawConnected(Graphics2D g2, List objects, Color c, int size) { - g2.setColor(c); + ITerrain terrainType = (ITerrain) objects.get(0); + int size = terrainType.getSize(); int r = size / 2; - // 1. Draw the "Body" of each object + g2.setColor(terrainType.getColor()); + for(GameObject o : objects) { g2.fillOval((int)o.x - r, (int)o.y - r, size, size); } - // 2. Draw "Connections" between close neighbors + // 2. Draw "Connections" g2.setStroke(new BasicStroke(size, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); for(int i = 0; i < objects.size(); i++) { @@ -35,7 +30,6 @@ private static void drawConnected(Graphics2D g2, List objects, Color GameObject b = objects.get(j); double dist = Math.hypot(a.x - b.x, a.y - b.y); - // If they are close (adjacent grid cells + wiggle room) if(dist < size + 20) { g2.drawLine((int)a.x, (int)a.y, (int)b.x, (int)b.y); } diff --git a/src/com/monkey/engine/CollisionChecker.java b/src/com/monkey/engine/CollisionChecker.java index 8e3d472..e3e050a 100644 --- a/src/com/monkey/engine/CollisionChecker.java +++ b/src/com/monkey/engine/CollisionChecker.java @@ -1,58 +1,97 @@ package com.monkey.engine; import com.monkey.core.GameObject; +import com.monkey.core.ITerrain; import com.monkey.core.Turtle; import com.monkey.gui.game.GameEnginePanel; +import java.util.ArrayList; +import java.util.List; + public class CollisionChecker { - // Hitbox sizes for the 50x50 tiles - private static final double OBSTACLE_RADIUS = 50.0; - private static final double RIVER_RADIUS = 50.0; - private static final double TURTLE_RADIUS = 50.0; + private static List getAllObjects(GameEnginePanel engine) { + List allObjects = new ArrayList<>(); + allObjects.addAll(engine.stones); + allObjects.addAll(engine.rivers); + allObjects.addAll(engine.bananas); + allObjects.addAll(engine.turtles); + + return allObjects; + } + + public static boolean isSolidCollision(GameEnginePanel engine, double targetX, double targetY) { + + for (GameObject obj : getAllObjects(engine)) { + if (obj instanceof ITerrain && ((ITerrain) obj).isSolid()) { - // Returns TRUE if the target position hits a stone - public static boolean isStoneCollision(GameEnginePanel engine, double targetX, double targetY) { - for (GameObject stone : engine.stones) { - if (Math.hypot(stone.x - targetX, stone.y - targetY) < OBSTACLE_RADIUS) { - return true; + if (obj.hitbox != null) { + if (obj.hitbox.contains(targetX, targetY)) { + return true; + } + } + else { + double radius = ((ITerrain) obj).getSize() / 2.0; + if (Math.hypot(obj.x - targetX, obj.y - targetY) < radius) { + return true; + } + } } } + return false; } - // Returns TRUE if the monkey is drowning (in water without a turtle) - public static boolean isWaterCollision(GameEnginePanel engine, double targetX, double targetY) { - boolean overWater = false; - for (GameObject river : engine.rivers) { - if (Math.hypot(river.x - targetX, river.y - targetY) < RIVER_RADIUS) { - overWater = true; - break; + public static boolean isDeadlyCollision(GameEnginePanel engine, double targetX, double targetY) { + boolean overDeadlyGround = false; + + for (GameObject obj : getAllObjects(engine)) { + if (obj instanceof ITerrain && ((ITerrain) obj).isDeadly()) { + + if (obj.hitbox != null) { + if (obj.hitbox.contains(targetX, targetY)) overDeadlyGround = true; + } else { + double radius = ((ITerrain) obj).getSize() / 2.0; + if (Math.hypot(obj.x - targetX, obj.y - targetY) < radius) overDeadlyGround = true; + } } + + if (overDeadlyGround) break; } - if (overWater) { - boolean onTurtle = false; + if (overDeadlyGround) { for (Turtle turtle : engine.turtles) { - if (Math.hypot(turtle.x - targetX, turtle.y - targetY) < TURTLE_RADIUS) { - onTurtle = true; - break; + if (Math.hypot(turtle.x - targetX, turtle.y - targetY) < 40) { + return false; } } - return !onTurtle; // If over water but NOT on a turtle, it's a collision! + return true; } + return false; } - // Returns TRUE if the turtle walks onto land public static boolean isTurtleLandCollision(GameEnginePanel engine, double targetX, double targetY) { boolean onWater = false; - for (GameObject river : engine.rivers) { - if (Math.hypot(river.x - targetX, river.y - targetY) < RIVER_RADIUS) { - onWater = true; - break; + + for (GameObject obj : getAllObjects(engine)) { + if (obj instanceof ITerrain && ((ITerrain) obj).isDeadly()) { + + if (obj.hitbox != null) { + if (obj.hitbox.contains(targetX, targetY)) { + onWater = true; + break; + } + } else { + double radius = ((ITerrain) obj).getSize() / 2.0; + if (Math.hypot(obj.x - targetX, obj.y - targetY) < radius) { + onWater = true; + break; + } + } } } - return !onWater; // If NOT on water, it's a collision! + + return !onWater; } } diff --git a/src/com/monkey/gui/game/GameRenderer.java b/src/com/monkey/gui/game/GameRenderer.java index 1a873c4..7c5cdeb 100644 --- a/src/com/monkey/gui/game/GameRenderer.java +++ b/src/com/monkey/gui/game/GameRenderer.java @@ -51,8 +51,8 @@ private void updateEffects() { public void draw(Graphics2D g2) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - TerrainDesign.drawRivers(g2, engine.rivers); - TerrainDesign.drawStones(g2, engine.stones); + TerrainDesign.drawTerrain(g2, engine.rivers); + TerrainDesign.drawTerrain(g2, engine.stones); for (Turtle t : engine.turtles) t.draw(g2); for (GameObject b : engine.bananas) ItemDesign.drawBanana(g2, b.x, b.y);