如何获取形状最高点以解决游戏角色浮空岛地形穿模问题?
解决角色与不规则地形的碰撞贴合问题
要让角色贴合不规则地形(由Area对象表示)移动且不穿模,核心思路是检测角色范围内的地形最高点,调整角色位置使其底部刚好贴合该最高点,以下是具体实现方案:
关键修改步骤
- 添加重力模拟,让角色自然下落
- 遍历角色宽度范围内的所有X坐标,通过
Area.contains()检测每个X对应的地形最高点 - 根据找到的最高点调整角色Y坐标,确保角色完全在地形上方
修改后的完整代码
import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.Timer; public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(() -> new Main().show()); } int x = 0; int y = 50; int gravity = 1; // 重力参数 Area area = new Area(); JFrame frame = new JFrame(); JPanel panel = new JPanel() { protected void paintComponent(java.awt.Graphics g1) { super.paintComponent(g1); Graphics2D g = (Graphics2D) g1; g.setColor(Color.GREEN); g.fill(area); g.setColor(Color.RED); g.fillOval(x, y, 100, 100); } }; boolean left; boolean right; public Main() { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(500, 300); frame.add(panel); panel.setBackground(Color.BLUE); // GENERATING TERRAIN int offset = 200; boolean reachedPeak = false; for(int i = 0; i < 500; i++) { if(!reachedPeak) { offset--; if(offset < 100) reachedPeak = true; area.add(new Area(new Rectangle(i, offset, 1, 1000))); } if(reachedPeak) { offset++; if(offset > 200) reachedPeak = false; area.add(new Area(new Rectangle(i, offset, 1, 1000))); } } panel.setFocusable(true); panel.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_LEFT) left = true; if(e.getKeyCode() == KeyEvent.VK_RIGHT) right = true; } @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_LEFT) left = false; if(e.getKeyCode() == KeyEvent.VK_RIGHT) right = false; } }); new Timer(5, e -> update()).start(); } private void show() { frame.setVisible(true); } private void update() { // 左右移动逻辑 if(left) x -= 5; if(right) x += 5; // 重力下落 y += gravity; int playerWidth = 100; int playerHeight = 100; int startX = x; int endX = x + playerWidth; int minTerrainY = Integer.MAX_VALUE; // 遍历角色宽度内的所有X坐标,寻找地形最高点 for (int checkX = startX; checkX <= endX; checkX++) { // 从角色当前底部往上检测,找到第一个属于地形的点(即该X的地形最高点) for (int checkY = y + playerHeight; checkY >= 0; checkY--) { if (area.contains(checkX, checkY)) { minTerrainY = Math.min(minTerrainY, checkY); break; // 找到当前X的最高点后停止向上检测 } } } // 调整角色位置,使其底部贴合地形最高点 if (minTerrainY != Integer.MAX_VALUE) { y = minTerrainY - playerHeight; } panel.repaint(); } }
方案说明
- 利用
Area.contains(int x, int y)方法精准检测点是否属于地形,适配任意由图片转换而来的不规则Area地形 - 遍历角色宽度范围内的所有X坐标,确保角色整个底部都贴合地形,避免局部穿模
- 重力模拟让角色自然下落,碰撞检测后自动修正位置,实现贴合地形的移动效果
内容的提问来源于stack exchange,提问作者user17820402
相关产品推荐
相关产品推荐

