简体   繁体   中英

2d Plateform Game Collision

Ok... So im creating my first 2d platform game... unfortunately everything is new but i have gotten everything else to work so far but I cant get collision to work. This is kinda long so i expect not to get an answer, but someone who can help... Thank you in advance.

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;

public class Expordium {
  private JFrame f = new JFrame("Expordium");
  private boolean win;
  private int level;
  private Display display;

  public boolean isR, isU, isL, isD;

  public static void main(String[] args) {
    Expordium game = new Expordium();
    game.play(game);
  }
  Expordium(){
    win=false;
    level=1;
  }
  private void play(Expordium game){
    display = new Display(game);
    f.getContentPane().add(display);
    f.addKeyListener(new MyKeyListener());
    f.setSize(980 , 360);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
  private void advanceLevel() {
    level++;
  }
  public String getLevel() {
    String strLevel;
    strLevel=Integer.toString(level);
    return strLevel;
  }

  public class MyKeyListener extends KeyAdapter{
    public void keyPressed(KeyEvent e) {
      int keyCode = e.getKeyCode();
      switch( keyCode ) {
        case KeyEvent.VK_UP:
          isU=true;
          break;
        case KeyEvent.VK_DOWN:
          isD=true;
          break;
        case KeyEvent.VK_LEFT:
          isL=true;
          break;
        case KeyEvent.VK_RIGHT:
          isR=true;
          break;
        case KeyEvent.VK_SPACE :
          display.shoot();
      } 
    }
    public void keyReleased( KeyEvent e ) {
      int keyCode = e.getKeyCode();
      switch( keyCode ) {
        case KeyEvent.VK_UP:
          isU=false;
          break;
        case KeyEvent.VK_DOWN:
          isD=false;
          break;
        case KeyEvent.VK_LEFT:
          isL=false;
          break;
        case KeyEvent.VK_RIGHT:
          isR=false;
          break;
      } 
    }
  }
}

Display Class

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.html.HTMLDocument.Iterator;

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

public class Display extends JPanel implements Runnable{

  private static final int FPS = 1000 / 36;
  private JFrame f = new JFrame("Expordium");
  private Collection<Block> elements = new ArrayList<Block>();
  private Collection<Bullet> bullets = new ArrayList<Bullet>();
  private BufferedImage Bg;

  public Wall wall;
  public Guy guy;
  public End end;
  public Bullet bullet;

  private String file;
  private Expordium game;
  private String[][] strLevel = new String[30][10];
  private String[][] strWall = new String[30][10];

