File confec.cpp changed (mode: 100644) (index 1fdd1c6..3234fdc) |
... |
... |
std::string app_version = "v0.6.1"; |
469 |
469 |
std::string app_name = "Confectioner Engine Demo"; |
std::string app_name = "Confectioner Engine Demo"; |
470 |
470 |
std::uint32_t app_steam_id = 1319170; |
std::uint32_t app_steam_id = 1319170; |
471 |
471 |
std::vector<int> inventory_service_generators = {}; |
std::vector<int> inventory_service_generators = {}; |
472 |
|
std::vector<SpecialItem> special_items; |
|
473 |
472 |
#else |
#else |
474 |
473 |
std::string app_name = "Confectioner Engine"; |
std::string app_name = "Confectioner Engine"; |
475 |
474 |
std::uint32_t app_steam_id = 1181900; |
std::uint32_t app_steam_id = 1181900; |
476 |
475 |
std::vector<int> inventory_service_generators = { 20, 10 }; |
std::vector<int> inventory_service_generators = { 20, 10 }; |
477 |
|
#ifdef __STEAM__ |
|
478 |
|
std::vector<SpecialItem> special_items; |
|
479 |
|
#else |
|
480 |
|
// Give DRM-free users essential special items. |
|
481 |
|
std::vector<SpecialItem> special_items = { |
|
482 |
|
{ fgl::newTexture, "Cake Pan", 100, 1 } |
|
483 |
|
}; |
|
484 |
|
#endif |
|
485 |
476 |
#endif |
#endif |
486 |
477 |
|
|
|
478 |
|
std::vector<SpecialItem> special_items; |
|
479 |
|
|
487 |
480 |
// Default to English. |
// Default to English. |
488 |
481 |
std::string language = "en"; |
std::string language = "en"; |
489 |
482 |
|
|
|
... |
... |
double zoom_factor = 1.0; |
530 |
523 |
|
|
531 |
524 |
fgl::Color ambient_colors[] = { |
fgl::Color ambient_colors[] = { |
532 |
525 |
{ 0.4f, 0.5f, 0.8f, 1.0f }, // Night. |
{ 0.4f, 0.5f, 0.8f, 1.0f }, // Night. |
533 |
|
{ 0.6f, 0.5f, 0.8f, 1.0f }, // Morning twilight. |
|
|
526 |
|
{ 0.45f, 0.5f, 0.8f, 1.0f }, // Morning twilight. |
534 |
527 |
{ 1.05f, 0.96f, 0.9f, 1.0f }, // Morning. |
{ 1.05f, 0.96f, 0.9f, 1.0f }, // Morning. |
535 |
528 |
{ 1.15f, 1.06f, 1.0f, 1.0f }, // Day. |
{ 1.15f, 1.06f, 1.0f, 1.0f }, // Day. |
536 |
529 |
{ 1.0f, 0.7f, 0.9f, 1.0f }, // Sunset. |
{ 1.0f, 0.7f, 0.9f, 1.0f }, // Sunset. |
537 |
|
{ 0.6f, 0.5f, 0.8f, 1.0f } // Evening twilight. |
|
|
530 |
|
{ 0.45f, 0.5f, 0.8f, 1.0f } // Evening twilight. |
538 |
531 |
}; |
}; |
539 |
532 |
|
|
540 |
533 |
fgl::Color ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f }; |
fgl::Color ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f }; |
|
... |
... |
GLfloat |
545 |
538 |
bloomThreshold = 0.56f, |
bloomThreshold = 0.56f, |
546 |
539 |
bloomAmount = 0.25f; |
bloomAmount = 0.25f; |
547 |
540 |
|
|
548 |
|
fgl::Pipeline bloomPipeline; |
|
|
541 |
|
fgl::Pipeline bloomPipeline, sunlitInstancePipeline; |
549 |
542 |
|
|
550 |
543 |
std::string fadeTo = ""; |
std::string fadeTo = ""; |
551 |
544 |
|
|
|
... |
... |
std::string vn_callback_file = ""; |
655 |
648 |
bool raining = false; |
bool raining = false; |
656 |
649 |
|
|
657 |
650 |
// Maximum number of raindrop particles. |
// Maximum number of raindrop particles. |
658 |
|
size_t max_raindrops = 1000; |
|
|
651 |
|
size_t max_raindrops = 1200; |
659 |
652 |
|
|
660 |
653 |
struct Raindrop { |
struct Raindrop { |
661 |
654 |
bool visible; |
bool visible; |
|
... |
... |
struct Raindrop { |
664 |
657 |
|
|
665 |
658 |
std::vector<Raindrop> raindrops; |
std::vector<Raindrop> raindrops; |
666 |
659 |
|
|
667 |
|
size_t max_gibs = 500; |
|
|
660 |
|
size_t max_gibs = 600; |
668 |
661 |
|
|
669 |
662 |
double gib_floor = -7.6; |
double gib_floor = -7.6; |
670 |
663 |
|
|
|
... |
... |
void AddRecipe( std::string name ); |
768 |
761 |
|
|
769 |
762 |
void Achieve( std::string id ); |
void Achieve( std::string id ); |
770 |
763 |
|
|
|
764 |
|
void AddSpecialItem( const std::string &name, int id, int count ); |
|
765 |
|
|
771 |
766 |
void AddEntity( fworld::Entity &ent, double x, double y, int idx = -1, bool recalc = true ); |
void AddEntity( fworld::Entity &ent, double x, double y, int idx = -1, bool recalc = true ); |
772 |
767 |
|
|
773 |
768 |
int GetEntityAt( double x, double y ); |
int GetEntityAt( double x, double y ); |
|
... |
... |
void Warp( std::string param ); |
794 |
789 |
|
|
795 |
790 |
void LoadMap( std::string file_path, bool autosave ); |
void LoadMap( std::string file_path, bool autosave ); |
796 |
791 |
|
|
|
792 |
|
fgl::Pipeline LoadShaders( std::string vertFile, std::string fragFile, std::vector<std::string> samplers ); |
|
793 |
|
|
797 |
794 |
fworld::Entity GetMapSpawn( std::string dataPath, std::string filePath ); |
fworld::Entity GetMapSpawn( std::string dataPath, std::string filePath ); |
798 |
795 |
|
|
799 |
796 |
void PauseMenu( std::string fileName ); |
void PauseMenu( std::string fileName ); |
|
... |
... |
int main( int argc, char* argv[] ){ |
1094 |
1091 |
InitCloud(); |
InitCloud(); |
1095 |
1092 |
|
|
1096 |
1093 |
// Load special item icons for DRM-free users. |
// Load special item icons for DRM-free users. |
1097 |
|
for( auto &item : special_items ){ |
|
1098 |
|
item.icon = world.getTexture( |
|
1099 |
|
data_path, |
|
1100 |
|
"special/" + std::to_string( item.id ) + ".png", |
|
1101 |
|
false |
|
1102 |
|
); |
|
1103 |
|
} |
|
|
1094 |
|
#ifndef __STEAM__ |
|
1095 |
|
AddSpecialItem( "Cake Pan", 100, 1 ); |
|
1096 |
|
#endif |
1104 |
1097 |
|
|
1105 |
1098 |
// 1024 samples keeps audio latency below 45 ms. |
// 1024 samples keeps audio latency below 45 ms. |
1106 |
1099 |
csctx = cs_make_context( nullptr, 44100, 1024, 10, nullptr ); |
csctx = cs_make_context( nullptr, 44100, 1024, 10, nullptr ); |
|
... |
... |
int main( int argc, char* argv[] ){ |
1117 |
1110 |
); |
); |
1118 |
1111 |
|
|
1119 |
1112 |
// Set up graphical effects. |
// Set up graphical effects. |
1120 |
|
std::string frag_path = data_path + "/glsl/postfx.frag"; |
|
1121 |
|
FILE* file = FileOpen( frag_path.c_str(), "rb" ); |
|
1122 |
|
if( !file ){ |
|
1123 |
|
fprintf( stderr, "Failed to open %s\n", frag_path.c_str() ); |
|
1124 |
|
return 1; |
|
1125 |
|
} |
|
1126 |
|
std::string text = ""; |
|
1127 |
|
char buf[4096]; |
|
1128 |
|
while( size_t len = fread( buf, 1, sizeof( buf ), file ) ){ |
|
1129 |
|
text += std::string( buf, len ); |
|
1130 |
|
} |
|
1131 |
|
fclose( file ); |
|
1132 |
|
bloomPipeline = fgl::loadPipeline( fgl::unlitVert, text.c_str(), { "u_texture" } ); |
|
|
1113 |
|
bloomPipeline = LoadShaders( |
|
1114 |
|
data_path + "/glsl/postfx.vert", |
|
1115 |
|
data_path + "/glsl/postfx.frag", |
|
1116 |
|
{ "u_texture" } |
|
1117 |
|
); |
|
1118 |
|
sunlitInstancePipeline = LoadShaders( |
|
1119 |
|
data_path + "/glsl/sunlit_instance.vert", |
|
1120 |
|
data_path + "/glsl/sunlit_instance.frag", |
|
1121 |
|
{ "u_texture" } |
|
1122 |
|
); |
1133 |
1123 |
framebuffer = fgl::createFramebuffer( fgl::getDisplayWidth(), fgl::getDisplayHeight() ); |
framebuffer = fgl::createFramebuffer( fgl::getDisplayWidth(), fgl::getDisplayHeight() ); |
1134 |
1124 |
fgl::setPipeline( fgl::colorModPipeline ); |
fgl::setPipeline( fgl::colorModPipeline ); |
1135 |
1125 |
|
|
|
... |
... |
int main( int argc, char* argv[] ){ |
1207 |
1197 |
} |
} |
1208 |
1198 |
if( param.length() > 12 |
if( param.length() > 12 |
1209 |
1199 |
&& param.substr( 0, 11 ) == "GIVESPECIAL" ){ |
&& param.substr( 0, 11 ) == "GIVESPECIAL" ){ |
1210 |
|
std::string item_name = param.substr( 12 ); |
|
1211 |
|
// TODO: This command and persistence via stats.special.<name>=<number> |
|
1212 |
|
//special_items.push_back( { fgl::newTexture, "Cake Pan", 100, 1 } ); |
|
|
1200 |
|
size_t space_at = param.find_first_of( ' ', 12 ); |
|
1201 |
|
if( space_at == std::string::npos |
|
1202 |
|
|| space_at == param.length() - 1 ){ |
|
1203 |
|
return 0.0; |
|
1204 |
|
} |
|
1205 |
|
double id = |
|
1206 |
|
world.safeStold( param.substr( 12, space_at - 12 ) ); |
|
1207 |
|
AddSpecialItem( param.substr( space_at + 1 ), (int)id, 1 ); |
|
1208 |
|
// TODO: Persistence via stats.special.<name>=<number> |
1213 |
1209 |
return 0.0; |
return 0.0; |
1214 |
1210 |
} |
} |
1215 |
1211 |
if( param.length() >= 16 |
if( param.length() >= 16 |
|
... |
... |
int main( int argc, char* argv[] ){ |
1443 |
1439 |
world.loadItems( data_path + "/items.json" ); |
world.loadItems( data_path + "/items.json" ); |
1444 |
1440 |
|
|
1445 |
1441 |
// Load the list of currently unlocked recipes. |
// Load the list of currently unlocked recipes. |
1446 |
|
file = fopen( ( user_data_path + "/" + user_recipes ).c_str(), "rb" ); |
|
|
1442 |
|
FILE *file = fopen( ( user_data_path + "/" + user_recipes ).c_str(), "rb" ); |
1447 |
1443 |
if( file ){ |
if( file ){ |
1448 |
1444 |
char line[4096]; |
char line[4096]; |
1449 |
1445 |
while( fgets( line, sizeof( line ), file ) ){ |
while( fgets( line, sizeof( line ), file ) ){ |
|
... |
... |
void Achieve( std::string id ){ |
2751 |
2747 |
#endif |
#endif |
2752 |
2748 |
} |
} |
2753 |
2749 |
|
|
|
2750 |
|
void AddSpecialItem( const std::string &name, int id, int count ){ |
|
2751 |
|
for( auto &item : special_items ){ |
|
2752 |
|
if( item.id == id ){ |
|
2753 |
|
item.count += count; |
|
2754 |
|
return; |
|
2755 |
|
} |
|
2756 |
|
} |
|
2757 |
|
special_items.push_back( { |
|
2758 |
|
world.getTexture( |
|
2759 |
|
data_path, |
|
2760 |
|
"special/" + std::to_string( id ) + ".png", |
|
2761 |
|
false |
|
2762 |
|
), |
|
2763 |
|
name, |
|
2764 |
|
id, |
|
2765 |
|
count |
|
2766 |
|
} ); |
|
2767 |
|
} |
|
2768 |
|
|
2754 |
2769 |
// Add an entity to the 2D world at (x,y) with optional index idx. |
// Add an entity to the 2D world at (x,y) with optional index idx. |
2755 |
2770 |
void AddEntity( fworld::Entity &ent, double x, double y, int idx, bool recalc ){ |
void AddEntity( fworld::Entity &ent, double x, double y, int idx, bool recalc ){ |
2756 |
2771 |
bool add_plant = ( ent.type == "flora" ); |
bool add_plant = ( ent.type == "flora" ); |
|
... |
... |
fworld::Entity GetMapSpawn( std::string dataPath, std::string filePath ){ |
3475 |
3490 |
return {}; |
return {}; |
3476 |
3491 |
} |
} |
3477 |
3492 |
|
|
|
3493 |
|
fgl::Pipeline LoadShaders( std::string vertFile, std::string fragFile, std::vector<std::string> samplers ){ |
|
3494 |
|
std::string |
|
3495 |
|
shader_files[2] = { vertFile, fragFile }, |
|
3496 |
|
shader_text[2] = {}; |
|
3497 |
|
for( size_t i = 0; i < 2; i++ ){ |
|
3498 |
|
FILE* file = FileOpen( shader_files[i].c_str(), "rb" ); |
|
3499 |
|
if( !file ){ |
|
3500 |
|
fprintf( stderr, "Failed to open %s\n", shader_files[i].c_str() ); |
|
3501 |
|
return fgl::newPipeline; |
|
3502 |
|
} |
|
3503 |
|
// TODO: Profile this against ftell/fseek. |
|
3504 |
|
char buf[4096]; |
|
3505 |
|
while( size_t len = fread( buf, 1, sizeof( buf ), file ) ){ |
|
3506 |
|
shader_text[i] += std::string( buf, len ); |
|
3507 |
|
} |
|
3508 |
|
fclose( file ); |
|
3509 |
|
} |
|
3510 |
|
return fgl::loadPipeline( shader_text[0].c_str(), shader_text[1].c_str(), samplers ); |
|
3511 |
|
} |
|
3512 |
|
|
3478 |
3513 |
// Bring up a menu that pauses the game. |
// Bring up a menu that pauses the game. |
3479 |
3514 |
void PauseMenu( std::string fileName ){ |
void PauseMenu( std::string fileName ){ |
3480 |
3515 |
if( fgl::mouseTrapped ) |
if( fgl::mouseTrapped ) |
|
... |
... |
void Render(){ |
4789 |
4824 |
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); |
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); |
4790 |
4825 |
// Day/night tinting. |
// Day/night tinting. |
4791 |
4826 |
fgl::setFog( ambient_light ); |
fgl::setFog( ambient_light ); |
4792 |
|
// Draw the world. |
|
|
4827 |
|
// Draw the world (fade in/fade out edition) |
4793 |
4828 |
world.simulate( d ); |
world.simulate( d ); |
4794 |
4829 |
world.drawMap(); |
world.drawMap(); |
4795 |
4830 |
SimulateParticles( d ); |
SimulateParticles( d ); |
|
... |
... |
void SimulateParticles( double d ){ |
5094 |
5129 |
gib.y += gib.vel_y * d; |
gib.y += gib.vel_y * d; |
5095 |
5130 |
gib.z += gib.vel_z * d; |
gib.z += gib.vel_z * d; |
5096 |
5131 |
if( gib.z < gib_floor ){ |
if( gib.z < gib_floor ){ |
5097 |
|
// Add the gib to the floor layer. |
|
5098 |
|
gib.z = gib_floor; |
|
5099 |
|
gib.vel_x = 0.0; |
|
5100 |
|
gib.vel_y = 0.0; |
|
5101 |
|
gib.vel_z = 0.0; |
|
5102 |
|
if( gibs_on_floor.size() == max_gibs ) |
|
5103 |
|
gibs_on_floor.erase( gibs_on_floor.begin() ); |
|
5104 |
|
gibs_on_floor.push_back( gib ); |
|
|
5132 |
|
// 1.34 is the approximate visual offset between a floor particle and a tile. |
|
5133 |
|
// This is a consequence of using multiple different view spaces. |
|
5134 |
|
if( !world.tileBlocking( gib.x, gib.y + 1.34 ) ){ |
|
5135 |
|
// Add the gib to the floor layer. |
|
5136 |
|
gib.z = gib_floor; |
|
5137 |
|
gib.vel_x = 0.0; |
|
5138 |
|
gib.vel_y = 0.0; |
|
5139 |
|
gib.vel_z = 0.0; |
|
5140 |
|
if( gibs_on_floor.size() == max_gibs ) |
|
5141 |
|
gibs_on_floor.erase( gibs_on_floor.begin() ); |
|
5142 |
|
gibs_on_floor.push_back( gib ); |
|
5143 |
|
} |
5105 |
5144 |
// This causes the gib to be deleted from the top layer. |
// This causes the gib to be deleted from the top layer. |
5106 |
5145 |
gib.visible = false; |
gib.visible = false; |
5107 |
5146 |
} |
} |
|
... |
... |
void SimulateParticles( double d ){ |
5115 |
5154 |
), |
), |
5116 |
5155 |
gibs.end() |
gibs.end() |
5117 |
5156 |
); |
); |
|
5157 |
|
// Angle the light to best accentuate the particles. |
|
5158 |
|
fgl::lightMatrix = |
|
5159 |
|
linalg::rotation_matrix( fgl::eulerToQuat( 0.0, -1.5, 1.5 ) ); |
5118 |
5160 |
} |
} |
5119 |
5161 |
|
|
5120 |
5162 |
void DrawFloorParticles(){ |
void DrawFloorParticles(){ |
|
... |
... |
void DrawFloorParticles(){ |
5128 |
5170 |
linalg::vec<double,4>( 0.0, 0.0, 0.0, 1.0 ), |
linalg::vec<double,4>( 0.0, 0.0, 0.0, 1.0 ), |
5129 |
5171 |
linalg::vec<double,3>( gib.x, -gib.y, gib.z ) |
linalg::vec<double,3>( gib.x, -gib.y, gib.z ) |
5130 |
5172 |
), |
), |
5131 |
|
linalg::scaling_matrix( linalg::vec<double,3>( 0.05, 0.05, 0.0 ) ) |
|
|
5173 |
|
linalg::scaling_matrix( linalg::vec<double,3>( 0.05, 0.05, 0.05 ) ) |
5132 |
5174 |
) |
) |
5133 |
5175 |
); |
); |
5134 |
5176 |
} |
} |
|
... |
... |
void DrawFloorParticles(){ |
5139 |
5181 |
viewMat[3][0] += world.cameraX; |
viewMat[3][0] += world.cameraX; |
5140 |
5182 |
viewMat[3][1] -= world.cameraY; |
viewMat[3][1] -= world.cameraY; |
5141 |
5183 |
auto projMat = linalg::perspective_matrix( 68.5 * 0.01745, (double)world.screenWidth / (double)world.screenHeight, 0.1, 44.0 ); |
auto projMat = linalg::perspective_matrix( 68.5 * 0.01745, (double)world.screenWidth / (double)world.screenHeight, 0.1, 44.0 ); |
5142 |
|
// Disable fog for the unlit instance pipeline. |
|
|
5184 |
|
// Disable fog. |
5143 |
5185 |
fgl::Color old_fog = fgl::fogColor; |
fgl::Color old_fog = fgl::fogColor; |
5144 |
5186 |
fgl::setFog( { 0.0f, 0.0f, 0.0f, 0.0f } ); |
fgl::setFog( { 0.0f, 0.0f, 0.0f, 0.0f } ); |
5145 |
5187 |
// Upload attributes. |
// Upload attributes. |
5146 |
5188 |
ib.upload(); |
ib.upload(); |
5147 |
5189 |
// Draw the instance buffer. |
// Draw the instance buffer. |
5148 |
5190 |
auto old_pipeline = fgl::drawPipeline; |
auto old_pipeline = fgl::drawPipeline; |
5149 |
|
fgl::setPipeline( fgl::unlitInstancePipeline ); |
|
|
5191 |
|
fgl::setPipeline( sunlitInstancePipeline ); |
5150 |
5192 |
fgl::setTexture( fgl::blankTexture, 0 ); |
fgl::setTexture( fgl::blankTexture, 0 ); |
5151 |
5193 |
ib.draw( fgl::cubeMesh, viewMat, projMat ); |
ib.draw( fgl::cubeMesh, viewMat, projMat ); |
5152 |
5194 |
ib.clear(); |
ib.clear(); |
|
... |
... |
void DrawParticles(){ |
5170 |
5212 |
// Create an instance for each raindrop. |
// Create an instance for each raindrop. |
5171 |
5213 |
for( auto &drop : raindrops ){ |
for( auto &drop : raindrops ){ |
5172 |
5214 |
ib.push( |
ib.push( |
5173 |
|
(fgl::Color){ 0.17f, 0.3f, 0.35f, 0.75f }, |
|
|
5215 |
|
(fgl::Color){ 0.17f, 0.3f, 0.35f, 0.6f }, |
5174 |
5216 |
linalg::mul( |
linalg::mul( |
5175 |
5217 |
linalg::pose_matrix( |
linalg::pose_matrix( |
5176 |
5218 |
fgl::directionToQuat( { drop.vel_x, drop.vel_y, drop.vel_z }, { 0.0, 0.0, 1.0 } ), |
fgl::directionToQuat( { drop.vel_x, drop.vel_y, drop.vel_z }, { 0.0, 0.0, 1.0 } ), |
|
... |
... |
void DrawParticles(){ |
5187 |
5229 |
viewMat[3][0] += world.cameraX; |
viewMat[3][0] += world.cameraX; |
5188 |
5230 |
viewMat[3][1] -= world.cameraY; |
viewMat[3][1] -= world.cameraY; |
5189 |
5231 |
auto projMat = linalg::perspective_matrix( 68.5 * 0.01745, (double)world.screenWidth / (double)world.screenHeight, 0.1, 44.0 ); |
auto projMat = linalg::perspective_matrix( 68.5 * 0.01745, (double)world.screenWidth / (double)world.screenHeight, 0.1, 44.0 ); |
5190 |
|
// Disable fog for the unlit instance pipeline. |
|
|
5232 |
|
// Disable fog. |
5191 |
5233 |
fgl::Color old_fog = fgl::fogColor; |
fgl::Color old_fog = fgl::fogColor; |
5192 |
5234 |
fgl::setFog( { 0.0f, 0.0f, 0.0f, 0.0f } ); |
fgl::setFog( { 0.0f, 0.0f, 0.0f, 0.0f } ); |
5193 |
5235 |
// Upload attributes. |
// Upload attributes. |
5194 |
5236 |
ib.upload(); |
ib.upload(); |
5195 |
5237 |
// Draw the instance buffer. |
// Draw the instance buffer. |
5196 |
5238 |
auto old_pipeline = fgl::drawPipeline; |
auto old_pipeline = fgl::drawPipeline; |
5197 |
|
fgl::setPipeline( fgl::unlitInstancePipeline ); |
|
|
5239 |
|
fgl::setPipeline( sunlitInstancePipeline ); |
5198 |
5240 |
fgl::setTexture( fgl::blankTexture, 0 ); |
fgl::setTexture( fgl::blankTexture, 0 ); |
5199 |
5241 |
ib.draw( fgl::cubeMesh, viewMat, projMat ); |
ib.draw( fgl::cubeMesh, viewMat, projMat ); |
5200 |
5242 |
ib.clear(); |
ib.clear(); |
|
... |
... |
void GameLoop( double d ){ |
5959 |
6001 |
// Day/night tinting. |
// Day/night tinting. |
5960 |
6002 |
fgl::setFog( ambient_light ); |
fgl::setFog( ambient_light ); |
5961 |
6003 |
|
|
|
6004 |
|
// Draw the world (main game loop edition) |
5962 |
6005 |
if( !sleep_mode ){ |
if( !sleep_mode ){ |
5963 |
6006 |
world.simulate( d ); |
world.simulate( d ); |
5964 |
6007 |
} |
} |
5965 |
|
|
|
5966 |
6008 |
world.drawMap(); |
world.drawMap(); |
5967 |
6009 |
SimulateParticles( d ); |
SimulateParticles( d ); |
5968 |
6010 |
DrawFloorParticles(); |
DrawFloorParticles(); |