网易首页 > 网易号 > 正文 申请入驻

这款中国程序员开源的游戏引擎,让你用不到100行代码就写出“愤怒的小鸟”

0
分享至

大家好,我是一个游戏引擎技术探索者,同时也是一名做过不少前端开发工作的程序员。如果你想知道如何从编写网页到开发游戏,那你来对地方了!

今天我们聊聊如何使用 Dora SSR,一个支持 TSX 且跨平台在 native 运行的游戏引擎,助你轻松跨入游戏开发的世界。

不必担心,说到游戏引擎并不是啥高不可攀的技术,反而和我们熟悉的前端开发工具可以有惊人相似之处。

一、游戏客户端开发也可以是一种前端开发

首先,让我们解释一下什么是游戏引擎。

简单来说,游戏引擎就是一套工具和库的集合,帮助开发者构建游戏,管理图形、声音、物理计算或碰撞检测等。

对于前端开发者来说,你可以把它想象成就是一种特殊的浏览器,专门用来运行游戏。

Dora SSR 的游戏场景管理使用了类似于 HTML DOM 的树形结构,这对我们来说再熟悉不过了。

想象一下,将 div 元素换成游戏中的各种对象,CSS 动画换成游戏动画,概念也差不多,代码写法上可能也差不多,是不是觉得有点意思了?


二、从 TypeScript 到 TSX:前端技术在游戏中的应用

许多前端开发者都熟悉 TypeScript 和 React 的 JSX 语法。

在 Dora SSR 开源游戏引擎中,我们通过支持 TSX,提供了与前端开发编程模式相似的游戏开发接口。

是的你没听错,就是那个 TSX。

使用 TSX 开发游戏,意味着你可以利用已有的前端技术栈 — 组件、模块和其他现代前端技术,直接在游戏开发中复用这些概念。

而且,Dora SSR 的性能优化确保了即使是在复杂的游戏场景中,也能保持流畅的运行。


三、挑战 100 行代码以内,教你写一个 “愤怒的小鸟” like 的游戏

好了,理论知识够多了,让我们来点实际操作吧。

来看看如何在 Dora SSR 中用 100 行以内的 TSX 代码编写一个类似 “愤怒的小鸟” 的小游戏。

当然,在开始之前还是要准备开发环境,做这个事用 Dora SSR 就很简单:我有一个安装包一装,我有一个浏览器一开,嗯,开始写代码运行吧。

