前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >游戏开发中的向量数学

游戏开发中的向量数学

作者头像
海拥
发布于 2021-08-23 08:59:21
发布于 2021-08-23 08:59:21
1.5K02
代码可运行
举报
文章被收录于专栏:全栈技术全栈技术
运行总次数:2
代码可运行

游戏开发中的向量数学

介绍

本教程是线性代数的简短实用介绍,因为它适用于游戏开发。线性代数是向量及其用途的研究。向量在2D和3D开发中都有许多应用,并且Godot广泛使用它们。对矢量数学有深入的了解对于成为一名强大的游戏开发者至关重要。

注意 本教程不是关于线性代数的正式教科书。我们只会研究如何将其应用于游戏开发。要更广泛地了解数学,请参见https://www.khanacademy.org/math/linear-algebra

坐标系(2D)

在2D空间中,使用水平轴(x)和垂直轴(y)定义坐标。2D空间中的特定位置被写为一对值,例如。(4, 3)

注意 如果您是计算机图形学的新手,那么正y轴是指向下而不是指向上,这似乎很奇怪,就像您在数学课上学到的那样。但是,这在大多数计算机图形应用程序中很常见。

二维平面中的任何位置都可以通过一对数字来标识。 但是,我们也可以将位置(4,3)视为与(0,0)点或原点的偏移量。 绘制一个从原点指向该点的箭头:

这是一个向量。 向量代表许多有用的信息。 除了告诉我们该点位于(4,3)之外,我们还可以将其视为角度θ和长度(或大小)m。 在这种情况下,箭头是位置矢量-它表示相对于原点的空间位置。

关于矢量要考虑的非常重要的一点是,它们仅代表相对方向和大小。没有向量位置的概念。以下两个向量是相同的:

两个向量都代表一个点,该点向右4个单位,在某个起点下方3个单位。在平面上绘制矢量的位置无关紧要,它始终表示相对方向和大小。

向量运算

您可以使用任何一种方法(x和y坐标或角度和大小)来引用矢量,但是为了方便起见,程序员通常使用坐标符号。例如,在Godot中,原点是屏幕的左上角,因此,要使用一个名为Node2D400像素,向下300像素的2D节点,请使用以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var node2D = (Node2D) GetNode("Node2D");
node2D.Position = new Vector2(400, 300);

Godot同时支持Vector2和 Vector3的2D和3D使用。本文讨论的相同数学规则适用于两种类型。

会员访问

可以直接通过名称访问向量的各个组成部分。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// create a vector with coordinates (2, 5)
var a = new Vector2(2, 5);
// create a vector and assign x and y manually
var b = new Vector2();
b.x = 3;
b.y = 1;

添加向量

当相加或相减两个向量时,将添加相应的分量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var c = a + b;  // (2, 5) + (3, 1) = (5, 6)

我们还可以通过在第一个向量的末尾添加第二个向量来直观地看到这一点:

注意,加a + b的结果与b + a相同。

标量乘法

注意 向量代表方向和大小。仅代表幅度的值称为标量。

一个向量可以乘以一个标量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var c = a * 2;  // (2, 5) * 2 = (4, 10)
var d = b / 3;  // (3, 6) / 3 = (1, 2)

注意 标量乘以向量不会改变其方向,只会改变其大小。这就是缩放向量的方式。

实际应用

让我们看一下向量加法和减法的两种常见用法。

运动

向量可以表示具有大小和方向的任何数量。典型示例是:位置,速度,加速度和力。在此图像中,步骤1的太空飞船的位置矢量为(1,3),速度矢量为(2,1)。速度矢量表示船每步移动多远。我们可以通过将速度添加到当前位置来找到步骤2的位置。

提示 速度测量单位时间的位置变化。通过将速度添加到先前位置来找到新位置。

指向目标

在这种情况下,您有一个坦克,希望将其炮塔指向机器人。从机器人的位置减去水箱的位置即可得出从水箱指向机器人的向量。

提示 要找到一个向量指向A来B使用。B - A

单位向量

大小为的向量1称为单位向量。它们有时也称为方向向量或法线。当需要跟踪方向时,单位矢量会很有用。

正常化

归一化向量意味着将其长度减小到,1同时保留其方向。这是通过将其每个组成部分除以其大小来完成的。因为这是这样一个共同的操作, Vector2并Vector3提供一种用于归一化的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a = a.Normalized();

警告 由于规范化涉及除以向量的长度,因此无法规范化length的向量0。尝试这样做将导致错误。

反射

单位向量的一种常见用法是指示法线。法线向量是垂直于表面对齐并定义其方向的单位向量。它们通常用于照明,碰撞以及涉及曲面的其他操作。

例如,假设我们有一个要从墙或其他物体上反弹的运动球:

表面法线的值为(0,-1),因为它是水平面。 当球碰撞时,我们采取其剩余的运动(当其击中表面时剩余的量)并使用法线反射它。 在Godot中,Vector2类具有bounce()方法来处理此问题。 这是上面使用KinematicBody2D的图的GDScript示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// KinematicCollision2D contains information about the collision
KinematicCollision2D collision = MoveAndCollide(_velocity * delta);
if (collision != null)
{
    var reflect = collision.Remainder.Bounce(collision.Normal);
    _velocity = _velocity.Bounce(collision.Normal);
    MoveAndCollide(reflect);
}

点积

该点积是矢量数学最重要的概念之一,但经常被误解。点积是对两个向量返回标量的运算。与既包含幅度又包含方向的向量不同,标量值仅包含幅度。

点积的公式有两种常见形式:

但是,在大多数情况下,最容易使用内置方法。请注意,两个向量的顺序无关紧要:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
float c = a.Dot(b);
float d = b.Dot(a); // These are equivalent.

与单位向量一起使用时,点积最有用,这会使第一个公式简化为just cosθ。这意味着我们可以使用点积来告诉我们有关两个向量之间的角度的一些信息:

使用单位矢量时,结果将始终在-1(180°)和1(0°)之间。

面对

我们可以利用这一事实来检测一个对象是否面向另一个对象。在下图中,玩家P试图避开僵尸A和B。假设僵尸的视野为180°,他们可以看到玩家吗?

绿色箭头fA和fB是代表僵尸面向方向的单位矢量,蓝色半圆形代表其视野。 对于僵尸A,我们使用P-A找到指向玩家的方向向量AP并将其标准化,但是Godot有一个辅助方法来执行此操作,称为direction_to。 如果此向量和面对的向量之间的角度小于90°,则僵尸可以看到玩家。

在代码中,它看起来像这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var AP = A.DirectionTo(P);
if (AP.Dot(fA) > 0)
{
    GD.Print("A sees P!");
}

叉积

像点积一样,叉积是对两个向量的运算。但是,叉积的结果是一个向量,向量的方向垂直于两者。其大小取决于它们的相对角度。如果两个向量平行,则其叉积的结果将为空向量。

叉积计算如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var c = new Vector3();
c.x = (a.y * b.z) - (a.z * b.y);
c.y = (a.z * b.x) - (a.x * b.z);
c.z = (a.x * b.y) - (a.y * b.x);

使用Godot,您可以使用内置方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var c = a.Cross(b);

注意 在交叉产品中,订单至关重要。a.cross(b)与给出的结果不同b.cross(a)。所得的矢量指向相反的方向。

计算法线

叉积的一种常见用法是在3D空间中找到平面或曲面的表面法线。如果我们有三角形,ABC则可以使用矢量减法找到两个边AB和AC。使用叉积, 产生一个垂直于两个方向的向量:表面法线。AB x AC

这是一个计算三角形法线的函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Vector3 GetTriangleNormal(Vector3 a, Vector3 b, Vector3 c)
{
    // find the surface normal given 3 vertices
    var side1 = b - a;
    var side2 = c - a;
    var normal = side1.Cross(side2);
    return normal;
}

指向目标

在上面的点积部分,我们看到了如何将其用于查找两个向量之间的角度。但是,在3D中,这还不够。我们还需要知道要旋转的轴。通过计算当前朝向和目标方向的叉积可以发现。所得的垂直向量是旋转轴。

更多信息 有关在Godot中使用向量数学的更多信息,请参见我后续的文章:

进阶向量数学 矩阵与变换

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
08:石头剪刀布
08:石头剪刀布 总时间限制: 1000ms 内存限制: 65536kB描述 石头剪刀布是常见的猜拳游戏。石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。 一天,小A和小B正好在玩石头剪刀布。已知他们的出拳都是有周期性规律的,比如:“石头-布-石头-剪刀-石头-布-石头-剪刀……”,就是以“石头-布-石头-剪刀”为周期不断循环的。请问,小A和小B比了N轮之后,谁赢的轮数多? 输入输入包含三行。 第一行包含三个整数:N,NA,NB,分别表示比了N轮,小A出拳的周期长度,小B出拳的周期长度
attack
2018/04/03
1.9K0
百练 石头剪刀布
总时间限制: 1000ms内存限制: 65536kB描述 石头剪刀布是常见的猜拳游戏。石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。 一天,小A和小B正好在玩石头剪刀布。已知他们的出拳都是有周期性规律的,比如:“石头-布-石头-剪刀-石头-布-石头-剪刀……”,就是以“石头-布-石头-剪刀”为周期不断循环的。请问,小A和小B比了N轮之后,谁赢的轮数多? 输入输入包含三行。 第一行包含三个整数:N,NA,NB,分别表示比了N轮,小A出拳的周期长度,小B出拳的周期长度。0 < N,NA,NB
用户1631856
2018/04/12
9510
P1328 生活大爆炸版石头剪刀布
题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第8 集中出现了一种石头剪刀布的升级版游戏。 升级版游戏在传统的石头剪刀布游
attack
2018/04/12
1.7K0
P1328 生活大爆炸版石头剪刀布
联想算法题-石头剪刀布
问题描述 剪刀石头布是一种常见的猜拳游戏,当玩家人数为两人时,它的规则如下:在每一轮中,双方分别同时给出石头(Rock)、剪刀(Scissor)和布(Paper)这三种手势中的一种。石头战胜剪刀;剪刀战胜布;布战胜石头。若双方给出的手势一样则本轮平局,双方分数不变;否则胜方积1分。 现在Alice和Bob想进行若干轮猜拳游戏,但他们不想逐轮进行游戏,于是决定分别在纸上写下他们每一轮要出的手势。作为裁判的你需要根据他们所写下的手势判断他们的比分是多少。 输入描述 第一行是一个正整数T,表示他们想进行的轮数。 第二行包含T个空格隔开的字符串s_1, s_2, …, s_T,其中s_i表示Alice写下的第i轮要出的手势。 第三行包含T个空格隔开的字符串t_1, t_2, …, t_T,其中t_i表示Bob写下的第i轮要出的手势。 所有的s_i和t_i均是”Rock”,”Scissor”,”Paper”中的一种。
GeekLiHua
2025/01/21
940
C语言 编写“剪刀石头布”小游戏[通俗易懂]
大家好~ 我是一名C语言初学者,学了C语言基础后,我制作了一个小游戏:剪刀石头布。 希望大家能对我的思路和代码提出小Tips(eg.更简便的方法与程序) 我也会虚心接受大家的建议~
全栈程序员站长
2022/09/15
3.8K0
1018 锤子剪刀布 (20 分)
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
可爱见见
2019/09/09
9820
​# 使用腾讯云AI代码助手实现石头剪刀布小游戏
石头剪刀布,这个看似简单的游戏,却蕴含着无穷的乐趣。它是人类历史上最古老、流传最广的游戏之一,几乎每个人在儿时都曾与伙伴们乐此不疲地对战过。这个游戏凭借其简单的规则和高度的互动性,成为了人们茶余饭后、朋友聚会时的经典娱乐项目。它不仅考验玩家的反应速度,更蕴含着一种策略性的思考。
Front_Yue
2025/04/01
1340
​# 使用腾讯云AI代码助手实现石头剪刀布小游戏
C语言实现石头剪刀布小游戏【源码演示】
代码运行结果演示 代码如下 #include<stdio.h> #include<stdlib.h> #include<time.h> //在【C语言中文社区】公众号回复“C语言”,免费领取200G学习资料。 int main() { printf("欢迎来到石头剪刀布游戏世界\n"); printf("我是你无法打败的对手-小布\n"); char game[3][20] = { "石头","剪刀","布" }; /*i表示游戏次数,如果玩家在15次比赛后累计得分60,
C语言中文社区
2022/05/31
3.3K1
C语言实现石头剪刀布小游戏【源码演示】
【C++】B2112 石头剪子布
石头剪子布,是一种猜拳游戏,起源于中国,然后传到日本,朝鲜等地,随着亚欧贸易的不断发展它传到西欧,到了现代化逐渐国际化的世界中。简单明了的规则,使得石头剪子布没有任何知识和规则漏洞可钻,单次玩法让比赛公平,容易且充满心理博弈,使得石头剪子布这个古老的游戏同时用于“意外”与“技术”两种特性,深受世界人民喜爱。
CSDN-Z
2025/01/24
600
【C++】B2112 石头剪子布
石头剪刀布c++实现
问题描述: 编写一个程序,玩“石头”“剪刀”“布”的游戏,在这个游戏中,两位玩家通时说出“石头”“剪刀”“布” 如果一位玩家所选的对象击败了另一个玩家所选的对象,那么前者就是赢家,规则是:布吃石头,石头吃剪刀 剪刀吃布,为选择的对象和最终的结果使用枚举,使用标准头文件中定义的ran()函数,为计算生成随机的选择。 输入: choose either rock,shear,cloth(R/S/P):S 输出: I chose Rock. I won 设计思路: 产生result的两个人,设计程序为你选你的(switch随机选),我产生我的(rand()函数随机产生对3求余,switch实现产生我的三种结果), 然后将你选的和我随机产生做比较,对产生的结果做判断,当然了本题也可以是两个人的结果都随机产生,然后作比较 。
全栈程序员站长
2022/09/15
1K0
石头剪刀布c++实现
16:矩阵剪刀石头布
16:矩阵剪刀石头布 总时间限制: 5000ms 内存限制: 65536kB描述 Bart的妹妹Lisa在一个二维矩阵上创造了新的文明。矩阵上每个位置被三种生命形式之一占据:石头,剪刀,布。每天,上下左右相邻的不同生命形式将会发生战斗。在战斗中,石头永远胜剪刀,剪刀永远胜布,布永远胜石头。每一天结束之后,败者的领地将被胜者占领。 你的工作是计算出n天之后矩阵的占据情况。 输入第一行包含三个正整数r,c,n,分别表示矩阵的行数、列数以及天数。每个整数均不超过100。 接下来r行,每行c个字符,描述矩阵
attack
2018/04/03
1.5K0
教小朋友了解 C++ 的循环结构
嗨,小朋友们!准备好进入C++的循环结构奇妙世界了吗?循环结构就像魔法石一样神奇,让我们来一起探索吧!
Yunjie Ge
2023/09/01
2700
教小朋友了解 C++ 的循环结构
Contest100000575 – 《算法笔记》3.1小节——入门模拟->简单模拟
http://codeup.cn/contest.php?cid=100000575 Problem A: 剩下的树 Time Limit: 1.000 Sec Memory Limit: 32 M
可定
2020/04/20
1.1K0
YbtOJ 971「fwt」猜拳游戏
有 n=3^m 个人(标号为 0\sim n-1)在玩猜拳。共有 t 轮游戏,每轮游戏都会进行 m 次猜拳。
yzxoi
2022/09/19
2800
PAT (Basic Level) Practice (中文)1018 锤子剪刀布 (20 分)
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
glm233
2020/09/28
3450
PAT (Basic Level) Practice (中文)1018 锤子剪刀布 (20 分)
大整数乘法的详解
由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大规模的高精度数值计算,因此需要利用其他方法实现高精度数值的计算,于是产生了大数运算。尤其是乘法运算,下面就是大整数的乘法的过程(加 减法都一样的原理)。
全栈程序员站长
2022/09/05
1.5K0
大整数乘法的详解
江哥带你玩转C语言 | 07 - C语言流程控制
流程控制基本概念 默认情况下程序运行后,系统会按书写顺序从上至下依次执行程序中的每一行代码。但是这并不能满足我们所有的开发需求, 为了方便我们控制程序的运行流程,C语言提供3种流程控制结构,不同的流程控制结构可以实现不同的运行流程。 这3种流程结构分别是顺序结构、选择结构、循环结构 顺序结构: 按书写顺序从上至下依次执行 选择结构 对给定的条件进行判断,再根据判断结果来决定执行代码 循环结构 在给定条件成立的情况下,反复执行某一段代码 ---- 选择结构 C语言中提供了两大选择结
极客江南
2021/07/11
1.6K0
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-919 组合数取模
        这段时间我会把蓝桥杯官网上的所有非VIP题目都发布一遍,让大家方便去搜索,所有题目都会有几种语言的写法,帮助大家提供一个思路,当然,思路只是思路,千万别只看着答案就认为会了啊,这个方法基本上很难让你成长,成长是在思考的过程中找寻到自己的那个解题思路,并且首先肯定要依靠于题海战术来让自己的解题思维进行一定量的训练,如果没有这个量变到质变的过程你会发现对于相对需要思考的题目你解决的速度就会非常慢,这个思维过程甚至没有纸笔的绘制你根本无法在大脑中勾勒出来,所以我们前期学习的时候是学习别人的思路通过自己的方式转换思维变成自己的模式,说着听绕口,但是就是靠量来堆叠思维方式,刷题方案自主定义的话肯定就是从非常简单的开始,稍微对数据结构有一定的理解,暴力、二分法等等,一步步的成长,数据结构很多,一般也就几种啊,线性表、树、图、再就是其它了。顺序表与链表也就是线性表,当然栈,队列还有串都是属于线性表的,这个我就不在这里一一细分了,相对来说都要慢慢来一个个搞定的。蓝桥杯中对于大专来说相对是比较友好的,例如三分枚举、离散化,图,复杂数据结构还有统计都是不考的,我们找简单题刷个一两百,然后再进行中等题目的训练,当我们掌握深度搜索与广度搜索后再往动态规划上靠一靠,慢慢的就会掌握各种规律,有了规律就能大胆的长一些难度比较高的题目了,再次说明,刷题一定要循序渐进,千万别想着直接就能解决难题,那只是对自己进行劝退处理。加油,平常心,一步步前进。
红目香薰
2023/02/23
3170
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-919 组合数取模
shell脚本实例精讲_shell脚本编程实例
shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效、安全、低成本地使用 Linux 内核,这就是 Shell 的本质。
全栈程序员站长
2022/11/10
1.4K0
C学习
链接:https://pan.baidu.com/s/1TKn-gy_UDsngbSzL9Cv5mQ 提取码:txcl
裴来凡
2022/05/29
6240
C学习
相关推荐
08:石头剪刀布
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验