游戏编程中需要掌握哪些数学物理知识

一、 相似三角形知识的应用

在摇杆控制物体运动的游戏中,摇杆的手柄(下图黄色圆饼),不能移出摇杆所在的套(下图灰色圆环),也就是说摇杆偏离中心点的最大距离为max_R。一旦触摸移动过程中移动的点超出此最大距离,我们需要将摇杆手柄拖回到最大距离处。

如何将摇杆拖回到灰色圆环处,无非是要求出在C点的坐标。根据△ODC和△OBA为相似三角形,有OD:OB = OC:OA,也就是?:pos.x = max_R:len。

其中pos为A点的坐标(x,y),len为向量OA的模。

?表示C点的x坐标,也就是但是我们求出来,要作为新的pos,去设置摇杆的位置。

所以有:

二、 单位向量

在摇杆控制物体的运动时,如果摇杆只控制物体的方向,也就是说不管摇杆偏离原点多远,都不会影响物体运动的速度,而只影响物体运动的方向,也就是实质上我们要获取一个方向的值(比如向量与x轴正方向的夹角),这时候,我们就需要使用单位向量。

单位向量是指向量的模为1的向量,也就是以一个单位长度为半径画一个圆,从圆心指向圆周上任意一点的向量都是单位向量。

假设单位向量OA与x轴正向的夹角为α,则向量OA可以用(cosα,sinα)表示,也就是A点的坐标。如下图所示:

所以不管任何向量,我们要转换为单位向量,只需要计算出这个向量的余弦和正弦值就可以了。例如向量OC我们将其转换为单位向量就是OC’,因为OC’的长度为1,所以向量OC’的坐标就是(cos(c),sin(c)),c为OC和x轴正方向的夹角。而OC’和OC的方向是重合的,他们与x轴正向夹角相等,也就是我们只需要计算向量OC的cos(c)、sin(c)即可。

假设得到的C点坐标为pos(x,y),则在Cocos游戏开发中,会有下列代码:

var len = pos.mag(); // 求向量pos的模(内部算法是(x2+y2)开根号)。

pos.x = pos.x / len;  // 得到单位向量的x坐标

pos.y = pos.y/ len;  // 得到单位向量的y坐标

三、 弧度角度转换

角度指从原点发出的射线与X轴正向的角度。而x轴正向绕原点在水平平面内旋转一周为360°。而弧度是指圆弧长度与半径的比值。假设有个半径r为1的圆,则其一周为360°。圆周对应的弧度长为2πr=2π。也就是说在角度转换为弧度是360°等价于2π,180°等价于π。

(1)弧度转换为角度:根据 degree : 180 = rad:π

var rad = Math.atan2(y,  x);  // 反正切函数,得到弧度

var degree = 180 * rad / Math.PI ; // 将弧度rad转换为角度

(2)角度转换为弧度:根据rad:π=degree:180

var degree = 90;

var rad = Math.PI * degree / 180; // 角度转换为弧度

四、 向量转换为夹角

在游戏中,有时候我们需要计算物体旋转了多少度,比如我们要模拟一个KTV里面的游戏转盘,手指触摸的时候,要获取触摸的点的位置,触摸点的位置与转盘中心点之间构成一个向量,我们要获取转动了多少度,就需要有一个参考向量。

如下图所示,假如蓝色的圆就是转盘的边缘,我们最开始触摸A点,然后转动到B点,这时候转动的角度就是∠AOB,这个角度在Cocos中如何求呢?

代码pos就表示B点的坐标,pos和原点(0,0)相减,得到向量OB,也即代码中的dirVec,弧AB为radian,转换为角度degree。

// 向量转换为角度

vectorsToDegree(dirVec) {

// 水平向右的对比向量

let comVec = cc.v2(1, 0);

// 求方向向量与对比向量间的弧度

let radian = dirVec.signAngle(comVec);

// 将弧度转换为角度

let degree = cc.misc.radiansToDegrees(radian);

return degree;

},

调用示例(具体可以参考我们的《KTV酒令转盘虚拟仿真实现》):

// 获取触摸点与原点连线的射线与X轴正向的角度

