《游戏人工智能编程案例精粹》读书笔记—数学和物理学初探

1.1.1 笛卡尔坐标系

在二维空间中,笛卡尔坐标系被定义成两个坐标轴成直角相交并且用单位长度标出。水平轴称为x 轴,而垂直轴称为y 轴,两个轴的交点称为原点,如图1.1 所示。

如图1.1所示,每个坐标轴端点的箭头表示它们在每个方向上无限延伸。假想有一张无限大的纸,上面有x 轴和y 轴,纸就表示 xy 平面,所有二维的笛卡尔坐标系中的点都可以给制在这个平面上。在2D 空间中的一个点可以用一对坐标(x,y) 表示。x 和y 的值代表沿着各自的轴上的距离。

为了表达三维空间,需要另外一个坐标轴z铀。z 轴从你的屏幕的后面延伸到屏幕的前面,在途中穿过原点。如图1.2 所示。

1.1.2 函数和方程

函数的概念是数学的基础。函数表达了两个(或更多个) 称为变量的项之间的关系,并且典型的写法是方程的形式(一个代数表达式等于另一个代数表达式)。

图1.3的左边显示了函数y=2x 在 xy 平面上绘制出来是怎样的图形,使用的x 值的范围是-5.0-5.0。

为了把函数y=mx+c 给制成一个图形,你必须首先有常数m 和c 的一些值。我们设m=2和c=3,给出函数y=2x+3。图1.3 右边显示了结果图形。

y=mx+c 是定义在三维空间的所有直线的函数。常数m定义了直线的斜率,或者说是直线倾斜的陡峭程度,常数c 规定了直线与y 轴相交的位置。

1.1.2.1 指数和幂

一个指数函数定义如下:

α 称为底而x 称为幂。如果口头描述此方程,就是f(x)等于a 的x 次幂。这意味着a 与自身相乘x 次。

图1.5 显示了方程在a=2 时绘制的图形。曲线明显地显示了y 的值是如何随着x 的值快速增加的。这种曲线的类型常常被称为指数增长。

1.1.2.3 化简方程

