java - 如何让碰撞和动画在 2d 平台游戏中发挥作用?

标签 java animation collision-detection

我希望在碰撞检测/移动方面获得一些帮助,它可以工作,但有问题。 我无法一致地重现碰撞检测/移动的错误。玩家有时无法向某些方向移动,我也无法重现卡住的情况,它似乎开始让你无缘无故地再次移动。重力并不总是在它应该起作用的时候起作用,有时你可能会被困在墙上。代码如下。

我还想听听有关如何在游戏中实现动画(例如在移动时播放行走动画)的任何建议。我已经让一个动画可以工作,但它很困惑并且使用了 Timer();我想找到一种更好的方法来做到这一点。如有任何建议,我们将不胜感激。

出于学习目的,我使用 eclipse 用 java 编写游戏,所以我不是在寻找 2d 游戏引擎。

这是所有代码。

MarioLikeGame.java

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class MarioLikeGame extends JFrame implements KeyListener
{
    private static Graphics graphics;
    private Image image;
    private static boolean running = true;
    private static Player player = new Player(4 * 32, 6 * 32 + 24,                             
    "images/playerStill.png", "images/playerWalking.png");
    private static PlayingBoard board = new PlayingBoard(player);
    private static ReadLevelFile readLevel = new ReadLevelFile();
    private static boolean scrollingRight = false;//To let player know to stop moving
    private static boolean scrollingLeft = false;


    public static void main(String[] args)
    {
        new MarioLikeGame();
        readLevel.openFile();
        readLevel.readFile(board);
        readLevel.closeFile();
        gameLoop();
    }

    public MarioLikeGame()
    {
        setTitle("SideSCroIIer");
        setResizable(false);
        setSize(448, 320 + 24);// 32*32 tiles 14 wide  10 high
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBackground(Color.BLACK);
        this.addKeyListener(this);
        setVisible(true);

    }

    public void paint(Graphics g)
    {
        image = createImage(getWidth(), getHeight());
        graphics = image.getGraphics();

        paintComponent(graphics);
        g.drawImage(image, 0, 0, null);
        repaint();
    }

    public void paintComponent(Graphics g)
    {   
        g.drawImage(image, 0, 0, null);
        for(int row = 0; row < board.gameTiles.length; row++)
        {
            for(int column = 0; column < board.gameTiles[row].length; column++)
            {
                board.gameTiles[row][column].draw(g);
            }
        }

        player.draw(g);

    }

    public static void gameLoop()
    {
        long startTime = System.currentTimeMillis();
        long cumTime = startTime;

        while(running)
        {
            long timePassed = System.currentTimeMillis() - cumTime;
            cumTime += timePassed;

            checkForCollision(timePassed);

            player.checkForPlayerMovement(timePassed, scrollingRight, scrollingLeft);
            board.checkForScroll(timePassed);

            try
            {
                Thread.sleep(20);
            }
            catch(Exception ex){}

        }
    }

    public static void checkForCollision(long timePassed)
    {
        //scroll if player tries to walk to the edge of the screen
        //check for scrollingRight
        if(player.xPos + 31 >= 11 * 32)
        {

            board.setScrollingRight(true);
            scrollingRight = true;


        }

        if(player.xPos + 31 < 11 * 32)
        {
            board.setScrollingRight(false);
            scrollingRight = false;
        }
        //Make sure to not scroll everything off screen
        //stop scrolling when the right walls right side is at the ride side of
             the screen
        if(board.gameTiles[board.gameTiles.length -1][0].xPos + 31 <= 448)
        {
            board.setScrollingRight(false);
            scrollingRight = false;
        }

        //check for scrollingLeft
        if(player.xPos <= 3 * 32)
        {

            board.setScrollingLeft(true);
            scrollingLeft = true;


        }

        if(player.xPos > 4 * 32)
        {
            board.setScrollingLeft(false);
            scrollingLeft = false;
        }

        //Make sure to not scroll everything off screen
        //stop scrolling when the left walls left side is at the ride left 
            of the screen
        if(board.gameTiles[0][0].xPos >= 0)
        {
            board.setScrollingLeft(false);
            scrollingLeft = false;
        }

        //check for collision with tiles while moving right
        if(player.movingRight == true)
        {
            for(int row = 0; row < board.gameTiles.length; row++)
            {
                for(int column = 0; column < board.gameTiles[row].length; 
                                column++)
                {
                    if((board.gameTiles[row]  
 [column].rect.contains(player.xPos + 32, player.yPos) 
|| board.gameTiles[row][column].rect.contains(player.xPos + 32, player.yPos + 31))  && 
board.gameTiles[row][column].isSolid == true)
                    {
                        player.setHitRight(true);
                    }

                    else if((board.gameTiles[row]
[column].rect.contains(player.xPos + 32, player.yPos) && board.gameTiles[row]
[column].rect.contains(player.xPos + 32, player.yPos + 31)) && board.gameTiles[row]
[column].isSolid == false)
                    {
                        player.setHitRight(false);
                    }

                }
            }
        }

        //Check for collision with tiles while moving left
        if(player.movingLeft == true)
        {
            for(int row = 0; row < board.gameTiles.length; row++)
            {
                for(int column = 0; column < board.gameTiles[row].length; 
column++)
                {
                    if((board.gameTiles[row]
[column].rect.contains(player.xPos - 1, player.yPos) || board.gameTiles[row]
[column].rect.contains(player.xPos - 1, player.yPos + 31)) && board.gameTiles[row]
[column].isSolid == true)
                    {
                        player.setHitLeft(true);
                    }
                    else if((board.gameTiles[row]  
[column].rect.contains(player.xPos - 1, player.yPos) && board.gameTiles[row]
[column].rect.contains(player.xPos - 1, player.yPos + 31)) && board.gameTiles[row]
[column].isSolid == false)
                    {
                        player.setHitLeft(false);
                    }
                }
            }
        }

        //only use gravity if there is nothing solid below player       
        for(int row = 0; row < board.gameTiles.length; row++)
        {
            for(int column = 0; column < board.gameTiles[row].length; column++)
            {
                if((board.gameTiles[row][column].rect.contains(player.xPos,
 player.yPos + 32) || board.gameTiles[row][column].rect.contains(player.xPos + 31, 
 player.yPos + 32)) && board.gameTiles[row][column].isSolid == true)
                {
                    player.setGravity(false);
                }
                else if((board.gameTiles[row]
[column].rect.contains(player.xPos, player.yPos + 32) && board.gameTiles[row]
[column].rect.contains(player.xPos + 31, player.yPos + 32)) && board.gameTiles[row]
[column].isSolid == false)
                {
                    if(player.gravityOff == false)//wtf? delete?
                    {
                        player.setGravity(true);
                    }
                }

            }
        }   


        //Jumping collision
        if(player.jumping == true)
        {

            player.setHitUp(false);//Set false time every works fine - see
 commented code below

            for(int row = 0; row < board.gameTiles.length; row++)
            {
                for(int column = 0; column < board.gameTiles[row].length;
 column++)
                {
                    if((board.gameTiles[row]
[column].rect.contains(player.xPos, player.yPos - 1) || board.gameTiles[row]
[column].rect.contains(player.xPos + 31, player.yPos - 1)) && board.gameTiles[row]
[column].isSolid == true)
                    {
                        player.setHitUp(true);
                    }
//                  else if((board.gameTiles[row]
[column].rect.contains(player.xPos, player.yPos - 1) && board.gameTiles[row]
[column].rect.contains(player.xPos + 31, player.yPos - 1)) && board.gameTiles[row]
[column].isSolid == false)

//                  {
//                      player.setHitUp(false);
//                  }//couldnt get this to set false properly fixed up 
top




                }
            }
        }


    }


    public void keyPressed(KeyEvent e) 
    {

        int keyCode = e.getKeyCode();

        if(keyCode == KeyEvent.VK_D)
        {

            player.setMovingRight(true);

        }

        if(keyCode == KeyEvent.VK_A)
        {
            player.setMovingLeft(true);
        }

        if(keyCode == KeyEvent.VK_W)
        {
            if(player.jumping == false)
            {
                if(player.gravity == false)
                {
                    player.jumping = true;
                    player.startYPos = player.yPos;
                }
            }
        }
    }


    public void keyReleased(KeyEvent e) 
    {
        int keyCode = e.getKeyCode();

        if(keyCode == KeyEvent.VK_D)
        {
            player.setMovingRight(false);

        }

        if(keyCode == KeyEvent.VK_A)
        {
            player.setMovingLeft(false);
        }


    }


    public void keyTyped(KeyEvent e) 
    {
        //does nothing
    }

}

