• 流沙画模拟器源码


        流沙画,在密封的玻璃镜框内,装入氧化铝、磨刚沙、无色的混合液和适量的气泡。
        当镜框倒竖时,利用氧化铝和磨刚沙的比重不同以及气泡的上浮力,使氧化铝和磨刚沙按不同速度下沉到空腔的底部,形成层次分明,跌宕有序的画面。
        装入镜框的沙粒,一般有黑色、白色、蓝色(或其它颜色),另外还可能加入一些较大的黑色颗粒。

        要用真实的物理模拟流沙画,需要给每个粒子赋予位置、速度等属性,使用流体动画,实现复杂,速度较慢。这里使用变通的方法,所有粒子沉降速度相同,这样粒子运动不会发生穿插,每一个像素上的粒子数量有限。利用粒子的颜色变化来模拟粒子沉积比例。

     可以贴到3DUI上

         //几个绘制小技巧, 左键撒沙子, 右键挖除, 每种粒子都可以调色

        //月亮:球形画刷+零重力 刷出圆形,右键挖出月亮。

        //云层:球形画刷+稀疏度+零重力 刷出云层,右键挖出云层轮廓,蓝色粒子洒在云彩上进行描边。

        //村落:方形画刷+稀疏度+零重力 刷出建筑,

        //滑坡:移动倾向+右键 挖出斜向山脊 
        
        //瀑布:右键挖空,使蓝色粒子下落形成瀑布水流

        //树木:先混合沙子撒少量树根,后撒树枝(棕色树叶代替),最后撒绿色树叶

        //小路:同色线刷子模拟路 或普降的烟尘

        //橡皮檫粒子会檫除接触到的其它粒子,树叶粒子会附着到树根粒子和其它树叶粒子。水粒子目前和沙粒子没有区别,应该具有更强的流动性。

        // 可以刷在已有沙子的内部,直接替换,刷出平滑体。可以用零重力沙子托起一堆带重力的沙子,然后檫除部分零重力沙子形成下雨或水流动画。

     源码:

    1. //========================================================
    2. // @Date: 2016.05
    3. // @File: SourceDemoClient/SandBox/MiniGameSandBox.h
    4. // @Brief: MiniGameSandBox
    5. // @Author: LouLei
    6. // @Email: twopointfive@163.com
    7. // @Copyright (Crapell) - All Rights Reserved
    8. //========================================================
    9. #ifndef __MiniGameSandBox__H__
    10. #define __MiniGameSandBox__H__
    11. #include "Math/MathLib.h"
    12. #include "Render/Texture.h"
    13. #include "Rpg/MiniGame.h"
    14. namespace RendSys
    15. {
    16. class MC_Frame;
    17. }
    18. class SandBoxPlayerRole;
    19. class MiniGameSandBox:public MiniGame
    20. {
    21. public:
    22. enum ParticleType
    23. {
    24. PT_Null = 0,
    25. PT_Sand ,
    26. PT_Water,
    27. PT_Stone,
    28. PT_Root , //树根在第一层,可以和沙粒混合
    29. PT_Tree , //树叶在第二层,和第一层可以重叠,其它粒子都在第一层
    30. PT_Wall ,
    31. PT_Erase,
    32. PT_Max ,
    33. };
    34. //大量堆积或挖空时沙子移动倾向
    35. enum ParticleMove
    36. {
    37. PM_Left = 0, //倾向左 (从右向左遍历行粒子)
    38. PM_Right , //倾向右 (从左向右遍历行粒子)
    39. PM_Down , //左右均衡 (偶数行从左向右遍历,奇数行从右向左遍历)
    40. PM_Max ,
    41. };
    42. enum BrushType
    43. {
    44. BT_Circle = 0,
    45. BT_Square ,
    46. BT_Line,
    47. BT_Max ,
    48. };
    49. //粒子移动方向
    50. enum Dir
    51. {
    52. UP =0,
    53. DOWN ,
    54. LEFT ,
    55. RIGHT,
    56. UPLEFT,
    57. UPRIGHT,
    58. DOWNLEFT,
    59. DOWNRIGHT,
    60. };
    61. //
    62. class ParticleStyle
    63. {
    64. public:
    65. ParticleStyle();
    66. void SetColor(const Color& color,float hRange);
    67. void FreshBatchColor(); //批次间变色
    68. void FreshParticleColor();//批次内变色
    69. public:
    70. bool active;
    71. int weight;
    72. bool gravity; //false不动,true没帧下降1像素,没有其它速度,同一个位置粒子数量有限
    73. ParticleType type;
    74. float hMin,hMax;
    75. float sMin,sMax;
    76. float lMin,lMax;
    77. //批次间变色
    78. float h,s,l;
    79. float r,g,b;
    80. float hSpeedBatch,sSpeedBatch,lSpeedBatch;
    81. //批次内变色
    82. bool particleHSL;
    83. float hParticle,sParticle,lParticle;
    84. float rParticle,gParticle,bParticle,aParticle;
    85. float hSpeedParticle,sSpeedParticle,lSpeedParticle;
    86. };
    87. //
    88. class Particle
    89. {
    90. public:
    91. //int id; //index
    92. //vec2I pos; //位置
    93. //layer1
    94. ParticleType type; //
    95. bool gravity;
    96. char color[4];
    97. //layer2
    98. ParticleType type2; //
    99. bool gravity2;
    100. char color2[4];
    101. bool rooted; //树叶粒子是否生根
    102. //char flag;
    103. Particle* neighbour[8];
    104. };
    105. MiniGameSandBox();
    106. virtual ~MiniGameSandBox();
    107. virtual bool KeepResource(bool once,int& circle,String& nextTip);
    108. virtual bool Start();
    109. virtual bool Stop();
    110. virtual bool Render();
    111. virtual void RenderUI();
    112. virtual bool Update();
    113. virtual bool Free();
    114. virtual bool IsEnd();
    115. //处理游戏网络命令包
    116. virtual int ProcessPacketCmd(PacketBase* packet);
    117. //virtual const char* CmdToString(const char* stream,int len);
    118. void ClearTarget();
    119. vec2I ScreenToTarget(const vec2 &pos);
    120. void UpdateInput();
    121. void UpdateParticle();
    122. void MapTarget();
    123. void Brushing(const vec2I& pos);
    124. void Digging(const vec2I& pos);
    125. void FreshWeightAll();
    126. ParticleStyle* RandParticle();
    127. //private:
    128. ParticleMove particleMove;
    129. ParticleStyle Styles[PT_Max];
    130. int WeightAll; //活动总概率 用于随机产生粒子
    131. vec2I Size;
    132. Particle* m_particles;
    133. RectF m_canvasRect;
    134. TexturePtr m_texTarget;
    135. Color m_backColor;
    136. int m_brushSize;
    137. int m_brushSparse; //刷子稀疏度
    138. bool m_brushSparseRand;//刷子稀疏度噪声扰动
    139. int m_brushShape;
    140. float m_brushTime;
    141. vec2I m_brushPos;
    142. SandBoxPlayerRole* m_myRolePlayer;
    143. //非观战时 viewside==myside
    144. int m_myViewSide;
    145. int m_curSide;
    146. bool m_workingWithAI;
    147. vec2I m_brushSpeed;
    148. };
    149. extern MiniGameSandBox* G_SandBoxGame;
    150. #endif

     

    1. //========================================================
    2. // @Date: 2016.05
    3. // @File: SourceDemoClient/SandBox/MiniGameSandBox.cpp
    4. // @Brief: MiniGameSandBox
    5. // @Author: LouLei
    6. // @Email: twopointfive@163.com
    7. // @Copyright (Crapell) - All Rights Reserved
    8. //========================================================
    9. #include "General/Pch.h"
    10. #include "General/Window.h"
    11. #include "General/Timer.h"
    12. #include "Gui/GuiMgr.h"
    13. #include "Gui/RpgGuis.h"
    14. #include "Gui/GuiControlMisc.h"
    15. #include "Input/InputMgr.h"
    16. #include "SandBox/SandBoxPlayer.h"
    17. #include "SandBox/MiniGameSandBox.h"
    18. #include "SandBox/MiSandBox_PlayGui.h"
    19. #include "Render/RendDriver.h"
    20. #include "Render/Shader.h"
    21. #include "Render/MC_Misc.h"
    22. #include "Rpg/SyncGameInfo.h"
    23. #include "Packet/PacketMiniGame.h"
    24. #include "Net/PacketList.h"
    25. #include "Render/Camera.h"
    26. #include "General/Pce.h"
    27. const char* SandBoxCmdToString(int enumeration)
    28. {
    29. switch(enumeration)
    30. {
    31. case CMD_ManMove :return "CMD_ManMove ";
    32. case CMD_GameOver:return "CMD_GameOver";
    33. case CMD_Restart :return "CMD_Restart ";
    34. default :return "CMD_unknow";
    35. }
    36. return "CMD_unknow";
    37. }
    38. static int opDir[] =
    39. {
    40. MiniGameSandBox::DOWN,//UP ,
    41. MiniGameSandBox::UP,//DOWN ,
    42. MiniGameSandBox::RIGHT,//LEFT ,
    43. MiniGameSandBox::LEFT,//RIGHT,
    44. MiniGameSandBox::DOWNRIGHT,//UPLEFT,
    45. MiniGameSandBox::DOWNLEFT,//UPRIGHT,
    46. MiniGameSandBox::UPRIGHT,//DOWNLEFT,
    47. MiniGameSandBox::UPLEFT,//DOWNRIGHT,
    48. };
    49. MiniGameSandBox* G_SandBoxGame;
    50. MiniGameSandBox::MiniGameSandBox()
    51. :m_particles(NULL)
    52. {
    53. G_SandBoxGame = this;
    54. CmdEnumToString = SandBoxCmdToString;
    55. }
    56. MiniGameSandBox::~MiniGameSandBox()
    57. {
    58. G_SandBoxGame = NULL;
    59. }
    60. bool MiniGameSandBox::Start()
    61. {
    62. m_myRolePlayer = NULL;
    63. if(!MiniGame::Start())
    64. return false;
    65. m_workingWithAI = false;
    66. ParticleStyle* style;
    67. //todo save and load from cfg file
    68. style = &Styles[PT_Sand];
    69. style->type = PT_Sand;
    70. style->SetColor(Color(230/255.0f, 170/255.0f, 20/255.0f, 1),0.07f);
    71. style->sMin = 0.3f;
    72. style->sMax = 0.6f;
    73. style->lMin = 0.1f;
    74. style->lMax = 0.5f;
    75. style->hSpeedBatch = 0.02f;
    76. style->sSpeedBatch = 0.08f;
    77. style->lSpeedBatch = 0.08f; //批次间变色
    78. style->hSpeedParticle = 0.005f;
    79. style->sSpeedParticle = 0.01f;
    80. style->lSpeedParticle = 0.01f; //批次内变色
    81. style = &Styles[PT_Water];
    82. style->type = PT_Water;
    83. style->SetColor(Color(20/255.0f, 150/255.0f, 230/255.0f, 1),0.03f);
    84. style->sMin = 0.4f;
    85. style->sMax = 0.6f;
    86. style->lMin = 0.3f;
    87. style->lMax = 0.8f;
    88. style->hSpeedBatch = 0.005f;
    89. style->sSpeedBatch = 0.05f;
    90. style->lSpeedBatch = 0.1f;
    91. style->hSpeedParticle = 0.005f;
    92. style->sSpeedParticle = 0.01f;
    93. style->lSpeedParticle = 0.01f;
    94. style = &Styles[PT_Stone];
    95. style->type = PT_Stone;
    96. style->SetColor(Color(20/255.0f, 50/255.0f, 50/255.0f, 1),0.01f);
    97. style->sMin = 0.4f;
    98. style->sMax = 0.6f;
    99. style->lMin = 0.3f;
    100. style->lMax = 0.5f;
    101. style->hSpeedBatch = 0.002f;
    102. style->sSpeedBatch = 0.05f;
    103. style->lSpeedBatch = 0.05f;
    104. style->hSpeedParticle = 0.005f;
    105. style->sSpeedParticle = 0.01f;
    106. style->lSpeedParticle = 0.01f;
    107. style = &Styles[PT_Root];
    108. style->type = PT_Root;
    109. style->SetColor(Color(20/255.0f, 250/255.0f, 30/255.0f, 1),0.05f);
    110. style->sMin = 0.4f;
    111. style->sMax = 0.6f;
    112. style->lMin = 0.3f;
    113. style->lMax = 0.5f;
    114. style->hSpeedBatch = 0.01f;
    115. style->sSpeedBatch = 0.05f;
    116. style->lSpeedBatch = 0.05f;
    117. style->hSpeedParticle = 0.005f;
    118. style->sSpeedParticle = 0.01f;
    119. style->lSpeedParticle = 0.01f;
    120. style = &Styles[PT_Tree];
    121. style->type = PT_Tree;
    122. style->SetColor(Color(20/255.0f, 250/255.0f, 30/255.0f, 1),0.05f);
    123. style->sMin = 0.4f;
    124. style->sMax = 0.6f;
    125. style->lMin = 0.3f;
    126. style->lMax = 0.5f;
    127. style->hSpeedBatch = 0.01f;
    128. style->sSpeedBatch = 0.05f;
    129. style->lSpeedBatch = 0.05f;
    130. style->hSpeedParticle = 0.005f;
    131. style->sSpeedParticle = 0.01f;
    132. style->lSpeedParticle = 0.01f;
    133. style = &Styles[PT_Erase];
    134. style->type = PT_Erase;
    135. style->SetColor(Color(255/255.0f, 0/255.0f, 0/255.0f, 1),0);
    136. style->sMin = 0.5f;
    137. style->sMax = 0.5f;
    138. style->lMin = 0.5f;
    139. style->lMax = 0.5f;
    140. style->hSpeedBatch = 0.0f;
    141. style->sSpeedBatch = 0.0f;
    142. style->lSpeedBatch = 0.0f;
    143. style->hSpeedParticle = 0.0f;
    144. style->sSpeedParticle = 0.0f;
    145. style->lSpeedParticle = 0.0f;
    146. //
    147. for (int i=0;i<PT_Max;i++)
    148. {
    149. style = &Styles[i];
    150. style->active = false;
    151. style->weight = 10;
    152. style->particleHSL = style->hSpeedParticle>0 || style->sSpeedParticle>0 || style->lSpeedParticle>0;
    153. }
    154. style = &Styles[PT_Sand];
    155. style->active = true;
    156. style = &Styles[PT_Root];
    157. style->weight = 1;
    158. FreshWeightAll();
    159. particleMove = PM_Down;
    160. m_3dMode = false;
    161. m_brushSize = 1;
    162. m_brushSparse = 1;
    163. m_brushSparseRand = false;
    164. m_brushShape = 1;
    165. m_brushTime = 0;
    166. Size = vec2I(390,300);
    167. const int Num = Size.x * Size.y;
    168. SafeDeleteArray(m_particles);
    169. m_texTarget = new Texture(true);
    170. m_texTarget->AllocTexture(Size.x,Size.y,RS_RGBA);
    171. m_particles = new Particle[Num];
    172. memset(m_particles,0,sizeof(Particle)*Num);
    173. //m_backColor = Color(50/255.0f, 90/255.0f, 120/255.0f, 0.3f);
    174. m_backColor = Color(50/255.0f, 90/255.0f, 120/255.0f, 0.9f);
    175. ClearTarget();
    176. Particle* p = m_particles;
    177. int sizeX_1 = Size.x - 1;
    178. int sizeY_1 = Size.y - 1;
    179. for(int y=0;y<Size.y;++y)
    180. {
    181. for(int x=0;x<Size.x;++x,++p)
    182. {
    183. if(x>0) p->neighbour[LEFT] = p-1;
    184. if(x<sizeX_1) p->neighbour[RIGHT] = p+1;
    185. if(y>0) p->neighbour[DOWN] = p-Size.x;
    186. if(y<sizeY_1) p->neighbour[UP] = p+Size.x;
    187. if(x>0 && y>0) p->neighbour[DOWNLEFT] = p-Size.x-1;
    188. if(x<sizeX_1 && y>0) p->neighbour[DOWNRIGHT] = p-Size.x+1;
    189. if(x>0 && y<sizeY_1) p->neighbour[UPLEFT] = p+Size.x-1;
    190. if(x<sizeX_1 && y<sizeY_1) p->neighbour[UPRIGHT] = p+Size.x+1;
    191. }
    192. }
    193. m_curSide=SideRed;
    194. if (m_movieScene)
    195. {
    196. Frame frame;
    197. frame.SetPos(m_startPos);
    198. m_movieScene->SetProgramFrame(&frame);
    199. m_movieScene->Advance();
    200. }
    201. m_gameState = MS_Gamming;
    202. m_myViewSide = SideBlack;
    203. //for(int i = 0; i < m_allPlayerNum; i++)
    204. //{
    205. // dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->m_side = i==0?SideRed:SideBlack;
    206. // //dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->m_side = i==0?SideBlack:SideRed;
    207. //}
    208. // if(m_myRolePlayer)
    209. // m_myViewSide = m_myRolePlayer->m_side;
    210. //进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。
    211. if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);
    212. //
    213. for(int i = 0; i < m_allPlayerNum; i++)
    214. {
    215. if(m_miniPlayer[i])
    216. m_miniPlayer[i]->Start();
    217. }
    218. //设置摄像机
    219. CameraCtrlerTarget* ctrler = new CameraCtrlerTarget;
    220. ctrler->SetDistToTar(60);
    221. ctrler->SetTarPos(m_startPos);
    222. G_Camera->PushCtrler(ctrler);
    223. G_Camera->SetEuler(0, -60, 0);
    224. //片头摄像机
    225. PushIntroCamera();
    226. return true;
    227. }
    228. void MiniGameSandBox::ClearTarget()
    229. {
    230. m_workingWithAI = false;
    231. const int Num = Size.x * Size.y;
    232. unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
    233. Particle* End = m_particles+Num;
    234. for(Particle* p=m_particles; p!=End; ++p)
    235. {
    236. //p->id = i;
    237. p->type = PT_Null;
    238. p->gravity = true;
    239. p->color[0] = BackColor[0];
    240. p->color[1] = BackColor[1];
    241. p->color[2] = BackColor[2];
    242. p->color[3] = BackColor[3];
    243. p->type2 = PT_Null;
    244. p->gravity2 = true;
    245. p->color2[0] = BackColor[0];
    246. p->color2[1] = BackColor[1];
    247. p->color2[2] = BackColor[2];
    248. p->color2[3] = BackColor[3];
    249. }
    250. }
    251. MiniPlayer* MiniGameSandBox::CreatePlayer()
    252. {
    253. return NULL;//new SandBoxPlayer;
    254. }
    255. MiniPlayer* MiniGameSandBox::CreateRobot()
    256. {
    257. return NULL;//new SandBoxPlayerRobot;
    258. }
    259. MiniPlayer* MiniGameSandBox::CreateRole()
    260. {
    261. m_myRolePlayer = NULL;//new SandBoxPlayerRole;
    262. return NULL;//m_myRolePlayer;
    263. }
    264. bool MiniGameSandBox::Stop()
    265. {
    266. G_Camera->PopCtrler();
    267. //CameraCtrlerTarget* ctrlerTarget = G_Camera->IsCurCtrler<CameraCtrlerTarget>();
    268. //if(ctrlerTarget)
    269. // ctrlerTarget->SetTarEntity(G_MyRole);
    270. {
    271. if (m_myPlayer && m_myPlayer->m_liveNum>0)
    272. {
    273. G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);
    274. }
    275. else
    276. {
    277. G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);
    278. }
    279. G_GuiMgr->PushGui("Rpg_ResultDialog",GL_DIALOGBOTTOM);
    280. }
    281. return MiniGame::Stop();
    282. }
    283. //SandBoxPlayer* MiniGameSandBox::GetTurnPlayer()
    284. //{
    285. // //return dynamic_cast<SandBoxPlayer*>(m_miniPlayer[m_curSide]);
    286. // for(int i = 0; i < m_allPlayerNum; i++)
    287. // {
    288. // SandBoxPlayer* player = dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i]);
    289. // if (player->m_side == m_curSide)
    290. // {
    291. // return player;
    292. // }
    293. // }
    294. // return NULL;
    295. //}
    296. bool MiniGameSandBox::KeepResource(bool once,int& circle,String& nextTip)
    297. {
    298. //
    299. char buf[256];
    300. if (m_movieScene == NULL)
    301. {
    302. LoadConfig loader(LoadConfig::GenDonotReShrinkBound, true, true);
    303. m_movieScene = new RendSys::MovieClip;
    304. m_movieScene->LoadFromFile("data/minigame/SandBox/sandboxscene.movie", &loader);
    305. Frame frame;
    306. frame.SetPos(m_startPos);
    307. m_movieScene->SetProgramFrame(&frame);
    308. m_movieScene->Advance();
    309. }
    310. if (m_movieScene->IsLoadComplete() == false)
    311. {
    312. m_gameState = MS_End;
    313. return false;
    314. }
    315. return true;
    316. }
    317. bool MiniGameSandBox::Render()
    318. {
    319. //attach target to ui3D control
    320. //for(int i = 0; i < m_allPlayerNum; i++)
    321. //{
    322. // dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->Render();
    323. //}
    324. return true;
    325. }
    326. void MiniGameSandBox::RenderUI()
    327. {
    328. MiniGame::RenderUI();
    329. }
    330. bool MiniGameSandBox::Update()
    331. {
    332. m_turnTime += G_Timer->GetStepTimeLimited();
    333. m_brushTime += G_Timer->GetStepTimeLimited();
    334. MiSandBox_PlayGui* playGui = G_GuiMgr->GetGui<MiSandBox_PlayGui>();
    335. m_canvasRect = playGui->m_canvas->GetRectReal();
    336. m_canvasRect.SetPos(playGui->m_canvas->GetOffset());
    337. playGui->m_canvas->SetTexture(m_texTarget,GCS_NORMAL);
    338. m_movieScene->Advance();
    339. UpdateInput();
    340. UpdateParticle();
    341. MapTarget();
    342. //for(int i = 0; i < m_allPlayerNum; i++)
    343. //{
    344. // dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->Update();
    345. //}
    346. return true;
    347. }
    348. void MiniGameSandBox::UpdateInput()
    349. {
    350. if (m_brushTime < 0.1f)
    351. {
    352. return;
    353. }
    354. //if (m_myRolePlayer && m_curSide != m_myRolePlayer->m_side)
    355. // return;
    356. vec2I pos;
    357. if (m_workingWithAI)
    358. {
    359. ParticleStyle* style;
    360. for (int i=0;i<PT_Max;i++)
    361. {
    362. style = &Styles[i];
    363. //style->active = false;
    364. //style->weight = 10;
    365. //style->particleHSL = style->hSpeedParticle>0 || style->sSpeedParticle>0 || style->lSpeedParticle>0;
    366. }
    367. Styles[PT_Root].active = true;
    368. Styles[PT_Water].active = true;
    369. Styles[PT_Tree].active = true;
    370. FreshWeightAll();
    371. m_brushSize = 7;
    372. m_brushSparse = 3;
    373. m_brushSparseRand = true;
    374. m_brushSpeed.x += RandRange(-2,2);
    375. Clamp(m_brushSpeed.x,-5,5);
    376. m_brushPos.y = Size.y - m_brushSize;
    377. m_brushPos.x += m_brushSpeed.x;
    378. Clamp(m_brushPos.x,m_brushSize,Size.x-m_brushSize);
    379. Brushing(m_brushPos);
    380. }
    381. else if (m_3dMode)
    382. {
    383. MiSandBox_PlayGui* playGui = G_GuiMgr->GetGui<MiSandBox_PlayGui>();
    384. vec2 newPosI;
    385. if (playGui->m_groupTargetCtrl->GetMapMousePos(G_Mouse->GetMousePos(),newPosI))
    386. {
    387. m_brushPos = ScreenToTarget(newPosI);
    388. }
    389. }
    390. else
    391. {
    392. m_brushPos = ScreenToTarget(G_Mouse->GetMousePos());
    393. }
    394. if (G_SandBoxGame->IsButtonPressed(MOUSE_RIGHT))
    395. {
    396. Digging(m_brushPos);
    397. }
    398. else if (G_SandBoxGame->IsButtonPressed(MOUSE_LEFT))
    399. {
    400. Brushing(m_brushPos);
    401. }
    402. }
    403. void MiniGameSandBox::Brushing(const vec2I& pos)
    404. {
    405. //刷粒子
    406. m_brushTime = 0;
    407. int brushSizeSq = m_brushSize*m_brushSize;
    408. int minX = max(0,pos.x-m_brushSize);
    409. int maxX = min(Size.x-1,pos.x+m_brushSize);
    410. int minY = max(0,pos.y-m_brushSize);
    411. int maxY = min(Size.y-1,pos.y+m_brushSize);
    412. if(m_brushShape==BT_Line)
    413. {
    414. minX = 0;
    415. maxX = Size.x-1;
    416. minY = pos.y;
    417. maxY = pos.y;
    418. }
    419. int minSparse = min(0,1-m_brushSparse);
    420. int maxSparse = max(0,m_brushSparse-1);
    421. unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
    422. //
    423. ParticleStyle* style;
    424. for (int i=0;i<PT_Max;i++)
    425. {
    426. style = &Styles[i];
    427. if (style->active)
    428. {
    429. style->FreshBatchColor();
    430. }
    431. }
    432. Particle* p;
    433. int rx,ry;
    434. for (int y=minY;y<=maxY;y+=m_brushSparse)
    435. {
    436. for (int x=minX;x<=maxX;x+=m_brushSparse)
    437. {
    438. if (m_brushSparseRand)
    439. {
    440. ry = y + RandRange(minSparse,maxSparse);
    441. rx = x + RandRange(minSparse,maxSparse);
    442. }
    443. else
    444. {
    445. ry = y;
    446. rx = x;
    447. }
    448. if( rx<minX || rx>maxX || ry<minY || ry>maxY)
    449. continue;
    450. if (m_brushShape==BT_Circle)
    451. {
    452. float difx = rx-pos.x;
    453. float dify = ry-pos.y;
    454. if( difx*difx + dify*dify > brushSizeSq)
    455. continue;
    456. }
    457. p = &m_particles[ry*Size.x + rx];
    458. style = RandParticle();
    459. if (style==NULL)
    460. {
    461. break;
    462. }
    463. if (style->particleHSL)
    464. {
    465. style->FreshParticleColor();
    466. }
    467. if (style->type==PT_Tree)
    468. {
    469. p->type2 = style->type;
    470. p->gravity2 = style->gravity;
    471. p->color2[0] = style->rParticle;
    472. p->color2[1] = style->gParticle;
    473. p->color2[2] = style->bParticle;
    474. p->color2[3] = style->aParticle;
    475. }
    476. else
    477. {
    478. p->type = style->type;
    479. p->gravity = style->gravity;
    480. p->color[0] = style->rParticle;
    481. p->color[1] = style->gParticle;
    482. p->color[2] = style->bParticle;
    483. p->color[3] = style->aParticle;
    484. }
    485. p->rooted = false;
    486. }
    487. }
    488. }
    489. void MiniGameSandBox::Digging(const vec2I& pos)
    490. {
    491. //挖除粒子
    492. int brushSizeSq = m_brushSize*m_brushSize;
    493. int minX = max(0,pos.x-m_brushSize);
    494. int maxX = min(Size.x-1,pos.x+m_brushSize);
    495. int minY = max(0,pos.y-m_brushSize);
    496. int maxY = min(Size.y-1,pos.y+m_brushSize);
    497. if(m_brushShape==BT_Line)
    498. {
    499. minX = 0;
    500. maxX = Size.x-1;
    501. minY = pos.y;
    502. maxY = pos.y;
    503. }
    504. int minSparse = min(0,1-m_brushSparse);
    505. int maxSparse = max(0,m_brushSparse-1);
    506. unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
    507. //
    508. Particle* p;
    509. int rx,ry;
    510. for (int y=minY;y<=maxY;y+=m_brushSparse)
    511. {
    512. for (int x=minX;x<=maxX;x+=m_brushSparse)
    513. {
    514. if (m_brushSparseRand)
    515. {
    516. ry = y + RandRange(minSparse,maxSparse);
    517. rx = x + RandRange(minSparse,maxSparse);
    518. }
    519. else
    520. {
    521. ry = y;
    522. rx = x;
    523. }
    524. if( rx<minX || rx>maxX || ry<minY || ry>maxY)
    525. continue;
    526. if (m_brushShape==BT_Circle)
    527. {
    528. float difx = rx-pos.x;
    529. float dify = ry-pos.y;
    530. if( difx*difx + dify*dify > brushSizeSq)
    531. continue;
    532. }
    533. p = &m_particles[ry*Size.x + rx];
    534. p->type = PT_Null;
    535. p->gravity = true;
    536. p->color[0] = BackColor[0];
    537. p->color[1] = BackColor[1];
    538. p->color[2] = BackColor[2];
    539. p->color[3] = BackColor[3];
    540. p->type2 = PT_Null;
    541. p->gravity2 = true;
    542. p->color2[0] = BackColor[0];
    543. p->color2[1] = BackColor[1];
    544. p->color2[2] = BackColor[2];
    545. p->color2[3] = BackColor[3];
    546. }
    547. }
    548. }
    549. void MiniGameSandBox::UpdateParticle()
    550. {
    551. unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
    552. //
    553. const Particle* End = m_particles+Size.x*Size.y;
    554. for(Particle* p=m_particles; p!=End; ++p)
    555. {
    556. // p->flag = 0;
    557. p->rooted = false;
    558. }
    559. //
    560. const int LineNum = Size.y;
    561. const int SizeX2a1 = Size.x*2 + 1;
    562. const int SizeX2_1 = Size.x*2 - 1;
    563. Particle* lineBegin = m_particles;
    564. Particle* lineEnd = m_particles + Size.x;
    565. int step = 1;
    566. if (particleMove==PM_Left)
    567. {
    568. lineBegin = m_particles + Size.x - 1;
    569. lineEnd = m_particles - 1;
    570. step = -1;
    571. }
    572. Particle* n;
    573. ParticleStyle* style;
    574. //(偶数行从左向右遍历 奇数行从右向左遍历,避免沙子向一侧堆时)
    575. //for(Particle* p=m_particles; p!=End; ++p)
    576. for(int _i=0; _i<LineNum;++_i)
    577. {
    578. for(Particle* p=lineBegin; p!=lineEnd; p+=step)
    579. {
    580. //style = &Styles[p->type];
    581. //layer2
    582. if (p->type2 == PT_Tree) //树叶粒子 穿透其它粒子和相框底部 附着树根和其它树叶
    583. {
    584. if (/*p->flag==0 && */p->gravity2)
    585. {
    586. n = p->neighbour[DOWN];
    587. if (n &&(n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
    588. {
    589. p->rooted = true;
    590. }
    591. n = p->neighbour[DOWNLEFT];
    592. if (n && (n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
    593. {
    594. p->rooted = true;
    595. }
    596. n = p->neighbour[DOWNRIGHT];
    597. if (n && (n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
    598. {
    599. p->rooted = true;
    600. }
    601. if(p->rooted==false)
    602. {
    603. //move down
    604. n = p->neighbour[DOWN];
    605. if (n==NULL)
    606. {
    607. p->type2 = PT_Null; //漏出底部边框
    608. p->gravity2 = true;
    609. p->color2[0] = BackColor[0];
    610. p->color2[1] = BackColor[1];
    611. p->color2[2] = BackColor[2];
    612. p->color2[3] = BackColor[3];
    613. }
    614. else
    615. {
    616. n->type2 = p->type2; //重叠下面的粒子
    617. n->gravity2 = p->gravity2;
    618. n->color2[0] = p->color2[0];
    619. n->color2[1] = p->color2[1];
    620. n->color2[2] = p->color2[2];
    621. p->color2[3] = p->color2[3];
    622. //n->flag = 1;
    623. p->type2 = PT_Null;
    624. p->gravity2 = true;
    625. p->color2[0] = BackColor[0];
    626. p->color2[1] = BackColor[1];
    627. p->color2[2] = BackColor[2];
    628. p->color2[3] = BackColor[3];
    629. p->flag = 0;
    630. }
    631. }
    632. }
    633. }
    634. //layer1
    635. {
    636. if (/*p->flag==0 && */p->type!=PT_Null && p->gravity)
    637. {
    638. n = NULL;
    639. if ( p->neighbour[DOWN]
    640. && p->neighbour[DOWN]->type==PT_Null
    641. ) //密度轻挤占
    642. {
    643. n = p->neighbour[DOWN];
    644. }
    645. else
    646. {
    647. //if (p->particleMove==PM_Left) //此处改变顺序, 无法改变优先移动方向 ,决定因素是x轴的遍历顺序
    648. //{
    649. if (p->neighbour[DOWNLEFT] && p->neighbour[DOWNLEFT]->type==PT_Null)
    650. {
    651. n = p->neighbour[DOWNLEFT];
    652. }
    653. else if (p->neighbour[DOWNRIGHT] && p->neighbour[DOWNRIGHT]->type==PT_Null)
    654. {
    655. n = p->neighbour[DOWNRIGHT];
    656. }
    657. //}
    658. }
    659. if (n)
    660. {
    661. n->type = p->type;
    662. n->gravity = p->gravity;
    663. n->color[0] = p->color[0];
    664. n->color[1] = p->color[1];
    665. n->color[2] = p->color[2];
    666. n->color[3] = p->color[3];
    667. //n->flag = 1;
    668. p->type = PT_Null;
    669. p->gravity = true;
    670. p->color[0] = BackColor[0];
    671. p->color[1] = BackColor[1];
    672. p->color[2] = BackColor[2];
    673. p->color[3] = BackColor[3];
    674. p->flag = 0;
    675. }
    676. //檫粒子
    677. if (p->type == PT_Erase)
    678. {
    679. n = p->neighbour[DOWN];
    680. if (n==NULL)
    681. {
    682. p->type = PT_Null; //漏出底部边框
    683. p->gravity = true;
    684. }
    685. else if(n->type!=PT_Null && n->type!=PT_Erase)
    686. {
    687. n->type = PT_Null; //檫除自己和下面的粒子,可以檫除树根 塌陷树木 不能直接檫除第二层的树叶, todo 不是立即檫除
    688. n->gravity = true;
    689. p->type = PT_Null;
    690. p->gravity = true;
    691. }
    692. }
    693. }
    694. }
    695. }
    696. if (particleMove==PM_Down)
    697. {
    698. //交换方向
    699. if (step==1)
    700. {
    701. lineBegin += SizeX2_1;
    702. lineEnd -= 1;
    703. step = -1;
    704. }
    705. else
    706. {
    707. lineBegin += 1;
    708. lineEnd += SizeX2a1;
    709. step = 1;
    710. }
    711. }
    712. else
    713. {
    714. lineBegin += Size.x;
    715. lineEnd += Size.x;
    716. }
    717. }
    718. }
    719. void MiniGameSandBox::MapTarget()
    720. {
    721. unsigned char* color;
    722. unsigned char* pixel = m_texTarget->GetImageData();
    723. const Particle* End = m_particles+Size.x*Size.y;
    724. for(Particle* p=m_particles; p!=End; ++p,pixel+=4)
    725. {
    726. if (p->type2!=PT_Null)
    727. {
    728. pixel[0] = p->color2[0];
    729. pixel[1] = p->color2[1];
    730. pixel[2] = p->color2[2];
    731. pixel[3] = p->color2[3];
    732. }
    733. else
    734. {
    735. pixel[0] = p->color[0];
    736. pixel[1] = p->color[1];
    737. pixel[2] = p->color[2];
    738. pixel[3] = p->color[3];
    739. }
    740. }
    741. //画笔
    742. if (m_brushPos.x>=0&&m_brushPos.x<Size.x
    743. &&m_brushPos.y>=0&&m_brushPos.y<Size.y)
    744. {
    745. int minX = max(0,m_brushPos.x-m_brushSize);
    746. int maxX = min(Size.x-1,m_brushPos.x+m_brushSize);
    747. int minY = max(0,m_brushPos.y-m_brushSize);
    748. int maxY = min(Size.y-1,m_brushPos.y+m_brushSize);
    749. Color color(1,1,1,1);
    750. if(m_brushShape==BT_Circle)
    751. {
    752. m_texTarget->Circle(m_brushPos.x,m_brushPos.y,m_brushSize,m_brushSize,1,color);
    753. }
    754. else if(m_brushShape==BT_Square)
    755. {
    756. m_texTarget->Line(minX,minY,maxX,minY,1,color);
    757. m_texTarget->Line(minX,minY,minX,maxY,1,color);
    758. m_texTarget->Line(maxX,maxY,maxX,minY,1,color);
    759. m_texTarget->Line(maxX,maxY,minX,maxY,1,color);
    760. }
    761. else if(m_brushShape==BT_Line)
    762. {
    763. m_texTarget->Line(0,m_brushPos.y,Size.x,m_brushPos.y,1,color);
    764. }
    765. }
    766. m_texTarget->RefreshFromData(m_texTarget->GetImageData(),RS_RGBA);
    767. }
    768. bool MiniGameSandBox::Free()
    769. {
    770. MiniGame::Free();
    771. m_texTarget = NULL;
    772. SafeDeleteArray(m_particles);
    773. return true;
    774. }
    775. bool MiniGameSandBox::IsEnd()
    776. {
    777. return m_gameState == MS_End;
    778. }
    779. int MiniGameSandBox::ProcessPacketCmd(PacketBase* packet)
    780. {
    781. int cmd;
    782. packet->ReadValue(cmd);
    783. switch(cmd)
    784. {
    785. case CMD_ManMove:
    786. break;
    787. case CMD_GameOver:
    788. break;
    789. case CMD_Restart:
    790. // Free();
    791. // Start();
    792. break;
    793. }
    794. return 0;
    795. }
    796. vec2I MiniGameSandBox::ScreenToTarget(const vec2 &pos_)
    797. {
    798. vec2 pos(pos_);
    799. pos -= m_canvasRect.GetPos();
    800. pos = pos / m_canvasRect.GetExtent();
    801. pos.y = 1 - pos.y;
    802. pos.x *= Size.x;
    803. pos.y *= Size.y;
    804. return vec2I(pos.x,pos.y);
    805. }
    806. MiniGameSandBox::ParticleStyle* MiniGameSandBox::RandParticle()
    807. {
    808. ParticleStyle* style;
    809. if (WeightAll==0)
    810. {
    811. return NULL;
    812. }
    813. int weight = (Rand()%WeightAll) + 1;
    814. for (int i=0;i<PT_Max;i++)
    815. {
    816. style = &Styles[i];
    817. if (style->active)
    818. {
    819. weight -= style->weight;
    820. if (weight <=0)
    821. {
    822. return style;
    823. }
    824. }
    825. }
    826. return &Styles[0];
    827. }
    828. void MiniGameSandBox::FreshWeightAll()
    829. {
    830. ParticleStyle* style;
    831. WeightAll = 0;
    832. for (int i=0;i<PT_Max;i++)
    833. {
    834. style = &Styles[i];
    835. if (style->active)
    836. {
    837. WeightAll += style->weight;
    838. }
    839. }
    840. }
    841. MiniGameSandBox::ParticleStyle::ParticleStyle()
    842. {
    843. type = PT_Null;
    844. SetColor(Color(230/255.0f, 170/255.0f, 20/255.0f, 1),0.07f);
    845. sMin = 0.3f;
    846. sMax = 0.6f;
    847. lMin = 0.1f;
    848. lMax = 0.5f;
    849. hSpeedBatch = 0.02f;
    850. sSpeedBatch = 0.08f;
    851. lSpeedBatch = 0.08f; //批次间变色
    852. hSpeedParticle = 0.005f;
    853. sSpeedParticle = 0.01f;
    854. lSpeedParticle = 0.01f; //批次内变色
    855. active = false;
    856. weight = 1;
    857. particleHSL = hSpeedParticle>0 || sSpeedParticle>0 || lSpeedParticle>0;
    858. }
    859. void MiniGameSandBox::ParticleStyle::SetColor(const Color& color,float hRange)
    860. {
    861. rgb2hsl(color.r,color.g,color.b,h,s,l);
    862. hMin = h - hRange;
    863. hMax = h + hRange;
    864. Clamp(hMin,0.0f,1.0f);
    865. Clamp(sMin,0.0f,1.0f);
    866. }
    867. void MiniGameSandBox::ParticleStyle::FreshBatchColor()
    868. {
    869. h += RandRange(-1.0f,1.0f)*hSpeedBatch;//批次间变色
    870. s += RandRange(-1.0f,1.0f)*sSpeedBatch;
    871. l += RandRange(-1.0f,1.0f)*lSpeedBatch;
    872. Clamp(h,hMin,hMax);
    873. Clamp(s,sMin,sMax);
    874. Clamp(l,lMin,lMax);
    875. hsl2rgb(h,s,l,r,g,b);
    876. r *=255;
    877. g *=255;
    878. b *=255;
    879. hParticle = h;//批次内变色
    880. sParticle = s;
    881. lParticle = l;
    882. rParticle = r;
    883. gParticle = g;
    884. bParticle = b;
    885. aParticle = 255;
    886. }
    887. void MiniGameSandBox::ParticleStyle::FreshParticleColor()
    888. {
    889. hParticle += RandRange(-1.0f,1.0f)*hSpeedParticle;//批次内变色
    890. sParticle += RandRange(-1.0f,1.0f)*sSpeedParticle;
    891. lParticle += RandRange(-1.0f,1.0f)*lSpeedParticle;
    892. Clamp(hParticle,hMin,hMax);
    893. Clamp(sParticle,sMin,sMax);
    894. Clamp(lParticle,lMin,lMax);
    895. hsl2rgb(hParticle,sParticle,lParticle,rParticle,gParticle,bParticle);
    896. rParticle *=255;
    897. gParticle *=255;
    898. bParticle *=255;
    899. //aParticle = 255;
    900. }

  • 相关阅读:
    pbjs 无法编码 bytes 类型数据问题的解决方案
    我用 ChatGPT 写 2023 高考语文作文:全国卷(一)
    第三篇,芯片启动和时钟系统
    金九银十进大厂必刷的105道Java面试题(不得不说的秘密)
    NR 物理层编码 S1 -概述
    JSON和全局异常处理
    【代码精读】中断路由代码导读:当cpu运行在ATF来了一个Non secure Group1中断
    大学毕业一年 - 北漂生活
    十四、SpringBoot原理——SpringBoot应用是怎么启动的?从创建容器到运行容器,逐行分析完整过程
    robotframework RequestsLibrary Post On Session关键字 body为json的问题
  • 原文地址:https://blog.csdn.net/twopointfive/article/details/125453207