1. 程式人生 > >cocos2dx 利用隨機數模擬雪花飄落、粒子系統

cocos2dx 利用隨機數模擬雪花飄落、粒子系統

執行截圖

這裡寫圖片描述

隨機數

  • 注意隨機種子的設定需要在for迴圈的外面
  • 用到了cocos2dx的 CCRANDOM_0_1
/** @def CCRANDOM_0_1
 returns a random float between 0 and 1
 */
#define CCRANDOM_0_1() ((float)rand()/RAND_MAX)
TIMEVAL psv;
gettimeofday(&psv, NULL);
// 初始化隨機種子
// timeval是個結構體,裡邊有倆個變數,一個是以秒為單位的,一個是以微妙為單位的 
unsigned rand_seed = (unsigned
)(psv.tv_sec * 1000 + psv.tv_usec / 1000); //都轉化為毫秒 srand(rand_seed); for (int i = 0; i < N; i++) { int a = 0; int b = visibleSize.width; float xt = CCRANDOM_0_1() * (b - a + 1) + a; a = 0; b = visibleSize.height; float yt = CCRANDOM_0_1() * (b - a + 1) + a; vx[i] = origin.x + xt; vy[i] = origin.y
+ yt; labels[i] = Label::createWithSystemFont("*", "Arial", 24); // position the label on the center of the screen labels[i]->setPosition(Point(vx[i], vy[i])); // add the label as a child to this layer this->addChild(labels[i], 1); }

完整程式碼

.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__ #include <vector> #include "cocos2d.h" #define N 200 USING_NS_CC; class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // a selector callback void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); public: virtual void update(float delta); void menuStopCallback(cocos2d::Ref* pSender); void menuSlowCallback(cocos2d::Ref* pSender); void menuMidCallback(cocos2d::Ref* pSender); void menuFastCallback(cocos2d::Ref* pSender); MenuItemFont *stop; // MenuItemFont *slow; // MenuItemFont *mid; // MenuItemFont *fast; public: Size visibleSize; Point origin; Label* labels[N]; float speed; float vx[N]; float vy[N]; }; #endif // __HELLOWORLD_SCENE_H__

.cpp

#include "HelloWorldScene.h"
#include <cstdlib>
#include <ctime>

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    visibleSize = Director::getInstance()->getVisibleSize();
    origin = Director::getInstance()->getVisibleOrigin();


    // add a label shows "Hello World"
    // create and initialize a label

