世嘉MD游戏开发进阶篇【三】:向量归一化的实现及应用

news/2024/11/28 0:49:46/

向量归一化是非常有用的,游戏中经常能用到,就说大家都见过的,FC魂斗罗的敌人发射子弹就能用到了,敌人向玩家发射子弹首先要获取到向量,这个向量不能直接作为方向去用,必须要经过归一化处理才行,经过归一化处理后你才能精确的设置子弹的速度,不然子弹的速度是不可控的。

我做了个小demo来演示玩家向目标点移动的效果,跟魂斗罗的敌人向玩家发射子弹是一样的道理,效果图如下:

黑色的小方框是玩家,黑色的小点就是移动的目标点。

我先介绍一下向量归一化的计算方法吧:

//比如有一个向量v
Vector3 v = new Vector3(6.0, 10.0, 15.0);//计算出向量所有元素的和,这里sum = 31,要是有元素是负数要用绝对值
float sum = v.x + v.y + v.z;//每一个元素除以sum
v.x /= sum;
v.y /= sum;
v.z /= sum;得到归一化的向量: [0.19, 0.32, 0.48]

在SGDK中的代码如下:

/*角色自动向点的方向移动,角色到点的距离小于等于1.5的时候,点的位置会随机改变
*/#include <genesis.h>
#include <vdp.h>
#include "resources.h"//目标点的坐标
Vect2D_f16 point;//角色坐标
Vect2D_f16 charPos;//精灵,目标点
Sprite *spr_point = NULL;//精灵,角色
Sprite *spr_char = NULL;//角色移动的速度
fix16 moveSpeed = FIX16(0.04);//角色到点的最小距离
fix16 minDistance = FIX16(1.5);//向量归一化
Vect2D_f16 vector_normalize(Vect2D_f32 _v);//随机设置点的位置
void randomPoint();int main()
{//绘制标题VDP_drawText("Vector Normalize", 12, 0);//设置PAL0的调色板VDP_setPalette(PAL0, res_point.palette->data);//初始化spriteSPR_init();//初始化点的位置charPos.x = FIX16(0);charPos.y = FIX16(0);//初始化角色的位置point.x = FIX16(60);point.y = FIX16(40);//设置点的精灵图片spr_point = SPR_addSprite(&res_point, fix16ToRoundedInt(point.x), fix16ToRoundedInt(point.y), TILE_ATTR(PAL0, 0, 0, 0));//设置角色的精灵图片spr_char = SPR_addSprite(&res_char, fix16ToRoundedInt(charPos.x), fix16ToRoundedInt(charPos.y), TILE_ATTR(PAL0, 0, 0, 0));//更新精灵SPR_update();while (TRUE){//dir用来计算方向向量Vect2D_f32 dir;//你想去哪个位置,就用哪个位置减去自己的位置dir.x = point.x - charPos.x;dir.y = point.y - charPos.y;//获取归一化的方向Vect2D_f16 _nDir = vector_normalize(dir);//这一段是勾股定理的内容,目的是求出角色到点的距离,A² + B² = C²,不多做解释了,详细看我的世嘉MD游戏开发进阶教程之两点的距离fix32 powX = dir.x * dir.x;fix32 powY = dir.y * dir.y;fix32 powDist = minDistance * minDistance;fix32 sumXY = powX + powY;//距离大于最小距离,也就是没碰到目标点if (sumXY > powDist){//向点的方向运动,方向_nDir和每帧移动速度moveSpeedcharPos.x += _nDir.x * moveSpeed;charPos.y += _nDir.y * moveSpeed;}else{//碰到目标点后随机改变目标点的位置randomPoint();}//这俩都是很基础的内容了,设置精灵的坐标SPR_setPosition(spr_char, fix16ToRoundedInt(charPos.x), fix16ToRoundedInt(charPos.y));SPR_setPosition(spr_point, fix16ToRoundedInt(point.x), fix16ToRoundedInt(point.y));//更新精灵SPR_update();VDP_waitVSync();}return 0;
}//向量归一化,计算方法是,先计算出向量所有数的和,二维向量就是x+y,三维向量就是x+y+z,然后再用每个元素除以这个和,得出归一化的元素
Vect2D_f16 vector_normalize(Vect2D_f32 _v)
{Vect2D_f16 _tmp;fix16 sum = fix32ToFix16(abs(_v.x) + abs(_v.y));_tmp.x = fix16Div(fix32ToFix16(_v.x), sum);_tmp.y = fix16Div(fix32ToFix16(_v.y), sum);return _tmp;
}//随机设置点的位置
void randomPoint()
{point.x = FIX16(random() % 319);point.y = FIX16(random() % 223);
}