通常,要解一个方程必须先化简。实现化简的一个黄金定律是在方程的两边通过同时加、减、乘或除一些项来得到方程的解。(这个规则有一个例外:当进行乘或除时,该项不能为零。〉只要方程两边做的运算相同,那么两边将保持相等。

1.1.3 三角学

角和弧度

一个角定义为有公共原点的两条射线的分散度,见图1.7。

弧度是以原点为中心的单位半径(半径为1) 圆为基准的一种度量单位。圆的半径是从圆的中心到圆周上的点的距离。在画有两条射线的同一图(见图1.7)中作单位圆,我们得到图1.8。在两条射线之间的曲线段的长度(在图中显示成点线的)是它们的夹角在弧度制下角的度量。

角度转弧度:弧度=角度×(π/180)

弧度转角度:角度=弧度×(180/π)

勾股定理

一个直角三角形直角所对内的斜边的平方等于其他两个边的平方和。三角形的斜边是它的最长的边,如图1.10 所示。

如果斜边用h 表示,勾股定理可以写成:

两边取平方根得:

这意味着如果我们知道一个直角三角形的任意两个边的长度,就可以轻松地找到第三边。

直角三角函数

α的正弦sinα=b/c;(对边÷斜边)

α的余弦cosα=a/c;(邻边÷斜边)

α的正切tanα=b/a;(对边÷邻边)

当已知角度时,就用正弦、余弦或正切函数得到对应的三角函数值; 反之,如果要想得到角度,就应该利用反三角函数计算。

1.1.4 向量

一个向表达了两个性质:方向和大小。1.16 右边显示了份子原点处的向量(9, 6)。

向量运算

(以下内容来自3D数学基础:图形与游戏开发)

1 零向量

零向量是唯一大小为零的向量,它的每一维都是零,零向量也是惟一一个没有方向的向量。其实零向量表示的就是“没有位移”,就像标量零表示“没有数量”一样。

1.2 负向量

要得到任意维向量的负向量,只需要简单地把每个分量都变负即可。数学表达式为:

几何解释:向量变负,将得到一个和原来向量大小相等,方向相反的向量。(向量在图中的位置是无关紧要的,只有大小和方向才是最重要的)。

1.3 向量大小

其实向量的大小和方向都没有在向量的数学表示中明确的表示出来。所有向量的大小是需要计算的,向量的大小也常被称作向量的长度或

n维向量大小的计算公式如下图:

线性代数中,向量的大小用向量两边双竖线表示,这和标量的绝对值在标量两边加单竖线表示类似。

1.4 标量与向量的乘法

虽然标量与向量不能相加,但它们能相乘。结果得到一个向量,与源向量平行,但长度不同或方向相反。

标量和向量的乘法非常直接,将向量的每一个分量都与标量相乘即可。

1.5 标准化向量

对许多向量,我们只关心它的方向而不关心其大小,这样的情况下,使用单位向量将非常方便。

单位向量就是大小为1的向量,单位向量经常也被称作标准化向量。

对于任意非零向量v,都能计算出一个和v方向相同的单位向量 v‘ 这个过程被称作向量的标准化,要标准化向量,将向量除以它的大小即可。

零向量不能被标准化。数学上这是不允许的,因为将导致除零。几何上也没有意义,因为零向量没用方向。

1.6 向量的加法与减法

如果两个向量的维数相同,那么它们能相加,或相减。结果向量的维数与原向量相同。向量加减法的记法和标量加减的记法相同。

两个向量相加或相减,将对应分量相加即可。

(1)向量不能与标量或维数不同的向量相加减。

(2)和标量加法一样,向量加法满足交换律,但向量减法不满足交换律。

1.7 向量点乘

向量点乘也常称作向量内积。

向量点乘就是对应分量乘积的和,结果是一个标量。

点乘结果描述了两个向量的“相似”程度,点乘结果越大,两个向量越相近。

1、判断是否垂直,如果A·B=0,那么A⊥B。

2、点乘结果的正负,如果A·B<0,那么Θ>90°,如果A·B>0,那么Θ<90°,其中Θ为向量A和向量B之间的夹角。

3、两向量之间的夹角,A·B=||A|| ||B||  cosΘ,其中Θ为向量A和向量B之间的夹角。

1.8 向量差乘

向量叉乘又叫叉积,仅可应用于3D向量。

叉乘得到的向量垂直于原来的两个向量。

C++向量封装类:

#ifndef __VECTOR3_H__
#define __VECTOR3_H__

#include <math.h>

/////////////////////////////////////////////////////////////
//
// Vector3类  简单的3D向量类
//
/////////////////////////////////////////////////////////////

class Vector3
{
public:
    float x, y, z;

// 构造函数

    // 默认构造函数,不执行任何操作
    Vector3() {}

    // 拷贝构造函数
    Vector3(const Vector3 &a) : x(a.x), y(a.y), z(a.z) {}

    // 带参数的构造函数,用三个值完成初始化
    Vector3(float nx, float ny, float nz) : x(nx), y(ny), z(nz) {}

// 标准对象操作

    // 重载“=”操作符
    Vector3& operator =(const Vector3 &a)
    {
        x = a.x; y = a.y; z = a.z;
        return *this;
    }

    // 重载“==”操作符
    bool operator ==(const Vector3 &a) const
    {
        return x==a.x && y==a.y && z==a.z;
    }

    // 重载“==”操作符
    bool operator !=(const Vector3 &a) const
    {
        return x!=a.x || y!=a.y || z!=a.z;
    }

// 向量运算

    // 向量归零
    void zero() { x = y = z = 0.0f; }

    // 重载一元“-”运算符
    Vector3 operator -() const { return Vector3(-x, -y, -y); }

    // 重载二元“+”和“-”运算符
    Vector3 operator +(const Vector3 &a) const
    {
        return Vector3(x+a.x, y+a.y, z+a.z);
    }

    Vector3 operator -(const Vector3 &a) const
    {
        return Vector3(x-a.x, y-a.y, z-a.z);
    }

    // 与标量的乘、除法
    Vector3 operator *(float a) const
    {
        return Vector3(x*a, y*a, z*a);
    }

    Vector3 operator /(float a) const
    {
        float oneOverA = 1.0f/a;
        return Vector3(x*oneOverA, y*oneOverA, z*oneOverA);
    }

    // 重载自反运算符
    Vector3& operator +=(const Vector3 &a)
    {
        x+= a.x; y+= a.y; z+= a.z;
        return *this;
    }

    Vector3& operator -=(const Vector3 &a)
    {
        x-= a.x; y-= a.y; z-= a.z;
        return *this;
    }

    Vector3& operator *=(const Vector3 &a)
    {
        x*= a.x; y*= a.y; z*= a.z;
        return *this;
    }

    Vector3& operator /=(float a)
    {
        float oneOverA = 1.0f/a;
        x*= oneOverA; y*=oneOverA; z*= oneOverA;
        return *this;
    }

    // 向量标准化
    void normailze()
    {
        float magSq = x*x +y*y +z*z;
        if ( magSq > 0.0f )
        {
            float oneOverMag = 1.0f / sqrtf(magSq);
            x*= oneOverMag;
            y*= oneOverMag;
            z*= oneOverMag;
        }
    }

    // 向量点乘,重载标准的乘法运算符
    float operator *(const Vector3 &a) const
    {
        return x*a.x + y*a.y + z*a.z;
    }
};

/////////////////////////////////////////////////////////////
//
// 非成员函数
//
/////////////////////////////////////////////////////////////

// 求向量模
inline float vectorMag(const Vector3 &a)
{
    return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z);
}

// 计算向量叉乘
inline Vector3 crossProduct(const Vector3 &a, const Vector3 &b)
{
    return Vector3(
        a.y*b.z - a.z*b.y,
        a.z*b.x - a.x*b.z,
        a.x*b.y - a.y*b.x
    );
}

 // 实现标量左乘
inline Vector3 operator *(float k, const Vector3 &v)
{
    return Vector3(k*v.x, k*v.y, k*v.z);
}

// 计算两点间距离
inline float distance(const Vector3 &a, const Vector3 &b)
{
    float dx = a.x-b.x;
    float dy = a.y-b.y;
    float dz = a.z-b.z;
    return sqrtf(dx*dx + dy*dy + dz*dz);
}

/////////////////////////////////////////////////////////////
//
// 全局变量
//
/////////////////////////////////////////////////////////////

// 提供一个全局零向量
extern const Vector3 kZeroVector;

#endif  // __VECTOR3_H__

1.2 物理学

本书中定义物理学如下:质量和能量以及它们之间互相作用的科学。游戏人工智能程序员常常会运用物理定律进行工作,特别是与运动有关的物理定律,即在这部分会介绍的内容。

1.2.1 时间

时间是一个标量(用它的大小就可以完全确定,没有方向),用秒来度量,简写成s。

1.2.2 距离

距离(一个标量)的标准单位是m (米)。

1.2.3 质量

质量是一个标量,用千克度量,简写成kg。质量是一个事物的总量的度量(不包括外力)。

1.2.4 位置

位置是相对于质心来度量的属性,质量的中心是物体的平衡点。假想在这一点上系一根绳子悬挂物体,物体可以在任何一个位置都保持平衡。另一
个想象质心的好方法是把它看作物体内所有质量的平衡位置。

1.2.5 速度

速度是一个矢量(一个具有大小和方向的量),表达了距离相对于时间的变化率。度量速度的标准单位是mls (米每秒)。它用数学公式表达为:

Δx表示距离上的变化,结束时候的距离减去开始移动时候的距离。Δt代表速度上的变化,结束时的时间减去开始移动时候的时间。

1.2.6 加速度

加速度是一个矢量,表达的是在时间段上速度的变化率,用米每二次方秒来度量,写作m/s²。加速度可以用数学式表达为:

1.2.7 力

力( Force) 是可以改变物体的速度或者运动线路的量。

我们知道如果施加在一个物体上的合力是非零的,就在该力的方向上产生了一个加速度;但是加速度是多少?答案是加速度的大小a 与物体的质量m 成反比,与所施加的合力F 成正比。这个关系可以用下式给出:

更多情况下,你将会看到写成这样的公式:

使用这个公式,如果我们知道一个物体的加速度有多大,并且知道它的质量,就可以计算施加在它上面的合力。

例如,如果一个物体的质量为2000kg ,井且它的加速度为1.5m/s²,施加在它上面的合力是:

《游戏人工智能编程案例精粹》读书笔记—数学和物理学初探

时间: 2024-11-04 14:11:19