Player.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Timer;


public class Player 
{ 
int xPos;
int yPos;
int height;
int width;
Image img1;
Image img2;
Rectangle rect;
double velocityX = 0.08;
double velocityY = 0.08;
boolean movingRight = false;
boolean movingLeft = false;
boolean hitRight = false;
boolean hitLeft = false;
boolean hitUp = false;
boolean gravity = true;
boolean jumping = false;
int startYPos;
boolean gravityOff = false;




public Player(final int xPos, final int yPos, final String img1, final String img2)
{
    this.xPos = xPos;
    this.yPos = yPos;
    this.height = 32;
    this.width = 32;
    this.img1 = getImage(img1);
    this.img2 = getImage(img2);
    this.rect = new Rectangle(xPos, yPos, width, height);


}

public void draw(Graphics g)
{

    g.drawImage(img1, xPos , yPos, width, height, null);

}

public void checkForPlayerMovement(long timePassed, boolean scrollingRight, boolean     
 scrollingLeft)
{
    if(movingRight == true)
    {
        if(hitRight == false)
        {
            if(scrollingRight == false)
            {
                moveRight(timePassed);
            }
        }
    }

    if(movingLeft == true)
    {
        if(hitLeft == false)
        {
            if(scrollingLeft == false)
            {
                moveLeft(timePassed);
            }
        }
    }

    if(gravity == true)
    {
        moveDown(timePassed);
    }

    if(jumping == true)
    {

            jump(timePassed, startYPos);
    }

}

public void jump(long timepassed,int startYPos)
{   
    if(this.yPos > startYPos - 63 && hitUp == false)//63 so you cant jumpe 2 blocks but it is easier jump onto a block = level to your start pos
    {
        moveUp(timepassed);
        gravityOff = true;
    }
    else
    {
        gravity = true;
        jumping = false;
        gravityOff = false;
    }

}

public void moveRight(long timePassed)
{
    //had to change velocity manualy because moving right is slower than moving left with same velocity. WTF!
    xPos += 0.12 * timePassed;
    this.rect.x += 0.12 * timePassed;
}

public void moveLeft(long timePassed)
{
    xPos -= velocityX * timePassed;
    this.rect.x -= velocityX * timePassed;

}

public void moveDown(long timePassed)
{
    yPos += velocityY * timePassed;
    this.rect.y += velocityY * timePassed;
}

public void moveUp(long timePassed)
{
    yPos -= velocityY * timePassed;
    this.rect.y -= velocityY * timePassed;
}

public void setMovingRight(boolean moving)
{
    movingRight = moving;
}

public void setMovingLeft(boolean moving)
{
    movingLeft = moving;
}

public void setHitRight(boolean hit)
{
    hitRight = hit;
}

public void setHitLeft(boolean hit)
{
    hitLeft = hit;
}

public void setHitUp(boolean hit)
{
    hitUp = hit;
}

public void setGravity(boolean onSolid)
{
    gravity = onSolid;
}


Image getImage(String img) 
{
    return Toolkit.getDefaultToolkit().getImage(img);
}



}

