BucketArray<T> BucketArray<T>::initBucketArray(uint32 elementSize, uint32 numElems, uint32 numBuckets, MemoryArena *arena) { elemSize = elementSize; elemCount = numElems; bucketCount = numBuckets; occupancy = PushArray(arena, elemCount * bucketCount, uint8); }
// �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 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 }; }
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; }
internal void SetTileValue(memory_arena *Arena, tile_map *TileMap, uint32 AbsTileX, uint32 AbsTileY, uint32 AbsTileZ, uint32 TileValue) { tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ); tile_chunk *TileChunk = GetTileChunk(TileMap, ChunkPos.TileChunkX, ChunkPos.TileChunkY, ChunkPos.TileChunkZ); Assert(TileChunk); if(!TileChunk->Tiles) { uint32 TileCount = TileMap->ChunkDim*TileMap->ChunkDim; TileChunk->Tiles = PushArray(Arena, TileCount, uint32); for(uint32 TileIndex = 0; TileIndex < TileCount; ++TileIndex) { TileChunk->Tiles[TileIndex] = 1; } } SetTileValue(TileMap, TileChunk, ChunkPos.RelTileX, ChunkPos.RelTileY, TileValue); }
INTERNAL void SetTileValue(MemoryArena* arena, TileMap* tileMap, uint32 absTileX, uint32 absTileY, uint32 absTileZ, uint32 tileValue) { TileChunkPosition chunkPosition = tileMap->GetChunkPositionFor(absTileX, absTileY, absTileZ); TileChunk* tileChunk = tileMap->GetTileChunk(chunkPosition.tileChunkX, chunkPosition.tileChunkY, chunkPosition.tileChunkZ); // TODO(Peacock): Create tile chunk if not already there ASSERT(tileChunk); if (!tileChunk->tiles) { uint32 tileCount = tileMap->chunkDim * tileMap->chunkDim; tileChunk->tiles = PushArray(arena, tileCount, uint32); for (uint32 i = 0; i < tileCount; ++i) { tileChunk->tiles[i] = 1; } } SetTileValue(tileMap, tileChunk, chunkPosition.relTileX, chunkPosition.relTileY, tileValue); }
int NativeInvoker::PushCellByRef(cell_t *cell, int flags) { return PushArray(cell, 1, flags); }
int CFunction::PushCellByRef(cell_t *cell, int flags) { return PushArray(cell, 1, flags); }
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; }
void ExecuteCycle(VM* vm) { if(vm->pc == -1) return; if(vm->debug) printf("pc %i: ", vm->pc); if(vm->stackSize < vm->numGlobals) printf("Global(s) were removed from the stack!\n"); switch(vm->program[vm->pc]) { case OP_PUSH_NULL: { if(vm->debug) printf("push_null\n"); ++vm->pc; PushObject(vm, &NullObject); } break; case OP_PUSH_NUMBER: { if(vm->debug) printf("push_number\n"); ++vm->pc; int index = ReadInteger(vm); PushNumber(vm, vm->numberConstants[index]); } break; case OP_PUSH_STRING: { if(vm->debug) printf("push_string\n"); ++vm->pc; int index = ReadInteger(vm); PushString(vm, vm->stringConstants[index]); } break; case OP_PUSH_FUNC: { if(vm->debug) printf("push_func\n"); Word hasEllipsis = vm->program[++vm->pc]; Word isExtern = vm->program[++vm->pc]; Word numArgs = vm->program[++vm->pc]; ++vm->pc; int index = ReadInteger(vm); PushFunc(vm, index, hasEllipsis, isExtern, numArgs); } break; case OP_PUSH_DICT: { if(vm->debug) printf("push_dict\n"); ++vm->pc; PushDict(vm); } break; case OP_CREATE_DICT_BLOCK: { if(vm->debug) printf("create_dict_block\n"); ++vm->pc; int length = ReadInteger(vm); Object* obj = PushDict(vm); if(length > 0) { // stack (before dict) is filled with key-value pairs (backwards, key is higher on stack) for(int i = 0; i < length * 2; i += 2) DictPut(&obj->dict, vm->stack[vm->stackSize - i - 2]->string.raw, vm->stack[vm->stackSize - i - 3]); vm->stackSize -= length * 2; vm->stack[vm->stackSize - 1] = obj; } } break; case OP_CREATE_ARRAY: { if(vm->debug) printf("create_array\n"); ++vm->pc; int length = (int)PopNumber(vm); PushArray(vm, length); } break; case OP_CREATE_ARRAY_BLOCK: { if(vm->debug) printf("create_array_block\n"); ++vm->pc; int length = ReadInteger(vm); Object* obj = PushArray(vm, length); if(length > 0) { for(int i = 0; i < length; ++i) obj->array.members[length - i - 1] = vm->stack[vm->stackSize - 2 - i]; vm->stackSize -= length; vm->stack[vm->stackSize - 1] = obj; } } break; case OP_LENGTH: { if(vm->debug) printf("length\n"); ++vm->pc; Object* obj = PopObject(vm); if(obj->type == OBJ_STRING) PushNumber(vm, strlen(obj->string.raw)); else if(obj->type == OBJ_ARRAY) PushNumber(vm, obj->array.length); else { fprintf(stderr, "Attempted to get length of %s\n", ObjectTypeNames[obj->type]); exit(1); } } break; case OP_ARRAY_PUSH: { if(vm->debug) printf("array_push\n"); ++vm->pc; Object* obj = PopArrayObject(vm); Object* value = PopObject(vm); while(obj->array.length + 1 >= obj->array.capacity) { obj->array.capacity *= 2; obj->array.members = erealloc(obj->array.members, obj->array.capacity * sizeof(Object*)); } obj->array.members[obj->array.length++] = value; } break; case OP_ARRAY_POP: { if(vm->debug) printf("array_pop\n"); ++vm->pc; Object* obj = PopArrayObject(vm); if(obj->array.length <= 0) { fprintf(stderr, "Cannot pop from empty array\n"); exit(1); } PushObject(vm, obj->array.members[--obj->array.length]); } break; case OP_ARRAY_CLEAR: { if(vm->debug) printf("array_clear\n"); ++vm->pc; Object* obj = PopArrayObject(vm); obj->array.length = 0; } break; case OP_DICT_SET: { if(vm->debug) printf("dict_set\n"); ++vm->pc; Object* obj = PopDict(vm); const char* key = PopString(vm); Object* value = PopObject(vm); DictPut(&obj->dict, key, value); } break; case OP_DICT_GET: { if(vm->debug) printf("dict_get\n"); ++vm->pc; Object* obj = PopDict(vm); const char* key = PopString(vm); Object* value = DictGet(&obj->dict, key); if(value) PushObject(vm, value); else PushObject(vm, &NullObject); } break; case OP_DICT_PAIRS: { if(vm->debug) printf("dict_pairs\n"); ++vm->pc; Object* obj = PopDict(vm); Object* aobj = PushArray(vm, obj->dict.numEntries); int len = 0; for(int i = 0; i <= obj->dict.capacity; ++i) { DictNode* node = obj->dict.buckets[i]; while(node) { Object* pair = PushArray(vm, 2); Object* key = NewObject(vm, OBJ_STRING); key->string.raw = estrdup(node->key); pair->array.members[0] = key; pair->array.members[1] = node->value; aobj->array.members[len++] = PopObject(vm); node = node->next; } } } break; #define BIN_OP_TYPE(op, operator, type) case OP_##op: { if(vm->debug) printf("%s\n", #op); Object* val2 = PopObject(vm); Object* val1 = PopObject(vm); PushNumber(vm, (type)val1->number operator (type)val2->number); ++vm->pc; } break; #define BIN_OP(op, operator) BIN_OP_TYPE(op, operator, double) BIN_OP(ADD, +) BIN_OP(SUB, -) BIN_OP(MUL, *) BIN_OP(DIV, /) BIN_OP_TYPE(MOD, %, int) BIN_OP_TYPE(OR, |, int) BIN_OP_TYPE(AND, &, int) BIN_OP(LT, <) BIN_OP(LTE, <=) BIN_OP(GT, >) BIN_OP(GTE, >=) BIN_OP_TYPE(LOGICAL_AND, &&, int) BIN_OP_TYPE(LOGICAL_OR, ||, int) #define CBIN_OP(op, operator) case OP_##op: { ++vm->pc; if(vm->debug) printf("%s\n", #op); Object* b = PopObject(vm); Object* a = PopObject(vm); a->number operator b->number; } break; CBIN_OP(CADD, +=) CBIN_OP(CSUB, -=) CBIN_OP(CMUL, *=) CBIN_OP(CDIV, /=) case OP_EQU: { ++vm->pc; Object* o2 = PopObject(vm); Object* o1 = PopObject(vm); if(o1->type != o2->type) PushNumber(vm, 0); else { if(o1->type == OBJ_STRING) { PushNumber(vm, strcmp(o1->string.raw, o2->string.raw) == 0); } else if(o1->type == OBJ_NUMBER) { PushNumber(vm, o1->number == o2->number); } else PushNumber(vm, o1 == o2); } } break; case OP_NEQU: { ++vm->pc; Object* o2 = PopObject(vm); Object* o1 = PopObject(vm); if(o1->type != o2->type) PushNumber(vm, 1); else { if(o1->type == OBJ_STRING) { PushNumber(vm, strcmp(o1->string.raw, o2->string.raw) != 0); } else if(o1->type == OBJ_NUMBER) { PushNumber(vm, o1->number != o2->number); } else PushNumber(vm, o1 != o2); } } break; case OP_NEG: { if(vm->debug) printf("neg\n"); ++vm->pc; Object* obj = PopObject(vm); PushNumber(vm, -obj->number); } break; case OP_LOGICAL_NOT: { if(vm->debug) printf("not\n"); ++vm->pc; Object* obj = PopObject(vm); PushNumber(vm, !obj->number); } break; case OP_SETINDEX: { ++vm->pc; Object* obj = PopObject(vm); Object* indexObj = PopObject(vm); Object* value = PopObject(vm); if(vm->debug) printf("setindex\n"); if(obj->type == OBJ_ARRAY) { if(indexObj->type != OBJ_NUMBER) { fprintf(stderr, "Attempted to index array with a %s (expected number)\n", ObjectTypeNames[indexObj->type]); exit(1); } int index = (int)indexObj->number; int arrayLength = obj->array.length; Object** members = obj->array.members; if(index >= 0 && index < arrayLength) members[index] = value; else { fprintf(stderr, "Invalid array index %i\n", index); exit(1); } } else if(obj->type == OBJ_STRING) { if(indexObj->type != OBJ_NUMBER) { fprintf(stderr, "Attempted to index string with a %s (expected number)\n", ObjectTypeNames[indexObj->type]); exit(1); } if(value->type != OBJ_NUMBER) { fprintf(stderr, "Attempted to assign a %s to an index of a string '%s' (expected number/character)\n", ObjectTypeNames[value->type], obj->string.raw); exit(1); } obj->string.raw[(int)indexObj->number] = (char)value->number; } else if(obj->type == OBJ_DICT) { if(indexObj->type != OBJ_STRING) { fprintf(stderr, "Attempted to index dict with a %s (expected string)\n", ObjectTypeNames[indexObj->type]); exit(1); } DictPut(&obj->dict, indexObj->string.raw, value); } else { fprintf(stderr, "Attempted to index a %s\n", ObjectTypeNames[obj->type]); exit(1); } } break; case OP_GETINDEX: { ++vm->pc; Object* obj = PopObject(vm); Object* indexObj = PopObject(vm); if(obj->type == OBJ_ARRAY) { if(indexObj->type != OBJ_NUMBER) { fprintf(stderr, "Attempted to index array with a %s (expected number)\n", ObjectTypeNames[indexObj->type]); exit(1); } int index = (int)indexObj->number; int arrayLength = obj->array.length; Object** members = obj->array.members; if(index >= 0 && index < arrayLength) { if(members[index]) PushObject(vm, members[index]); else { fprintf(stderr, "attempted to index non-existent value in array\n"); exit(1); } if(vm->debug) printf("getindex %i\n", index); } else { fprintf(stderr, "Invalid array index %i\n", index); exit(1); } } else if(obj->type == OBJ_STRING) { if(indexObj->type != OBJ_NUMBER) { fprintf(stderr, "Attempted to index string with a %s (expected number)\n", ObjectTypeNames[indexObj->type]); exit(1); } PushNumber(vm, obj->string.raw[(int)indexObj->number]); } else if(obj->type == OBJ_DICT) { if(indexObj->type != OBJ_STRING) { fprintf(stderr, "Attempted to index dict with a %s (expected string)\n", ObjectTypeNames[indexObj->type]); exit(1); } Object* val = (Object*)DictGet(&obj->dict, indexObj->string.raw); if(val) PushObject(vm, val); else PushObject(vm, &NullObject); } else { fprintf(stderr, "Attempted to index a %s\n", ObjectTypeNames[obj->type]); exit(1); } } break; case OP_SET: { ++vm->pc; int index = ReadInteger(vm); Object* top = PopObject(vm); vm->stack[index] = top; if(vm->debug) { if(top->type == OBJ_NUMBER) printf("set %i to %g\n", index, top->number); else if(top->type == OBJ_STRING) printf("set %i to %s\n", index, top->string); } } break; case OP_GET: { ++vm->pc; int index = ReadInteger(vm); if(vm->stack[index]) PushObject(vm, (vm->stack[index])); else PushObject(vm, &NullObject); if(vm->debug) printf("get %i\n", index); } break; case OP_WRITE: { if(vm->debug) printf("write\n"); Object* top = PopObject(vm); WriteObject(vm, top); printf("\n"); ++vm->pc; } break; case OP_READ: { if(vm->debug) printf("read\n"); char* string = ReadStringFromStdin(); PushString(vm, string); free(string); ++vm->pc; } break; case OP_GOTO: { ++vm->pc; int pc = ReadInteger(vm); vm->pc = pc; if(vm->debug) printf("goto %i\n", vm->pc); } break; case OP_GOTOZ: { ++vm->pc; int pc = ReadInteger(vm); Object* top = PopObject(vm); if(top->number == 0) { vm->pc = pc; if(vm->debug) printf("gotoz %i\n", vm->pc); } } break; case OP_CALL: { Word nargs = vm->program[++vm->pc]; ++vm->pc; int index = ReadInteger(vm); if(vm->debug) printf("call %s\n", vm->functionNames[index]); PushIndir(vm, nargs); vm->pc = vm->functionPcs[index]; } break; case OP_CALLP: { Word hasEllipsis, isExtern, numArgs; Word nargs = vm->program[++vm->pc]; ++vm->pc; int id = PopFunc(vm, &hasEllipsis, &isExtern, &numArgs); if(vm->debug) printf("callp %s%s\n", isExtern ? "extern " : "", isExtern ? vm->externNames[id] : vm->functionNames[id]); if(isExtern) vm->externs[id](vm); else { if(!hasEllipsis) { if(nargs != numArgs) { fprintf(stderr, "Function '%s' expected %i args but recieved %i args\n", vm->functionNames[id], numArgs, nargs); exit(1); } } else { if(nargs < numArgs) { fprintf(stderr, "Function '%s' expected at least %i args but recieved %i args\n", vm->functionNames[id], numArgs, nargs); exit(1); } } if(!hasEllipsis) PushIndir(vm, nargs); else { // runtime collapsing of arguments: // the concrete arguments (known during compilation) are on the top of // the stack. We create an array (by pushing it and then decrementing the // stack pointer) and fill it up with the ellipsed arguments (behind the // concrete arguments). We then place this array just before the concrete // arguments in the stack so that it can be accessed as an argument "args". // The indirection info is pushed onto the indirection stack (the concrete and // non-concrete [aside from the one that the 'args' array replaces] are still // present on the stack, so all of the arguments are to be removed) /*printf("args:\n"); for(int i = 0; i < nargs; ++i) { WriteObject(vm, vm->stack[vm->stackSize - i - 1]); printf("\n"); } printf("end\n");*/ //printf("members:\n"); Object* obj = PushArray(vm, nargs - numArgs); vm->stackSize -= 1; for(int i = 0; i < obj->array.length; ++i) { obj->array.members[i] = vm->stack[vm->stackSize - numArgs - 1 - i]; /*WriteObject(vm, obj->array.members[i]); printf("\n");*/ } //printf("end\n"); vm->stack[vm->stackSize - numArgs - 1] = obj; /*printf("final args:\n"); for(int i = 0; i < numArgs + 1; ++i) { WriteObject(vm, vm->stack[vm->stackSize - i - 1]); printf("\n"); } printf("end\n");*/ PushIndir(vm, nargs); } vm->pc = vm->functionPcs[id]; } } break; case OP_RETURN: { if(vm->debug) printf("ret\n"); PopIndir(vm); } break; case OP_RETURN_VALUE: { if(vm->debug) printf("retval\n"); Object* returnValue = PopObject(vm); PopIndir(vm); PushObject(vm, returnValue); } break; case OP_CALLF: { ++vm->pc; int index = ReadInteger(vm); if(vm->debug) printf("callf %s\n", vm->externNames[index]); vm->externs[index](vm); } break; case OP_GETLOCAL: { ++vm->pc; int index = ReadInteger(vm); PushObject(vm, GetLocal(vm, index)); if(vm->debug) printf("getlocal %i (fp: %i, stack size: %i)\n", index, vm->fp, vm->stackSize); } break; case OP_SETLOCAL: { if(vm->debug) printf("setlocal\n"); ++vm->pc; int index = ReadInteger(vm); SetLocal(vm, index, PopObject(vm)); } break; case OP_HALT: { if(vm->debug) printf("halt\n"); vm->pc = -1; } break; default: printf("Invalid instruction %i\n", vm->program[vm->pc]); break; } }
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; }
// Returns true if it was added to at least one quadtree, false if you are trying to add out of bounds static bool AddTile(TileGroup* tile_group, MemoryArena* arena, Tile* tile) { if(!Contains(tile_group, tile->aabb)) { // didn't add here, return false; return false; } if(IsLeaf(tile_group)) { if(tile_group->contained_colliders < MAX_LEAF_SIZE) { tile_group->colliders[tile_group->contained_colliders] = tile; ++tile_group->contained_colliders; } else { // Split the node into 4 Tile* temp_colliders[MAX_LEAF_SIZE]; memcpy(temp_colliders, tile_group->colliders, sizeof(temp_colliders)); tile_group->child_nodes = PushArray(arena, TileGroup, QUADTREE_CHILDREN); tile_group->is_parent = true; uint16 new_depth = tile_group->depth + 1; TileGroup* new_node = tile_group->child_nodes; Rectf r = tile_group->aabb; float half_width = r.w / 2.f; float half_height = r.h / 2.f; Rectf divided_rects[QUADTREE_CHILDREN] = { { r.x , r.y , half_width, half_height }, { r.x + half_height, r.y , half_width, half_height }, { r.x , r.y + half_height, half_width, half_height }, { r.x + half_height, r.y + half_height, half_width, half_height }, }; for(uint32 i = 0; i < QUADTREE_CHILDREN; ++i, ++new_node) { new_node->aabb = divided_rects[i]; new_node->depth = new_depth; new_node->is_parent = false; } // Add the original tile that was passed in. AddTile(tile_group, arena, tile); // re-add the old pointers to the new child nodes. for(uint32 i = 0; i < MAX_LEAF_SIZE; ++i) { AddTile(tile_group, arena, temp_colliders[i]); } } } else { // Not a leaf, recurse TileGroup* child = tile_group->child_nodes; for(uint32 j = 0; j < QUADTREE_CHILDREN; ++j, ++child) { if(Contains(child, tile->aabb)) { AddTile(child, arena, tile); } } } // Either added here or in a child return true; }