diff --git a/src/OpenJazz.h b/src/OpenJazz.h
index 01647ddd841e4c4fdd57eb0c373077119c6ff232..c80c4eb58307391e554432c4ecde8e171d8cbe93 100644
--- a/src/OpenJazz.h
+++ b/src/OpenJazz.h
@@ -193,7 +193,6 @@ EXTERN unsigned int globalTicks;
 
 // Trigonometric function look-up tables
 EXTERN fixed sinLut[1024];
-EXTERN fixed tanLut[1024];
 
 
 // Functions in main.cpp
@@ -216,7 +215,6 @@ EXTERN void   log                  (const char *message, int number);
 EXTERN void   logError             (const char *message, const char *detail);
 EXTERN fixed  fSin                 (fixed angle);
 EXTERN fixed  fCos                 (fixed angle);
-EXTERN fixed  fTan                 (fixed angle);
 
 #ifdef VERBOSE
 #define LOG(x, y) log(x, y)
diff --git a/src/bonus/bonus.cpp b/src/bonus/bonus.cpp
index 3e4ed3028ef58b538ab7c73239adf2b46ce78780..a0dc4bddbb1f1741a8ae496c121dc755543ef158 100644
--- a/src/bonus/bonus.cpp
+++ b/src/bonus/bonus.cpp
@@ -188,7 +188,7 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
 	File *file;
 	unsigned char *buffer;
 	char *string, *fileString;
-	int x, y;
+	int count, x, y;
 
 	try {
 
@@ -224,6 +224,36 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
 	delete[] fileString;
 
 
+	// Load animations
+
+	file->seek(134, true);
+	buffer = file->loadBlock(BANIMS << 6);
+
+	// Create animation set based on that data
+	for (count = 0; count < BANIMS; count++) {
+
+		animSet[count].setData(buffer[(count << 6) + 6],
+			buffer[count << 6], buffer[(count << 6) + 1],
+			buffer[(count << 6) + 4], buffer[(count << 6) + 5]);
+
+		for (y = 0; y < buffer[(count << 6) + 6]; y++) {
+
+			// Get frame
+			x = buffer[(count << 6) + 7 + y];
+			if (x > sprites) x = sprites;
+
+			// Assign sprite and vertical offset
+			animSet[count].setFrame(y, true);
+			animSet[count].setFrameData(spriteSet + x,
+				buffer[(count << 6) + 26 + y], buffer[(count << 6) + 45 + y]);
+
+		}
+
+	}
+
+	delete[] buffer;
+
+
 	// Load tiles
 
 	file->seek(2694, true);
@@ -437,10 +467,11 @@ int Bonus::step () {
 void Bonus::draw () {
 
 	unsigned char* row;
-	Sprite *sprite;
+	Anim* anim;
+	Sprite* sprite;
 	SDL_Rect dst;
 	fixed playerX, playerY, playerSin, playerCos;
-	fixed distance, opposite, adjacent, nX;
+	fixed distance, fwdX, fwdY, nX, sideX, sideY;
 	int levelX, levelY;
 	int x, y;
 
@@ -473,18 +504,20 @@ void Bonus::draw () {
 
 	for (y = 1; y <= (canvasH >> 1) - 15; y++) {
 
-		distance = fTan((y * 512 / ((canvasH * 3) >> 1)) + 93) * 20;
-		opposite = MUL(distance, playerSin);
-		adjacent = MUL(distance, playerCos);
+		distance = DIV(ITOF(800), ITOF(92) - (ITOF(y * 84) / ((canvasH >> 1) - 16)));
+		sideX = MUL(distance, playerCos);
+		sideY = MUL(distance, playerSin);
+		fwdX = playerX + MUL(distance - F16, playerSin) - (sideX >> 1);
+		fwdY = playerY - MUL(distance - F16, playerCos) - (sideY >> 1);
 
 		row = ((unsigned char *)(canvas->pixels)) + (canvas->pitch * (canvasH - y));
 
 		for (x = 0; x < canvasW; x++) {
 
-			nX = (ITOF(x) / canvasW) - FH;
+			nX = ITOF(x) / canvasW;
 
-			levelX = FTOI(playerX + opposite + MUL(nX, adjacent));
-			levelY = FTOI(playerY - adjacent + MUL(nX, opposite));
+			levelX = FTOI(fwdX + MUL(nX, sideX));
+			levelY = FTOI(fwdY + MUL(nX, sideY));
 
 			row[x] = ((unsigned char *)(tileSet->pixels))
 				[(grid[ITOT(levelY) & 255][ITOT(levelX) & 255].tile << 10) +
@@ -507,9 +540,9 @@ void Bonus::draw () {
 
 			fixed sX = TTOF((direction & 512)? x: -x) + F16 - (playerX & 32767);
 
-			fixed divisor = MUL(sX, playerSin) - MUL(sY, playerCos);
+			fixed divisor = F16 + MUL(sX, playerSin) - MUL(sY, playerCos);
 
-			if (FTOI(divisor) > 0) {
+			if (FTOI(divisor) > 8) {
 
 				switch (grid[((((direction - FQ) & 512)? y: -y) + FTOT(playerY)) & 255][(((direction & 512)? x: -x) + FTOT(playerX)) & 255].event) {
 
@@ -567,6 +600,12 @@ void Bonus::draw () {
 	}
 
 
+	// Show the player
+	anim = animSet + localPlayer->getAnim();
+	anim->setFrame(ticks / 75, true);
+	anim->draw(ITOF((canvasW - anim->getWidth()) >> 1), ITOF(canvasH - anim->getHeight() - 28));
+
+
 	// Show gem count
 	bonusFont->showString("*", 0, 0);
 	bonusFont->showNumber(localPlayer->getItems() / 10, 50, 0);
@@ -714,7 +753,7 @@ int Bonus::play () {
 
 		// Draw the graphics
 
-		if (ticks < returnTime) direction += (ticks - prevTicks) * T_BONUS_END / (returnTime - ticks);
+		if ((ticks < returnTime) && !paused) direction += (ticks - prevTicks) * T_BONUS_END / (returnTime - ticks);
 
 		draw();
 
diff --git a/src/bonus/bonus.h b/src/bonus/bonus.h
index 1aa8d6dffab4d64661365ac26058c67569a671a9..c85f6669a326f5e04eb94af8d939a7b922c15dc0 100644
--- a/src/bonus/bonus.h
+++ b/src/bonus/bonus.h
@@ -24,6 +24,8 @@
 #define _BONUS_H
 
 #include "baselevel.h"
+
+#include "io/gfx/anim.h"
 
 #include <SDL/SDL.h>
 
@@ -31,8 +33,9 @@
 // Constants
 
 // General
-#define BLW 256 /* Bonus level width */
-#define BLH 256 /* Bonus level height */
+#define BLW    256 /* Bonus level width */
+#define BLH    256 /* Bonus level height */
+#define BANIMS  32
 
 #define T_BONUS_END 2000
 
@@ -53,6 +56,7 @@ class Bonus : public BaseLevel {
 
 	private:
 		SDL_Surface*     background;
+		Anim             animSet[BANIMS];
 		BonusGridElement grid[BLH][BLW];
 		char             mask[60][64]; // At most 60 tiles, all with 8 * 8 masks
 		fixed            direction;
diff --git a/src/io/gfx/anim.cpp b/src/io/gfx/anim.cpp
index 3a0644e880e5e84dcecfaf3749b3c023a991a5b3..b2791d8a66398ca02ae2d6b0c94f61369fd50f8c 100644
--- a/src/io/gfx/anim.cpp
+++ b/src/io/gfx/anim.cpp
@@ -106,8 +106,8 @@ fixed Anim::getShootY () {
 
 void Anim::draw (fixed x, fixed y) {
 
-	sprites[frame]->draw(FTOI(x) + xOffsets[frame] - xOffset - FTOI(viewX),
-		FTOI(y) + yOffsets[frame] - yOffset - FTOI(viewY));
+	sprites[frame]->draw(FTOI(x) + xOffsets[frame] - xOffset,
+		FTOI(y) + yOffsets[frame] - yOffset);
 
 	return;
 
diff --git a/src/level/bullet.cpp b/src/level/bullet.cpp
index 88c9f7fbd8133f017a39bb35cc5f00edf9ba4043..e471c845ec513ea51f0c03a837cf09cf310239b4 100644
--- a/src/level/bullet.cpp
+++ b/src/level/bullet.cpp
@@ -79,7 +79,7 @@ Bullet::Bullet (Player* sourcePlayer, bool lower, unsigned int ticks) {
 
 	}
 
-	anim = source->getAnim();
+	anim = level->getAnim(source->getAnim());
 	x = source->getX() + anim->getShootX() + PXO_MID - F4;
 	y = source->getY() + anim->getShootY() - F4;
 
@@ -306,9 +306,7 @@ void Bullet::draw (int change) {
 	if (next) next->draw(change);
 
 	// Show the bullet
-	sprite->draw(
-		FTOI(getDrawX(change)) - FTOI(viewX),
-		FTOI(getDrawY(change)) - FTOI(viewY));
+	sprite->draw(FTOI(getDrawX(change)), FTOI(getDrawY(change)));
 
 	return;
 
diff --git a/src/level/event/bridge.cpp b/src/level/event/bridge.cpp
index f0c25668d49cdede71b25c106e1cc0884eac605d..832b873aef7bef55364eb2cdc5a8349da72e0e79 100644
--- a/src/level/event/bridge.cpp
+++ b/src/level/event/bridge.cpp
@@ -151,11 +151,11 @@ void Bridge::draw (unsigned int ticks, int change) {
 		for (count = 0; count < bridgeLength; count += F4 * set[E_BRIDGELENGTH]) {
 
 			if (count < leftDipX)
-				anim->draw(x + count, y + (count * leftDipY / leftDipX));
+				anim->draw(getDrawX(change) + count, getDrawY(change) + (count * leftDipY / leftDipX));
 			else if (count < dy)
-				anim->draw(x + count, y + leftDipY + ((count - leftDipX) * (rightDipY - leftDipY) / (rightDipX - leftDipX)));
+				anim->draw(getDrawX(change) + count, getDrawY(change) + leftDipY + ((count - leftDipX) * (rightDipY - leftDipY) / (rightDipX - leftDipX)));
 			else
-				anim->draw(x + count, y + ((bridgeLength - count) * rightDipY / (bridgeLength - rightDipX)));
+				anim->draw(getDrawX(change) + count, getDrawY(change) + ((bridgeLength - count) * rightDipY / (bridgeLength - rightDipX)));
 
 		}
 
@@ -172,9 +172,9 @@ void Bridge::draw (unsigned int ticks, int change) {
 		for (count = 0; count < bridgeLength; count += F4 * set[E_BRIDGELENGTH]) {
 
 			if (count < leftDipY)
-				anim->draw(x + count, y + (count * rightDipY / leftDipY));
+				anim->draw(getDrawX(change) + count, getDrawY(change) + (count * rightDipY / leftDipY));
 			else
-				anim->draw(x + count, y + ((bridgeLength - count) * rightDipY / (bridgeLength - leftDipY)));
+				anim->draw(getDrawX(change) + count, getDrawY(change) + ((bridgeLength - count) * rightDipY / (bridgeLength - leftDipY)));
 
 		}
 
diff --git a/src/level/event/eventframe.cpp b/src/level/event/eventframe.cpp
index 05ef5fae3d30dfffc1bc2b976b38bc1a8cfab543..36873c68a5a85bb20b60d259390f8c48d971eede 100644
--- a/src/level/event/eventframe.cpp
+++ b/src/level/event/eventframe.cpp
@@ -986,7 +986,7 @@ void Event::draw (unsigned int ticks, int change) {
 
 		if (ticks < flashTime) anim->flashPalette(0);
 
-		anim->draw(viewX + ITOF(viewW - 44), viewY + ITOF(count + 48));
+		anim->draw(ITOF(viewW - 44), ITOF(count + 48));
 
 		if (ticks < flashTime) anim->restorePalette();
 
diff --git a/src/level/event/guardians.cpp b/src/level/event/guardians.cpp
index 30085138b40d30d82c2470d61f09a5e430e8e5ae..1403ac4d6d398c7a54c708e93ebbf6b9080c10ef 100644
--- a/src/level/event/guardians.cpp
+++ b/src/level/event/guardians.cpp
@@ -143,7 +143,7 @@ void DeckGuardian::draw (unsigned int ticks, int change) {
 	// If the event has been removed from the grid, do not show it
 	if (!set) return;
 
-
+
 	// Draw the boss
 
 	if (stage < 3) {
@@ -154,9 +154,9 @@ void DeckGuardian::draw (unsigned int ticks, int change) {
 
 		if (ticks < flashTime) anim->flashPalette(0);
 
-		if (stage == 0) anim->draw(x - F64, y + F32);
-		else if (stage == 1) anim->draw(x + F32 - F8 - F4, y + F32);
-		else anim->draw(x + F8 - F64, y + F32);
+		if (stage == 0) anim->draw(getDrawX(change) - F64, getDrawY(change) + F32);
+		else if (stage == 1) anim->draw(getDrawX(change) + F32 - F8 - F4, getDrawY(change) + F32);
+		else anim->draw(getDrawX(change) + F8 - F64, getDrawY(change) + F32);
 
 		if (ticks < flashTime) anim->restorePalette();
 
@@ -177,7 +177,7 @@ void DeckGuardian::draw (unsigned int ticks, int change) {
 
 		if (ticks < flashTime) anim->flashPalette(0);
 
-		anim->draw(viewX + ITOF(viewW - 44), viewY + ITOF(count + 48));
+		anim->draw(ITOF(viewW - 44), ITOF(count + 48));
 
 		if (ticks < flashTime) anim->restorePalette();
 
diff --git a/src/main.cpp b/src/main.cpp
index 005256b31ff33845b04debb15ad55cbd60da50a5..1481f3707d8d3a52b85d52b68a818fe832101a26 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -54,7 +54,6 @@
 #ifdef __SYMBIAN32__
 extern char KOpenJazzPath[256];
 extern float sinf (float);
-extern float tanf (float);
 #else
 	#include <math.h>
 #endif
@@ -457,12 +456,8 @@ int loadMain (int argc, char *argv[]) {
 
 
 	// Fill trigonomatric function look-up tables
-	for (count = 0; count < 1024; count++) {
-
+	for (count = 0; count < 1024; count++)
 		sinLut[count] = fixed(sinf(2 * PI * float(count) / 1024.0f) * 1024.0f);
-		tanLut[count] = fixed(tanf(2 * PI * float(count) / 1024.0f) * 1024.0f);
-
-	}
 
 
 	// Initiate networking
diff --git a/src/movable.cpp b/src/movable.cpp
index 19e12dbec74af2523556c777f1cd64eabb97c9d5..f40b7497e891f3b9a8a406b2d780ba68d266337a 100644
--- a/src/movable.cpp
+++ b/src/movable.cpp
@@ -26,18 +26,20 @@
 
 
 #include "movable.h"
+
+#include "level/level.h"
 
 
 fixed Movable::getDrawX (int change) {
 
-	return x + ((dx * change) >> 10);
+	return x + ((dx * change) >> 10) - viewX;
 
 }
 
 
 fixed Movable::getDrawY (int change) {
 
-	return y + ((dy * change) >> 10);
+	return y + ((dy * change) >> 10) - viewY;
 
 }
 
diff --git a/src/platforms/symbian.cpp b/src/platforms/symbian.cpp
index 722f013852a2b524748cb41a7fe6f24a9348da07..4c974628c8f9ded1c2bc6f2697430070a8915e7a 100644
--- a/src/platforms/symbian.cpp
+++ b/src/platforms/symbian.cpp
@@ -17,13 +17,13 @@ class COpenJazzApp: public CSDLApp {
 public:
 	COpenJazzApp();
    	~COpenJazzApp();
-#ifdef UIQ3	
+#ifdef UIQ3
 	/**
 	 * Returns the resource id to be used to declare the views supported by this UIQ3 app
  	 * @return TInt, resource id
    	*/
 	TInt ViewResourceId();
-#endif	
+#endif
 	/**
 	 * This has a default empty implementation.
 	 * Is called just before SDL_Main is called to allow init of system vars
@@ -97,7 +97,7 @@ void COpenJazzApp::PreInitializeAppL()
 			return;
 		}
 	}
-	
+
 #ifdef UIQ3
 	ptr.Copy(_L8("c:\\shared\\openjazz\\"));
 #else
@@ -121,13 +121,6 @@ float sinf(float value)
 	return ret;
 }
 
-float tanf(float value)
-{
-	TReal ret;
-	Math::Tan(ret, value);
-	return ret;
-}
-
 /////////////////////////////////////////////////////////////////////////////////////////////////
 
 
diff --git a/src/player/player.cpp b/src/player/player.cpp
index cbff09f9dedc2dac215888d5c453ed2653726bf9..25e29ade93f20e5f0af93e37afb98ad166d479c8 100644
--- a/src/player/player.cpp
+++ b/src/player/player.cpp
@@ -78,8 +78,10 @@ void Player::init (char *playerName, unsigned char *playerCols, unsigned char ne
 	// Assign name
 	name = createString(playerName);
 
+	// Create default animation mappings
+	for (count = 0; count < PANIMS; count++) anims[count] = count & 31;
+
 	// Assign initial values
-	memset(anims, 0, PANIMS);
 	score = 0;
 	lives = 3;
 	ammoType = -1;
@@ -721,9 +723,9 @@ fixed Player::getDirection () {
 }
 
 
-Anim * Player::getAnim () {
+unsigned char Player::getAnim () {
 
-	return level->getAnim(anims[animType]);
+	return anims[animType];
 
 }
 
diff --git a/src/player/player.h b/src/player/player.h
index 6143e62c766e2117a36a769247f3c8dbf8f2f5c6..82f198bb4399661449c4fda372ffd2156df295de 100644
--- a/src/player/player.h
+++ b/src/player/player.h
@@ -37,7 +37,7 @@
 
 // Constants
 
-// Player animations
+// Level animations
 #define PA_LWALK    0
 #define PA_RWALK    1
 #define PA_LJUMP    2
@@ -76,6 +76,15 @@
 #define PA_RHALT    35
 #define PA_RSPRING  36
 #define PA_LSPRING  37 /* Surely these are the wrong way round? */
+
+// Bonus level animations
+#define PA_WALK  0
+#define PA_LEFT  1
+#define PA_RIGHT 2
+#define PA_USER  3
+#define PA_JUMP  4
+#define PA_CRASH 5
+#define PA_OTHER 6
 
 // Player reaction times
 #define PRT_HURT       1000
@@ -234,7 +243,7 @@ class Player : public Movable {
 		void            setSpeed     (fixed newDx, fixed newDy);
 		bool            getFacing    ();
 		fixed           getDirection ();
-		Anim*           getAnim      ();
+		unsigned char   getAnim      ();
 		unsigned char   getTeam      ();
 		void            send         (unsigned char* data);
 		void            receive      (unsigned char* buffer);
diff --git a/src/player/playerframe.cpp b/src/player/playerframe.cpp
index b1e69eaa7f1485da65bb8dfda9ec6f3f6022593d..e29920148c7458a0654a3ab73233fb4a7af1c180 100644
--- a/src/player/playerframe.cpp
+++ b/src/player/playerframe.cpp
@@ -634,7 +634,7 @@ void Player::bonusStep (unsigned int ticks, int msps, Bonus* bonus) {
 		if (dx < 0) dx += PRA_REVERSE * msps;
 		else if (dx < PRS_RUN) dx += PRA_RUN * msps;
 
-		facing = true;
+		animType = PA_WALK;
 
 	} else if (pcontrols[C_DOWN]) {
 
@@ -643,7 +643,7 @@ void Player::bonusStep (unsigned int ticks, int msps, Bonus* bonus) {
 		if (dx > 0) dx -= PRA_REVERSE * msps;
 		else if (dx > PRS_REVERSE) dx -= PRA_RUN * msps;
 
-		facing = false;
+		animType = PA_WALK;
 
 	} else {
 
@@ -663,11 +663,23 @@ void Player::bonusStep (unsigned int ticks, int msps, Bonus* bonus) {
 
 		}
 
+		animType = PA_OTHER;
+
 	}
 
-	if (pcontrols[C_LEFT]) direction -= msps >> 2;
+	if (pcontrols[C_LEFT]) {
+
+		direction -= msps >> 2;
+		animType = PA_LEFT;
+
+	}
 
-	if (pcontrols[C_RIGHT]) direction += msps >> 2;
+	if (pcontrols[C_RIGHT]) {
+
+		direction += msps >> 2;
+		animType = PA_RIGHT;
+
+	}
 
 
 	// Apply trajectory
@@ -751,7 +763,7 @@ void Player::draw (unsigned int ticks, int change) {
 
 	// Choose sprite
 
-	an = getAnim();
+	an = level->getAnim(getAnim());
 	an->setFrame(frame, reaction != PR_KILLED);
 
 
diff --git a/src/util.cpp b/src/util.cpp
index 8495900c192569ccaaf7df8845f4d101fe841360..eec38e6a373e1a505e30598bf2b8b62a7f47b2db 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -200,10 +200,3 @@ fixed fCos (fixed angle) {
 
 }
 
-
-fixed fTan (fixed angle) {
-
-	return tanLut[angle & 1023];
-
-}
-