先来一个效果图嘚瑟一下。
就是一个喷泉效果。
粒子效果是很好看的
我写的时候考虑到 平移 旋转 缩放 还有透明。
很可惜,透明我没有搞,旋转在windows里面找到
setworldtransform函数可以旋转图片,可惜我没有研究清楚,就只有 平移和缩放了。
粒子的大约属性就是围绕这两个属性来的。
当然还有发射图片的选择。
一个开始我想 一个粒子系统可以有多个发射源。后来觉得有点小难就只有一个发射源了,当然是可以有很多发射源的。
好了,就是一个记录。
程序架构 主文件
// tWinMain.cpp : Defines the entry point for the application.
//
#include "windows.h"
#include "tchar.h"
#include "ResMgr.h"
#include "Back.h"
#include "GlobalDef.h"
#include "ParticleSystem.h"
#define _USE_MATH_DEFINES
#include "math.h"
#define WNDWIDTH BKWIDTH
#define WNDHEIGHT BKHEIGHT
// Global Variables:
HWND g_hWnd = NULL;
DWORD g_dwPreTick = 0;
DWORD g_dwCurTick = 0;
HDC g_hDrawDC = NULL;
HDC g_hSwapDC = NULL;
HBITMAP g_hComBitmap = NULL;
CResMgr g_ResMgr;
CBack g_Back;
CParticleSystem g_ParticleSystem;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL GameInit(HWND hWnd);
VOID GamePaint(HWND hWnd);
BOOL GameCleanup(HWND hWnd);
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg = {0};
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
g_dwCurTick = GetTickCount();
if (g_dwCurTick - g_dwPreTick > 10)
{
g_dwPreTick = g_dwCurTick;
GamePaint(g_hWnd);
}
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("WndClass");
wcex.hIconSm = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(_T("WndClass"), _T("LearnGame"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, WNDWIDTH, WNDHEIGHT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
g_hWnd = hWnd;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if (!GameInit(hWnd))
{
return FALSE;
}
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
GameCleanup(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL GameInit(HWND hWnd)
{
HDC hdc = GetDC(hWnd);
g_hSwapDC = CreateCompatibleDC(hdc);
g_hDrawDC = CreateCompatibleDC(hdc);
g_hComBitmap = CreateCompatibleBitmap(hdc, WNDWIDTH, WNDHEIGHT);
srand(timeGetTime());
if (!g_ResMgr.Init())
{
return FALSE;
}
if (!g_ParticleSystem.Init("snow.bmp", 1000, WNDWIDTH / 2, WNDHEIGHT / 2, 10, 10, 0, -30, 30, 2, 0, 3, 0, 0, 20, 20, 5, 5, 0, WNDWIDTH, 0, WNDHEIGHT, 20, 0))
{
return FALSE;
}
ReleaseDC(hWnd, hdc);
GamePaint(hWnd);
return TRUE;
}
VOID GamePaint(HWND hWnd)
{
HDC hdc = GetDC(hWnd);
SelectObject(g_hSwapDC, g_hComBitmap);
g_Back.Paint(g_hSwapDC, g_hDrawDC);
g_ParticleSystem.Paint(g_hSwapDC, g_hDrawDC);
BitBlt(hdc, 0, 0, WNDWIDTH, WNDHEIGHT, g_hSwapDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc);
}
BOOL GameCleanup(HWND hWnd)
{
DeleteObject(g_hComBitmap);
DeleteObject(g_hDrawDC);
DeleteObject(g_hSwapDC);
return TRUE;
}
资源管理类文件
#include "ResMgr.h"
#include "GlobalDef.h"
#include "algorithm"
CResMgr::CResMgr()
{
}
CResMgr::~CResMgr()
{
for_each(m_BitMap.begin(), m_BitMap.end(), [](pair<string, HBITMAP> rPair){
DeleteObject(rPair.second);
});
m_BitMap.clear();
}
bool CResMgr::Init()
{
HBITMAP hBack = (HBITMAP)LoadImage(NULL, _T("bg.bmp"), IMAGE_BITMAP, BKWIDTH, BKHEIGHT, LR_LOADFROMFILE);
if (hBack == NULL)
{
return false;
}
m_BitMap.insert(make_pair("bg.bmp", hBack));
HBITMAP hPlayer = (HBITMAP)LoadImage(NULL, _T("player.bmp"), IMAGE_BITMAP, 100, 100, LR_LOADFROMFILE);
if (hPlayer == NULL)
{
return false;
}
m_BitMap.insert(make_pair("player.bmp", hPlayer));
HBITMAP hSnow = (HBITMAP)LoadImage(NULL, _T("snow.bmp"), IMAGE_BITMAP, 380, 413, LR_LOADFROMFILE);
if (hSnow == NULL)
{
return false;
}
m_BitMap.insert(make_pair("snow.bmp", hSnow));
return true;
}
HBITMAP CResMgr::GetBitMap(string name)
{
BitMapMapItor bItor = m_BitMap.find(name);
if (bItor != m_BitMap.end())
{
return bItor->second;
}
return NULL;
}
粒子系统实现文件
#include "ParticleSystem.h"
CParticle::CParticle()
{
}
CParticle::~CParticle()
{
}
bool CParticle::Init(CParticleSystem* pSystem,CEmitter* pEmitter)
{
this->m_pSystem = pSystem;
this->m_pEmitter = pEmitter;
m_hBitmap = m_pSystem->m_hBitmap;
Reset();
return true;
}
void CParticle::Reset()
{
m_bDead = false;
m_x = PartcleRand(m_pSystem->m_x, m_pSystem->m_xRand);
m_y = PartcleRand(m_pSystem->m_y, m_pSystem->m_yRand);
m_xSpeed = PartcleRand(m_pSystem->m_xSpeed, m_pSystem->m_xSpeedRand);
m_ySpeed = PartcleRand(m_pSystem->m_ySpeed, m_pSystem->m_ySpeedRand);
m_xSpeedFactor = PartcleRand(m_pSystem->m_xSpeedFactor, m_pSystem->m_xSpeedFactorRand);
m_ySpeedFactor = PartcleRand(m_pSystem->m_ySpeedFactor, m_pSystem->m_ySpeedFactorRand);
m_width = PartcleRand(m_pSystem->m_particleWidth, m_pSystem->m_particleWidthRand);
m_height = PartcleRand(m_pSystem->m_particleHeight, m_pSystem->m_particleHeightRand);
}
int CParticle::PartcleRand(int base, int factor)
{
return factor == 0 ? base : (base + rand() % factor - factor / 2);
}
bool CParticle::GetDead()
{
return m_bDead;
}
void CParticle::Paint(HDC hSwapDC, HDC hDrawDC)
{
if (!m_bDead)
{
SelectObject(hDrawDC, m_hBitmap);
TransparentBlt(hSwapDC, m_x, m_y, m_width, m_height, hDrawDC, 0, 0, 380, 413, RGB(0, 0, 0));
m_xSpeed += m_xSpeedFactor;
m_ySpeed += m_ySpeedFactor;
m_x += m_xSpeed;
m_y += m_ySpeed;
if (m_x <= m_pSystem->m_xLeft || m_x >= m_pSystem->m_xRight || m_y <= m_pSystem->m_yTop || m_y >= m_pSystem->m_yBottom)
{
m_bDead = true;
}
}
}
CEmitter::CEmitter()
{
}
CEmitter::~CEmitter()
{
if (nSpawn>0)
{
for_each(m_aliveVec.begin(), m_aliveVec.end(), [](CParticle* particle){
delete particle;
});
m_aliveVec.clear();
}
}
bool CEmitter::Init(CParticleSystem* pSystem)
{
this->m_pSystem = pSystem;
return true;
}
void CEmitter::Paint(HDC hSwapDC, HDC hDrawDC)
{
if (!m_aliveVec.empty())
{
for_each(m_aliveVec.begin(), m_aliveVec.end(), [=](CParticle* particle){
if (!particle->GetDead())
{
particle->Paint(hSwapDC, hDrawDC);
}
});
}
if (nSpawn < m_pSystem->m_nMaxNum)
{
int SpawnNum = m_pSystem->m_nEmitParticle;
if (m_pSystem->m_nEmitParticleRand != 0)
{
SpawnNum = SpawnNum + rand() % m_pSystem->m_nEmitParticleRand - m_pSystem->m_nEmitParticleRand / 2;
}
for (int idx = 0; idx < SpawnNum; idx++)
{
CParticle* particle = new CParticle();
particle->Init(this->m_pSystem, this);
m_aliveVec.push_back(particle);
nSpawn++;
}
}
else
{
int SpawnNum = m_pSystem->m_nEmitParticle;
if (m_pSystem->m_nEmitParticleRand != 0)
{
SpawnNum = SpawnNum + rand() % m_pSystem->m_nEmitParticleRand - m_pSystem->m_nEmitParticleRand / 2;
}
for (int idx = 0; idx < SpawnNum; idx++)
{
vector<CParticle*>::iterator vItor = find_if(m_aliveVec.begin(), m_aliveVec.end(), [](CParticle* particle){
if (particle->GetDead())
{
particle->Reset();
return true;
}
return false;
});
}
}
}
CParticleSystem::CParticleSystem()
{
m_pEmitter = NULL;
}
CParticleSystem::~CParticleSystem()
{
if (m_pEmitter != NULL)
{
delete m_pEmitter;
m_pEmitter = NULL;
}
}
void CParticleSystem::Paint(HDC hSwapDC, HDC hDrawDC)
{
m_pEmitter->Paint(hSwapDC, hDrawDC);
}
bool CParticleSystem::Init(string picName,
int nMaxNum,
int x,
int y,
int xRand,
int yRand,
int xSpeed,
int ySpeed,
int xSpeedRand,
int ySpeedRand,
int xSpeedFactor,
int ySpeedFactor,
int xSpeedFactorRand,
int ySpeedFactorRand,
int width,
int height,
int wRand,
int hRand,
int xLeft,
int xRight,
int yTop,
int yBottom,
int nEmitParticle,
int nEmitParticleRand)
{
this->m_hBitmap = g_ResMgr.GetBitMap(picName);
if (this->m_hBitmap == NULL)
{
return false;
}
m_nMaxNum = nMaxNum;
m_x = x;
m_y = y;
m_xRand = xRand;
m_yRand = yRand;
m_xSpeed = xSpeed;
m_ySpeed = ySpeed;
m_xSpeedRand = xSpeedRand;
m_ySpeedRand = ySpeedRand;
m_xSpeedFactor = xSpeedFactor;
m_ySpeedFactor = ySpeedFactor;
m_xSpeedFactorRand = xSpeedFactorRand;
m_ySpeedFactorRand = ySpeedFactorRand;
m_particleWidth = width;
m_particleHeight = height;
m_particleWidthRand = wRand;
m_particleHeightRand = hRand;
m_xLeft = xLeft;
m_xRight = xRight;
m_yTop = yTop;
m_yBottom = yBottom;
m_nEmitParticle = nEmitParticle;
m_nEmitParticleRand = nEmitParticleRand;
m_pEmitter = new CEmitter();
m_pEmitter->Init(this);
return true;
}
一些个全局宏定义文件
#pragma once
#define BKWIDTH 1366
#define BKHEIGHT 768
然后是游戏物体实现文件
#include "GameObject.h"
#include "GlobalDef.h"
CGameObject::CGameObject()
{
x = 0;
y = 0;
}
CGameObject::~CGameObject()
{
}
void CGameObject::Paint(HDC hSwapDC, HDC hDrawDC)
{
}
其实没啥可说的,结构我看着很清楚,但是自己写的罢了。
其他的 资源需要时32位的bmp
需要链接 msimg32.lib winmm.lib库
就这吧
没地方放了 一个cocos2dx 飘字代码
void HelloWorld::showTipText(int x, int y, const string& text)
{
auto pLabel = Label::createWithTTF(text, "fonts/Marker Felt.ttf", 24);
pLabel->setPosition(x, y);
pLabel->setString(text);
this->addChild(pLabel, 1, 1000);
CCFadeIn* actionFadeIn = CCFadeIn::create(1.0f);
CCMoveBy* actionMoveBy = CCMoveBy::create(1.0f, Vec2(0.0f, 40.0f));
CCEaseSineOut* actionEaseSineOut = CCEaseSineOut::create(actionMoveBy);
CCSpawn* actionSpawnIn = CCSpawn::create(actionFadeIn, actionEaseSineOut, NULL);
CCFadeOut* actionFadeOut = CCFadeOut::create(0.5f);
CCMoveBy* actionMoveBy2 = CCMoveBy::create(0.5f, Vec2(0.0f, 40.0f));
CCEaseSineIn* actionEaseSineOut2 = CCEaseSineIn::create(actionMoveBy2);
CCSpawn* actionSpawnIn2 = CCSpawn::create(actionFadeOut, actionEaseSineOut2, NULL);
CCCallFunc* actionCallFunc = CCCallFunc::create(this, callfunc_selector(HelloWorld::setLabelVisibleFalse));
CCSequence* actions = CCSequence::create(actionSpawnIn, actionSpawnIn2, actionCallFunc, NULL);
pLabel->runAction(actions);
}
void HelloWorld::setLabelVisibleFalse()
{
removeChildByTag(1000);
}