Commit d804c074 authored by alistert's avatar alistert

Added support for JJ2 animations. Made player animations use pointers instead of indices.

parent 14296d13
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#define F_PANEL "PANEL.000" #define F_PANEL "PANEL.000"
#define F_SOUNDS "SOUNDS.000" #define F_SOUNDS "SOUNDS.000"
#define F_BONUS "BONUS.000" #define F_BONUS "BONUS.000"
#define F_ANIMS_J2A "ANIMS.J2A"
#define F_BONUS_0SC "BONUS.0SC" #define F_BONUS_0SC "BONUS.0SC"
#define F_END_0SC "END.0SC" #define F_END_0SC "END.0SC"
......
...@@ -46,7 +46,6 @@ BaseLevel::BaseLevel () { ...@@ -46,7 +46,6 @@ BaseLevel::BaseLevel () {
smoothfps = 50.0f; smoothfps = 50.0f;
paletteEffects = NULL; paletteEffects = NULL;
spriteSet = NULL;
paused = false; paused = false;
...@@ -66,8 +65,6 @@ BaseLevel::~BaseLevel () { ...@@ -66,8 +65,6 @@ BaseLevel::~BaseLevel () {
if (paletteEffects) delete paletteEffects; if (paletteEffects) delete paletteEffects;
if (spriteSet) delete[] spriteSet;
return; return;
} }
......
...@@ -69,7 +69,6 @@ class BaseLevel { ...@@ -69,7 +69,6 @@ class BaseLevel {
SetupMenu setupMenu; SetupMenu setupMenu;
protected: protected:
Sprite* spriteSet;
PaletteEffect* paletteEffects; PaletteEffect* paletteEffects;
SDL_Color palette[256]; SDL_Color palette[256];
int sprites; int sprites;
......
...@@ -185,6 +185,7 @@ int Bonus::loadTiles (char *fileName) { ...@@ -185,6 +185,7 @@ int Bonus::loadTiles (char *fileName) {
Bonus::Bonus (char * fileName, unsigned char diff) { Bonus::Bonus (char * fileName, unsigned char diff) {
Anim* pAnims[BPANIMS];
File *file; File *file;
unsigned char *buffer; unsigned char *buffer;
char *string, *fileString; char *string, *fileString;
...@@ -214,7 +215,16 @@ Bonus::Bonus (char * fileName, unsigned char diff) { ...@@ -214,7 +215,16 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
} }
// Load sprites // Load sprites
loadSprites(); count = loadSprites();
if (count < 0) {
delete file;
delete font;
throw count;
}
// Load tileset // Load tileset
...@@ -324,26 +334,21 @@ Bonus::Bonus (char * fileName, unsigned char diff) { ...@@ -324,26 +334,21 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
// Generate player's animation set references // Generate player's animation set references
string = new char[PANIMS]; for (count = 0; count < BPANIMS; count++) pAnims[count] = animSet + count;
for (count = 0; count < PANIMS; count++) string[count] = count & 31;
// Set the players' initial values // Set the players' initial values
if (game) { if (game) {
game->setCheckpoint(x, y); game->setCheckpoint(x, y);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_BONUS, string); for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_BONUS, pAnims);
} else { } else {
localPlayer->reset(LT_BONUS, string, x, y); localPlayer->reset(LT_BONUS, pAnims, x, y);
} }
delete[] string;
delete file; delete file;
...@@ -376,6 +381,8 @@ Bonus::~Bonus () { ...@@ -376,6 +381,8 @@ Bonus::~Bonus () {
SDL_FreeSurface(tileSet); SDL_FreeSurface(tileSet);
delete[] spriteSet;
delete font; delete font;
return; return;
...@@ -667,7 +674,7 @@ void Bonus::draw () { ...@@ -667,7 +674,7 @@ void Bonus::draw () {
// Show the player // Show the player
bonusPlayer->draw(ticks, animSet); bonusPlayer->draw(ticks);
// Show gem count // Show gem count
......
...@@ -60,6 +60,7 @@ class Bonus : public BaseLevel { ...@@ -60,6 +60,7 @@ class Bonus : public BaseLevel {
SDL_Surface* tileSet; SDL_Surface* tileSet;
SDL_Surface* background; SDL_Surface* background;
Font* font; Font* font;
Sprite* spriteSet;
Anim animSet[BANIMS]; Anim animSet[BANIMS];
BonusGridElement grid[BLH][BLW]; BonusGridElement grid[BLH][BLW];
char mask[60][64]; // At most 60 tiles, all with 8 * 8 masks char mask[60][64]; // At most 60 tiles, all with 8 * 8 masks
......
...@@ -343,10 +343,29 @@ void Game::resetPlayer (Player *player) { ...@@ -343,10 +343,29 @@ void Game::resetPlayer (Player *player) {
} }
void Game::resetPlayer (Player *player, LevelType levelType, char* anims) { void Game::resetPlayer (Player *player, LevelType levelType, Anim** anims) {
Anim* pAnims[PANIMS];
int count;
if (anims) {
player->reset(levelType, anims, checkX, checkY); player->reset(levelType, anims, checkX, checkY);
} else if (level) {
for (count = 0; count < PANIMS; count++) pAnims[count] = level->getAnim(0);
player->reset(levelType, pAnims, checkX, checkY);
} else if (jj2Level) {
pAnims[0] = jj2Level->getAnim(54, 0, false);
pAnims[1] = jj2Level->getAnim(54, 0, true);
player->reset(levelType, pAnims, checkX, checkY);
}
return; return;
} }
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
#define MTL_G_PROPS 8 #define MTL_G_PROPS 8
#define MTL_G_PJOIN 10 #define MTL_G_PJOIN 10
#define MTL_G_PQUIT 3 #define MTL_G_PQUIT 3
#define MTL_G_LEVEL 4 #define MTL_G_LEVEL 4 /* + amount of level data */
#define MTL_G_CHECK 4 #define MTL_G_CHECK 4
#define MTL_G_SCORE 3 #define MTL_G_SCORE 3
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#define MTL_L_GRID 6 #define MTL_L_GRID 6
#define MTL_L_STAGE 3 #define MTL_L_STAGE 3
#define MTL_P_ANIMS (PANIMS + 3) #define MTL_P_ANIMS 3 /* + PANIMS, BPANIMS, or 1 (for JJ2) */
#define MTL_P_TEMP 46 #define MTL_P_TEMP 46
#define BUFFER_LENGTH 255 /* Should always be big enough to hold any message */ #define BUFFER_LENGTH 255 /* Should always be big enough to hold any message */
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
// Classes // Classes
class Anim;
class File; class File;
class Game { class Game {
...@@ -104,7 +105,7 @@ class Game { ...@@ -104,7 +105,7 @@ class Game {
virtual void score (unsigned char team); virtual void score (unsigned char team);
virtual void setCheckpoint (unsigned char gridX, unsigned char gridY); virtual void setCheckpoint (unsigned char gridX, unsigned char gridY);
void resetPlayer (Player *player); void resetPlayer (Player *player);
void resetPlayer (Player *player, LevelType levelType, char* anims); void resetPlayer (Player *player, LevelType levelType, Anim** anims);
}; };
......
...@@ -28,6 +28,10 @@ ...@@ -28,6 +28,10 @@
Anim::Anim () { Anim::Anim () {
sprites = new Sprite *[19];
xOffsets = new signed char[19];
yOffsets = new signed char[19];
frame = 0; frame = 0;
yOffset = 0; yOffset = 0;
ignoreDefaultYOffset = false; ignoreDefaultYOffset = false;
...@@ -39,6 +43,10 @@ Anim::Anim () { ...@@ -39,6 +43,10 @@ Anim::Anim () {
Anim::~Anim () { Anim::~Anim () {
delete[] sprites;
delete[] xOffsets;
delete[] yOffsets;
return; return;
} }
...@@ -46,6 +54,18 @@ Anim::~Anim () { ...@@ -46,6 +54,18 @@ Anim::~Anim () {
void Anim::setData (int amount, signed char sX, signed char sY, signed char aX, signed char aY, unsigned char a, signed char y) { void Anim::setData (int amount, signed char sX, signed char sY, signed char aX, signed char aY, unsigned char a, signed char y) {
if (amount > 19) {
delete[] sprites;
delete[] xOffsets;
delete[] yOffsets;
sprites = new Sprite *[amount];
xOffsets = new signed char[amount];
yOffsets = new signed char[amount];
}
frames = amount; frames = amount;
shootX = sX; shootX = sX;
shootY = sY; shootY = sY;
......
...@@ -36,15 +36,15 @@ class Sprite; ...@@ -36,15 +36,15 @@ class Sprite;
class Anim { class Anim {
private: private:
Sprite *sprites[19]; Sprite** sprites;
signed char* xOffsets;
signed char* yOffsets;
bool ignoreDefaultYOffset; bool ignoreDefaultYOffset;
signed char shootX; signed char shootX;
signed char shootY; signed char shootY;
signed char accessoryX; signed char accessoryX;
signed char accessoryY; signed char accessoryY;
signed char yOffset; signed char yOffset;
signed char xOffsets[19];
signed char yOffsets[19];
unsigned char frames; // Number of frames unsigned char frames; // Number of frames
unsigned char frame; // Current frame unsigned char frame; // Current frame
unsigned char accessory; // Number of an animation that is an accessory to this animation unsigned char accessory; // Number of an animation that is an accessory to this animation
......
...@@ -38,8 +38,8 @@ class Sprite { ...@@ -38,8 +38,8 @@ class Sprite {
SDL_Surface* pixels; SDL_Surface* pixels;
public: public:
unsigned char xOffset; short int xOffset;
unsigned char yOffset; short int yOffset;
Sprite (); Sprite ();
~Sprite (); ~Sprite ();
......
...@@ -47,6 +47,8 @@ JJ2Event::JJ2Event (JJ2Event* newNext, unsigned char gridX, unsigned char gridY, ...@@ -47,6 +47,8 @@ JJ2Event::JJ2Event (JJ2Event* newNext, unsigned char gridX, unsigned char gridY,
hits = 0; hits = 0;
endTime = 0; endTime = 0;
facing = true;
return; return;
} }
......
...@@ -40,6 +40,7 @@ class JJ2Event : public Movable { ...@@ -40,6 +40,7 @@ class JJ2Event : public Movable {
unsigned char anim; unsigned char anim;
unsigned char frame; unsigned char frame;
unsigned int flashTime; unsigned int flashTime;
bool facing;
JJ2Event* remove (); JJ2Event* remove ();
void destroy (unsigned int ticks); void destroy (unsigned int ticks);
...@@ -51,7 +52,7 @@ class JJ2Event : public Movable { ...@@ -51,7 +52,7 @@ class JJ2Event : public Movable {
unsigned char getType (); unsigned char getType ();
JJ2Event* step (int ticks, int msps); JJ2Event* step (int ticks, int msps);
void draw (int change); void draw (unsigned int ticks, int change);
}; };
......
...@@ -97,12 +97,12 @@ JJ2Event* JJ2Event::step (int ticks, int msps) { ...@@ -97,12 +97,12 @@ JJ2Event* JJ2Event::step (int ticks, int msps) {
} }
void JJ2Event::draw (int change) { void JJ2Event::draw (unsigned int ticks, int change) {
Anim* an; Anim* an;
int drawX, drawY; int drawX, drawY;
if (next) next->draw(change); if (next) next->draw(ticks, change);
// Don't draw if too far off-screen // Don't draw if too far off-screen
if ((x < viewX - F64) || (y < viewY - F64) || if ((x < viewX - F64) || (y < viewY - F64) ||
...@@ -115,37 +115,37 @@ void JJ2Event::draw (int change) { ...@@ -115,37 +115,37 @@ void JJ2Event::draw (int change) {
case 60: // Frozen green spring case 60: // Frozen green spring
an = jj2Level->getAnim(35); an = jj2Level->getAnim(92, 5, !facing);
break; break;
case 62: // Spring crate case 62: // Spring crate
an = jj2Level->getAnim(37); an = jj2Level->getAnim(92, 0, !facing);
break; break;
case 83: // Checkpoint case 83: // Checkpoint
an = jj2Level->getAnim(49); an = jj2Level->getAnim(67, 14, !facing);
break; break;
case 85: // Red spring case 85: // Red spring
an = jj2Level->getAnim(32); an = jj2Level->getAnim(92, 7, !facing);
break; break;
case 86: // Green spring case 86: // Green spring
an = jj2Level->getAnim(35); an = jj2Level->getAnim(92, 5, !facing);
break; break;
case 87: // Blue spring case 87: // Blue spring
an = jj2Level->getAnim(37); an = jj2Level->getAnim(92, 0, !facing);
break; break;
...@@ -158,6 +158,7 @@ void JJ2Event::draw (int change) { ...@@ -158,6 +158,7 @@ void JJ2Event::draw (int change) {
} }
an->setFrame((int)ticks / 60, true);
an->draw(drawX, drawY); an->draw(drawX, drawY);
return; return;
......
...@@ -77,6 +77,15 @@ JJ2Level::~JJ2Level () { ...@@ -77,6 +77,15 @@ JJ2Level::~JJ2Level () {
delete[] musicFile; delete[] musicFile;
delete[] nextLevel; delete[] nextLevel;
for (count = 0; count < nAnimSets; count++) {
if (animSets[count]) delete[] animSets[count];
}
delete[] animSets;
delete[] spriteSet;
SDL_FreeSurface(flippedTileSet); SDL_FreeSurface(flippedTileSet);
SDL_FreeSurface(tileSet); SDL_FreeSurface(tileSet);
...@@ -196,9 +205,9 @@ Sprite* JJ2Level::getSprite (unsigned char sprite) { ...@@ -196,9 +205,9 @@ Sprite* JJ2Level::getSprite (unsigned char sprite) {
} }
Anim* JJ2Level::getAnim (unsigned char anim) { Anim* JJ2Level::getAnim (int set, int anim, bool flipped) {
return animSet + anim; return (flipped? flippedAnimSets: animSets)[set] + anim;
} }
......
...@@ -105,19 +105,22 @@ class JJ2Level : public BaseLevel { ...@@ -105,19 +105,22 @@ class JJ2Level : public BaseLevel {
char* flippedMask; char* flippedMask;
char* musicFile; char* musicFile;
char* nextLevel; char* nextLevel;
Anim animSet[128]; Sprite* spriteSet;
int soundMap[32]; Sprite* flippedSpriteSet;
Anim** animSets;
Anim** flippedAnimSets;
JJ2Layer* layers[LAYERS]; JJ2Layer* layers[LAYERS];
JJ2Layer* layer; JJ2Layer* layer;
JJ2Modifier** mods; JJ2Modifier** mods;
int nAnimSets;
bool TSF; bool TSF;
unsigned char difficulty; unsigned char difficulty;
fixed waterLevel; fixed waterLevel;
fixed waterLevelTarget; fixed waterLevelTarget;
fixed waterLevelSpeed; fixed waterLevelSpeed;
void loadSprite (File* file, Sprite* sprite); void loadSprite (unsigned char* parameters, unsigned char* compressedPixels, Sprite* sprite, Sprite* flippedSprite);
int loadSprites (char* fileName); int loadSprites ();
int loadTiles (char* fileName); int loadTiles (char* fileName);
int load (char* fileName, unsigned char diff, bool checkpoint); int load (char* fileName, unsigned char diff, bool checkpoint);
...@@ -130,7 +133,7 @@ class JJ2Level : public BaseLevel { ...@@ -130,7 +133,7 @@ class JJ2Level : public BaseLevel {
bool checkMaskDown (fixed x, fixed y, bool drop); bool checkMaskDown (fixed x, fixed y, bool drop);
bool checkMaskUp (fixed x, fixed y); bool checkMaskUp (fixed x, fixed y);
Anim* getAnim (unsigned char anim); Anim* getAnim (int set, int anim, bool flipped);
JJ2Modifier* getModifier (unsigned char gridX, unsigned char gridY); JJ2Modifier* getModifier (unsigned char gridX, unsigned char gridY);
Sprite* getSprite (unsigned char sprite); Sprite* getSprite (unsigned char sprite);
fixed getWaterLevel (); fixed getWaterLevel ();
......
...@@ -122,7 +122,7 @@ void JJ2Level::draw () { ...@@ -122,7 +122,7 @@ void JJ2Level::draw () {
// Show the events // Show the events
if (events) events->draw(change); if (events) events->draw(ticks, change);
// Show the players // Show the players
......
...@@ -46,76 +46,112 @@ ...@@ -46,76 +46,112 @@
#define SKEY 254 /* Sprite colour key */ #define SKEY 254 /* Sprite colour key */
void JJ2Level::loadSprite (File* file, Sprite* sprite) { void JJ2Level::loadSprite (unsigned char* parameters, unsigned char* compressedPixels, Sprite* sprite, Sprite* flippedSprite) {
// TODO: Load sprites from JJ2 files
unsigned char* pixels; unsigned char* pixels;
int pos, maskOffset;
int width, height; int width, height;
int srcPos, dstPos, rle;
int x, y;
// Load dimensions // Load dimensions
width = file->loadShort() << 2; width = createShort(parameters);
height = file->loadShort(); height = createShort(parameters + 2);
if ((width == 0) || (height == 0)) {
file->seek(2, false); sprite->clearPixels();
maskOffset = file->loadShort(); return;
pos = file->loadShort() << 2; }
// Sprites can be either masked or not masked.
if (maskOffset) {
// Masked // Decompress pixels
height++; pixels = new unsigned char[width * height];
memset(pixels, 0, width * height);
// Skip to mask srcPos = createInt(parameters + 16);
file->seek(maskOffset, false); dstPos = 0;
// Find the end of the data while (dstPos < width * height) {
pos += file->tell() + ((width >> 2) * height);
// Read scrambled, masked pixel data rle = compressedPixels[srcPos];
pixels = file->loadPixels(width * height, SKEY); srcPos++;
sprite->setPixels(pixels, width, height, SKEY);
delete[] pixels; if (rle > 128) {
file->seek(pos, true); rle &= 127;
} else if (width) { if (dstPos + rle < width * height)
memcpy(pixels + dstPos, compressedPixels + srcPos, rle);
// Not masked srcPos += rle;
dstPos += rle;
// Read scrambled pixel data } else if (rle == 128) {
pixels = file->loadPixels(width * height);
sprite->setPixels(pixels, width, height, SKEY);
delete[] pixels; rle = dstPos % width;
if (rle) dstPos = dstPos + width - rle;
} else {
dstPos += rle;
}
}
// Set sprite data
sprite->xOffset = createShort(parameters + 8);
sprite->yOffset = createShort(parameters + 10);
sprite->setPixels(pixels, width, height, 0);
// Flip sprite
for (y = 0; y < height; y++) {
for (x = 0; x < (width >> 1); x++) {
rle = pixels[(y * width) + x];
pixels[(y * width) + x] = pixels[(y * width) + (width - 1) - x];
pixels[(y * width) + (width - 1) - x] = rle;
}
} }
// Set flipped sprite data
flippedSprite->xOffset = -createShort(parameters + 8) - width;
flippedSprite->yOffset = createShort(parameters + 10);
flippedSprite->setPixels(pixels, width, height, 0);
delete[] pixels;
return; return;
} }
int JJ2Level::loadSprites (char * fileName) { int JJ2Level::loadSprites () {
// TODO: Load sprites from JJ2 files File* file;
unsigned char* aBuffer;
unsigned char* bBuffer;
unsigned char* cBuffer;
int* setOffsets;
int aCLength, bCLength, cCLength, dCLength;
int aLength, bLength, cLength, dLength;
int setAnims, sprites, animSprites;
int set, anim, sprite, setSprite;
File* mainFile = NULL; // Thanks to Neobeo for working out the .j2a format
File* specFile = NULL;
int count;
// Open fileName
try { try {
specFile = new File(fileName, false); file = new File(F_ANIMS_J2A, false);
} catch (int e) { } catch (int e) {
...@@ -123,104 +159,109 @@ int JJ2Level::loadSprites (char * fileName) { ...@@ -123,104 +159,109 @@ int JJ2Level::loadSprites (char * fileName) {
} }
file->seek(24, true);
// This function loads all the sprites, not fust those in fileName nAnimSets = file->loadInt();
try {
mainFile = new File(F_MAINCHAR, false); setOffsets = new int[nAnimSets];
} catch (int e) { for (set = 0; set < nAnimSets; set++) setOffsets[set] = file->loadInt();
delete specFile;
return e; // Count number of sprites
} sprites = 0;
for (set = 0; set < nAnimSets; set++) {
sprites = specFile->loadShort(); file->seek(setOffsets[set] + 6, true);
// Include space in the sprite set for the blank sprite at the end sprites += file->loadShort();
spriteSet = new Sprite[sprites + 1];
// Read horizontal offsets }
for (count = 0; count < sprites; count++)
spriteSet[count].xOffset = specFile->loadChar() << 2;
// Read vertical offsets spriteSet = new Sprite[sprites];
for (count = 0; count < sprites; count++) flippedSpriteSet = new Sprite[sprites];
spriteSet[count].yOffset = specFile->loadChar(); animSets = new Anim *[nAnimSets];
flippedAnimSets = new Anim *[nAnimSets];
// Skip to where the sprites start in mainchar.000 // Load animations and sprites
mainFile->seek(2, true);
sprites = 0;
// Loop through all the sprites to be loaded for (set = 0; set < nAnimSets; set++) {
for (count = 0; count < sprites; count++) {
if (specFile->loadChar() == 0xFF) { file->seek(setOffsets[set] + 4, true);
// Go to the next sprite/file indicator setAnims = file->loadChar();
specFile->seek(1, false);
if (mainFile->loadChar() == 0xFF) { if (setAnims) {
// Go to the next sprite/file indicator animSets[set] = new Anim[setAnims];
mainFile->seek(1, false); flippedAnimSets[set] = new Anim[setAnims];
/* Both fileName and mainchar.000 have file indicators, so } else {
create a blank sprite */
spriteSet[count].clearPixels();
continue; animSets[set] = NULL;
flippedAnimSets[set] = NULL;
} else { }
// Return to the start of the sprite file->seek(7, false);
mainFile->seek(-1, false);
// Load the individual sprite data aCLength = file->loadInt();
loadSprite(mainFile, spriteSet + count); aLength = file->loadInt();
bCLength = file->loadInt();
bLength = file->loadInt();
cCLength = file->loadInt();
cLength = file->loadInt();
dCLength = file->loadInt();
dLength = file->loadInt();
} aBuffer = file->loadLZ(aCLength, aLength);
bBuffer = file->loadLZ(bCLength, bLength);
cBuffer = file->loadLZ(cCLength, cLength);
} else { setSprite = 0;
// Return to the start of the sprite for (anim = 0; anim < setAnims; anim++) {
specFile->seek(-1, false);
// Go to the main file's next sprite/file indicator animSprites = createShort(aBuffer + (anim * 8));
mainFile->seek(2, false);
// Load the individual sprite data // Fonts are loaded separately
loadSprite(specFile, spriteSet + count); if (animSprites == 224) animSprites = 1;
} animSets[set][anim].setData(animSprites, 0, 0, 0, 0, 0, 0);
flippedAnimSets[set][anim].setData(animSprites, 0, 0, 0, 0, 0, 0);
for (sprite = 0; sprite < animSprites; sprite++) {
// Check if the next sprite exists loadSprite(bBuffer + (setSprite * 24), cBuffer, spriteSet + sprites, flippedSpriteSet + sprites);
// If not, create blank sprites for the remainder
if (specFile->tell() >= specFile->getSize()) {
for (count++; count < sprites; count++) { animSets[set][anim].setFrame(sprite, false);
animSets[set][anim].setFrameData(spriteSet + sprites, 0, 0);
flippedAnimSets[set][anim].setFrame(sprite, false);
flippedAnimSets[set][anim].setFrameData(flippedSpriteSet + sprites, 0, 0);
spriteSet[count].clearPixels(); setSprite++;
sprites++;
} }
} }
delete[] cBuffer;
delete[] bBuffer;
delete[] aBuffer;
} }
delete mainFile;
delete specFile;
delete[] setOffsets;
delete file;
// Include a blank sprite at the end
spriteSet[sprites].clearPixels();
spriteSet[sprites].xOffset = 0;
spriteSet[sprites].yOffset = 0;
return E_NONE; return E_NONE;
...@@ -306,7 +347,7 @@ int JJ2Level::loadTiles (char* fileName) { ...@@ -306,7 +347,7 @@ int JJ2Level::loadTiles (char* fileName) {
SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, 0); SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, 0);
// Flip tiles // Flip tiles
for (count = 0; count < tiles * 32; count++) { for (count = 0; count < TTOI(tiles); count++) {
for (x = 0; x < 16; x++) { for (x = 0; x < 16; x++) {
...@@ -394,8 +435,8 @@ int JJ2Level::loadTiles (char* fileName) { ...@@ -394,8 +435,8 @@ int JJ2Level::loadTiles (char* fileName) {
int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) { int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
Anim* pAnims[2];
File *file; File *file;
unsigned char *buffer;
char *string; char *string;
unsigned char* aBuffer; unsigned char* aBuffer;
unsigned char* bBuffer; unsigned char* bBuffer;
...@@ -408,7 +449,6 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -408,7 +449,6 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
unsigned char tileQuad[8]; unsigned char tileQuad[8];
short int* quadRefs; short int* quadRefs;
int flags, width, pitch, height; int flags, width, pitch, height;
int worldNum;
unsigned char startX, startY; unsigned char startX, startY;
// Thanks to Neobeo for working out the most of the .j2l format // Thanks to Neobeo for working out the most of the .j2l format
...@@ -614,68 +654,9 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -614,68 +654,9 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
delete[] aBuffer; delete[] aBuffer;
// Load anims from anims.j2a
// Open JJ1 level file for remaining data if (loadSprites() < 0) {
// Use first level
worldNum = 0;
string = createFileName(F_LEVEL, 0, worldNum);
try {
file = new File(string, false);
} catch (int e) {
// Failed to load first level, so try loading first Christmas level
worldNum = 50;
string[8] = '5';
try {
file = new File(string, false);
} catch (int e) {
delete[] string;
if (events) delete events;
delete[] *mods;
delete[] mods;
for (count = 0; count < LAYERS; count++) delete layers[count];
delete[] flippedMask;
delete[] mask;
delete[] musicFile;
delete[] nextLevel;
SDL_FreeSurface(flippedTileSet);
SDL_FreeSurface(tileSet);
delete font;
return e;
}
}
delete[] string;
// Load sprite set from corresponding Sprites.###
string = createFileName(F_SPRITES, worldNum);
count = loadSprites(string);
delete[] string;
if (count < 0) {
delete file; delete file;
...@@ -701,155 +682,49 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -701,155 +682,49 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
} }
// Skip to tile and event reference data // Set initial water level
file->seek(39, true); waterLevelTarget = TTOF(layer->getHeight() + 1);
// Skip tile references
file->skipRLE();
// A mysterious block of mystery
file->skipRLE();
// Skip mask data
file->skipRLE();
// Skip special event path
file->skipRLE();
// Skip event set
file->skipRLE();
// Yet more doubtless essential data
file->skipRLE();
// Load animation set
buffer = file->loadRLE(128 << 6);
// Create animation set based on that data
for (count = 0; count < 128; count++) {
animSet[count].setData(buffer[(count << 6) + 6],
buffer[count << 6], buffer[(count << 6) + 1],
buffer[(count << 6) + 3], buffer[(count << 6) + 4],
buffer[(count << 6) + 2], 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;
// At general data
// There's a a whole load of unknown data around here
// Like another one of those pesky RLE blocks
file->skipRLE();
// And 217 bytes of DOOM
file->seek(217, false);
// Load sound map
x = file->tell();
for (count = 0; count < 32; count++) {
file->seek(x + (count * 9), true);
string = file->loadString();
soundMap[count] = -1;
// Search for matching sound
for (y = 0; (y < nSounds) && (soundMap[count] == -1); y++) {
if (!strcmp(string, sounds[y].name)) soundMap[count] = y;
}
delete[] string;
}
// Skip file names
file->seek(x + 366, true);
// Skip the players' initial coordinates
file->seek(4, false);
// Skip next level numbers
file->seek(2, false);
// Thanks to Doubble Dutch for the water level bytes
file->seek(4, false);
waterLevelTarget = ITOF(file->loadShort());
waterLevel = waterLevelTarget - F8; waterLevel = waterLevelTarget - F8;
waterLevelSpeed = 0; waterLevelSpeed = 0;
// Thanks to Feline and the JCS94 team for the next bits: // Generate player's animation set references
file->seek(3, false);
// Now at "Section 15"
// Load player's animation set references
buffer = file->loadRLE(PANIMS * 2);
string = new char[PANIMS + 3];
for (x = 0; x < PANIMS; x++) string[x + 3] = buffer[x << 1];
delete[] buffer;
if (gameMode) { if (gameMode) {
string[0] = MTL_P_ANIMS; string = new char[MTL_P_ANIMS + 1];
string[0] = MTL_P_ANIMS + 1;
string[1] = MT_P_ANIMS; string[1] = MT_P_ANIMS;
string[2] = 0; string[2] = 0;
string[3] = 54;
game->send((unsigned char *)string); game->send((unsigned char *)string);
delete[] string;
} }
// Set the players' initial values // Set the players' initial values
pAnims[0] = animSets[54];
pAnims[1] = flippedAnimSets[54];
if (game) { if (game) {
if (!checkpoint) game->setCheckpoint(startX, startY); if (!checkpoint) game->setCheckpoint(startX, startY);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_JJ2LEVEL, string + 3); for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_JJ2LEVEL, pAnims);
} else { } else {
localPlayer->reset(LT_JJ2LEVEL, string + 3, startX, startY); localPlayer->reset(LT_JJ2LEVEL, pAnims, startX, startY);
} }
delete[] string;
// And that's us done! // And that's us done!
delete file;
// Set the tick at which the level will end, though this is not used // Set the tick at which the level will end, though this is not used
endTime = (5 - difficulty) * 2 * 60 * 1000; endTime = (5 - difficulty) * 2 * 60 * 1000;
......
...@@ -79,7 +79,7 @@ Bullet::Bullet (LevelPlayer* sourcePlayer, bool lower, unsigned int ticks) { ...@@ -79,7 +79,7 @@ Bullet::Bullet (LevelPlayer* sourcePlayer, bool lower, unsigned int ticks) {
} }
anim = level->getAnim(source->getAnim()); anim = source->getAnim();
x = source->getX() + anim->getShootX() + PXO_MID - F4; x = source->getX() + anim->getShootX() + PXO_MID - F4;
y = source->getY() + anim->getShootY() - F4; y = source->getY() + anim->getShootY() - F4;
......
...@@ -116,6 +116,8 @@ Level::~Level () { ...@@ -116,6 +116,8 @@ Level::~Level () {
delete[] sceneFile; delete[] sceneFile;
delete[] musicFile; delete[] musicFile;
delete[] spriteSet;
SDL_FreeSurface(tileSet); SDL_FreeSurface(tileSet);
deletePanel(); deletePanel();
......
...@@ -100,6 +100,7 @@ class Level : public BaseLevel { ...@@ -100,6 +100,7 @@ class Level : public BaseLevel {
Event* events; Event* events;
char* musicFile; char* musicFile;
char* sceneFile; char* sceneFile;
Sprite* spriteSet;
Anim animSet[ANIMS]; Anim animSet[ANIMS];
char miscAnims[4]; char miscAnims[4];
signed char bulletSet[BULLETS][BLENGTH]; signed char bulletSet[BULLETS][BLENGTH];
......
...@@ -408,12 +408,13 @@ int Level::loadTiles (char* fileName) { ...@@ -408,12 +408,13 @@ int Level::loadTiles (char* fileName) {
} }
int Level::load (char *fileName, unsigned char diff, bool checkpoint) { int Level::load (char* fileName, unsigned char diff, bool checkpoint) {
File *file; Anim* pAnims[PANIMS];
unsigned char *buffer; File* file;
const char *ext; unsigned char* buffer;
char *string; const char* ext;
char* string;
int tiles; int tiles;
int count, x, y, type; int count, x, y, type;
unsigned char startX, startY; unsigned char startX, startY;
...@@ -874,36 +875,41 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -874,36 +875,41 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
// Load player's animation set references // Load player's animation set references
buffer = file->loadRLE(PANIMS * 2); buffer = file->loadRLE(PANIMS * 2);
string = new char[PANIMS + 3]; string = new char[MTL_P_ANIMS + PANIMS];
for (x = 0; x < PANIMS; x++) {
for (x = 0; x < PANIMS; x++) string[x + 3] = buffer[x << 1]; pAnims[x] = animSet + buffer[x << 1];
string[MTL_P_ANIMS + x] = buffer[x << 1];
}
delete[] buffer; delete[] buffer;
if (gameMode) { if (gameMode) {
string[0] = MTL_P_ANIMS; string[0] = MTL_P_ANIMS + PANIMS;
string[1] = MT_P_ANIMS; string[1] = MT_P_ANIMS;
string[2] = 0; string[2] = 0;
game->send((unsigned char *)string); game->send((unsigned char *)string);
} }
delete[] string;
// Set the players' initial values // Set the players' initial values
if (game) { if (game) {
if (!checkpoint) game->setCheckpoint(startX, startY); if (!checkpoint) game->setCheckpoint(startX, startY);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_LEVEL, string + 3); for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_LEVEL, pAnims);
} else { } else {
localPlayer->reset(LT_LEVEL, string + 3, startX, startY); localPlayer->reset(LT_LEVEL, pAnims, startX, startY);
} }
delete[] string;
// Load miscellaneous animations // Load miscellaneous animations
miscAnims[0] = file->loadChar(); miscAnims[0] = file->loadChar();
......
...@@ -37,14 +37,14 @@ ...@@ -37,14 +37,14 @@
#include <string.h> #include <string.h>
BonusPlayer::BonusPlayer (Player* parent, char *newAnims, unsigned char startX, unsigned char startY) { BonusPlayer::BonusPlayer (Player* parent, Anim **newAnims, unsigned char startX, unsigned char startY) {
int count; int count;
player = parent; player = parent;
memcpy(anims, newAnims, PANIMS); memcpy(anims, newAnims, BPANIMS * sizeof(Anim*));
x = TTOF(startX) + F16; x = TTOF(startX) + F16;
y = TTOF(startY) + F16; y = TTOF(startY) + F16;
...@@ -184,11 +184,11 @@ void BonusPlayer::step (unsigned int ticks, int msps, Bonus* bonus) { ...@@ -184,11 +184,11 @@ void BonusPlayer::step (unsigned int ticks, int msps, Bonus* bonus) {
} }
void BonusPlayer::draw (unsigned int ticks, Anim* animSet) { void BonusPlayer::draw (unsigned int ticks) {
Anim* anim; Anim* anim;
anim = animSet + anims[animType]; anim = anims[animType];
anim->disableDefaultOffset(); anim->disableDefaultOffset();
anim->setFrame(ticks / 75, true); anim->setFrame(ticks / 75, true);
if (canvasW <= SW) anim->draw(ITOF((canvasW - anim->getWidth()) >> 1), ITOF(canvasH - anim->getHeight() - 28)); if (canvasW <= SW) anim->draw(ITOF((canvasW - anim->getWidth()) >> 1), ITOF(canvasH - anim->getHeight() - 28));
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#define PA_CRASH 5 #define PA_CRASH 5
#define PA_OTHER 6 #define PA_OTHER 6
#define BPANIMS 7
// Player speeds // Player speeds
#define PRS_REVERSE ITOF(-32) #define PRS_REVERSE ITOF(-32)
#define PRS_RUN ITOF(64) #define PRS_RUN ITOF(64)
...@@ -61,7 +63,7 @@ class BonusPlayer { ...@@ -61,7 +63,7 @@ class BonusPlayer {
private: private:
SDL_Color palette[256]; SDL_Color palette[256];
char anims[PANIMS]; Anim* anims[BPANIMS];
fixed x, y, direction, dr; fixed x, y, direction, dr;
unsigned char animType; unsigned char animType;
int gems; int gems;
...@@ -69,7 +71,7 @@ class BonusPlayer { ...@@ -69,7 +71,7 @@ class BonusPlayer {
public: public:
Player* player; Player* player;
BonusPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY); BonusPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY);
~BonusPlayer (); ~BonusPlayer ();
void addGem (); void addGem ();
...@@ -79,7 +81,7 @@ class BonusPlayer { ...@@ -79,7 +81,7 @@ class BonusPlayer {
fixed getY (); fixed getY ();
void step (unsigned int ticks, int msps, Bonus* bonus); void step (unsigned int ticks, int msps, Bonus* bonus);
void draw (unsigned int ticks, Anim* animSet); void draw (unsigned int ticks);
}; };
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <string.h> #include <string.h>
JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird) { JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, bool hasBird) {
int offsets[14] = {JJ2PCO_GREY, JJ2PCO_SGREEN, JJ2PCO_BLUE, JJ2PCO_RED, int offsets[14] = {JJ2PCO_GREY, JJ2PCO_SGREEN, JJ2PCO_BLUE, JJ2PCO_RED,
JJ2PCO_LGREEN, JJ2PCO_LEVEL1, JJ2PCO_YELLOW, JJ2PCO_LEVEL2, JJ2PCO_LGREEN, JJ2PCO_LEVEL1, JJ2PCO_YELLOW, JJ2PCO_LEVEL2,
...@@ -52,8 +52,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st ...@@ -52,8 +52,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st
player = parent; player = parent;
if (newAnims) memcpy(anims, newAnims, PANIMS); anims = newAnims[0];
else memset(anims, 0, PANIMS); flippedAnims = newAnims[1];
bird = hasBird; bird = hasBird;
...@@ -74,8 +74,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st ...@@ -74,8 +74,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st
length = lengths[player->cols[0]]; length = lengths[player->cols[0]];
for (count = 0; count < 16; count++) for (count = 0; count < 16; count++)
palette[count + 48].r = palette[count + 48].g = palette[count + 48].b = palette[count + 16].r = palette[count + 16].g = palette[count + 16].b =
(count * length / 16) + start; (count * length / 8) + start;
// Bandana colours // Bandana colours
...@@ -84,8 +84,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st ...@@ -84,8 +84,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st
length = lengths[player->cols[1]]; length = lengths[player->cols[1]];
for (count = 0; count < 16; count++) for (count = 0; count < 16; count++)
palette[count + 32].r = palette[count + 32].g = palette[count + 32].b = palette[count + 24].r = palette[count + 24].g = palette[count + 24].b =
(count * length / 16) + start; (count * length / 8) + start;
// Gun colours // Gun colours
...@@ -94,8 +94,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st ...@@ -94,8 +94,8 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st
length = lengths[player->cols[2]]; length = lengths[player->cols[2]];
for (count = 0; count < 9; count++) for (count = 0; count < 9; count++)
palette[count + 23].r = palette[count + 23].g = palette[count + 23].b = palette[count + 32].r = palette[count + 32].g = palette[count + 32].b =
(count * length / 9) + start; (count * length / 8) + start;
// Wristband colours // Wristband colours
...@@ -104,16 +104,10 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st ...@@ -104,16 +104,10 @@ JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char st
length = lengths[player->cols[3]]; length = lengths[player->cols[3]];
for (count = 0; count < 8; count++) for (count = 0; count < 8; count++)
palette[count + 88].r = palette[count + 88].g = palette[count + 88].b = palette[count + 40].r = palette[count + 40].g = palette[count + 40].b =
(count * length / 8) + start; (count * length / 8) + start;
// Fix creepy black eyes
for (count = 0; count < 16; count++)
palette[count].r = palette[count].g = palette[count].b = (count >> 1) + 64;
return; return;
} }
...@@ -132,7 +126,7 @@ void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) { ...@@ -132,7 +126,7 @@ void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) {
energy = 5; energy = 5;
floating = false; floating = false;
facing = true; facing = true;
animType = PA_RSTAND; animType = PA_STAND;
event = LPE_NONE; event = LPE_NONE;
reaction = JJ2PR_NONE; reaction = JJ2PR_NONE;
reactionTime = 0; reactionTime = 0;
...@@ -179,9 +173,9 @@ void JJ2LevelPlayer::centreY () { ...@@ -179,9 +173,9 @@ void JJ2LevelPlayer::centreY () {
} }
unsigned char JJ2LevelPlayer::getAnim () { Anim* JJ2LevelPlayer::getAnim () {
return anims[animType]; return (facing? anims: flippedAnims) + animType;
} }
...@@ -600,7 +594,8 @@ void JJ2LevelPlayer::receive (unsigned char *buffer) { ...@@ -600,7 +594,8 @@ void JJ2LevelPlayer::receive (unsigned char *buffer) {
case MT_P_ANIMS: case MT_P_ANIMS:
memcpy(anims, (char *)buffer + 3, PANIMS); anims = jj2Level->getAnim(buffer[3], 0, false);
flippedAnims = jj2Level->getAnim(buffer[3], 0, true);
break; break;
......
...@@ -73,44 +73,112 @@ ...@@ -73,44 +73,112 @@
#define JJ2PCL_LEVEL5 16 #define JJ2PCL_LEVEL5 16
// Animations // Animations
#define PA_LWALK 0 #define PA_WOOZYSHAKE 0
#define PA_RWALK 1 #define PA_BOARD 1
#define PA_LJUMP 2 #define PA_BOARDSW 2
#define PA_RJUMP 3 #define PA_STOMP 3
#define PA_LSPIN 4 #define PA_DEAD 4
#define PA_RSPIN 5 #define PA_DIE 5
#define PA_LSHOOT 6 #define PA_CROUCH1 6
#define PA_RSHOOT 7 #define PA_CROUCHED 7
#define PA_LCROUCH 8 #define PA_CROUCHSHOOT 8
#define PA_RCROUCH 9 #define PA_CROUCH2 9
#define PA_LFALL 10 #define PA_EXIT1 10
#define PA_RFALL 11 #define PA_VINE 11
#define PA_LHURT 12 #define PA_EXIT2 12
#define PA_RHURT 13 #define PA_FALL 13
#define PA_LLEAN 14 #define PA_STOMPING 14
#define PA_RLEAN 15 #define PA_LAND 15
#define PA_LBOARD 16 #define PA_STANDSHOOT 16
#define PA_RBOARD 17 #define PA_STANDSHOOTUP 17
#define PA_LSTAND 18 #define PA_WHIP1 18
#define PA_RSTAND 19 #define PA_UNFROG 19
#define PA_LEAT 20 #define PA_MOUNT 20
#define PA_REAT 21 #define PA_HOOKWHIP 21
#define PA_LEDGE 22 #define PA_HOOKDIAG 22
#define PA_REDGE 23 #define PA_HOOKSHOOTUP 23
#define PA_LOOKUP 24 #define PA_HOOK1 24
#define PA_LOOKDOWN 25 #define PA_HOOK2 25
#define PA_LSWIM 26 #define PA_HOOKWHIPUP 26
#define PA_RSWIM 27 #define PA_HOOKSHOOT 27
#define PA_LRUN 28 #define PA_HELI 28
#define PA_RRUN 29 #define PA_HELIWHIP 29
#define PA_LDIE 30 #define PA_HELISHOOT 30
#define PA_RDIE 31 #define PA_HPOLE 31
#define PA_LSTOP 32 #define PA_HURT1 32
#define PA_RSTOP 33 #define PA_WAIT1 33
#define PA_LHALT 34 /* Yeah, I was wondering the same thing... */ #define PA_WAIT2 34
#define PA_RHALT 35 #define PA_WAIT3 35
#define PA_RSPRING 36 #define PA_WAIT4 36
#define PA_LSPRING 37 /* Surely these are the wrong way round? */ #define PA_WAIT5 37
#define PA_FALLWHIP 38
#define PA_FALLSHOOT 39
#define PA_FLOAT1 40
#define PA_FLOAT2 41
#define PA_UP1 42
#define PA_EDGE 43
#define PA_CARRY 44
#define PA_UNLOAD 45
#define PA_LOAD 46
#define PA_LOOKUP1 47
#define PA_WALK45 48
#define PA_WALK90 49
#define PA_WALK135 50
#define PA_WALK180 51
#define PA_WALK225 52
#define PA_WALK270 53
#define PA_WALK315 54
#define PA_WOOZYWALK 55
#define PA_PUSH 56
#define PA_WHIP2 57
#define PA_EXIT3 58
#define PA_SPEED1 59
#define PA_SPEED2 60
#define PA_FALLMOVE 61
#define PA_MYSTERY1 62
#define PA_JUMP2 63
#define PA_FALLMOVEWHIP 64
#define PA_MYSTERY2 65
#define PA_JUMPSHOOTUP 66
#define PA_BALL 67
#define PA_WALKSHOOT 68
#define PA_WALKDIAG 69
#define PA_RUN 70
#define PA_SPEEDRUN 71
#define PA_STOP1 72
#define PA_MYSTERY3 73
#define PA_STOP2 74
#define PA_UP2 75
#define PA_STAND 76
#define PA_POWER 77
#define PA_POWEREND 78
#define PA_POWERSTART 79
#define PA_WOOZYSTAND 80
#define PA_SWIMDOWN 81
#define PA_SWIM 82
#define PA_SWIMDIAGDOWN 83
#define PA_SWIMDIAGUP 84
#define PA_SWIMUP 85
#define PA_VINESDIAG 86
#define PA_WARPOUT 87
#define PA_WARPFALLIN 88
#define PA_WARPFALL 89
#define PA_WARPFALLOUT 90
#define PA_WARPIN 91
#define PA_VPOLE 92
#define PA_CROUCH3 93
#define PA_CROUCH4 94
#define PA_FALLSTRANGE1 95
#define PA_HURT2 96
#define PA_WAIT6 97
#define PA_FALLSTRANGE2 98
#define PA_CROUCH5 99
#define PA_LOOKUP2 100
#define PA_WALK2 101
#define PA_WORRY 102
#define PA_LOOKUP3 103
#define JJ2PANIMS 104 /* Number of player animations. */
// Player reaction times // Player reaction times
#define PRT_HURT 1000 #define PRT_HURT 1000
...@@ -180,9 +248,10 @@ class JJ2LevelPlayer : public Movable { ...@@ -180,9 +248,10 @@ class JJ2LevelPlayer : public Movable {
private: private:
bool bird; // Placeholder for eventual JJ2Bird object bool bird; // Placeholder for eventual JJ2Bird object
Anim* anims;
Anim* flippedAnims;
JJ2Modifier* mod; JJ2Modifier* mod;
SDL_Color palette[256]; SDL_Color palette[256];
char anims[PANIMS];
int energy; int energy;
JJ2Shield shield; JJ2Shield shield;
int floating; /* 0 = normal, 1 = helicopter ears, 2 = boarding */ int floating; /* 0 = normal, 1 = helicopter ears, 2 = boarding */
...@@ -207,13 +276,13 @@ class JJ2LevelPlayer : public Movable { ...@@ -207,13 +276,13 @@ class JJ2LevelPlayer : public Movable {
public: public:
Player* player; Player* player;
JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird); JJ2LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, bool hasBird);
~JJ2LevelPlayer (); ~JJ2LevelPlayer ();
void reset (unsigned char startX, unsigned char startY); void reset (unsigned char startX, unsigned char startY);
void addGem (int colour); void addGem (int colour);
unsigned char getAnim (); Anim* getAnim ();
int getEnemies (); int getEnemies ();
int getEnergy (); int getEnergy ();
bool getFacing (); bool getFacing ();
......
...@@ -188,7 +188,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) { ...@@ -188,7 +188,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
dx = 0; dx = 0;
dy = 0; dy = 0;
animType = facing? PA_RDIE: PA_LDIE; animType = PA_DIE;
return; return;
...@@ -443,7 +443,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) { ...@@ -443,7 +443,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
if (ticks > fireTime) { if (ticks > fireTime) {
// Make sure bullet position is taken from correct animation // Make sure bullet position is taken from correct animation
if (platform) animType = facing? PA_RSHOOT: PA_LSHOOT; if (platform) animType = PA_STANDSHOOT;
// TODO: Create new bullet // TODO: Create new bullet
...@@ -494,55 +494,53 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) { ...@@ -494,55 +494,53 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
// Choose animation // Choose animation
if ((reaction == JJ2PR_HURT) && (reactionTime - ticks > PRT_HURT - PRT_HURTANIM)) if ((reaction == JJ2PR_HURT) && (reactionTime - ticks > PRT_HURT - PRT_HURTANIM))
animType = facing? PA_RHURT: PA_LHURT; animType = PA_HURT1;
else if (y + PYO_MID > jj2Level->getWaterLevel()) else if (y + PYO_MID > jj2Level->getWaterLevel())
animType = facing? PA_RSWIM: PA_LSWIM; animType = PA_SWIM;
else if (floating) animType = facing? PA_RBOARD: PA_LBOARD; else if (floating) animType = PA_BOARD;
else if (dy < 0) { else if (dy < 0) {
if (event == LPE_SPRING) animType = facing? PA_RSPRING: PA_LSPRING; if (event == LPE_SPRING) animType = PA_FLOAT1;
else animType = facing? PA_RJUMP: PA_LJUMP; else animType = PA_JUMP2;
} else if (platform) { } else if (platform) {
if (dx) { if (dx) {
if (dx <= -PXS_RUN) animType = PA_LRUN; if (dx <= -PXS_RUN) animType = PA_RUN;
else if (dx >= PXS_RUN) animType = PA_RRUN; else if (dx >= PXS_RUN) animType = PA_RUN;
else if ((dx < 0) && facing) animType = PA_LSTOP; else if ((dx < 0) && facing) animType = PA_STOP1;
else if ((dx > 0) && !facing) animType = PA_RSTOP; else if ((dx > 0) && !facing) animType = PA_STOP1;
else animType = facing? PA_RWALK: PA_LWALK; else animType = PA_WALK2;
} else if (!jj2Level->checkMaskDown(x + PXO_ML, y + F12, drop) && } else if (!jj2Level->checkMaskDown(x + PXO_ML, y + F12, drop) &&
!jj2Level->checkMaskDown(x + PXO_L, y + F2, drop) /*&& !jj2Level->checkMaskDown(x + PXO_L, y + F2, drop) &&
(event != 3) && (event != 4)*/) (event != LPE_PLATFORM))
animType = PA_LEDGE; animType = PA_EDGE;
else if (!jj2Level->checkMaskDown(x + PXO_MR, y + F12, drop) && else if (!jj2Level->checkMaskDown(x + PXO_MR, y + F12, drop) &&
!jj2Level->checkMaskDown(x + PXO_R, y + F2, drop) /*&& !jj2Level->checkMaskDown(x + PXO_R, y + F2, drop) &&
(event != 3) && (event != 4)*/) (event != LPE_PLATFORM))
animType = PA_REDGE; animType = PA_EDGE;
else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime))
animType = PA_LOOKUP; animType = PA_LOOKUP1;
else if (lookTime > 0) { else if (lookTime > 0) {
if ((int)ticks < 1000 + lookTime) animType = facing? PA_RCROUCH: PA_LCROUCH; if ((int)ticks < 1000 + lookTime) animType = PA_CROUCHED;
else animType = PA_LOOKDOWN; else animType = PA_CROUCH1;
} }
else if (player->pcontrols[C_FIRE]) else if (player->pcontrols[C_FIRE]) animType = PA_STANDSHOOT;
animType = facing? PA_RSHOOT: PA_LSHOOT;
else else animType = PA_STAND;
animType = facing? PA_RSTAND: PA_LSTAND;
} else animType = facing? PA_RFALL: PA_LFALL; } else animType = PA_FALL;
return; return;
...@@ -811,15 +809,14 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) { ...@@ -811,15 +809,14 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) {
// Choose sprite // Choose sprite
an = jj2Level->getAnim(getAnim()); an = getAnim();
an->setFrame(frame, reaction != JJ2PR_KILLED); an->setFrame(frame, reaction != JJ2PR_KILLED);
// Show the player // Show the player
// Use player colour // Use player colour
an->setPalette(palette, 23, 41); an->setPalette(palette, 16, 32);
an->setPalette(palette, 88, 8);
// Flash on and off if hurt // Flash on and off if hurt
if ((reaction != JJ2PR_HURT) || ((ticks / 30) & 2)) { if ((reaction != JJ2PR_HURT) || ((ticks / 30) & 2)) {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <string.h> #include <string.h>
LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird) { LevelPlayer::LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, bool hasBird) {
int offsets[15] = {PCO_GREY, PCO_SGREEN, PCO_BLUE, PCO_RED, PCO_LGREEN, int offsets[15] = {PCO_GREY, PCO_SGREEN, PCO_BLUE, PCO_RED, PCO_LGREEN,
PCO_LEVEL1, PCO_YELLOW, PCO_LEVEL2, PCO_ORANGE, PCO_LEVEL3, PCO_LEVEL4, PCO_LEVEL1, PCO_YELLOW, PCO_LEVEL2, PCO_ORANGE, PCO_LEVEL3, PCO_LEVEL4,
...@@ -49,8 +49,7 @@ LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX, ...@@ -49,8 +49,7 @@ LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX,
player = parent; player = parent;
if (newAnims) memcpy(anims, newAnims, PANIMS); memcpy(anims, newAnims, PANIMS * sizeof(Anim*));
else memset(anims, 0, PANIMS);
if (hasBird) bird = new Bird(this, startX, startY - 2); if (hasBird) bird = new Bird(this, startX, startY - 2);
else bird = NULL; else bird = NULL;
...@@ -165,7 +164,7 @@ void LevelPlayer::clearEvent (unsigned char gridX, unsigned char gridY) { ...@@ -165,7 +164,7 @@ void LevelPlayer::clearEvent (unsigned char gridX, unsigned char gridY) {
} }
unsigned char LevelPlayer::getAnim () { Anim* LevelPlayer::getAnim () {
return anims[animType]; return anims[animType];
...@@ -680,13 +679,16 @@ void LevelPlayer::send (unsigned char *buffer) { ...@@ -680,13 +679,16 @@ void LevelPlayer::send (unsigned char *buffer) {
void LevelPlayer::receive (unsigned char *buffer) { void LevelPlayer::receive (unsigned char *buffer) {
int count;
// Interpret data received from client/server // Interpret data received from client/server
switch (buffer[1]) { switch (buffer[1]) {
case MT_P_ANIMS: case MT_P_ANIMS:
memcpy(anims, (char *)buffer + 3, PANIMS); for (count = 0; count < PANIMS; count++)
anims[count] = level->getAnim(buffer[MTL_P_ANIMS + count]);
break; break;
......
...@@ -96,6 +96,8 @@ ...@@ -96,6 +96,8 @@
#define PA_RSPRING 36 #define PA_RSPRING 36
#define PA_LSPRING 37 /* Surely these are the wrong way round? */ #define PA_LSPRING 37 /* Surely these are the wrong way round? */
#define PANIMS 38 /* Number of player animations. May be higher. */
// Player reaction times // Player reaction times
#define PRT_HURT 1000 #define PRT_HURT 1000
#define PRT_HURTANIM 200 #define PRT_HURTANIM 200
...@@ -150,7 +152,7 @@ class LevelPlayer : public Movable { ...@@ -150,7 +152,7 @@ class LevelPlayer : public Movable {
private: private:
Bird* bird; Bird* bird;
SDL_Color palette[256]; SDL_Color palette[256];
char anims[PANIMS]; Anim* anims[PANIMS];
int energy; int energy;
int shield; /* 0 = none, 1 = 1 yellow, 2 = 2 yellow, 3 = 1 orange, 4 = 2 orange, 5 = 3 orange, 6 = 4 orange */ int shield; /* 0 = none, 1 = 1 yellow, 2 = 2 yellow, 3 = 1 orange, 4 = 2 orange, 5 = 3 orange, 6 = 4 orange */
bool floating; /* false = normal, true = boarding/bird/etc. */ bool floating; /* false = normal, true = boarding/bird/etc. */
...@@ -174,14 +176,14 @@ class LevelPlayer : public Movable { ...@@ -174,14 +176,14 @@ class LevelPlayer : public Movable {
public: public:
Player* player; Player* player;
LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird); LevelPlayer (Player* parent, Anim** newAnims, unsigned char startX, unsigned char startY, bool hasBird);
~LevelPlayer (); ~LevelPlayer ();
void reset (unsigned char startX, unsigned char startY); void reset (unsigned char startX, unsigned char startY);
void addItem (); void addItem ();
void clearEvent (unsigned char gridX, unsigned char gridY); void clearEvent (unsigned char gridX, unsigned char gridY);
unsigned char getAnim (); Anim* getAnim ();
int getEnemies (); int getEnemies ();
int getEnergy (); int getEnergy ();
bool getFacing (); bool getFacing ();
......
...@@ -688,7 +688,7 @@ void LevelPlayer::draw (unsigned int ticks, int change) { ...@@ -688,7 +688,7 @@ void LevelPlayer::draw (unsigned int ticks, int change) {
// Choose sprite // Choose sprite
an = level->getAnim(getAnim()); an = anims[animType];
an->setFrame(frame, reaction != PR_KILLED); an->setFrame(frame, reaction != PR_KILLED);
......
...@@ -126,13 +126,14 @@ void Player::deinit () { ...@@ -126,13 +126,14 @@ void Player::deinit () {
void Player::reset (unsigned char x, unsigned char y) { void Player::reset (unsigned char x, unsigned char y) {
if (levelPlayer) levelPlayer->reset(x, y); if (levelPlayer) levelPlayer->reset(x, y);
else if (jj2LevelPlayer) jj2LevelPlayer->reset(x, y);
return; return;
} }
void Player::reset (LevelType levelType, char* newAnims, unsigned char x, unsigned char y) { void Player::reset (LevelType levelType, Anim** anims, unsigned char x, unsigned char y) {
int count; int count;
...@@ -163,19 +164,19 @@ void Player::reset (LevelType levelType, char* newAnims, unsigned char x, unsign ...@@ -163,19 +164,19 @@ void Player::reset (LevelType levelType, char* newAnims, unsigned char x, unsign
case LT_LEVEL: case LT_LEVEL:
levelPlayer = new LevelPlayer(this, newAnims, x, y, bird); levelPlayer = new LevelPlayer(this, anims, x, y, bird);
break; break;
case LT_BONUS: case LT_BONUS:
bonusPlayer = new BonusPlayer(this, newAnims, x, y); bonusPlayer = new BonusPlayer(this, anims, x, y);
break; break;
case LT_JJ2LEVEL: case LT_JJ2LEVEL:
jj2LevelPlayer = new JJ2LevelPlayer(this, newAnims, x, y, bird); jj2LevelPlayer = new JJ2LevelPlayer(this, anims, x, y, bird);
break; break;
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#define CHAR_WBAND 8 #define CHAR_WBAND 8
// General // General
#define PANIMS 38 /* Number of player animations. Is probably higher. */
#define PCONTROLS 8 /* Number of player controls. */ #define PCONTROLS 8 /* Number of player controls. */
#define PCOLOURS 4 /* Number of configurable colour ranges */ #define PCOLOURS 4 /* Number of configurable colour ranges */
...@@ -79,6 +78,7 @@ enum PlayerEvent { ...@@ -79,6 +78,7 @@ enum PlayerEvent {
// Classes // Classes
class Anim;
class LevelPlayer; class LevelPlayer;
class BonusPlayer; class BonusPlayer;
class JJ2LevelPlayer; class JJ2LevelPlayer;
...@@ -111,7 +111,7 @@ class Player { ...@@ -111,7 +111,7 @@ class Player {
void init (char* playerName, unsigned char* cols, unsigned char newTeam); void init (char* playerName, unsigned char* cols, unsigned char newTeam);
void deinit (); void deinit ();
void reset (unsigned char x, unsigned char y); void reset (unsigned char x, unsigned char y);
void reset (LevelType levelType, char* newAnims, unsigned char x, unsigned char y); void reset (LevelType levelType, Anim** anims, unsigned char x, unsigned char y);
void addLife (); void addLife ();
void addScore (int addedScore); void addScore (int addedScore);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment