Confusione di rilevamento collisione rettangolo Java

Ho fatto un semplice gioco di cambiamento di stato in 2D usando i tutorial Java di Bucky, ho modificato questo gioco e ora voglio impostare collisioni sulla mappa in modo che il mio giocatore non possa attraversare la casa sulla mappa. Penso di avere un’idea di come funzionano le collisioni:

fai 2 rettangoli usando il seguente codice:

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

}

1 per il giocatore e 1 per l’ostacolo, come inserirò questo nel mio codice e come direi a java che il rettangolo per l’ostacolo è diverso dal rettangolo del giocatore?

Quindi, dopo aver creato i 2 rettangoli, avrei impostato un’istruzione if che dicesse qualcosa come se gli intersechi facessero questo …

    Speriamo che dopo questo penso che avrebbe funzionato. Qualche informazione in più sul gioco, essendo un gioco di cambio di stato ha alcuni metodi, metodi come init, render e update (dove metto i miei rettangoli e le istruzioni if, nel metodo di aggiornamento?) Anche, è un gioco di visualizzazione dall’alto un po ‘come pokemon se questo aiuta. Se hai bisogno del mio codice per favore chiedi, non volevo metterlo ora per sovraffollare questo post.

    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; } } 

    Questa è la mia class di gioco, l’unica altra 2 class che ho sono il principale e il menu, non posso immaginare i metodi rettangolari che vengono fatti nella class principale o del menu, quindi l’unico rimasto è il gioco, ma non capisco come fare 2 diversi rettangoli (uno per il giocatore l’altro per la casa) nel codice che ho fatto finora. Se hai bisogno della mia class principale e del mio menu, per favore dimmelo.

    Modifica 3:

    Ho provato quello che hai detto e ho creato una class Rectanglebase e ho messo il messaggio che hai postato lì dentro, ma sto avendo degli errori, mi sta chiedendo di fare un metodo per getX e getY nella mia class di giocatori anche il pubblico in costruttore ha anche un errore:

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

    Ho anche fatto una lezione di Home and Player come avevi detto, ma sono un po ‘confuso su quello che devo mettere dentro, ho messo sotto la class Home:

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

    ma sto ricevendo errori, non sono sicuro se l’ho fatto correttamente o no. Inoltre, nella class del giocatore per le posizioni x, y come posso impostare le mie variabili float dalla mia class di gioco per il mio giocatore?

    Ecco un esempio di Game Loop / Game Logic e rilevamento delle collisioni tramite il metodo Rectangle2D#intersects(..) .

    Usa JPanel per disegnare tutto e Rectangle2D è usato per la class Entity (che è qualsiasi object necessario per essere disegnato su GamePanel che è il nostro JPanel dove tutto è disegnato).

    Il metodo updateGame() è dove troverai il controllo delle collisioni:

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

    Sei il giocatore 1 e vai con W , A , S , D. Quando intersechi il Player 2 , un println() confermerà l’intersezione.

    inserisci la descrizione dell'immagine qui

    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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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}

    finché la tua casa e i rettangoli del tuo giocatore sono definiti in classi diverse, java sarà in grado di dire la differenza

    crea prima una class che sia una class base per trattare i rettangoli:

     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 

    ora scrivi le classi per la casa e il giocatore:

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

    quando generi la casa nel tuo codice principale, puoi crearne di tuoi:

    House house = new House();

    quindi generi la class per il giocatore in un modo simile, quindi costruisci il tuo codice principale:

    Player player = new Player()

    house e player sono variabili diverse, questo è il modo in cui java dirà la differenza tra casa e giocatore