下载 App

《物种大陆》开发日志Day6

修改于10/169 浏览综合
2026.10.6 晴
今天天气晴朗,起个早,锻炼身体,先去爬了个400多米的紫金山,然后中午回来开始写代码。
今天的代码是重点是生成随机地块。要求是一共60个格子,一行10个,一共6行。分别生成不同的地形,地形包括:"草原", "森林", "湿地", "山脉", "沙漠", "雪地", "海洋",其中海洋为边缘修饰,不参与计算。其他6种地形,根据一定比例生成。其中60个地块,取30-45个地块作为可用的,其他都是海洋。这45个地块要从中心地带连续,随机生成。每次都生成不同的地形。先思考了2个小时,也没想到好的办法,于是就把要求描述好,问DEEPSEEK,5秒不到,DEEPSEEK就给写好了,虽然方法有一些问题,但是经过几轮调试,测试后,还是完成了这个功能。分享下代码如下:
TapTap
public static List<DiKuai> GetRandomDiKuais(int count)
    {
        // 参数校验:count 限制在 30-40 之间
        if (count < 30) count = 30;
        if (count > 40) count = 40;
        const int rows = 6;
        const int cols = 10;
        const int total = rows * cols; // 60
        // 初始化 60 个格子,默认全部为海洋
        var list = new List<DiKuai>(total);
        for (int i = 1; i <= total; i++)
        {
            DiKuai dk = new DiKuai();
            dk.id = i;
            dk.type = DiKuaiType.HaiYang;
            dk.pic = DiKuai.GetDiKuaiPicName(dk.type);
            dk.name = DiKuai.GetDiKuaiName(dk.type);
            dk.maxZhiWuXiShu = 1000000;
            dk.curZhiWuXiShu = 1000000;
            list.Add(dk);
        }
        // 通过 id 快速索引
        var map = new DiKuai[total + 1]; // 1-based
        foreach (var d in list) map[d.id] = d;
        // 序号 -> (行, 列),行列从 0 开始
        Func<int, (int r, int c)> toRC = id => ((id - 1) / cols, (id - 1) % cols);
        // (行, 列) -> 序号
        Func<int, int, int> toId = (r, c) => r * cols + c + 1;
        var rand = new System.Random();
        // 随机抽取陆地类型
        // 权重大致:草原/森林/湿地 最大,山脉第二,沙漠/雪地最少
        Func<int> randLandType = () =>
        {
            // 权重表:索引 0-5 对应 草原/森林/湿地/山脉/沙漠/雪地
            // 权重和 = 100,可直接当作百分比
            int[] weights = { 35, 35, 10, 10, 5, 5 };
            int totalWeight = 0;
            for (int i = 0; i < weights.Length; i++) totalWeight += weights[i]; // = 100
            int r = rand.Next(totalWeight);
            int acc = 0;
            for (int i = 0; i < weights.Length; i++)
            {
                acc += weights[i];
                if (r < acc) return i; // 返回 0-5,正好对应 DiKuaiType
            }
            return 0; // 兜底(草原)
        };
        // 把某个格子设为陆地,并完善所有字段
        Action<int> setLand = id =>
        {
            var dk = map[id];
            int landType = randLandType();
            DiKuaiType type = (DiKuaiType)landType;
            dk.type = type;
            dk.pic = DiKuai.GetDiKuaiPicName(dk.type);
            dk.name = DiKuai.GetDiKuaiName(dk.type);
            dk.maxZhiWuXiShu = 1000000;   // 陆地植被系数上限,可按需调整
            dk.curZhiWuXiShu = 1000000;   // 陆地初始植被系数,可按需调整
        };
        // 最中间的 4 个格子:25, 26, 35, 36 设为陆地
        var landSet = new HashSet<int> { 25, 26, 35, 36 };
        foreach (var id in landSet) setLand(id);
        // 从已有陆地向外随机扩展,直到陆地数量达到 count
        // 候选边界:与陆地相邻的海洋格子
        var frontier = new HashSet<int>();
        Action<int> addNeighbors = id =>
        {
            var (r, c) = toRC(id);
            int[] dr = { -1, 1, 0, 0 };
            int[] dc = { 0, 0, -1, 1 };
            for (int k = 0; k < 4; k++)
            {
                int nr = r + dr[k], nc = c + dc[k];
                if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
                int nid = toId(nr, nc);
                if (map[nid].type == DiKuaiType.HaiYang && !frontier.Contains(nid))
                    frontier.Add(nid);
            }
        };
        foreach (var id in landSet) addNeighbors(id);
        // 记录陆地扩展的范围,用于平衡方向(避免偏向某一侧)
        // 用于统计左右上下扩展的格子数
        int extendLeft = 0, extendRight = 0, extendUp = 0, extendDown = 0;
        // 中心点(用于判断扩展方向)
        const int centerCol = (cols - 1) / 2;         // 4
        const int centerRow = (rows - 1) / 2;         // 2
        while (landSet.Count < count && frontier.Count > 0)
        {
            // 按照方向偏差加权的随机挑选:往扩展较少的方向加权更大
            // 计算候选格子的方向权重
            var candidates = frontier.ToList();
            // 计算左右上下的不平衡度
            int diffLR = extendRight - extendLeft;    // >0 表示偏右
            int diffUD = extendDown - extendUp;       // >0 表示偏下
            // 给每个候选计算权重(越大越容易被选中)
            var weights = new int[candidates.Count];
            int totalW = 0;
            for (int i = 0; i < candidates.Count; i++)
            {
                int cid = candidates[i];
                var (r, c) = toRC(cid);
                int w = 10; // 基础权重
                // 如果向左扩展偏少,则左侧格子权重大
                if (c < centerCol) w += Math.Max(0, diffLR) * 3;
                // 如果向右扩展偏少,则右侧格子权重大
                if (c > centerCol) w += Math.Max(0, -diffLR) * 3;
                // 如果向上扩展偏少,则上方格子权重大
                if (r < centerRow) w += Math.Max(0, diffUD) * 3;
                // 如果向下扩展偏少,则下方格子权重大
                if (r > centerRow) w += Math.Max(0, -diffUD) * 3;
                weights[i] = w;
                totalW += w;
            }
            // 加权随机挑选
            int rnd = rand.Next(totalW);
            int acc2 = 0;
            int pickedIndex = 0;
            for (int i = 0; i < candidates.Count; i++)
            {
                acc2 += weights[i];
                if (rnd < acc2) { pickedIndex = i; break; }
            }
            int picked = candidates[pickedIndex];
            frontier.Remove(picked);
            // 统计方向扩展
            var (pr, pc) = toRC(picked);
            if (pc < centerCol) extendLeft++;
            else if (pc > centerCol) extendRight++;
            if (pr < centerRow) extendUp++;
            else if (pr > centerRow) extendDown++;
            setLand(picked);
            landSet.Add(picked);
            addNeighbors(picked);
        }
        return list;
    }