  Display(Expordium g){
    game=g;
    readFile();
    for(int i=0; i<30; i++){
      for(int j=0; j<10; j++){
        if(strLevel[i][j].equals("W")){
          elements.add(new Wall(i*32,j*32,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Block/Grass-T.PNG"));
          strWall[i][j]=strLevel[i][j];
        }
        if(strLevel[i][j].equals("A")){
          elements.add(new Wall(i*32,j*32,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Block/Grass-L.PNG"));
          strWall[i][j]=strLevel[i][j];
        }
        if(strLevel[i][j].equals("S")){
          elements.add(new Wall(i*32,j*32,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Block/Grass-B.PNG"));
          strWall[i][j]=strLevel[i][j];
        }
        if(strLevel[i][j].equals("D")){
          elements.add(new Wall(i*32,j*32,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Block/Grass-R.PNG"));
          strWall[i][j]=strLevel[i][j];
        }
        if(strLevel[i][j].equals("s")){
          elements.add(guy=new Guy(i*32,j*32,false,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Guy/Guy-R.PNG"));
        }
        if(strLevel[i][j].equals("e")){
          elements.add(end=new End(i*32,j*32,false,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Block/End.PNG"));
        }
      }
    }
    new Thread(this).start();
  }

  public void run(){
    long tm = System.currentTimeMillis();

    while(true){
      update();
      repaint();

      try {
        tm += FPS;
        Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
      }
      catch(InterruptedException e)
      {
        System.out.println(e);
      }
    }
  }

This is the collision detection part:

    public boolean collision() {
      java.util.Iterator<Block> iterator = elements.iterator();
      while(iterator.hasNext()){
        if(iterator.next().isSolid && guy.isColliding((Block)iterator.next())){
          return true;
        }
      }
      return false;
    }

End

    public void update() {
      if(!guy.isJump && game.isU){
        guy.Jump();
      }
      if(game.isR){
        if(!collision()){
          guy.Move(2);
        }
      }
      if(game.isL){
        if(!collision()){
          guy.Move(1);
        }
      }
      if(guy.isJump){
        guy.Jump();
      }
    }

  public void paint(Graphics g){
    try {
      Bg = ImageIO.read(new File("C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Object/BackGround.PNG"));
    } catch (IOException e) {}
    g.drawImage(Bg, 0,0,null);
    java.util.Iterator<Block> iterator = elements.iterator();
    while(iterator.hasNext())
      ((Block) iterator.next()).draw(g);

    java.util.Iterator<Bullet> iterator1 = bullets.iterator();
    while(iterator1.hasNext())
      ((Block) iterator1.next()).draw(g);

  }

  private void readFile() {
    int num=0;
    String noFile = "";
    String loc ="C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Level/Level " + game.getLevel() + ".txt";
    File Level = new File(loc);
    file=TextFile.getContents(Level);
    for(int i=0; i<file.length(); i++){
      if(file.substring(num, num+1).equals("W") || file.substring(num, num+1).equals("A") || file.substring(num, num+1).equals("S") || file.substring(num, num+1).equals("D") || file.substring(num, num+1).equals("e") || file.substring(num, num+1).equals("s") ||  file.substring(num, num+1).equals(" ")){
        noFile=noFile+file.substring(num, num+1);
      }
      num++;
    }
    num=0;
    for(int j=0; j<10; j++){
      for(int i=0; i<30; i++){
        strLevel[i][j]=noFile.substring(num, num+1);
        num++;
      }
    }
  }

  public void shoot() {
    if(guy.dir==1){
      bullets.add(new Bullet(guy.getX(),guy.getY(),1,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Object/Bullet.PNG"));
    }
    if(guy.dir==2){
      bullets.add(new Bullet(guy.getX(),guy.getY(),2,true,"C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Object/Bullet.PNG"));
    }
  }

}

Guy Class

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Guy extends Block{
  private int x, y, groundY;
  public boolean isSolid;
  private BufferedImage guy;
  public boolean isJump=false;
  private int accM, accJ;
  private String location;
  public int dir=2;

  public Guy(int startx, int starty, boolean solid, String loc) {
    super(startx, starty, solid, loc);
    try {                
      guy = ImageIO.read(new File(loc));
    }catch (IOException ex) {}
    x=startx;
    y=starty;
    isSolid=solid;
    location=loc;
  }

  public boolean isColliding(Block e){
    int leftSide = getX();
    int rightSide = getX() + 31;
    int top = getY();
    int bottom = getY() + 31;

    int eLeftSide = e.getX();
    int eRightSide = e.getX() + 31;
    int eTop = e.getY();
    int eBottom = e.getY() + 31;


    if(eLeftSide < rightSide)
      if(eRightSide > leftSide)
        if(eTop < bottom)
          if(eBottom > top)
            return true;

    return false;
  }

  public void draw(Graphics g) {
    try {
      guy = ImageIO.read(new File(location));
    } catch (IOException e) {}
    g.drawImage(guy,x,y,null);
  }
  public int getX(){
    return x;
  }
  public int getY(){
    return y;
  }
  public void setX(int x1){
    x=x1;
  }
  public void setY(int y1){
    y=y1;
  }
  public void Move(int i) {
    if(i==2){
      dir=2;
      location="C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Guy/Guy-R.PNG";
      x=x+2;
    }
    else{
      dir=1;
      location="C:/Program Files (x86)/Software/eclipse/Programs/Expordium/Picture/Guy/Guy-L.PNG";
      x=x-2;
    }
  }
  public void Jump() {
    if(groundY==0){
      isJump=true;
      y=y+3;
      groundY=groundY+3;
    }
    else if(groundY!=0 && groundY<=48 && groundY!=96){
      y=y-3;
      groundY=groundY+3;
    }
    else if(groundY!=0 && groundY>=48 && groundY!=96){
      y=y+3;
      groundY=groundY+3;
    }
    else{
      isJump=false;
      groundY=0;
    }
  }
}

Wall Class

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Wall extends Block{
  private int x, y;
  public boolean isSolid;
  private BufferedImage wall;

  public Wall(int startx, int starty, boolean solid, String loc) {
    super(startx, starty, solid, loc);
    try {                
      wall = ImageIO.read(new File(loc));
    }catch (IOException ex) {}
    x=startx;
    y=starty;
    isSolid=solid;
  }

  public void draw(Graphics g) {
    g.drawImage(wall,x,y,null);
  }

  public int getX(){
    return x;
  }
  public int getY(){
    return y;
  }
}

End Class

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class End extends Block{
  private int x, y;
  public boolean isSolid;
  private BufferedImage end;

  public End(int startx, int starty, boolean solid, String loc) {
    super(startx, starty, solid, loc);
    try {                
      end = ImageIO.read(new File(loc));
    }catch (IOException ex) {}
    x=startx;
    y=starty;
    isSolid=solid;
  }

  public void draw(Graphics g) {
    g.drawImage(end,x,y,null);
  }

  public int getX(){
    return x;
  }
  public int getY(){
    return y;
  }
}

Block Class

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public abstract class Block {
  private int x, y;
  public boolean isSolid;
  private BufferedImage block;
  private String location;

  public Block(int startx, int starty, boolean solid, String loc) {
    x=startx;
    y=starty;
    isSolid=solid;
    location=loc;
    try {
      block = ImageIO.read(new File(loc));
    } catch (IOException e) {
    }
  }

  public abstract void draw(Graphics g);

  public int getX(){
    return x;
  }
  public int getY(){
    return y;
  }
}

Bullet Class

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Bullet extends Block{
  private int x, y;
  public boolean isSolid;
  private BufferedImage bullet;
  public int dir;

  public Bullet(int startx, int starty, int dir1, boolean solid, String loc) {
    super(startx, starty, solid, loc);
    try {                
      bullet = ImageIO.read(new File(loc));
    }catch (IOException ex) {}
    x=startx;
    y=starty;
    dir=dir1;
    isSolid=solid;
  }

  public void draw(Graphics g) {
    if(dir==1){
      x=x-5;
    }
    if(dir==2){
      x=x+5;
    }
    g.drawImage(bullet,x,y,null);
  }

  public int getX(){
    return x;
  }
  public int getY(){
    return y;
  }
}

One thing I noticed is that you're calling the next() method twice in the iterator. Each time you call the next() method the iterator returns the next Block. If there are no Block objects left, you'll get an exception. The code below fixes that, but I doubt if it's going to fix the problem itself...

public boolean collision() {
    java.util.Iterator<Block> iterator = elements.iterator();
    while(iterator.hasNext()){
        Block item = iterator.next();
        if(item.isSolid && guy.isColliding(item)){
            return true;
        }
    }
    return false;
}

This has nothing to do with your question, but what you are doing is so bad, especially my first remark.

  • Each time you render the game, you load the image for your "guy" from the file. You should load them all (player-left, player-right) and then render the correct image, depending on the direction of your "guy".

  • You are using absolute path to point to the images. Use relative paths.

  • Do not use 1 and 2 as directions, but something more logic, eg:
    • -2 means run to the left
    • -1 means no movement, but pointing to the left
    • ( 0 means no movement)
    • +1 means no movement, but pointing to the right
    • +2 means run to the right
  • Variable names do start with a lowercase character, eg: bg instead of Bg
  • Use in your next game project float s for the coordinates.

Here is some code:

private BufferedImage player_left;
private BufferedImage player_right;

public Guy() { // Your consturctor:
    player_left = ImageIO.read(new File("resources/img/player-left.png"));
    player_right = ImageIO.read(new Fiel("resources/img/player-right.png"));
}

public void draw(Graphics g)
{
    if (direction == -1) { // left
        g.draw(player_left, .......);
    } else if (direction == 1) // right
    {
        g.draw(player_right, ......);
    } else if (direction == ...)
    {
        .....
    }
}

Have you ever looked into an open source 2d game engine ? It will do all the heavy lifting for you eg Physics / Collision Detection / Controls.

Here is a usefull stackoverflow post:

https://stackoverflow.com/questions/293079/java-2d-game-frameworks

in the following part of the code:

if(eLeftSide < rightSide)
    if(eRightSide > leftSide)
        if(eTop < bottom)
            if(eBottom > top)
                return true;

return false;

you only check for one instance of collision (when the guy is inside the block). For simple bounding box collisions you'll need other type of checking. Try drawing two boxes on paper and check how they can be colliding and try to implement that

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM