Commit f1bbcd3a authored by alistert's avatar alistert

More JJ2 events.

parent e34e2bf4
......@@ -45,11 +45,14 @@ JJ2Event* JJ2Event::step (int ticks, int msps) {
switch (type) {
case 60: // Frozen green spring
case 62: // Spring crate
case 83: // Checkpoint
case 85: // Red spring
case 86: // Green spring
case 87: // Blue spring
if (!jj2Level->checkMaskDown(x, y + F8)) y += F8;
if (!jj2Level->checkMaskDown(x, y + F1, true)) y += F1;
break;
......@@ -99,6 +102,24 @@ void JJ2Event::draw (int change) {
switch (type) {
case 60: // Frozen green spring
an = jj2Level->getAnim(35);
break;
case 62: // Spring crate
an = jj2Level->getAnim(37);
break;
case 83: // Checkpoint
an = jj2Level->getAnim(49);
break;
case 85: // Red spring
an = jj2Level->getAnim(32);
......
......@@ -103,7 +103,9 @@ bool JJ2Level::checkMaskUp (fixed x, fixed y) {
return true;
// Event 1 is one-way
if (mods[tY][tX].type == 1) return false;
// Event 3 is vine
// Event 4 is hook
if ((mods[tY][tX].type == 1) || (mods[tY][tX].type == 3) || (mods[tY][tX].type == 4)) return false;
// Check the mask in the tile in question
return (layer->getFlipped(tX, tY)? flippedMask: mask)[(layer->getTile(tX, tY) << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)];
......@@ -111,7 +113,7 @@ bool JJ2Level::checkMaskUp (fixed x, fixed y) {
}
bool JJ2Level::checkMaskDown (fixed x, fixed y) {
bool JJ2Level::checkMaskDown (fixed x, fixed y, bool drop) {
int tX, tY;
......@@ -122,6 +124,10 @@ bool JJ2Level::checkMaskDown (fixed x, fixed y) {
if ((x < 0) || (y < 0) || (tX >= layer->getWidth()) || (tY >= layer->getHeight()))
return true;
// Event 3 is vine
// Event 4 is hook
if (drop && ((mods[tY][tX].type == 3) || (mods[tY][tX].type == 4))) return false;
// Check the mask in the tile in question
return (layer->getFlipped(tX, tY)? flippedMask: mask)[(layer->getTile(tX, tY) << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)];
......@@ -196,6 +202,13 @@ void JJ2Level::setFrame (unsigned char gridX, unsigned char gridY, unsigned char
}
JJ2Modifier* JJ2Level::getModifier (unsigned char gridX, unsigned char gridY) {
return mods[gridY] + gridX;
}
Sprite* JJ2Level::getSprite (unsigned char sprite) {
return spriteSet + sprite;
......@@ -358,9 +371,13 @@ int JJ2Level::play () {
// The level is over, so draw gem counts
returnTime = ticks + 1000;
if (!returnTime) {
returnTime = ticks + 3000;
playSound(S_UPLOOP);
}
// Display statistics
font->showString("red gems", (canvasW >> 1) - 152, (canvasH >> 1) - 60);
......
......@@ -118,6 +118,7 @@ class JJ2Level : public BaseLevel {
int loadSprites (char* fileName);
int loadTiles (char* fileName);
int load (char* fileName, unsigned char diff, bool checkpoint);
int step ();
void draw ();
......@@ -125,16 +126,19 @@ class JJ2Level : public BaseLevel {
JJ2Level (char* fileName, unsigned char diff, bool checkpoint);
~JJ2Level ();
bool checkMaskDown (fixed x, fixed y, bool drop);
bool checkMaskUp (fixed x, fixed y);
bool checkMaskDown (fixed x, fixed y);
bool checkSpikes (fixed x, fixed y);
void setNext (char* fileName);
void setFrame (unsigned char gridX, unsigned char gridY, unsigned char frame);
Sprite* getSprite (unsigned char sprite);
Anim* getAnim (unsigned char anim);
void setWaterLevel (unsigned char gridY);
JJ2Modifier* getModifier (unsigned char gridX, unsigned char gridY);
Sprite* getSprite (unsigned char sprite);
fixed getWaterLevel ();
void setFrame (unsigned char gridX, unsigned char gridY, unsigned char frame);
void setNext (char* fileName);
void setWaterLevel (unsigned char gridY);
void receive (unsigned char* buffer);
int play ();
};
......
......@@ -503,7 +503,10 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
// Next level
nextLevel = createString((char *)aBuffer + 115);
string = (char *)aBuffer + 115;
if (fileExists(string)) nextLevel = createString(string);
else nextLevel = createString(string, ".j2l");
// Music file
......@@ -574,7 +577,7 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
count = bBuffer[((y * width) + x) << 2];
if (count < 33) {
if ((count < 33) || (count == 230)) {
mods[y][x].type = count;
mods[y][x].property = bBuffer[(((y * width) + x) << 2) + 1];
......
......@@ -129,6 +129,7 @@ JJ2LevelPlayer::~JJ2LevelPlayer () {
void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) {
event = NULL;
mod = NULL;
energy = 5;
floating = false;
facing = true;
......@@ -138,7 +139,7 @@ void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) {
jumpHeight = ITOF(92);
jumpY = TTOF(256);
fastFeetTime = 0;
warpTime = 0;
stopTime = 0;
dx = 0;
dy = 0;
x = TTOF(startX);
......@@ -317,16 +318,36 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps
switch (touched->getType()) {
case 60: // Frozen green spring
jumpY = y - TTOF(14);
event = touched;
break;
case 62: // Spring crate
jumpY = y - TTOF(18);
event = touched;
break;
case 83: // Checkpoint
game->setCheckpoint(FTOT(x + PXO_MID), FTOT(y + PYO_MID));
break;
case 85: // Red spring
jumpY = y - TTOF(6);
jumpY = y - TTOF(7);
event = touched;
break;
case 86: // Green spring
jumpY = y - TTOF(12);
jumpY = y - TTOF(14);
event = touched;
break;
......
......@@ -31,6 +31,7 @@
#include "player.h"
#include "jj2level/jj2level.h"
#include "level/movable.h"
#include "OpenJazz.h"
......@@ -138,6 +139,12 @@
#define PYS_SINK ITOF(150)
#define PYS_JUMP ITOF(-350)
#define PXS_POLE ITOF(3000)
#define PYS_POLE ITOF(1000)
#define PYS_RSPRING ITOF(-500)
#define PYS_GSPRING ITOF(-600)
#define PYS_BSPRING ITOF(-700)
// Player accelerations
#define PXA_REVERSE 900
#define PXA_STOP 1000
......@@ -172,6 +179,7 @@ class JJ2LevelPlayer : public Movable {
private:
bool bird; // Placeholder for eventual JJ2Bird object
JJ2Modifier* mod;
JJ2Event* event;
SDL_Color palette[256];
char anims[PANIMS];
......@@ -187,8 +195,7 @@ class JJ2LevelPlayer : public Movable {
fixed jumpHeight;
fixed jumpY;
unsigned int fastFeetTime;
unsigned char warpX, warpY;
unsigned int warpTime;
unsigned int stopTime;
int gems[4];
public:
......
......@@ -28,6 +28,7 @@
#include "jj2levelplayer.h"
#include "game/game.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/gfx/font.h"
......@@ -40,12 +41,17 @@
void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
bool platform;
JJ2Modifier* nextMod;
bool drop, platform;
unsigned char type;
if (event) type = event->getType();
else type = 0;
nextMod = jj2Level->getModifier(FTOT(x + PXO_MID), FTOT(y + PYO_MID));
// Respond to controls, unless the player has been killed
// If the player has been killed, drop but otherwise do not move
......@@ -87,7 +93,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
facing = false;
} else {
} else if ((nextMod->type >> 1) != 3) {
// Slow down
......@@ -111,14 +117,15 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
if (dx > PXS_RUN) dx = PXS_RUN;
drop = player->pcontrols[C_DOWN];
// Check for platform event, bridge or level mask below player
platform = /*(event >= 3) ||*/
jj2Level->checkMaskDown(x + PXO_ML, y + 1) ||
jj2Level->checkMaskDown(x + PXO_MID, y + 1) ||
jj2Level->checkMaskDown(x + PXO_MR, y + 1) ||
((dx > 0) && jj2Level->checkMaskDown(x + PXO_ML, y + F8)) ||
((dx < 0) && jj2Level->checkMaskDown(x + PXO_MR, y + F8));
jj2Level->checkMaskDown(x + PXO_ML, y + 1, drop) ||
jj2Level->checkMaskDown(x + PXO_MID, y + 1, drop) ||
jj2Level->checkMaskDown(x + PXO_MR, y + 1, drop) ||
((dx > 0) && jj2Level->checkMaskDown(x + PXO_ML, y + F8, drop)) ||
((dx < 0) && jj2Level->checkMaskDown(x + PXO_MR, y + F8, drop));
if (floating) {
......@@ -138,7 +145,7 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
else if (dy < PXS_WALK) dy += PXA_WALK * msps;
else if (dy < PXS_RUN) dy += PXA_RUN * msps;
} else {
} else if ((nextMod->type >> 1) != 3) {
// Slow down
......@@ -160,9 +167,9 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
if (type) {
if (type == 85) dy = PYS_JUMP;
else if (type == 86) dy = PYS_JUMP;
else if (type == 87) dy = PYS_JUMP;
if (type == 85) dy = PYS_RSPRING;
else if (type == 86) dy = PYS_GSPRING;
else if (type == 87) dy = PYS_BSPRING;
}
......@@ -242,11 +249,9 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
dy = (jumpY - y - F64) * 4;
// Spring up speed limit
if ((type == 85) || (type == 86) || (type == 87)) {
if (dy < PYS_JUMP) dy = PYS_JUMP;
}
if ((type == 85) && (dy < PYS_RSPRING)) dy = PYS_RSPRING;
if ((type == 86) && (dy < PYS_GSPRING)) dy = PYS_GSPRING;
if ((type == 87) && (dy < PYS_BSPRING)) dy = PYS_BSPRING;
// Avoid jumping too fast, unless caused by an event
if (!event && (dy < PYS_JUMP)) dy = PYS_JUMP;
......@@ -298,6 +303,125 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
}
// Handle modifiers
switch (nextMod->type) {
case 4: // Hook
dx = 0;
break;
case 6: // H-pole
if (!stopTime) {
// Catch player
if (nextMod != mod) {
dy = 0;
x = ((x + PXO_MID) & ~32767) + F16 - PXO_MID;
y = ((y + PYO_MID) & ~32767) + F16 - PYO_MID;
stopTime = ticks + 1000;
}
} else if (ticks < stopTime) {
dy = 0;
x = ((x + PXO_MID) & ~32767) + F16 - PXO_MID;
y = ((y + PYO_MID) & ~32767) + F16 - PYO_MID;
} else {
dx = (dx > 0) ? PXS_POLE: -PXS_POLE;
stopTime = 0;
}
break;
case 7: // V-pole
if (!stopTime) {
// Catch player
if (nextMod != mod) {
dx = 0;
x = ((x + PXO_MID) & ~32767) + F16 - PXO_MID;
y = ((y + PYO_MID) & ~32767) + F16 - PYO_MID;
stopTime = ticks + 1000;
}
} else if (ticks < stopTime) {
dx = 0;
x = ((x + PXO_MID) & ~32767) + F16 - PXO_MID;
y = ((y + PYO_MID) & ~32767) + F16 - PYO_MID;
} else {
dy = (dy > 0) ? PYS_POLE: -PYS_POLE;
stopTime = 0;
}
break;
case 8: // Fly off
floating = false;
break;
case 17: // End of level
if (!energy) return;
if (!gameMode) {
if (game) game->setCheckpoint(FTOT(x + PXO_MID), FTOT(y + PYO_MID));
jj2Level->setStage(LS_END);
} else if (!(gameMode->endOfLevel(player, FTOT(x + PXO_MID), FTOT(y + PYO_MID)))) return;
break;
case 230: // Warp
if (!stopTime) {
// Catch player
dx = 0;
dy = 0;
stopTime = ticks + 1000;
} if (ticks > stopTime) {
// TODO: Find corresponding warp target
//x = TTOF();
//y = TTOF();
stopTime = 0;
}
break;
default:
stopTime = 0;
break;
}
mod = nextMod;
// Handle firing
if (player->pcontrols[C_FIRE]) {
......@@ -377,13 +501,13 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
else if ((dx > 0) && !facing) animType = PA_RSTOP;
else animType = facing? PA_RWALK: PA_LWALK;
} else if (!jj2Level->checkMaskDown(x + PXO_ML, y + F12) &&
!jj2Level->checkMaskDown(x + PXO_L, y + F2) /*&&
} else if (!jj2Level->checkMaskDown(x + PXO_ML, y + F12, drop) &&
!jj2Level->checkMaskDown(x + PXO_L, y + F2, drop) /*&&
(event != 3) && (event != 4)*/)
animType = PA_LEDGE;
else if (!jj2Level->checkMaskDown(x + PXO_MR, y + F12) &&
!jj2Level->checkMaskDown(x + PXO_R, y + F2) /*&&
else if (!jj2Level->checkMaskDown(x + PXO_MR, y + F12, drop) &&
!jj2Level->checkMaskDown(x + PXO_R, y + F2, drop) /*&&
(event != 3) && (event != 4)*/)
animType = PA_REDGE;
......@@ -415,14 +539,8 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
fixed pdx, pdy;
int count;
bool drop;
if (warpTime && (ticks > warpTime)) {
x = TTOF(warpX);
y = TTOF(warpY + 1);
warpTime = 0;
}
// Apply as much of the trajectory as possible, without going into the
// scenery
......@@ -439,37 +557,40 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
}
// First for the vertical component of the trajectory
drop = player->pcontrols[C_DOWN];
if (pdy < 0) {
// Moving up
count = (-pdy) >> 12;
count = (-pdy) >> 10;
while (count > 0) {
if (jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - F4)) {
if (jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - F1)) {
y &= ~4095;
y &= ~1023;
dy = 0;
break;
}
y -= F4;
y -= F1;
count--;
}
pdy = (-pdy) & 4095;
pdy = (-pdy) & 1023;
if (!jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - pdy))
y -= pdy;
else {
y &= ~4095;
y &= ~1023;
dy = 0;
}
......@@ -478,35 +599,35 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
// Moving down
count = pdy >> 12;
count = pdy >> 10;
while (count > 0) {
if (jj2Level->checkMaskDown(x + PXO_ML, y + F4) ||
jj2Level->checkMaskDown(x + PXO_MID, y + F4) ||
jj2Level->checkMaskDown(x + PXO_MR, y + F4)) {
if (jj2Level->checkMaskDown(x + PXO_ML, y + F1, drop) ||
jj2Level->checkMaskDown(x + PXO_MID, y + F1, drop) ||
jj2Level->checkMaskDown(x + PXO_MR, y + F1, drop)) {
y |= 4095;
y |= 1023;
dy = 0;
break;
}
y += F4;
y += F1;
count--;
}
pdy &= 4095;
pdy &= 1023;
if (!(jj2Level->checkMaskDown(x + PXO_ML, y + pdy) ||
jj2Level->checkMaskDown(x + PXO_MID, y + pdy) ||
jj2Level->checkMaskDown(x + PXO_MR, y + pdy)))
if (!(jj2Level->checkMaskDown(x + PXO_ML, y + pdy, drop) ||
jj2Level->checkMaskDown(x + PXO_MID, y + pdy, drop) ||
jj2Level->checkMaskDown(x + PXO_MR, y + pdy, drop)))
y += pdy;
else {
y |= 4095;
y |= 1023;
dy = 0;
}
......@@ -521,71 +642,71 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
// Moving left
count = (-pdx) >> 12;
count = (-pdx) >> 10;
while (count > 0) {
// If there is an obstacle, stop
if (jj2Level->checkMaskUp(x + PXO_L - F4, y + PYO_MID)) {
if (jj2Level->checkMaskUp(x + PXO_L - F1, y + PYO_MID)) {
x &= ~4095;
x &= ~1023;
break;
}
x -= F4;
x -= F1;
count--;
// If on an uphill slope, push the player upwards
if (jj2Level->checkMaskUp(x + PXO_ML, y) &&
!jj2Level->checkMaskUp(x + PXO_ML, y - F4)) y -= F4;
!jj2Level->checkMaskUp(x + PXO_ML, y - F1)) y -= F1;
}
pdx = (-pdx) & 4095;
pdx = (-pdx) & 1023;
if (!jj2Level->checkMaskUp(x + PXO_L - pdx, y + PYO_MID)) x -= pdx;
else x &= ~4095;
else x &= ~1023;
// If on an uphill slope, push the player upwards
while (jj2Level->checkMaskUp(x + PXO_ML, y) &&
!jj2Level->checkMaskUp(x + PXO_ML, y - F4)) y -= F1;
!jj2Level->checkMaskUp(x + PXO_ML, y - F1)) y -= F1;
} else if (pdx > 0) {
// Moving right
count = pdx >> 12;
count = pdx >> 10;
while (count > 0) {
// If there is an obstacle, stop
if (jj2Level->checkMaskUp(x + PXO_R + F4, y + PYO_MID)) {
if (jj2Level->checkMaskUp(x + PXO_R + F1, y + PYO_MID)) {
x |= 4095;
x |= 1023;
break;
}
x += F4;
x += F1;
count--;
// If on an uphill slope, push the player upwards
if (jj2Level->checkMaskUp(x + PXO_MR, y) &&
!jj2Level->checkMaskUp(x + PXO_MR, y - F4)) y -= F4;
!jj2Level->checkMaskUp(x + PXO_MR, y - F1)) y -= F1;
}
pdx &= 4095;
pdx &= 1023;
if (!jj2Level->checkMaskUp(x + PXO_R + pdx, y + PYO_MID)) x += pdx;
else x |= 4095;
else x |= 1023;
// If on an uphill slope, push the player upwards
while (jj2Level->checkMaskUp(x + PXO_MR, y) &&
!jj2Level->checkMaskUp(x + PXO_MR, y - F4)) y -= F1;
!jj2Level->checkMaskUp(x + PXO_MR, y - F1)) y -= F1;
}
......@@ -603,10 +724,10 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
// Handle spikes
if (jj2Level->checkSpikes(x + PXO_MID, y + PYO_TOP - F4) ||
jj2Level->checkSpikes(x + PXO_MID, y + F4) ||
jj2Level->checkSpikes(x + PXO_L - F4, y + PYO_MID) ||
jj2Level->checkSpikes(x + PXO_R + F4, y + PYO_MID)) hit(NULL, ticks);
if (jj2Level->checkSpikes(x + PXO_MID, y + PYO_TOP - F1) ||
jj2Level->checkSpikes(x + PXO_MID, y + F1) ||
jj2Level->checkSpikes(x + PXO_L - F1, y + PYO_MID) ||
jj2Level->checkSpikes(x + PXO_R + F1, y + PYO_MID)) hit(NULL, ticks);
return;
......
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