most basic sand sim you can create with Raylib 4.0
Last active
October 16, 2023 17:23
-
-
Save andrew-raphael-lukasik/abb41e01d5ccefb9ab2a283239fd9d90 to your computer and use it in GitHub Desktop.
most basic sand sim you can create with Raylib 4.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include "raylib.h" | |
#include "math.h" | |
#include "rlgl.h" | |
bool SameRGB ( Color lhs , Color rhs ); | |
bool SwapIf ( Color condition , int src , Color srcColor , int dst , char tick , Color* pixels ); | |
#define AIR SKYBLUE | |
#define SAND ORANGE | |
#define WATER BLUE | |
const int screenWidth = 640; | |
const int screenHeight = 480; | |
const int pixelScale = 10; | |
const int pixelsWidth = screenWidth / pixelScale; | |
const int pixelsHeight = screenHeight / pixelScale; | |
const int pixelsLength = pixelsWidth * pixelsHeight; | |
int main ( void ) | |
{ | |
// Initialization | |
InitWindow( screenWidth , screenHeight , "sand" ); | |
SetTargetFPS( 30 ); | |
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) | |
// Dynamic memory allocation to store pixels data (Color type) | |
Color *pixels = (Color*) malloc( pixelsLength * sizeof(Color) ); | |
for( int i=0 ; i<pixelsLength ; i++ ) pixels[i] = AIR; | |
// Load pixels data into an image structure and create texture | |
Image pixelsImage = { | |
.data = pixels, | |
.width = pixelsWidth, | |
.height = pixelsHeight, | |
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, | |
.mipmaps = 1 | |
}; | |
Texture2D pixelsTexture = LoadTextureFromImage( pixelsImage ); | |
SetTextureFilter( pixelsTexture , TEXTURE_FILTER_POINT ); | |
// GAME LOOP | |
unsigned char tick = 0; | |
while( !WindowShouldClose() ) | |
{ | |
// UPDATE | |
float dt = GetFrameTime(); | |
double time = GetTime(); | |
tick++; | |
Vector2 mouse = GetMousePosition(); | |
int mouseX = (int) mouse.x; | |
int mouseY = (int) mouse.y; | |
int mousePixelIndex = mouseY/pixelScale * pixelsWidth + mouseX/pixelScale; | |
{ | |
for( int y=0 ; y<pixelsHeight ; y++ ) | |
for( int x=0 ; x<pixelsWidth ; x++ ) | |
{ | |
int src = y*pixelsWidth + x; | |
Color srcColor = pixels[src]; | |
if( SameRGB(srcColor,AIR) ) continue;// early exit | |
int down = (y+1)*pixelsWidth + x; | |
int downRight = (y+1)*pixelsWidth + x+1; | |
int downLeft = (y+1)*pixelsWidth + x-1; | |
int right = y*pixelsWidth + x+1; | |
int left = y*pixelsWidth + x-1; | |
if( SameRGB(srcColor,SAND) && srcColor.a!=tick )// is this SAND && not changed this frame | |
{ | |
// falling down | |
if( SwapIf(AIR,src,srcColor,down,tick,pixels) ) continue; | |
else if( SwapIf(WATER,src,srcColor,down,tick,pixels ) ) continue; | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,downRight,tick,pixels) ) continue; | |
else if( SwapIf(WATER,src,srcColor,downRight,tick,pixels ) ) continue; | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,downLeft,tick,pixels) ) continue; | |
else if( SwapIf(WATER,src,srcColor,downLeft,tick,pixels ) ) continue; | |
} | |
else if( SameRGB(srcColor,WATER) && srcColor.a!=tick )// is this WATER && not changed this frame | |
{ | |
// falling down | |
if( SwapIf(AIR,src,srcColor,down,tick,pixels) ) continue; | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,downRight,tick,pixels) ) continue; | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,downLeft,tick,pixels) ) continue; | |
// moving sideways | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,right,tick,pixels) ) continue; | |
if( GetRandomValue(0,1)==1 ) | |
if( SwapIf(AIR,src,srcColor,left,tick,pixels) ) continue; | |
} | |
} | |
if( IsMouseButtonDown(0) ) | |
{ | |
pixels[mousePixelIndex] = SAND; | |
pixels[mousePixelIndex].a = tick; | |
} | |
else if( IsMouseButtonDown(1) ) | |
{ | |
pixels[mousePixelIndex] = WATER; | |
pixels[mousePixelIndex].a = tick; | |
} | |
else if( IsMouseButtonDown(2) ) | |
{ | |
pixels[mousePixelIndex] = AIR; | |
pixels[mousePixelIndex].a = tick; | |
} | |
} | |
// RENDER | |
BeginDrawing(); | |
{ | |
// ClearBackground( BLACK ); | |
rlSetBlendFactors( 1 , 0 , 0x0104 );// 1 for GL_ONE, 0 for GL_ZERO, 0x0104 for GL_ADD | |
rlSetBlendMode( BLEND_CUSTOM ); | |
UpdateTexture( pixelsTexture , pixels ); | |
DrawTextureEx( pixelsTexture , (Vector2){ 0 , 0 } , 0 , pixelScale , WHITE ); | |
// DrawText( TextFormat( "mouse:(%i,%i)" , mouseX , mouseY ), 72, 148, 30, BLUE ); | |
} | |
EndDrawing(); | |
} | |
// De-Initialization | |
UnloadImage( pixelsImage );// unloads CPU (RAM) image data (pixels) | |
UnloadTexture( pixelsTexture ); | |
CloseWindow();// Close window and OpenGL context | |
return 0; | |
} | |
bool SameRGB ( Color lhs , Color rhs ) { return lhs.r==rhs.r && lhs.g==rhs.g && lhs.b==rhs.b; } | |
bool SwapIf ( Color condition , int src , Color srcColor , int dst , char tick , Color* pixels ) | |
{ | |
if( dst>=0 && dst<pixelsLength ) | |
{ | |
Color dstColor = pixels[dst]; | |
if( dstColor.a!=tick )// not changed this frame | |
if( SameRGB(dstColor,condition) ) | |
{ | |
pixels[dst] = srcColor; | |
pixels[dst].a = tick; | |
pixels[src] = dstColor; | |
pixels[src].a = tick; | |
return true; | |
} | |
} | |
return false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment