Java游戏 - 如何阻止玩家越过障碍物

时间:2012-12-26 21:34:37

标签: java awt collision-detection

我制作了一个非常简单的2D Java游戏类,由一般的2D游戏方法组成,例如渲染和更新,我已经设置了所有的if语句,以便玩家使用键盘箭头输入在地图上移动。我现在正试图设置我所读到的是碰撞检测,我知道我需要做什么的基础知识,因为我在实际来到这里之前做了很多阅读,从我读过的内容开始像这样的东西:

制作2个矩形

Rectangle rectOne = new Rectangle(playerX, playerY, 40, 40); 
//keep in mind that the variables playerX and playerY are already made previously
Rectangle rectTwo = new Rectangle(50, 50, 100,100);

然后根据我的更新方法,我会说:

if(rectOne.intersects(rectTwo)){//change the player direction so that he 
can go no further}

我只是不明白我的if语句会有什么内容,我需要一些东西阻止我的玩家在交叉点发生时继续前进但我怎么能写这个因为玩家可以在4个不同的方向移动(UP,DOWN , 左右)。如果它只是1维会更简单,因为我可以将方向改为与它的相反,但是它的两个维度,所以它有点令人困惑。

其他信息:

我的游戏视图类似于以下内容: http://www.2dplay.com/awesome-tanks/awesome-tanks-play.htm

编辑3:

                package javagame;

                import java.awt.Rectangle;

                IMPORTS ARE HERE


public class Play extends BasicGameState{

    Animation bucky, movingUp, movingDown, movingLeft, movingRight;
    Image worldMap;
    boolean quit = false;//gives user to quit the game
    int[] duration = {200, 200};//how long frame stays up for
    int buckyPositionX = 0;
    int buckyPositionY = 0;
    int x = buckyPositionX + 320;//keeps user in the middle of the screem
    int y = buckyPositionY + 160;//the numbers are half of the screen size

    Rectangle rectOne = new Rectangle(x, y,90,90);
    Rectangle rectTwo = new Rectangle(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);



private int xSpeed, ySpeed;///////////////////////////CODE FOR COLLISION


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


    movingUp = new Animation(walkUp, duration, false);
    movingDown = new Animation(walkDown, duration, false);  
    movingLeft = new Animation(walkLeft, duration, false);  
    movingRight = new Animation(walkRight, 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(x, y);//makes him appear at center of map
    g.fillRect(x, y,90,90);
    g.fillRect(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);


    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 setSpeedWithDirection(int speed, int direction)////////////CODE FOR COLLISION
{
xSpeed = (int) (Math.cos(direction) * speed);//////////////////////////CODE FOR COLLISION
ySpeed = (int) (Math.sin(direction) * speed);//////////////////////////CODE FOR COLLISION
}

    public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException{
    Input input = gc.getInput();



x += xSpeed;//////////////////////////////////////////CODE FOR COLLISION
y += ySpeed;//////////////////////////////////////////CODE FOR COLLISION

if(rectOne.intersects(rectTwo))///////////////////////CODE FOR COLLISION
{
xSpeed = 0;////////////////////////////CODE FOR COLLISION
ySpeed = 0;////////////////////////////CODE FOR COLLISION
}



    //up
    if(input.isKeyDown(Input.KEY_UP)){
        bucky = movingUp;//changes the image to his back
        buckyPositionY += 2;;//increase the Y coordinates of bucky (move him up)
        if(buckyPositionY>162){//if I reach the top 
            buckyPositionY -= 2;//stops any further movement in that direction
        }
    }

    //down
    if(input.isKeyDown(Input.KEY_DOWN)){
        bucky = movingDown;
        buckyPositionY -= 2;
        if(buckyPositionY<-550){
            buckyPositionY += 2;//basically change the direction if + make -
    }}
    //left
    if(input.isKeyDown(Input.KEY_LEFT)){
        bucky = movingLeft;
        buckyPositionX += 2;
        if(buckyPositionX>324){
            buckyPositionX -= 2;//delta * .1f
    }}
    //right
    if(input.isKeyDown(Input.KEY_RIGHT)){
        bucky = movingRight;
        buckyPositionX -= 2;
        if(buckyPositionX<-776){
            buckyPositionX += 2;
    }}



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

2 个答案:

答案 0 :(得分:4)

作为先决条件,您的播放器类(或其中一个超类)应该有一些描述其速度的字段(x速度和y速度的一对字段非常有效,尽管您需要触发来设置在给定方向上的球员)。以下是具有x和y速度字段的简单播放器类的示例:

public class Player
{
     //coordinates of the player 
     private int x, y;

     //horizontal and vertical components of the player's speed.
     private int xSpeed, ySpeed; 

     //call a method similar to this one every time your player updates its position
     public void updatePosition()
     {
          x += xSpeed;
          y += ySpeed;
     }

     //Converts a speed and a direction (much easier to deal with)
     //to an x speed and a y speed (much easier for actually moving) 
     //and sets the player's motion
     public void setSpeedWithDirection(int speed, float direction)
     {
         xSpeed = Math.cos(direction) * speed;
         ySpeed = Math.sin(direction) * speed;
     }
}

为了让它真正反映你的玩家的速度,每次将x速度添加到玩家的x坐标,并在每次玩家更新时将y速度添加到玩家的y坐标。现在,碰撞发生时可能会发生很多事情。最简单的方法是通过将其x速度和y速度设置为零来停止播放器。然而,这可能看起来很奇怪,因为无论他们进入什么方向,玩家都会停止移动。稍微好一点的方法是分析交叉点的形状(假设你使用java.awt.Rectangle你可以使用{{ 1}}方法,几乎​​所有Rectangle类都有类似的东西)并确定x-speed,y-speed或两者都应该设置为零。例如,如果交点较宽(x轴大于y轴),则应将y速度设置为零,但x速度不受影响。如果你想让玩家转身(180度),只需翻转x速度和y速度的标志。如果您希望玩家“反弹”而不是停止,请像前一种情况一样分析交叉点,但是反转速度而不是将其设置为零。以下是一些代码示例(可能不会完全按照编写的方式工作,因为我不知道您的类是如何设置的):

intersection()

请注意,无论您选择做什么,碰撞都很难顺利进行。我会考虑所有这些选项,可以始终构建的良好起点。我希望这会有所帮助。

答案 1 :(得分:0)

我建议创建一个枚举Way。您应该知道他现在要去的Way,然后只需将Way更改为相反的Way,或者您可以锁定当前Way并选择随机Way