getTouchAngle(e){

var screen_pos = e.getLocation();  // 触摸点世界坐标

    // 转换为相对于当前节点的锚点的坐标

var pos = this.node.convertToNodeSpaceAR(screen_pos);

// 获取触摸点距离轮盘中心点的向量

var dirVec = pos.sub(cc.v2(0,0));

// 将向量转换为基于参考方向(v2(0,1))的角度

return this.vectorsToDegree(dirVec);

},

五、 切水果游戏中的抛物线

重力加速g:

Vy = V0 + g * t;

h = V0 * t + 0.5 * g * t * t;

斜抛运动(如下图所示):

分解到水平上: 匀速直线运动;

分解到竖直方向: 匀变速直线运动 (加速度)。

具体在Cocos中如何实现,限于篇幅,在此不做赘述,可以参考我们的公开课《切水果》核心技术:抛物线物理仿真。

六、 如何产生不重复的随机序列

应用场景:例如洗牌,发牌,例如扫雷游戏中从100个格子中随机抽取10个埋雷。

凡是需要打乱顺序,或者从某个数组中抽取一定数量的不重复的元素,都用得着。

// 数组工具类

var ArrayUtils = function(){};

// 【1】初始化得到有序元素数组:[start,end)的自然数序列

ArrayUtils.initOrderArray = function(start, end){

let sortArray = [];

for(let i= start; i<end; i++){

        sortArray.push(i);

    }

return sortArray;

};

// 【2】从数组arr中随机抽取count个元素,返回数组

ArrayUtils.randChoiseFromArr = function(arr, count){

let result = arr;

// 随机排序,打乱顺序

result.sort(function(){

return 0.5 - Math.random();

    });

// 返回打乱顺序后的数组中的前count个元素

return result.slice(0,count);

};

// 【3】从从start到end中的连续整数中随机抽取count个数字

ArrayUtils.randChoiseFromTo = function(start, end, count){

let arr = this.initOrderArray(start,end);

return this.randChoiseFromArr(arr, count);

};

// 【2】-【方式二】从数组arr中随机抽取count个元素,返回数组

ArrayUtils.getRandomArrayElements = function(arr, count) {

// 从0位置取到结束位置存入shffled数组

let shuffled = arr.slice(0);

let i = arr.length;

let min = i - count;

let temp = 0;

let index = 0;

// 随机一个位置的元素和最后一个元素交换

    // 随机一个位置元素和倒数第二个元素交换

    // 假设i=8,count=3,则min=5,

    // 循环体中[i]=7,6,5,也就是说最后三个元素要从数组中随机取

    // 循环结束后,从min=5的位置取到结束,即取3个元素。

while(i-- > min) {

        index = Math.floor((i + 1) * Math.random());

        temp = shuffled[index];

        shuffled[index] = shuffled[i];

        shuffled[i] = temp;

    }

return shuffled.slice(min);

};

module.exports = ArrayUtils;

原理解析:如上述代码,方式一randChoiseFromArr 方法,采用随机排序打乱数组中所有元素的顺序,然后从数组第一个元素开始抽取需要的count个元素。

方式二getRandomArrayElements方法,需要取几个元素,就随机几个位置和倒数最后几个元素交换,最后取倒数最后几个元素即可。注意:index = Math.floor((i + 1) * Math.random()); i+1才能保证最后一个元素可能是自身和自身交换,也就是保证这个位置的元素可能是原有这个位置的元素。

上面所有代码我们已经全部测试通过,感兴趣的朋友可以自己动手去实践。

相似三角形、单位向量转换、弧度角度转换,大家可以看我们的公开课《Cocos Creator坦克大战游戏》。向量转换为夹角在我们公开课《KTV酒令转盘虚拟仿真实现》中讲过。如何产生不重复的随机序列,在扫雷游戏中应用。需要这方面资料视频的朋友,可以点击下面链接加群了解点击链接加入群聊【cocos/unity交流群】

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 148,827评论 1 317
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 63,511评论 1 266
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 99,318评论 0 218
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,108评论 0 189
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,112评论 1 266
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,387评论 1 185
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,905评论 2 283
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,657评论 0 177
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,144评论 0 223
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,744评论 2 225
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,100评论 1 236
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,565评论 2 222
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,041评论 3 216
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,769评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,301评论 0 178
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,173评论 2 239
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,313评论 2 242

推荐阅读更多精彩内容