D3D游戏编程系列(六):自己动手编写第一人称射击游戏之第一人称视角的构建
说起第一人称射击游戏,不得不提第一人称视角啊,没有这个,那么这个第一就无从谈起啊,我作为一个观察者究竟如何在这个地图上顺利的移动和观察呢,那么,我们一起来研究下。
我们首先来看下CDXCamera类:
- class CDXCamera
- {
- public:
- void Go(float fLen); //前进
- void Back(float fLen); //后退
- void Up(float fLen); //上升
- void Down(float fLen); //下降
- void Left(float fLen); //左移
- void Right(float fLen); //右移
- void TurnLeft(float fAngle); //向左转
- void TurnRight(float fAngle); //向右转
- void TurnUp(float fAngle); //向上看
- void TurnDown(float fAngle); //向下看
- void Reset(CDXWindow *pWin,D3DXVECTOR3 vEye,D3DXVECTOR3 vAt); //初始化
- void SetTransForm(); //设置取景变换
- D3DXVECTOR3 GetEye();
- D3DXVECTOR3 GetAt();
- float GetX();
- float GetY();
- float GetZ();
- float GetRightAngle(); //水平转向的角度
- float GetUpAngle(); //垂直转向的角度
- protected:
- LPDIRECT3DDEVICE9 m_pDevice;
- D3DXVECTOR3 m_vEye;
- D3DXVECTOR3 m_vAt;
- D3DXVECTOR3 m_vUp;
- float m_fRightAngle;
- float m_fUpAngle;
- float m_fRad;
- };
上面的这个类我相信大家应该明白个大概了吧,其实在DX的龙书上就有关于Camera的叙述,不过我这里和他的实现有点不同。我们首先来看一下这个Camera是如何创建的:
- void CDXCamera::Reset(CDXWindow *pWin,D3DXVECTOR3 vEye,D3DXVECTOR3 vAt)
- {
- m_pDevice=pWin->GetD3dDevice();
- D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);
- m_vUp=vUp;
- m_vEye=vEye;
- m_vAt=vAt;
- m_fRad=sqrtf(powf(m_vAt.x-m_vEye.x,2)+powf(m_vAt.z-m_vEye.z,2));
- m_fRightAngle=acos((m_vAt.z-m_vEye.z)/m_fRad)*180/D3DX_PI;
- if((m_vAt.x-m_vEye.x)/m_fRad<0)
- {
- m_fRightAngle=360-m_fRightAngle;
- }
- cout<<m_fRightAngle<<endl;
- m_fUpAngle=atan((m_vAt.y-m_vEye.y)/m_fRad)*180/D3DX_PI;
- }
大家可以看到,我在处理水平角度上做了一个判断,因为是360度都可以旋转,所以直接去计算cos会有问题,我这里先判断sin的值,再决定角度是在0到180度还是180度到360度。那么我们要往前走一步,这个又是如何实现的呢,假设行走的距离为fLen个长度,那么便有如下代码:
float x,z;
x=fLen*sin(m_fRightAngle*(D3DX_PI/180.0f));
z=fLen*cos(m_fRightAngle*(D3DX_PI/180.0f));
m_vEye.x+=x;
m_vEye.z+=z;
是不是很简单的就解决这个问题了呢,好,接下去,我们假设要向左旋转fAngle个角度,该怎么办呢:
float x,z;
float fTempAngle=m_fRightAngle;
m_fRightAngle-=fAngle;
if(m_fRightAngle<0)
{
m_fRightAngle=360+fTempAngle-fAngle;
}
x=m_fRad*sin(m_fRightAngle*(D3DX_PI/180.0f));
z=m_fRad*cos(m_fRightAngle*(D3DX_PI/180.0f));
m_vAt.x=m_vEye.x+x;
m_vAt.z=z+m_vEye.z;
首先我们判断旋转后的角度是否在0到360度之间,否则调整角度,然后计算出需要需要移动的x和z的大小,然后和当前的Eye相加,便是新的At位置。于是我们就完成了旋转。依次类推,其他方法也是这样实现的。
在这个CDXCamera构建完成后,如何应用到我们的游戏中去呢,那么就是在游戏的逻辑帧里面做判断,如果当前没有和墙壁以及其他人物碰撞的话,便行走,同时把人物的骨骼动画移动到当前Camera的位置,否则原地不动。还有一点的就是如何用鼠标控制观察视角的上下左右呢,大家应该还记得DIMOUSESTATE这个对象吧:
typedef struct _DIMOUSESTATE {
LONG lX;
LONG lY;
LONG lZ;
BYTE rgbButtons[4];
} DIMOUSESTATE, *LPDIMOUSESTATE;
lX,lY,lZ便是相对于上次移动的相对坐标,我们只要去判断这个相对坐标的大小,便可以去改变观察视角了。
- int iMouseX=DXMouseMickeyX();
- int iMouseY=DXMouseMickeyY();
- if(iMouseX>0)
- {
- m_Camera.TurnRight(iMouseX*0.1);
- m_Player.SetMatrix(m_Camera.GetRightAngle(),m_Camera.GetEye(),m_fDeltaTime);
- _SendPlayerPosMsg(&m_Player);
- }else if(iMouseX<0)
- {
- m_Camera.TurnLeft(-iMouseX*0.1);
- m_Player.SetMatrix(m_Camera.GetRightAngle(),m_Camera.GetEye(),m_fDeltaTime);
- _SendPlayerPosMsg(&m_Player);
- }
- if(iMouseY>0)
- {
- m_Camera.TurnDown(iMouseY*0.1);
- float fAngle=m_Camera.GetUpAngle();
- if(fAngle<=270 && fAngle>=90)
- {
- m_Camera.TurnUp(270-fAngle+1);
- }
- }else if(iMouseY<0)
- {
- m_Camera.TurnUp(-iMouseY*0.1);
- float fAngle=m_Camera.GetUpAngle();
- if(fAngle<=270 && fAngle>=90)
- {
- m_Camera.TurnDown(fAngle-90+1);
- }
- }
还是很简单的吧,最后我们clipwindow并且showcursor一下,便可以欺骗玩家眼睛,让玩家可以用鼠标随意控制上下左右视角的效果了。
其实关于第一人称射击游戏还有很多的内容,我这里给大家留下一个小问题,就是如何去判断一个子弹是否击中对方了呢,我们怎么在子弹的运行轨迹中去识别墙壁这些障碍物呢,呵呵,其实是有一定数学小技巧的,大家想一想应该能想到的。
本文有不足之处,还望大家多多指正。
D3D游戏编程系列(六):自己动手编写第一人称射击游戏之第一人称视角的构建的更多相关文章
- Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo完结篇
懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 ) 写下这些东西的同时 旁边放了两部电影 周星驰的<还魂夜> 甄子丹的<特殊身份& ...
- D3D游戏编程系列(四):自己动手编写即时战略游戏之网络同步
说到网络同步,这真是一个网络游戏的重中之重,一个好的网络同步机制,可以让玩家的用户体验感飙升,至少,我玩过的魔兽争霸在网络同步方面做得非常好,即便是网络状况很不稳定,依然可以保证用户数据不会出现意想不 ...
- WCF编程系列(六)以编程方式配置终结点
WCF编程系列(六)以编程方式配置终结点 示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...
- 学习ASP.NET Core Blazor编程系列六——新增图书(上)
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- OWIN系列之自己动手编写中间件
一.前言 1.基于OWIN的项目摆脱System.Web束缚脱颖而出,轻量级+跨平台,使得ASP.NET应用程序只需依赖这个抽象接口,不用关心所运行的Web服务器. 2.OWIN.dll介绍 使用反编 ...
- 异步编程系列第04章 编写Async方法
p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...
- 学习ASP.NET Core Razor 编程系列六——数据库初始化
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 学习ASP.NET Core Blazor编程系列六——初始化数据
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- [C入门 - 游戏编程系列] 贪吃蛇篇(一) - 世界定义
每个游戏都有一个很明确的目的或者说游戏主题,贪吃蛇的目的很明确:蛇找到并吃掉食物.只有目的是很无聊的,算不上一个好游戏.所以设计者增加了创意:1. 吃掉食物后蛇会增长:2. 吃掉食物后分数会增加.有些 ...
随机推荐
- H264/AVC视频解码时AVC1和H264的区别
AVC1与H264的区别 http://blog.csdn.net/qiuchangyong/article/details/6660253 H.264 Video Types The followi ...
- intelliJ idea读取资源文件
原文:intelliJ idea读取资源文件 原文地址 http://yanwushu.sinaapp.com/intellij-idea_raed_resource_file/ 官方文档 以下是je ...
- (原创)CityEngine 2014和ArcGIS 10.3冲突问题的解决
先卸载ArcGIS License Manager 10.3 安装ArcGIS License Manager 10.2.2 用keygen算出ArcGIS 10.3的许可,似乎本许可在ArcGI ...
- 2014年最火的 21个JavaScript 框架
下面,我们将会介绍 2014 年最火的 21 款JavaScript 框架,专为前端开发者准备的哦:)众所周知, JavaScript 框架是 JavaScript编程语言最棒的特性之一. JavaS ...
- 分布式java应用
大型应用,通常会拆分为多个子系统来实现. 对Java来说,这些子系统可能部署在同一台机器的多个不同的JVM中,也可能部署在不同的机器上,但这些子系统又不是完全独立的,要相互通信来共同实现业 ...
- Ubuntu12.04下arm交叉编译环境的建立
http://blog.csdn.net/heyangya2009/article/details/5424376 备注:ubuntu12.04+Android+Real6410 在主机上用来编译其他 ...
- C语言一维数组中的数据随机排列
#include <stdio.h>#include <stdlib.h> void randomlize(int *a, int n){ int i = 0,j ...
- [转载]12款免费与开源的NoSQL数据库介绍
Naresh Kumar是位软件工程师与热情的博主,对于编程与新事物拥有极大的兴趣,非常乐于与其他开发者和程序员分享技术上的研究成果.近日,Naresh撰文谈到了12款知名的免费.开源NoSQL数据库 ...
- word2010中莫名出现灰色中括号解决方案
灰色中括号[]是文中书签,解决方案: word 文件-选项-高级,在“显示文档内容”部分,去掉“显示书签”前面的勾选.
- (六)学习CSS之color属性
参考:http://www.w3school.com.cn/cssref/pr_text_color.asp color 属性规定文本的颜色. 这个属性设置了一个元素的前景色(在 HTML 表现中,就 ...