当前位置:网站首页>Quicksand painting simulator source code
Quicksand painting simulator source code
2022-06-27 02:39:00 【Lou Lei】
Quicksand painting , In a sealed glass frame , Add alumina 、 Grinding Congo sand 、 Colorless mixture and proper amount of bubbles .
When the frame is inverted , Using the different specific gravity of alumina and sand and the buoyancy of bubbles , Make alumina and grinding sand sink to the bottom of the cavity at different speeds , Form a hierarchy , A picture of ups and downs .
Sand packed into the frame , Usually black 、 white 、 Blue ( Or other colors ), In addition, some large black particles may be added .
Use real physics to simulate quicksand painting , Each particle needs to be given a position 、 Speed and other attributes , Use fluid animation , The implementation is complex , Slower . Here is a workaround , All particles have the same settling velocity , In this way, the motion of particles will not be interspersed , The number of particles per pixel is limited . The color change of particles is used to simulate the deposition ratio of particles .

Can be posted to 3DUI On 
// A few drawing tips , Left click to sprinkle sand , Right click to excavate , Each particle can be tinted
// The moon : Spherical brush + Zero gravity Brush a circle , Right click to dig out the moon .
// a bank of clouds : Spherical brush + Sparsity + Zero gravity Brush out the clouds , Right click to dig out the cloud outline , Blue particles are sprinkled on the clouds to trace .
// village : Square brush + Sparsity + Zero gravity Paint the building ,
// Landslide : Tendency to move + Right click Dig out an oblique ridge
// The waterfall : Right click to excavate , Make the blue particles fall to form a waterfall
// tree : First mix the sand and sprinkle a small amount of tree roots , Then scatter the branches ( Brown leaves instead ), Finally, sprinkle green leaves
// path : The same color line brush simulates the road Or the general smoke
// Eraser particles wipe away other particles they come into contact with , Leaf particles attach to root particles and other leaf particles . Water particles are no different from sand particles at present , Should have greater liquidity .
// It can be brushed inside the existing sand , Direct replacement , Brush out the smooth body . You can lift a pile of gravitational sand with zero gravity sand , Then wipe away some zero gravity sand to form rain or water animation .

