Commit 588abf12 authored by alistert's avatar alistert

Added basic support for JJ2 levels.

parent 3abea93d
...@@ -9,6 +9,8 @@ objects = src/bonus/bonus.o \ ...@@ -9,6 +9,8 @@ objects = src/bonus/bonus.o \
src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \ src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \
src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \ src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \
src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \ src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \
src/jj2level/jj2layer.o src/jj2level/jj2level.o \
src/jj2level/jj2levelframe.o src/jj2level/jj2levelload.o \
src/level/event/bridge.o src/level/event/guardians.o \ src/level/event/bridge.o src/level/event/guardians.o \
src/level/event/event.o src/level/event/eventframe.o \ src/level/event/event.o src/level/event/eventframe.o \
src/level/bullet.o src/level/demolevel.o src/level/level.o \ src/level/bullet.o src/level/demolevel.o src/level/level.o \
...@@ -16,14 +18,15 @@ objects = src/bonus/bonus.o \ ...@@ -16,14 +18,15 @@ objects = src/bonus/bonus.o \
src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \ src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \
src/menu/setupmenu.o \ src/menu/setupmenu.o \
src/planet/planet.o \ src/planet/planet.o \
src/player/bird.o src/player/bonusplayer.o src/player/levelplayer.o \ src/player/bird.o src/player/bonusplayer.o src/player/jj2levelplayer.o \
src/player/jj2levelplayerframe.o src/player/levelplayer.o \
src/player/levelplayerframe.o src/player/player.o \ src/player/levelplayerframe.o src/player/player.o \
src/scene/scene.o src/scene/sceneload.o \ src/scene/scene.o src/scene/sceneload.o \
src/baselevel.o src/main.o src/util.o src/baselevel.o src/main.o src/util.o
OpenJazz: $(objects) OpenJazz: $(objects)
cc -Wall -o OpenJazz -lSDL -lstdc++ $(objects) cc -Wall -o OpenJazz -lSDL -lstdc++ -lz $(objects)
%.o: %.cpp %.o: %.cpp
cc -Wall -DUSE_SOCKETS -DSCALE -Isrc -O2 -c $< -o $@ cc -Wall -DUSE_SOCKETS -DSCALE -Isrc -O2 -c $< -o $@
......
...@@ -33,6 +33,8 @@ OBJS = src/bonus/bonus.o \ ...@@ -33,6 +33,8 @@ OBJS = src/bonus/bonus.o \
src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \ src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \
src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \ src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \
src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \ src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \
src/jj2level/jj2layer.o src/jj2level/jj2level.o \
src/jj2level/jj2levelframe.o src/jj2level/jj2levelload.o \
src/level/event/bridge.o src/level/event/guardians.o \ src/level/event/bridge.o src/level/event/guardians.o \
src/level/event/event.o src/level/event/eventframe.o \ src/level/event/event.o src/level/event/eventframe.o \
src/level/bullet.o src/level/demolevel.o src/level/level.o \ src/level/bullet.o src/level/demolevel.o src/level/level.o \
...@@ -40,7 +42,8 @@ OBJS = src/bonus/bonus.o \ ...@@ -40,7 +42,8 @@ OBJS = src/bonus/bonus.o \
src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \ src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \
src/menu/setupmenu.o \ src/menu/setupmenu.o \
src/planet/planet.o \ src/planet/planet.o \
src/player/bird.o src/player/bonusplayer.o src/player/levelplayer.o \ src/player/bird.o src/player/bonusplayer.o src/player/jj2levelplayer.o \
src/player/jj2levelplayerframe.o src/player/levelplayer.o \
src/player/levelplayerframe.o src/player/player.o \ src/player/levelplayerframe.o src/player/player.o \
src/scene/scene.o src/scene/sceneload.o \ src/scene/scene.o src/scene/sceneload.o \
src/baselevel.o src/main.o src/util.o src/baselevel.o src/main.o src/util.o
...@@ -68,7 +71,7 @@ endif ...@@ -68,7 +71,7 @@ endif
endif endif
CXXFLAGS += -g -Wall -O3 -fsigned-char -DUSE_SOCKETS -I$(PREFIX)/include -I$(PREFIX)/include/SDL -Isrc CXXFLAGS += -g -Wall -O3 -fsigned-char -DUSE_SOCKETS -I$(PREFIX)/include -I$(PREFIX)/include/SDL -Isrc
LDFLAGS += -L$(PREFIX)/lib -lSDL LDFLAGS += -L$(PREFIX)/lib -lSDL -lz
# Uncomment the following two lines for music (requires libmodplug) # Uncomment the following two lines for music (requires libmodplug)
CXXFLAGS += -DUSE_MODPLUG -I$(PREFIX)/include/libmodplug CXXFLAGS += -DUSE_MODPLUG -I$(PREFIX)/include/libmodplug
......
...@@ -9,6 +9,8 @@ objects = src/bonus/bonus.o \ ...@@ -9,6 +9,8 @@ objects = src/bonus/bonus.o \
src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \ src/io/gfx/scale2x/scale2x.o src/io/gfx/scale2x/scale3x.o \
src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \ src/io/gfx/scale2x/scalebit.o src/io/gfx/scale2x/simple2x.o \
src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \ src/io/controls.o src/io/file.o src/io/network.o src/io/sound.o \
src/jj2level/jj2layer.o src/jj2level/jj2level.o \
src/jj2level/jj2levelframe.o src/jj2level/jj2levelload.o \
src/level/event/bridge.o src/level/event/guardians.o \ src/level/event/bridge.o src/level/event/guardians.o \
src/level/event/event.o src/level/event/eventframe.o \ src/level/event/event.o src/level/event/eventframe.o \
src/level/bullet.o src/level/demolevel.o src/level/level.o \ src/level/bullet.o src/level/demolevel.o src/level/level.o \
...@@ -16,7 +18,8 @@ objects = src/bonus/bonus.o \ ...@@ -16,7 +18,8 @@ objects = src/bonus/bonus.o \
src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \ src/menu/gamemenu.o src/menu/mainmenu.o src/menu/menu.o \
src/menu/setupmenu.o \ src/menu/setupmenu.o \
src/planet/planet.o \ src/planet/planet.o \
src/player/bird.o src/player/bonusplayer.o src/player/levelplayer.o \ src/player/bird.o src/player/bonusplayer.o src/player/jj2levelplayer.o \
src/player/jj2levelplayerframe.o src/player/levelplayer.o \
src/player/levelplayerframe.o src/player/player.o \ src/player/levelplayerframe.o src/player/player.o \
src/scene/scene.o src/scene/sceneload.o \ src/scene/scene.o src/scene/sceneload.o \
src/baselevel.o src/main.o src/util.o src/baselevel.o src/main.o src/util.o
...@@ -29,7 +32,7 @@ CXXFLAGS += -g -Wall -O2 -DUSE_SOCKETS -DSCALE ...@@ -29,7 +32,7 @@ CXXFLAGS += -g -Wall -O2 -DUSE_SOCKETS -DSCALE
#LDFLAGS += `pkg-config --libs libmodplug` #LDFLAGS += `pkg-config --libs libmodplug`
OpenJazz: $(objects) OpenJazz: $(objects)
cc $(CXXFLAGS) -o OpenJazz $(LDFLAGS) -lSDL -lstdc++ $(objects) cc $(CXXFLAGS) -o OpenJazz $(LDFLAGS) -lSDL -lstdc++ -lz $(objects)
%.o: %.cpp %.o: %.cpp
cc $(CXXFLAGS) -Isrc -c $< -o $@ cc $(CXXFLAGS) -Isrc -c $< -o $@
......
...@@ -27,14 +27,17 @@ ...@@ -27,14 +27,17 @@
#include "game/game.h" #include "game/game.h"
#include "io/controls.h"
#include "io/gfx/font.h" #include "io/gfx/font.h"
#include "io/gfx/paletteeffects.h" #include "io/gfx/paletteeffects.h"
#include "io/gfx/sprite.h" #include "io/gfx/sprite.h"
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/sound.h" #include "io/sound.h"
#include "menu/menu.h"
#include "player/player.h" #include "player/player.h"
#include "scene/scene.h" #include "scene/scene.h"
#include "baselevel.h" #include "baselevel.h"
#include "loop.h"
BaseLevel::BaseLevel () { BaseLevel::BaseLevel () {
...@@ -49,6 +52,8 @@ BaseLevel::BaseLevel () { ...@@ -49,6 +52,8 @@ BaseLevel::BaseLevel () {
// Set the level stage // Set the level stage
stage = LS_NORMAL; stage = LS_NORMAL;
stats = 0;
return; return;
} }
...@@ -141,7 +146,7 @@ void BaseLevel::timeCalcs () { ...@@ -141,7 +146,7 @@ void BaseLevel::timeCalcs () {
} }
void BaseLevel::drawStats (int stats, unsigned char bg) { void BaseLevel::drawStats (unsigned char bg) {
int count, width; int count, width;
...@@ -204,6 +209,112 @@ void BaseLevel::drawStats (int stats, unsigned char bg) { ...@@ -204,6 +209,112 @@ void BaseLevel::drawStats (int stats, unsigned char bg) {
} }
int BaseLevel::loop (bool& menu, int& option, bool& message) {
int ret;
// Networking
if (gameMode) {
ret = game->step(ticks);
switch (ret) {
case E_UNUSED:
return E_NONE;
case E_NONE:
break;
default:
return ret;
}
}
// Main loop
if (::loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT;
if (controls.release(C_ESCAPE)) {
menu = !menu;
option = 0;
}
if (controls.release(C_PAUSE)) message = !message;
if (controls.release(C_STATS)) {
if (!gameMode) stats ^= S_SCREEN;
else stats = (stats + 1) & 3;
}
if (menu) {
// Deal with menu controls
if (controls.release(C_UP)) option = (option + 4) % 5;
if (controls.release(C_DOWN)) option = (option + 1) % 5;
if (controls.release(C_ENTER)) {
switch (option) {
case 0: // Continue
menu = false;
break;
case 1: // Save
break;
case 2: // Load
break;
case 3: // Setup
if (!gameMode) {
if (setupMenu.setup() == E_QUIT) return E_QUIT;
// Restore level palette
video.setPalette(palette);
}
break;
case 4: // Quit game
return E_NONE;
}
}
}
if (!gameMode) paused = message || menu;
timeCalcs();
return 1;
}
void BaseLevel::addTimer () { void BaseLevel::addTimer () {
unsigned char buffer[MTL_L_PROP]; unsigned char buffer[MTL_L_PROP];
...@@ -228,3 +339,32 @@ void BaseLevel::addTimer () { ...@@ -228,3 +339,32 @@ void BaseLevel::addTimer () {
} }
void BaseLevel::setStage (LevelStage newStage) {
unsigned char buffer[MTL_L_STAGE];
if (stage == newStage) return;
stage = newStage;
if (gameMode) {
buffer[0] = MTL_L_STAGE;
buffer[1] = MT_L_STAGE;
buffer[2] = stage;
game->send(buffer);
}
return;
}
LevelStage BaseLevel::getStage () {
return stage;
}
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
#include "io/gfx/paletteeffects.h" #include "io/gfx/paletteeffects.h"
#include "menu/menu.h"
#include <SDL/SDL.h>
// Macros // Macros
...@@ -40,6 +39,12 @@ ...@@ -40,6 +39,12 @@
// Enums // Enums
enum LevelType {
LT_LEVEL, LT_BONUS, LT_JJ2LEVEL
};
enum LevelStats { enum LevelStats {
S_PLAYERS = 1, S_SCREEN = 2 S_PLAYERS = 1, S_SCREEN = 2
...@@ -60,6 +65,9 @@ class Sprite; ...@@ -60,6 +65,9 @@ class Sprite;
class BaseLevel { class BaseLevel {
private:
SetupMenu setupMenu;
protected: protected:
SDL_Surface* tileSet; SDL_Surface* tileSet;
Sprite* spriteSet; Sprite* spriteSet;
...@@ -72,18 +80,29 @@ class BaseLevel { ...@@ -72,18 +80,29 @@ class BaseLevel {
int items; int items;
bool paused; bool paused;
LevelStage stage; LevelStage stage;
int stats;
int playScene (char* file); int playScene (char* file);
void timeCalcs (); void timeCalcs ();
void drawStats (int stats, unsigned char bg); void drawStats (unsigned char bg);
int loop (bool& menu, int& option, bool& message);
public: public:
BaseLevel (); BaseLevel ();
~BaseLevel (); virtual ~BaseLevel ();
void addTimer (); void addTimer ();
LevelStage getStage ();
void setStage (LevelStage stage);
virtual void receive (unsigned char* buffer) = 0;
}; };
// Variables
EXTERN BaseLevel* baseLevel;
EXTERN fixed viewX, viewY;
#endif #endif
...@@ -36,9 +36,7 @@ ...@@ -36,9 +36,7 @@
#include "io/gfx/sprite.h" #include "io/gfx/sprite.h"
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/sound.h" #include "io/sound.h"
#include "menu/menu.h"
#include "player/bonusplayer.h" #include "player/bonusplayer.h"
#include "loop.h"
#include "util.h" #include "util.h"
#include <string.h> #include <string.h>
...@@ -335,11 +333,11 @@ Bonus::Bonus (char * fileName, unsigned char diff) { ...@@ -335,11 +333,11 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
game->setCheckpoint(x, y); game->setCheckpoint(x, y);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, true, string); for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_BONUS, string);
} else { } else {
localPlayer->reset(true, string, x, y); localPlayer->reset(LT_BONUS, string, x, y);
} }
...@@ -352,9 +350,6 @@ Bonus::Bonus (char * fileName, unsigned char diff) { ...@@ -352,9 +350,6 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
// Palette animations // Palette animations
// Free any existing palette effects
if (paletteEffects) delete paletteEffects;
// Spinny whirly thing // Spinny whirly thing
paletteEffects = new RotatePaletteEffect(112, 16, F32, NULL); paletteEffects = new RotatePaletteEffect(112, 16, F32, NULL);
...@@ -409,6 +404,44 @@ bool Bonus::checkMask (fixed x, fixed y) { ...@@ -409,6 +404,44 @@ bool Bonus::checkMask (fixed x, fixed y) {
} }
void Bonus::receive (unsigned char* buffer) {
// Interpret data received from client/server
switch (buffer[1]) {
case MT_L_PROP:
if (buffer[2] == 2) {
if (stage == LS_NORMAL)
endTime += 2 * 60 * 1000; // 2 minutes. Is this right?
}
break;
case MT_L_GRID:
if (buffer[4] == 0) grid[buffer[3]][buffer[2]].tile = buffer[5];
else if (buffer[4] == 2)
grid[buffer[3]][buffer[2]].event = buffer[5];
break;
case MT_L_STAGE:
stage = LevelStage(buffer[2]);
break;
}
return;
}
int Bonus::step () { int Bonus::step () {
BonusPlayer* bonusPlayer; BonusPlayer* bonusPlayer;
...@@ -659,10 +692,10 @@ void Bonus::draw () { ...@@ -659,10 +692,10 @@ void Bonus::draw () {
int Bonus::play () { int Bonus::play () {
SetupMenu setupMenu; const char* options[5] =
const char *options[3] = {"continue game", "setup options", "quit game"}; {"continue game", "save game", "load game", "setup options", "quit game"};
bool pmenu, pmessage; bool pmenu, pmessage;
int stats, option; int option;
unsigned int returnTime; unsigned int returnTime;
int count; int count;
...@@ -673,7 +706,6 @@ int Bonus::play () { ...@@ -673,7 +706,6 @@ int Bonus::play () {
pmessage = pmenu = false; pmessage = pmenu = false;
option = 0; option = 0;
stats = 0;
returnTime = 0; returnTime = 0;
...@@ -681,68 +713,9 @@ int Bonus::play () { ...@@ -681,68 +713,9 @@ int Bonus::play () {
while (true) { while (true) {
if (loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT; count = loop(pmenu, option, pmessage);
if (controls.release(C_ESCAPE)) {
pmenu = !pmenu;
option = 0;
}
if (controls.release(C_PAUSE)) pmessage = !pmessage;
if (controls.release(C_STATS)) {
if (!gameMode) stats ^= S_SCREEN;
else stats = (stats + 1) & 3;
}
if (pmenu) {
// Deal with menu controls
if (controls.release(C_UP)) option = (option + 2) % 3;
if (controls.release(C_DOWN)) option = (option + 1) % 3;
if (controls.release(C_ENTER)) {
switch (option) {
case 0: // Continue
pmenu = false;
break;
case 1: // Setup
if (!gameMode) {
if (setupMenu.setup() == E_QUIT) return E_QUIT;
// Restore level palette
video.setPalette(palette);
}
break;
case 2: // Quit game
return E_NONE;
}
}
}
if (!gameMode) paused = pmessage || pmenu;
timeCalcs(); if (count <= 0) return count;
// Check if level has been won // Check if level has been won
...@@ -791,7 +764,7 @@ int Bonus::play () { ...@@ -791,7 +764,7 @@ int Bonus::play () {
font->showString("pause", (canvasW >> 1) - 44, 32); font->showString("pause", (canvasW >> 1) - 44, 32);
// Draw statistics // Draw statistics
drawStats(stats, 0); drawStats(0);
// Draw the menu // Draw the menu
if (pmenu) { if (pmenu) {
......
...@@ -75,6 +75,7 @@ class Bonus : public BaseLevel { ...@@ -75,6 +75,7 @@ class Bonus : public BaseLevel {
~Bonus (); ~Bonus ();
bool checkMask (fixed x, fixed y); bool checkMask (fixed x, fixed y);
void receive (unsigned char* buffer);
int play (); int play ();
}; };
......
...@@ -146,8 +146,6 @@ ClientGame::ClientGame (char* address) { ...@@ -146,8 +146,6 @@ ClientGame::ClientGame (char* address) {
// Download the level from the server // Download the level from the server
level = NULL;
levelFile = createString(LEVEL_FILE); levelFile = createString(LEVEL_FILE);
file = NULL; file = NULL;
...@@ -398,7 +396,7 @@ int ClientGame::step (unsigned int ticks) { ...@@ -398,7 +396,7 @@ int ClientGame::step (unsigned int ticks) {
players[count].init((char *)recvBuffer + 9, players[count].init((char *)recvBuffer + 9,
recvBuffer + 5, recvBuffer[4]); recvBuffer + 5, recvBuffer[4]);
resetPlayer(players + count, false, NULL); resetPlayer(players + count, LT_LEVEL, NULL);
printf("Player %d joined team %d.\n", count, recvBuffer[4]); printf("Player %d joined team %d.\n", count, recvBuffer[4]);
...@@ -452,7 +450,7 @@ int ClientGame::step (unsigned int ticks) { ...@@ -452,7 +450,7 @@ int ClientGame::step (unsigned int ticks) {
case MC_LEVEL: case MC_LEVEL:
if (level) level->receive(recvBuffer); if (baseLevel) baseLevel->receive(recvBuffer);
break; break;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "io/gfx/font.h" #include "io/gfx/font.h"
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/sound.h" #include "io/sound.h"
#include "jj2level/jj2level.h"
#include "level/level.h" #include "level/level.h"
#include "planet/planet.h" #include "planet/planet.h"
#include "player/bonusplayer.h" #include "player/bonusplayer.h"
...@@ -115,11 +116,11 @@ int Game::play () { ...@@ -115,11 +116,11 @@ int Game::play () {
// Load and play the level // Load and play the level
if (!strncmp(levelFile, F_BONUSMAP, 8)) { if (!strncasecmp(levelFile, F_BONUSMAP, 8)) {
try { try {
bonus = new Bonus(levelFile, difficulty); baseLevel = bonus = new Bonus(levelFile, difficulty);
} catch (int e) { } catch (int e) {
...@@ -132,6 +133,7 @@ int Game::play () { ...@@ -132,6 +133,7 @@ int Game::play () {
if (ret <= 0) { if (ret <= 0) {
delete bonus; delete bonus;
baseLevel = NULL;
if (ret == E_NONE) playMusic("menusng.psm"); if (ret == E_NONE) playMusic("menusng.psm");
...@@ -147,12 +149,58 @@ int Game::play () { ...@@ -147,12 +149,58 @@ int Game::play () {
} }
delete bonus; delete bonus;
baseLevel = NULL;
} else if (!strcasecmp(levelFile + strlen(levelFile) - 4, ".j2l")) {
try {
baseLevel = jj2Level = new JJ2Level(levelFile, difficulty, checkpoint);
} catch (int e) {
return e;
}
ret = jj2Level->play();
if (ret <= 0) {
delete jj2Level;
baseLevel = jj2Level = NULL;
if (ret == E_NONE) playMusic("menusng.psm");
return ret;
} else if (ret == WON) {
// Won the level
// Do not use old level's checkpoint coordinates
checkpoint = false;
} else {
// Lost the level
if (!localPlayer->getLives()) return E_NONE;
// Use checkpoint coordinates
checkpoint = true;
}
delete jj2Level;
baseLevel = jj2Level = NULL;
} else { } else {
try { try {
level = new Level(levelFile, difficulty, checkpoint); baseLevel = level = new Level(levelFile, difficulty, checkpoint);
} catch (int e) { } catch (int e) {
...@@ -197,6 +245,7 @@ int Game::play () { ...@@ -197,6 +245,7 @@ int Game::play () {
if (ret <= 0) { if (ret <= 0) {
delete level; delete level;
baseLevel = level = NULL;
if (ret == E_NONE) playMusic("menusng.psm"); if (ret == E_NONE) playMusic("menusng.psm");
...@@ -222,6 +271,7 @@ int Game::play () { ...@@ -222,6 +271,7 @@ int Game::play () {
} }
delete level; delete level;
baseLevel = level = NULL;
} }
...@@ -284,7 +334,7 @@ void Game::setCheckpoint (unsigned char gridX, unsigned char gridY) { ...@@ -284,7 +334,7 @@ void Game::setCheckpoint (unsigned char gridX, unsigned char gridY) {
} }
void Game::resetPlayer (LevelPlayer *player) { void Game::resetPlayer (Player *player) {
player->reset(checkX, checkY); player->reset(checkX, checkY);
...@@ -293,9 +343,9 @@ void Game::resetPlayer (LevelPlayer *player) { ...@@ -293,9 +343,9 @@ void Game::resetPlayer (LevelPlayer *player) {
} }
void Game::resetPlayer (Player *player, bool bonus, char* anims) { void Game::resetPlayer (Player *player, LevelType levelType, char* anims) {
player->reset(bonus, anims, checkX, checkY); player->reset(levelType, anims, checkX, checkY);
return; return;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "gamemode.h" #include "gamemode.h"
#include "baselevel.h"
#include "io/network.h" #include "io/network.h"
...@@ -80,7 +81,6 @@ ...@@ -80,7 +81,6 @@
// Classes // Classes
class File; class File;
class Player;
class Game { class Game {
...@@ -103,8 +103,8 @@ class Game { ...@@ -103,8 +103,8 @@ class Game {
virtual int step (unsigned int ticks); virtual int step (unsigned int ticks);
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 (LevelPlayer *player); void resetPlayer (Player *player);
void resetPlayer (Player *player, bool bonus, char* anims); void resetPlayer (Player *player, LevelType levelType, char* anims);
}; };
......
...@@ -28,27 +28,27 @@ ...@@ -28,27 +28,27 @@
#include "player/levelplayer.h" #include "player/levelplayer.h"
bool GameMode::hit (LevelPlayer *source, LevelPlayer *victim) { bool GameMode::hit (Player *source, Player *victim) {
return true; return true;
} }
bool GameMode::kill (LevelPlayer *source, LevelPlayer *victim) { bool GameMode::kill (Player *source, Player *victim) {
if (source && (victim->player == localPlayer)) game->score(source->player->getTeam()); if (source && (victim == localPlayer)) game->score(source->getTeam());
return true; return true;
} }
bool GameMode::endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY) { bool GameMode::endOfLevel (Player *player, unsigned char gridX, unsigned char gridY) {
game->setCheckpoint(gridX, gridY); game->setCheckpoint(gridX, gridY);
level->setStage(LS_END); baseLevel->setStage(LS_END);
return true; return true;
...@@ -153,11 +153,11 @@ GameModeType CoopGameMode::getMode () { ...@@ -153,11 +153,11 @@ GameModeType CoopGameMode::getMode () {
} }
bool CoopGameMode::endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY) { bool CoopGameMode::endOfLevel (Player *player, unsigned char gridX, unsigned char gridY) {
game->setCheckpoint(gridX, gridY); game->setCheckpoint(gridX, gridY);
level->setStage(LS_END); baseLevel->setStage(LS_END);
return true; return true;
...@@ -185,16 +185,16 @@ GameModeType RaceGameMode::getMode () { ...@@ -185,16 +185,16 @@ GameModeType RaceGameMode::getMode () {
} }
bool RaceGameMode::hit (LevelPlayer *source, LevelPlayer *victim) { bool RaceGameMode::hit (Player *source, Player *victim) {
return false; return false;
} }
bool RaceGameMode::endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY) { bool RaceGameMode::endOfLevel (Player *player, unsigned char gridX, unsigned char gridY) {
if (player->player == localPlayer) game->score(localPlayer->getTeam()); if (player == localPlayer) game->score(localPlayer->getTeam());
game->resetPlayer(player); game->resetPlayer(player);
......
...@@ -44,7 +44,7 @@ enum GameModeType { ...@@ -44,7 +44,7 @@ enum GameModeType {
// Classes // Classes
class Font; class Font;
class LevelPlayer; class Player;
class GameMode { class GameMode {
...@@ -52,9 +52,9 @@ class GameMode { ...@@ -52,9 +52,9 @@ class GameMode {
virtual GameModeType getMode () = 0; virtual GameModeType getMode () = 0;
virtual unsigned char chooseTeam () = 0; virtual unsigned char chooseTeam () = 0;
virtual void drawScore (Font* font) = 0; virtual void drawScore (Font* font) = 0;
virtual bool hit (LevelPlayer *source, LevelPlayer *victim); virtual bool hit (Player *source, Player *victim);
virtual bool kill (LevelPlayer *source, LevelPlayer *victim); virtual bool kill (Player *source, Player *victim);
virtual bool endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY); virtual bool endOfLevel (Player *player, unsigned char gridX, unsigned char gridY);
virtual void outOfTime (); virtual void outOfTime ();
}; };
...@@ -87,7 +87,7 @@ class CoopGameMode : public CooperativeGameMode { ...@@ -87,7 +87,7 @@ class CoopGameMode : public CooperativeGameMode {
public: public:
GameModeType getMode (); GameModeType getMode ();
bool endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY); bool endOfLevel (Player *player, unsigned char gridX, unsigned char gridY);
}; };
...@@ -118,8 +118,8 @@ class RaceGameMode : public FreeForAllGameMode { ...@@ -118,8 +118,8 @@ class RaceGameMode : public FreeForAllGameMode {
public: public:
GameModeType getMode (); GameModeType getMode ();
bool hit (LevelPlayer *source, LevelPlayer *victim); bool hit (Player *source, Player *victim);
bool endOfLevel (LevelPlayer *player, unsigned char gridX, unsigned char gridY); bool endOfLevel (Player *player, unsigned char gridX, unsigned char gridY);
}; };
......
...@@ -257,12 +257,11 @@ int ServerGame::step (unsigned int ticks) { ...@@ -257,12 +257,11 @@ int ServerGame::step (unsigned int ticks) {
players[nPlayers].init((char *)(recvBuffers[count]) + 9, players[nPlayers].init((char *)(recvBuffers[count]) + 9,
recvBuffers[count] + 5, recvBuffers[count][4]); recvBuffers[count] + 5, recvBuffers[count][4]);
resetPlayer(players + nPlayers, false, NULL); resetPlayer(players + nPlayers, LT_LEVEL, NULL);
printf("Player %d joined team %d.\n", nPlayers, recvBuffers[count][4]); printf("Player %d joined team %d.\n", nPlayers, recvBuffers[count][4]);
recvBuffers[count][3] = clientPlayer[count] = recvBuffers[count][3] = clientPlayer[count] = nPlayers;
nPlayers;
nPlayers++; nPlayers++;
...@@ -279,8 +278,7 @@ int ServerGame::step (unsigned int ticks) { ...@@ -279,8 +278,7 @@ int ServerGame::step (unsigned int ticks) {
for (pcount = 0; pcount < nPlayers; pcount++) { for (pcount = 0; pcount < nPlayers; pcount++) {
if (players[pcount].getTeam() == if (players[pcount].getTeam() == recvBuffers[count][2])
recvBuffers[count][2])
players[pcount].teamScore++; players[pcount].teamScore++;
} }
...@@ -291,7 +289,7 @@ int ServerGame::step (unsigned int ticks) { ...@@ -291,7 +289,7 @@ int ServerGame::step (unsigned int ticks) {
case MC_LEVEL: case MC_LEVEL:
level->receive(recvBuffers[count]); baseLevel->receive(recvBuffers[count]);
break; break;
...@@ -364,14 +362,13 @@ int ServerGame::step (unsigned int ticks) { ...@@ -364,14 +362,13 @@ int ServerGame::step (unsigned int ticks) {
for (pcount = 0; pcount < nPlayers; pcount++) { for (pcount = 0; pcount < nPlayers; pcount++) {
sendBuffer[0] = MTL_G_PJOIN + sendBuffer[0] = MTL_G_PJOIN + strlen(players[pcount].getName());
strlen(players[pcount].getName());
sendBuffer[2] = count; sendBuffer[2] = count;
sendBuffer[3] = pcount; sendBuffer[3] = pcount;
sendBuffer[4] = players[pcount].getTeam(); sendBuffer[4] = players[pcount].getTeam();
memcpy(sendBuffer + 5, players[pcount].getCols(), 4); memcpy(sendBuffer + 5, players[pcount].getCols(), PCOLOURS);
memcpy(sendBuffer + 9, players[pcount].getName(), memcpy(sendBuffer + 9, players[pcount].getName(), strlen(players[pcount].getName()) + 1);
strlen(players[pcount].getName()) + 1);
net->send(clientSock[count], sendBuffer); net->send(clientSock[count], sendBuffer);
} }
...@@ -402,10 +399,8 @@ int ServerGame::step (unsigned int ticks) { ...@@ -402,10 +399,8 @@ int ServerGame::step (unsigned int ticks) {
players[clientPlayer[count]].deinit(); players[clientPlayer[count]].deinit();
// If necessary, move more recent players // If necessary, move more recent players
for (pcount = clientPlayer[count]; pcount < nPlayers; for (pcount = clientPlayer[count]; pcount < nPlayers; pcount++)
pcount++) memcpy(players + pcount, players + pcount + 1, sizeof(Player));
memcpy(players + pcount, players + pcount + 1,
sizeof(Player));
// Clear duplicate pointers // Clear duplicate pointers
memset(players + nPlayers, 0, sizeof(Player)); memset(players + nPlayers, 0, sizeof(Player));
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "util.h" #include "util.h"
#include <string.h> #include <string.h>
#include <zlib.h>
File::File (const char* name, bool write) { File::File (const char* name, bool write) {
...@@ -284,6 +285,24 @@ void File::skipRLE () { ...@@ -284,6 +285,24 @@ void File::skipRLE () {
} }
unsigned char* File::loadLZ (int compressedLength, int length) {
unsigned char* compressedBuffer;
unsigned char* buffer;
compressedBuffer = loadBlock(compressedLength);
buffer = new unsigned char[length];
uncompress(buffer, (unsigned long int *)&length, compressedBuffer, compressedLength);
delete[] compressedBuffer;
return buffer;
}
char * File::loadString () { char * File::loadString () {
char *string; char *string;
......
...@@ -56,6 +56,7 @@ class File { ...@@ -56,6 +56,7 @@ class File {
unsigned char* loadBlock (int length); unsigned char* loadBlock (int length);
unsigned char* loadRLE (int length); unsigned char* loadRLE (int length);
void skipRLE (); void skipRLE ();
unsigned char* loadLZ (int compressedLength, int length);
char* loadString (); char* loadString ();
SDL_Surface* loadSurface (int width, int height); SDL_Surface* loadSurface (int width, int height);
unsigned char* loadPixels (int length); unsigned char* loadPixels (int length);
......
...@@ -24,7 +24,9 @@ ...@@ -24,7 +24,9 @@
#include "paletteeffects.h" #include "paletteeffects.h"
#include "video.h" #include "video.h"
#include "jj2level/jj2level.h"
#include "level/level.h" #include "level/level.h"
#include "player/jj2levelplayer.h"
#include "player/levelplayer.h" #include "player/levelplayer.h"
#include <string.h> #include <string.h>
...@@ -527,7 +529,10 @@ void WaterPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) ...@@ -527,7 +529,10 @@ void WaterPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf)
currentPalette = video.getPalette(); currentPalette = video.getPalette();
position = localPlayer->getLevelPlayer()->getY() - level->getWaterLevel();
if (level) position = localPlayer->getLevelPlayer()->getY() - level->getWaterLevel();
else if (jj2Level) position = localPlayer->getJJ2LevelPlayer()->getY() - jj2Level->getWaterLevel();
else return;
if (position <= 0) return; if (position <= 0) return;
......
/*
*
* jj2layer.cpp
*
* 30th June 2010: Created jj2layer.cpp from parts of jj2levelframe.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Handles JJ2 level layers.
*
*/
#include "jj2level.h"
#include "io/gfx/video.h"
JJ2Layer::JJ2Layer () {
// Create a blank layer
width = height = 1;
grid = new JJ2GridElement *[1];
*(grid) = new JJ2GridElement[1];
(*grid)->tile = 0;
return;
}
JJ2Layer::JJ2Layer (int newWidth, int newHeight) {
int row;
width = newWidth;
height = newHeight;
grid = new JJ2GridElement *[height];
*(grid) = new JJ2GridElement[width * height];
for (row = 0; row < height; row++) grid[row] = *(grid) + (row * width);
return;
}
JJ2Layer::~JJ2Layer () {
delete[] *(grid);
delete[] grid;
return;
}
int JJ2Layer::getHeight () {
return height;
}
int JJ2Layer::getTile (int x, int y) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0;
return grid[y][x].tile;
}
int JJ2Layer::getWidth () {
return width;
}
void JJ2Layer::draw (SDL_Surface* tileSet) {
SDL_Rect src, dst;
int vX, vY;
int x, y;
// Set tile drawing dimensions
src.w = TTOI(1);
src.h = TTOI(1);
src.x = 0;
// Calculate the layer view
if (width <= 30) {
vX = 0;
vY = 0;
} else {
vX = FTOI(viewX);
vY = FTOI(viewY);
}
for (y = 0; y <= ITOT(viewH - 1) + 1; y++) {
for (x = 0; x <= ITOT(viewW - 1) + 1; x++) {
dst.x = TTOI(x) - (vX & 31);
dst.y = TTOI(y) - (vY & 31);
src.y = TTOI(getTile(x + ITOT(vX), y + ITOT(vY)));
if (src.y) SDL_BlitSurface(tileSet, &src, canvas, &dst);
}
}
return;
}
/*
*
* jj2level.cpp
*
* 29th June 2010: Created jj2level.cpp from parts of level.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Deals with the creating, playing and freeing of levels.
*
*/
#include "jj2level.h"
#include "game/game.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/file.h"
#include "io/gfx/font.h"
#include "io/gfx/paletteeffects.h"
#include "io/gfx/sprite.h"
#include "io/gfx/video.h"
#include "io/sound.h"
#include "player/jj2levelplayer.h"
#include "scene/scene.h"
#include "util.h"
#include <string.h>
JJ2Level::JJ2Level (char* fileName, unsigned char diff, bool checkpoint) {
int ret;
// Load level data
ret = load(fileName, diff, checkpoint);
if (ret < 0) throw ret;
return;
}
JJ2Level::~JJ2Level () {
int count;
for (count = 0; count < LAYERS; count++) delete layers[count];
delete[] mask;
delete[] musicFile;
delete[] nextLevel;
delete font;
// Restore panel font palette
panelBigFont->restorePalette();
panelSmallFont->restorePalette();
return;
}
bool JJ2Level::checkMaskUp (fixed x, fixed y) {
JJ2GridElement *ge;
// Anything off the edge of the map is solid
if ((x < 0) || (y < 0) || (x >= TTOF(layers[3]->getWidth())) || (y >= TTOF(layers[3]->getHeight())))
return true;
ge = layers[3]->grid[FTOT(y)] + FTOT(x);
// Event 122 is one-way
//if (ge->event == 122) return false;
// Check the mask in the tile in question
return mask[(ge->tile << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)];
}
bool JJ2Level::checkMaskDown (fixed x, fixed y) {
// Anything off the edge of the map is solid
if ((x < 0) || (y < 0) || (x >= TTOF(layers[3]->getWidth())) || (y >= TTOF(layers[3]->getHeight())))
return true;
// Check the mask in the tile in question
return mask[(layers[3]->grid[FTOT(y)][FTOT(x)].tile << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)];
}
bool JJ2Level::checkSpikes (fixed x, fixed y) {
JJ2GridElement *ge;
// Anything off the edge of the map is not spikes
if ((x < 0) || (y < 0) || (x > TTOF(layers[3]->getWidth())) || (y > TTOF(layers[3]->getHeight())))
return false;
ge = layers[3]->grid[FTOT(y)] + FTOT(x);
// Event 126 is spikes
//if (ge->event != 126) return false;
// Check the mask in the tile in question
//return mask[(ge->tile << 10) + ((y >> 5) & 992) + ((x >> 10) & 31)];
return false;
}
void JJ2Level::setNext (char* fileName) {
unsigned char buffer[MTL_L_PROP];
delete[] nextLevel;
nextLevel = createString(fileName);
if (gameMode) {
buffer[0] = MTL_L_PROP;
buffer[1] = MT_L_PROP;
buffer[2] = 0; // set next level
buffer[3] = 0;
buffer[4] = 0;
game->send(buffer);
}
return;
}
void JJ2Level::setFrame (unsigned char gridX, unsigned char gridY, unsigned char frame) {
unsigned char buffer[MTL_L_GRID];
layers[3]->grid[gridY][gridX].frame = frame;
if (gameMode) {
buffer[0] = MTL_L_GRID;
buffer[1] = MT_L_GRID;
buffer[2] = gridX;
buffer[3] = gridY;
buffer[4] = 0; // tile variable
buffer[5] = frame;
game->send(buffer);
}
return;
}
Sprite* JJ2Level::getSprite (unsigned char sprite) {
return spriteSet + sprite;
}
Anim* JJ2Level::getAnim (unsigned char anim) {
return animSet + anim;
}
void JJ2Level::setWaterLevel (unsigned char gridY) {
unsigned char buffer[MTL_L_PROP];
waterLevelTarget = TTOF(gridY);
if (gameMode) {
buffer[0] = MTL_L_PROP;
buffer[1] = MT_L_PROP;
buffer[2] = 1; // set water level
buffer[3] = gridY;
buffer[4] = 0; // Doesn't really matter
game->send(buffer);
}
return;
}
fixed JJ2Level::getWaterLevel () {
return waterLevel;
}
void JJ2Level::receive (unsigned char* buffer) {
// Interpret data received from client/server
switch (buffer[1]) {
case MT_L_PROP:
if (buffer[2] == 1) {
waterLevelTarget = TTOF(buffer[3]);
} else if (buffer[2] == 2) {
if (stage == LS_NORMAL)
endTime += 2 * 60 * 1000; // 2 minutes. Is this right?
}
break;
case MT_L_GRID:
if (buffer[4] == 0) layers[3]->grid[buffer[3]][buffer[2]].frame = buffer[5];
break;
case MT_L_STAGE:
stage = LevelStage(buffer[2]);
break;
}
return;
}
int JJ2Level::play () {
JJ2LevelPlayer* jj2LevelPlayer;
const char* options[5] =
{"continue game", "save game", "load game", "setup options", "quit game"};
bool pmessage, pmenu;
int option;
unsigned int returnTime;
int count;
jj2LevelPlayer = localPlayer->getJJ2LevelPlayer();
tickOffset = globalTicks;
ticks = 16;
prevStepTicks = 0;
pmessage = pmenu = false;
option = 0;
returnTime = 0;
video.setPalette(palette);
playMusic(musicFile);
while (true) {
count = loop(pmenu, option, pmessage);
if (count <= 0) return count;
// Check if level has been won
if (game && returnTime && (ticks > returnTime)) {
count = game->setLevel(nextLevel);
if (count < 0) return count;
return WON;
}
// Process frame-by-frame activity
if (!paused && (ticks >= prevStepTicks + 16)) {
// Apply controls to local player
for (count = 0; count < PCONTROLS; count++)
localPlayer->setControl(count, controls.getState(count));
count = step();
if (count) return count;
}
// Draw the graphics
draw();
// If paused, draw "PAUSE"
if (pmessage && !pmenu)
font->showString("pause", (canvasW >> 1) - 44, 32);
// Draw statistics
drawStats(JJ2_BLACK);
if (stage == LS_END) {
// The level is over, so draw gem counts
returnTime = ticks + 1000;
playSound(S_UPLOOP);
// Display statistics
font->showString("red gems", (canvasW >> 1) - 152, (canvasH >> 1) - 60);
font->showNumber(jj2LevelPlayer->getGems(0), (canvasW >> 1) + 124, (canvasH >> 1) - 60);
font->showString("green gems", (canvasW >> 1) - 152, (canvasH >> 1) - 40);
font->showNumber(jj2LevelPlayer->getGems(1), (canvasW >> 1) + 124, (canvasH >> 1) - 40);
font->showString("blue gems", (canvasW >> 1) - 152, (canvasH >> 1) - 20);
font->showNumber(jj2LevelPlayer->getGems(2), (canvasW >> 1) + 124, (canvasH >> 1) - 20);
}
if (pmenu) {
// Draw the menu
drawRect((canvasW >> 2) - 8, (canvasH >> 1) - 46, 144, 92, JJ2_BLACK);
for (count = 0; count < 5; count++) {
if (count == option) fontmn2->mapPalette(240, 8, 31, -8);
else fontmn2->mapPalette(240, 8, 71, -8);
fontmn2->showString(options[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 38);
}
fontmn2->restorePalette();
}
}
return E_NONE;
}
/*
*
* jj2level.h
*
* 29th June 2010: Created jj2level.h from parts of level.h
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* "Tile" is a flexible term. Here it is used to refer specifically to the
individual elements of the tile set.
"Tiles" in the context of level units are referred to as grid elements. */
#ifndef _JJ2LEVEL_H
#define _JJ2LEVEL_H
#include "baselevel.h"
#include "io/gfx/anim.h"
#include "OpenJazz.h"
#include <SDL/SDL.h>
// Constants
// Number of layers
#define LAYERS 8
// Black palette index
#define JJ2_BLACK 0
// Datatypes
typedef struct {
unsigned short int tile; // Indexes the tile set
unsigned char frame; // Current frame being used (for animated tiles)
} JJ2GridElement;
// Classes
class Font;
class JJ2Layer {
private:
int width, height;
public:
JJ2GridElement** grid;
JJ2Layer ();
JJ2Layer (int newWidth, int newHeight);
~JJ2Layer ();
int getHeight ();
int getTile (int x, int y);
int getWidth ();
void draw (SDL_Surface* tileSet);
};
class JJ2Level : public BaseLevel {
private:
char* musicFile;
char* nextLevel;
Anim animSet[128];
char* mask;
int soundMap[32];
JJ2Layer* layers[LAYERS];
unsigned char difficulty;
fixed waterLevel;
fixed waterLevelTarget;
fixed waterLevelSpeed;
void loadSprite (File* file, Sprite* sprite);
int loadSprites (char* fileName);
int loadTiles (char* fileName);
int load (char* fileName, unsigned char diff, bool checkpoint);
int step ();
void draw ();
public:
Font* font;
JJ2Level (char* fileName, unsigned char diff, bool checkpoint);
~JJ2Level ();
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);
fixed getWaterLevel ();
void receive (unsigned char* buffer);
int play ();
};
// Variable
EXTERN JJ2Level* jj2Level;
#endif
/*
*
* jj2levelframe.cpp
*
* 29th June 2010: Created jj2levelframe.cpp from parts of levelframe.cpp
* 30th June 2010: Created jj2layer.cpp from parts of jj2levelframe.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Provides the once-per-frame functions for levels.
*
*/
#include "jj2level.h"
#include "game/game.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/gfx/font.h"
#include "io/gfx/video.h"
#include "player/jj2levelplayer.h"
#include "util.h"
int JJ2Level::step () {
int x;
int msps;
// Milliseconds per step
msps = ticks - prevStepTicks;
prevStepTicks = ticks;
// Determine the players' trajectories
for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->control(ticks, msps);
// Apply as much of those trajectories as possible, without going into the
// scenery
for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->move(ticks, msps);
// Handle change in water level
if (waterLevel < waterLevelTarget) waterLevelSpeed += 100 * msps;
else waterLevelSpeed -= 100 * msps;
if (waterLevelSpeed > 40000) waterLevelSpeed = 40000;
if (waterLevelSpeed < -40000) waterLevelSpeed = -40000;
waterLevel += (waterLevelSpeed * msps) >> 10;
// Handle player reactions
for (x = 0; x < nPlayers; x++) {
if (players[x].getJJ2LevelPlayer()->reacted(ticks) == JJ2PR_KILLED) {
if (!gameMode) return LOST;
game->resetPlayer(players + x);
}
}
return E_NONE;
}
void JJ2Level::draw () {
int count, energy;
unsigned int change;
// Calculate viewport
if (game && (stage == LS_END)) game->view(paused? 0: ((ticks - prevTicks) * 160));
else localPlayer->getJJ2LevelPlayer()->view(ticks, paused? 0: (ticks - prevTicks));
// Ensure the new viewport is within the level
if (viewX < 0) viewX = 0;
if (FTOI(viewX) + viewW >= TTOI(layers[3]->getWidth())) viewX = ITOF(TTOI(layers[3]->getWidth()) - viewW);
if (viewY < 0) viewY = 0;
if (FTOI(viewY) + viewH >= TTOI(layers[3]->getHeight())) viewY = ITOF(TTOI(layers[3]->getHeight()) - viewH);
// Show background layers
for (count = 7; count >= 3; count--) layers[count]->draw(tileSet);
// Calculate change since last step
change = paused? 0: ticks - prevStepTicks;
// Show the players
for (count = 0; count < nPlayers; count++) players[count].getJJ2LevelPlayer()->draw(ticks, change);
// Show foreground layers
for (count = 2; count >= 0; count--) layers[count]->draw(tileSet);
// Temporary lines showing the water level
drawRect(0, FTOI(waterLevel - viewY), canvasW, 2, 72);
drawRect(0, FTOI(waterLevel - viewY) + 3, canvasW, 1, 72);
drawRect(0, FTOI(waterLevel - viewY) + 6, canvasW, 1, 72);
drawRect(0, FTOI(waterLevel - viewY) + 10, canvasW, 1, 72);
// Show "panel" data
// Show score
if (gameMode) gameMode->drawScore(font);
else panelSmallFont->showNumber(localPlayer->getScore(), 16, 8);
// Draw hearts
energy = localPlayer->getJJ2LevelPlayer()->getEnergy();
for (count = 1; count <= energy; count++) {
drawRect(viewW - (count * 12), 4, 8, 8, 48);
}
// Show lives
panelSmallFont->showNumber(localPlayer->getLives(), 16, canvasH - 16);
// Show ammo
if (localPlayer->getAmmo(false) == -1) {
panelSmallFont->showString(":", viewW - 24, canvasH - 16);
panelSmallFont->showString(";", viewW - 16, canvasH - 16);
} else panelSmallFont->showNumber(localPlayer->getAmmo(true), viewW - 8, canvasH - 16);
return;
}
/*
*
* levelloadjj2.cpp
*
* 28th June 2010: Created levelloadjj2.cpp from parts of levelload.cpp
* 29th June 2010: Renamed levelloadjj2.cpp to jj2levelload.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Deals with the loading of JJ2 level data.
*
*/
#include "jj2level.h"
#include "game/game.h"
#include "io/file.h"
#include "io/gfx/font.h"
#include "io/gfx/sprite.h"
#include "io/gfx/video.h"
#include "io/sound.h"
#include "menu/menu.h"
#include "player/jj2levelplayer.h"
#include "loop.h"
#include "util.h"
#include <string.h>
#define SKEY 254 /* Sprite colour key */
void JJ2Level::loadSprite (File* file, Sprite* sprite) {
// TODO: Load sprites from JJ2 files
unsigned char* pixels;
int pos, maskOffset;
int width, height;
// Load dimensions
width = file->loadShort() << 2;
height = file->loadShort();
file->seek(2, false);
maskOffset = file->loadShort();
pos = file->loadShort() << 2;
// Sprites can be either masked or not masked.
if (maskOffset) {
// Masked
height++;
// Skip to mask
file->seek(maskOffset, false);
// Find the end of the data
pos += file->tell() + ((width >> 2) * height);
// Read scrambled, masked pixel data
pixels = file->loadPixels(width * height, SKEY);
sprite->setPixels(pixels, width, height, SKEY);
delete[] pixels;
file->seek(pos, true);
} else if (width) {
// Not masked
// Read scrambled pixel data
pixels = file->loadPixels(width * height);
sprite->setPixels(pixels, width, height, SKEY);
delete[] pixels;
}
return;
}
int JJ2Level::loadSprites (char * fileName) {
// TODO: Load sprites from JJ2 files
File* mainFile = NULL;
File* specFile = NULL;
int count;
// Open fileName
try {
specFile = new File(fileName, false);
} catch (int e) {
return e;
}
// This function loads all the sprites, not fust those in fileName
try {
mainFile = new File(F_MAINCHAR, false);
} catch (int e) {
delete specFile;
return e;
}
sprites = specFile->loadShort();
// Include space in the sprite set for the blank sprite at the end
spriteSet = new Sprite[sprites + 1];
// Read horizontal offsets
for (count = 0; count < sprites; count++)
spriteSet[count].xOffset = specFile->loadChar() << 2;
// Read vertical offsets
for (count = 0; count < sprites; count++)
spriteSet[count].yOffset = specFile->loadChar();
// Skip to where the sprites start in mainchar.000
mainFile->seek(2, true);
// Loop through all the sprites to be loaded
for (count = 0; count < sprites; count++) {
if (specFile->loadChar() == 0xFF) {
// Go to the next sprite/file indicator
specFile->seek(1, false);
if (mainFile->loadChar() == 0xFF) {
// Go to the next sprite/file indicator
mainFile->seek(1, false);
/* Both fileName and mainchar.000 have file indicators, so
create a blank sprite */
spriteSet[count].clearPixels();
continue;
} else {
// Return to the start of the sprite
mainFile->seek(-1, false);
// Load the individual sprite data
loadSprite(mainFile, spriteSet + count);
}
} else {
// Return to the start of the sprite
specFile->seek(-1, false);
// Go to the main file's next sprite/file indicator
mainFile->seek(2, false);
// Load the individual sprite data
loadSprite(specFile, spriteSet + count);
}
// Check if the next sprite exists
// If not, create blank sprites for the remainder
if (specFile->tell() >= specFile->getSize()) {
for (count++; count < sprites; count++) {
spriteSet[count].clearPixels();
}
}
}
delete mainFile;
delete specFile;
// Include a blank sprite at the end
spriteSet[sprites].clearPixels();
spriteSet[sprites].xOffset = 0;
spriteSet[sprites].yOffset = 0;
return E_NONE;
}
int JJ2Level::loadTiles (char* fileName) {
File* file;
unsigned char* aBuffer;
unsigned char* bBuffer;
unsigned char* dBuffer;
unsigned char* tileBuffer;
int aCLength, bCLength, cCLength, dCLength;
int aLength, bLength, cLength, dLength;
int count, x, y;
int maxTiles;
int tiles;
// Thanks to Neobeo for working out the most of the .j2t format
try {
file = new File(fileName, false);
} catch (int e) {
return e;
}
// Skip to version indicator
file->seek(220, true);
maxTiles = file->loadShort();
if (maxTiles == 0x201) maxTiles = 4096;
else maxTiles = 1024;
// Skip to compressed block lengths
file->seek(8, false);
aCLength = file->loadInt();
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);
file->seek(cCLength, false); // Don't need this block
dBuffer = file->loadLZ(dCLength, dLength);
delete file;
// Load the palette
for (count = 0; count < 256; count++) {
palette[count].r = aBuffer[count << 2];
palette[count].g = aBuffer[(count << 2) + 1];
palette[count].b = aBuffer[(count << 2) + 2];
}
// Load tiles
tiles = aBuffer[1024] + (aBuffer[1025] << 8);
tileBuffer = new unsigned char[tiles << 10];
for (count = 0; count < tiles; count++) {
memcpy(tileBuffer + (count << 10), bBuffer + ((int *)aBuffer)[257 + (maxTiles >> 1) + count], 1024);
}
tileSet = createSurface(tileBuffer, TTOI(1), TTOI(tiles));
SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, 0);
delete[] tileBuffer;
// Load mask
mask = new char[tiles << 10];
// Unpack bits
for (count = 0; count < tiles; count++) {
for (y = 0; y < 32; y++) {
for (x = 0; x < 32; x++)
mask[(count << 10) + (y << 5) + x] = (dBuffer[((int *)aBuffer)[257 + ((maxTiles * 9) >> 1) + count] + (y << 2) + (x >> 3)] >> (x & 7)) & 1;
}
}
delete[] dBuffer;
delete[] bBuffer;
delete[] aBuffer;
/* Uncomment the code below if you want to see the mask instead of the tile
graphics during gameplay */
/*if (SDL_MUSTLOCK(tileSet)) SDL_LockSurface(tileSet);
for (count = 0; count < tiles; count++) {
for (y = 0; y < 32; y++) {
for (x = 0; x < 32; x++) {
if (mask[(count << 10) + (y << 5) + x] == 1)
((char *)(tileSet->pixels))[(count << 10) + (y << 5) + x] = 88;
}
}
}
if (SDL_MUSTLOCK(tileSet)) SDL_UnlockSurface(tileSet);*/
return tiles;
}
int JJ2Level::load (char *fileName, unsigned char diff, bool checkpoint) {
File *file;
unsigned char *buffer;
char *string;
unsigned char* aBuffer;
unsigned char* cBuffer;
unsigned char* dBuffer;
int aCLength, bCLength, cCLength, dCLength;
int aLength, bLength, cLength, dLength;
int tiles;
int count, x, y;
unsigned char tileQuad[8];
short int* quadRefs;
int width, pitch, height;
int worldNum;
unsigned char startX, startY;
// Thanks to Neobeo for working out the most of the .j2l format
try {
font = new Font(false);
} catch (int e) {
throw e;
}
difficulty = diff;
// Open JJ2 level file
try {
file = new File(fileName, false);
} catch (int e) {
delete font;
return e;
}
// Load level name
file->seek(188, true);
string = (char *)file->loadBlock(32);
// Show loading screen
video.setPalette(menuPalette);
clearScreen(0);
x = (canvasW >> 1) - ((strlen(string) + 6) << 2);
x = fontmn2->showString("LOADING ", x - 60, (canvasH >> 1) - 16);
fontmn2->showString(string, x, (canvasH >> 1) - 16);
delete[] string;
if (::loop(NORMAL_LOOP) == E_QUIT) return E_QUIT;
// Skip to compressed block lengths
file->seek(230, true);
aCLength = file->loadInt();
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);
file->seek(bCLength, false); // Don't use this block yet
cBuffer = file->loadLZ(cCLength, cLength);
dBuffer = file->loadLZ(dCLength, dLength);
delete file;
// Load tile set from given file
tiles = loadTiles((char *)aBuffer + 51);
if (tiles < 0) {
delete[] dBuffer;
delete[] cBuffer;
delete[] aBuffer;
delete font;
return tiles;
}
// Next level
nextLevel = createString((char *)aBuffer + 115);
// Music file
string = (char *)aBuffer + 179;
if (fileExists(string)) musicFile = createString(string);
else musicFile = createString(string, ".j2b");
// Create layers
quadRefs = (short int *)dBuffer;
for (count = 0; count < LAYERS; count++) {
width = ((int *)(aBuffer + 8443 + 8))[count];
pitch = ((int *)(aBuffer + 8443 + 40))[count];
height = ((int *)(aBuffer + 8443 + 72))[count];
if (aBuffer[8443 + count]) {
layers[count] = new JJ2Layer(width, height);
for (y = 0; y < height; y++) {
for (x = 0; x < layers[count]->getWidth(); x++) {
if ((x & 3) == 0) memcpy(tileQuad, cBuffer + (quadRefs[x >> 2] << 3), 8);
layers[count]->grid[y][x].tile = tileQuad[(x & 3) << 1] + (tileQuad[((x & 3) << 1) + 1] << 8);
layers[count]->grid[y][x].frame = 0;
if (layers[count]->grid[y][x].tile > tiles) layers[count]->grid[y][x].tile = 0;
}
quadRefs += pitch >> 2;
}
} else {
// No tile data
layers[count] = new JJ2Layer();
}
}
// Open JJ1 level file for remaining data
// 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;
delete[] musicFile;
delete[] nextLevel;
SDL_FreeSurface(tileSet);
delete[] dBuffer;
delete[] cBuffer;
delete[] aBuffer;
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[] musicFile;
delete[] nextLevel;
SDL_FreeSurface(tileSet);
delete[] dBuffer;
delete[] cBuffer;
delete[] aBuffer;
delete font;
return count;
}
// Skip to tile and event reference data
file->seek(39, true);
// 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;
waterLevelSpeed = 0;
// Thanks to Feline and the JCS94 team for the next bits:
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) {
string[0] = MTL_P_ANIMS;
string[1] = MT_P_ANIMS;
string[2] = 0;
game->send((unsigned char *)string);
}
// Set the players' initial values
startX = 10;
startY = 5;
if (game) {
if (!checkpoint) game->setCheckpoint(startX, startY);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_JJ2LEVEL, string + 3);
} else {
localPlayer->reset(LT_JJ2LEVEL, string + 3, startX, startY);
}
delete[] string;
// And that's us done!
delete file;
// Set the tick at which the level will end, though this is not used
endTime = (5 - difficulty) * 2 * 60 * 1000;
// Adjust panel fonts to use bonus level palette
panelBigFont->mapPalette(0, 32, 64, 8);
panelSmallFont->mapPalette(75, 5, 64, 8);
return E_NONE;
}
...@@ -231,7 +231,7 @@ Bullet* Bullet::step (unsigned int ticks, int msps) { ...@@ -231,7 +231,7 @@ Bullet* Bullet::step (unsigned int ticks, int msps) {
ITOF(sprite->getWidth()), ITOF(sprite->getHeight()))) { ITOF(sprite->getWidth()), ITOF(sprite->getHeight()))) {
// If the hit was successful, destroy the bullet // If the hit was successful, destroy the bullet
if (players[count].getLevelPlayer()->hit(source, ticks)) return remove(); if (players[count].getLevelPlayer()->hit(source? source->player: NULL, ticks)) return remove();
} }
......
...@@ -94,7 +94,6 @@ DemoLevel::~DemoLevel () { ...@@ -94,7 +94,6 @@ DemoLevel::~DemoLevel () {
int DemoLevel::play () { int DemoLevel::play () {
int stats;
unsigned char macroPoint; unsigned char macroPoint;
int ret; int ret;
...@@ -103,14 +102,12 @@ int DemoLevel::play () { ...@@ -103,14 +102,12 @@ int DemoLevel::play () {
ticks = 16; ticks = 16;
prevStepTicks = 0; prevStepTicks = 0;
stats = 0;
video.setPalette(palette); video.setPalette(palette);
while (true) { while (true) {
// Do general processing // Do general processing
if (loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT; if (::loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT;
if (controls.release(C_ESCAPE)) return E_NONE; if (controls.release(C_ESCAPE)) return E_NONE;
...@@ -172,7 +169,7 @@ int DemoLevel::play () { ...@@ -172,7 +169,7 @@ int DemoLevel::play () {
// Draw the graphics // Draw the graphics
draw(); draw();
drawStats(stats, BLACK); drawStats(LEVEL_BLACK);
font->showString("demo", (canvasW >> 1) - 36, 32); font->showString("demo", (canvasW >> 1) - 36, 32);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* 19th July 2009: Added parts of levelload.cpp to level.cpp * 19th July 2009: Added parts of levelload.cpp to level.cpp
* 30th March 2010: Created baselevel.cpp from parts of level.cpp and * 30th March 2010: Created baselevel.cpp from parts of level.cpp and
* levelframe.cpp * levelframe.cpp
* 29th June 2010: Created jj2level.cpp from parts of level.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -50,10 +51,8 @@ ...@@ -50,10 +51,8 @@
#include "io/gfx/sprite.h" #include "io/gfx/sprite.h"
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/sound.h" #include "io/sound.h"
#include "menu/menu.h"
#include "player/levelplayer.h" #include "player/levelplayer.h"
#include "scene/scene.h" #include "scene/scene.h"
#include "loop.h"
#include "util.h" #include "util.h"
#include <string.h> #include <string.h>
...@@ -78,9 +77,6 @@ Level::Level (char* fileName, unsigned char diff, bool checkpoint) { ...@@ -78,9 +77,6 @@ Level::Level (char* fileName, unsigned char diff, bool checkpoint) {
if (ret < 0) throw ret; if (ret < 0) throw ret;
// Arbitrary initial value
smoothfps = 50.0f;
return; return;
} }
...@@ -187,8 +183,7 @@ void Level::setNext (int nextLevel, int nextWorld) { ...@@ -187,8 +183,7 @@ void Level::setNext (int nextLevel, int nextWorld) {
} }
void Level::setTile (unsigned char gridX, unsigned char gridY, void Level::setTile (unsigned char gridX, unsigned char gridY, unsigned char tile) {
unsigned char tile) {
unsigned char buffer[MTL_L_GRID]; unsigned char buffer[MTL_L_GRID];
...@@ -400,35 +395,6 @@ void Level::flash (unsigned char red, unsigned char green, unsigned char blue, i ...@@ -400,35 +395,6 @@ void Level::flash (unsigned char red, unsigned char green, unsigned char blue, i
} }
void Level::setStage (LevelStage newStage) {
unsigned char buffer[MTL_L_STAGE];
if (stage == newStage) return;
stage = newStage;
if (gameMode) {
buffer[0] = MTL_L_STAGE;
buffer[1] = MT_L_STAGE;
buffer[2] = stage;
game->send(buffer);
}
return;
}
LevelStage Level::getStage () {
return stage;
}
int Level::playBonus () { int Level::playBonus () {
Bonus *bonus; Bonus *bonus;
...@@ -444,7 +410,7 @@ int Level::playBonus () { ...@@ -444,7 +410,7 @@ int Level::playBonus () {
try { try {
bonus = new Bonus(bonusFile, difficulty); baseLevel = bonus = new Bonus(bonusFile, difficulty);
} catch (int e) { } catch (int e) {
...@@ -457,6 +423,7 @@ int Level::playBonus () { ...@@ -457,6 +423,7 @@ int Level::playBonus () {
ret = bonus->play(); ret = bonus->play();
delete bonus; delete bonus;
baseLevel = NULL;
if (ret == E_NONE) playMusic("menusng.psm"); if (ret == E_NONE) playMusic("menusng.psm");
...@@ -520,9 +487,8 @@ int Level::play () { ...@@ -520,9 +487,8 @@ int Level::play () {
const char* options[5] = const char* options[5] =
{"continue game", "save game", "load game", "setup options", "quit game"}; {"continue game", "save game", "load game", "setup options", "quit game"};
char *string; char *string;
SetupMenu setupMenu;
bool pmessage, pmenu; bool pmessage, pmenu;
int stats, option; int option;
unsigned int returnTime; unsigned int returnTime;
int perfect; int perfect;
int timeBonus; int timeBonus;
...@@ -537,7 +503,6 @@ int Level::play () { ...@@ -537,7 +503,6 @@ int Level::play () {
pmessage = pmenu = false; pmessage = pmenu = false;
option = 0; option = 0;
stats = 0;
returnTime = 0; returnTime = 0;
timeBonus = -1; timeBonus = -1;
...@@ -549,76 +514,9 @@ int Level::play () { ...@@ -549,76 +514,9 @@ int Level::play () {
while (true) { while (true) {
if (loop(NORMAL_LOOP, paletteEffects) == E_QUIT) return E_QUIT; count = loop(pmenu, option, pmessage);
if (controls.release(C_ESCAPE)) {
pmenu = !pmenu;
option = 0;
}
if (controls.release(C_PAUSE)) pmessage = !pmessage;
if (controls.release(C_STATS)) {
if (!gameMode) stats ^= S_SCREEN;
else stats = (stats + 1) & 3;
}
if (pmenu) {
// Deal with menu controls
if (controls.release(C_UP)) option = (option + 4) % 5;
if (controls.release(C_DOWN)) option = (option + 1) % 5;
if (controls.release(C_ENTER)) {
switch (option) {
case 0: // Continue
pmenu = false;
break;
case 1: // Save
break;
case 2: // Load
break;
case 3: // Setup
if (!gameMode) {
if (setupMenu.setup() == E_QUIT) return E_QUIT;
// Restore level palette
video.setPalette(palette);
}
break;
case 4: // Quit game
return E_NONE;
}
}
}
if (!gameMode) paused = pmessage || pmenu;
timeCalcs(); if (count <= 0) return count;
// Check if level has been won // Check if level has been won
...@@ -677,12 +575,8 @@ int Level::play () { ...@@ -677,12 +575,8 @@ int Level::play () {
font->showString("pause", (canvasW >> 1) - 44, 32); font->showString("pause", (canvasW >> 1) - 44, 32);
// If this is a competitive game, draw the score
if (gameMode) gameMode->drawScore(font);
// Draw statistics // Draw statistics
drawStats(stats, BLACK); drawStats(LEVEL_BLACK);
if (stage == LS_END) { if (stage == LS_END) {
...@@ -728,7 +622,6 @@ int Level::play () { ...@@ -728,7 +622,6 @@ int Level::play () {
} }
// Display statistics & bonuses // Display statistics & bonuses
// TODO: Display percentage symbol
font->showString("time", (canvasW >> 1) - 152, (canvasH >> 1) - 60); font->showString("time", (canvasW >> 1) - 152, (canvasH >> 1) - 60);
font->showNumber(timeBonus, (canvasW >> 1) + 124, (canvasH >> 1) - 60); font->showNumber(timeBonus, (canvasW >> 1) + 124, (canvasH >> 1) - 60);
...@@ -762,7 +655,7 @@ int Level::play () { ...@@ -762,7 +655,7 @@ int Level::play () {
// Draw the menu // Draw the menu
drawRect((canvasW >> 2) - 8, (canvasH >> 1) - 46, 144, 92, BLACK); drawRect((canvasW >> 2) - 8, (canvasH >> 1) - 46, 144, 92, LEVEL_BLACK);
for (count = 0; count < 5; count++) { for (count = 0; count < 5; count++) {
...@@ -777,31 +670,6 @@ int Level::play () { ...@@ -777,31 +670,6 @@ int Level::play () {
} }
// Networking
if (gameMode) {
count = game->step(ticks);
switch (count) {
case E_UNUSED:
return E_NONE;
case E_NONE:
break;
default:
return count;
}
}
} }
return E_NONE; return E_NONE;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* 4th February 2009: Created events.h from parts of level.h * 4th February 2009: Created events.h from parts of level.h
* 19th March 2009: Created sprite.h from parts of level.h * 19th March 2009: Created sprite.h from parts of level.h
* 30th March 2010: Created baselevel.h from parts of level.h * 30th March 2010: Created baselevel.h from parts of level.h
* 29th June 2010: Created jj2level.h from parts of level.h
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -53,7 +54,7 @@ ...@@ -53,7 +54,7 @@
#define TKEY 127 /* Tileset colour key */ #define TKEY 127 /* Tileset colour key */
// Black palette index // Black palette index
#define BLACK 31 #define LEVEL_BLACK 31
// Fade delays // Fade delays
#define T_START 500 #define T_START 500
...@@ -152,8 +153,6 @@ class Level : public BaseLevel { ...@@ -152,8 +153,6 @@ class Level : public BaseLevel {
fixed getWaterLevel (); fixed getWaterLevel ();
void playSound (int sound); void playSound (int sound);
void flash (unsigned char red, unsigned char green, unsigned char blue, int duration); void flash (unsigned char red, unsigned char green, unsigned char blue, int duration);
void setStage (LevelStage stage);
LevelStage getStage ();
void receive (unsigned char* buffer); void receive (unsigned char* buffer);
virtual int play (); virtual int play ();
...@@ -174,10 +173,9 @@ class DemoLevel : public Level { ...@@ -174,10 +173,9 @@ class DemoLevel : public Level {
}; };
// Variables // Variable
EXTERN Level* level; EXTERN Level* level;
EXTERN fixed viewX, viewY;
#endif #endif
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* 19th July 2009: Created levelframe.cpp from parts of level.cpp * 19th July 2009: Created levelframe.cpp from parts of level.cpp
* 30th March 2010: Created baselevel.cpp from parts of level.cpp and * 30th March 2010: Created baselevel.cpp from parts of level.cpp and
* levelframe.cpp * levelframe.cpp
* 29th June 2010: Created jj2levelframe.cpp from parts of levelframe.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -56,8 +57,7 @@ int Level::step () { ...@@ -56,8 +57,7 @@ int Level::step () {
// Search for active events // Search for active events
for (y = FTOT(viewY) - 5; y < ITOT(FTOI(viewY) + viewH) + 5; y++) { for (y = FTOT(viewY) - 5; y < ITOT(FTOI(viewY) + viewH) + 5; y++) {
for (x = FTOT(viewX) - 5; x < ITOT(FTOI(viewX) + viewW) + 5; x++) for (x = FTOT(viewX) - 5; x < ITOT(FTOI(viewX) + viewW) + 5; x++) {
{
if ((x >= 0) && (y >= 0) && (x < LW) && (y < LH) && if ((x >= 0) && (y >= 0) && (x < LW) && (y < LH) &&
grid[y][x].event && (grid[y][x].event < 121)) { grid[y][x].event && (grid[y][x].event < 121)) {
...@@ -157,7 +157,7 @@ int Level::step () { ...@@ -157,7 +157,7 @@ int Level::step () {
if (!gameMode) return LOST; if (!gameMode) return LOST;
game->resetPlayer(players[x].getLevelPlayer()); game->resetPlayer(players + x);
} }
...@@ -247,8 +247,7 @@ void Level::draw () { ...@@ -247,8 +247,7 @@ void Level::draw () {
// If this tile uses a black background, draw it // If this tile uses a black background, draw it
if (ge->bg) if (ge->bg)
drawRect(TTOI(x) - (vX & 31), TTOI(y) - (vY & 31), 32, 32, drawRect(TTOI(x) - (vX & 31), TTOI(y) - (vY & 31), 32, 32, LEVEL_BLACK);
BLACK);
// If this is not a foreground tile, draw it // If this is not a foreground tile, draw it
...@@ -329,6 +328,10 @@ void Level::draw () { ...@@ -329,6 +328,10 @@ void Level::draw () {
if (events) events->drawEnergy(ticks); if (events) events->drawEnergy(ticks);
// If this is a competitive game, draw the score
if (gameMode) gameMode->drawScore(font);
// Show panel // Show panel
SDL_SetClipRect(canvas, NULL); SDL_SetClipRect(canvas, NULL);
...@@ -336,13 +339,12 @@ void Level::draw () { ...@@ -336,13 +339,12 @@ void Level::draw () {
// Change the ammo type display on the panel // Change the ammo type display on the panel
dst.x = 250; dst.x = 250;
dst.y = 2; dst.y = 2;
SDL_BlitSurface(panelAmmo[localPlayer->getAmmo(false) + 1], NULL, panel, SDL_BlitSurface(panelAmmo[localPlayer->getAmmo(false) + 1], NULL, panel, &dst);
&dst);
dst.x = 0; dst.x = 0;
dst.y = canvasH - 33; dst.y = canvasH - 33;
SDL_BlitSurface(panel, NULL, canvas, &dst); SDL_BlitSurface(panel, NULL, canvas, &dst);
drawRect(0, canvasH - 1, SW, 1, BLACK); drawRect(0, canvasH - 1, SW, 1, LEVEL_BLACK);
// Show panel data // Show panel data
...@@ -424,7 +426,7 @@ void Level::draw () { ...@@ -424,7 +426,7 @@ void Level::draw () {
// Fill in remaining energy bar space with black // Fill in remaining energy bar space with black
drawRect(dst.x, canvasH - 13, dst.w, 7, BLACK); drawRect(dst.x, canvasH - 13, dst.w, 7, LEVEL_BLACK);
return; return;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* 18th July 2009: Created demolevel.cpp from parts of level.cpp and * 18th July 2009: Created demolevel.cpp from parts of level.cpp and
* levelload.cpp * levelload.cpp
* 19th July 2009: Added parts of levelload.cpp to level.cpp * 19th July 2009: Added parts of levelload.cpp to level.cpp
* 28th June 2010: Created levelloadjj2.cpp from parts of levelload.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -34,10 +35,8 @@ ...@@ -34,10 +35,8 @@
#include "level.h" #include "level.h"
#include "game/game.h" #include "game/game.h"
#include "game/gamemode.h"
#include "io/file.h" #include "io/file.h"
#include "io/gfx/font.h" #include "io/gfx/font.h"
#include "io/gfx/paletteeffects.h"
#include "io/gfx/sprite.h" #include "io/gfx/sprite.h"
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/sound.h" #include "io/sound.h"
...@@ -229,10 +228,10 @@ int Level::loadSprites (char * fileName) { ...@@ -229,10 +228,10 @@ int Level::loadSprites (char * fileName) {
} }
int Level::loadTiles (char * fileName) { int Level::loadTiles (char* fileName) {
File *file; File* file;
unsigned char *buffer; unsigned char* buffer;
int rle, pos, index, count, fileSize; int rle, pos, index, count, fileSize;
int tiles; int tiles;
...@@ -264,7 +263,7 @@ int Level::loadTiles (char * fileName) { ...@@ -264,7 +263,7 @@ int Level::loadTiles (char * fileName) {
tiles = 240; // Never more than 240 tiles tiles = 240; // Never more than 240 tiles
buffer = new unsigned char[tiles * 1024]; buffer = new unsigned char[tiles << 10];
file->seek(4, false); file->seek(4, false);
...@@ -273,7 +272,7 @@ int Level::loadTiles (char * fileName) { ...@@ -273,7 +272,7 @@ int Level::loadTiles (char * fileName) {
// Read the RLE pixels // Read the RLE pixels
// file::loadRLE() cannot be used, for reasons that will become clear // file::loadRLE() cannot be used, for reasons that will become clear
while ((pos < 1024 * tiles) && (file->tell() < fileSize)) { while ((pos < (tiles << 10)) && (file->tell() < fileSize)) {
rle = file->loadChar(); rle = file->loadChar();
...@@ -296,9 +295,9 @@ int Level::loadTiles (char * fileName) { ...@@ -296,9 +295,9 @@ int Level::loadTiles (char * fileName) {
file->seek(2, false); /* I assume this is the length of the next file->seek(2, false); /* I assume this is the length of the next
tile block */ tile block */
if (pos == 1024 * 60) file->seek(2, false); if (pos == (60 << 10)) file->seek(2, false);
if (pos == 1024 * 120) file->seek(2, false); if (pos == (120 << 10)) file->seek(2, false);
if (pos == 1024 * 180) file->seek(2, false); if (pos == (180 << 10)) file->seek(2, false);
} }
...@@ -308,7 +307,7 @@ int Level::loadTiles (char * fileName) { ...@@ -308,7 +307,7 @@ int Level::loadTiles (char * fileName) {
// Work out how many tiles were actually loaded // Work out how many tiles were actually loaded
// Should be a multiple of 60 // Should be a multiple of 60
tiles = pos / 1024; tiles = pos >> 10;
tileSet = createSurface(buffer, TTOI(1), TTOI(tiles)); tileSet = createSurface(buffer, TTOI(1), TTOI(tiles));
SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, TKEY); SDL_SetColorKey(tileSet, SDL_SRCCOLORKEY, TKEY);
...@@ -423,7 +422,7 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -423,7 +422,7 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
delete[] string; delete[] string;
if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT; if (::loop(NORMAL_LOOP) == E_QUIT) return E_QUIT;
...@@ -442,8 +441,6 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -442,8 +441,6 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
} }
// Load level data from a Level#.### file
// Load the blocks.### extension // Load the blocks.### extension
// Skip past all level data // Skip past all level data
...@@ -792,18 +789,18 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -792,18 +789,18 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
if (!checkpoint) game->setCheckpoint(startX, startY); if (!checkpoint) game->setCheckpoint(startX, startY);
for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, false, string + 3); for (count = 0; count < nPlayers; count++) game->resetPlayer(players + count, LT_LEVEL, string + 3);
} else { } else {
localPlayer->reset(false, string + 3, startX, startY); localPlayer->reset(LT_LEVEL, string + 3, startX, startY);
} }
delete[] string; delete[] string;
// Load Skip to bullet set // Load miscellaneous animations
miscAnims[0] = file->loadChar(); miscAnims[0] = file->loadChar();
miscAnims[1] = file->loadChar(); miscAnims[1] = file->loadChar();
miscAnims[2] = file->loadChar(); miscAnims[2] = file->loadChar();
...@@ -847,9 +844,6 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -847,9 +844,6 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
sky = false; sky = false;
// Free any existing palette effects
if (paletteEffects) delete paletteEffects;
switch (type) { switch (type) {
case 2: case 2:
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "io/gfx/video.h" #include "io/gfx/video.h"
#include "io/network.h" #include "io/network.h"
#include "io/sound.h" #include "io/sound.h"
#include "jj2level/jj2level.h"
#include "level/level.h" #include "level/level.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "player/player.h" #include "player/player.h"
...@@ -457,6 +458,10 @@ int loadMain (int argc, char *argv[]) { ...@@ -457,6 +458,10 @@ int loadMain (int argc, char *argv[]) {
net = new Network(); net = new Network();
baseLevel = NULL;
level = NULL;
jj2Level = NULL;
return E_NONE; return E_NONE;
} }
......
...@@ -108,10 +108,9 @@ GameMenu::~GameMenu () { ...@@ -108,10 +108,9 @@ GameMenu::~GameMenu () {
} }
int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) { int GameMenu::newGameDifficulty (GameModeType mode, char* firstLevel) {
const char *options[4] = {"easy", "medium", "hard", "turbo"}; const char *options[4] = {"easy", "medium", "hard", "turbo"};
char *firstLevel;
SDL_Rect src, dst; SDL_Rect src, dst;
int count; int count;
...@@ -154,9 +153,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) ...@@ -154,9 +153,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum)
playSound(S_ORB); playSound(S_ORB);
if (levelNum == -1) firstLevel = createFileName(F_BONUSMAP, worldNum);
else firstLevel = createFileName(F_LEVEL, levelNum, worldNum);
if (mode == M_SINGLE) { if (mode == M_SINGLE) {
try { try {
...@@ -165,8 +161,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) ...@@ -165,8 +161,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum)
} catch (int e) { } catch (int e) {
delete[] firstLevel;
message("COULD NOT START GAME"); message("COULD NOT START GAME");
return e; return e;
...@@ -181,8 +175,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) ...@@ -181,8 +175,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum)
} catch (int e) { } catch (int e) {
delete[] firstLevel;
message("COULD NOT CREATE SERVER"); message("COULD NOT CREATE SERVER");
return e; return e;
...@@ -191,8 +183,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) ...@@ -191,8 +183,6 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum)
} }
delete[] firstLevel;
// Play the level(s) // Play the level(s)
...@@ -225,8 +215,26 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) ...@@ -225,8 +215,26 @@ int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum)
} }
int GameMenu::newGameDifficulty (GameModeType mode, int levelNum, int worldNum) {
char* firstLevel;
int ret;
if (levelNum == -1) firstLevel = createFileName(F_BONUSMAP, worldNum);
else firstLevel = createFileName(F_LEVEL, levelNum, worldNum);
ret = newGameDifficulty(mode, firstLevel);
delete[] firstLevel;
return ret;
}
int GameMenu::newGameLevel (GameModeType mode) { int GameMenu::newGameLevel (GameModeType mode) {
/*
int option, worldNum, levelNum; int option, worldNum, levelNum;
worldNum = levelNum = option = 0; worldNum = levelNum = option = 0;
...@@ -288,6 +296,30 @@ int GameMenu::newGameLevel (GameModeType mode) { ...@@ -288,6 +296,30 @@ int GameMenu::newGameLevel (GameModeType mode) {
} }
return E_NONE; return E_NONE;
*/
char* fileName;
int ret;
fileName = createString("castle1.j2l");
ret = E_NONE;
while (true) {
ret = textInput("level file name:", fileName);
if (ret < 0) break;
ret = newGameDifficulty(mode, fileName);
if (ret < 0) break;
}
delete[] fileName;
return ret;
} }
......
...@@ -272,7 +272,7 @@ int MainMenu::main () { ...@@ -272,7 +272,7 @@ int MainMenu::main () {
try { try {
level = new DemoLevel(F_MACRO); baseLevel = level = new DemoLevel(F_MACRO);
} catch (int e) { } catch (int e) {
...@@ -294,6 +294,8 @@ int MainMenu::main () { ...@@ -294,6 +294,8 @@ int MainMenu::main () {
} }
delete level; delete level;
baseLevel = level = NULL;
delete[] players; delete[] players;
localPlayer = NULL; localPlayer = NULL;
......
...@@ -129,6 +129,8 @@ int Menu::textInput (const char* request, char*& text) { ...@@ -129,6 +129,8 @@ int Menu::textInput (const char* request, char*& text) {
int count, terminate, character, x; int count, terminate, character, x;
unsigned int cursor; unsigned int cursor;
video.setPalette(menuPalette);
// Create input string // Create input string
input = createEditableString(text); input = createEditableString(text);
......
...@@ -60,6 +60,7 @@ class GameMenu : public Menu { ...@@ -60,6 +60,7 @@ class GameMenu : public Menu {
int episodes; int episodes;
unsigned char difficulty; unsigned char difficulty;
int newGameDifficulty (GameModeType mode, char* firstLevel);
int newGameDifficulty (GameModeType mode, int levelNum, int worldNum); int newGameDifficulty (GameModeType mode, int levelNum, int worldNum);
int newGameLevel (GameModeType mode); int newGameLevel (GameModeType mode);
int newGameEpisode (GameModeType mode); int newGameEpisode (GameModeType mode);
......
...@@ -506,8 +506,7 @@ int SetupMenu::setup () { ...@@ -506,8 +506,7 @@ int SetupMenu::setup () {
const char *setupOptions[6] = {"character", "keyboard", "joystick", "resolution", "scaling", "sound"}; const char *setupOptions[6] = {"character", "keyboard", "joystick", "resolution", "scaling", "sound"};
const char *setupCharacterOptions[5] = {"name", "fur", "bandana", "gun", "wristband"}; const char *setupCharacterOptions[5] = {"name", "fur", "bandana", "gun", "wristband"};
const char *setupCharacterColOptions[8] = {"white", "red", "orange", "yellow", "green", "blue", "animation 1", "animation 2"}; const char *setupCharacterColOptions[8] = {"white", "red", "orange", "yellow", "green", "blue", "animation 1", "animation 2"};
const unsigned char setupCharacterCols[8] = {PC_WHITE, PC_RED, PC_ORANGE, const unsigned char setupCharacterCols[8] = {PC_GREY, PC_RED, PC_ORANGE, PC_YELLOW, PC_LGREEN, PC_BLUE, PC_SANIM, PC_LANIM};
PC_YELLOW, PC_LGREEN, PC_BLUE, PC_SANIM, PC_LANIM};
int ret; int ret;
int option, suboption, subsuboption; int option, suboption, subsuboption;
...@@ -549,8 +548,7 @@ int SetupMenu::setup () { ...@@ -549,8 +548,7 @@ int SetupMenu::setup () {
if (ret == E_QUIT) return E_QUIT; if (ret == E_QUIT) return E_QUIT;
if (ret == E_NONE) if (ret == E_NONE)
characterCols[suboption - 1] = characterCols[suboption - 1] = setupCharacterCols[subsuboption];
setupCharacterCols[subsuboption];
break; break;
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
BonusPlayer::BonusPlayer (Player* parent, char *newAnims, unsigned char startX, unsigned char startY) { BonusPlayer::BonusPlayer (Player* parent, char *newAnims, unsigned char startX, unsigned char startY) {
int count;
player = parent; player = parent;
memcpy(anims, newAnims, PANIMS); memcpy(anims, newAnims, PANIMS);
...@@ -50,6 +53,15 @@ BonusPlayer::BonusPlayer (Player* parent, char *newAnims, unsigned char startX, ...@@ -50,6 +53,15 @@ BonusPlayer::BonusPlayer (Player* parent, char *newAnims, unsigned char startX,
dr = 0; dr = 0;
gems = 0; gems = 0;
// Create the player's palette
for (count = 0; count < 256; count++)
palette[count].r = palette[count].g = palette[count].b = count;
// TODO: Custom colours
return; return;
} }
......
...@@ -60,6 +60,7 @@ class Bonus; ...@@ -60,6 +60,7 @@ class Bonus;
class BonusPlayer { class BonusPlayer {
private: private:
SDL_Color palette[256];
char anims[PANIMS]; char anims[PANIMS];
fixed x, y, direction, dr; fixed x, y, direction, dr;
unsigned char animType; unsigned char animType;
......
/*
*
* jj2levelplayer.cpp
*
* 29th June 2010: Created jj2levelplayer.cpp from parts of levelplayer.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Deals with the creation and destruction of players in levels, and their
* interactions with other level objects.
*
*/
#include "jj2levelplayer.h"
#include "game/game.h"
#include "game/gamemode.h"
#include "io/sound.h"
#include "jj2level/jj2level.h"
#include <string.h>
JJ2LevelPlayer::JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird) {
int offsets[14] = {JJ2PCO_GREY, JJ2PCO_SGREEN, JJ2PCO_BLUE, JJ2PCO_RED,
JJ2PCO_LGREEN, JJ2PCO_LEVEL1, JJ2PCO_YELLOW, JJ2PCO_LEVEL2,
JJ2PCO_ORANGE, JJ2PCO_LEVEL3, JJ2PCO_LEVEL4, JJ2PCO_SANIM, JJ2PCO_LANIM,
JJ2PCO_LEVEL5};
int lengths[14] = {JJ2PCL_GREY, JJ2PCL_SGREEN, JJ2PCL_BLUE, JJ2PCL_RED,
JJ2PCL_LGREEN, JJ2PCL_LEVEL1, JJ2PCL_YELLOW, JJ2PCL_LEVEL2,
JJ2PCL_ORANGE, JJ2PCL_LEVEL3, JJ2PCL_LEVEL4, JJ2PCL_SANIM, JJ2PCL_LANIM,
JJ2PCL_LEVEL5};
int count, start, length;
player = parent;
if (newAnims) memcpy(anims, newAnims, PANIMS);
else memset(anims, 0, PANIMS);
bird = hasBird;
shield = JJ2S_NONE;
reset(startX, startY);
// Create the player's palette
for (count = 0; count < 256; count++)
palette[count].r = palette[count].g = palette[count].b = count;
// Fur colours
start = offsets[player->cols[0]];
length = lengths[player->cols[0]];
for (count = 0; count < 16; count++)
palette[count + 48].r = palette[count + 48].g = palette[count + 48].b =
(count * length / 16) + start;
// Bandana colours
start = offsets[player->cols[1]];
length = lengths[player->cols[1]];
for (count = 0; count < 16; count++)
palette[count + 32].r = palette[count + 32].g = palette[count + 32].b =
(count * length / 16) + start;
// Gun colours
start = offsets[player->cols[2]];
length = lengths[player->cols[2]];
for (count = 0; count < 9; count++)
palette[count + 23].r = palette[count + 23].g = palette[count + 23].b =
(count * length / 9) + start;
// Wristband colours
start = offsets[player->cols[3]];
length = lengths[player->cols[3]];
for (count = 0; count < 8; count++)
palette[count + 88].r = palette[count + 88].g = palette[count + 88].b =
(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;
}
JJ2LevelPlayer::~JJ2LevelPlayer () {
return;
}
void JJ2LevelPlayer::reset (unsigned char startX, unsigned char startY) {
energy = 5;
floating = false;
facing = true;
reaction = JJ2PR_NONE;
reactionTime = 0;
jumpHeight = ITOF(92);
jumpY = TTOF(256);
fastFeetTime = 0;
warpTime = 0;
dx = 0;
dy = 0;
x = TTOF(startX);
y = TTOF(startY);
gems[0] = gems[1] = gems[2] = gems[3] = 0;
return;
}
void JJ2LevelPlayer::addGem (int colour) {
gems[colour]++;
return;
}
unsigned char JJ2LevelPlayer::getAnim () {
return anims[animType];
}
int JJ2LevelPlayer::getEnergy () {
return energy;
}
bool JJ2LevelPlayer::getFacing () {
return facing;
}
int JJ2LevelPlayer::getGems (int colour) {
return gems[colour];
}
bool JJ2LevelPlayer::hasBird () {
return bird;
}
bool JJ2LevelPlayer::hit (Player *source, unsigned int ticks) {
// Invulnerable if reacting to e.g. having been hit
if (reaction != JJ2PR_NONE) return false;
// Hits from the same team have no effect
if (source && (source->getTeam() == player->team)) return false;
if (!gameMode || gameMode->hit(source, player)) {
energy--;
//if (bird) bird->hit();
playSound(S_OW);
}
if (energy) {
reaction = JJ2PR_HURT;
reactionTime = ticks + PRT_HURT;
if (dx < 0) {
dx = PXS_RUN;
dy = PYS_JUMP;
} else {
dx = -PXS_RUN;
dy = PYS_JUMP;
}
} else {
kill(source, ticks);
}
return true;
}
void JJ2LevelPlayer::kill (Player *source, unsigned int ticks) {
if (reaction != JJ2PR_NONE) return;
if (!gameMode || gameMode->kill(source, player)) {
energy = 0;
player->lives--;
reaction = JJ2PR_KILLED;
reactionTime = ticks + PRT_KILLED;
}
return;
}
bool JJ2LevelPlayer::overlap (fixed left, fixed top, fixed width, fixed height) {
return (x + PXO_R >= left) && (x + PXO_L < left + width) &&
(y >= top) && (y + PYO_TOP < top + height);
}
JJ2PlayerReaction JJ2LevelPlayer::reacted (unsigned int ticks) {
JJ2PlayerReaction oldReaction;
if ((reaction != JJ2PR_NONE) && (reactionTime < ticks)) {
oldReaction = reaction;
reaction = JJ2PR_NONE;
return oldReaction;
}
return JJ2PR_NONE;
}
void JJ2LevelPlayer::setPosition (fixed newX, fixed newY) {
x = newX;
y = newY;
return;
}
void JJ2LevelPlayer::setSpeed (fixed newDx, fixed newDy) {
dx = newDx;
if (newDy) dy = newDy;
return;
}
bool JJ2LevelPlayer::takeEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks) {
return true;
}
bool JJ2LevelPlayer::touchEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks, int msps) {
return false;
}
void JJ2LevelPlayer::send (unsigned char *buffer) {
// Copy data to be sent to clients/server
buffer[9] = bird? 1: 0;
buffer[23] = energy;
buffer[25] = shield;
buffer[26] = floating;
buffer[27] = getFacing();
buffer[29] = jumpHeight >> 24;
buffer[30] = (jumpHeight >> 16) & 255;
buffer[31] = (jumpHeight >> 8) & 255;
buffer[32] = jumpHeight & 255;
buffer[33] = jumpY >> 24;
buffer[34] = (jumpY >> 16) & 255;
buffer[35] = (jumpY >> 8) & 255;
buffer[36] = jumpY & 255;
buffer[37] = x >> 24;
buffer[38] = (x >> 16) & 255;
buffer[39] = (x >> 8) & 255;
buffer[40] = x & 255;
buffer[41] = y >> 24;
buffer[42] = (y >> 16) & 255;
buffer[43] = (y >> 8) & 255;
buffer[44] = y & 255;
return;
}
void JJ2LevelPlayer::receive (unsigned char *buffer) {
// Interpret data received from client/server
switch (buffer[1]) {
case MT_P_ANIMS:
memcpy(anims, (char *)buffer + 3, PANIMS);
break;
case MT_P_TEMP:
if ((buffer[9] & 1) && !bird) bird = true;
if (!(buffer[9] & 1) && bird) {
bird = false;
}
energy = buffer[23];
shield = (JJ2Shield)buffer[25];
floating = buffer[26];
facing = buffer[27];
jumpHeight = (buffer[29] << 24) + (buffer[30] << 16) + (buffer[31] << 8) + buffer[32];
jumpY = (buffer[33] << 24) + (buffer[34] << 16) + (buffer[35] << 8) + buffer[36];
x = (buffer[37] << 24) + (buffer[38] << 16) + (buffer[39] << 8) + buffer[40];
y = (buffer[41] << 24) + (buffer[42] << 16) + (buffer[43] << 8) + buffer[44];
break;
}
return;
}
/*
*
* jj2levelplayer.h
*
* 29th June 2010: Created jj2levelplayer.h from parts of levelplayer.h
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* "Tile" is a flexible term. Here it is used to refer specifically to the
individual elements of the tile set.
"Tiles" in the context of level units are referred to as grid elements. */
#ifndef _JJ2LEVELPLAYER_H
#define _JJ2LEVELPLAYER_H
#include "player.h"
#include "level/movable.h"
#include "OpenJazz.h"
#include <SDL/SDL.h>
// Constants
// Colour offsets
#define JJ2PCO_GREY 72
#define JJ2PCO_SGREEN 16
#define JJ2PCO_BLUE 35
#define JJ2PCO_RED 24
#define JJ2PCO_LGREEN 16
#define JJ2PCO_LEVEL1 96
#define JJ2PCO_YELLOW 59
#define JJ2PCO_LEVEL2 112
#define JJ2PCO_ORANGE 43
#define JJ2PCO_LEVEL3 128
#define JJ2PCO_LEVEL4 144
#define JJ2PCO_SANIM 160
#define JJ2PCO_LANIM 176
#define JJ2PCO_LEVEL5 208
// Colour lengths
#define JJ2PCL_GREY 8
#define JJ2PCL_SGREEN 8
#define JJ2PCL_BLUE 5
#define JJ2PCL_RED 8
#define JJ2PCL_LGREEN 8
#define JJ2PCL_LEVEL1 16
#define JJ2PCL_YELLOW 5
#define JJ2PCL_LEVEL2 16
#define JJ2PCL_ORANGE 5
#define JJ2PCL_LEVEL3 16
#define JJ2PCL_LEVEL4 16
#define JJ2PCL_SANIM 16
#define JJ2PCL_LANIM 32
#define JJ2PCL_LEVEL5 16
// Animations
#define PA_LWALK 0
#define PA_RWALK 1
#define PA_LJUMP 2
#define PA_RJUMP 3
#define PA_LSPIN 4
#define PA_RSPIN 5
#define PA_LSHOOT 6
#define PA_RSHOOT 7
#define PA_LCROUCH 8
#define PA_RCROUCH 9
#define PA_LFALL 10
#define PA_RFALL 11
#define PA_LHURT 12
#define PA_RHURT 13
#define PA_LLEAN 14
#define PA_RLEAN 15
#define PA_LBOARD 16
#define PA_RBOARD 17
#define PA_LSTAND 18
#define PA_RSTAND 19
#define PA_LEAT 20
#define PA_REAT 21
#define PA_LEDGE 22
#define PA_REDGE 23
#define PA_LOOKUP 24
#define PA_LOOKDOWN 25
#define PA_LSWIM 26
#define PA_RSWIM 27
#define PA_LRUN 28
#define PA_RRUN 29
#define PA_LDIE 30
#define PA_RDIE 31
#define PA_LSTOP 32
#define PA_RSTOP 33
#define PA_LHALT 34 /* Yeah, I was wondering the same thing... */
#define PA_RHALT 35
#define PA_RSPRING 36
#define PA_LSPRING 37 /* Surely these are the wrong way round? */
// Player reaction times
#define PRT_HURT 1000
#define PRT_HURTANIM 200
#define PRT_KILLED 2000
#define PRT_INVINCIBLE 10000
// Other time periods
#define T_FASTFEET 25000
#define T_WARP 1000
// Player offsets
#define PXO_MID F16
#define PXO_L (PXO_MID - F10)
#define PXO_ML (PXO_MID - F4)
#define PXO_MR (PXO_MID + F4)
#define PXO_R (PXO_MID + F10)
#define PYO_TOP (-F20)
#define PYO_MID (-F10)
// Player speeds
#define PXS_WALK ITOF(300)
#define PXS_RUN ITOF(325)
#define PXS_FFRUN ITOF(500)
#define PYS_FALL ITOF(350)
#define PYS_SINK ITOF(150)
#define PYS_JUMP ITOF(-350)
// Player accelerations
#define PXA_REVERSE 900
#define PXA_STOP 1000
#define PXA_WALK 500
#define PXA_RUN 200
#define PXA_FFRUN 200
#define PYA_GRAVITY 2750
#define PYA_SINK 1000
// Enum
enum JJ2PlayerReaction {
JJ2PR_NONE, JJ2PR_HURT, JJ2PR_KILLED, JJ2PR_INVINCIBLE
};
enum JJ2Shield {
JJ2S_NONE = 0, JJ2S_FLAME = 1, JJ2S_BUBBLE = 2, JJ2S_PLASMA = 3, JJ2S_LASER = 4
};
// Classes
class Anim;
class JJ2LevelPlayer : public Movable {
private:
bool bird; // Placeholder for eventual JJ2Bird object
SDL_Color palette[256];
char anims[PANIMS];
int energy;
JJ2Shield shield;
int floating; /* 0 = normal, 1 = helicopter ears, 2 = boarding */
bool facing;
unsigned char animType;
int lookTime; /* Negative if looking up, positive if looking down, 0 if neither */
JJ2PlayerReaction reaction;
unsigned int reactionTime;
unsigned int fireTime;
fixed jumpHeight;
fixed jumpY;
unsigned int fastFeetTime;
unsigned char warpX, warpY;
unsigned int warpTime;
int gems[4];
public:
Player* player;
JJ2LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird);
~JJ2LevelPlayer ();
void reset (unsigned char startX, unsigned char startY);
void addGem (int colour);
unsigned char getAnim ();
int getEnemies ();
int getEnergy ();
bool getFacing ();
int getGems (int colour);
bool hasBird ();
bool hit (Player* source, unsigned int ticks);
void kill (Player* source, unsigned int ticks);
bool overlap (fixed left, fixed top, fixed width, fixed height);
JJ2PlayerReaction reacted (unsigned int ticks);
void setPosition (fixed newX, fixed newY);
void setSpeed (fixed newDx, fixed newDy);
bool takeEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks);
bool touchEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks, int msps);
void send (unsigned char* buffer);
void receive (unsigned char* buffer);
void control (unsigned int ticks, int msps);
void move (unsigned int ticks, int msps);
void view (unsigned int ticks, int mspf);
void draw (unsigned int ticks, int change);
};
#endif
/*
*
* jj2levelplayerframe.cpp
*
* 29th June 2010: Created jj2levelplayerframe.cpp from parts of
* levelplayerframe.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Provides the once-per-frame functions of players in levels.
*
*/
#include "jj2levelplayer.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/gfx/font.h"
#include "io/gfx/video.h"
#include "io/sound.h"
#include "jj2level/jj2level.h"
#include "util.h"
void JJ2LevelPlayer::control (unsigned int ticks, int msps) {
bool platform;
// Respond to controls, unless the player has been killed
// If the player has been killed, drop but otherwise do not move
if (!energy) {
dx = 0;
if (floating) dy = 0;
else {
dy += PYA_GRAVITY * msps;
if (dy > PYS_FALL) dy = PYS_FALL;
}
animType = facing? PA_RDIE: PA_LDIE;
return;
}
if (player->pcontrols[C_RIGHT]) {
// Walk/run right
if (dx < 0) dx += PXA_REVERSE * msps;
else if (dx < PXS_WALK) dx += PXA_WALK * msps;
else if (dx < PXS_RUN) dx += PXA_RUN * msps;
facing = true;
} else if (player->pcontrols[C_LEFT]) {
// Walk/run left
if (dx > 0) dx -= PXA_REVERSE * msps;
else if (dx > -PXS_WALK) dx -= PXA_WALK * msps;
else if (dx > -PXS_RUN) dx -= PXA_RUN * msps;
facing = false;
} else {
// Slow down
if (dx > 0) {
if (dx < PXA_STOP * msps) dx = 0;
else dx -= PXA_STOP * msps;
}
if (dx < 0) {
if (dx > -PXA_STOP * msps) dx = 0;
else dx += PXA_STOP * msps;
}
}
if (dx < -PXS_RUN) dx = -PXS_RUN;
if (dx > PXS_RUN) dx = PXS_RUN;
// 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));
if (floating) {
if (player->pcontrols[C_UP]) {
// Fly upwards
if (dy > 0) dy -= PXA_REVERSE * msps;
else if (dy > -PXS_WALK) dy -= PXA_WALK * msps;
else if (dy > -PXS_RUN) dy -= PXA_RUN * msps;
} else if (player->pcontrols[C_DOWN]) {
// Fly downwards
if (dy < 0) dy += PXA_REVERSE * msps;
else if (dy < PXS_WALK) dy += PXA_WALK * msps;
else if (dy < PXS_RUN) dy += PXA_RUN * msps;
} else {
// Slow down
if (dy > 0) {
if (dy < PXA_STOP * msps) dy = 0;
else dy -= PXA_STOP * msps;
}
if (dy < 0) {
if (dy > -PXA_STOP * msps) dy = 0;
else dy += PXA_STOP * msps;
}
}
/*if (event) {
if (event == 1) dy = jj2Level->getEvent(eventX, eventY)[E_MULTIPURPOSE] * -F20;
else if (event == 2) dy = PYS_JUMP;
}*/
if (dy < -PXS_RUN) dy = -PXS_RUN;
if (dy > PXS_RUN) dy = PXS_RUN;
} else if (y + PYO_MID > jj2Level->getWaterLevel()) {
if (player->pcontrols[C_SWIM]) {
// Swim upwards
if (dy > 0) dy -= PXA_REVERSE * msps;
else if (dy > -PXS_WALK) dy -= PXA_WALK * msps;
else if (dy > -PXS_RUN) dy -= PXA_RUN * msps;
// Prepare to jump upon leaving the water
if (!jj2Level->checkMaskUp(x + PXO_MID, y - F36)) {
jumpY = y - jumpHeight;
if (dx < 0) jumpY += dx >> 4;
else if (dx > 0) jumpY -= dx >> 4;
//event = 0;
}
} else if (player->pcontrols[C_DOWN]) {
// Swim downwards
if (dy < 0) dy += PXA_REVERSE * msps;
else if (dy < PXS_WALK) dy += PXA_WALK * msps;
else if (dy < PXS_RUN) dy += PXA_RUN * msps;
} else {
// Sink
dy += PYA_SINK * msps;
if (dy > PYS_SINK) dy = PYS_SINK;
}
if (dy < -PXS_RUN) dy = -PXS_RUN;
if (dy > PXS_RUN) dy = PXS_RUN;
} else {
if (platform && player->pcontrols[C_JUMP] &&
!jj2Level->checkMaskUp(x + PXO_MID, y - F36)) {
// Jump
jumpY = y - jumpHeight;
// Increase jump height if walking/running
if (dx < 0) jumpY += dx >> 3;
else if (dx > 0) jumpY -= dx >> 3;
//event = 0;
playSound(S_JUMPA);
}
// Stop jumping
if (!player->pcontrols[C_JUMP] /*&& (event != 1) && (event != 2)*/)
jumpY = TTOF(256);
if (y >= jumpY) {
// If jumping, rise
dy = (jumpY - y - F64) * 4;
// Spring/float up speed limit
/*if ((event == 1) || (event == 2)) {
speed = jj2Level->getEvent(eventX, eventY)[E_MULTIPURPOSE] * -F20;
if (speed >= 0) speed = PYS_JUMP;
if (dy < speed) dy = speed;
}*/
// Avoid jumping too fast, unless caused by an event
if (/* !event &&*/ (dy < PYS_JUMP)) dy = PYS_JUMP;
} else if (!platform) {
// Fall under gravity
dy += PYA_GRAVITY * msps;
if (dy > PYS_FALL) dy = PYS_FALL;
}
// Don't descend through platforms
//if ((dy > 0) && (event >= 3)) dy = 0;
if (platform && !lookTime) {
// If requested, look up or down
if (player->pcontrols[C_UP]) lookTime = -ticks;
else if (player->pcontrols[C_DOWN]) lookTime = ticks;
}
// Stop looking if there is no platform or the control has been released
if (!platform ||
(!player->pcontrols[C_UP] && (lookTime < 0)) ||
(!player->pcontrols[C_DOWN] && (lookTime > 0))) lookTime = 0;
}
// If there is an obstacle above and the player is not floating up, stop
// rising
if (jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - F4) && (jumpY < y) /*&& (event != 2)*/) {
jumpY = TTOF(256);
if (dy < 0) dy = 0;
//if ((event != 3) && (event != 4)) event = 0;
}
// If jump completed, stop rising
if (y <= jumpY) {
jumpY = TTOF(256);
//if ((event != 3) && (event != 4)) event = 0;
}
// Handle firing
if (player->pcontrols[C_FIRE]) {
if (ticks > fireTime) {
// Make sure bullet position is taken from correct animation
if (platform) animType = facing? PA_RSHOOT: PA_LSHOOT;
// TODO: Create new bullet
// Set when the next bullet can be fired
if (player->fireSpeed) fireTime = ticks + (1000 / player->fireSpeed);
else fireTime = 0x7FFFFFFF;
// Remove the bullet from the arsenal
if (player->ammoType != -1) player->ammo[player->ammoType]--;
/* If the current ammo type has been exhausted, use the previous
non-exhausted ammo type */
while ((player->ammoType > -1) && !player->ammo[player->ammoType]) player->ammoType--;
}
} else fireTime = 0;
// Check for a change in ammo
if (player->pcontrols[C_CHANGE]) {
if (player == localPlayer) controls.release(C_CHANGE);
player->ammoType = ((player->ammoType + 2) % 5) - 1;
// If there is no ammo of this type, go to the next type that has ammo
while ((player->ammoType > -1) && !player->ammo[player->ammoType])
player->ammoType = ((player->ammoType + 2) % 5) - 1;
}
// Deal with the bird
/*if (bird) {
if (bird->step(ticks, msps)) {
delete bird;
bird = NULL;
}
}*/
// Choose animation
if ((reaction == JJ2PR_HURT) && (reactionTime - ticks > PRT_HURT - PRT_HURTANIM))
animType = facing? PA_RHURT: PA_LHURT;
else if (y + PYO_MID > jj2Level->getWaterLevel())
animType = facing? PA_RSWIM: PA_LSWIM;
else if (floating) animType = facing? PA_RBOARD: PA_LBOARD;
else if (dy < 0) {
/*if (event == 1) animType = facing? PA_RSPRING: PA_LSPRING;
else*/ animType = facing? PA_RJUMP: PA_LJUMP;
} else if (platform) {
if (dx) {
if (dx <= -PXS_RUN) animType = PA_LRUN;
else if (dx >= PXS_RUN) animType = PA_RRUN;
else if ((dx < 0) && facing) animType = PA_LSTOP;
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) /*&&
(event != 3) && (event != 4)*/)
animType = PA_LEDGE;
else if (!jj2Level->checkMaskDown(x + PXO_MR, y + F12) &&
!jj2Level->checkMaskDown(x + PXO_R, y + F2) /*&&
(event != 3) && (event != 4)*/)
animType = PA_REDGE;
else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime))
animType = PA_LOOKUP;
else if (lookTime > 0) {
if ((int)ticks < 1000 + lookTime) animType = facing? PA_RCROUCH: PA_LCROUCH;
else animType = PA_LOOKDOWN;
}
else if (player->pcontrols[C_FIRE])
animType = facing? PA_RSHOOT: PA_LSHOOT;
else
animType = facing? PA_RSTAND: PA_LSTAND;
} else animType = facing? PA_RFALL: PA_LFALL;
return;
}
void JJ2LevelPlayer::move (unsigned int ticks, int msps) {
fixed pdx, pdy;
int count;
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
if (fastFeetTime > ticks) {
pdx = (dx * msps * 3) >> 11;
pdy = (dy * msps * 3) >> 11;
} else {
pdx = (dx * msps) >> 10;
pdy = (dy * msps) >> 10;
}
// First for the vertical component of the trajectory
if (pdy < 0) {
// Moving up
count = (-pdy) >> 12;
while (count > 0) {
if (jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - F4)) {
y &= ~4095;
dy = 0;
break;
}
y -= F4;
count--;
}
pdy = (-pdy) & 4095;
if (!jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - pdy))
y -= pdy;
else {
y &= ~4095;
dy = 0;
}
} else if (pdy > 0) {
// Moving down
count = pdy >> 12;
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)) {
y |= 4095;
dy = 0;
break;
}
y += F4;
count--;
}
pdy &= 4095;
if (!(jj2Level->checkMaskDown(x + PXO_ML, y + pdy) ||
jj2Level->checkMaskDown(x + PXO_MID, y + pdy) ||
jj2Level->checkMaskDown(x + PXO_MR, y + pdy)))
y += pdy;
else {
y |= 4095;
dy = 0;
}
}
// Then for the horizontal component of the trajectory
if (pdx < 0) {
// Moving left
count = (-pdx) >> 12;
while (count > 0) {
// If there is an obstacle, stop
if (jj2Level->checkMaskUp(x + PXO_L - F4, y + PYO_MID)) {
x &= ~4095;
break;
}
x -= F4;
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;
}
pdx = (-pdx) & 4095;
if (!jj2Level->checkMaskUp(x + PXO_L - pdx, y + PYO_MID)) x -= pdx;
else x &= ~4095;
// 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;
} else if (pdx > 0) {
// Moving right
count = pdx >> 12;
while (count > 0) {
// If there is an obstacle, stop
if (jj2Level->checkMaskUp(x + PXO_R + F4, y + PYO_MID)) {
x |= 4095;
break;
}
x += F4;
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;
}
pdx &= 4095;
if (!jj2Level->checkMaskUp(x + PXO_R + pdx, y + PYO_MID)) x += pdx;
else x |= 4095;
// 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;
}
// If using a float up event and have hit a ceiling, ignore event
/*if ((event == 2) && jj2Level->checkMaskUp(x + PXO_MID, y + PYO_TOP - F4)) {
jumpY = TTOF(256);
event = 0;
}*/
if (jj2Level->getStage() == LS_END) return;
// 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);
return;
}
void JJ2LevelPlayer::view (unsigned int ticks, int mspf) {
int oldViewX, oldViewY, speed;
// Calculate viewport
// Record old viewport position for applying lag
oldViewX = viewX;
oldViewY = viewY;
// There is no panel, so use the whole height
viewH = canvasH;
// Find new position
viewX = x + F8 - (viewW << 9);
viewY = y - F24 - (viewH << 9);
if ((lookTime > 0) && ((int)ticks > 1000 + lookTime)) {
// Look down
if ((int)ticks < 2000 + lookTime) viewY += 64 * (ticks - (1000 + lookTime));
else viewY += F64;
} else if ((lookTime < 0) && ((int)ticks > 1000 - lookTime)) {
// Look up
if ((int)ticks < 2000 - lookTime) viewY -= 64 * (ticks - (1000 - lookTime));
else viewY -= F64;
}
// Apply lag proportional to player "speed"
speed = ((dx >= 0? dx: -dx) + (dy >= 0? dy: -dy)) >> 14;
if (speed && (mspf < speed)) {
viewX = ((oldViewX * (speed - mspf)) + (viewX * mspf)) / speed;
viewY = ((oldViewY * (speed - mspf)) + (viewY * mspf)) / speed;
}
return;
}
void JJ2LevelPlayer::draw (unsigned int ticks, int change) {
Anim *an;
int frame;
fixed drawX, drawY;
// The current frame for animations
if (reaction == JJ2PR_KILLED) frame = (ticks + PRT_KILLED - reactionTime) / 75;
else frame = ticks / 75;
// Get position
drawX = getDrawX(change);
drawY = getDrawY(change);
// Choose sprite
an = jj2Level->getAnim(getAnim());
an->setFrame(frame, reaction != JJ2PR_KILLED);
// Show the player
// Flash red if hurt, otherwise use player colour
if ((reaction == JJ2PR_HURT) && (!((ticks / 30) & 3)))
an->flashPalette(36);
else {
an->setPalette(palette, 23, 41);
an->setPalette(palette, 88, 8);
}
// Draw "motion blur"
if (fastFeetTime > ticks) an->draw(drawX - (dx >> 6), drawY);
// Draw player
an->draw(drawX, drawY);
// Remove red flash or player colour from sprite
an->restorePalette();
// Uncomment the following to see the area of the player
/*drawRect(FTOI(drawX + PXO_L - viewX),
FTOI(drawY + PYO_TOP - viewY),
FTOI(PXO_R - PXO_L),
FTOI(-PYO_TOP), 89);
drawRect(FTOI(drawX + PXO_ML - viewX),
FTOI(drawY + PYO_TOP - viewY),
FTOI(PXO_MR - PXO_ML),
FTOI(-PYO_TOP), 88);*/
if (reaction == JJ2PR_INVINCIBLE) {
// TODO: Show invincibility effect
}
switch (shield) {
case JJ2S_NONE:
// Do nothing
break;
case JJ2S_FLAME:
// TODO: Show shield effect
break;
case JJ2S_BUBBLE:
// TODO: Show shield effect
break;
case JJ2S_PLASMA:
// TODO: Show shield effect
break;
case JJ2S_LASER:
// TODO: Show shield effect
break;
}
// Show the bird
//if (bird) bird->draw(ticks, change);
// Show the player's name
if (gameMode)
panelBigFont->showString(player->name,
FTOI(drawX + PXO_MID) - (panelBigFont->getStringWidth(player->name) >> 1),
FTOI(drawY - F32 - F16));
return;
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* levelplayer.cpp * levelplayer.cpp
* *
* 24th June 2010: Created levelplayer.cpp from parts of player.cpp * 24th June 2010: Created levelplayer.cpp from parts of player.cpp
* 29th June 2010: Created jj2levelplayer.cpp from parts of levelplayer.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -40,6 +41,12 @@ ...@@ -40,6 +41,12 @@
LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird) { LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX, unsigned char startY, bool hasBird) {
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_SANIM, PCO_LANIM, PCO_LEVEL5, 256};
int count, start, length;
player = parent; player = parent;
if (newAnims) memcpy(anims, newAnims, PANIMS); if (newAnims) memcpy(anims, newAnims, PANIMS);
...@@ -54,6 +61,53 @@ LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX, ...@@ -54,6 +61,53 @@ LevelPlayer::LevelPlayer (Player* parent, char* newAnims, unsigned char startX,
reset(startX, startY); reset(startX, startY);
// Create the player's palette
for (count = 0; count < 256; count++)
palette[count].r = palette[count].g = palette[count].b = count;
// Fur colours
start = offsets[player->cols[0]];
length = offsets[player->cols[0] + 1] - start;
for (count = 0; count < 16; count++)
palette[count + 48].r = palette[count + 48].g = palette[count + 48].b =
(count * length / 16) + start;
// Bandana colours
start = offsets[player->cols[1]];
length = offsets[player->cols[1] + 1] - start;
for (count = 0; count < 16; count++)
palette[count + 32].r = palette[count + 32].g = palette[count + 32].b =
(count * length / 16) + start;
// Gun colours
start = offsets[player->cols[2]];
length = offsets[player->cols[2] + 1] - start;
for (count = 0; count < 9; count++)
palette[count + 23].r = palette[count + 23].g = palette[count + 23].b =
(count * length / 9) + start;
// Wristband colours
start = offsets[player->cols[3]];
length = offsets[player->cols[3] + 1] - start;
for (count = 0; count < 8; count++)
palette[count + 88].r = palette[count + 88].g = palette[count + 88].b =
(count * length / 8) + start;
return; return;
} }
...@@ -159,18 +213,18 @@ bool LevelPlayer::hasGem () { ...@@ -159,18 +213,18 @@ bool LevelPlayer::hasGem () {
} }
bool LevelPlayer::hit (LevelPlayer *source, unsigned int ticks) { bool LevelPlayer::hit (Player *source, unsigned int ticks) {
// Invulnerable if reacting to e.g. having been hit // Invulnerable if reacting to e.g. having been hit
if (reaction != PR_NONE) return false; if (reaction != PR_NONE) return false;
// Hits from the same team have no effect // Hits from the same team have no effect
if (source && (source->player->getTeam() == player->team)) return false; if (source && (source->getTeam() == player->team)) return false;
if (shield == 3) shield = 0; if (shield == 3) shield = 0;
else if (shield) shield--; else if (shield) shield--;
else if (!gameMode || gameMode->hit(source, this)) { else if (!gameMode || gameMode->hit(source, player)) {
energy--; energy--;
...@@ -208,11 +262,11 @@ bool LevelPlayer::hit (LevelPlayer *source, unsigned int ticks) { ...@@ -208,11 +262,11 @@ bool LevelPlayer::hit (LevelPlayer *source, unsigned int ticks) {
} }
void LevelPlayer::kill (LevelPlayer *source, unsigned int ticks) { void LevelPlayer::kill (Player *source, unsigned int ticks) {
if (reaction != PR_NONE) return; if (reaction != PR_NONE) return;
if (!gameMode || gameMode->kill(source, this)) { if (!gameMode || gameMode->kill(source, player)) {
energy = 0; energy = 0;
player->lives--; player->lives--;
...@@ -324,7 +378,7 @@ bool LevelPlayer::takeEvent (unsigned char gridX, unsigned char gridY, unsigned ...@@ -324,7 +378,7 @@ bool LevelPlayer::takeEvent (unsigned char gridX, unsigned char gridY, unsigned
level->setStage(LS_END); level->setStage(LS_END);
} else if (!(gameMode->endOfLevel(this, gridX, gridY))) return false; } else if (!(gameMode->endOfLevel(player, gridX, gridY))) return false;
break; break;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* levelplayer.h * levelplayer.h
* *
* 24th June 2010: Created levelplayer.h from parts of player.h * 24th June 2010: Created levelplayer.h from parts of player.h
* 29th June 2010: Created jj2levelplayer.h from parts of levelplayer.h
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -39,6 +40,22 @@ ...@@ -39,6 +40,22 @@
// Constants // Constants
// Colour offsets
#define PCO_GREY 0
#define PCO_SGREEN 16
#define PCO_BLUE 23
#define PCO_RED 32
#define PCO_LGREEN 48
#define PCO_LEVEL1 64
#define PCO_YELLOW 75
#define PCO_LEVEL2 80
#define PCO_ORANGE 88
#define PCO_LEVEL3 96
#define PCO_LEVEL4 104
#define PCO_SANIM 112
#define PCO_LANIM 116
#define PCO_LEVEL5 124
// Animations // Animations
#define PA_LWALK 0 #define PA_LWALK 0
#define PA_RWALK 1 #define PA_RWALK 1
...@@ -134,6 +151,7 @@ class LevelPlayer : public Movable { ...@@ -134,6 +151,7 @@ class LevelPlayer : public Movable {
private: private:
Bird* bird; Bird* bird;
SDL_Color palette[256];
char anims[PANIMS]; char 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 */
...@@ -172,8 +190,8 @@ class LevelPlayer : public Movable { ...@@ -172,8 +190,8 @@ class LevelPlayer : public Movable {
int getItems (); int getItems ();
bool hasBird (); bool hasBird ();
bool hasGem (); bool hasGem ();
bool hit (LevelPlayer* source, unsigned int ticks); bool hit (Player* source, unsigned int ticks);
void kill (LevelPlayer* source, unsigned int ticks); void kill (Player* source, unsigned int ticks);
bool overlap (fixed left, fixed top, fixed width, fixed height); bool overlap (fixed left, fixed top, fixed width, fixed height);
PlayerReaction reacted (unsigned int ticks); PlayerReaction reacted (unsigned int ticks);
void setEvent (unsigned char gridX, unsigned char gridY); void setEvent (unsigned char gridX, unsigned char gridY);
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* *
* 18th July 2009: Created playerframe.cpp from parts of player.cpp * 18th July 2009: Created playerframe.cpp from parts of player.cpp
* 24th June 2010: Renamed playerframe.cpp to levelplayerframe.cpp * 24th June 2010: Renamed playerframe.cpp to levelplayerframe.cpp
* 29th June 2010: Created jj2levelplayerframe.cpp from parts of
* levelplayerframe.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -703,8 +705,8 @@ void LevelPlayer::draw (unsigned int ticks, int change) { ...@@ -703,8 +705,8 @@ void LevelPlayer::draw (unsigned int ticks, int change) {
else { else {
an->setPalette(player->palette, 23, 41); an->setPalette(palette, 23, 41);
an->setPalette(player->palette, 88, 8); an->setPalette(palette, 88, 8);
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "bird.h" #include "bird.h"
#include "bonusplayer.h" #include "bonusplayer.h"
#include "jj2levelplayer.h"
#include "levelplayer.h" #include "levelplayer.h"
#include "baselevel.h" #include "baselevel.h"
...@@ -48,6 +49,7 @@ Player::Player () { ...@@ -48,6 +49,7 @@ Player::Player () {
levelPlayer = NULL; levelPlayer = NULL;
bonusPlayer = NULL; bonusPlayer = NULL;
jj2LevelPlayer = NULL;
name = NULL; name = NULL;
...@@ -67,11 +69,6 @@ Player::~Player () { ...@@ -67,11 +69,6 @@ Player::~Player () {
void Player::init (char *playerName, unsigned char *playerCols, unsigned char newTeam) { void Player::init (char *playerName, unsigned char *playerCols, unsigned char newTeam) {
int offsets[15] = {PC_WHITE, PC_SGREEN, PC_BLUE, PC_RED, PC_LGREEN,
PC_LEVEL1, PC_YELLOW, PC_LEVEL2, PC_ORANGE, PC_LEVEL3, PC_LEVEL4,
PC_SANIM, PC_LANIM, PC_LEVEL5, 256};
int count, start, length;
// Clear existing player // Clear existing player
deinit(); deinit();
...@@ -91,71 +88,18 @@ void Player::init (char *playerName, unsigned char *playerCols, unsigned char ne ...@@ -91,71 +88,18 @@ void Player::init (char *playerName, unsigned char *playerCols, unsigned char ne
team = newTeam; team = newTeam;
teamScore = 0; teamScore = 0;
if (playerCols) {
// Create the player's palette memcpy(cols, playerCols, PCOLOURS);
for (count = 0; count < 256; count++)
palette[count].r = palette[count].g = palette[count].b = count;
if (playerCols == NULL) return;
memcpy(cols, playerCols, 4);
// Fur colours
count = 0;
while (cols[0] >= offsets[count + 1]) count++;
start = offsets[count];
length = offsets[count + 1] - start;
for (count = 0; count < 16; count++)
palette[count + 48].r = palette[count + 48].g = palette[count + 48].b =
(count * length / 16) + start;
// Bandana colours
count = 0;
while (cols[1] >= offsets[count + 1]) count++;
start = offsets[count];
length = offsets[count + 1] - start;
for (count = 0; count < 16; count++)
palette[count + 32].r = palette[count + 32].g = palette[count + 32].b =
(count * length / 16) + start;
} else {
// Gun colours cols[0] = CHAR_FUR;
cols[1] = CHAR_BAND;
count = 0; cols[2] = CHAR_GUN;
cols[3] = CHAR_WBAND;
while (cols[2] >= offsets[count + 1]) count++;
start = offsets[count];
length = offsets[count + 1] - start;
for (count = 0; count < 9; count++)
palette[count + 23].r = palette[count + 23].g = palette[count + 23].b =
(count * length / 9) + start;
// Wristband colours
count = 0;
while (cols[3] >= offsets[count + 1]) count++;
start = offsets[count];
length = offsets[count + 1] - start;
for (count = 0; count < 8; count++)
palette[count + 88].r = palette[count + 88].g = palette[count + 88].b =
(count * length / 8) + start;
}
return; return;
...@@ -166,8 +110,10 @@ void Player::deinit () { ...@@ -166,8 +110,10 @@ void Player::deinit () {
if (levelPlayer) delete levelPlayer; if (levelPlayer) delete levelPlayer;
if (bonusPlayer) delete bonusPlayer; if (bonusPlayer) delete bonusPlayer;
if (jj2LevelPlayer) delete levelPlayer;
levelPlayer = NULL; levelPlayer = NULL;
bonusPlayer = NULL; bonusPlayer = NULL;
jj2LevelPlayer = NULL;
if (name) delete[] name; if (name) delete[] name;
name = NULL; name = NULL;
...@@ -177,7 +123,16 @@ void Player::deinit () { ...@@ -177,7 +123,16 @@ void Player::deinit () {
} }
void Player::reset (bool bonus, char* newAnims, unsigned char x, unsigned char y) { void Player::reset (unsigned char x, unsigned char y) {
if (levelPlayer) levelPlayer->reset(x, y);
return;
}
void Player::reset (LevelType levelType, char* newAnims, unsigned char x, unsigned char y) {
int count; int count;
...@@ -185,20 +140,44 @@ void Player::reset (bool bonus, char* newAnims, unsigned char x, unsigned char y ...@@ -185,20 +140,44 @@ void Player::reset (bool bonus, char* newAnims, unsigned char x, unsigned char y
bird = levelPlayer->hasBird(); bird = levelPlayer->hasBird();
delete levelPlayer; delete levelPlayer;
levelPlayer = NULL;
} }
if (bonusPlayer) delete bonusPlayer; if (bonusPlayer) {
if (bonus) { delete bonusPlayer;
bonusPlayer = NULL;
levelPlayer = NULL; }
bonusPlayer = new BonusPlayer(this, newAnims, x, y);
} else { if (jj2LevelPlayer) {
bird = jj2LevelPlayer->hasBird();
delete jj2LevelPlayer;
jj2LevelPlayer = NULL;
}
switch (levelType) {
case LT_LEVEL:
levelPlayer = new LevelPlayer(this, newAnims, x, y, bird); levelPlayer = new LevelPlayer(this, newAnims, x, y, bird);
bonusPlayer = NULL;
break;
case LT_BONUS:
bonusPlayer = new BonusPlayer(this, newAnims, x, y);
break;
case LT_JJ2LEVEL:
jj2LevelPlayer = new JJ2LevelPlayer(this, newAnims, x, y, bird);
break;
} }
...@@ -230,6 +209,13 @@ char * Player::getName () { ...@@ -230,6 +209,13 @@ char * Player::getName () {
} }
JJ2LevelPlayer* Player::getJJ2LevelPlayer () {
return jj2LevelPlayer;
}
LevelPlayer* Player::getLevelPlayer () { LevelPlayer* Player::getLevelPlayer () {
return levelPlayer; return levelPlayer;
...@@ -337,6 +323,7 @@ void Player::send (unsigned char *buffer) { ...@@ -337,6 +323,7 @@ void Player::send (unsigned char *buffer) {
buffer[45] = pcontrols[C_SWIM]; buffer[45] = pcontrols[C_SWIM];
if (levelPlayer) levelPlayer->send(buffer); if (levelPlayer) levelPlayer->send(buffer);
if (jj2LevelPlayer) jj2LevelPlayer->send(buffer);
return; return;
...@@ -370,6 +357,7 @@ void Player::receive (unsigned char *buffer) { ...@@ -370,6 +357,7 @@ void Player::receive (unsigned char *buffer) {
} }
if (levelPlayer) levelPlayer->receive(buffer); if (levelPlayer) levelPlayer->receive(buffer);
if (jj2LevelPlayer) jj2LevelPlayer->receive(buffer);
return; return;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* player.h * player.h
* *
* 31st January 2006: Created player.h from parts of OpenJazz.h * 31st January 2006: Created player.h from parts of OpenJazz.h
* 24th June 2010: Created levelplayer.h from parts of player.h
* 24th June 2010: Created bonusplayer.h from parts of player.h
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -29,55 +31,61 @@ ...@@ -29,55 +31,61 @@
#define _PLAYER_H #define _PLAYER_H
#include "OpenJazz.h" #include "baselevel.h"
#include <SDL/SDL.h>
// Constants // Constants
// Player colours
#define PC_WHITE 0
#define PC_SGREEN 16
#define PC_BLUE 23
#define PC_RED 32
#define PC_LGREEN 48
#define PC_LEVEL1 64
#define PC_YELLOW 75
#define PC_LEVEL2 80
#define PC_ORANGE 88
#define PC_LEVEL3 96
#define PC_LEVEL4 104
#define PC_SANIM 112
#define PC_LANIM 116
#define PC_LEVEL5 124
// Player defaults // Player defaults
#define CHAR_NAME "jazz" #define CHAR_NAME "jazz"
#define CHAR_FUR PC_LGREEN #define CHAR_FUR 4
#define CHAR_BAND PC_RED #define CHAR_BAND 3
#define CHAR_GUN PC_BLUE #define CHAR_GUN 2
#define CHAR_WBAND PC_ORANGE #define CHAR_WBAND 8
// General // General
#define PANIMS 38 /* Number of player animations. Is probably higher. */ #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 */
// Enum
enum PlayerColour {
PC_GREY = 0,
PC_SGREEN = 1,
PC_BLUE = 2,
PC_RED = 3,
PC_LGREEN = 4,
PC_LEVEL1 = 5,
PC_YELLOW = 6,
PC_LEVEL2 = 7,
PC_ORANGE = 8,
PC_LEVEL3 = 9,
PC_LEVEL4 = 10,
PC_SANIM = 11,
PC_LANIM = 12,
PC_LEVEL5 = 13
};
// Classes // Classes
class BonusPlayer;
class LevelPlayer; class LevelPlayer;
class BonusPlayer;
class JJ2LevelPlayer;
class Player { class Player {
private: private:
LevelPlayer* levelPlayer; LevelPlayer* levelPlayer;
BonusPlayer* bonusPlayer; BonusPlayer* bonusPlayer;
JJ2LevelPlayer* jj2LevelPlayer;
char* name; char* name;
bool pcontrols[PCONTROLS]; bool pcontrols[PCONTROLS];
SDL_Color palette[256]; unsigned char cols[PCOLOURS];
unsigned char cols[4];
int ammo[4]; int ammo[4];
int ammoType; /* -1 = blaster, 0 = toaster, 1 = missiles, 2 = bouncer 3 = TNT */ int ammoType; /* -1 = blaster, 0 = toaster, 1 = missiles, 2 = bouncer 3 = TNT */
int score; int score;
...@@ -96,7 +104,8 @@ class Player { ...@@ -96,7 +104,8 @@ 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 (bool bonus, char* newAnims, 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 addLife (); void addLife ();
void addScore (int addedScore); void addScore (int addedScore);
...@@ -104,6 +113,7 @@ class Player { ...@@ -104,6 +113,7 @@ class Player {
BonusPlayer* getBonusPlayer (); BonusPlayer* getBonusPlayer ();
unsigned char* getCols (); unsigned char* getCols ();
bool getControl (int control); bool getControl (int control);
JJ2LevelPlayer* getJJ2LevelPlayer ();
LevelPlayer* getLevelPlayer (); LevelPlayer* getLevelPlayer ();
int getLives (); int getLives ();
char* getName (); char* getName ();
...@@ -115,6 +125,7 @@ class Player { ...@@ -115,6 +125,7 @@ class Player {
void receive (unsigned char* buffer); void receive (unsigned char* buffer);
friend class LevelPlayer; friend class LevelPlayer;
friend class JJ2LevelPlayer;
}; };
...@@ -127,7 +138,7 @@ EXTERN int nPlayers; ...@@ -127,7 +138,7 @@ EXTERN int nPlayers;
// Configuration data // Configuration data
EXTERN char* characterName; EXTERN char* characterName;
EXTERN unsigned char characterCols[4]; EXTERN unsigned char characterCols[PCOLOURS];
#endif #endif
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