《游戏人工智能编程案例精粹》读书笔记—数学和物理学初探的相关文章

《游戏人工智能编程案例精粹》读书笔记&mdash;状态驱动智能体设计

一个有限状态机是一个设备,或是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使得从一个状态变换到另一个状态,或者是促使一个输出或者一种行为的发生.一个有限状态机在任何瞬间只能处于一种状态. 状态变换表 状态变换表是一个条件和那些条件导致的状态的表,这个表可以被智能体在规则的间隔内训问,使得它能基于从游戏环境中接收到刺激进行必须的状态转换. 内置的规则 每个状态模块依靠自身的逻辑来决定它是否应该运行自己变换到一个替代状态,智能体只向外部提供操作和获取自身属性的函数,状态

【游戏设计模式】之四 《游戏编程模式》读书笔记:全书内容梗概总结

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/53240330 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 本文的Github版本:QianMo/Reading-Notes/<游戏编程模式>读书笔记 这是一篇超过万字读书笔记,总结了<游戏编程模式>一书中所有章节与内容的知识梗概. 我们知道,游戏行业其实一直很缺一本系

VC++编程之道读书笔记(2)

第三篇 技术细节 第七章:细说开发人员必知必会的39个开发细节 细节36:单例模式的应用 在开发程序时,往往需要在整个工程中只需要一个类的实例.而这个实例一旦被创建就不能被其他的实例再创建了,通常我们称这个实现过程为单例模式. 既然要保证类只有一个实例,那么就需要其他的类不能使用实例化该类.因此,需要将其构造方法设为私有的,即使用private关键字修饰.同时,类中提供一个静态方法,该方法的返回值是该类的一个实例.这样就只能使用该静态方法来获取类的实例了,从而保证了唯一性. 下面通过具体代码来实

VC++编程之道读书笔记

第二篇 缪误21:位图数据是按照红绿蓝顺序存储的 大家都知道位图的颜色是由红.绿.蓝三个分量构成的,但是位图颜色数据存储的方式则不是按照这个顺序存储的,而是按照蓝.绿.红的顺序存储的.并且对于真彩色位图来说,位图的颜色数据是倒序存储的,即位图的第一行数据位于位图数据的最底部. 第三篇 细节12 :内存中的数组 在C++中通过数组可以操作内存,创建数组时需要为数组分配内存空间,操作数组时就是对内存空间中的数组元素进行操作.数组创建后,数组引用和数组元素分别存储在栈内存和堆内存中,并通过数组引用与数

《Linux多线程编程手册》读书笔记

第二章 基本线程编程 1.(P25)如果多个线程等待同一个线程终止,则所有等待线程将一直等到目标线程终止.然后,一个等待线程成功返回,其余的等待线程将失败并返回ESRCH错误. 2.(P26)将新线程的pbe参数作为栈参数进行传递.这个线程参数之所以能够作为栈参数传递,是因为主线程会等待辅助线程终止.不过,首选方法是使用malloc从堆分配存储,而不是传递指向线程栈存储的地址.如果将该参数作为地址传递到线程栈存储,则该地址可能无效或者在线程终止时会被重新分配. 3.(P28)pthread_de

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software

《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候都会发生缓冲.通过缓冲可以在一定程度上将用户空间与实际的物理设备分离,还可以减少内核访问磁盘的次数. 先来看看关于内核缓冲区高速缓冲:read和write调用在对磁盘文件进行操作的时候不会直接访问磁盘,如下图所示. 例如:write(fd, "abc", 3) write调用会将"

《Linux/Unix系统编程手册》读书笔记9(文件属性)

<Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有更深入的研究一定会写出来. 下图为磁盘分区与文件系统的关系 文件系统中的文件(目录)在i-node表上都有唯一的记录(i-node).i-node通过数据块指针指向数据块,这些数据块就是该i-node对应的文件的数据. i-node与数据块的关系如下: 因为Linux支持很多类型的文件系统,但是每种文件系统的

编程之美读书笔记1.8 - 小飞的电梯调度算法

http://blog.csdn.net/pipisorry/article/details/36688019 问题: 亚洲微软研究院所在的希格玛大厦一共有6部电梯.在高峰时间,每层都有人上下,电梯每层都停.实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法: 由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层.所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层.在一楼的时候,每个乘客选择自己的目