void Octree::insert(Entity *entity, MemoryArena *memArena) { if(isLeafNode()) { uint32 hashIndex = entityHashFunction(entity); entity_reference *existingReference = entityReferenceBlock->entityReferences + hashIndex; if(existingReference->index == 0) { existingReference->index = entity->entityID; entityReferenceBlock->entityCount++; } else { // External chaining while(existingReference->next) { existingReference = existingReference->next; } existingReference->next = PushStruct(memArena, entity_reference); existingReference->next->index = entity->entityID; existingReference->next->next = 0; } } else { insertToCollidedChildren(entity, memArena); } entityCount++; }
internal PlayingSound* PlaySound(SoundMixer *mixer, Sound *sound, real32 volume = 1.0f, real32 pitch = 1.0f, bool32 loop = false) { // NOTE(Joey): get new|free PlayingSound at top of linked list PlayingSound *playingSound = 0; if(mixer->FirstFreePlayingSound) { playingSound = mixer->FirstFreePlayingSound; mixer->FirstFreePlayingSound = playingSound->Next; playingSound->Next = 0; } else { playingSound = PushStruct(&mixer->MixerArena, PlayingSound); } playingSound->Next = mixer->FirstPlayingSound; mixer->FirstPlayingSound = playingSound; // NOTE(Joey): initialize playing sound playingSound->Source = sound; playingSound->SamplesPlayed = 0; playingSound->Loop = loop; playingSound->CurrentVolume[0] = playingSound->TargetVolume[0] = volume; playingSound->CurrentVolume[1] = playingSound->TargetVolume[1] = volume; playingSound->dVolume[0] = playingSound->dVolume[1] = 0.0f; playingSound->Pitch = pitch; return playingSound; }
static GameState* CreateNewGameState(char* window_title, int res_x, int res_y) { MemoryArena arena; // NOTE: this is the allocation for the game, store this somewhere if this should be freed manually at some point AllocateMemoryArena(&arena, sizeof(GameState) + GAME_PERMANENT_MEMORY_SIZE + FRAME_TEMPORARY_MEMORY_SIZE); GameState* result = PushStruct(&arena, GameState); result->temporary_memory = CreateSubArena(&arena, FRAME_TEMPORARY_MEMORY_SIZE); result->permanent_memory = CreateSubArena(&arena, GAME_PERMANENT_MEMORY_SIZE); assert(arena.used == arena.size); result->input = PushStruct(&result->permanent_memory, NewInput); result->renderer = CreateRenderer(&result->permanent_memory); InitializeTime(result, MS_PER_FRAME); return result->renderer ? result : nullptr; }
Octree * ConstructOctree(AABBox bounds, uint32 depth, MemoryArena *memArena) { Octree *node = InitOctreeNode(bounds, memArena); if(depth) { for(uint32 child = 0; child < 8; ++child) { bool32 signX = (child & 1); bool32 signY = (child & 2); bool32 signZ = (child & 4); glm::vec3 minBound = glm::vec3(signX ? node->origin.x : node->aabb.minBound.x, signY ? node->origin.x : node->aabb.minBound.y, signZ ? node->origin.z : node->aabb.minBound.z); glm::vec3 maxBound = glm::vec3(signX ? node->aabb.maxBound.x : node->origin.x, signY ? node->aabb.maxBound.y : node->origin.y, signZ ? node->aabb.maxBound.z : node->origin.z); AABBox childBounds = { minBound, maxBound }; node->children[child] = ConstructOctree(childBounds, depth - 1, memArena); } } else { node->entityReferenceBlock = PushStruct(memArena, entity_block); } return node; }
// �D���q�p�r�|���u�� ���q���u�{�� �r �����p�~�y�|�y���u // �B���x�r���p���p�u�� �s�|���q�p�|���~���z �y�~�t�u�{�� ���q���u�{���p �r �s���������u uint32 AddEntityToGroup(memory_arena *Arena, entity_group *Group) { uint32 Result = 0; entity_group *ActiveGroup = Group; while (ActiveGroup->NextGroup) { Result += ActiveGroup->GroupSize; ActiveGroup = ActiveGroup->NextGroup; } if (ActiveGroup->EntityCount == ActiveGroup->GroupSize) { // �P�u���u�����|�~�u�~�y�u, �r���t�u�|�y���� �}�u������ �����t �~���r���� �s���������� entity_group *NextGroup = PushStruct(Arena, entity_group); Assert(NextGroup); NextGroup->Entities = PushArray(Arena, 4096, entity); Assert(NextGroup->Entities); NextGroup->GroupSize = 4096; NextGroup->EntityCount = 0; NextGroup->NextGroup = 0; ActiveGroup->NextGroup = NextGroup; ActiveGroup = NextGroup; } Result += ActiveGroup->EntityCount++; return Result; }
void insert_value(memory_arena *Arena, node **Node, char *Key, void *Value) { if(!(*Node)) { *Node = (node *)PushStruct(Arena, node); (*Node)->Value = Value; strcpy((*Node)->Key, Key); (*Node)->Left = 0; (*Node)->Right = 0; } else if(strcmp((*Node)->Key, Key) < 0) { insert_value(Arena, &((*Node)->Left), Key, Value); } else if(strcmp((*Node)->Key, Key) > 0) { insert_value(Arena, &((*Node)->Right), Key, Value); } else { (*Node)->Value = Value; } return; }
filelines * GetFile(memory_arena *Arena, const char *FileName) { filelines *FileLines = PushStruct(Arena, filelines); struct stat sb; if(stat (FileName, &sb) != 0) { ERROR("Unable to STAT file: %s.", FileName); } else { int32 len = sb.st_size; FILE *DAY = fopen(FileName, "r"); if(DAY) { FileLines->File = (char *)PushSize(Arena, len); fread(FileLines->File, sizeof(char), (len), DAY); FileLines->Lines[0] = FileLines->File; int32 numlines = 1; for(int i = 0; i < len; ++i) { char Character = *(FileLines->File + i); if( Character == EOF) { len = i; break; } if( Character == '\n') { *(FileLines->File + i) = '\0'; FileLines->Lines[numlines] = FileLines->File + i + 1; numlines++; } } FileLines->File[len] = '\0'; FileLines->NumLines = --numlines; FileLines->FileSize = len; fclose(DAY); } else { ERROR("Unable to open file: %s.\n", FileName); FileLines->File = 0; FileLines->NumLines = 0; FileLines->FileSize = -1; } } return(FileLines); }
static Scene* PushScene(MemoryArena* arena, uint32 num_entities) { Scene* result = PushStruct(arena, Scene); result->max_entities = num_entities; result->entities = PushArray(arena, Entity, num_entities); // This should be done when loading a level // This needs to subarena for a quad tree result->tilemap = PushStruct(arena, TileMap); Vec2 map_size = { 100.f, 100.f }; uint32 max_tiles = 1000; AllocateTileMap(arena, result->tilemap, map_size, max_tiles); return result; }
Octree * InitOctreeNode(AABBox bounds, MemoryArena *memArena) { Octree *result = PushStruct(memArena, Octree); result->aabb = bounds; result->origin = (bounds.minBound + bounds.maxBound) * 0.5f; result->entityCount = 0; return result; }
internal debug_tree * AddTree(debug_state *DebugState, debug_variable *Group, v2 AtP) { debug_tree *Tree = PushStruct(&DebugState->DebugArena, debug_tree); Tree->UIP = AtP; Tree->Group = Group; DLIST_INSERT(&DebugState->TreeSentinel, Tree); return Tree; }
// note(caf): DEBUG ONLY internal framebuffer *gmbLoadBitmap(gmbstate *state, memory_arena *arena, char *filename) { void *readIntoMem = state->DEBUGPlatformReadEntireFile(filename); bitmap *b = (bitmap *)readIntoMem; assert(b->Compression == 3); assert(b->Height > 0); assert(b->BitsPerPixel == 32); assert(b->AlphaMask == 0); assert(b->SizeOfBitmap < arena->size - arena->curOffset); // find the first bit that is set for each of the masks int redOffsetShift = findLeastBitSet(b->RedMask); int blueOffsetShift = findLeastBitSet(b->BlueMask); int greenOffsetShift = findLeastBitSet(b->GreenMask); int alphaOffsetShift = findLeastBitSet(b->AlphaMask); // important(caf): assumes 4 bytes per pixel always! framebuffer *f = (framebuffer *)PushStruct(arena, framebuffer, 1); assert(f); f->width = b->Width; f->height = b->Height; f->stride = b->BitsPerPixel / 8; uint32 a, bl, g, r; uint32 *src = (uint32 *)((uint8 *)b + b->BitmapOffset); uint32 *dest = (uint32 *)PushBytes(arena, b->SizeOfBitmap); assert(dest); f->pixels = (void *)dest; // copy the bitmap pixels into memory // note(caf): assumes target bitmap is top-down and source is bottom up // start walking source pixels at the beginning of the last row for (int y = b->Height - 1; y >= 0; y--) { for (int x = 0; x < b->Width; x++) { uint32 *s = src + (y * b->Width) + x; // note(caf): we automatically truncate to the bits we want by casting to // uint8 first a = (uint32)(uint8)(*s >> alphaOffsetShift); bl = (uint32)(uint8)(*s >> blueOffsetShift); g = (uint32)(uint8)(*s >> greenOffsetShift); r = (uint32)(uint8)(*s >> redOffsetShift); // note(caf): assumes target/internal bitmap format ABGR *dest = uint32(a << 24 | bl << 16 | g << 8 | r << 0); dest++; } } if (readIntoMem) { state->DEBUGPlatformFreeFile(readIntoMem); } return f; }
void AllocateTileMap(MemoryArena* arena, TileMap* tilemap, Vec2 map_size, uint32 max_tiles) { tilemap->size = map_size; // TODO: accurate allocation of sub arena tilemap->tiles = PushArray(arena, Tile, max_tiles); tilemap->max_tiles = max_tiles; tilemap->num_tiles = 0; tilemap->quadtree_memory = CreateSubArena(arena, sizeof(TileGroup) * max_tiles); tilemap->tile_quadtree = PushStruct(&tilemap->quadtree_memory, TileGroup); tilemap->tile_quadtree->aabb = { 0, 0, map_size.x, map_size.y }; }
void VenomModuleStart(GameMemory* memory) { SystemInfo* sys = &memory->systemInfo; GameData* data = PushStruct(GameData, &memory->mainBlock); memory->userdata = data; RenderState* rs = &memory->renderState; BeginProfileEntry("Initalize Terrain Generator"); InitalizeTerrainGenerator(&data->terrain, V3(0.0, 0.0, 0.0), &memory->mainBlock); EndProfileEntry(); rs->terrain = &data->terrain; GetEngine()->physicsSimulation.terrain = &data->terrain; #if 0 { ModelData data = {}; data = ImportExternalModelData(VENOM_ASSET_FILE("axis.obj"), 0); FILE* file = fopen("test.txt", "wb"); assert(file != 0); for(size_t i = 0; i < data.meshData.vertexCount; i++) { fprintf(file, "V3{%ff, %ff, %ff},\n", data.meshData.vertices[i].position.x, data.meshData.vertices[i].position.y, data.meshData.vertices[i].position.z); } fprintf(file, "\n"); for(size_t i = 0; i < data.meshData.indexCount; i++) { fprintf(file, "%u,", data.meshData.indices[i]); if(i % 3 == 0) fprintf(file, "\n"); } } #endif InitializeCamera(&data->camera, 45*DEG2RAD, 0.1f, 10000.0f, sys->screenWidth, sys->screenHeight); data->camera.position = {4, 10, 2}; EntityContainerInit(&data->entityContainer, 1024, 8); { AssetManifest *assetManifest = &memory->assetManifest; EntityContainer *entityContainer = &data->entityContainer; EntityIndex player_index; Entity *player = CreateEntity(EntityType_Player, &player_index, entityContainer); assign_model_to_entity(player_index, GetModelID("player", assetManifest), assetManifest, entityContainer); ModelAsset *asset = GetModelAsset(player->modelID, assetManifest); player->animation_state.model_id = player->modelID; player->position = player->position += V3(1, 5.0f, 1); data->playerEntityIndex = player_index; #if 0 Orientation cameraOrientation = CalculateCameraOrientationForTrackTarget(player->position); data->camera.position = cameraOrientation.position; V3 eulerRotation = QuaternionToEuler(cameraOrientation.rotation); data->camera.pitch = eulerRotation.x; data->camera.yaw = eulerRotation.y; #endif RNGSeed seed(15); ScatterInRectangle(&seed, -128, -128, 256, 256, 8, 8, [&](V2 point) { Entity *e = CreateEntity(EntityType_StaticObject, entityContainer); e->modelID = GetModelID("Tree", assetManifest); e->position.x = point.x; e->position.z = point.y; }); } }
// int main(int argc, char* argv[]) int GameMain() { // assert(argc || argv[0]); // Fixes the compiler complaining about unused values; GameState* game_state = CreateNewGameState("EnGen", 1600, 900); Renderer* renderer = game_state->renderer; game_state->active_scene = PushScene(&game_state->permanent_memory, MAX_GAME_ENTITES); TileMap* tilemap = game_state->active_scene->tilemap; for (int32 i = 0; i < 10; ++i) { Vec2 pos = { (float)i, 2.f }; AddTileToMap(tilemap, pos); } for (int32 i = 0; i < 10; ++i) { Vec2 pos = { 0, (float)i }; AddTileToMap(tilemap, pos); } for (int32 i = 0; i < 10; ++i) { Vec2 pos = { 10.f, (float)i }; AddTileToMap(tilemap, pos); } UIWindow* ui = PushStruct(&game_state->permanent_memory, UIWindow); SetTitle(ui, "Editor UI!"); SetSize(ui, { 0.1f, 0.3f, 0.2f, 0.2f }, 0.05f); UIWindow* ui2 = PushStruct(&game_state->permanent_memory, UIWindow); SetTitle(ui2, "Editor UI2!"); SetSize(ui2, { 0.2f, 0.3f, 0.2f, 0.2f }, 0.05f); InitializeDebugConsole(); #if 0 InitializeAudio(); char* test_sound_file = "C:\\projects\\imperial_march.wav"; bool test_sound_loaded = LoadWavFile(test_sound_file); if(test_sound_loaded) { printf("Loaded File\n"); } PauseAudio(false); #endif Camera default_camera = {}; // maybe put this in game_state? default_camera.position = vec2(0, 0); default_camera.viewport_size.x = 16; default_camera.viewport_size.y = 9; uint32 frame_count = 0; uint32 fps = 0; double last_fps_time = 0; bool running = true; while (running) { ProfileBeginFrame(); ProfileBeginSection(Profile_Frame); ProfileBeginSection(Profile_Input); Platform_RunMessageLoop(game_state->input); Camera* draw_camera = game_state->active_camera ? game_state->active_camera : &default_camera; game_state->window.resolution = Platform_GetResolution(); UpdateMouseWorldPosition(game_state->input, game_state->window.resolution, draw_camera->viewport_size, draw_camera->position); ProfileEndSection(Profile_Input); Vec2i mouse_pos = MousePosition(game_state->input); //DebugPrintf("Mouse World Position: (%.2f, %.2f)", mouse_pos.x, mouse_pos.y); DebugPrintf("Mouse World Position: (%d, %d)", mouse_pos.x, mouse_pos.y); DebugPrintf("Main Camera Position: (%.2f, %.2f)", default_camera.position.x, default_camera.position.y); DebugPrintf("Key Pressed: %s", IsDown(game_state->input, KeyCode_a) ? "TRUE" : "FALSE"); if (OnDown(game_state->input, KeyCode_ESCAPE)) { running = false; break; } #if 0 // TODO: Platform layer if (OnDown(game_state->input, KeyCode_z)) { ForceColorClear(); SwapBuffer(game_state); //WindowSetScreenMode(&game_state->window, ScreenMode_Windowed); } else if (OnDown(game_state->input, KeyCode_c)) { ForceColorClear(); SwapBuffer(game_state); //WindowSetScreenMode(&game_state->window, ScreenMode_Borderless); } #endif static bool draw_debug = true; if (OnDown(game_state->input, KeyCode_BACKQUOTE)) { draw_debug = !draw_debug; } Renderer* debug_renderer = draw_debug ? renderer : 0; TimeBeginFrame(game_state); // Update the scene first, pushing draw calls if necessary. // Then call begin_frame which builds matrices and clears buffers; float current_time = CurrentTime(game_state); if (current_time - last_fps_time > 1.0f) { last_fps_time = current_time; fps = frame_count; frame_count = 0; } frame_count++; DebugPrintf("FPS: \t\t%d \tFrames: \t%d", fps, FrameCount(game_state)); DebugControlCamera(game_state, &default_camera); // TODO(cgenova): separate update and render calls so that things can be set up when rendering begins; BeginFrame(renderer, &game_state->window); ProfileBeginSection(Profile_SceneUpdate); DebugPrintPushColor(vec4(1.0f, 0, 0, 1.0f)); DebugPrintf("Active scene entity usage: (%d / %d)", game_state->active_scene->active_entities, MAX_GAME_ENTITES); DebugPrintPopColor(); UpdateSceneEntities(game_state, game_state->active_scene); DrawSceneEntities(game_state->active_scene, renderer); ProfileEndSection(Profile_SceneUpdate); #if 1 // Spaghetti test const size_t num_verts = 200; static SimpleVertex v[num_verts]; static bool initialized = false; if (!initialized) { initialized = true; for (uint32 i = 0; i < num_verts; ++i) { SimpleVertex verts = {}; verts.position = vec2((float)(i / 50.f) - 2.f, (float)i); verts.color = vec4(1, 1, 0, 1.f); v[i] = verts; } } else { for (uint32 i = 0; i < num_verts; ++i) { v[i].position.y = sin(CurrentTime(game_state) + i / (PI * 20)); } } PrimitiveDrawParams spaghetti_params = {}; spaghetti_params.line_draw_flags |= PrimitiveDraw_Smooth; // spaghetti_params.line_draw_flags |= Draw_ScreenSpace; spaghetti_params.line_width = 0; DrawLine(renderer, v, num_verts, spaghetti_params); #endif DrawTileMap(game_state, game_state->active_scene->tilemap); UpdateUIWindow(game_state, ui); UpdateUIWindow(game_state, ui2); RenderDrawBuffer(renderer, draw_camera); ProfileEndSection(Profile_Frame); ProfileEndFrame(debug_renderer, TARGET_FPS); DebugDrawConsole(debug_renderer); // NOTE: // For drawing Debug info, the profiling in this section will be discarded, // but it is only drawing text and the debug graph. RenderDrawBuffer(renderer, draw_camera); SwapBuffer(game_state); // TODO(cgenova): High granularity sleep function! ResetArena(&game_state->temporary_memory); }// End main loop return 1; }
void InitGameMemory(game_memory *Memory, Canvas &canvas) { // �I�~�y���y�p�|�y�x�p���y�� game_state* GameState = (game_state*)Memory->PermanentStorage; InitializeArena(&GameState->WorldArena, Memory->PermanentStorageSize - sizeof(game_state), (uint8*)Memory->PermanentStorage + sizeof(game_state)); GameState->World = PushStruct(&GameState->WorldArena, world); world *World = GameState->World; World->TileMap = PushStruct(&GameState->WorldArena, tile_map); tile_map *TileMap = World->TileMap; GameState->Tick = 0; GameState->TimeElapsedFromLastTick = 0; // Camera GameState->CameraPos.Tile = Vec2i(0, 0); GameState->CameraPos.TilePos = Vec2f(0, 0); GameState->CameraOrigin = GameState->ScreenSize / 2.0f; GameState->EntityToCameraIn = Rect(-7, -5, 7, 5); GameState->EntityToCameraOut = Rect(-8, -6, 8, 6); // �H�p�s�����x�y���� �������p�z���� GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_sprite, "sand_tile_01.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_object_sprite_001, "object_storage_01.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_object_sprite_stone1, "object_stone_01.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_player_image, "robot_base_horizontal.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_player_image_v, "robot_base_vertical.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_player_image_ur, "robot_base_diagonal_ur.png"); GameState->LoadGameSpriteFromImage(canvas, GameState->GameSprites.tmp_player_image_ul, "robot_base_diagonal_ul.png"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_ground_sprite_01, "ground_concrete_tileset"); GameState->AddGameSpriteFrameFromImage(canvas, GameState->GameSprites.tmp_ground_sprite_01, "ground_tile_01.png"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_torso, "robot_torso"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_down, "track_v_down"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_left, "track_h_left"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_right, "track_h_right"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_up, "track_v_up"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_ur, "track_d_ur"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_ul, "track_d_ul"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_br, "track_d_br"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_player_image_track_bl, "track_d_bl"); GameState->LoadGameSpriteFromResource(canvas, &GameState->game_resources, GameState->GameSprites.tmp_wall_sprite1, "tileset_brick_wall"); // Player entity // GameState->PlayerEntity = AddEntity(GameState); GameState->PlayerEntity->Position.Tile = Vec2i(0, 0); GameState->PlayerEntity->Position.TilePos = Vec2f(0, 0); GameState->PlayerEntity->EntityType = EntityType_Robot; GameState->PlayerEntity->CollisionType = 1; GameState->PlayerEntity->CollisionBox = Rectf(-0.45f, -0.25f, 0.45f, 0.25f); GameState->PlayerEntity->Controller.Active = 1; GameState->PlayerEntity->Mass = 20000.0f; GameState->PlayerEntity->RResistance = 0.008f; SetEntityToActive(GameState->PlayerEntity, GameState); World->TileSizeMeters = Vec2f(1.0f, 1.0f); World->TileSizePixels = Vec2f(100.0f, 100.0f); World->MetersToPixels = World->TileSizePixels / World->TileSizeMeters; World->g = 4.2f; TileMap->TileChunkSize = Vec2ui(16, 16); //TileMap->CenterChunkPosition = TileMap->TileChunksCount / (uint32)2; GameState->TilesOnHalfScreen.width = (int)((GameState->ScreenSize.width / 2) / World->TileSizePixels.x) + 1; GameState->TilesOnHalfScreen.height = (int)((GameState->ScreenSize.height / 2) / World->TileSizePixels.y) + 1; Vec2i TilesPerScreen = GameState->TilesOnHalfScreen * 2; for (int32 ScreenY = -16; ScreenY < 16; ScreenY++) { for (int32 ScreenX = -16; ScreenX < 16; ScreenX++) { for (int32 TY = 0; TY < TilesPerScreen.y; TY++) { for (int32 TX = 0; TX < TilesPerScreen.x; TX++) { int32 AbsTileX = ScreenX * TilesPerScreen.x + TX; int32 AbsTileY = ScreenY * TilesPerScreen.y + TY; SetTileValue(&GameState->WorldArena, TileMap, Vec2i(AbsTileX, AbsTileY), rand() % 16 + 1); } } } } /* for (int32 Y = 1; Y < 4; Y++) { for (int32 X = 1; X < 5; X++) { SetTileValue(&GameState->WorldArena, TileMap, Vec2i(X, Y), 5); SetTileValue(&GameState->WorldArena, TileMap, Vec2i(X - 7, Y), 5); SetTileValue(&GameState->WorldArena, TileMap, Vec2i(X - 5, Y + 6), 4); } } */ // Game entities GameState->TiledEntities.Entities = PushArray(&GameState->WorldArena, 4096, entity); GameState->TiledEntities.GroupSize = 4096; GameState->TiledEntities.EntityCount = 0; GameState->TiledEntities.NextGroup = 0; AddEntityToGroup(&GameState->WorldArena, &GameState->TiledEntities); // �N���|�u�r���z ���q���u�{�� �~�u �y�������|���x���u������ // Add many stone entities world_position EntityPos; //Rectf CollisionBox(-0.4f, 0.0f, 0.4f, 0.3f); Rectf CollisionBox(-0.5f, -0.5f, 0.5f, 0.5f); for (int32 Y = 1; Y < 10; Y++) { for (int32 X = 1; X < 10; X++) { EntityPos.Tile = Vec2i(X, Y); EntityPos.TilePos = Vec2f(0, 0); uint32 StoneIndex = AddEntityToGroup(&GameState->WorldArena, &GameState->TiledEntities); entity *Entity = GetEntityFromGroupByIndex(&GameState->TiledEntities, StoneIndex); Entity->EntityType = EntityType_Storage; Entity->Position = EntityPos; Entity->CollisionType = 1; Entity->CollisionBox = CollisionBox; AddEntityToTile(GameState->World->TileMap, EntityPos.Tile, StoneIndex); } } /* EntityPos.Tile = Vec2i(1, 1); EntityPos.TilePos = Vec2f(0, 0); entity *Entity = AddEntity(GameState); Entity->EntityType = EntityType_Stone; Entity->Position = EntityPos; Entity->CollisionType = 1; Entity->CollisionBox = CollisionBox; //SetEntityToActive(Entity, GameState); /* Entity = AddEntity(GameState); Entity->EntityType = EntityType_Wall; EntityPos.Tile = Vec2i(0, -2); Entity->Position = EntityPos; Entity->CollisionType = 1; Entity->CollisionBox = Rectf(-0.5f, -0.1f, 0.5f, 0.1f); Entity->EntityFrame = 0; //SetEntityToActive(Entity, GameState); */ // Call to camera reset to activate entities in camera space MapEntitiesInCameraSpace(GameState); GameState->IsInitialized = 1; }
void LoadSound(assets_s* assets, soundId_s id, taskWithMemory_s* tasks, uint32_t maxTaskCount) { if (id.value) { if((AtomicCompareExchangeUint8(GetLsbPointer(&assets->slots[id.value].state), (uint8_t) assetState_queued, (uint8_t) assetState_unloaded) != assetState_unloaded)) { return; } } else { return; } assetData_s* slot = &assets->slots[id.value]; SetSlotType(slot, assetSlotType_sound); assetFileData_s* asset = &assets->assets[id.value]; waAssetFileData_s* waAsset = &asset->wa; waSound_s* info = &waAsset->sound; sound_s* sound = &slot->sound; sound->sampleCount = info->sampleCount; sound->channelCount = info->channelCount; Assert(sound->channelCount < ArrayCount(sound->samples)); uint32_t channelSize = sound->sampleCount * sizeof(int16_t); slot->memorySize = sound->channelCount * channelSize; void* memory = AcquireAssetMemory(assets, (uint64_t) slot->memorySize); if(!memory) { SetSlotState(slot, assetState_unloaded); return; } int16_t* soundAt = (int16_t*) memory; for(uint32_t channelIndex = 0; channelIndex < sound->channelCount; ++channelIndex) { sound->samples[channelIndex] = soundAt; soundAt += channelSize; } taskWithMemory_s* task = BeginTaskWithMemory(tasks, maxTaskCount); if(!task) { SetSlotState(slot, assetState_unloaded); return; } loadAssetWork_s* lawData = PushStruct(&task->memoryBlock, loadAssetWork_s); lawData->task = task; lawData->slot = slot; lawData->handle = GetFileHandle(assets, asset->fileIndex); lawData->offset = waAsset->dataOffset; lawData->size = slot->memorySize; lawData->destination = memory; lawData->finalState = assetState_loaded; slot->cell = Append(&assets->assetUseQueue, slot); Platform.addEntry(Platform.workQueues, LoadAssetWork, lawData, queueLevel_1); }
// �R���x�t�p���� �t�p�~�~���u �p�{���y�r�~���s�� ���q���u�{���p // TODO: �y�x�q�p�r�y�������� ���� �������s�� �y�x�r���p���u�~�y�� void PushActiveEntity(entity *Entity, memory_arena *Arena, world_position CameraPos) { Entity->ActiveData = PushStruct(Arena, entity_active_data); Entity->ActiveData->EntityBaseData = Entity; Entity->ActiveData->Pos = Vec2f(Entity->Position.Tile - CameraPos.Tile) + Entity->Position.TilePos; }
void LoadFont(assets_s* assets, fontId_s id, taskWithMemory_s* tasks, uint32_t maxTaskCount, bool locked, bool spawnThread) { if (id.value) { if(AtomicCompareExchangeUint8(GetLsbPointer(&assets->slots[id.value].state), (uint8_t) assetState_queued, (uint8_t) assetState_unloaded) != assetState_unloaded) { return; } } else { return; } assetData_s* slot = &assets->slots[id.value]; SetSlotType(slot, assetSlotType_font); assetFileData_s* asset = &assets->assets[id.value]; waAssetFileData_s* waAsset = &asset->wa; waFont_s* info = &waAsset->font; font_s* font = &slot->font; font->glyphType = info->glyphType; font->minCodePoint = info->minCodePoint; font->maxCodePoint = info->maxCodePoint; font->codePointRange = font->maxCodePoint - font->minCodePoint + 1; font->ascenderHeight = info->ascenderHeight; font->descenderHeight = info->descenderHeight; font->externalLeading = info->externalLeading; font->glyphCount = info->glyphCount; size_t codePointToIndexSize = sizeof(uint32_t) * MAX_UNICODE_VALUE; size_t horizontalAdvanceSize = sizeof(float) * info->glyphCount * info->glyphCount; slot->memorySize = codePointToIndexSize + horizontalAdvanceSize; font->codePointToIndex = (uint32_t*) AcquireAssetMemory(assets, (uint64_t) slot->memorySize); if(!font->codePointToIndex) { SetSlotState(slot, assetState_unloaded); return; } font->horizontalAdvance = (float*) (((uint8_t*) font->codePointToIndex) + codePointToIndexSize); taskWithMemory_s* task = BeginTaskWithMemory(tasks, maxTaskCount); if(!task) { SetSlotState(slot, assetState_unloaded); return; } loadAssetWork_s* lawData = PushStruct(&task->memoryBlock, loadAssetWork_s); lawData->task = task; lawData->handle = GetFileHandle(assets, asset->fileIndex); lawData->slot = slot; lawData->offset = waAsset->dataOffset; lawData->size = slot->memorySize; lawData->destination = font->codePointToIndex; lawData->finalState = (uint8_t)assetState_loaded; lawData->lockState = (uint8_t)(locked ? assetState_locked : 0); slot->cell = Append(&assets->assetUseQueue, slot); if(spawnThread) { Platform.addEntry(Platform.workQueues, LoadAssetWork, lawData, queueLevel_1); } else { RawLoadAssetWork(lawData); } }
void LoadBitmap(assets_s* assets, bitmapId_s id, taskWithMemory_s* tasks, uint32_t maxTaskCount, bool locked, bool spawnThread) { if (id.value) { if(AtomicCompareExchangeUint8(GetLsbPointer(&assets->slots[id.value].state), (uint8_t) assetState_queued, (uint8_t) assetState_unloaded) != assetState_unloaded) { return; } } else { return; } assetData_s* slot = &assets->slots[id.value]; SetSlotType(slot, assetSlotType_bitmap); assetFileData_s* asset = &assets->assets[id.value]; waAssetFileData_s* waAsset = &asset->wa; waBitmap_s* info = &waAsset->bitmap; bitmap_s* bitmap = &slot->bitmap; bitmap->width = info->dim[0]; bitmap->height = info->dim[1]; bitmap->alignPercentage = V2(info->alignPercentage[0], info->alignPercentage[1]); bitmap->widthOverHeight = info->widthOverHeight; bitmap->heightOverWidth = info->heightOverWidth; bitmap->pitch = 4*info->dim[0]; slot->memorySize = bitmap->pitch * bitmap->height; bitmap->memory = AcquireAssetMemory(assets, (uint64_t) slot->memorySize); if(!bitmap->memory) { SetSlotState(slot, assetState_unloaded); return; } taskWithMemory_s* task = BeginTaskWithMemory(tasks, maxTaskCount); if(!task) { SetSlotState(slot, assetState_unloaded); return; } loadAssetWork_s* lawData = PushStruct(&task->memoryBlock, loadAssetWork_s); lawData->task = task; lawData->handle = GetFileHandle(assets, asset->fileIndex); lawData->slot = slot; lawData->offset = waAsset->dataOffset; lawData->size = slot->memorySize; lawData->destination = bitmap->memory; lawData->finalState = (uint8_t)assetState_loaded; lawData->lockState = (uint8_t)(locked ? assetState_locked : 0); slot->cell = Append(&assets->assetUseQueue, slot); if(spawnThread) { Platform.addEntry(Platform.workQueues, LoadAssetWork, lawData, queueLevel_1); } else { RawLoadAssetWork(lawData); } }
void LoadCard(assets_s* assets, cardId_s id, taskWithMemory_s* tasks, uint32_t maxTaskCount) { // LoadCard(group->assets, id, tasks, maxTaskCount, false, false) if (id.value) { if(AtomicCompareExchangeUint8(GetLsbPointer(&assets->slots[id.value].state), (uint8_t) assetState_queued, (uint8_t) assetState_unloaded) != assetState_unloaded) { return; } } else { return; } assetData_s* slot = &assets->slots[id.value]; SetSlotType(slot, assetSlotType_bitmap); assetFileData_s* asset = &assets->assets[id.value]; waAssetFileData_s* waAsset = &asset->wa; waCard_s* info = &waAsset->card; cardData_s* cardData = &slot->card; cardData->cardId = info->id; cardData->selfSeconds = info->selfSeconds; cardData->oppSeconds = info->oppSeconds; cardData->redValue = info->redValue; cardData->redCost = info->redCost; cardData->blueValue = info->blueValue; cardData->blueCost = info->blueCost; cardData->greenValue = info->greenValue; cardData->greenCost = info->greenCost; //effects cardData->cardToDrawCondition = effectConditions_none; cardData->cardToDraw = 0; // #define CARD_STRING_MAX_LENGTH 140 // char tempString[CARD_STRING_MAX_LENGTH]; slot->memorySize = info->descriptionLength; cardData->description = (char*) AcquireAssetMemory(assets, (uint64_t) slot->memorySize); //TODO: acquire memory for composite string if(!cardData->description) { SetSlotState(slot, assetState_unloaded); return; } taskWithMemory_s* task = BeginTaskWithMemory(tasks, maxTaskCount); if(!task) { SetSlotState(slot, assetState_unloaded); return; } loadAssetWork_s* lawData = PushStruct(&task->memoryBlock, loadAssetWork_s); lawData->task = task; lawData->handle = GetFileHandle(assets, asset->fileIndex); lawData->slot = slot; lawData->offset = waAsset->dataOffset; lawData->size = slot->memorySize; lawData->destination = cardData->description; lawData->finalState = (uint8_t)assetState_loaded; lawData->lockState = 0; slot->cell = Append(&assets->assetUseQueue, slot); RawLoadAssetWork(lawData); }
assets_s* AllocateAssets(memoryBlock_s* memoryBlock) { assets_s* assets = PushStruct(memoryBlock, assets_s); assets->assetUseQueue = InitLinkedList(memoryBlock, Kilobytes(2)); assets->dyMemoryBlock = InitDynamicMemoryBlock(memoryBlock, Megabytes(64), Kilobytes(10)); assets->tagCount = 1; assets->assetCount = 1; platformFileGroup_s* fileGroup = Platform.getAllFilesOfTypeBegin("wa"); assets->fileCount = fileGroup->fileCount; assets->files = PushArray(memoryBlock, assets->fileCount, assetFile_s); for(uint32_t index = 0; index < assets->fileCount; index++) { assetFile_s* file = assets->files + index; file->tagBase = assets->tagCount; file->handle = Platform.openNextFile(fileGroup); file->header = {}; Platform.readDataFromFile(file->handle, 0, sizeof(file->header), &file->header); uint32_t assetTypeArraySize = file->header.assetTypesCount*sizeof(waAssetType_s); file->assetTypeArray = (waAssetType_s*) PushSize(memoryBlock, assetTypeArraySize); Platform.readDataFromFile(file->handle, file->header.assetTypes, assetTypeArraySize, file->assetTypeArray); if(PlatformNoFileErrors(file->handle)) { if(file->header.magicValue != MAGIC_VALUE) { Platform.fileError(file->handle, "wa file has an invalid magic value"); } if(file->header.version > WALLACE_ASSET_VERSION) { Platform.fileError(file->handle, "wa file has a version which exceeds game version"); } if(PlatformNoFileErrors(file->handle)) { // NOTE: The first asset and tag slot in every // .wa is a null (reserved) so we don't count it as // something we will need space for! assets->tagCount += (file->header.tagCount - 1); assets->assetCount += (file->header.assetCount - 1); } } else { InvalidCodePath; } } Platform.getAllFilesOfTypeEnd(fileGroup); assets->assets = PushArray(memoryBlock, assets->assetCount, assetFileData_s); assets->slots = PushArray(memoryBlock, assets->assetCount, assetData_s); assets->tags = PushArray(memoryBlock, assets->tagCount, waTag_s); assets->tags[0] = {}; for(uint32_t fileIndex = 0; fileIndex < assets->fileCount; fileIndex++) { assetFile_s* file = assets->files + fileIndex; if(PlatformNoFileErrors(file->handle)) { uint32_t tagArraySize = sizeof(waTag_s) * (file->header.tagCount - 1); Platform.readDataFromFile(file->handle, file->header.tags + sizeof(waTag_s), tagArraySize, assets->tags + file->tagBase); } } // NOTE: Reserve one null asset at the beginning uint32_t assetCount = 0; assets->assets[assetCount] = {}; assetCount++; for(uint32_t destTypeId = 0; destTypeId < assetType_last; destTypeId++) { waAssetType_s* destType = assets->assetTypes + destTypeId; destType->firstAssetIndex = assetCount; for(uint32_t fileIndex = 0; fileIndex < assets->fileCount; fileIndex++) { assetFile_s* file = assets->files + fileIndex; if(PlatformNoFileErrors(file->handle)) { for(uint32_t sourceIndex = 0; sourceIndex < file->header.assetTypesCount; sourceIndex++) { waAssetType_s* sourceType = file->assetTypeArray + sourceIndex; if(sourceType->typeId == destTypeId) { uint32_t assetCountForType = sourceType->onePastLastAssetIndex - sourceType->firstAssetIndex; temporaryMemory_s tempMem = BeginTemporaryMemory(memoryBlock); waAssetFileData_s* waAssetArray = PushArray(memoryBlock, assetCountForType, waAssetFileData_s); Platform.readDataFromFile(file->handle, file->header.assets + sourceType->firstAssetIndex * sizeof(waAssetFileData_s), assetCountForType * sizeof(waAssetFileData_s), waAssetArray); for(uint32_t assetIndex = 0; assetIndex < assetCountForType; assetIndex++) { waAssetFileData_s* waAsset = waAssetArray + assetIndex; // Assert(assetCount < assets->assetCount); assetFileData_s* asset = assets->assets + assetCount++; asset->fileIndex = fileIndex; asset->wa = *waAsset; if(asset->wa.firstTagIndex == 0) { asset->wa.firstTagIndex = 0; asset->wa.onePastLastTagIndex = 0; } else { asset->wa.firstTagIndex += (file->tagBase - 1); asset->wa.onePastLastTagIndex += (file->tagBase - 1); } } EndTemporaryMemory(tempMem); } } } } destType->onePastLastAssetIndex = assetCount; } // Assert(assetCount == assets->assetCount); return assets; }
int main() { SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_Window * window = SDL_CreateWindow("gamedev", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 768, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); if(window) { SDL_GLContext gl_context = SDL_GL_CreateContext(window); // Initialize GLEW so we can get 3.30 stuff // I copied this from my quaternion demo // TODO: Can I do this without glew? // This experimental flag seems to be necessary for GLEW to load entry points // for certain core profile functions, like glGenVertexArrays. Really // looking forward to getting rid of GLEW glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); exit(1); // or handle the error in a nicer way } if (!GLEW_VERSION_3_3) // { printf("Missing OpenGL version 3.3\n"); exit(1); // or handle the error in a nicer way } printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); game_memory Memory = {}; Memory.PermanentStoreSize = Megabytes(256); Memory.TransientStoreSize = Gigabytes(1); Memory.TotalSize = Memory.PermanentStoreSize + Memory.TransientStoreSize; void * AllocatedMemory = mmap(0, Memory.TotalSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); if(AllocatedMemory != MAP_FAILED) { //TODO: zero out the memory? Memory.PermanentStore = (uint8*)AllocatedMemory; Memory.TransientStore = Memory.PermanentStore + Memory.PermanentStoreSize; Memory.PermanentArena.Base = Memory.PermanentStore; Memory.PermanentArena.Size = Memory.PermanentStoreSize; Memory.PermanentArena.Offset = 0; Memory.TransientArena.Base = Memory.TransientStore; Memory.TransientArena.Size = Memory.TransientStoreSize; Memory.TransientArena.Offset = 0; game_state * GameState = PushStruct(&Memory.PermanentArena, game_state); bool Quit = false; while(!Quit) { // Handle keyboard events SDL_Event Event; while(SDL_PollEvent(&Event)) { // TODO: probably don't want to take all the events here switch(Event.type) { case SDL_KEYUP: case SDL_KEYDOWN: SDL_KeyboardEvent KB_Event = Event.key; SDL_Keysym Keysym = KB_Event.keysym; switch(Keysym.sym) { case SDLK_q: Quit = true; break; } break; } } // Update/draw UpdateAndRender(&Memory, GameState); SDL_GL_SwapWindow(window); } } SDL_GL_DeleteContext(gl_context); } else { printf("Could not initialize SDL window."); return 1; } return 0; }