Commit 0d00bb30 authored by alistert's avatar alistert

More JJ2 events.

parent b8f1b0f2
...@@ -45,6 +45,7 @@ JJ2Event::JJ2Event (JJ2Event* newNext, unsigned char gridX, unsigned char gridY, ...@@ -45,6 +45,7 @@ JJ2Event::JJ2Event (JJ2Event* newNext, unsigned char gridX, unsigned char gridY,
data[2] = properties[3]; data[2] = properties[3];
hits = 0; hits = 0;
endTime = 0;
return; return;
...@@ -59,7 +60,7 @@ JJ2Event::~JJ2Event () { ...@@ -59,7 +60,7 @@ JJ2Event::~JJ2Event () {
void JJ2Event::destroy (unsigned int ticks) { void JJ2Event::destroy (unsigned int ticks) {
time = ticks + 1000; endTime = ticks + 1000;
return; return;
......
...@@ -36,7 +36,7 @@ class JJ2Event : public Movable { ...@@ -36,7 +36,7 @@ class JJ2Event : public Movable {
unsigned char type; unsigned char type;
unsigned char data[3]; unsigned char data[3];
unsigned char hits; // Number of times the event has been shot unsigned char hits; // Number of times the event has been shot
int time; /* Point at which the event will do something, e.g. terminate */ int endTime; // Point at which the event will terminate
unsigned char anim; unsigned char anim;
unsigned char frame; unsigned char frame;
unsigned int flashTime; unsigned int flashTime;
......
...@@ -64,6 +64,16 @@ JJ2Event* JJ2Event::step (int ticks, int msps) { ...@@ -64,6 +64,16 @@ JJ2Event* JJ2Event::step (int ticks, int msps) {
} }
// If the reaction time has expired
if (endTime && (ticks > endTime)) {
return remove();
}
if (endTime) return this;
// Handle contact with player // Handle contact with player
for (count = 0; count < nPlayers; count++) { for (count = 0; count < nPlayers; count++) {
...@@ -141,7 +151,7 @@ void JJ2Event::draw (int change) { ...@@ -141,7 +151,7 @@ void JJ2Event::draw (int change) {
default: default:
drawRect(FTOI(drawX) + 8, FTOI(drawY) + 8, 16, 16, type); if (!endTime) drawRect(FTOI(drawX) + 8, FTOI(drawY) + 8, 16, 16, type);
panelBigFont->showNumber(type, FTOI(drawX) + 24, FTOI(drawY) + 12); panelBigFont->showNumber(type, FTOI(drawX) + 24, FTOI(drawY) + 12);
return; return;
......
...@@ -134,26 +134,6 @@ bool JJ2Level::checkMaskDown (fixed x, fixed y, bool drop) { ...@@ -134,26 +134,6 @@ bool JJ2Level::checkMaskDown (fixed x, fixed y, bool drop) {
} }
bool JJ2Level::checkSpikes (fixed x, fixed y) {
int tX, tY;
tX = FTOT(x);
tY = FTOT(y);
// Anything off the edge of the map is not spikes
if ((x < 0) || (y < 0) || (tX >= layer->getWidth()) || (tY >= layer->getHeight()))
return false;
// Event 2 is spikes
if (mods[tY][tX].type != 2) 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)];
}
void JJ2Level::setNext (char* fileName) { void JJ2Level::setNext (char* fileName) {
unsigned char buffer[MTL_L_PROP]; unsigned char buffer[MTL_L_PROP];
...@@ -252,6 +232,29 @@ fixed JJ2Level::getWaterLevel () { ...@@ -252,6 +232,29 @@ fixed JJ2Level::getWaterLevel () {
} }
void JJ2Level::warp (JJ2LevelPlayer *player, int id) {
int x, y;
for (y = 0; y < layer->getHeight(); y++) {
for (x = 0; x < layer->getWidth(); x++) {
if ((mods[y][x].type == 240) && ((mods[y][x].properties & 255) == id)) {
player->setPosition(TTOF(x), TTOF(y));
return;
}
}
}
}
void JJ2Level::receive (unsigned char* buffer) { void JJ2Level::receive (unsigned char* buffer) {
......
...@@ -59,7 +59,7 @@ typedef struct { ...@@ -59,7 +59,7 @@ typedef struct {
typedef struct { typedef struct {
unsigned char type; unsigned char type;
int property; int properties;
} JJ2Modifier; } JJ2Modifier;
...@@ -92,6 +92,7 @@ class JJ2Layer { ...@@ -92,6 +92,7 @@ class JJ2Layer {
}; };
class JJ2Event; class JJ2Event;
class JJ2LevelPlayer;
class JJ2Level : public BaseLevel { class JJ2Level : public BaseLevel {
...@@ -129,7 +130,6 @@ class JJ2Level : public BaseLevel { ...@@ -129,7 +130,6 @@ 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);
bool checkSpikes (fixed x, fixed y);
Anim* getAnim (unsigned char anim); Anim* getAnim (unsigned char anim);
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);
...@@ -137,6 +137,7 @@ class JJ2Level : public BaseLevel { ...@@ -137,6 +137,7 @@ class JJ2Level : public BaseLevel {
void setFrame (unsigned char gridX, unsigned char gridY, unsigned char frame); void setFrame (unsigned char gridX, unsigned char gridY, unsigned char frame);
void setNext (char* fileName); void setNext (char* fileName);
void setWaterLevel (unsigned char gridY); void setWaterLevel (unsigned char gridY);
void warp (JJ2LevelPlayer *player, int id);
void receive (unsigned char* buffer); void receive (unsigned char* buffer);
......
...@@ -144,7 +144,7 @@ void JJ2Level::draw () { ...@@ -144,7 +144,7 @@ void JJ2Level::draw () {
// Show score // Show score
if (gameMode) gameMode->drawScore(font); if (gameMode) gameMode->drawScore(font);
else panelSmallFont->showNumber(localPlayer->getScore(), 16, 8); else panelSmallFont->showNumber(localPlayer->getScore(), 64, 8);
// Draw hearts // Draw hearts
......
...@@ -577,10 +577,13 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -577,10 +577,13 @@ int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
count = bBuffer[((y * width) + x) << 2]; count = bBuffer[((y * width) + x) << 2];
if ((count < 33) || (count == 230)) { if ((count < 33) || (count == 206) || (count == 230) || (count == 240)) {
mods[y][x].type = count; mods[y][x].type = count;
mods[y][x].property = bBuffer[(((y * width) + x) << 2) + 1]; mods[y][x].properties =
(bBuffer[(((y * width) + x) << 2) + 1] >> 4) +
(bBuffer[(((y * width) + x) << 2) + 2] << 4) +
(bBuffer[(((y * width) + x) << 2) + 3] << 12);
if (count == 29) { if (count == 29) {
......
...@@ -632,12 +632,12 @@ int Level::play () { ...@@ -632,12 +632,12 @@ int Level::play () {
} else if (timeBonus - count >= 0) { } else if (timeBonus - count >= 0) {
localPlayer->addScore(count); localPlayer->addScore(count * 10);
timeBonus -= count; timeBonus -= count;
} else { } else {
localPlayer->addScore(timeBonus); localPlayer->addScore(timeBonus * 10);
timeBonus = 0; timeBonus = 0;
} }
......
...@@ -145,6 +145,7 @@ void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) { ...@@ -145,6 +145,7 @@ void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) {
x = TTOF(startX); x = TTOF(startX);
y = TTOF(startY); y = TTOF(startY);
gems[0] = gems[1] = gems[2] = gems[3] = 0; gems[0] = gems[1] = gems[2] = gems[3] = 0;
coins = 0;
return; return;
...@@ -160,6 +161,24 @@ void JJ2LevelPlayer::addGem (int colour) { ...@@ -160,6 +161,24 @@ void JJ2LevelPlayer::addGem (int colour) {
} }
void JJ2LevelPlayer::centreX () {
x = ((x + PXO_MID) & ~32767) + F16 - PXO_MID;
return;
}
void JJ2LevelPlayer::centreY () {
y = ((y + PYO_MID) & ~32767) + F16 - PYO_MID;
return;
}
unsigned char JJ2LevelPlayer::getAnim () { unsigned char JJ2LevelPlayer::getAnim () {
return anims[animType]; return anims[animType];
...@@ -307,16 +326,62 @@ void JJ2LevelPlayer::setSpeed (fixed newDx, fixed newDy) { ...@@ -307,16 +326,62 @@ void JJ2LevelPlayer::setSpeed (fixed newDx, fixed newDy) {
} }
bool JJ2LevelPlayer::takeEvent (JJ2Event* event, unsigned int ticks) { bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps) {
return true; unsigned char type;
bool fullPickup = false;
} type = touched->getType();
switch (type) {
bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps) { case 34: // Ammo
player->addAmmo(2, 3);
player->addScore(100);
return true;
case 36: // Ammo
player->addAmmo(1, 3);
player->addScore(100);
return true;
case 37: // Ammo
player->addAmmo(0, 3);
player->addScore(100);
return true;
switch (touched->getType()) { case 38: // TNT
player->addAmmo(3, 3);
player->addScore(100);
return true;
case 44:
coins++;
player->addScore(500);
return true;
case 45:
coins += 5;
player->addScore(1000);
return true;
case 59: // Board
floating = true;
return true;
case 60: // Frozen green spring case 60: // Frozen green spring
...@@ -326,6 +391,12 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps ...@@ -326,6 +391,12 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps
break; break;
case 61: // Rapid fire
player->fireSpeed++;
return true;
case 62: // Spring crate case 62: // Spring crate
throwY = y - TTOF(18); throwY = y - TTOF(18);
...@@ -334,6 +405,66 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps ...@@ -334,6 +405,66 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps
break; break;
case 63: // Red gem
gems[0]++;
player->addScore(100);
return true;
case 64: // Green gem
gems[1]++;
player->addScore(100);
return true;
case 65: // Blue gem
gems[2]++;
player->addScore(100);
return true;
case 66: // Purple gem
gems[3]++;
player->addScore(100);
return true;
case 72: // Carrot
if ((energy < 5) || fullPickup) {
if (energy < 5) energy++;
player->addScore(200);
return true;
}
break;
case 73: // Full carrot
if ((energy < 5) || fullPickup) {
energy = 5;
return true;
}
break;
case 80: // 1-up
player->addLife();
return true;
case 83: // Checkpoint case 83: // Checkpoint
game->setCheckpoint(FTOT(x + PXO_MID), FTOT(y + PYO_MID)); game->setCheckpoint(FTOT(x + PXO_MID), FTOT(y + PYO_MID));
...@@ -364,8 +495,63 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps ...@@ -364,8 +495,63 @@ bool JJ2LevelPlayer::touchEvent (JJ2Event* touched, unsigned int ticks, int msps
break; break;
case 88: //Invincibility
reaction = JJ2PR_INVINCIBLE;
reactionTime = ticks + PRT_INVINCIBLE;
return true;
case 91: // Horizontal red spring
if (true) throwX = x + TTOF(7);
else throwX = x - TTOF(7);
dy = 0;
break;
case 92: // Horizontal green spring
if (true) throwX = x + TTOF(14);
else throwX = x - TTOF(14);
dy = 0;
break;
case 93: // Horizontal blue spring
if (true) throwX = x + TTOF(18);
else throwX = x - TTOF(18);
dy = 0;
break;
case 96: // Helicarrot
floating = true;
return true;
case 192: // Gem ring
gems[0] += 8;
return true;
default: default:
if (((type >= 141) && (type <= 147)) || ((type >= 154) && (type <= 182))) {
// Food
player->addScore(50);
return true;
}
break; break;
} }
......
...@@ -142,8 +142,8 @@ ...@@ -142,8 +142,8 @@
#define PYS_SINK ITOF(150) #define PYS_SINK ITOF(150)
#define PYS_JUMP ITOF(-350) #define PYS_JUMP ITOF(-350)
#define PXS_POLE ITOF(3000) #define PXS_POLE ITOF(500)
#define PYS_POLE ITOF(3000) #define PYS_POLE ITOF(500)
#define PYS_SPRING ITOF(-500) #define PYS_SPRING ITOF(-500)
// Player accelerations // Player accelerations
...@@ -198,6 +198,11 @@ class JJ2LevelPlayer : public Movable { ...@@ -198,6 +198,11 @@ class JJ2LevelPlayer : public Movable {
unsigned int fastFeetTime; unsigned int fastFeetTime;
unsigned int stopTime; unsigned int stopTime;
int gems[4]; int gems[4];
int coins;
void centreX ();
void centreY ();
void modify (JJ2Modifier* nextMod, unsigned int ticks);
public: public:
Player* player; Player* player;
...@@ -220,7 +225,6 @@ class JJ2LevelPlayer : public Movable { ...@@ -220,7 +225,6 @@ class JJ2LevelPlayer : public Movable {
JJ2PlayerReaction reacted (unsigned int ticks); JJ2PlayerReaction reacted (unsigned int ticks);
void setPosition (fixed newX, fixed newY); void setPosition (fixed newX, fixed newY);
void setSpeed (fixed newDx, fixed newDy); void setSpeed (fixed newDx, fixed newDy);
bool takeEvent (JJ2Event* event, unsigned int ticks);
bool touchEvent (JJ2Event* touched, unsigned int ticks, int msps); bool touchEvent (JJ2Event* touched, unsigned int ticks, int msps);
void send (unsigned char* buffer); void send (unsigned char* buffer);
......
...@@ -38,37 +38,178 @@ ...@@ -38,37 +38,178 @@
#include "jj2level/jj2level.h" #include "jj2level/jj2level.h"
#include "util.h" #include "util.h"
void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
JJ2Modifier* nextMod; void JJ2LevelPlayer::modify (JJ2Modifier* nextMod, unsigned int ticks) {
bool drop, platform;
switch (nextMod->type) {
case 2: // Spikes
nextMod = jj2Level->getModifier(FTOT(x + PXO_MID), FTOT(y + PYO_MID)); if (jj2Level->checkMaskDown(x + PXO_MID, y + F1, false))
hit(NULL, ticks);
break;
case 4: // Hook
dx = 0;
break;
case 6: // H-pole
if (!stopTime) {
// Catch player
if (nextMod != mod) {
centreX();
centreY();
stopTime = ticks + 1000;
}
} else if (ticks > stopTime) {
dx = (dx > 0) ? PXS_POLE: -PXS_POLE;
stopTime = 0;
}
break;
case 7: // V-pole
if (!stopTime) {
// Catch player
if (nextMod != mod) {
centreX();
centreY();
stopTime = ticks + 1000;
}
} else if (ticks > stopTime) {
if (dy < 0) {
throwY = y - TTOF(16);
dy = -PYS_POLE;
} else {
dy = PYS_POLE;
}
stopTime = 0;
}
break;
case 8: // Fly off
floating = false;
break;
case 17: // End of level
case 18: // 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 206: // Sucker tube
dx = (nextMod->properties & 0x40) ? -((nextMod->properties << 15) & 0x1F8000): ((nextMod->properties << 15) & 0x1F8000);
dy = (nextMod->properties & 0x2000) ? -((nextMod->properties << 8) & 0x1F8000): ((nextMod->properties << 8) & 0x1F8000);
if (dx) centreY();
if (dy) centreX();
break;
case 230: // Warp
if (!stopTime) {
// Catch player
if (coins >= ((nextMod->properties >> 8) & 255)) stopTime = ticks + 1000;
} else if (ticks > stopTime) {
coins -= (nextMod->properties >> 8) & 255;
jj2Level->warp(this, nextMod->properties & 255);
stopTime = 0;
}
break;
default:
stopTime = 0;
break;
}
mod = nextMod;
return;
}
void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
JJ2Modifier* nextMod;
bool drop, platform;
// Respond to controls, unless the player has been killed // Respond to controls, unless the player has been killed
// If the player has been killed, drop but otherwise do not move // If the player has been killed, do not move
if (!energy) { if (!energy) {
dx = 0; dx = 0;
dy = 0;
if (floating) dy = 0;
else {
dy += PYA_GRAVITY * msps;
if (dy > PYS_FALL) dy = PYS_FALL;
}
animType = facing? PA_RDIE: PA_LDIE; animType = facing? PA_RDIE: PA_LDIE;
return; return;
} }
// Get overlapping modifier
nextMod = jj2Level->getModifier(FTOT(x + PXO_MID), FTOT(y + PYO_MID));
if (stopTime) {
// Can't control player, so just apply modifier
modify(nextMod, ticks);
return;
}
if (player->pcontrols[C_RIGHT]) { if (player->pcontrols[C_RIGHT]) {
// Walk/run right // Walk/run right
...@@ -283,134 +424,8 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) { ...@@ -283,134 +424,8 @@ void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
} }
// Handle modifiers // Apply modifier
modify(nextMod, ticks);
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 {
if (dy < 0) {
throwY = y - TTOF(16);
dy = -PYS_POLE;
} else {
dy = PYS_POLE;
}
stopTime = 0;
}
break;
case 8: // Fly off
floating = false;
break;
case 17: // End of level
case 18: // 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;
// Limit speed // Limit speed
...@@ -540,7 +555,10 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) { ...@@ -540,7 +555,10 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
fixed pdx, pdy; fixed pdx, pdy;
int count; int count;
bool drop; bool drop;
if (stopTime) return;
// Apply as much of the trajectory as possible, without going into the // Apply as much of the trajectory as possible, without going into the
// scenery // scenery
...@@ -723,13 +741,6 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) { ...@@ -723,13 +741,6 @@ void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
if (jj2Level->getStage() == LS_END) return; if (jj2Level->getStage() == LS_END) return;
// Handle spikes
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; return;
} }
...@@ -794,8 +805,8 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) { ...@@ -794,8 +805,8 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) {
// Get position // Get position
drawX = getDrawX(change); drawX = getDrawX(stopTime? 0: change);
drawY = getDrawY(change); drawY = getDrawY(stopTime? 0: change);
// Choose sprite // Choose sprite
...@@ -883,7 +894,9 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) { ...@@ -883,7 +894,9 @@ void JJ2LevelPlayer::draw (unsigned int ticks, int change) {
panelBigFont->showString(player->name, panelBigFont->showString(player->name,
FTOI(drawX + PXO_MID) - (panelBigFont->getStringWidth(player->name) >> 1), FTOI(drawX + PXO_MID) - (panelBigFont->getStringWidth(player->name) >> 1),
FTOI(drawY - F32 - F16)); FTOI(drawY - F32 - F16));
//panelBigFont->showNumber(mod->properties, FTOI(drawX) + 24, FTOI(drawY) + 12);
return; return;
} }
......
...@@ -534,7 +534,7 @@ bool LevelPlayer::takeEvent (unsigned char gridX, unsigned char gridY, unsigned ...@@ -534,7 +534,7 @@ bool LevelPlayer::takeEvent (unsigned char gridX, unsigned char gridY, unsigned
} }
player->addScore(set[E_ADDEDSCORE]); player->addScore(set[E_ADDEDSCORE] * 10);
// Add to player's enemy/item tally // Add to player's enemy/item tally
// If the event hurts and can be killed, it is an enemy // If the event hurts and can be killed, it is an enemy
......
...@@ -241,7 +241,7 @@ bool Player::getControl (int control) { ...@@ -241,7 +241,7 @@ bool Player::getControl (int control) {
void Player::addScore (int addedScore) { void Player::addScore (int addedScore) {
score += addedScore * 10; score += addedScore;
return; 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