自己写的粒子系统

先来一个效果图嘚瑟一下。
这里写图片描述

就是一个喷泉效果。

粒子效果是很好看的
我写的时候考虑到 平移 旋转 缩放 还有透明。
很可惜,透明我没有搞,旋转在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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

当当小螳螂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值