手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏17
2022-01-09 本文已影响0人
__豆约翰__
这节比较有趣,我们来实现Enemy自动追踪Player的算法,无论player走到哪里,enemy都如影随形。
这里我们主要用到了向量加减的几何意义。
向量类
Vector2d.java
package utils;
public class Vector2d {
public double dX;
public double dY;
// Constructor methods ....
public Vector2d(double dXp, double dYp ) {
this.dX = dXp;
this.dY = dYp;
}
public Vector2d() {
dX = dY = 0.0;
}
// Convert Vector2d to a string ...
public String toString() {
return "Vector2d(" + dX + ", " + dY + ")";
}
// Compute magnitude of Vector2d ....
public double length() {
return Math.sqrt ( dX*dX + dY*dY );
}
// Sum of two Vector2ds ....
public void add( Vector2d v1 ) {
this.dX += v1.dX;
this.dY += v1.dY;
}
// Subtract Vector2d v1 from v .....
public void sub( Vector2d v1 ) {
this.dX -= v1.dX;
this.dY -= v1.dY;
}
// Scale Vector2d by a constant ...
public void scale( double scaleFactor ) {
this.dX *=scaleFactor;
this.dY *=scaleFactor;
}
// Normalize a Vector2ds length....
public Vector2d normalize() {
Vector2d v2 = new Vector2d();
double length = Math.sqrt( this.dX*this.dX + this.dY*this.dY );
if (length != 0) {
v2.dX = this.dX/length;
v2.dY = this.dY/length;
}
return v2;
}
// Dot product of two Vector2ds .....
public double dotProduct ( Vector2d v1 ) {
return this.dX*v1.dX + this.dY*v1.dY;
}
}
修改Enemy类,添加Player类型的成员;因为我们要追踪Player,所以必须维护一个Player类型的对象,作为追踪的目标。
_isInRange()方法主要用来判断Enemy是否已经距离Player足够近了,主要是检测两者x坐标和y坐标之间的差值是否足够小。
每帧对update方法的调用中,我们都调用followPath()方法来计算新的enemy位置。
public class Enemy extends AttackAbleObject{
private Animator _animator;
private Player _player;
private double _speed = 1.5;
public Enemy(Player players, Animator animator, int hurtx, int hurty, int hurtscale_x, int hurtscale_y
, int hitoffset_x1, int hitoffset_y1, int hitoffset_x2, int hitoffset_y2){
super(animator,hurtx,hurty,hurtscale_x,hurtscale_y
,hitoffset_x1,hitoffset_y1,hitoffset_x2,hitoffset_y2);
_animator = animator;
_player= players;
_animator.setAnimation("idle");
}
@Override
public void update(Graphics2D g){
_animator.show(g);
followPath();
}
public Transform getTransform(){
return _animator;
}
private boolean _isInRange(){
boolean bRet = Math.abs(getX() - _player.getX()) < 60
&& Math.abs(getZ() - _player.getZ()) < Config.Z_FIGHT_DIST;
return bRet;
}
public void followPath(){
if(!_isInRange()){
Vector2d towards = new Vector2d(_player.getX()-getX(),
_player.getZ()-getZ());
Vector2d normalizedTowards = towards.normalize();
Vector2d posVector = new Vector2d(normalizedTowards.dX,normalizedTowards.dY);
posVector.scale(_speed);
posVector.add(new Vector2d(getX(),getZ()));
setPosition(posVector.dX,posVector.dY);
if((getX()-_player.getX())<0 && !getTransform().isFlippedRight()){
getTransform().flip();
}
if((getX()-_player.getX())>=0 && getTransform().isFlippedRight()){
getTransform().flip();
}
}
}
}
followPath()方法是自动追踪的核心算法,原理如下图所示:
31aaa47bd98c24184a056865d2256e1.png如果您迷路了,请参考完整源码: