diff options
| author | Treeki <treeki@gmail.com> | 2013-02-28 05:55:10 +0100 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2013-02-28 05:55:10 +0100 | 
| commit | 306549db49e602e0c6fd02a282f779e254f371c1 (patch) | |
| tree | d49a6f65806e61a388a2d3a2ac448cc0d24a1074 /src/koopatlas | |
| parent | b376ded880b4c863adfbe99ef04155d492e82c01 (diff) | |
| download | kamek-306549db49e602e0c6fd02a282f779e254f371c1.tar.gz kamek-306549db49e602e0c6fd02a282f779e254f371c1.zip | |
camera panning onto unlocked paths, among other fancy stuff and fixes
Diffstat (limited to '')
| -rw-r--r-- | src/koopatlas/camera.cpp | 116 | ||||
| -rw-r--r-- | src/koopatlas/camera.h | 11 | ||||
| -rw-r--r-- | src/koopatlas/hud.cpp | 19 | ||||
| -rw-r--r-- | src/koopatlas/hud.h | 3 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.cpp | 202 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.h | 17 | 
6 files changed, 324 insertions, 44 deletions
| diff --git a/src/koopatlas/camera.cpp b/src/koopatlas/camera.cpp index d98bff0..f80ebcc 100644 --- a/src/koopatlas/camera.cpp +++ b/src/koopatlas/camera.cpp @@ -31,7 +31,9 @@ dWorldCamera_c::dWorldCamera_c() {  	currentX = 416;  	currentY = -224; -	zoomLevel = 2.8f; +	zoomLevel = STD_ZOOM; + +	followPlayer = true;  } @@ -70,7 +72,31 @@ int dWorldCamera_c::onExecute() {  		currentX = 2040.0f;  		currentY = -1460.0f;  		zoomLevel = 3.4f; -	} else { + +	} else if (panning) { +		// Calculate where we are +#define SMOOTHSTEP(x) ((x) * (x) * (3 - 2 * (x))) +		float stepRatio = panCurrentStep / panTotalSteps; +		stepRatio = 1.0f - SMOOTHSTEP(stepRatio); +		//OSReport("PAN: Step %f / %f ---- Ratio: %f", panCurrentStep, panTotalSteps, stepRatio); +		//OSReport("From %f, %f to %f, %f --- Zoom: %f to %f\n", panFromX, panFromY, panToX, panToY, panFromZoom, panToZoom); + +		currentX = (panFromX * stepRatio) + (panToX * (1.0f - stepRatio)); +		currentY = (panFromY * stepRatio) + (panToY * (1.0f - stepRatio)); +		zoomLevel = (panFromZoom * stepRatio) + (panToZoom * (1.0f - stepRatio)); +		//OSReport("Calculated: %f, %f with zoom %f\n", currentX, currentY, zoomLevel); + +		panCurrentStep += 1.0f; + +		if (panCurrentStep > panTotalSteps) { +			// YAY, we reached the end +			panning = false; +			currentX = panToX; +			currentY = panToY; +			zoomLevel = panToZoom; +		} + +	} else if (followPlayer) {  		daWMPlayer_c *player = daWMPlayer_c::instance;  		currentX = player->pos.x;  		currentY = player->pos.y; @@ -83,6 +109,92 @@ int dWorldCamera_c::onExecute() {  	return true;  } +void dWorldCamera_c::panToBounds(float left, float top, float right, float bottom) { +	// Pad it a bit +	left -= 64.0f; +	right += 64.0f; +	top -= 48.0f; +	bottom += 48.0f; + +	//OSReport("Panning camera to bounds %f,%f to %f,%f\n", left, top, right, bottom); + +	// Figure out the centre x/y we want +	float width = right - left; +	float height = bottom - top; + +	float desiredCentreX = left + (width * 0.5f); +	float desiredCentreY = -(top + (height * 0.5f)); + +	//OSReport("Size: %f x %f ; Desired Centre: %f, %f\n", width, height, desiredCentreX, desiredCentreY); + +	// Our default zoom is 2.8 +	float minScreenWidth = GlobalScreenWidth * 1.2f; +	float minScreenHeight = GlobalScreenHeight * 1.2f; +	float maxScreenWidth = GlobalScreenWidth * 4.0f; +	float maxScreenHeight = GlobalScreenHeight * 4.0f; + +	//OSReport("Screen Sizes: Minimum possible %f x %f ; Maximum possible %f x %f\n", minScreenWidth, minScreenHeight, maxScreenWidth, maxScreenHeight); + +	// First off, gotta cap it to the ratio +	float screenRatio = GlobalScreenWidth / GlobalScreenHeight; +	float boundsRatio = width / height; +	float correctedWidth = width, correctedHeight = height; +	float desiredZoomLevel; +	//OSReport("Actual screen size is %f x %f --- Screen Ratio: %f, Bounds Ratio: %f\n", GlobalScreenWidth, GlobalScreenHeight, screenRatio, boundsRatio); + +	float widthScale = width / GlobalScreenWidth; +	float heightScale = height / GlobalScreenHeight; + +	if (heightScale > widthScale) { +		// Thing is constrained on the top/bottom +		desiredZoomLevel = heightScale; +	} else { +		// Thing is constrained on the left/right +		desiredZoomLevel = widthScale; +	} + +	//OSReport("Desired zoom level is %f\n", desiredZoomLevel); + +	// Cap the zoom +	if (desiredZoomLevel < 2.0f) +		desiredZoomLevel = 2.0f; +	if (desiredZoomLevel > 4.5f) +		desiredZoomLevel = 4.5f; +	//OSReport("After capping: %f\n", desiredZoomLevel); + +	// And we're almost there YAY +	panToPosition(desiredCentreX, desiredCentreY, desiredZoomLevel); +} + + +void dWorldCamera_c::panToPosition(float x, float y, float zoom) { +	panFromX = currentX; +	panFromY = currentY; +	panFromZoom = zoomLevel; + +	panToX = x; +	panToY = y; +	panToZoom = zoom; + +	float xDiff = abs(panToX - panFromX); +	float yDiff = abs(panToY - panFromY); + +	float panLength = sqrtf((xDiff*xDiff) + (yDiff*yDiff)); +	float panSteps = panLength / 2.3f; +	float scaleSteps = abs(panToZoom - panFromZoom) / 0.1f; +	float stepCount = max(panSteps, scaleSteps); + +	//OSReport("Pan length: %f over %f steps\n", panLength, panSteps); +	//OSReport("Scale steps: %f\n", scaleSteps); +	//OSReport("Step Count: %f\n", stepCount); + +	panCurrentStep = 0.0f; +	panTotalSteps = stepCount; + +	panning = true; +	followPlayer = false; +} +  int dWorldCamera_c::onDraw() {  	GXRenderModeObj *rmode = nw4r::g3d::G3DState::GetRenderModeObj(); diff --git a/src/koopatlas/camera.h b/src/koopatlas/camera.h index 39e34d0..836c819 100644 --- a/src/koopatlas/camera.h +++ b/src/koopatlas/camera.h @@ -3,6 +3,8 @@  #include "koopatlas/core.h" +#define STD_ZOOM 2.8f +  class dWorldCamera_c : public dBase_c {  	public:  		int onCreate(); @@ -20,7 +22,6 @@ class dWorldCamera_c : public dBase_c {  		Vec camPos, camTarget, camUp; -  		float currentX, currentY, zoomLevel;  		void calculateScreenGeometry(); @@ -28,6 +29,14 @@ class dWorldCamera_c : public dBase_c {  		float zoomDivisor, screenLeft, screenTop, screenWidth, screenHeight; +		bool followPlayer; +		void panToBounds(float left, float top, float right, float bottom); +		void panToPosition(float x, float y, float zoom=STD_ZOOM); +		bool panning; +		float panFromX, panFromY, panToX, panToY; +		float panFromZoom, panToZoom; +		float panCurrentStep; +		float panTotalSteps;  		void doStuff(float);  		void generateCameraMatrices(); diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp index ce54d8f..22928a5 100644 --- a/src/koopatlas/hud.cpp +++ b/src/koopatlas/hud.cpp @@ -110,11 +110,6 @@ int dWMHud_c::onCreate() {  		willShowFooter = false;  		loadFooterInfo(); -		SaveBlock *save = GetSaveFile()->GetBlock(-1); -		willShowFooter = (save->newerWorldName[0] != 0) && (save->hudHintH != 2000); - -		if (!dScKoopatlas_c::instance->pathManager.isMoving) -			enteredNode();  		setupLives();  	} @@ -123,6 +118,20 @@ int dWMHud_c::onCreate() {  } +void dWMHud_c::loadInitially() { +	if (doneFirstShow) +		return; + +	doneFirstShow = true; + +	SaveBlock *save = GetSaveFile()->GetBlock(-1); +	willShowFooter = (save->newerWorldName[0] != 0) && (save->hudHintH != 2000); + +	if (!dScKoopatlas_c::instance->pathManager.isMoving) +		enteredNode(); +} + +  int dWMHud_c::onDelete() {  	dWMHud_c::instance = 0; diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h index 982b38a..2fd194e 100644 --- a/src/koopatlas/hud.h +++ b/src/koopatlas/hud.h @@ -19,6 +19,9 @@ class dWMHud_c : public dBase_c {  		static dWMHud_c *build();  		static dWMHud_c *instance; +		bool doneFirstShow; +		void loadInitially(); +  		void enteredNode(dKPNode_s *node = 0);  		void leftNode(); diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 89b9f59..48590f9 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -50,12 +50,14 @@ void dWMPathManager_c::setup() {  	levelStartWait = -1;  	unlockPaths(); -	waitForAfterDeathAnim = -1; -	mustPlayAfterDeathAnim = false; +	waitAfterInitialPlayerAnim = -1;  	if (LastPowerupStoreType == LOSE_LEVEL) {  		mustPlayAfterDeathAnim = true;  		daWMPlayer_c::instance->visible = false;  		LastPowerupStoreType = BEAT_LEVEL; +	} else if (LastPowerupStoreType == BEAT_LEVEL && LastLevelPlayed[0] != 0xFF) { +		mustPlayAfterWinAnim = true; +		daWMPlayer_c::instance->visible = false;  	}  	SpammyReport("done\n"); @@ -78,7 +80,7 @@ void dWMPathManager_c::setup() {  				found = true;  				currentNode = node; -				//OSReport("Found CHANGE node: %d %p\n", changeID, node); +				SpammyReport("Found CHANGE node: %d %p\n", changeID, node);  				// figure out where we should move to  				dKPPath_s *exitTo = 0; @@ -237,6 +239,8 @@ void dWMPathManager_c::setup() {  	if (wm->isAfterKamekCutscene)  		copyWorldDefToSave(wm->mapData.findWorldDef(1)); + +	finalisePathUnlocks();  }  static u8 *PathAvailabilityData = 0; @@ -505,10 +509,13 @@ void dWMPathManager_c::unlockPaths() {  		node->setLayerAlpha((node->isUnlocked() & !node->isNew) ? 255 : 0);  	} +} +void dWMPathManager_c::finalisePathUnlocks() {  	// if anything was new, set it as such  	if (newlyAvailablePaths || newlyAvailableNodes) {  		countdownToFadeIn = 30; +		findCameraBoundsForUnlockedPaths();  	}  	unlockingAlpha = -1;  } @@ -592,7 +599,9 @@ bool dWMPathManager_c::evaluateUnlockCondition(u8 *&in, SaveBlock *save, int sta  bool dWMPathManager_c::doingThings() {  	if (isEnteringLevel || (waitAfterUnlock > 0) || (completionAnimDelay > 0) || -			(waitAtStart > 0) || (waitForAfterDeathAnim > 0) || +			(waitAtStart > 0) || (waitAfterInitialPlayerAnim > 0) || +			panningCameraToPaths || panningCameraFromPaths || +			(waitBeforePanBack > 0) ||  			(countdownToFadeIn > 0) || (unlockingAlpha != -1))  		return true; @@ -613,11 +622,52 @@ void dWMPathManager_c::execute() {  		return;  	} +	if (waitAtStart > 0) { +		waitAtStart--; +		if (waitAtStart == 0) { +			if (mustPlayAfterDeathAnim) { +				daWMPlayer_c::instance->visible = true; +				daWMPlayer_c::instance->startAnimation(ending_wait, 1.0f, 0.0f, 0.0f); +				waitAfterInitialPlayerAnim = 60; + +				nw4r::snd::SoundHandle something; +				PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_VOC_MA_CS_COURSE_MISS, 1); +			} else if (mustPlayAfterWinAnim) { +				daWMPlayer_c::instance->visible = true; +				daWMPlayer_c::instance->startAnimation(dm_surp_wait, 1.0f, 0.0f, 0.0f); +				waitAfterInitialPlayerAnim = 38; + +				nw4r::snd::SoundHandle something; +				PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_VOC_MA_CS_JUMP, 1); +			} +		} +		return; +	} + +	if (waitAfterInitialPlayerAnim > 0) { +		waitAfterInitialPlayerAnim--; +		if (waitAfterInitialPlayerAnim == 0) +			daWMPlayer_c::instance->startAnimation(wait_select, 1.0f, 0.0f, 0.0f); +		if (mustPlayAfterWinAnim && (waitAfterInitialPlayerAnim == 9)) { +			nw4r::snd::SoundHandle something; +			PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_PLY_LAND_ROCK, 1); +		} +		return; +	} + +  	// handle path fading  	if (countdownToFadeIn > 0) {  		countdownToFadeIn--;  		if (countdownToFadeIn <= 0) { -			unlockingAlpha = 0; +			if (camBoundsValid) { +				dWorldCamera_c::instance->currentX = currentNode->x; +				dWorldCamera_c::instance->currentY = -currentNode->y; +				dWorldCamera_c::instance->panToBounds(camMinX, camMinY, camMaxX, camMaxY); + +				panningCameraToPaths = true; +			} else +				unlockingAlpha = 0;  			nw4r::snd::SoundHandle something;  			PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_OBJ_GEN_LOAD, 1); @@ -626,6 +676,13 @@ void dWMPathManager_c::execute() {  		}  	} +	if (panningCameraToPaths) { +		if (dWorldCamera_c::instance->panning) +			return; +		panningCameraToPaths = false; +		unlockingAlpha = 0; +	} +  	if (unlockingAlpha != -1) {  		unlockingAlpha += 3; @@ -648,6 +705,7 @@ void dWMPathManager_c::execute() {  			unlockingAlpha = -1;  			nw4r::snd::SoundHandle something;  			PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_OBJ_GEN_NEW_COURSE, 1); +  			waitAfterUnlock = 15;  			for (int i = 0; i < pathLayer->nodeCount; i++) { @@ -667,16 +725,36 @@ void dWMPathManager_c::execute() {  	if (waitAfterUnlock > 0) {  		waitAfterUnlock--; +		if (waitAfterUnlock == 0) +			waitBeforePanBack = 20;  		return;  	} +	if (waitBeforePanBack > 0) { +		waitBeforePanBack--; +		if (waitBeforePanBack == 0 && camBoundsValid) { +			dWorldCamera_c::instance->panToPosition( +					currentNode->x, -currentNode->y, +					STD_ZOOM); +			panningCameraFromPaths = true; +		} +	} + +	if (panningCameraFromPaths) { +		if (dWorldCamera_c::instance->panning) +			return; +		panningCameraFromPaths = false; +		dWorldCamera_c::instance->followPlayer = true; +	} + +	if (dmGladDuration > 0) { +		dmGladDuration--; +		if (dmGladDuration == 0) +			daWMPlayer_c::instance->startAnimation(wait_select, 1.0f, 0.0f, 0.0f); +	} +  	if (completionAnimDelay > 0) {  		completionAnimDelay--; -		if (dmGladDuration > 0) { -			dmGladDuration--; -			if (dmGladDuration == 0) -				daWMPlayer_c::instance->startAnimation(wait_select, 1.0f, 0.0f, 0.0f); -		}  		if (completionAnimDelay == 0)  			completionMessagePending = true;  		return; @@ -710,35 +788,17 @@ void dWMPathManager_c::execute() {  		return;  	} -	if (waitAtStart > 0) { -		waitAtStart--; -		if (waitAtStart == 0) { -			if (mustPlayAfterDeathAnim) { -				daWMPlayer_c::instance->visible = true; -				daWMPlayer_c::instance->startAnimation(ending_wait, 1.0f, 0.0f, 0.0f); -				waitForAfterDeathAnim = 60; - -				nw4r::snd::SoundHandle something; -				PlaySoundWithFunctionB4(SoundRelatedClass, &something, SE_VOC_MA_CS_COURSE_MISS, 1); -			} - -			dScKoopatlas_c::instance->startMusic(); -		} -		return; -	} - -	if (waitForAfterDeathAnim > 0) { -		waitForAfterDeathAnim--; -		if (waitForAfterDeathAnim == 0) -			daWMPlayer_c::instance->startAnimation(wait_select, 1.0f, 0.0f, 0.0f); -		return; -	} -  	if (shouldRequestSave) {  		dScKoopatlas_c::instance->showSaveWindow();  		shouldRequestSave = false;  	} +	if (!initialLoading) { +		dScKoopatlas_c::instance->startMusic(); +		dWMHud_c::instance->loadInitially(); +		initialLoading = true; +	} +  	int nowPressed = Remocon_GetPressed(GetActiveRemocon());  	// Left, right, up, down @@ -1191,7 +1251,7 @@ void dWMPathManager_c::moveThroughPath(int pressedDir) {  		} else if (reallyStop) {  			// Stop here -			player->startAnimation(0, 1.2, 10.0, 0.0); +			player->startAnimation(wait_select, 1.2, 10.0, 0.0);  			player->hasEffect = false;  			player->hasSound = false; @@ -1314,3 +1374,75 @@ void dWMPathManager_c::unlockAllPaths(char type) {  } + + +void dWMPathManager_c::findCameraBoundsForUnlockedPaths() { +	dKPMapData_c *data = &dScKoopatlas_c::instance->mapData; + +	camMinX = 10000; +	camMaxX = 0; +	camMinY = 10000; +	camMaxY = 0; + +	nodeStackLength = 0; +	for (int i = 0; i < data->pathLayer->nodeCount; i++) +		data->pathLayer->nodes[i]->reserved1 = false; + +	visitNodeForCamCheck(currentNode); +	OSReport("Worked out camera bounds: %d,%d to %d,%d with validity %d\n", camMinX, camMinY, camMaxX, camMaxY, camBoundsValid); +} + +void dWMPathManager_c::visitNodeForCamCheck(dKPNode_s *node) { +	// Yay. +	nodeStackLength++; +	node->reserved1 = true; + +	for (int i = 0; i < 4; i++) { +		dKPPath_s *path = node->exits[i]; +		if (!path) +			continue; + +		OSReport("Checking path %p, whose status is %d\n", path, path->isAvailable); +		if (path->isAvailable == dKPPath_s::NEWLY_AVAILABLE) { +			addNodeToCameraBounds(path->start); +			addNodeToCameraBounds(path->end); +		} + +		// Should we follow the other node? +		dKPNode_s *otherNode = path->getOtherNodeTo(node); + +		if (otherNode->reserved1) +			continue; +		if (otherNode->type == otherNode->LEVEL) { +			OSReport("Not travelling to %p because it's level %d-%d\n", otherNode, otherNode->levelNumber[0], otherNode->levelNumber[1]); +			continue; +		} +		if (otherNode->type == otherNode->CHANGE) { +			OSReport("Not travelling to %p because it's a change\n", otherNode); +			continue; +		} +		if (otherNode->type == otherNode->WORLD_CHANGE) { +			OSReport("Not travelling to %p because it's a world change\n", otherNode); +			continue; +		} + +		visitNodeForCamCheck(otherNode); +	} + +	nodeStackLength--; +} + +void dWMPathManager_c::addNodeToCameraBounds(dKPNode_s *node) { +	camBoundsValid = true; +	OSReport("Adding node to camera bounds: %p at %d,%d\n", node, node->x, node->y); + +	if (node->x < camMinX) +		camMinX = node->x; +	if (node->x > camMaxX) +		camMaxX = node->x; +	if (node->y < camMinY) +		camMinY = node->y; +	if (node->y > camMaxY) +		camMaxY = node->y; +} + diff --git a/src/koopatlas/pathmanager.h b/src/koopatlas/pathmanager.h index 522db7f..27fcfd6 100644 --- a/src/koopatlas/pathmanager.h +++ b/src/koopatlas/pathmanager.h @@ -74,12 +74,16 @@ class dWMPathManager_c {  		int newlyAvailablePaths;  		int newlyAvailableNodes; +		bool panningCameraToPaths; +		bool panningCameraFromPaths;  		int unlockingAlpha; // -1 if not used  		int countdownToFadeIn;  		int waitAfterUnlock; +		int waitBeforePanBack;  	private:  		void unlockPaths(); +		void finalisePathUnlocks();  		bool evaluateUnlockCondition(u8 *&in, SaveBlock *save, int stack);  		int cachedTotalStarCoinCount;  		int cachedUnspentStarCoinCount; @@ -97,11 +101,22 @@ class dWMPathManager_c {  		int levelStartWait;  		int waitAtStart;  		bool mustPlayAfterDeathAnim; -		int waitForAfterDeathAnim; +		bool mustPlayAfterWinAnim; +		int waitAfterInitialPlayerAnim; +		bool initialLoading;  		bool doingThings();  		dLevelInfo_c::entry_s *enteredLevel; + + +	private: +		int camMinX, camMinY, camMaxX, camMaxY; +		int nodeStackLength; +		bool camBoundsValid; +		void visitNodeForCamCheck(dKPNode_s *node); +		void findCameraBoundsForUnlockedPaths(); +		void addNodeToCameraBounds(dKPNode_s *node);  };  #endif | 
