从零开始手写mmo游戏从框架到爆炸(二十)— 战斗系统一

导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客     

规则       

        我们现在设计并尝试开发战斗系统。战斗系统我们先设定几个规则

        1、多人对多人:英雄可以携带宝宝,面对的野怪也可以是成群的,故要设计成多人对多人的战斗引擎;

        2、速度快的先出手:这点应该没有异议,根据速度来判定出手间隔,但是这里要有一个数据转换的问题,比如并不是速度100的就比速度50的出手速度快一倍,应该有一个计算公式来根据英雄的速度属性计算出手间隔。

        3、急速打架:考虑到不能在后台慢慢的让两方打,这样耗时又费机器,用户也等不了这么久,所以最好的方法是在后台迅速的计算出结果,然后把打斗的过程返回给前端,前端再进行展示。笔者玩了一些小游戏也是这么做的。

       4、要有底线:如果双方攻击力都不足,或者奶量都十足,那么很有可能永远打不完,就死循环要导致内存溢出了故而应该设定一个最长打斗时间,如果到了最长打斗时间还没有分出胜负就是平局。

       5、技能的问题:技能的问题很复杂,有光环型的技能,有召唤型的技能,有单伤,都群伤,有被动,有主动,所以目前我们暂时先不考虑技能,先让咱们的游戏可以动起来,可以打怪,然后掉落宝物。之后我们再根据技能的设定重新来完善战斗系统。

       基于以上几点规则,我们先尝试写几个demo来模拟打斗的场面。

代码       

      首先我们创建测试的英雄类,简化战斗模型,只有姓名、攻击、生命值、速度这四个属性。并且增加一个攻击方法。

Hero.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hero {

    String name = "hero";

    int attack =  10;

    int speed = 10;

    int hp = 100;

    public Hero(String name) {
        this.name = name;
    }

    /***
     * 模拟攻击
     * @param hero
     */
    public void attack(Hero hero) {
        if(hero.getHp() > 0) {
            hero.setHp(hero.getHp() - getAttack());
            System.out.println(getName() + "攻击," + hero.getName() + "生命值减少" + getAttack());
        }
    }
}

创建一个动作接口,用于封装攻击的数据- Action

public interface Action {

    void run();

    /***
     * 是否继续
     * @return
     */
    boolean checkContinue();


    int speed();
}

先实现1V1- BaseAttack

public class BaseAttack implements Action {

    private Hero heroA;

    private Hero heroB;

    public BaseAttack(Hero heroA, Hero heroB) {
        this.heroA = heroA;
        this.heroB = heroB;
    }

    @Override
    public void run() {
        heroA.attack(heroB);
    }

    @Override
    public boolean checkContinue() {
        return heroA.getHp()>0;
    }

    @Override
    public int speed() {
        return heroA.getSpeed();
    }
}

1v1的打斗服务 - BattleOneToOne

public class BattleOneToOne {

    // 正式战斗是以秒为单位,但是我们不可能真的按照秒来进行战斗,会大大的影响服务器的性能,所以我们应该要做的就是缩短打架的过程把结果返回给客户端即可,并把实际打斗时间告诉给客户端,然后客户端再进行时延的播放即可

    // 设计一个队列,在
    private LinkedList<Action> actions = new LinkedList<>();

    private int addAction(Action action){
        actions.offer(action);
        return actions.size();
    }

    public void fight(Hero A,Hero B) throws InterruptedException {
        // 根据速度放入队列
        if(A.getSpeed() > B.getSpeed()){
            addAction(new BaseAttack(A,B));
            addAction(new BaseAttack(B,A));
        }else{
            addAction(new BaseAttack(B,A));
            addAction(new BaseAttack(A,B));
        }

        while(A.getHp() > 0 && B.getHp() > 0) {
            Action pop = actions.pop();
            pop.run();
            // 再放进去
            if (pop.checkContinue()) {
                addAction(pop);
            }
        }

        if(A.getHp() > 0) {
            System.out.println(A.getName() + "获胜:" + A.getHp());
        }else{
            System.out.println(B.getName() + "获胜:" + B.getHp());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        BattleOneToOne battleOneToOne = new BattleOneToOne();

        Hero A = new Hero("刘备");
        Hero B = new Hero("关羽");
        B.setSpeed(20);
        B.setAttack(20);
        battleOneToOne.fight(A,B);
    }

}

 效果如下:

关羽攻击,刘备生命值减少20
刘备攻击,关羽生命值减少10
关羽攻击,刘备生命值减少20
刘备攻击,关羽生命值减少10
关羽攻击,刘备生命值减少20
刘备攻击,关羽生命值减少10
关羽攻击,刘备生命值减少20
刘备攻击,关羽生命值减少10
关羽攻击,刘备生命值减少20
关羽获胜:60

我们再来写一个多人对战的- GroupAttack

public class GroupAttack implements Action {

    private Hero heroA;

    private List<Hero> defenceList;

    public GroupAttack(Hero heroA, List<Hero> defenceList) {
        this.heroA = heroA;
        this.defenceList = defenceList;
    }

    @Override
    public boolean run() {
        // 自己血量少于0 返回
        if(heroA.getHp() > 0) {        // 遍历并找到血量最少的攻击
            defenceList = defenceList.stream().filter(e -> e.getHp() > 0).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(defenceList)) {
                defenceList.sort(Comparator.comparing(Hero::getHp));
                heroA.attack(defenceList.get(0));
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean checkContinue() {
        return heroA.getHp() > 0 && defenceList.stream().anyMatch(e -> e.getHp() > 0);
    }

    @Override
    public int speed() {
        return heroA.getSpeed();
    }
}

BattleManyToMany

public class BattleManyToMany {

    // 队列不变
    private LinkedList<Action> actions = new LinkedList<>();

    private int addAction(Action action){
        actions.offer(action);
        return actions.size();
    }

    public void fight(List<Hero> listA, List<Hero> listB) throws InterruptedException {
        // 先放入listA
        listA.sort(Comparator.comparing(Hero::getSpeed).reversed());
        for (int i = 0; i < listA.size(); i++) {
            addAction(new GroupAttack(listA.get(i),listB));
        }

        // 再放入listB
        listB.sort(Comparator.comparing(Hero::getSpeed).reversed());
        for (int i = 0; i < listB.size(); i++) {
            addAction(new GroupAttack(listB.get(i),listA));
        }

        // 如果A集合和B集合的生命值都还大于0

        while(listA.stream().anyMatch(e -> e.getHp() > 0) && listB.stream().anyMatch(e -> e.getHp() > 0)) {
            Action pop = actions.pop();
            boolean run = pop.run();
            if(run) {
                // 再放进去
                if (pop.checkContinue()) {
                    addAction(pop);
                }
                // 打印
                System.out.println("A集团 :" + JSON.toJSONString(listA));
                System.out.println("B集团 :" + JSON.toJSONString(listB));
            }

        }

        if(listA.stream().anyMatch(e -> e.getHp() > 0)) {
            System.out.println("A集团 获胜:" + JSON.toJSONString(listA));
        }else{
            System.out.println("B集团 获胜:" + JSON.toJSONString(listB));
        }
    }

    public static void main(String[] args) throws InterruptedException {
        BattleManyToMany battle = new BattleManyToMany();

        Hero A = new Hero("A");
        Hero B = new Hero("B");
        B.setSpeed(20);
        B.setAttack(20);

        Hero C = new Hero("C");
        C.setSpeed(5);
        C.setAttack(20);

        Hero D = new Hero("D");
        D.setSpeed(10);
        D.setAttack(15);
        battle.fight(Arrays.asList(A,C),Arrays.asList(B,D));
    }

}

运行结果如下:

A攻击,B生命值减少10
A集团 :[{"attack":10,"hp":100,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":90,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
C攻击,B生命值减少20
A集团 :[{"attack":10,"hp":100,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":70,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
B攻击,A生命值减少20
A集团 :[{"attack":10,"hp":80,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":70,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
D攻击,A生命值减少15
A集团 :[{"attack":10,"hp":65,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":70,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
A攻击,B生命值减少10
A集团 :[{"attack":10,"hp":65,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":60,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
C攻击,B生命值减少20
A集团 :[{"attack":10,"hp":65,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":40,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
B攻击,A生命值减少20
A集团 :[{"attack":10,"hp":45,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":40,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
D攻击,A生命值减少15
A集团 :[{"attack":10,"hp":30,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":40,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
A攻击,B生命值减少10
A集团 :[{"attack":10,"hp":30,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":30,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
C攻击,B生命值减少20
A集团 :[{"attack":10,"hp":30,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":10,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
B攻击,A生命值减少20
A集团 :[{"attack":10,"hp":10,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":10,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
D攻击,A生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":10,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
C攻击,B生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":100,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
D攻击,C生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":85,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":100,"name":"D","speed":10}]
C攻击,D生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":85,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":80,"name":"D","speed":10}]
D攻击,C生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":70,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":80,"name":"D","speed":10}]
C攻击,D生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":70,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":60,"name":"D","speed":10}]
D攻击,C生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":55,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":60,"name":"D","speed":10}]
C攻击,D生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":55,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":40,"name":"D","speed":10}]
D攻击,C生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":40,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":40,"name":"D","speed":10}]
C攻击,D生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":40,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":20,"name":"D","speed":10}]
D攻击,C生命值减少15
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":25,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":20,"name":"D","speed":10}]
C攻击,D生命值减少20
A集团 :[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":25,"name":"C","speed":5}]
B集团 :[{"attack":20,"hp":-10,"name":"B","speed":20},{"attack":15,"hp":0,"name":"D","speed":10}]
A集团 获胜:[{"attack":10,"hp":-5,"name":"A","speed":10},{"attack":20,"hp":25,"name":"C","speed":5}]

Process finished with exit code 0

全部源码详见:

gitee : eternity-online: 多人在线mmo游戏 - Gitee.com

分支:step-11

请各位帅哥靓女帮忙去gitee上点个星星,谢谢!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值