[开发者心得] [开发实战]教你使用单脚本制作打怪游戏

  [复制链接]
2355 |10
森林鹿 发表于 2023-12-21 16:40:26 | 显示全部楼层 |阅读模式
简介
现在论坛上有很多很牛的单脚本,而且都特别通用。今天我们要聊的是,怎么把这些脚本集合起来,搭建出一个属于你自己的游戏框架。
这篇文章的主旨是教你如何构建一个数值模拟的核心框架,让你更容易做出数值模拟游戏。我们会用到一些工具,比如[怪物编辑器][动效编辑器][属性管理器],还有[血条系统]。这些系统的基本用法就不多说了,咱们主要关注它们的“高级玩法”。

详细说明

1. 装上怪物和玩家的“血条”
血条系统默认给玩家已经装备好了血条。所以我们的任务是给怪物也来一个。怪物默认是没血条的,但是它们会触发怪物生成的事件。所以,我们只需要监听这个事件,然后给生成的怪物加上血条就行了。代码?嗯,就几行搞定:
//怪物生成事件
MobsDef.onBorn.add((EnemyEntityCom) => {
    //异步获取怪物的配置
    MobsDef.getCfgAsync(EnemyEntityCom.cfgId).then((value) => {
        //调用血条系统的方法给怪物添加上血条
        MyClearHP.addMyClearHPForChar(EnemyEntityCom.char, { charName: value.backdes, curHP: value.Hp, maxHP: value.Hp });
    });
});

2.怪物死亡时掉落经验
由于怪物编辑器中的怪物使用的是对象池管理,所以我们在怪物死亡时还需要对血条进行处理,不然可能会导致性能问题。另外可以在此监听中添加怪物死亡后给予玩家的一些奖励。

// 怪物死亡事件
MyClearMobs.onDie.add((EnemyEntityCom, killerId) => {
    //异步获取怪物的配置
    MyClearMobs.getCfgAsync(EnemyEntityCom.cfgId).then((value) => {
        const player = Player.getPlayer(killerId);
        const cfg = JSON.parse(value.ExtraUserData);
        //给击败该怪物的玩家增加经验值
        if (cfg && player) {
            MyClearAttrGo.setAttrValue("Exp",MyClearAttrGo.getAttrValue("Exp",player.userId)+cfg.Exp,player.userId);
        }
        //怪物死亡后清理掉其身上的血条
        MyClearHP.removeMyClearHPForChar(EnemyEntityCom.char.gameObjectId);
    });
});

3.怪物攻击玩家造成伤害
怪物现在还不能给玩家造成伤害,但这很简单,只需要监听怪物命中玩家的事件就可以了。下面就是几行代码的事,而且你还可以在这里定义怎样的伤害公式!
//攻击玩家事件
MobsDef.onHitPlayer_server.add((EnemyEntityCom, playerId, damage) => {
    const player = Player.getPlayer(playerId);
    //调用血条系统给被攻击的玩家执行扣血操作
    MyClearHP.ServerChangeCharCurHP(EnemyEntityCom.char.gameObjectId, player.userId, -damage);
});

4.玩家攻击怪物造成伤害
当然啦,不能让怪物一直打玩家,玩家也要有反击的机会!动效编辑器提供了处理伤害的事件,该事件在判定盒判定成功后发送。我们可以监听这个事件来实现给怪物造成伤害的功能。
// 服务器上玩家对角色造成伤害事件
MyClearAct.ServerDamageChar.push((AttackerID: string, VictimID: string, damage: number) => {
    //获取怪物配置信息
    const obj = GameObject.findGameObjectById(VictimID);
    const EnemyCom = MobsDef.tryGetEnemyCom(obj);

    if (EnemyCom) {
        //调用怪物系统中给怪物造成伤害的方法
        MobsDef.tryHurtEnemy(obj, Player.getPlayer(AttackerID), damage);
    }
});

怪物受到伤害是实现了,但我们还看不到怪物当前的血量。这是因为我们还没联动到血条系统。通过监听怪物受伤的事件,我们可以更改怪物的血量。
// 怪物受到伤害事件
MobsDef.onTakeDamage.add((EnemyEntityCom, attackerPlayerId, damage) => {
    const player = Player.getPlayer(attackerPlayerId);
    //调用血条系统更改怪物的血量
    MyClearHP.ServerChangeCharCurHP(player.userId, EnemyEntityCom.char.gameObjectId, -damage);
});

其他功能
至此,我们已经完成了最核心的打怪功能。你还可以继续扩展和完善你的游戏框架。比如,监听怪物死亡的事件,让怪物死亡时掉落一些东西给玩家,增加一些正反馈。还有很多其他的扩展,期待大家一起来搞事情!

工程下载
我制作了一个小 demo,已经把上述功能都实现了。大家可以直接下载这个 demo 进行游戏扩展。欢迎大家后续来交作业,看看你们能做出一个什么样的游戏。
打怪demo.zip (329.06 KB, 下载次数: 205)
回复

使用道具 举报

睡到自然醒 发表于 2023-12-22 09:09:20 | 显示全部楼层
酱紫帅?
回复

使用道具 举报

syef 发表于 2024-1-5 11:27:55 | 显示全部楼层
大师,我想请问一下028版本运行,怪物打不死是什么原因呢
回复

使用道具 举报

森林鹿楼主 发表于 2024-1-5 15:41:48 | 显示全部楼层
syef 发表于 2024-1-5 11:27
大师,我想请问一下028版本运行,怪物打不死是什么原因呢

已经更新了~
主要是怪物编辑器有一些判断,demo也同步更新了~
重新下载试试吧
回复

使用道具 举报

天启 发表于 2024-1-17 21:08:48 | 显示全部楼层
demo是不是过时了
回复

使用道具 举报

天启 发表于 2024-1-24 20:53:33 | 显示全部楼层
myclearMobs和myclearHP有严重的代码逻辑错误,生成怪在对象池取也会再次加血条,导致一个怪后期会很多血条
回复

使用道具 举报

森林鹿楼主 发表于 2024-1-25 13:39:22 | 显示全部楼层
天启 发表于 2024-1-17 21:08
demo是不是过时了

现在已经更新啦~
回复

使用道具 举报

森林鹿楼主 发表于 2024-1-25 13:39:47 | 显示全部楼层
天启 发表于 2024-1-24 20:53
myclearMobs和myclearHP有严重的代码逻辑错误,生成怪在对象池取也会再次加血条,导致一个怪后期会很多血条 ...

demo本身是有处理哒~
在贴子里现在也更新了处理方法啦~
回复

使用道具 举报

躲猫猫作者_思想的鱼 发表于 2024-1-30 17:01:04 | 显示全部楼层
本帖最后由 躲猫猫作者_思想的鱼 于 2024-2-6 14:14 编辑

玩家如果设置成布娃娃状态,附近的怪物依然是会播放攻击动作。是否需要在执行技能那里做个判断的。



    private attackLogic() {

        let targetChar = this.getTargetChar()

        if (targetChar == null) {
            this.curState = EnemyState.Idle;
            if (this.curAttackAni != null) this.curAttackAni.stop();
            this.curAttackAni = null;
            return;
        }
        if(targetChar.ragdollEnabled) {
            return;
        }


增加targetChar.ragdollEnabled可以在玩家角色死亡后,怪物不会继续攻击
回复

使用道具 举报

躲猫猫作者_思想的鱼 发表于 2024-1-31 10:05:55 | 显示全部楼层
角色吸引仇恨后,然后站立不动有概率走到人旁边就静止不动了。然后角色移动,怪物才会发起攻击。如果此时玩家不移动,但是执行act就可以无伤打怪了。
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表