还是挺简单的^_^


http://www.ppmy.cn/news/535667.html

相关文章

django中发送get post请求并获得数据

django中发送get post请求并获得数据 项目结构如下注册路由 urls.py在处理函数中处理请求 views.py进行 get的请求01浏览器 get请求传参数02服务器django get参数解析获取01浏览器 post的发送浏览器get 请求 获取页面返回的 form 发送post请求 带参数 02服务器django的post请求…

世嘉MD游戏开发进阶篇【二】:C语言实现有限状态机

有限状态机应用是非常广泛的&#xff0c;比如关卡的切换、角色动画状态的切换等等&#xff0c;我自己写了个有限状态机&#xff0c;开发世嘉MD游戏的朋友可以用得到&#xff0c;对于解耦还是有点帮助的&#xff0c;不必挤在一个文件里。 没有学过MD游戏开发基础的可以翻看我写…

世嘉MD游戏开发【十一】:背景卷轴滚动(视差滚动)Parallax Scroll和摄像机

背景卷轴这个名字现在比较少听到了&#xff0c;现在的游戏引擎都不用这项技术了&#xff0c;或者可以轻松实现这个功能不值一提了&#xff0c;又或者不用这个技术照样也可以等等原因&#xff0c;大家基本听不到了。 玩过世嘉MD模拟器的可能对图层分层显示这个功能有印象&#…

世嘉MD游戏开发【三】:输入控制(上)

这一节讲一下SGDK中的输入控制&#xff0c;SGDK提供了两种输入控制方式&#xff0c;一种是用回调函数接收输入信息&#xff0c;很自然的另一种就没有用回调函数了&#xff08;貌似废话-.-!&#xff09;&#xff0c;成上下两节&#xff0c;这一节讲不用回调函数来接收输入信息。…

世嘉MD游戏开发【六】:矩形填充Tile图块

上节课讲了如何显示一个Tile图块&#xff0c;这节课我来讲一下Tile图块的矩形填充。 打开Sega Genesis Tile Designer&#xff0c;设置tile宽度为4tiles&#xff0c;高度也是4tiles&#xff1a; 随便绘制几个tile块&#xff0c;下面我用我自己绘制的作为例子&#xff1a; 导出…

世嘉MD游戏开发【八】:淡入和淡出

淡入淡出&#xff0c;很好理解&#xff0c;淡入就是画面由黑过渡到彩色&#xff0c;淡出就是画面由彩色过渡到黑色&#xff0c;其实也不一定必须是黑色&#xff0c;看你自己需求了。 注&#xff1a;淡入淡出的功能可以完成非常多的游戏玩法设计哦~打开脑洞就有惊喜~ 效果图如…

世嘉MD游戏开发进阶篇【一】:两点之间的距离

开发游戏免不了要计算两个坐标之间的距离&#xff0c;计算两点之间的距离我们可以用勾股定理&#xff0c;比如说A代表直角三角形的一条直角边&#xff0c;B代表另一条直角边&#xff0c;C代表斜边&#xff0c;得到公式ABC。C也就是两点之间的距离&#xff0c;根据公式可计算出C…

世嘉MD游戏开发【十】:精灵动画,Sprite Animation

能在世嘉MD上显示自己做的精灵动画实在是一件令人兴奋的事啊&#xff0c;今天就来讲一下如何在MD上显示精灵动画。 先准备好一张精灵图片序列&#xff0c;有这么几点要求&#xff1a; 1.单个精灵的像素宽x高不能超过16384&#xff0c;(以tile为单位的话&#xff0c;就是16x16…