diff options
Diffstat (limited to '')
-rw-r--r-- | src/koopatlas/map.cpp | 162 |
1 files changed, 149 insertions, 13 deletions
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp index ef63eb1..d78aad4 100644 --- a/src/koopatlas/map.cpp +++ b/src/koopatlas/map.cpp @@ -3,6 +3,7 @@ //#define TILE_DEBUGGING //#define BOUND_DEBUGGING +//#define DOODAD_DEBUGGING #ifdef TILE_DEBUGGING #define TileReport OSReport @@ -16,6 +17,12 @@ inline void TileReport(const char *str, ...) { } inline void BoundReport(const char *str, ...) { } #endif +#ifdef DOODAD_DEBUGGING +#define DoodadReport OSReport +#else +inline void DoodadReport(const char *str, ...) { } +#endif + dWMMap_c *dWMMap_c::instance = 0; dWMMap_c *dWMMap_c::build() { @@ -61,29 +68,32 @@ int dWMMap_c::onDraw() { void dWMMap_c::renderer_c::drawOpa() { - //drawTiles(); + //drawLayers(); } void dWMMap_c::renderer_c::drawXlu() { - drawTiles(); + drawLayers(); } -void dWMMap_c::renderer_c::drawTiles() { - beginRendering(); - +void dWMMap_c::renderer_c::drawLayers() { dKPMapData_c *dataCls = &dScKoopatlas_c::instance->mapData; dKPMapFile_s *data = dataCls->data; baseZ = 1000 - (10 * data->layerCount); + beginRendering(); + for (int iLayer = data->layerCount - 1; iLayer >= 0; iLayer--) { dKPLayer_s *layer = data->layers[iLayer]; + renderMtx[2][3] += 10; TileReport("Checking layer %d with type %d\n", iLayer, layer->type); if (layer->type == dKPLayer_s::OBJECTS) renderTileLayer(layer, data->sectors); + else if (layer->type == dKPLayer_s::DOODADS) + renderDoodadLayer(layer); } endRendering(); @@ -104,9 +114,9 @@ void dWMMap_c::renderer_c::beginRendering() { dWorldCamera_c *camObj = dWorldCamera_c::instance; minX = ((int)camObj->screenLeft) / 16; - minY = ((int)(-camObj->screenTop)) / 16; + minY = ((int)(-camObj->screenTop) - 15) / 16; maxX = (((int)(camObj->screenLeft + camObj->screenWidth)) + 15) / 16; - maxY = (((int)(-camObj->screenTop + camObj->screenHeight)) + 15) / 16; + maxY = ((int)(-camObj->screenTop + camObj->screenHeight)) / 16; GXClearVtxDesc(); @@ -116,6 +126,9 @@ void dWMMap_c::renderer_c::beginRendering() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XY, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); + GXSetNumIndStages(0); for (int i = 0; i < 0x10; i++) GXSetTevDirect((GXTevStageID)i); @@ -154,7 +167,6 @@ void dWMMap_c::renderer_c::beginRendering() { void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector_s *sectors) { //TileReport("Rendering layer %p\n", layer); - renderMtx[2][3] += 10; // don't render it if we don't need to if (maxX < layer->left || minX > layer->right) @@ -215,21 +227,21 @@ void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector if (tileID == 0xFFFF) continue; - s16 worldX = (worldSectorX | inX) << 4; - s16 worldY = -((worldSectorY | inY) << 4); + s16 worldX = (worldSectorX | inX) * 24; + s16 worldY = -((worldSectorY | inY) * 24); u8 tileX = (tileID & 0x1F) * 8; u8 tileY = ((tileID & 0x1E0) / 32) * 16; TileReport("Drawing tile %d at %d,%d\n", tileID, worldX, worldY); GXBegin(GX_QUADS, GX_VTXFMT0, 4); - GXPosition2s16(worldX + 16, worldY - 16); + GXPosition2s16(worldX + 24, worldY - 24); GXTexCoord2u8(tileX + 7, tileY + 14); - GXPosition2s16(worldX + 16, worldY); + GXPosition2s16(worldX + 24, worldY); GXTexCoord2u8(tileX + 7, tileY + 2); GXPosition2s16(worldX, worldY); GXTexCoord2u8(tileX + 1, tileY + 2); - GXPosition2s16(worldX, worldY - 16); + GXPosition2s16(worldX, worldY - 24); GXTexCoord2u8(tileX + 1, tileY + 14);//*/ GXEnd(); } @@ -242,6 +254,126 @@ void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector //TileReport("Layer complete\n"); } +void dWMMap_c::renderer_c::renderDoodadLayer(dKPLayer_s *layer) { + for (int i = 0; i < layer->doodadCount; i++) { + dKPDoodad_s *doodad = layer->doodads[i]; + DoodadReport("Doodad @ %f,%f sized %f,%f with angle %f\n", doodad->x, doodad->y, doodad->width, doodad->height, doodad->angle); + + // ANIMATE THE FUCKER + float effectiveX = doodad->x, effectiveY = doodad->y; + float effectiveWidth = doodad->width, effectiveHeight = doodad->height; + float effectiveAngle = doodad->angle; + + if (doodad->animationCount > 0) { + for (int j = 0; j < doodad->animationCount; j++) { + dKPDoodad_s::animation_s *anim = &doodad->animations[j]; + + u32 baseTick = anim->baseTick; + if (baseTick == 0) { + anim->baseTick = baseTick = GlobalTickCount; + } + + u32 elapsed = GlobalTickCount - baseTick; + if (anim->isReversed) + elapsed = anim->frameCount - 1 - elapsed; + + if (elapsed >= anim->frameCount) { + // we've reached the end + switch (anim->loop) { + case dKPDoodad_s::animation_s::CONTIGUOUS: + // Stop here + elapsed = anim->frameCount - 1; + break; + + case dKPDoodad_s::animation_s::LOOP: + // Start over + elapsed = 0; + anim->baseTick = GlobalTickCount; + break; + + case dKPDoodad_s::animation_s::REVERSE_LOOP: + // Change direction + anim->isReversed = !anim->isReversed; + elapsed = (anim->isReversed) ? (anim->frameCount - 1) : 0; + anim->baseTick = GlobalTickCount; + break; + } + } + + // now calculate the thing + float progress = elapsed / (float)anim->frameCount; + float value; + + switch (anim->curve) { + case dKPDoodad_s::animation_s::LINEAR: + value = progress; + break; + case dKPDoodad_s::animation_s::SIN: + value = (sin(((progress * M_PI * 2)) - M_PI_2) + 1) / 2; + break; + case dKPDoodad_s::animation_s::COS: + value = (cos(((progress * M_PI * 2)) - M_PI_2) + 1) / 2; + break; + } + + float delta = anim->end - anim->start; + float frame; + + if (anim->isReversed) + frame = anim->start + ceil(delta * value); + else + frame = anim->start + (delta * value); + + // and apply it! + switch (anim->type) { + case dKPDoodad_s::animation_s::X_POS: + effectiveX += frame; + break; + case dKPDoodad_s::animation_s::Y_POS: + effectiveY += frame; + break; + case dKPDoodad_s::animation_s::ANGLE: + effectiveAngle += frame; + break; + case dKPDoodad_s::animation_s::X_SCALE: + effectiveWidth = (effectiveWidth * frame / 100.0); + break; + case dKPDoodad_s::animation_s::Y_SCALE: + effectiveHeight = (effectiveHeight * frame / 100.0); + break; + case dKPDoodad_s::animation_s::OPACITY: + // TODO + break; + } + } + } + + float halfW = effectiveWidth * 0.5f, halfH = effectiveHeight * 0.5f; + + Mtx doodadMtx; + MTXTransApply(renderMtx, doodadMtx, effectiveX + halfW, -effectiveY - halfH, 0); + + Mtx rotMtx; + MTXRotDeg(rotMtx, 'z', -effectiveAngle); + + MTXConcat(doodadMtx, rotMtx, doodadMtx); + + loadCamera(doodadMtx); + loadTexture(doodad->texObj); + + GXBegin(GX_QUADS, GX_VTXFMT1, 4); + GXPosition2f32(halfW, -halfH); + GXTexCoord2u8(255, 255); + GXPosition2f32(halfW, halfH); + GXTexCoord2u8(255, 0); + GXPosition2f32(-halfW, halfH); + GXTexCoord2u8(0, 0); + GXPosition2f32(-halfW, -halfH); + GXTexCoord2u8(0, 255); + GXEnd(); + } +} + void dWMMap_c::renderer_c::endRendering() { } @@ -257,3 +389,7 @@ void dWMMap_c::renderer_c::loadCamera() { GXLoadPosMtxImm(renderMtx, GX_PNMTX0); } +void dWMMap_c::renderer_c::loadCamera(Mtx m) { + GXLoadPosMtxImm(m, GX_PNMTX0); +} + |