PlayingBoard.java

public class PlayingBoard 
{
public Tile[][] gameTiles = new Tile[28][10];
public boolean scrollingRight = false;
public boolean scrollingLeft = false;
double velocityX = 0.05;
Player player;

public PlayingBoard(Player player)
{
    this.player = player;
    setUpBlankBoard();
}

public void setUpBlankBoard()
{
    for(int row = 0; row < gameTiles.length; row++)
    {
        for(int column = 0; column < gameTiles[row].length; column++)
        {
            gameTiles[row][column] = new Tile(row * 32, column * 32 + 24, 0);
        }

    }

}

public void checkForScroll(long timePassed)
{
    if(scrollingRight == true)
    {
        if(player.movingRight == true)
        {
            if(player.hitRight == false)
            {
                scrollRight(timePassed);
            }
        }
    }

    if(scrollingLeft == true)
    {
        if(player.movingLeft == true)
        {
            if(player.hitLeft == false)
            {
                scrollLeft(timePassed);
            }
        }
    }
}

public void scrollRight(long timePassed)
{
    for(int row = 0; row < gameTiles.length; row++)
    {
        for(int column = 0; column < gameTiles[row].length; column++)
        {
            gameTiles[row][column].xPos -= velocityX * timePassed;
            gameTiles[row][column].rect.x -= velocityX * timePassed;

        }

    }
}

public void scrollLeft(long timePassed)
{
    for(int row = 0; row < gameTiles.length; row++)
    {
        for(int column = 0; column < gameTiles[row].length; column++)
        {
            gameTiles[row][column].xPos += velocityX * timePassed;
            gameTiles[row][column].rect.x += velocityX * timePassed;

        }

    }
}

public void setScrollingRight(boolean scrolling)
{
    scrollingRight = scrolling;
}

public void setScrollingLeft(boolean scrolling)
{
    scrollingLeft = scrolling;
}

}

瓷砖.java

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;

public class Tile 
{
int xPos;
int yPos;
int height;
int width;
boolean isSolid = false;
boolean isHazard = false;
boolean isDeadly = false;
Image img1;
Rectangle rect;
int tileType;


public Tile(final int xPos, final int yPos, final int tileType)
{
    this.tileType = tileType;
    this.xPos = xPos;
    this.yPos = yPos;
    width = 32;
    height = 32;
    this.rect =  new Rectangle(xPos, yPos, width, height);
    defineTile();

}

public void draw(Graphics g)
{
    if(tileType != 0)
    {   
        g.drawImage(img1, xPos, yPos, width, height, null); 

    }

}

public void defineTile()
{
    if(tileType == 0)
    {
        blankTile();
    }
    if(tileType == 1)
    {
        groundTile();
    }
}

public void groundTile()
{
    img1 = getImage("images/ground.png");
    isSolid = true;

}

public void blankTile()
{

}

public void setTileType(int type)
{
    tileType = type;
    defineTile();
}




Image getImage(String img) 
{
    return Toolkit.getDefaultToolkit().getImage(img);
}


}

ReadLevelFile.java

import java.io.File;
import java.util.Scanner;


public class ReadLevelFile 
{
Scanner input;
int column = 0;
int row = 0;
public void openFile()
{
    try
    {
        input = new Scanner(new File("level1.txt"));
    }
    catch(Exception ex){}
}

public void readFile(PlayingBoard board)
{

    for(int column = 0; column < board.gameTiles[column].length; column++)
    {
        for(int row = 0; row < board.gameTiles.length; row++)
        {
            int x = input.nextInt();
            board.gameTiles[row][column].setTileType(x);
        }

    }
}

public void closeFile()
{
    input.close();
}
}

最佳答案

有一些软件包可以做这种类型的事情——你真的需要一个!

我会发布一个关于什么是好的 2D 游戏框架的问题。

祝你好运。

关于java - 如何让碰撞和动画在 2d 平台游戏中发挥作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7707164/

相关文章:

java - 将多个 Maven 项目组合成一场 war

java - 来自 url 的 android png 的透明度显示为黑色

java - 对调用多个私有(private)方法的公共(public)方法进行单元测试

java - 用 vector 填充二维数组时出现 NullPointerException

android - 共享元素和圆形显示

java - 如何在碰撞时从 arrayList 中删除一个项目?

css - react 中的全屏过渡动画

python - 是否可以将使用 Tkinter 创建的动画保存在文件中?

JavaScript:碰撞检测不起作用

python - pygame中的旋转命中框矩形