简易的Win32小球碰撞程序
Posted 独饮月色的猫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简易的Win32小球碰撞程序相关的知识,希望对你有一定的参考价值。
//--------------------------------------------------------------
// - classes.cpp
// - To define different classes
//--------------------------------------------------------------
// Marcos and constants
#define TITLE_NAME "Running Ball"
#define WINDOW_CLASS_NAME "DrimoonA1"
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
const int WINDOW_WIDTH = GetSystemMetrics(SM_CXFULLSCREEN);
const int WINDOW_HEIGHT = (GetSystemMetrics(SM_CYFULLSCREEN)+77);
// Structs and Classes
struct Point
int x, y;
;
class Velo
public:
int vx, vy;
Velo()
vx=0, vy=0;
double GetVelo();
;
class Ball
public:
Point p;
Velo v;
int r;
HPEN pen;
public:
Ball();
void InitPos(int, int);
void DrawBall(HDC hDC);
void Control();
void Process();
bool IsCollision(Ball* ball);
void SwapVelo(Ball* ball);
;
//--------------------------------------------------------------
// - functions.cpp
// - To define functions of different classes
//--------------------------------------------------------------
#include <windows.h>
#include <cmath>
#include "classes.h"
// Point class function
// Velo class function
double Velo::GetVelo()
return sqrt(vx*vx+vy*vy);
// Ball class function
Ball::Ball()
p.x=50, p.y=50;
v.vx=10, v.vy=10;
r=50;
pen=NULL;
void Ball::InitPos(int x0, int y0)
p.x=x0, p.y=y0;
void Ball::DrawBall(HDC hDC)
Arc(hDC,p.x-r,p.y-r,p.x+r,p.y+r,0,0,0,0);
void Ball::Control()
if (KEYDOWN(VK_DOWN))
v.vy++;
if (KEYDOWN(VK_UP))
v.vy--;
if (KEYDOWN(VK_LEFT))
v.vx--;
if (KEYDOWN(VK_RIGHT))
v.vx++;
if (KEYDOWN(VK_SPACE))
v.vx=0, v.vy=0;
void Ball::Process()
p.x += v.vx;
p.y += v.vy;
if (p.x <= r || p.x >= WINDOW_WIDTH - r)
v.vx = -v.vx;
p.x += v.vx;
if (p.y <= r || p.y >= WINDOW_HEIGHT - r)
v.vy = -v.vy;
p.y += v.vy;
bool Ball::IsCollision(Ball* ball)
int disX = (this->p.x+this->v.vx)-(ball->p.x+ball->v.vx);
int disY = (this->p.y+this->v.vy)-(ball->p.y+ball->v.vy);
int dis = disX*disX+disY*disY;
if(dis <= 4*r*r)
return true;
return false;
void Ball::SwapVelo(Ball* ball)
Velo tmp;
tmp = v;
v = ball->v;
ball->v = tmp;
//--------------------------------------------------------------
// - main.cpp
// - To demo Running Ball
//--------------------------------------------------------------
#include <windows.h>
#include <ctime>
#include "classes.h"
#define WIN32_LEAN_AND_MEAN
// Global varibles
HDC g_hDC=NULL;
const int BALL_NUM = 10;
Ball ball[BALL_NUM];
RECT rect=0,0,WINDOW_WIDTH,WINDOW_HEIGHT;
HBRUSH myBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
// Function prototype
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Erase();
void Frame();
// WinMain
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
HWND hWnd;
MSG msg;
int i;
MyRegisterClass(hInstance);
hWnd = CreateWindowEx(NULL,
WINDOW_CLASS_NAME,
TITLE_NAME,
WS_POPUP | WS_VISIBLE,
0,0,
WINDOW_WIDTH,WINDOW_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if(!hWnd)
return 0;
SetWindowLong(hWnd,GWL_EXSTYLE,GetWindowLong(hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd,0,220,LWA_ALPHA);
g_hDC=GetDC(hWnd);
srand((unsigned)(time(0)));
for(i=0;i<BALL_NUM;i++)
ball[i].InitPos(ball[i].r+rand()%(WINDOW_WIDTH-2*ball[i].r),ball[i].r+rand()%(WINDOW_HEIGHT-2*ball[i].r));
for (i = 0; i < BALL_NUM; i++)
for (int j = i + 1; j < BALL_NUM; j++)
if (ball[i].IsCollision(&ball[j]))
ball[i].InitPos(ball[i].r + rand() % (WINDOW_WIDTH - 2 * ball[i].r), ball[i].r + rand() % (WINDOW_HEIGHT - 2 * ball[i].r));
while(TRUE)
DWORD start_time = GetTickCount();
if( PeekMessage(&msg,NULL,0,0,PM_REMOVE) )
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
Frame();
while((GetTickCount() - start_time) < 33);
if (KEYDOWN(VK_ESCAPE))
SendMessage(hWnd, WM_CLOSE, 0, 0);
return msg.wParam;
// Register window class
ATOM MyRegisterClass(HINSTANCE hInstance)
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(hInstance, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_CLASS_NAME;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
void Erase()
SelectObject(g_hDC,myBrush);
FillRect(g_hDC,&rect,myBrush);
DeleteObject(myBrush);
void Frame()
int i;
Erase();
ball[0].Control();
for(i=0; i<BALL_NUM; i++)
switch(i%6)
case 0:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(255,0,0));
SelectObject(g_hDC,ball[i].pen);
break;
case 1:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(0,255,80));
SelectObject(g_hDC,ball[i].pen);
break;
case 2:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(0,0,255));
SelectObject(g_hDC,ball[i].pen);
break;
case 3:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(0,255,200));
SelectObject(g_hDC,ball[i].pen);
break;
case 4:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(125,0,255));
SelectObject(g_hDC,ball[i].pen);
break;
case 5:
ball[i].pen=CreatePen(PS_SOLID,3,RGB(255,120,0));
SelectObject(g_hDC,ball[i].pen);
break;
default:
break;
ball[i].DrawBall(g_hDC);
DeleteObject(ball[i].pen);
ball[i].Process();
for(i=0; i<BALL_NUM; i++)
for(int j=i+1; j<BALL_NUM; j++)
if(ball[i].IsCollision(&ball[j]))
ball[i].SwapVelo(&ball[j]);
//PlaySound(".\\\\Hit.wav",NULL,SND_ALIAS|SND_ASYNC);
Ball tmp;
tmp=ball[i];
ball[i]=ball[j];
ball[j]=tmp;
// Window Process
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
PAINTSTRUCT ps;
HDC hdc;
switch (message)
case WM_CREATE:
return 0;
case WM_TIMER:
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT rt;
GetClientRect(hWnd, &rt);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default: break;
return DefWindowProc(hWnd, message, wParam, lParam);
注意:
1、Windows Application,纯Windows API写的, #define WIN32_LEAN_AND_MEAN 表示不使用MFC相关内容。
2、小球碰撞的物理逻辑不够完善,非对心碰撞的物理逻辑尚未完成。
3、为什么没有注释?因为大多是一些框架代码,相信阅读起来很简单,只是代码看起来多一点。。。下次注意!
4、实现窗口半透明代码要用到WS_EX_LAYERED宏,此宏在VC++6.0那个年代里。。windows API中还没有加入Window EX Style。。所以请在高阶的VC++2005(就是VS2005装C++版本)啊什么的运行,当然了,你把它注释掉或者换用
SetWindowLong(hWnd,GWL_EXSTYLE,GetWindowLong(hWnd,GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary(_T("User32.DLL"));
if(hInst != NULL)
typedef BOOL (WINAPI *MYFUNC)(HWND, COLORREF, BYTE, DWORD);
MYFUNC pFunc=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");
if(pFunc!=NULL)
pFunc(m_hWnd,0,220,2);
FreeLibrary(hInst);
hInst=NULL;
以上是关于简易的Win32小球碰撞程序的主要内容,如果未能解决你的问题,请参考以下文章