💽 游戏开发中的编程理论基础
2024-04-07
基础知识
编程范式
int main(){
//第一个点
float x1 = 2.0f;
float y1 = 3.0f;
float z1 = 0.1f;
//第二个点
float x2 = 1.0f;
float y2 = 2.0f;
float z2 = 0.6f;
}
struct Vector3 {
float x;
float y;
float z;
};
走近面向对象编程,之前
在本文中,“对数据的操作”、“操作”和“函数”的含义差不多,在本模块的语境中请当作一个概念看待。
什么是面向对象 OOP
public class Vector3 {
//成员字段
public float x;
public float y;
public float z;
//成员方法
public void Clear() {
x = 0f;
y = 0f;
z = 0f;
}
}
void Clear(Vector3 self) {
self.x = 0f;
self.y = 0f;
self.z = 0f;
}
-
执行流过长会导致程序的运行难以分析和排障 -
变量和关于它们的操作在代码逻辑上没有关联性
class Block {
String name;
float explosionResistance; //爆炸抵挡能力
float destroyTime; //破坏这个方块需要的时间
Item item;
...
}
Block dirt = new Block("dirt",...);
Block dirt = new Block("dirt",...);
Block stone = new Block("stone",...);
Block leaf = new Block("leaf",...);
...
//Block class
void spawnDrops(){
}

class LeafBlock extends Block {
void spawnDrops() {
//有概率掉落树苗的逻辑
}
}
class DirtBlock extends Block {
void spawnDrops() {
//掉落方块物品的逻辑
}
}
用继承模型实现游戏

public void aiStep() {
super.aiStep();
this.oFlap = this.flap;
this.oFlapSpeed = this.flapSpeed;
this.flapSpeed += (this.onGround() ? -1.0F : 4.0F) * 0.3F;
this.flapSpeed = Mth.clamp(this.flapSpeed, 0.0F, 1.0F);
if (!this.onGround() && this.flapping < 1.0F) {
this.flapping = 1.0F;
}
this.flapping *= 0.9F;
Vec3 vec3 = this.getDeltaMovement();
if (!this.onGround() && vec3.y < 0.0D) {
this.setDeltaMovement(vec3.multiply(1.0D, 0.6D, 1.0D));
}
this.flap += this.flapping * 2.0F;
if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) {
this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
this.spawnAtLocation(Items.EGG);
this.gameEvent(GameEvent.ENTITY_PLACE);
this.eggTime = this.random.nextInt(6000) + 6000;
}
}


组合模型大于继承模型
-
生命能力 -
Ai 能力 -
走路能力 -
缓落能力 -
接受药水效果能力 -
……
组合模型和继承并不冲突
容易接触到的组合模型


面向对象在游戏开发中的问题
什么是数据驱动 Data-Driven
在下面的文章中 “数据驱动” 和 “面向数据” 表示同一个意思,当你看到其中的一个时,请将其换成你喜欢的那一个名词;
在开始介绍新范式之前
从数据开始
min :: (Ord t) => t -> t -> t
min a b = case compare a b of
LT -> a
GT -> b
EQ -> a

什么是 ECS
本篇介绍的 Component 与 Unity 的 Component 并不相同,类似地 Entity 也并不是 GameObject,它们或许有些类似,但请大家不要带入过往的经验。
ECS 是一种用面向数据思想设计的框架,我们下面也会介绍 ECS 系统如何用面向数据思想来实现的。
注:Minecraft 并不是用 ECS 模型实现的游戏,但我们以 Minecraft 的游戏内容为例来介绍 ECS,或者说如果我们以 ECS 模型来实现 Minecraft,我们会怎样设计。以下的 Entity(实体)定义与我们上面介绍过的 Minecraft 中的 Entity 没有关系。
先介绍一下什么是实体和组件
- Transform //位置、旋转、缩放信息
- ItemTexture //物品的贴图
- RegistryName //这个物品种类的唯一标识
- Count //掉落的物品的数量
- DroppedItem //不存储数据,只是一个用来标识这时掉落物的标签
..

什么是系统(System)
-
我们怎样获取需要的数据(主要为组件)?(了解组件的存储方式) -
我们怎样调用我们的系统?(了解系统的存储方式)
组件是怎样被存储的

将系统放在一起
🌰 例子
fn rotate_drops(query: Query<&Transform, With<DroppedItem>>, time: Res<Time>){
for transform in query{
rotate_with_time(&mut transform, time.delta());
}
}
ECS 的应用
-
Unreal 的使用的就是混合的 ECS 范式。
-
一个是 Bevy,这是一个基于 rust 的纯 ECS 的面向数据的游戏引擎。 -
另一个就是 Unity 于今年(2023)刚刚更新的 DOTS 框架,Unity 特别强调了该框架 ECS 和面向数据的特性。
附录
再好的学习资料也不能解决一切问题,学习的过程中希望大家广泛地运用搜索引擎、ChatGPT、New Bing 等来解决自己的问题。 在开发领域,在国际搜索引擎(Bing 国际版、Google 等)用英文搜索能得到更有帮助的答案。
程序设计基础方向
适合的人群:希望了解程序设计基础知识的人; 你可以从中获得:作为程序员,我们在编程时到底在做什么和应该思考什么。程序设计的基本理念。
适合的人群:希望了解编程语言如何赋予我们组合和抽象的能力,以及希望了解如何设计出良好程序的人群; 你可以从中获得:Lisp 语言的基础知识,设计良好程序的能力,分析编程语言结构的能力。
面向对象的编程范式方向
C# (C Sharp)
适合的人群:无编程语言经验的编程入门人群、只有非面向对象编程语言经验的人群; 你可以从中获得:C# 程序设计语言的基础和进阶知识及实践指导,面向对象基本理论在 C# 编程中的实践。
Java & Kotlin
Kotlin 是一个可以用于编写 Java 程序、跨平台应用、Web开发、安卓应用等的编程语言。 Kotlin 更加现代并且完全兼容 Java,所以越来越多的 Java 项目开始使用 Kotlin 作为主要开发语言(例如安卓系统)。
适合的人群:无编程语言经验的编程入门人群、只有非面向对象编程语言经验的人群,想要学习 Java 的人群; 你可以从中获得:理解面向对象这种编程范式并学习如何用 Java 语言实践。
适合的人群:有面向对象语言编程经验、想学习 Kotlin 的人群。
游戏引擎
适合人群:对游戏和游戏引擎如何运作好奇的人群,即使大部分听不懂,也能收获颇多 你可以从中获得:现代游戏引擎的理论知识
Bevy 引擎
适合的人群:好奇 Bevy 是如何设计出干净的 ECS 结构的人 你可以从中获得:使用 Bevy 引擎的能力;ECS 的游戏引擎是如何被实践出来的知识;对数据驱动更深刻的认识。
进阶