安装启动参见:Dora 启动!
(https://dora-ssr.net/zh-Hans/docs/tutorial/quick-start)

不小心装成了APK包在手机上?那就在同局域网下访问,直接在手机上进行开发调试吧

1. 编写最简单游戏场景

在编写实际的代码之前,我们可以先写一个有特别功能的注释,它可以告诉 Dora SSR 的 Web IDE 在我们按下 Ctrl + S 保存文件时,自动热更新运行的代码,以实现代码运行结果的实时预览功能。

// @preview-file on

然后,我们引入必要的库和组件。

当然我们的代码编辑器也会提示辅助我们自动引入需要的模块,可以放到后面编码过程中再完成:

import { React, toNode, useRef } from 'DoraX';
import { Body, BodyMoveType, Ease, Label, Line, Scale, TypeName, Vec2, tolua } from 'Dora';

在 Dora SSR 中显示一个图片很简单,只要使用 标签,最后通过toNode()函数将标签实例化为一个游戏对象就可以了。

toNode( );

好的,至此你已经基本掌握大部分 Dora SSR 游戏开发的诀窍了,开始做你自己的游戏吧(认真)。

2. 编写游戏箱子组件

接下来我们在游戏中碰撞的箱子会由Box组件定义,它接受
numxychildren等属性:

interface BoxProps {
num: number;
x?: number;
y?: number;
children?: any | any[];
}

const Box = (props: BoxProps) => {
const numText = props.num.toString();
return (
draw-node>
{numText} label>
{props.children}
body>
);
};

我们使用仿 React 的函数组件的写法来完成我们箱子组件的定义,其中:

  • body组件的tag属性:用于存储箱子的分数。

  • rect-fixture:定义了箱子的碰撞形状。

  • draw-node:用于绘制箱子的外观。

  • label:用于显示盒子的分数。

3. 创建 TSX 实例化后的对象引用

使⽤ useRef 创建两个引⽤变量进行备用,分别指向⼩⻦和分数标签:

const bird = useRef ();
const score = useRef ();


4. 创建发射线

发射线由line变量创建,并添加触摸(同时也是鼠标点击)的事件处理:

let start = Vec2.zero;
let delta = Vec2.zero;
const line = Line();

toNode(

onTapBegan= {(touch) => {
start = touch.location;
line.clear();
}}
onTapMoved= {(touch) => {
delta = delta.add(touch.delta);
line.set([start, start.add(delta)]);
}}
onTapEnded= {() => {
if (!bird.current) return;
bird.current.velocity = delta.mul(Vec2(10, 10));
start = Vec2.zero;
delta = Vec2.zero;
line.clear();
}}
>
{/* ...在物理世界下创建其它游戏元素 ... */}


  • onTapBegan事件中,记录触摸开始的位置并清除发射线。

  • onTapMoved事件中,计算触摸移动的距离并更新发射线。

  • onTapEnded事件中,根据触摸移动的距离设置小鸟的发射速度并清除发射线。

5. 创建其它游戏元素

接下来,我们以 作为游戏场景的父级标签,在它下面继续创建游戏场景中的各个元素:

5.1 地面

首先,我们使用body组件创建一个地面,并将其设置为静态刚体:


draw-node>
body>


  • type={BodyMoveType.Static}:表明这是一个静态刚体,不会受到物理模拟的影响。

  • rect-fixture:定义地面碰撞形状为一个矩形。

  • draw-node:用于绘制地面的外观。

  • rect-shape:绘制一个矩形,颜色为黄色。

5.2 箱子

接下来,我们使用之前写好的Box组件创建 5 个箱子,并设置不同的初始位置和分数,在创建时播放出场动画:

{
[10, 20, 30, 40, 50].map((num, i) => (
sequence>
Box>
))
}


  • map函数:用于遍历分数数组从 10 到 50,并为每个分数创建一个需要小鸟撞击的箱子。

  • Box组件:用于创建箱子,并传入以下属性:

    • num={num}:箱子的分数,对应数组中的数字。

    • x={200}:箱子的初始 x 轴位置,为 200。

    • y={-150 + i * 100}:箱子的初始 y 轴位置,根据创建序号递增。

  • sequence组件:用于创建要在父节点上播放的动画序列,包含以下动画:

    • delay time={i * 0.2}:延迟播放动画,延迟时间根据创建序号递增。

    • scale time={0.3} start={0} stop={1}:缩放动画,从不显示到完全显示,耗时 0.3 秒。

5.3 小鸟

最后,我们使用body组件创建小鸟,并设置碰撞形状、外观和分数标签:

{
if (other.tag !== '' && score.current) {
// 累加积分
const sc = parseFloat(score.current.text) + parseFloat(other.tag);
score.current.text = sc.toString();
// 清除被撞箱子上的分数
const label = tolua.cast(other.children?.last, TypeName.Label);
if (label) label.text = '';
other.tag = '';
// 播放箱子被撞的动画
other.perform(Scale(0.2, 0.7, 1.0));
}
}}>
draw-node>
0 label>
body>


  • ref={bird}:使用ref创建引用变量,方便后续操控小鸟。

  • type={BodyMoveType.Dynamic}:表明这是一个动态刚体,会受到物理模拟的影响。

  • onContactStart={(other) => {}}:小鸟的物理体接触到其它物体时触发的回调处理函数。

  • disk-fixture:定义小鸟形状为一个圆盘。

  • draw-node:用于绘制小鸟的外观。

  • label:用于显示小鸟的累积分数。

  • scale:用于播放小鸟的出场动画。

6. 完成游戏逻辑

至此,我们已经完成了小游戏的核心逻辑。你可以根据自己的想法进一步完善游戏逻辑和增加功能。

完整的 demo 代码可以见这个链接:

https://github.com/IppClub/Dora-SSR/blob/main/Assets/Script/Test/Birdy.tsx

下面是一些运行效果的截图。

拖拽屏幕发射了“愤怒的小鸟”

高超的技巧,使我一击获得了所有得分


四、简单揭秘一下 1. 是鹿还是马

事实上我们写的这段游戏代码,在 Dora SSR 引擎的能力下是可以确保在跨 Linux、Android、iOS、macOS 和 Windows 获得一致的运行结果。

但是为了运行这段代码,我们的 Dora SSR 引擎甚至都没有做 JavaScript 运行环境的支持……(你说什么?)

是的,Dora SSR 的底层技术实现其实是基于 Lua 和 WASM 虚拟机作为脚本语言运行环境的。

对 TypeScript 的支持其实是通过整合了 TypescriptToLua 这个编译器提供的。
( https://github.com/TypeScriptToLua/Typ‍eScriptToLua )

TSTL 通过重新编写了 TypeScript 语言编译器的后端,将 TS 和 TSX 的代码编译为了等价运行的 Lua 代码,从而使得 TS 代码可以在 Dora 上加载运行。

在 Dora 自带的 Web IDE 的代码编辑器下,可以帮助大家做 TS 的语言检查和补全以及 Dora 内置库 API 的提示。

最终的使用体验,大家就可以不用管最后是鹿还是马,只要代码能通过了 TS 的编译检查,拉出来那都是一样的跑啦。

2. 和 React 有关系吗

这个问题的答案目前是:可以有(所以截至发文前还没有)。

React 最重要的能力是通过 Virtual DOM 和执行 Tree Diff 处理的过程来进行渲染组件和业务数据的状态同步,目前这个机制还没有在 Dora SSR 中实现,所以大家目前看到的用 TSX 编写出的类似 VDOM 的构建代码只会在运行时做一次性的游戏渲染对象的构建,往后都是底层 C++ 实现的引擎功能在负责继续处理。

也许有一天我们会为游戏 UI 的开发,提供仿 React 通过执行 Tree Diff 做状态同步的能力,或是仿 SolidJS 基于 TSX 实现其它的渲染组件状态同步的机制。

所以在这里也诚挚地邀请广大前端开发的朋友,加入我们,一起玩 Dora SSR 项目,一起研究怎么运用前端开发技术思想,为游戏开发也引入更多好用便捷的轮子吧。

最后我们的 Q 群在这里,欢迎过来玩:
512620381

作者介绍

李瑾:金融行业大数据工程师,Dora SSR 和 Yuescript 开源软件作者。

项目介绍

Dora SSR(多萝珍奇引擎)是一个用于多种设备上快速开发2D游戏的游戏引擎。
它内置易用的开发工具链,支持在手机、开源掌机等设备上直接进行游戏开发。

项目仓库

https://gitee.com/pig/Dora-SSR
https://github.com/IppClub/Dora-SSR

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
哪怕半血也是神!帕森斯:塔图姆50%状态回归,绿军也是大升级

哪怕半血也是神!帕森斯:塔图姆50%状态回归,绿军也是大升级

大眼瞄世界
2026-03-04 22:35:08
“高速节假日免费”改“每年固定里程免费”,连续4年都有全国两会代表委员提建议,专家:短期内不具备全面落地可行性

“高速节假日免费”改“每年固定里程免费”,连续4年都有全国两会代表委员提建议,专家:短期内不具备全面落地可行性

极目新闻
2026-03-04 12:28:35
网传小象优品老板跑路!员工半年没发工资,清退消金股权小贷牌照

网传小象优品老板跑路!员工半年没发工资,清退消金股权小贷牌照

开甲财经
2026-03-04 10:35:17
美国也没想到,转为中国籍仅6年,谷爱凌竟已成美国头号劲敌

美国也没想到,转为中国籍仅6年,谷爱凌竟已成美国头号劲敌

青烟小先生
2026-01-31 19:10:22
李亚鹏的元宵节小屋藏暖,爱在烟火间双向奔赴

李亚鹏的元宵节小屋藏暖,爱在烟火间双向奔赴

暖心萌阿菇凉
2026-03-04 06:01:33
苹果把iPhone芯片塞进MacBook,PC圈真要变天了

苹果把iPhone芯片塞进MacBook,PC圈真要变天了

PConline太平洋科技
2026-03-05 06:37:59
央视公布!中国卫星立大功,全程直播美军行动,一举一动尽收眼底

央视公布!中国卫星立大功,全程直播美军行动,一举一动尽收眼底

离离言几许
2026-03-04 17:11:33
今天中东的乱局,都源于680年沙漠里那一场没有赢家的屠杀

今天中东的乱局,都源于680年沙漠里那一场没有赢家的屠杀

花仙历史说
2026-03-02 20:46:40
基辛格生前大胆预测:第三次世界大战爆发,敢打美国的国家就3个

基辛格生前大胆预测:第三次世界大战爆发,敢打美国的国家就3个

古史青云啊
2026-02-17 22:44:51
玄学真相:凡事“反着来”,你就赢了——这才是人生最高级的破局之道

玄学真相:凡事“反着来”,你就赢了——这才是人生最高级的破局之道

青苹果sht
2026-02-27 06:28:52
杨紫真的已经瘦到天赋上限了,这也太牛了…

杨紫真的已经瘦到天赋上限了,这也太牛了…

手工制作阿歼
2026-02-22 13:25:34
世界上唯一“没有穷人的国家”:结婚、生娃、买房,国家全给包了

世界上唯一“没有穷人的国家”:结婚、生娃、买房,国家全给包了

看尽人间百态
2026-02-17 14:33:25
亨德利:斯诺克世锦赛第一轮对赵心童很关键 闯过去就能够走更远

亨德利:斯诺克世锦赛第一轮对赵心童很关键 闯过去就能够走更远

罗克
2026-03-04 14:46:43
IF椰子水否认产品掺假:天然纯粹!未添加任何外源糖/水/香精

IF椰子水否认产品掺假:天然纯粹!未添加任何外源糖/水/香精

快科技
2026-03-04 17:37:05
看到段曦与张杰恋爱时的照片,才懂谢娜为啥不澄清被扇耳光的传闻

看到段曦与张杰恋爱时的照片,才懂谢娜为啥不澄清被扇耳光的传闻

小娱乐悠悠
2026-03-04 09:17:27
又有2名间谍被抓!潜藏中国17年,境外渗透曝光,泄密细节惊人

又有2名间谍被抓!潜藏中国17年,境外渗透曝光,泄密细节惊人

快看张同学
2026-02-24 19:23:29
永远不要向任何人,包括你的亲戚和好友,透露你真实的财务状况

永远不要向任何人,包括你的亲戚和好友,透露你真实的财务状况

流苏晚晴
2026-02-27 18:09:29
回归首秀!你好,李凯尔!等了整整2年时间

回归首秀!你好,李凯尔!等了整整2年时间

篮球实战宝典
2026-03-04 18:15:55
《成何体统》爆火网络,作者是位杭州姑娘,有网友说:这是杭二中的学姐呀!

《成何体统》爆火网络,作者是位杭州姑娘,有网友说:这是杭二中的学姐呀!

都市快报橙柿互动
2026-03-04 00:41:05
东北男人“新战袍”:4000元的迪桑特,成了体制内的隐形工牌

东北男人“新战袍”:4000元的迪桑特,成了体制内的隐形工牌

梦在深巷aqa
2026-02-25 00:15:06
2026-03-05 08:36:49
开源中国 incentive-icons
开源中国
每天为开发者推送最新技术资讯
7604文章数 34504关注度
往期回顾 全部

科技要闻

4599元起!MacBook Neo发布:搭载A18 Pro

头条要闻

外媒称伊朗封锁霍尔木兹海峡只让中俄船通行 中方回应

头条要闻

外媒称伊朗封锁霍尔木兹海峡只让中俄船通行 中方回应

体育要闻

2026年中超,为什么值得你多看一眼?

娱乐要闻

谢谢谢娜 贡献出26年内娱的第一个笑话

财经要闻

人大代表建议:将农民养老金提到500元

汽车要闻

鸿蒙智行首款猎装车 尚界Z7/Z7T首发

态度原创

手机
健康
家居
数码
公开课

手机要闻

谷歌以外首家:OPPO Find X9将通过Quick Share支持苹果隔空投送

转头就晕的耳石症,能开车上班吗?

家居要闻

极简无界 静居自安然

数码要闻

英伟达发布热修复显卡驱动595.76,解决显卡超频电压受限等问题

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版