【发布时间】:2011-10-09 23:04:04
【问题描述】:
我希望在我的碰撞检测/运动方面获得一些帮助,它可以工作但有问题。 我无法始终如一地重现碰撞检测/运动的错误。玩家有时无法向某些方向移动,我也无法重现脱开它似乎只是开始让你无缘无故地再次移动。重力并不总是在它应该起作用的时候起作用,有时你可能会被困在墙上。代码如下。
我还想听听有关如何在游戏中实现动画(例如在移动时播放行走动画)的任何建议。我已经制作了一个动画,但它很乱并且使用了 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;
}
}
Tile.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();
}
}
【问题讨论】:
-
您不应该在相机滚动时弄乱平铺位置。这些应该是相对不可变的。改用在绘图计算中使用的偏移量。
-
谢谢克里斯。这很有意义,但我不知道该怎么做。我会看看如果我能弄清楚。
-
我想我不明白。我试图做的不是移动瓷砖的矩形,而是只显示瓷砖和播放器,就好像它们在滚动一样。这是错误的想法还是我没有正确编码?
-
仅当您使用精灵框架时,精灵才能作为一个组移动(使用组偏移量)。您应该只关心相机,以及如何相对于相机进行绘图。
标签: java animation collision-detection