summaryrefslogtreecommitdiff
path: root/src/koopatlas/map.cpp
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2012-01-16 01:49:43 +0100
committerTreeki <treeki@gmail.com>2012-01-16 01:49:43 +0100
commit2bf4f9ef114e667aa8a230b169e05f1edf005107 (patch)
tree7a5af201c753c274db243a4eea2798899ccd147d /src/koopatlas/map.cpp
parent663c7538e18aaeeb460cffd7700e8caff1420f8a (diff)
downloadkamek-2bf4f9ef114e667aa8a230b169e05f1edf005107.tar.gz
kamek-2bf4f9ef114e667aa8a230b169e05f1edf005107.zip
added doodads + animation, plus bugfixes
Diffstat (limited to 'src/koopatlas/map.cpp')
-rw-r--r--src/koopatlas/map.cpp162
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);
+}
+