Source code :
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SandBox/MiniGameSandBox.h
// @Brief: MiniGameSandBox
// @Author: LouLei
// @Email: [email protected]
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#ifndef __MiniGameSandBox__H__
#define __MiniGameSandBox__H__
#include "Math/MathLib.h"
#include "Render/Texture.h"
#include "Rpg/MiniGame.h"
namespace RendSys
{
class MC_Frame;
}
class SandBoxPlayerRole;
class MiniGameSandBox:public MiniGame
{
public:
enum ParticleType
{
PT_Null = 0,
PT_Sand ,
PT_Water,
PT_Stone,
PT_Root , // The roots are on the first floor , It can be mixed with sand
PT_Tree , // The leaves are on the second floor , And the first layer can overlap , The other particles are in the first layer
PT_Wall ,
PT_Erase,
PT_Max ,
};
// The tendency of sand to move when it is piled up or hollowed out
enum ParticleMove
{
PM_Left = 0, // Lean to the left ( Traverse row particles from right to left )
PM_Right , // Lean to the right ( Traverse row particles from left to right )
PM_Down , // Left right balance ( Even rows traverse from left to right , Odd rows traverse from right to left )
PM_Max ,
};
enum BrushType
{
BT_Circle = 0,
BT_Square ,
BT_Line,
BT_Max ,
};
// Direction of particle movement
enum Dir
{
UP =0,
DOWN ,
LEFT ,
RIGHT,
UPLEFT,
UPRIGHT,
DOWNLEFT,
DOWNRIGHT,
};
//
class ParticleStyle
{
public:
ParticleStyle();
void SetColor(const Color& color,float hRange);
void FreshBatchColor(); // Discoloration between batches
void FreshParticleColor();// Discoloration within the batch
public:
bool active;
int weight;
bool gravity; //false Immobility ,true No frame drop 1 Pixels , No other speed , The number of particles in the same position is limited
ParticleType type;
float hMin,hMax;
float sMin,sMax;
float lMin,lMax;
// Discoloration between batches
float h,s,l;
float r,g,b;
float hSpeedBatch,sSpeedBatch,lSpeedBatch;
// Discoloration within the batch
bool particleHSL;
float hParticle,sParticle,lParticle;
float rParticle,gParticle,bParticle,aParticle;
float hSpeedParticle,sSpeedParticle,lSpeedParticle;
};
//
class Particle
{
public:
//int id; //index
//vec2I pos; // Location
//layer1
ParticleType type; //
bool gravity;
char color[4];
//layer2
ParticleType type2; //
bool gravity2;
char color2[4];
bool rooted; // Whether leaf particles take root
//char flag;
Particle* neighbour[8];
};
MiniGameSandBox();
virtual ~MiniGameSandBox();
virtual bool KeepResource(bool once,int& circle,String& nextTip);
virtual bool Start();
virtual bool Stop();
virtual bool Render();
virtual void RenderUI();
virtual bool Update();
virtual bool Free();
virtual bool IsEnd();
// Handle game network command package
virtual int ProcessPacketCmd(PacketBase* packet);
//virtual const char* CmdToString(const char* stream,int len);
void ClearTarget();
vec2I ScreenToTarget(const vec2 &pos);
void UpdateInput();
void UpdateParticle();
void MapTarget();
void Brushing(const vec2I& pos);
void Digging(const vec2I& pos);
void FreshWeightAll();
ParticleStyle* RandParticle();
//private:
ParticleMove particleMove;
ParticleStyle Styles[PT_Max];
int WeightAll; // Total probability of activity For randomly generating particles
vec2I Size;
Particle* m_particles;
RectF m_canvasRect;
TexturePtr m_texTarget;
Color m_backColor;
int m_brushSize;
int m_brushSparse; // Brush sparsity
bool m_brushSparseRand;// Brush sparsity noise disturbance
int m_brushShape;
float m_brushTime;
vec2I m_brushPos;
SandBoxPlayerRole* m_myRolePlayer;
// When not watching the war viewside==myside
int m_myViewSide;
int m_curSide;
bool m_workingWithAI;
vec2I m_brushSpeed;
};
extern MiniGameSandBox* G_SandBoxGame;
#endif
//========================================================
// @Date: 2016.05
// @File: SourceDemoClient/SandBox/MiniGameSandBox.cpp
// @Brief: MiniGameSandBox
// @Author: LouLei
// @Email: [email protected]
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "General/Window.h"
#include "General/Timer.h"
#include "Gui/GuiMgr.h"
#include "Gui/RpgGuis.h"
#include "Gui/GuiControlMisc.h"
#include "Input/InputMgr.h"
#include "SandBox/SandBoxPlayer.h"
#include "SandBox/MiniGameSandBox.h"
#include "SandBox/MiSandBox_PlayGui.h"
#include "Render/RendDriver.h"
#include "Render/Shader.h"
#include "Render/MC_Misc.h"
#include "Rpg/SyncGameInfo.h"
#include "Packet/PacketMiniGame.h"
#include "Net/PacketList.h"
#include "Render/Camera.h"
#include "General/Pce.h"
const char* SandBoxCmdToString(int enumeration)
{
switch(enumeration)
{
case CMD_ManMove :return "CMD_ManMove ";
case CMD_GameOver:return "CMD_GameOver";
case CMD_Restart :return "CMD_Restart ";
default :return "CMD_unknow";
}
return "CMD_unknow";
}
static int opDir[] =
{
MiniGameSandBox::DOWN,//UP ,
MiniGameSandBox::UP,//DOWN ,
MiniGameSandBox::RIGHT,//LEFT ,
MiniGameSandBox::LEFT,//RIGHT,
MiniGameSandBox::DOWNRIGHT,//UPLEFT,
MiniGameSandBox::DOWNLEFT,//UPRIGHT,
MiniGameSandBox::UPRIGHT,//DOWNLEFT,
MiniGameSandBox::UPLEFT,//DOWNRIGHT,
};
MiniGameSandBox* G_SandBoxGame;
MiniGameSandBox::MiniGameSandBox()
:m_particles(NULL)
{
G_SandBoxGame = this;
CmdEnumToString = SandBoxCmdToString;
}
MiniGameSandBox::~MiniGameSandBox()
{
G_SandBoxGame = NULL;
}
bool MiniGameSandBox::Start()
{
m_myRolePlayer = NULL;
if(!MiniGame::Start())
return false;
m_workingWithAI = false;
ParticleStyle* style;
//todo save and load from cfg file
style = &Styles[PT_Sand];
style->type = PT_Sand;
style->SetColor(Color(230/255.0f, 170/255.0f, 20/255.0f, 1),0.07f);
style->sMin = 0.3f;
style->sMax = 0.6f;
style->lMin = 0.1f;
style->lMax = 0.5f;
style->hSpeedBatch = 0.02f;
style->sSpeedBatch = 0.08f;
style->lSpeedBatch = 0.08f; // Discoloration between batches
style->hSpeedParticle = 0.005f;
style->sSpeedParticle = 0.01f;
style->lSpeedParticle = 0.01f; // Discoloration within the batch
style = &Styles[PT_Water];
style->type = PT_Water;
style->SetColor(Color(20/255.0f, 150/255.0f, 230/255.0f, 1),0.03f);
style->sMin = 0.4f;
style->sMax = 0.6f;
style->lMin = 0.3f;
style->lMax = 0.8f;
style->hSpeedBatch = 0.005f;
style->sSpeedBatch = 0.05f;
style->lSpeedBatch = 0.1f;
style->hSpeedParticle = 0.005f;
style->sSpeedParticle = 0.01f;
style->lSpeedParticle = 0.01f;
style = &Styles[PT_Stone];
style->type = PT_Stone;
style->SetColor(Color(20/255.0f, 50/255.0f, 50/255.0f, 1),0.01f);
style->sMin = 0.4f;
style->sMax = 0.6f;
style->lMin = 0.3f;
style->lMax = 0.5f;
style->hSpeedBatch = 0.002f;
style->sSpeedBatch = 0.05f;
style->lSpeedBatch = 0.05f;
style->hSpeedParticle = 0.005f;
style->sSpeedParticle = 0.01f;
style->lSpeedParticle = 0.01f;
style = &Styles[PT_Root];
style->type = PT_Root;
style->SetColor(Color(20/255.0f, 250/255.0f, 30/255.0f, 1),0.05f);
style->sMin = 0.4f;
style->sMax = 0.6f;
style->lMin = 0.3f;
style->lMax = 0.5f;
style->hSpeedBatch = 0.01f;
style->sSpeedBatch = 0.05f;
style->lSpeedBatch = 0.05f;
style->hSpeedParticle = 0.005f;
style->sSpeedParticle = 0.01f;
style->lSpeedParticle = 0.01f;
style = &Styles[PT_Tree];
style->type = PT_Tree;
style->SetColor(Color(20/255.0f, 250/255.0f, 30/255.0f, 1),0.05f);
style->sMin = 0.4f;
style->sMax = 0.6f;
style->lMin = 0.3f;
style->lMax = 0.5f;
style->hSpeedBatch = 0.01f;
style->sSpeedBatch = 0.05f;
style->lSpeedBatch = 0.05f;
style->hSpeedParticle = 0.005f;
style->sSpeedParticle = 0.01f;
style->lSpeedParticle = 0.01f;
style = &Styles[PT_Erase];
style->type = PT_Erase;
style->SetColor(Color(255/255.0f, 0/255.0f, 0/255.0f, 1),0);
style->sMin = 0.5f;
style->sMax = 0.5f;
style->lMin = 0.5f;
style->lMax = 0.5f;
style->hSpeedBatch = 0.0f;
style->sSpeedBatch = 0.0f;
style->lSpeedBatch = 0.0f;
style->hSpeedParticle = 0.0f;
style->sSpeedParticle = 0.0f;
style->lSpeedParticle = 0.0f;
//
for (int i=0;i<PT_Max;i++)
{
style = &Styles[i];
style->active = false;
style->weight = 10;
style->particleHSL = style->hSpeedParticle>0 || style->sSpeedParticle>0 || style->lSpeedParticle>0;
}
style = &Styles[PT_Sand];
style->active = true;
style = &Styles[PT_Root];
style->weight = 1;
FreshWeightAll();
particleMove = PM_Down;
m_3dMode = false;
m_brushSize = 1;
m_brushSparse = 1;
m_brushSparseRand = false;
m_brushShape = 1;
m_brushTime = 0;
Size = vec2I(390,300);
const int Num = Size.x * Size.y;
SafeDeleteArray(m_particles);
m_texTarget = new Texture(true);
m_texTarget->AllocTexture(Size.x,Size.y,RS_RGBA);
m_particles = new Particle[Num];
memset(m_particles,0,sizeof(Particle)*Num);
//m_backColor = Color(50/255.0f, 90/255.0f, 120/255.0f, 0.3f);
m_backColor = Color(50/255.0f, 90/255.0f, 120/255.0f, 0.9f);
ClearTarget();
Particle* p = m_particles;
int sizeX_1 = Size.x - 1;
int sizeY_1 = Size.y - 1;
for(int y=0;y<Size.y;++y)
{
for(int x=0;x<Size.x;++x,++p)
{
if(x>0) p->neighbour[LEFT] = p-1;
if(x<sizeX_1) p->neighbour[RIGHT] = p+1;
if(y>0) p->neighbour[DOWN] = p-Size.x;
if(y<sizeY_1) p->neighbour[UP] = p+Size.x;
if(x>0 && y>0) p->neighbour[DOWNLEFT] = p-Size.x-1;
if(x<sizeX_1 && y>0) p->neighbour[DOWNRIGHT] = p-Size.x+1;
if(x>0 && y<sizeY_1) p->neighbour[UPLEFT] = p+Size.x-1;
if(x<sizeX_1 && y<sizeY_1) p->neighbour[UPRIGHT] = p+Size.x+1;
}
}
m_curSide=SideRed;
if (m_movieScene)
{
Frame frame;
frame.SetPos(m_startPos);
m_movieScene->SetProgramFrame(&frame);
m_movieScene->Advance();
}
m_gameState = MS_Gamming;
m_myViewSide = SideBlack;
//for(int i = 0; i < m_allPlayerNum; i++)
//{
// dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->m_side = i==0?SideRed:SideBlack;
// //dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->m_side = i==0?SideBlack:SideRed;
//}
// if(m_myRolePlayer)
// m_myViewSide = m_myRolePlayer->m_side;
// Get into miniplaygui,( pick 、 The level selection has been completed in the room ).
if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);
//
for(int i = 0; i < m_allPlayerNum; i++)
{
if(m_miniPlayer[i])
m_miniPlayer[i]->Start();
}
// Set up the camera
CameraCtrlerTarget* ctrler = new CameraCtrlerTarget;
ctrler->SetDistToTar(60);
ctrler->SetTarPos(m_startPos);
G_Camera->PushCtrler(ctrler);
G_Camera->SetEuler(0, -60, 0);
// The title camera
PushIntroCamera();
return true;
}
void MiniGameSandBox::ClearTarget()
{
m_workingWithAI = false;
const int Num = Size.x * Size.y;
unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
Particle* End = m_particles+Num;
for(Particle* p=m_particles; p!=End; ++p)
{
//p->id = i;
p->type = PT_Null;
p->gravity = true;
p->color[0] = BackColor[0];
p->color[1] = BackColor[1];
p->color[2] = BackColor[2];
p->color[3] = BackColor[3];
p->type2 = PT_Null;
p->gravity2 = true;
p->color2[0] = BackColor[0];
p->color2[1] = BackColor[1];
p->color2[2] = BackColor[2];
p->color2[3] = BackColor[3];
}
}
MiniPlayer* MiniGameSandBox::CreatePlayer()
{
return NULL;//new SandBoxPlayer;
}
MiniPlayer* MiniGameSandBox::CreateRobot()
{
return NULL;//new SandBoxPlayerRobot;
}
MiniPlayer* MiniGameSandBox::CreateRole()
{
m_myRolePlayer = NULL;//new SandBoxPlayerRole;
return NULL;//m_myRolePlayer;
}
bool MiniGameSandBox::Stop()
{
G_Camera->PopCtrler();
//CameraCtrlerTarget* ctrlerTarget = G_Camera->IsCurCtrler<CameraCtrlerTarget>();
//if(ctrlerTarget)
// ctrlerTarget->SetTarEntity(G_MyRole);
{
if (m_myPlayer && m_myPlayer->m_liveNum>0)
{
G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);
}
else
{
G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);
}
G_GuiMgr->PushGui("Rpg_ResultDialog",GL_DIALOGBOTTOM);
}
return MiniGame::Stop();
}
//SandBoxPlayer* MiniGameSandBox::GetTurnPlayer()
//{
// //return dynamic_cast<SandBoxPlayer*>(m_miniPlayer[m_curSide]);
// for(int i = 0; i < m_allPlayerNum; i++)
// {
// SandBoxPlayer* player = dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i]);
// if (player->m_side == m_curSide)
// {
// return player;
// }
// }
// return NULL;
//}
bool MiniGameSandBox::KeepResource(bool once,int& circle,String& nextTip)
{
//
char buf[256];
if (m_movieScene == NULL)
{
LoadConfig loader(LoadConfig::GenDonotReShrinkBound, true, true);
m_movieScene = new RendSys::MovieClip;
m_movieScene->LoadFromFile("data/minigame/SandBox/sandboxscene.movie", &loader);
Frame frame;
frame.SetPos(m_startPos);
m_movieScene->SetProgramFrame(&frame);
m_movieScene->Advance();
}
if (m_movieScene->IsLoadComplete() == false)
{
m_gameState = MS_End;
return false;
}
return true;
}
bool MiniGameSandBox::Render()
{
//attach target to ui3D control
//for(int i = 0; i < m_allPlayerNum; i++)
//{
// dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->Render();
//}
return true;
}
void MiniGameSandBox::RenderUI()
{
MiniGame::RenderUI();
}
bool MiniGameSandBox::Update()
{
m_turnTime += G_Timer->GetStepTimeLimited();
m_brushTime += G_Timer->GetStepTimeLimited();
MiSandBox_PlayGui* playGui = G_GuiMgr->GetGui<MiSandBox_PlayGui>();
m_canvasRect = playGui->m_canvas->GetRectReal();
m_canvasRect.SetPos(playGui->m_canvas->GetOffset());
playGui->m_canvas->SetTexture(m_texTarget,GCS_NORMAL);
m_movieScene->Advance();
UpdateInput();
UpdateParticle();
MapTarget();
//for(int i = 0; i < m_allPlayerNum; i++)
//{
// dynamic_cast<SandBoxPlayer*>(m_miniPlayer[i])->Update();
//}
return true;
}
void MiniGameSandBox::UpdateInput()
{
if (m_brushTime < 0.1f)
{
return;
}
//if (m_myRolePlayer && m_curSide != m_myRolePlayer->m_side)
// return;
vec2I pos;
if (m_workingWithAI)
{
ParticleStyle* style;
for (int i=0;i<PT_Max;i++)
{
style = &Styles[i];
//style->active = false;
//style->weight = 10;
//style->particleHSL = style->hSpeedParticle>0 || style->sSpeedParticle>0 || style->lSpeedParticle>0;
}
Styles[PT_Root].active = true;
Styles[PT_Water].active = true;
Styles[PT_Tree].active = true;
FreshWeightAll();
m_brushSize = 7;
m_brushSparse = 3;
m_brushSparseRand = true;
m_brushSpeed.x += RandRange(-2,2);
Clamp(m_brushSpeed.x,-5,5);
m_brushPos.y = Size.y - m_brushSize;
m_brushPos.x += m_brushSpeed.x;
Clamp(m_brushPos.x,m_brushSize,Size.x-m_brushSize);
Brushing(m_brushPos);
}
else if (m_3dMode)
{
MiSandBox_PlayGui* playGui = G_GuiMgr->GetGui<MiSandBox_PlayGui>();
vec2 newPosI;
if (playGui->m_groupTargetCtrl->GetMapMousePos(G_Mouse->GetMousePos(),newPosI))
{
m_brushPos = ScreenToTarget(newPosI);
}
}
else
{
m_brushPos = ScreenToTarget(G_Mouse->GetMousePos());
}
if (G_SandBoxGame->IsButtonPressed(MOUSE_RIGHT))
{
Digging(m_brushPos);
}
else if (G_SandBoxGame->IsButtonPressed(MOUSE_LEFT))
{
Brushing(m_brushPos);
}
}
void MiniGameSandBox::Brushing(const vec2I& pos)
{
// Brush particles
m_brushTime = 0;
int brushSizeSq = m_brushSize*m_brushSize;
int minX = max(0,pos.x-m_brushSize);
int maxX = min(Size.x-1,pos.x+m_brushSize);
int minY = max(0,pos.y-m_brushSize);
int maxY = min(Size.y-1,pos.y+m_brushSize);
if(m_brushShape==BT_Line)
{
minX = 0;
maxX = Size.x-1;
minY = pos.y;
maxY = pos.y;
}
int minSparse = min(0,1-m_brushSparse);
int maxSparse = max(0,m_brushSparse-1);
unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
//
ParticleStyle* style;
for (int i=0;i<PT_Max;i++)
{
style = &Styles[i];
if (style->active)
{
style->FreshBatchColor();
}
}
Particle* p;
int rx,ry;
for (int y=minY;y<=maxY;y+=m_brushSparse)
{
for (int x=minX;x<=maxX;x+=m_brushSparse)
{
if (m_brushSparseRand)
{
ry = y + RandRange(minSparse,maxSparse);
rx = x + RandRange(minSparse,maxSparse);
}
else
{
ry = y;
rx = x;
}
if( rx<minX || rx>maxX || ry<minY || ry>maxY)
continue;
if (m_brushShape==BT_Circle)
{
float difx = rx-pos.x;
float dify = ry-pos.y;
if( difx*difx + dify*dify > brushSizeSq)
continue;
}
p = &m_particles[ry*Size.x + rx];
style = RandParticle();
if (style==NULL)
{
break;
}
if (style->particleHSL)
{
style->FreshParticleColor();
}
if (style->type==PT_Tree)
{
p->type2 = style->type;
p->gravity2 = style->gravity;
p->color2[0] = style->rParticle;
p->color2[1] = style->gParticle;
p->color2[2] = style->bParticle;
p->color2[3] = style->aParticle;
}
else
{
p->type = style->type;
p->gravity = style->gravity;
p->color[0] = style->rParticle;
p->color[1] = style->gParticle;
p->color[2] = style->bParticle;
p->color[3] = style->aParticle;
}
p->rooted = false;
}
}
}
void MiniGameSandBox::Digging(const vec2I& pos)
{
// Dig out the particles
int brushSizeSq = m_brushSize*m_brushSize;
int minX = max(0,pos.x-m_brushSize);
int maxX = min(Size.x-1,pos.x+m_brushSize);
int minY = max(0,pos.y-m_brushSize);
int maxY = min(Size.y-1,pos.y+m_brushSize);
if(m_brushShape==BT_Line)
{
minX = 0;
maxX = Size.x-1;
minY = pos.y;
maxY = pos.y;
}
int minSparse = min(0,1-m_brushSparse);
int maxSparse = max(0,m_brushSparse-1);
unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
//
Particle* p;
int rx,ry;
for (int y=minY;y<=maxY;y+=m_brushSparse)
{
for (int x=minX;x<=maxX;x+=m_brushSparse)
{
if (m_brushSparseRand)
{
ry = y + RandRange(minSparse,maxSparse);
rx = x + RandRange(minSparse,maxSparse);
}
else
{
ry = y;
rx = x;
}
if( rx<minX || rx>maxX || ry<minY || ry>maxY)
continue;
if (m_brushShape==BT_Circle)
{
float difx = rx-pos.x;
float dify = ry-pos.y;
if( difx*difx + dify*dify > brushSizeSq)
continue;
}
p = &m_particles[ry*Size.x + rx];
p->type = PT_Null;
p->gravity = true;
p->color[0] = BackColor[0];
p->color[1] = BackColor[1];
p->color[2] = BackColor[2];
p->color[3] = BackColor[3];
p->type2 = PT_Null;
p->gravity2 = true;
p->color2[0] = BackColor[0];
p->color2[1] = BackColor[1];
p->color2[2] = BackColor[2];
p->color2[3] = BackColor[3];
}
}
}
void MiniGameSandBox::UpdateParticle()
{
unsigned char BackColor[4] ={m_backColor.r*255,m_backColor.g*255,m_backColor.b*255,m_backColor.a*255};
//
const Particle* End = m_particles+Size.x*Size.y;
for(Particle* p=m_particles; p!=End; ++p)
{
// p->flag = 0;
p->rooted = false;
}
//
const int LineNum = Size.y;
const int SizeX2a1 = Size.x*2 + 1;
const int SizeX2_1 = Size.x*2 - 1;
Particle* lineBegin = m_particles;
Particle* lineEnd = m_particles + Size.x;
int step = 1;
if (particleMove==PM_Left)
{
lineBegin = m_particles + Size.x - 1;
lineEnd = m_particles - 1;
step = -1;
}
Particle* n;
ParticleStyle* style;
//( Even rows traverse from left to right Odd rows traverse from right to left , Avoid piling sand to one side )
//for(Particle* p=m_particles; p!=End; ++p)
for(int _i=0; _i<LineNum;++_i)
{
for(Particle* p=lineBegin; p!=lineEnd; p+=step)
{
//style = &Styles[p->type];
//layer2
if (p->type2 == PT_Tree) // Leaf particles Penetrate other particles and the bottom of the frame Attach tree roots and other leaves
{
if (/*p->flag==0 && */p->gravity2)
{
n = p->neighbour[DOWN];
if (n &&(n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
{
p->rooted = true;
}
n = p->neighbour[DOWNLEFT];
if (n && (n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
{
p->rooted = true;
}
n = p->neighbour[DOWNRIGHT];
if (n && (n->type==PT_Root || (n->type2==PT_Tree&&n->rooted==true)))
{
p->rooted = true;
}
if(p->rooted==false)
{
//move down
n = p->neighbour[DOWN];
if (n==NULL)
{
p->type2 = PT_Null; // Leak out the bottom border
p->gravity2 = true;
p->color2[0] = BackColor[0];
p->color2[1] = BackColor[1];
p->color2[2] = BackColor[2];
p->color2[3] = BackColor[3];
}
else
{
n->type2 = p->type2; // Overlap the particles below
n->gravity2 = p->gravity2;
n->color2[0] = p->color2[0];
n->color2[1] = p->color2[1];
n->color2[2] = p->color2[2];
p->color2[3] = p->color2[3];
//n->flag = 1;
p->type2 = PT_Null;
p->gravity2 = true;
p->color2[0] = BackColor[0];
p->color2[1] = BackColor[1];
p->color2[2] = BackColor[2];
p->color2[3] = BackColor[3];
p->flag = 0;
}
}
}
}
//layer1
{
if (/*p->flag==0 && */p->type!=PT_Null && p->gravity)
{
n = NULL;
if ( p->neighbour[DOWN]
&& p->neighbour[DOWN]->type==PT_Null
) // Density light crowding
{
n = p->neighbour[DOWN];
}
else
{
//if (p->particleMove==PM_Left) // Change the order here , Unable to change the preferred movement direction , The decisive factor is x Traversal order of axes
//{
if (p->neighbour[DOWNLEFT] && p->neighbour[DOWNLEFT]->type==PT_Null)
{
n = p->neighbour[DOWNLEFT];
}
else if (p->neighbour[DOWNRIGHT] && p->neighbour[DOWNRIGHT]->type==PT_Null)
{
n = p->neighbour[DOWNRIGHT];
}
//}
}
if (n)
{
n->type = p->type;
n->gravity = p->gravity;
n->color[0] = p->color[0];
n->color[1] = p->color[1];
n->color[2] = p->color[2];
n->color[3] = p->color[3];
//n->flag = 1;
p->type = PT_Null;
p->gravity = true;
p->color[0] = BackColor[0];
p->color[1] = BackColor[1];
p->color[2] = BackColor[2];
p->color[3] = BackColor[3];
p->flag = 0;
}
// Sassafras particle
if (p->type == PT_Erase)
{
n = p->neighbour[DOWN];
if (n==NULL)
{
p->type = PT_Null; // Leak out the bottom border
p->gravity = true;
}
else if(n->type!=PT_Null && n->type!=PT_Erase)
{
n->type = PT_Null; // Wipe yourself and the particles below , It can wipe away roots Collapsing trees Do not directly wipe off the second layer of leaves , todo Not immediately wipe
n->gravity = true;
p->type = PT_Null;
p->gravity = true;
}
}
}
}
}
if (particleMove==PM_Down)
{
// Switch directions
if (step==1)
{
lineBegin += SizeX2_1;
lineEnd -= 1;
step = -1;
}
else
{
lineBegin += 1;
lineEnd += SizeX2a1;
step = 1;
}
}
else
{
lineBegin += Size.x;
lineEnd += Size.x;
}
}
}
void MiniGameSandBox::MapTarget()
{
unsigned char* color;
unsigned char* pixel = m_texTarget->GetImageData();
const Particle* End = m_particles+Size.x*Size.y;
for(Particle* p=m_particles; p!=End; ++p,pixel+=4)
{
if (p->type2!=PT_Null)
{
pixel[0] = p->color2[0];
pixel[1] = p->color2[1];
pixel[2] = p->color2[2];
pixel[3] = p->color2[3];
}
else
{
pixel[0] = p->color[0];
pixel[1] = p->color[1];
pixel[2] = p->color[2];
pixel[3] = p->color[3];
}
}
// paint brush
if (m_brushPos.x>=0&&m_brushPos.x<Size.x
&&m_brushPos.y>=0&&m_brushPos.y<Size.y)
{
int minX = max(0,m_brushPos.x-m_brushSize);
int maxX = min(Size.x-1,m_brushPos.x+m_brushSize);
int minY = max(0,m_brushPos.y-m_brushSize);
int maxY = min(Size.y-1,m_brushPos.y+m_brushSize);
Color color(1,1,1,1);
if(m_brushShape==BT_Circle)
{
m_texTarget->Circle(m_brushPos.x,m_brushPos.y,m_brushSize,m_brushSize,1,color);
}
else if(m_brushShape==BT_Square)
{
m_texTarget->Line(minX,minY,maxX,minY,1,color);
m_texTarget->Line(minX,minY,minX,maxY,1,color);
m_texTarget->Line(maxX,maxY,maxX,minY,1,color);
m_texTarget->Line(maxX,maxY,minX,maxY,1,color);
}
else if(m_brushShape==BT_Line)
{
m_texTarget->Line(0,m_brushPos.y,Size.x,m_brushPos.y,1,color);
}
}
m_texTarget->RefreshFromData(m_texTarget->GetImageData(),RS_RGBA);
}
bool MiniGameSandBox::Free()
{
MiniGame::Free();
m_texTarget = NULL;
SafeDeleteArray(m_particles);
return true;
}
bool MiniGameSandBox::IsEnd()
{
return m_gameState == MS_End;
}
int MiniGameSandBox::ProcessPacketCmd(PacketBase* packet)
{
int cmd;
packet->ReadValue(cmd);
switch(cmd)
{
case CMD_ManMove:
break;
case CMD_GameOver:
break;
case CMD_Restart:
// Free();
// Start();
break;
}
return 0;
}
vec2I MiniGameSandBox::ScreenToTarget(const vec2 &pos_)
{
vec2 pos(pos_);
pos -= m_canvasRect.GetPos();
pos = pos / m_canvasRect.GetExtent();
pos.y = 1 - pos.y;
pos.x *= Size.x;
pos.y *= Size.y;
return vec2I(pos.x,pos.y);
}
MiniGameSandBox::ParticleStyle* MiniGameSandBox::RandParticle()
{
ParticleStyle* style;
if (WeightAll==0)
{
return NULL;
}
int weight = (Rand()%WeightAll) + 1;
for (int i=0;i<PT_Max;i++)
{
style = &Styles[i];
if (style->active)
{
weight -= style->weight;
if (weight <=0)
{
return style;
}
}
}
return &Styles[0];
}
void MiniGameSandBox::FreshWeightAll()
{
ParticleStyle* style;
WeightAll = 0;
for (int i=0;i<PT_Max;i++)
{
style = &Styles[i];
if (style->active)
{
WeightAll += style->weight;
}
}
}
MiniGameSandBox::ParticleStyle::ParticleStyle()
{
type = PT_Null;
SetColor(Color(230/255.0f, 170/255.0f, 20/255.0f, 1),0.07f);
sMin = 0.3f;
sMax = 0.6f;
lMin = 0.1f;
lMax = 0.5f;
hSpeedBatch = 0.02f;
sSpeedBatch = 0.08f;
lSpeedBatch = 0.08f; // Discoloration between batches
hSpeedParticle = 0.005f;
sSpeedParticle = 0.01f;
lSpeedParticle = 0.01f; // Discoloration within the batch
active = false;
weight = 1;
particleHSL = hSpeedParticle>0 || sSpeedParticle>0 || lSpeedParticle>0;
}
void MiniGameSandBox::ParticleStyle::SetColor(const Color& color,float hRange)
{
rgb2hsl(color.r,color.g,color.b,h,s,l);
hMin = h - hRange;
hMax = h + hRange;
Clamp(hMin,0.0f,1.0f);
Clamp(sMin,0.0f,1.0f);
}
void MiniGameSandBox::ParticleStyle::FreshBatchColor()
{
h += RandRange(-1.0f,1.0f)*hSpeedBatch;// Discoloration between batches
s += RandRange(-1.0f,1.0f)*sSpeedBatch;
l += RandRange(-1.0f,1.0f)*lSpeedBatch;
Clamp(h,hMin,hMax);
Clamp(s,sMin,sMax);
Clamp(l,lMin,lMax);
hsl2rgb(h,s,l,r,g,b);
r *=255;
g *=255;
b *=255;
hParticle = h;// Discoloration within the batch
sParticle = s;
lParticle = l;
rParticle = r;
gParticle = g;
bParticle = b;
aParticle = 255;
}
void MiniGameSandBox::ParticleStyle::FreshParticleColor()
{
hParticle += RandRange(-1.0f,1.0f)*hSpeedParticle;// Discoloration within the batch
sParticle += RandRange(-1.0f,1.0f)*sSpeedParticle;
lParticle += RandRange(-1.0f,1.0f)*lSpeedParticle;
Clamp(hParticle,hMin,hMax);
Clamp(sParticle,sMin,sMax);
Clamp(lParticle,lMin,lMax);
hsl2rgb(hParticle,sParticle,lParticle,rParticle,gParticle,bParticle);
rParticle *=255;
gParticle *=255;
bParticle *=255;
//aParticle = 255;
}
边栏推荐
- Flink學習2:應用場景
- 学习太极创客 — MQTT 第二章(一)QoS 服务质量等级
- Yalm 100b: 100billion parameter open source large model from yandex, Russia, allowing commercial use
- 消费者追捧iPhone,在于它的性价比超越国产手机
- Svg drag dress Kitty Cat
- Memcached basics 13
- Fork (), exec (), waitpid (), $? > > in Perl 8 combination
- Constraintlayout Development Guide
- 学习太极创客 — MQTT(七)MQTT 主题进阶
- SQLite reader plug-in tests SQLite syntax
猜你喜欢

消费者追捧iPhone,在于它的性价比超越国产手机

Calculation of average wind direction and speed (unit vector method)

Learn Tai Chi maker mqtt (IX) esp8266 subscribe to and publish mqtt messages at the same time

Why pass SPIF_ Sendchange flag systemparametersinfo will hang?

平均风向风速计算(单位矢量法)

学习太极创客 — MQTT(八)ESP8266订阅MQTT主题

参数估计——《概率论及其数理统计》第七章学习报告(点估计)

Geometric distribution (a discrete distribution)

Flink learning 4:flink technology stack

CVPR2022 | PointDistiller:面向高效紧凑3D检测的结构化知识蒸馏
随机推荐
ORM cache package for laravel
C language -- Design of employee information management system
Oracle/PLSQL: NumToDSInterval Function
2022茶艺师(高级)上岗证题库模拟考试平台操作
2022年氯碱电解工艺试题及答案
学习太极创客 — MQTT(八)ESP8266订阅MQTT主题
Web development framework - Express (installation and use, static hosting, routing processing, use of Middleware)
2022中式面点师(高级)复训题库及在线模拟考试
Brief introduction of 228 dropout methods of pytorch and fast implementation of dropblock with 4 lines of code based on dropout
Mmdetection uses yolox to train its own coco data set
学习太极创客 — MQTT(九)ESP8266 同时订阅和发布 MQTT 消息
平均风向风速计算(单位矢量法)
Learning Tai Chi Maker - mqtt Chapter 2 (II) esp8266 QoS application
TechSmith Camtasia最新2022版详细功能讲解下载
pytorch 22 8种Dropout方法的简介 及 基于Dropout用4行代码快速实现DropBlock
I earned 3W yuan a month from my sideline: the industry you despise really makes money!
How does the brain do arithmetic? Both addition and subtraction methods have special neurons, and the symbol text can activate the same group of cell sub journals
【数组】剑指 Offer II 012. 左右两边子数组的和相等 | 剑指 Offer II 013. 二维子矩阵的和
Learning Tai Chi Maker - mqtt (VII) advanced mqtt theme
lodash get js代码实现