【童谣镇】聚光灯第二次开发日志截图
【童谣镇】聚光灯第二次开发日志
开发进度: 美术 1、主角人物立绘已细化完成 2、所有NPC的QQ人形象与呼吸动画已设计完成 3、大部分UI界面已设计完成 4、面包房建模与树屋建模以及基础房屋、路灯、树木模型已完成。 5、制作过场动效,制作通用动效材质ing 6、广场资产替换、永续桥和植被的资产替换、房屋资产替换,河流制作 7、学校模型的材质完成 8、石墩子、小道具模型制作ing 9、NPC正比胸像绘制ing 策划 1、任务系统
16 赞
10 回复
00:34
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!截图
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!
- 人类曾因掌握元素合成技术而一度辉煌,又因滥用元素能量而逐渐从内里衰败。 - 30世纪80年代。社会文化充斥着激进乐观主义与庞大机械美学,在这里,污染和能源共生,幸福与痛苦并存。官方广播和宣传画里依旧在宣扬“科学将战胜一切”、“元素能量将再造新农田”的口号,而世界主城却已经因为污染过度而濒临崩溃、空间挤压严重。为了寻找新的生存空间与无污染能源,官方启动了“重构拓荒计划”。 - 玩家将作为前线拓展
18 赞
6 回复
00:07
雨天決行 开发者日志02-人工智能的自我修养截图
雨天決行 开发者日志02-人工智能的自我修养
又和大家见面啦!第二篇日志,说实话一开始不知道该怎么编排,但团队里惊喜的成果越来越多,我们已经迫不及待把更新的内容端上来给大家啦!那么事不宜迟,快来看看都有什么新情报吧ദ്ദി˶ー̀֊ー́ )✧ 一.美术(重磅升级) 以主美小为的生命力作为燃料(bushi)本次美术组取得了大进程!首先是各个ui界面的优化和细化,上次大家看到时还只是初具雏形的草稿,现在大多都完整起来了哦! 同时,随着配色的补全,手
43 赞
39 回复
00:30
《失心》游戏开发者日志01|游戏UI迭代及实机演示截图
《失心》游戏开发者日志01|游戏UI迭代及实机演示
进入《失心》之前,玩家首先看到的是我们工作室 UNLOOK 的标识。我们将原来的标识转成 SVG,并让其中的红色瞳点转动、观察,再逐步显露完整字形,希望这个短暂的开场能带出一点好奇和不安。 这次《失心》的开局 UI,我们围绕小灵通(因为游戏的主要交互道具就是小灵通)做了几轮调整,希望玩家从打开游戏开始,就能感受到故事里的年代和气氛(故事年代背景为2000s)。 早期版本先确定了一个方向:把菜单放进
15 赞
10 回复
开发日志01截图
开发日志01
“涌现” 1.读作 ‌yǒng xiàn‌,意思是(人或事物)在同一时期大量出现,或者突然出现。‌‌ 2.科学含义‌:在复杂性科学里,涌现指大量简单个体相互作用后,整体产生了单个个体不具备的新特性,也就是“整体大于部分之和”,比如蚁群表现出的智慧、人工智能大模型的推理能力。 刚看见这个题目的时候,有一点点懵。看了词语解释之后,才有了一点想法。 考虑到时间还有个人开发的能力限制,目前决定做一个纯粹的
2 赞
开发者日志03截图
开发者日志03
大家好,第三篇开发日志来了。先公布一件事:我们的游戏正式定名为《尸涌》!这是一款以丧尸战斗和村庄探索为核心的第一人称射击游戏。这次也把最近几轮的战斗、成长、界面和探索进展一起整理出来。 故事从一位旅行者的失踪开始。主角作为她的好友,沿着她的旅行轨迹来到这个村庄,寻找她留下的线索,却逐渐发现村民与城里的制药公司之间,藏着秘密人体实验。村庄里的丧尸灾变究竟是怎么发生的?失踪的好友又去了哪里?这是我们刚
1 赞
【涌现符】开发日志#1截图
【涌现符】开发日志#1
大家好,我们是电子织机队,核心成员都来自同一个学校社团。 经过了五天的设计大烧烤终于把玩法大概定了下来。虽然题目一出大家立刻都想到了涌现式玩法,但是在这么短的时间内设计出优秀好玩的涌现式玩法对于没有太多经验的学生还是难度颇高,涌现式叙事对于没有专门编剧的我们队也难以达到理想的效果。 皮尔斯提出的"Symbols grow"是一个很有趣的概念,也即一个符号在使用中产生解释,解释引导预期和行动,经验又
4 赞
2 回复
聚光灯 GameJam 开发日志 02|“涌现”有了,但不好玩截图
聚光灯 GameJam 开发日志 02|“涌现”有了,但不好玩
#聚光灯gamejam开发者日志 一个被我们亲手放弃的原型 上一篇日志还在讨论“涌现”到底应该怎么做。 这几天,我们没有急着把先前的一个创意一路堆下去,而是先做了一个可以真正运行、真正试玩的原型。 然后—— 它被放弃了。 听起来进度好像倒退了,但现在回头看,这几天可能反而是整个项目里非常重要的一段。 因为我们第一次比较明确地知道了: “概念上符合涌现”和“真的好玩”,完全是两回事。 游戏原型:一
2 赞
《源墨名出》开发者日志 01|情绪会变成颜色,也会淤成一团墨截图
《源墨名出》开发者日志 01|情绪会变成颜色,也会淤成一团墨
大家好,这里是脑洞俱乐部,很高兴能够站在这里与大家一同参加本次聚光灯大赛。 10 月 1 号题目公布 ——「涌现」。我们盯着这两个字沉默了三分钟,然后有人说:要不,我们聊聊情绪吧。 于是就有了《源墨名出》 我们是怎么理解 "涌现" 的? 我们觉得,情绪这东西本来是看不见的。但当它被你看见、被你说出口、被人接住的时候,它就 "涌现" 成了具体的样子 —— 我们让它涌现成了颜色。 红是愤怒,橙是喜悦,
19 赞
14 回复
《涌》开发日志 #1:在从深圳去海南的船上,我想了一整天的玩法截图
《涌》开发日志 #1:在从深圳去海南的船上,我想了一整天的玩法
本期进展 这次聚光灯本来不打算参加的。大四了,事情一堆。后来看到赛制里可以做纯 H5——不用下载不用安装,浏览器点开就能玩——我转念一想:写代码的活儿反正交给 AI,我负责想玩法和挑毛病,那就参加吧。 开题那天是 10 月 1 号,我正好在从深圳回海南的路上。白天在车上晃,晚上还要坐过海的船,船上睡不踏实,就在那种又困又清醒的状态里,把玩法想了一整天。 想出来的就是《涌》。 一句话说:你在一卷展开
4 赞
1 回复