#if 0
    //LabelTTF* label = LabelTTF::create("1", "Arial", 24);
    Label* label = Label::createWithSystemFont("1", "Arial", 24);

    // position the label on the center of the screen
    label->setPosition(Point(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(label, 1);
#endif

    TIMEVAL psv;
    gettimeofday(&psv, NULL);
    // 初始化隨機種子
    // timeval是個結構體,裡邊有倆個變數,一個是以秒為單位的,一個是以微妙為單位的 
    unsigned rand_seed = (unsigned)(psv.tv_sec * 1000 + psv.tv_usec / 1000);    //都轉化為毫秒 
    srand(rand_seed);

    for (int i = 0; i < N; i++)
    {
        int a = 0;
        int b = visibleSize.width;
        float xt = CCRANDOM_0_1() * (b - a + 1) + a;

        a = 0;
        b = visibleSize.height;
        float yt = CCRANDOM_0_1() * (b - a + 1) + a;

        vx[i] = origin.x + xt;
        vy[i] = origin.y + yt;

        labels[i] = Label::createWithSystemFont("*", "Arial", 24);

        // position the label on the center of the screen
        labels[i]->setPosition(Point(vx[i], vy[i]));

        // add the label as a child to this layer
        this->addChild(labels[i], 1);
    }

    speed = 1;

    this->scheduleUpdate(); // 定時器
    //
    MenuItemFont::setFontSize(22);// 系統設定字型大小
stop = MenuItemFont::create("stop");
    stop->setTarget(this, menu_selector(HelloWorld::menuStopCallback));
    //
slow = MenuItemFont::create("slow");
    slow->setColor(Color3B::RED);
    slow->setTarget(this, menu_selector(HelloWorld::menuSlowCallback));
    //
mid = MenuItemFont::create("mid");
    mid->setTarget(this, menu_selector(HelloWorld::menuMidCallback));
    //
fast = MenuItemFont::create("fast");
    fast->setTarget(this, menu_selector(HelloWorld::menuFastCallback));

    //建立一個選單容器 把選單欄目放上去
    Menu *menu = Menu::create(stop, slow, mid, fast, NULL);
    //顯示選單
    this->addChild(menu);
    //選單的顯示位置
    menu->setPosition(Point(50,visibleSize.height - 100));
    //設定欄目間的寬度距離
    menu->alignItemsVerticallyWithPadding(10.0);


    return true;
}

void HelloWorld::update(float delta)
{
    for (int i = 0; i < N; i++)
    {
        vy[i] -= speed;//2.0;
        if (vy[i] <= 0)
        {
            int a = 0;
            int b = visibleSize.width;
            vx[i] = origin.x + CCRANDOM_0_1() * (b - a + 1) + a;
            vy[i] = visibleSize.height;
        }
        labels[i]->setPosition(Point(vx[i], vy[i]));
    }
}

// 改變下落的速度
void HelloWorld::menuStopCallback(cocos2d::Ref* pSender)
{
    this->unscheduleUpdate();
    speed = -1.0;

    stop->setColor(Color3B::RED);
    slow->setColor(Color3B::WHITE);
    mid->setColor(Color3B::WHITE);
    fast->setColor(Color3B::WHITE);
}
void HelloWorld::menuSlowCallback(cocos2d::Ref* pSender)
{
    if (speed < 0)
        this->scheduleUpdate(); 
    speed = 1.0;

    stop->setColor(Color3B::WHITE);
    slow->setColor(Color3B::RED);
    mid->setColor(Color3B::WHITE);
    fast->setColor(Color3B::WHITE);
}
void HelloWorld::menuMidCallback(cocos2d::Ref* pSender)
{
    if (speed < 0)
        this->scheduleUpdate();
    speed = 3.0;

    stop->setColor(Color3B::WHITE);
    slow->setColor(Color3B::WHITE);
    mid->setColor(Color3B::RED);
    fast->setColor(Color3B::WHITE);
}
void HelloWorld::menuFastCallback(cocos2d::Ref* pSender)
{
    if (speed < 0)
        this->scheduleUpdate();
    speed = 6.0;

    stop->setColor(Color3B::WHITE);
    slow->setColor(Color3B::WHITE);
    mid->setColor(Color3B::WHITE);
    fast->setColor(Color3B::RED);
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
    MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    //Director::getInstance()->end();
    speed = 10;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

粒子系統實現snow

bg.png

snow.png
這裡寫圖片描述

#include "HelloWorldScene.h"
#include <cstdlib>
#include <ctime>

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    visibleSize = Director::getInstance()->getVisibleSize();
    origin = Director::getInstance()->getVisibleOrigin();

    auto bg = Sprite::create("bg.png");
    bg->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
    this->addChild(bg);

#if 0
    ParticleSystem* ps = ParticleSnow::createWithTotalParticles(9999);
    //ParticleSystem* ps = ParticleSnow::create();
    ps->setTexture(Director::getInstance()->getTextureCache()->addImage("snow.png"));
    ps->setPosition(Point(visibleSize.width/2, visibleSize.height + 10));//生成的雪花從這個座標往下落
    //ps->setEmissionRate(10);
    ps->setSpeed(200);
    ps->setLife(10);
    this->addChild(ps);
#endif

#if 1
    auto particleSystem = ParticleSystemQuad::createWithTotalParticles(200);
    //設定雪花粒子紋理圖片
    particleSystem->setTexture(TextureCache::getInstance()->addImage("snow.png"));
    //設定發射粒子的持續時間-1表示永遠持續
    particleSystem->setDuration(-1);
    //這個點是相對發射點,x正方向為右,y正方向為上 ,可以設定發射的方向
    particleSystem->setGravity(Point(-10, -20));

    //設定角度以及偏差
    particleSystem->setAngle(90);
    particleSystem->setAngleVar(360);

    //設定徑向加速度以及偏差
    particleSystem->setRadialAccel(10);
    particleSystem->setRadialAccelVar(0);

    //設定粒子的切向加速度以及偏差
    particleSystem->setTangentialAccel(30);
    particleSystem->setTangentialAccelVar(30);

    // 設定粒子初始化位置偏差
    //particleSystem->setPosition(CCPoint(400, 500));
    particleSystem->setPosVar(Point(400, 0));


    //設定粒子生命期以及偏差
    particleSystem->setLife(4);
    particleSystem->setLifeVar(2);

    //設定粒子開始時候旋轉角度以及偏差
    particleSystem->setStartSpin(30);
    particleSystem->setStartSpinVar(60);

    //設定結束時候的旋轉角度以及偏差
    particleSystem->setEndSpin(60);
    particleSystem->setEndSpinVar(60);

    //設定開始時候的顏色以及偏差
    particleSystem->setStartColor(Color4F(1, 1, 1, 1));
    //設定結束時候的顏色以及偏差
    particleSystem->setEndColor(Color4F(0.9, 0.9, 0.9, 1));

    //設定開始時候粒子大小以及偏差
    particleSystem->setStartSize(30);
    particleSystem->setStartSizeVar(0);

    //設定粒子結束時候大小以及偏差
    particleSystem->setEndSize(20.0f);
    particleSystem->setEndSizeVar(0);

    //設定每秒鐘產生粒子的數量
    particleSystem->setEmissionRate(100);

    // 粒子系統位置
    particleSystem->setPosition(Point(visibleSize.width * 0.75, visibleSize.height + 50));

    this->addChild(particleSystem);
#endif

    return true;
}

void HelloWorld::update(float delta)
{

}