Directx9学习(九)碰撞——基于边界和基于距离
2017-10-03 10:33
225 查看
好久没有碰D3D了,生疏了太多。忘记了如何新建窗口,写到这里,下次再用的时候就可以看这个。
然后是初始化D3D,首先需要创建变量
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
然后在窗口进入主消息循环之前调用Init就可以初始化了
从文件装载texture,写成一个函数方便用
然后设置矩阵:
然后绘制带变化的Sprite
准备工作差不多就OK了,由于生疏了所以都写了一遍,没有进展。
这次首先使用基于边界的碰撞检测:只是实现一个简单的,利用WINAPI IntersectRect 实现一个根据边界判断是否有碰撞的功能,不过旋转目前不会弄。按下空格键,图片1前进10个单位
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 按键按下
bool IntersectRect(LPRECT lprcDst,RECT* rect1,RECT* rect2 ) 看后面的两个RECT是否存在交集
步骤差不多是 首先声明一个SPRITE结构,参数是:
然后在初始化的时候给这两个sprite初始量,定下他们的位置和贴图,由于还需要获得确定图片的长和宽,赋给两个变量,所以这里改写了LoadTexture函数,让他传入两个整形的地址并在LoadTexture中改变这两个整形让他们存储原始图片的长和宽
在初始化函数中添加:
然后就是在主消息循环中画图了
然后是基于距离的:原理很简单,两个点(图片中心)的距离小于等于两个图片的半径之和的时候就撞上了。
bool Collition_Dis(D3DXVECTOR2 pos1, D3DXVECTOR2 pos2, float dis)
{
int deltaX = pos1.x - pos2.x;
int deltaY = pos1.y - pos2.y;
if ((deltaX * deltaX + deltaY * deltaY) < dis*dis)
{
return true; //撞上
}
else
return false;
}
然后是看图片是否撞上,要获得图片的长和宽
int w1 = sp1.collitionRect.right - sp1.collitionRect.left;
int w2 = sp2.collitionRect.right - sp2.collitionRect.left;
int h1 = sp1.collitionRect.bottom - sp1.collitionRect.top;
int h2 = sp2.collitionRect.bottom - sp2.collitionRect.top;
D3DXVECTOR2 vec1(sp1.collitionRect.left + (int)(0.5f*w1), sp1.collitionRect.top + (int)(0.5f*h1));
D3DXVECTOR2 vec2(sp2.collitionRect.left + (int)(0.5f*w2), sp2.collitionRect.top + (int)(0.5f*h2));
canSP1Move = !Collition_Dis(vec1, vec2, (int)((w1 + w2)*0.5f)); //如果canSP1Move 为否,就说明撞了
上面两个就是基本的碰撞检测的两种方法。
这次由于好久不看了 感觉很简单的东西花了好长时间才弄好。。。感觉最近懵得很。。唉 慢慢来吧
#include"MyD3D.h" //#include<windows.h> //窗口回调函数 LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: gameOver = true; //跳出那个消息循环 否则就算关了还会一直跑 PostQuitMessage(0); break; } return DefWindowProc(hwnd, msg, wParam, lParam); } //winMain int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, LPSTR lpCmdLine, int nCmdShow) { //初始化窗口设定 WNDCLASSEX wc; //wc必须都初始化 wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WinProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = "MainWindowClass"; wc.lpszMenuName = NULL; wc.hIconSm = NULL; RegisterClassEx(&wc); HWND window = CreateWindow( "MainWindowClass", "MainWindowClass", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, NULL, NULL, hInstance, NULL ); if (window == 0) return 0; ShowWindow(window, nCmdShow); UpdateWindow(window); MSG message; //主消息循环 while (!gameOver) { if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&message); DispatchMessage(&message); } } return message.wParam; }
然后是初始化D3D,首先需要创建变量
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
然后在窗口进入主消息循环之前调用Init就可以初始化了
bool Direct3D_Init(HWND hwnd, int width, int height, bool fullScreen) { d3d = Direct3DCreate9(D3D_SDK_VERSION); if (!d3d) return false; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); //这样设置呈现参数能够保证可以创建透明的Sprite d3dpp.Windowed = (!fullScreen); d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.BackBufferCount = 1; d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.hDeviceWindow = hwnd; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.EnableAutoDepthStencil = 1; //以呈现参数创建d3ddev d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev ); if (!d3ddev) return false; }
从文件装载texture,写成一个函数方便用
//从文件装载Texture LPDIRECT3DTEXTURE9 LoadTexture(string fileName, D3DCOLOR transColor) { LPDIRECT3DTEXTURE9 tex = NULL; D3DXIMAGE_INFO info; //获得图片信息 HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info); if (result != D3D_OK) return NULL; //从文件加载纹理 result = D3DXCreateTextureFromFileEx( d3ddev, fileName.c_str(), info.Width, info.Height, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, transColor, &info, NULL, &tex ); if (result != D3D_OK) return NULL; return tex; }
然后设置矩阵:
//设置矩阵 D3DXMATRIX SetMartex(int x, int y, int width,int height, float rotation, float scaling) { D3DXVECTOR2 scale(scaling, scaling); D3DXVECTOR2 trans(x, y); D3DXVECTOR2 center((float)(width*scaling) / 2, (float)(height*scaling) / 2); D3DXMATRIX mat; D3DXMatrixTransformation2D(&mat, NULL, 0, &scale, ¢er, rotation, &trans); return mat; }
然后绘制带变化的Sprite
//绘制带变换的Sprite void DrawSpriteWithTrans(LPD3DXSPRITE _sprite,LPDIRECT3DTEXTURE9 tex, D3DXMATRIX mat,D3DCOLOR color) { _sprite->SetTransform(&mat); //设置矩阵然后画整张图片 _sprite->Draw(tex, NULL, NULL, NULL, color); }
准备工作差不多就OK了,由于生疏了所以都写了一遍,没有进展。
这次首先使用基于边界的碰撞检测:只是实现一个简单的,利用WINAPI IntersectRect 实现一个根据边界判断是否有碰撞的功能,不过旋转目前不会弄。按下空格键,图片1前进10个单位
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 按键按下
bool IntersectRect(LPRECT lprcDst,RECT* rect1,RECT* rect2 ) 看后面的两个RECT是否存在交集
步骤差不多是 首先声明一个SPRITE结构,参数是:
struct SPRITE { LPD3DXSPRITE m_sprite; //Sprite LPDIRECT3DTEXTURE9 tex; //Texture RECT collitionRect; //碰撞矩形 float scaling, rotation; //旋转和缩放 D3DCOLOR color; SPRITE() { color = D3DCOLOR_XRGB(255, 252, 255); scaling = 1.0f; rotation = 0.0f; m_sprite = NULL; tex = NULL; } }; //声明两个SPRITE变量 SPRITE sp1, sp2;
然后在初始化的时候给这两个sprite初始量,定下他们的位置和贴图,由于还需要获得确定图片的长和宽,赋给两个变量,所以这里改写了LoadTexture函数,让他传入两个整形的地址并在LoadTexture中改变这两个整形让他们存储原始图片的长和宽
在初始化函数中添加:
//初始化sprite //创建Sprite D3DXCreateSprite(d3ddev, &sp1.m_sprite); D3DXCreateSprite(d3ddev, &sp2.m_sprite); int *w , *h ; //存储原始Texture的长度和宽度 w = new int(); h = new int(); sp1.tex = LoadTexture("D:\\Personal\\Documents\\My Pictures\\c75c10385343fbf24781fe05b17eca8065388f63.jpg",D3DCOLOR_XRGB(255,255,255), w, h); sp1.collitionRect.left = 0; sp1.collitionRect.right = (*w)*sp1.scaling; //长度和宽度应该乘上缩放量才是碰撞体本身的长宽 sp1.collitionRect.top = 0; sp1.collitionRect.bottom = (*h)*sp1.scaling; sp2.tex = LoadTexture("D:\\Personal\\Documents\\My Pictures\\111724628725fc12aao.jpg", D3DCOLOR_XRGB(255, 255, 255), w, h); sp2.collitionRect.left = 500; sp2.collitionRect.right = 500 + (*w)*sp2.scaling; sp2.collitionRect.top = 0; sp2.collitionRect.bottom = (*h)*sp2.scaling;
然后就是在主消息循环中画图了
while (!gameOver) { if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&message); DispatchMessage(&message); } if (KEY_DOWN(VK_SPACE)) { //修改碰撞的位置 if (!keyHasDown) { RECT rec; //判断是否会撞上 canSP1Move = !IntersectRect(&rec, &(sp1.collitionRect), &(sp2.collitionRect)); if (canSP1Move) { int w = sp1.collitionRect.right - sp1.collitionRect.left; sp1.collitionRect.left += 10; sp1.collitionRect.right = sp1.collitionRect.left + w; times += 10; //修改变换矩阵 mat1 = SetMartex(times, 0, sp1.collitionRect.left + w, sp1.collitionRect.bottom, 0.0f, 1.0f); keyHasDown = true; } } } else { keyHasDown = false; } //清空缓存 就没有之前画的重影了 否则之前的就会一直在上面 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0F, 0); //绘画 if (d3ddev->BeginScene()) { sp1.m_sprite->Begin(D3DXSPRITE_ALPHABLEND); DrawSpriteWithTrans(sp1.m_sprite, sp1.tex, mat1, D3DCOLOR_XRGB(255, 252, 255)); sp1.m_sprite->End(); sp2.m_sprite->Begin(D3DXSPRITE_ALPHABLEND); DrawSpriteWithTrans(sp2.m_sprite, sp2.tex, mat2, D3DCOLOR_XRGB(255, 252, 255)); sp2.m_sprite->End(); d3ddev->EndScene(); d3ddev->Present(NULL, NULL, NULL, NULL); } }
然后是基于距离的:原理很简单,两个点(图片中心)的距离小于等于两个图片的半径之和的时候就撞上了。
bool Collition_Dis(D3DXVECTOR2 pos1, D3DXVECTOR2 pos2, float dis)
{
int deltaX = pos1.x - pos2.x;
int deltaY = pos1.y - pos2.y;
if ((deltaX * deltaX + deltaY * deltaY) < dis*dis)
{
return true; //撞上
}
else
return false;
}
然后是看图片是否撞上,要获得图片的长和宽
int w1 = sp1.collitionRect.right - sp1.collitionRect.left;
int w2 = sp2.collitionRect.right - sp2.collitionRect.left;
int h1 = sp1.collitionRect.bottom - sp1.collitionRect.top;
int h2 = sp2.collitionRect.bottom - sp2.collitionRect.top;
D3DXVECTOR2 vec1(sp1.collitionRect.left + (int)(0.5f*w1), sp1.collitionRect.top + (int)(0.5f*h1));
D3DXVECTOR2 vec2(sp2.collitionRect.left + (int)(0.5f*w2), sp2.collitionRect.top + (int)(0.5f*h2));
canSP1Move = !Collition_Dis(vec1, vec2, (int)((w1 + w2)*0.5f)); //如果canSP1Move 为否,就说明撞了
上面两个就是基本的碰撞检测的两种方法。
这次由于好久不看了 感觉很简单的东西花了好长时间才弄好。。。感觉最近懵得很。。唉 慢慢来吧
相关文章推荐
- V-rep学习笔记:碰撞检测与距离计算
- 笔记:基于距离的多物体碰撞检测
- 基于ZF中的.htaccess文件学习Apache的Rewrite语法
- 基于 Python 的数据结构与算法分析学习记录(6-6)—— 分析树
- 学习手记-基于iTOP4412 tftp服务器的搭建与测试
- OpenCV学习笔记-卷积边界
- 基于VTK User Guide和VTK Textbook学习
- JBox2D学习 - 小球碰撞实例 .
- Hibernate学习09---基于XML配置的一对一单向外键关联
- MFC学习日记十一:Mfc基于对话框编程之逃跑按钮(第八课)
- 基于android NDK的初步学习
- 基于分离轴定理的二维游戏碰撞检测算法
- Matlab图像识别/检索系列(6)-10行代码完成深度学习网络之基于CNN的图像分类
- 基于stm32f103zet6的定时器的学习3(定时器产生4路PWM)
- Spring4学习笔记-AOP(基于注解的方式)
- openshift/origin学习记录(1)——基于二进制文件的安装(单机版)
- 基于STM32的USB枚举过程学习笔记
- [转]基于 Android NDK 的学习之旅-----环境搭建
- Caffe_Linux学习笔记(一)基于Ubuntu16.04+CPU only+Python2.7环境下的Caffe配置
- 3.A计划学习--基于MVC开发俄罗斯方块