Java矩形碰撞检测混淆

我使用Bucky的光滑Java教程做了一个简单的2D状态改变游戏,我修改了这个游戏,现在想在地图上设置碰撞,这样我的玩家就无法通过地图上的房子。 我想我对碰撞的工作方式有所了解:

使用以下代码制作2个矩形:

public Rectangle getBounds() { return new Rectangle(x, y, width, height); 

}

1为播放器,1为障碍物,我如何将其放入我的代码中?如何告诉java障碍物的矩形与播放器矩形不同?

然后在制作了2个矩形后,我会设置一个if语句,说如果相交就行了……

希望在此之后,我认为它会起作用。 关于游戏的一些更多信息,它是一个状态改变游戏,它有一些方法,如init,渲染和更新的方法(我在哪里放置我的矩形和if语句,在更新方法中?),它还是一个顶上视图游戏有点像口袋妖怪,如果这有帮助。 如果您需要我的代码,请询问,我现在不想让它过度拥挤这篇文章。

EDIT1:

 package javagame; import org.newdawn.slick.*; import org.newdawn.slick.state.*; public class Play extends BasicGameState{ Animation bucky, movingUp, movingDown, movingLeft, movingRight, movingBL, movingBR, movingFL, movingFR; Image worldMap; boolean quit = false;//gives user to quit the game int[] duration = {200, 200};//how long frame stays up for float buckyPositionX = 0; float buckyPositionY = 0; float shiftX = buckyPositionX + 320;//keeps user in the middle of the screem float shiftY = buckyPositionY + 160;//the numbers are half of the screen size public Play(int state){ } public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{ worldMap = new Image("res/world.png"); Image[] walkUp = {new Image("res/b.png"), new Image("res/b.png")}; //these are the images to be used in the "walkUp" animation Image[] walkDown = {new Image("res/f.png"), new Image("res/f.png")}; Image[] walkLeft = {new Image("res/l.png"), new Image("res/l.png")}; Image[] walkRight = {new Image("res/r.png"), new Image("res/r.png")}; Image[] walkBL = {new Image("res/bl.png"), new Image("res/bl.png")}; Image[] walkBR = {new Image("res/br.png"), new Image("res/br.png")}; Image[] walkFL = {new Image("res/fl.png"), new Image("res/fl.png")}; Image[] walkFR = {new Image("res/fr.png"), new Image("res/fr.png")}; movingUp = new Animation(walkUp, duration, false); movingDown = new Animation(walkDown, duration, false); movingLeft = new Animation(walkLeft, duration, false); movingRight = new Animation(walkRight, duration, false); movingBL = new Animation(walkBL, duration, false); movingBR = new Animation(walkBR, duration, false); movingFL = new Animation(walkFL, duration, false); movingFR = new Animation(walkFR, duration, false); bucky = movingDown;//facing screen initially on startup } public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{ worldMap.draw(buckyPositionX, buckyPositionY);//position 0,0 bucky.draw(shiftX, shiftY);//makes him appear at center of map g.drawString("Suraj's X: "+buckyPositionX+"\nSuraj's Y: "+buckyPositionY,400,20);//tells us the position if(quit==true){ g.drawString("Resume(R)", 250, 100); g.drawString("Main(M)", 250, 150); g.drawString("Quit Game(Q)", 250, 200); if(quit==false){ g.clear();//wipe off everything from screen } } } public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException{ Input input = gc.getInput(); //up if(input.isKeyDown(Input.KEY_UP)){ bucky = movingUp;//changes the image to his back buckyPositionY += 10;;//increase the Y coordinates of bucky (move him up) if(buckyPositionY>162){//if I reach the top buckyPositionY -= 10;//stops any further movement in that direction } } //down if(input.isKeyDown(Input.KEY_DOWN)){ bucky = movingDown; buckyPositionY -= 10; if(buckyPositionY324){ buckyPositionX -= 10;//delta * .1f }} //right if(input.isKeyDown(Input.KEY_RIGHT)){ bucky = movingRight; buckyPositionX -= 10; if(buckyPositionX<-840){ buckyPositionX += 10; }} //2 key combos start here if(input.isKeyDown(Input.KEY_RIGHT) && input.isKeyDown(Input.KEY_UP)){ bucky = movingBR; buckyPositionX -= delta * .1f; if(buckyPositionX162){ buckyPositionY -= delta * .1f; }}} if(input.isKeyDown(Input.KEY_LEFT) && input.isKeyDown(Input.KEY_UP)){ bucky = movingBL; buckyPositionX -= delta * .1f; if(buckyPositionX>324){ buckyPositionX -= delta * .1f; if(buckyPositionY>162){ buckyPositionY -= delta * .1f; }}} if(input.isKeyDown(Input.KEY_RIGHT) && input.isKeyDown(Input.KEY_DOWN)){ bucky = movingFR; buckyPositionX -= delta * .1f; if(buckyPositionY<-600){ buckyPositionY += delta * .1f; if(buckyPositionX<-840){ buckyPositionX += delta * .1f; }}} if(input.isKeyDown(Input.KEY_LEFT) && input.isKeyDown(Input.KEY_DOWN)){ bucky = movingFL; buckyPositionX -= delta * .1f; if(buckyPositionY324){ buckyPositionX -= delta * .1f; }}} //escape if(input.isKeyDown(Input.KEY_ESCAPE)){ quit=true; } //when the menu is up if(quit==true){//is the menu on the screen if(input.isKeyDown(Input.KEY_R)){ quit = false;//resumes the game, makes menu dissapear } if(input.isKeyDown(Input.KEY_M)){ sbg.enterState(0);//takes you to the main menu } if(input.isKeyDown(Input.KEY_Q)){ System.exit(0);//quits the game } } } public int getID(){ return 1; } } 

这是我的Play类,我唯一​​的另外两个类是main和菜单,我无法想象在main或menu类中制作的矩形方法所以剩下的唯一一个是Play,但我不明白如何制作到目前为止我已经完成的代码中有2个不同的矩形(一个用于播放器,另一个用于房子)。 如果您需要我的主菜单和菜单类,请告诉我。

编辑3:

我已经尝试了你所说的并制作了一个Rectanglebase类并把你发布的if sattement放在那里但是我遇到了错误,它要求我在我的播放器类中为getX和getY制作一个方法也是公共的构造函数也有错误:

 public Rectanglebase{}//the public is saying syntax error 

我也像你说过的那样建立了一个家庭和玩家类,但我对我需要放入的内容感到有点困惑,我把它归入Home类:

 return Rectangle(100,100,100,100); 

但我得到错误,我不确定我是否正确。 另外,在x的玩家类中,y定位我如何为我的玩家设置我的Play类的浮点变量?

以下是通过Rectangle2D#intersects(..)方法进行游戏循环 / 游戏逻辑碰撞检测的示例。

它使用JPanel绘制所有内容, Rectangle2D用于Entity类(这是需要绘制到GamePanel任何对象, GamePanel是我们的JPanel,其中绘制了所有内容)。

您可以在updateGame()方法中找到冲突检查:

  private void updateGame() { if (entities.get(0).intersects(entities.get(1))) { System.out.println("Intersecting"); } .... } 

你是玩家1并随着WASD移动 。 当您与Player 2相交时, println()将确认交叉点。

在此处输入图像描述

GameLogic.java:

 import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.AbstractAction; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; /** * * @author David Kroukamp */ public class GameLogic { public GameLogic() { initComponents(); } final GamePanel gp = new GamePanel(500, 500); private void initComponents() { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Entity entity1 = new Entity(100, 100, 100, 100, createWhiteImage()); Entity entity2 = new Entity(300, 200, 100, 100, createBlackImage()); gp.addEntity(entity1); gp.addEntity(entity2);//just a standing still JPanel setGamePanelKeyBindings(gp, entity1); frame.add(gp); frame.pack(); frame.setVisible(true); //start the game loop which will repaint the screen runGameLoop(); } //Starts a new thread and runs the game loop in it. public void runGameLoop() { Thread loop = new Thread(new Runnable() { @Override public void run() { gp.running.set(true); gp.gameLoop(); } }); loop.start(); } private void setGamePanelKeyBindings(GamePanel gp, final Entity entity) { gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "D pressed"); gp.getActionMap().put("D pressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.RIGHT = true; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "A pressed"); gp.getActionMap().put("A pressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.LEFT = true; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("W"), "W pressed"); gp.getActionMap().put("W pressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.UP = true; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "S pressed"); gp.getActionMap().put("S pressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.DOWN = true; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released D"), "D released"); gp.getActionMap().put("D released", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.RIGHT = false; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released A"), "A released"); gp.getActionMap().put("A released", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.LEFT = false; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released W"), "W released"); gp.getActionMap().put("W released", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.UP = false; } }); gp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released S"), "S released"); gp.getActionMap().put("S released", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { entity.DOWN = false; } }); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new GameLogic(); } }); } private BufferedImage createWhiteImage() { BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setColor(Color.WHITE); g2.fillRect(0, 0, img.getWidth(), img.getHeight()); return img; } private BufferedImage createBlackImage() { BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setColor(Color.BLACK); g2.fillRect(0, 0, img.getWidth(), img.getHeight()); return img; } } class Entity extends Rectangle2D.Double { private int speed = 5; public boolean UP = false, DOWN = false, LEFT = false, RIGHT = false; private final BufferedImage image; public Entity(int x, int y, int width, int height, BufferedImage image) { super(x, y, width, height); this.width = width; this.height = height; this.image = image; } public BufferedImage getImage() { return image; } public void move() { if (UP) { y -= speed; } if (DOWN) { y += speed; } if (LEFT) { x -= speed; } if (RIGHT) { x += speed; } } } class GamePanel extends JPanel { private int width, height; private int frameCount = 0; private int fps = 0; public static AtomicBoolean running = new AtomicBoolean(false), paused = new AtomicBoolean(false); final ArrayList entities = new ArrayList<>(); GamePanel(int w, int h) { super(true); setIgnoreRepaint(true);//mustnt repaint itself the gameloop will do that setLayout(null); width = w; height = h; } @Override public Dimension getPreferredSize() { return new Dimension(width, height); } public void addEntity(Entity e) { entities.add(e); } //Only run this in another Thread! public void gameLoop() { //This value would probably be stored elsewhere. final double GAME_HERTZ = 30.0; //Calculate how many ns each frame should take for our target game hertz. final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ; //At the very most we will update the game this many times before a new render. //If you're worried about visual hitches more than perfect timing, set this to 1. final int MAX_UPDATES_BEFORE_RENDER = 5; //We will need the last update time. double lastUpdateTime = System.nanoTime(); //Store the last time we rendered. double lastRenderTime = System.nanoTime(); //If we are able to get as high as this FPS, don't render again. final double TARGET_FPS = 60; final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS; //Simple way of finding FPS. int lastSecondTime = (int) (lastUpdateTime / 1000000000); while (running.get()) { double now = System.nanoTime(); int updateCount = 0; if (!paused.get()) { //Do as many game updates as we need to, potentially playing catchup. while (now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER) { updateGame(); lastUpdateTime += TIME_BETWEEN_UPDATES; updateCount++; } //If for some reason an update takes forever, we don't want to do an insane number of catchups. //If you were doing some sort of game that needed to keep EXACT time, you would get rid of this. if (now - lastUpdateTime > TIME_BETWEEN_UPDATES) { lastUpdateTime = now - TIME_BETWEEN_UPDATES; } drawGame(); lastRenderTime = now; //Update the frames we got. int thisSecond = (int) (lastUpdateTime / 1000000000); if (thisSecond > lastSecondTime) { System.out.println("NEW SECOND " + thisSecond + " " + frameCount); fps = frameCount; frameCount = 0; lastSecondTime = thisSecond; } //Yield until it has been at least the target time between renders. This saves the CPU from hogging. while (now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES) { //allow the threading system to play threads that are waiting to run. Thread.yield(); //This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it. //You can remove this line and it will still work (better), your CPU just climbs on certain OSes. //FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this. //On my OS it does not unpuase the game if i take this away try { Thread.sleep(1); } catch (Exception e) { } now = System.nanoTime(); } } } } private void drawGame() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { repaint(); } }); } private void updateGame() { if (entities.get(0).intersects(entities.get(1))) { System.out.println("Intersecting"); } for (Entity e : entities) { e.move(); } } @Override protected void paintComponent(Graphics grphcs) { super.paintComponent(grphcs); Graphics2D g2d = (Graphics2D) grphcs; applyRenderHints(g2d); g2d.setColor(Color.GREEN); g2d.fillRect(0, 0, getWidth(), getHeight()); for (Entity e : entities) { g2d.drawImage(e.getImage(), (int) e.getX(), (int) e.getY(), null); } g2d.setColor(Color.BLACK); g2d.drawString("FPS: " + fps, 5, 10); frameCount++; } private final static RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); private final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); private final static RenderingHints colorRenderHints = new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); private final static RenderingHints interpolationRenderHints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); private final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); public static void applyRenderHints(Graphics2D g2d) { g2d.setRenderingHints(textRenderHints); g2d.setRenderingHints(imageRenderHints); g2d.setRenderingHints(colorRenderHints); g2d.setRenderingHints(interpolationRenderHints); g2d.setRenderingHints(renderHints); } } 

if(house.getBounds().contains(player.getX(),player.getY()){//do something}

只要你的房子和你的玩家矩形在不同的类中定义,java就能分辨出来

首先创建一个类,它是处理矩形的基类:

 public class Rectanglebase{ public void getBounds(){//write method} //write other methods you will need to use for both rectangles here public Rectanglebase{//default constructor} }//end class definition 

现在为房子和玩家写课:

 public class House extends Rectanglebase{ //getBounds() is inherited, so just write stuff to do with the graphics of the house here } 

当你在主代码中生成房子时,你可以自己创建:

House house = new House();

然后以类似的方式为玩家生成类,然后在主代码中构造:

Player player = new Player()

houseplayer是不同的变量,这就是java将如何区分你的房子和玩家