手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏20
2022-01-14 本文已影响0人
__豆约翰__
block效果
ActorObject.java
我们在AttackAbleObject和Enemy类之间,新增一个类层次ActorObject;ActorObject类型主要实现sprite被攻击后的阻塞效果(一种后退效果)。
AttackAbleObject类型主要负责hitbox和hurtbox。
有些对象可能没有阻塞效果,比如后面我们会介绍的野狗对象,这样野狗类就可以继承AttackAbleObject;
而像player和enemy这些有阻塞效果的对象,我们就让他们继承ActorObject
另外我们还把一些之前在AttackAbleObject类中实现的方法转移到了ActorObject类中,具体看源码。
阻塞效果主要由blockEffect()方法实现:
总体思想是实现一种后退的效果,后退时我们不想实现成是匀速的,希望开始时少退些,后来多退些,故这里我们使用了正弦函数。
另外在我们判断出当前对象正在遭受攻击时,设置_blocked = true
而在update方法中,如果我们判断blocked为true,我们就调用blockEffect()方法,展示阻塞效果。
public abstract class ActorObject extends AttackAbleObject{
private Animator _animator;
private double _flipCord = 1;
private float _xBlockOffset = 90f;
private double _blockDelay = 700;
private double _blockSpeed = 1.5;
// private double _blockStrength = 2.0;
private double _blockStrength = 0.2;
private double _blockDelayTimer = _blockDelay;
private int _hp = 0;
private int _maxHp = 0;
private boolean _blocked = false;
private boolean _blockedFromRight = true;
public ActorObject(Animator anim, int hp, int strength, int hurt_x, int hurt_y, int hurtscale_x, int hurtscale_y,
int hitoffset_x1, int hitoffset_y1, int hitoffset_x2, int hitoffset_y2){
super(anim,strength,hurt_x,hurt_y,hurtscale_x,hurtscale_y,hitoffset_x1,hitoffset_y1,hitoffset_x2,hitoffset_y2);
_animator = anim;
_hp = hp;
}
public Animator getAnimator(){
return _animator;
}
@Override
public void move(double x,double y){
super.move(x, y);
if(x>0 && _flipCord<0){
_animator.flip();
_flipCord = x;
}
if(x<0 && _flipCord>0){
_animator.flip();
_flipCord = x;
}
}
public void update(Graphics2D g){
if(!isDead()){
_animator.show(g);
if(isBlocked()){
blockEffect();
}
setHitting(false);
}
}
abstract void handleAttack();
abstract void attack();
abstract void idle();
public void takeDamage(AttackAbleObject dyn){
setHp(getHp()-dyn.getStrength());
}
public boolean isDead(){
return getHp()<=0;
}
public boolean isHit(AttackAbleObject dyn){
if(!isDead()){
if(!_blocked){
if(dyn.hasHitBoxCollide(this) && dyn.isHitting()){
if(!dyn.getTransform().isFlippedRight()){
_blockedFromRight = false;
}else{
_blockedFromRight = true;
}
_blocked = true;
return true;
}
else{
return false;
}
}
}
return false;
}
public void setBlocked(boolean bl){
_blocked = bl;
}
public boolean isBlocked(){
return _blocked;
}
public boolean isBlockedFromRight(){
return _blockedFromRight;
}
public void setHp(int hp){
_hp = hp;
}
public int getHp(){
return _hp;
}
public void setMaxHp(int max){
_maxHp = max;
}
public int getMaxHp(){
return _maxHp;
}
void blockEffect(){
_xBlockOffset -= _blockSpeed;
double y = Math.toRadians(_xBlockOffset);
if(getX()>50 && getX()<555){
if(isBlockedFromRight()){
_animator.translate(Math.sin(y)*_blockStrength, 0);
}else{
_animator.translate(-Math.sin(y)*_blockStrength, 0);
}
}
_blockDelayTimer -= Config.TIMER_DIF;
if(_blockDelayTimer<=0){
setBlocked(false);
_blockDelayTimer = _blockDelay;
_xBlockOffset = 100;
}
}
}
同时,在Enemy类的update方法中,我们判断如果对象当前的状态是block,我们就设置block动画。
public class Enemy extends ActorObject{
private Animator _animator;
private Player _player;
private double _speed = 1.5;
@Override
public void update(Graphics2D g){
if(!this.isDead()){
_animator.show(g);
super.update(g);
if(!isDead()){
if(isBlocked()){
getAnimator().setAnimation("block");
}
else{
if(!getAnimator().isPlaying("idle")
&& !getAnimator().isPlaying("block")
){
getAnimator().setAnimation("idle");
}
}
followPath();
if(this.isHit(_player)){
this.takeDamage(_player);
}
}
}
}
如果您迷路了,请参考完整源码: