基于PF规则的CRPG制作尝试(十)动态先攻检定

基于PF规则的CRPG制作尝试(十)动态先攻检定

在之前的先攻检定中,我直接默认场景中只有两个角色进入了战斗,因此使用了枚举状态enum,但实际的战斗中并不一定是这样的。在我看来,实际战斗的游戏回转应是这样的:
1.查找目前场景中进入战斗的全部角色并存入动态数组中。
2.根据角色的名字查找gameobject,根据gameobject的tag,来getcomponent它的ActorController类或MonsterController中的先攻检定函数并执行。将先攻检定值保存到另一个动态数组中。(其实用二维动态数组更好,但我太菜了)
3.将先攻检定进行排序,并根据排序的变动改变角色名数组的顺序。
4.游戏回转的实现。
以下是具体实现

一、查找目前场景中进入战斗的全部角色并存入动态数组

这一步并不复杂,使用FindObjectsOfTypeAll方法,查找当前场景中active,且tag为“player”或“monster”的gameobject,最后将以上物体保存到名为character的数组中。
具体代码如下:

public int actornum = 0;
ArrayList character = new ArrayList();
void Start()
    {
        var all = Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[];
        foreach (var item in all)
        {
            if (item.scene.isLoaded && (item.tag == "player" || item.tag == "monster") && item.activeInHierarchy == true)
            {
                actornum++;
                character.Add(item.name);
            }
        }
    }

二、获取并执行以上gameobject的先攻检定函数并存入数组

没什么可说的,直接上代码:

ArrayList namelist = new ArrayList();
ArrayList inilist = new ArrayList();
public void Inicheck()
    {
        for (int i = 0; i < actornum ; i++)
        {
            GameObject a = GameObject.Find(character[i].ToString());
            if (a.tag == "player")
            {
                namelist.Add(a.name);
                inilist.Add(a.GetComponent<ActorController>().Iniroll());
            }
            else if (a.tag == "monster")
            {
                namelist.Add(a.name);
                inilist.Add(a.GetComponent<MonsterController>().Iniroll());               
            }
        }
    }

三、将先攻检定进行排序,并根据排序的变动改变角色名数组的顺序

使用了冒泡排序,当所有先攻检定的值都不相等的时候就能很简单的进行排序,但当两个角色的先攻检定相同时,就需要比较其先攻修正,如果先攻修正再相同的话就需要投100面骰比较结果(投骰子的具体方法请看第七节),将角色名数组的顺序根据先攻值数组的变动同时地进行变动。

void Start()
    {
        Inicheck();
    }
    public void Inicheck()
    {
        //获取并保存角色名数组,roll先攻并保存进先攻值数组
        for (int i = 0; i < actornum ; i++)
        {
            GameObject a = GameObject.Find(character[i].ToString());
            if (a.tag == "player")
            {
                namelist.Add(a.name);
                inilist.Add(a.GetComponent<ActorController>().Iniroll());
            }
            else if (a.tag == "monster")
            {
                namelist.Add(a.name);
                inilist.Add(a.GetComponent<MonsterController>().Iniroll());               
            }
        }
        //冒泡排序,角色名数组根据先攻值数组顺序的调整而调整顺序
        for (int i = 0; i < actornum - 1; i++)
        {
            for (int j = 0; j < actornum - 1 - i; j++)
            {
                if ((int)inilist[j] < (int)inilist[j + 1])
                {
                    object m = inilist[j];
                    object n = namelist[j];
                    inilist[j] = inilist[j + 1];
                    namelist[j] = namelist[j + 1];
                    inilist[j + 1] = m;
                    namelist[j + 1] = n;
                    print("按大小进行了一次排序");
                }
                //如果先攻值相同,比较先攻修正
                else if ((int)inilist[j] == (int)inilist[j + 1])
                {
                    int inicom1 = 0, inicom2 = 0;
                    GameObject a = GameObject.Find(namelist[i].ToString());
                    GameObject b = GameObject.Find(namelist[i + 1].ToString());
                    if (a.tag == "player")
                    {
                        inicom1 = a.GetComponent<ActorData>().INI;
                    }
                    else if (a.tag == "monster")
                    {
                        inicom1 = a.GetComponent<MonsterData>().INI;
                    }
                    if (b.tag == "player")
                    {
                        inicom2 = b.GetComponent<ActorData>().INI;
                    }
                    else if (b.tag == "monster")
                    {
                        inicom2 = b.GetComponent<MonsterData>().INI;
                    }
                    if (inicom1 < inicom2)
                    {
                        object m = inilist[j];
                        object n = namelist[j];
                        inilist[j] = inilist[j + 1];
                        namelist[j] = namelist[j + 1];
                        inilist[j + 1] = m;
                        namelist[j + 1] = n;
                        print("先攻相同,比较先攻修正,改变了顺序");
                    }
                    //如果先攻修正也相同,那就rd100比较结果
                    else if (inicom1 == inicom2)
                    {
                        if (Inicheckloop() == false)
                        {
                            object m = inilist[j];
                            object n = namelist[j];
                            inilist[j] = inilist[j + 1];
                            namelist[j] = namelist[j + 1];
                            inilist[j + 1] = m;
                            namelist[j + 1] = n;
                            print("先攻修正相同,进行roll点,改变了顺序");
                        }
                        else
                            print("先攻修正相同,进行roll点,未改变顺序");
                    }
                    else
                        print("先攻相同,比较先攻修正,未改变顺序");
                }
            }
        }
        PrintArray(namelist);
        PrintArray(inilist);
    }
    //返回true,意味着不需要改变顺序,返回false,意味着需要改变顺序
    public bool Inicheckloop()
    {
        int check1 = Dice100();
        int check2 = Dice100();
        if (check1 < check2)
        {
            return false;
        }
        else if (check1 == check2)
        {
            //如果还想等,就再来一遍
            return Inicheckloop();
        }
        else
            return true;
    }
    //打印数组
    void PrintArray(ArrayList A)
    {
        string S = "[";
        for (int i = 0; i < A.Count; i++)
        {
            S += A[i].ToString();
            if (i != A.Count - 1)
            {
                S += ',';
            }
        }
        S += "]";
        print(S);
    }

四、实现游戏回转

之前我使用了状态枚举enum来实现游戏回转,但enum多用于表达稳定的分类标准。几乎没有任何改变的可能或者趋势。因此当我想要动态设置状态来实现游戏回转时,我发现使用enum是不恰当的。因此我最后使用最笨的方法,public了一个string类型的gamestate来表示游戏状态。同时public了一个int类型的gsNo来表达游戏状态的序号。

    public string gamestate ;
    public int gsNo = 0;
    void Start()
    {
        //开始的时候gamestate为ORD,此时gsNo为0
        gamestate = "ORD";
    }
     void Update()
    {
        //print(actornum);
        //点击Q切换状态,gamestate变为下一个角色名
        if (Input.GetKeyDown(KeyCode.Q))
        {
            if (gsNo < actornum)
            {
                gsNo++;
                gamestate = namelist[gsNo - 1].ToString();
            }
            //到最后一个角色时再按Q,回到第一个角色的状态
            else  
            {
                gsNo = 1;
                gamestate = namelist[gsNo - 1].ToString();
            }
        }
        //按P回到ORD状态
        if (Input.GetKeyDown(KeyCode.P))
        {
            gsNo = 0;
            gamestate = "ORD";
        }
    }

然后在ActorController或MonsterController中用gm.gamestate == gameObject.name或gm.gamestate==“ORD”来表示游戏状态相关的逻辑判定。

以上

写一个简易 CRPG 是一项很复杂的任务,需要设计游戏世界、角色、道具、怪物等众多要素,并编写相关的代码来实现游戏逻辑。下面是一个简单的示例,只包含了一些基本的游戏元素和逻辑: ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; // 定义角色结构体 struct Player { string name; int hp; int mp; int level; int exp; int gold; }; // 定义怪物结构体 struct Monster { string name; int hp; int attack; int defense; int exp; int gold; }; // 初始化角色 void initPlayer(Player& player) { player.name = "Hero"; player.hp = 100; player.mp = 50; player.level = 1; player.exp = 0; player.gold = 0; } // 显示角色状态 void showPlayer(Player& player) { cout << "Name: " << player.name << endl; cout << "Level: " << player.level << endl; cout << "HP: " << player.hp << endl; cout << "MP: " << player.mp << endl; cout << "Exp: " << player.exp << endl; cout << "Gold: " << player.gold << endl; } // 初始化怪物 void initMonster(Monster& monster) { monster.name = "Slime"; monster.hp = 50; monster.attack = 10; monster.defense = 5; monster.exp = 20; monster.gold = 10; } // 显示怪物状态 void showMonster(Monster& monster) { cout << "Name: " << monster.name << endl; cout << "HP: " << monster.hp << endl; cout << "Attack: " << monster.attack << endl; cout << "Defense: " << monster.defense << endl; cout << "Exp: " << monster.exp << endl; cout << "Gold: " << monster.gold << endl; } // 角色攻击怪物 void playerAttack(Player& player, Monster& monster) { int damage = player.level * 10 + rand() % 10 - monster.defense; if (damage < 0) damage = 0; monster.hp -= damage; cout << player.name << " deals " << damage << " damage to " << monster.name << endl; if (monster.hp <= 0) { cout << monster.name << " is defeated!" << endl; player.exp += monster.exp; player.gold += monster.gold; if (player.exp >= player.level * 100) { player.exp -= player.level * 100; player.level++; cout << player.name << " levels up!" << endl; } initMonster(monster); } } // 怪物攻击角色 void monsterAttack(Player& player, Monster& monster) { int damage = monster.attack - player.level * 2; if (damage < 0) damage = 0; player.hp -= damage; cout << monster.name << " deals " << damage << " damage to " << player.name << endl; if (player.hp <= 0) { cout << player.name << " is defeated!" << endl; exit(0); } } // 主函数 int main() { srand(time(NULL)); Player player; Monster monster; initPlayer(player); initMonster(monster); while (true) { showPlayer(player); showMonster(monster); cout << "1. Attack" << endl; cout << "2. Run away" << endl; int choice; cin >> choice; if (choice == 1) { playerAttack(player, monster); monsterAttack(player, monster); } else if (choice == 2) { cout << "You run away!" << endl; initMonster(monster); } } return 0; } ``` 这个简易 CRPG 的逻辑很简单,玩家需要与怪物战斗,获得经验和金币,提升自己的等级。玩家每次攻击怪物或者被怪物攻击时,都会有一定的随机因素,使得游戏更加有趣。这只是一个简单的示例,实际上一个完整的 CRPG 需要更加复杂的设计和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值