所以这是我的Player
课程(我想跳到空格键上的对象),我只是不知道从哪里开始,有什么好的资源我可以在互联网上阅读与我有关吗?任何帮助都很棒,谢谢你。
package com.zetcode;
import java.awt.Color;
import java.awt.Graphics;
public class Player extends Creature {
private boolean jumping = false;
private Creature creature;
public Player(Handler handler, float x, float y) {
super(handler, x, y, Creature.PLAYER_WIDTH, Creature.PLAYER_HEIGHT);
bounds.x = 16;
bounds.y = 31;
bounds.width = 40;
bounds.height = 58;
}
@Override
public void tick() {
getInput();
move();
handler.getGameCamera().centerOnEntity(this);
}
private void getInput(){
xMove = 0;
yMove = 3;
gravity = 2;
if(handler.getKeyManager().jump)
yMove = -speed;
if(handler.getKeyManager().down)
yMove = speed;
if(handler.getKeyManager().left)
xMove = -speed;
if(handler.getKeyManager().right)
xMove = speed;
}
@Override
public void render(Graphics g) {
g.drawImage(Assets.player, (int) (x - handler.getGameCamera().getxOffset()), (int) (y - handler.getGameCamera().getyOffset()), width, height, null);
}
}
这是我的KeyManager
课程:
package com.zetcode;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyManager implements KeyListener{
private boolean[] keys;
public boolean up, down, left, right, jump;
public KeyManager(){
keys = new boolean[256];
}
public void tick(){
down = keys[KeyEvent.VK_S];
left = keys[KeyEvent.VK_A];
right = keys[KeyEvent.VK_D];
jump = keys[KeyEvent.VK_SPACE];
}
@Override
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
System.out.println("A Key was pressed");
}
@Override
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
@Override
public void keyTyped(KeyEvent e) {
}
}
我一直在努力为我的角色实现跳跃的方式,目前玩家在空格键按下时向上移动Y轴,但我可以按住键并无休止地跳跃。
我将添加我的碰撞检测Creature
类:
package com.zetcode;
public abstract class Creature extends Entity {
public static final int DEFAULT_HEALTH = 10;
public static final float DEFAULT_SPEED = 3.0f;
public static final int DEFAULT_CREATURE_WIDTH = 64,
DEFAULT_CREATURE_HEIGHT = 64;
public static final int PLAYER_HEIGHT = 90, PLAYER_WIDTH = 64;
protected int health;
protected float speed;
protected float xMove, yMove;
protected float gravity;
public boolean falling = true;
private boolean jumping = false;
public Creature(Handler handler, float x, float y, int width, int height) {
super(handler, x, y, width, height);
health = DEFAULT_HEALTH;
speed = DEFAULT_SPEED;
xMove = 0;
yMove = 0;
gravity = 0;
}
//collision detection
public void move(){
moveX();
moveY();
}
public void moveX(){
if(xMove > 0){//move right
int tx = (int) (x + xMove + bounds.x + bounds.width) / Tile.TILE_WIDTH;
if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top right corner of hitbox
!collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom right corner of hitbox
x += xMove;
}else{
x = tx * Tile.TILE_WIDTH - bounds.x - bounds.width - 1;
}
}else if(xMove < 0){//move left
int tx = (int) (x + xMove + bounds.x) / Tile.TILE_WIDTH;
if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top left corner of hitbox
!collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom left corner of hitbox
x += xMove;
}else{
x = tx * Tile.TILE_WIDTH + Tile.TILE_WIDTH - bounds.x;
}
}
}
public void moveY(){
if(yMove < 0){//up
int ty = (int) (y+ yMove + bounds.y) / Tile.TILE_HEIGHT;
if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH, ty) &&
!collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILE_WIDTH,ty)){
y += yMove;
}else{
y = ty * Tile.TILE_HEIGHT + Tile.TILE_HEIGHT - bounds.y;
}
}else if(yMove > 0){//down
int ty = (int) (y+ yMove + bounds.y + bounds.getHeight()) / Tile.TILE_HEIGHT;
if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH,ty) &&
!collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILE_WIDTH,ty)){
y += yMove;
}else{
y = ty * Tile.TILE_HEIGHT - bounds.y - bounds.height -1;
}
}
}
protected boolean collisionWithTile(int x, int y){
return handler.getWorld().getTile(x, y).isSolid();
}
//getters and setters
public float getxMove() {
return xMove;
}
public void setxMove(float xMove) {
this.xMove = xMove;
}
public float getyMove() {
return yMove;
}
public void setyMove(float yMove) {
this.yMove = yMove;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
}
您想要做的是为场景中的对象实现速度,加速度和重力。速度是一个2D矢量,可以告诉您某些物体的移动速度,而加速度则告诉您速度增加了多少。
所有对象都应该有一个update()
方法,它定期调用。它会将物体的速度应用到它的位置(这就是速度和位置之间的相关关系),当你想要加速一个物体时,你基本上只会提高它的速度。在update()
方法中我们也应用重力(以负Y加速度的形式)
你也可以利用摩擦力。摩擦确保您的物体在向某个方向移动时减速。
在这个简单的模拟中,当值接近1
时,摩擦变弱。这意味着在FRICTION==1
你没有摩擦,在FRICTION==0
你的物体将立即停止。
public class PhysicsObject {
public static final double FRICTION = 0.99;
public static final double GRAVITY = 0.01;
private double posX;
private double posY;
private double speedX = 0;
private double speedY = 0;
public PhysicsObject(double posX, double posY) {
this.posX = posX;
this.posY = posY;
}
public void accelerate(double accelerationX, double accelerationY) {
speedX += accelerationX;
speedY += accelerationY;
}
public void move(double xDelta, double yDelta) {
posX += xDelta;
posY += yDelta;
// do collision detection here. upon collision, set speedX/speedY to zero..!
}
public void update() {
move(speedX, speedY);
speedX *= FRICTION;
speedY *= FRICTION;
accelerate(0, -GRAVITY); // gravity accelerates the object downwards each tick
}
public double getPosX() {
return posX;
}
public double getPosY() {
return posY;
}
}
你也可以使用update()
来处理碰撞检测(它应该将速度设置为零)并且敌人可以执行他们的AI逻辑。
你上课Player
可以扩展这个PhysicsObject
并有方法jump()
,runLeft()
和runRight()
,它们看起来像这样:
public class Player extends PhysicsObject{
public static final double JUMP_STRENGTH = 5;
public static final double SPEED = 1;
public void jump() {
accelerate(0, JUMP_STRENGTH); // change 5 for some constant or variable indicating the "strength" of the jump
}
public void runRight() {
move(SPEED, 0);
}
public void runLeft() {
move(-SPEED, 0);
}
}
碰撞检测本身就是一件很大的事情,而且这里的内容太多了,但this video描述得非常好。去看看吧!