Commit 40768f56 authored by alistert's avatar alistert

Added new font. More work on bonus levels.

parent 30bfea2a
......@@ -70,41 +70,61 @@
#define LEVEL_FILE "openjazz.tmp"
#ifdef UPPERCASE_FILENAMES
#define F_MAINCHAR "MAINCHAR.000"
#define F_MENU "MENU.000"
#define F_PANEL "PANEL.000"
#define F_SOUNDS "SOUNDS.000"
#define F_BONUS "BONUS.000"
#define F_STARTUP_0SC "STARTUP.0SC"
#define F_END_0SC "END.0SC"
#define F_MACRO "MACRO.2"
#define F_FONTS "FONTS.000"
#define F_MAINCHAR "MAINCHAR.000"
#define F_MENU "MENU.000"
#define F_PANEL "PANEL.000"
#define F_SOUNDS "SOUNDS.000"
#define F_BONUS "BONUS.000"
#define F_BONUS_0SC "BONUS.0SC"
#define F_END_0SC "END.0SC"
#define F_INSTRUCT_0SC "INSTRUCT.0SC"
#define F_ORDER_0SC "ORDER.0SC"
#define F_STARTUP_0SC "STARTUP.0SC"
#define F_MACRO "MACRO.2"
#define F_FONT2_0FN "FONT2.0FN"
#define F_FONTBIG_0FN "FONTBIG.0FN"
#define F_FONTINY_0FN "FONTINY.0FN"
#define F_FONTMN1_0FN "FONTMN1.0FN"
#define F_FONTMN2_0FN "FONTMN2.0FN"
// File path prefixes
#define F_BLOCKS "BLOCKS"
#define F_BONUSMAP "BONUSMAP"
#define F_LEVEL "LEVEL"
#define F_PLANET "PLANET"
#define F_SPRITES "SPRITES"
#define F_BLOCKS "BLOCKS"
#define F_BONUSMAP "BONUSMAP"
#define F_LEVEL "LEVEL"
#define F_PLANET "PLANET"
#define F_SPRITES "SPRITES"
#else
#define F_MAINCHAR "mainchar.000"
#define F_MENU "menu.000"
#define F_PANEL "panel.000"
#define F_SOUNDS "sounds.000"
#define F_BONUS "bonus.000"
#define F_STARTUP_0SC "startup.0sc"
#define F_END_0SC "end.0sc"
#define F_MACRO "macro.2"
#define F_FONTS "fonts.000"
#define F_MAINCHAR "mainchar.000"
#define F_MENU "menu.000"
#define F_PANEL "panel.000"
#define F_SOUNDS "sounds.000"
#define F_BONUS "bonus.000"
#define F_BONUS_0SC "bonus.0sc"
#define F_END_0SC "end.0sc"
#define F_INSTRUCT_0SC "instruct.0SC"
#define F_ORDER_0SC "order.0SC"
#define F_STARTUP_0SC "startup.0sc"
#define F_MACRO "macro.2"
#define F_FONT2_0FN "font2.0fn"
#define F_FONTBIG_0FN "fontbig.0fn"
#define F_FONTINY_0FN "fontiny.0fn"
#define F_FONTMN1_0FN "fontmn1.0fn"
#define F_FONTMN2_0FN "fontmn2.0fn"
// File path prefixes
#define F_BLOCKS "blocks"
#define F_BONUSMAP "bonusmap"
#define F_LEVEL "level"
#define F_PLANET "planet"
#define F_SPRITES "sprites"
#define F_BLOCKS "blocks"
#define F_BONUSMAP "bonusmap"
#define F_LEVEL "level"
#define F_PLANET "planet"
#define F_SPRITES "sprites"
#endif
// Standard string length
......
......@@ -26,6 +26,7 @@
*/
#include "game/game.h"
#include "io/gfx/font.h"
#include "io/gfx/video.h"
#include "player/player.h"
......@@ -39,6 +40,9 @@ BaseLevel::BaseLevel () {
paused = false;
// Set the level stage
stage = LS_NORMAL;
return;
}
......@@ -151,3 +155,28 @@ void BaseLevel::drawStats (int stats) {
}
void BaseLevel::addTimer () {
unsigned char buffer[MTL_L_PROP];
if (stage != LS_NORMAL) return;
endTime += 2 * 60 * 1000; // 2 minutes. Is this right?
if (gameMode) {
buffer[0] = MTL_L_PROP;
buffer[1] = MT_L_PROP;
buffer[2] = 2; // add timer
buffer[3] = 0;
buffer[4] = 0; // Don't really matter
game->send(buffer);
}
return;
}
......@@ -46,6 +46,15 @@
#define TTOI(x) ((x) << 5)
// Enum
enum LevelStage {
LS_NORMAL = 0, LS_SUDDENDEATH = 1, LS_END = 2
};
// Classes
class BaseLevel {
......@@ -58,12 +67,15 @@ class BaseLevel {
float smoothfps;
int items;
bool paused;
LevelStage stage;
void timeCalcs ();
void drawStats (int stats);
public:
BaseLevel ();
BaseLevel ();
void addTimer ();
};
......
......@@ -26,7 +26,8 @@
*/
#include "bonus.h"
#include "bonus.h"
#include "game/game.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/file.h"
......@@ -146,7 +147,37 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
delete[] buffer;
file->seek(178, false);
// Set the tick at which the level will end
endTime = file->loadShort() * 1000;
// Number of gems to collect
items = file->loadShort();
// The players' coordinates
x = file->loadShort();
y = file->loadShort();
if (game) game->setCheckpoint(x, y);
// Set the players' initial values
if (game) {
for (x = 0; x < nPlayers; x++)
game->resetPlayer(players + x, true);
} else {
localPlayer->reset();
localPlayer->setPosition(TTOF(x) + F16, TTOF(y) + F16);
}
delete file;
......@@ -168,12 +199,8 @@ Bonus::Bonus (char * fileName, unsigned char diff) {
// Apply the palette to surfaces that already exist, e.g. fonts
usePalette(palette);
// Adjust fontmn1 to use bonuslevel palette
fontmn1->mapPalette(224, 8, 0, 16);
// Set the tick at which the level will end
endTime = (5 - diff) * 30 * 1000;
// Adjust fontmn1 to use bonus level palette
fontsFont->mapPalette(0, 16, 15, -16);
return;
......@@ -193,12 +220,186 @@ Bonus::~Bonus () {
SDL_FreeSurface(tileSet);
fontmn1->restorePalette();
fontsFont->restorePalette();
return;
}
int Bonus::step () {
fixed playerX, playerY;
int gridX, gridY;
int msps;
int count;
// Milliseconds per step
msps = ticks - prevStepTicks;
prevStepTicks = ticks;
// Check if time has run out
if (ticks > endTime) return LOST;
// Apply controls to local player
for (count = 0; count < PCONTROLS; count++)
localPlayer->setControl(count, controls.getState(count));
// Process players
for (count = 0; count < nPlayers; count++) {
players[count].bonusStep(ticks, msps);
playerX = players[count].getX();
playerY = players[count].getY();
gridX = FTOT(playerX);
gridY = FTOT(playerY);
if ((playerX > TTOF(gridX) + F12) && (playerX < TTOF(gridX) + F20) &&
(playerY > TTOF(gridY) + F12) && (playerY < TTOF(gridY) + F20)) {
while (gridX < 0) gridX += BLW;
while (gridY < 0) gridY += BLH;
switch (events[gridY][gridX]) {
case 1: // Extra time
addTimer();
events[gridY][gridX] = 0;
break;
case 2: // Gem
players[count].addItem();
events[gridY][gridX] = 0;
if (players[count].getItems() >= items) return WON;
break;
case 3: // Hand
players[count].setSpeed(0, 0);
break;
case 4: // Exit
return LOST;
default:
// Do nothing
break;
}
}
}
return E_NONE;
}
void Bonus::draw () {
SDL_Rect src, dst;
int x, y;
src.x = 0;
src.w = 32;
src.h = 32;
int vX = FTOI(localPlayer->getX()) - (canvasW >> 1);
int vY = FTOI(localPlayer->getY()) - (canvasH >> 1);
for (y = 0; y <= ITOT(canvasH - 1) + 1; y++) {
for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) {
src.y = TTOI(tiles[(y + ITOT(vY) + BLH) % BLH][(x + ITOT(vX) + BLW) % BLW]);
dst.x = TTOI(x) - (vX & 31);
dst.y = TTOI(y) - (vY & 31);
SDL_BlitSurface(tileSet, &src, canvas, &dst);
dst.x = 12 + TTOI(x) - (vX & 31);
dst.y = 12 + TTOI(y) - (vY & 31);
switch (events[(y + ITOT(vY) + BLH) % BLH][(x + ITOT(vX) + BLW) % BLW]) {
case 0: // No event
break;
case 1: // Extra time
drawRect(dst.x, dst.y, 8, 8, 60);
break;
case 2: // Gem
drawRect(dst.x, dst.y, 8, 8, 67);
break;
case 3: // Hand
drawRect(dst.x, dst.y, 8, 8, 15);
break;
case 4: // Exit
drawRect(dst.x, dst.y, 8, 8, 45);
break;
default:
drawRect(dst.x, dst.y, 8, 8, 0);
break;
}
}
}
// Draw the "player"
drawRect(
(canvasW >> 1) + fixed(sin(localPlayer->getDirection() * 6.283185 / 1024.0) * 3) - 4,
(canvasH >> 1) - fixed(cos(localPlayer->getDirection() * 6.283185 / 1024.0) * 3) - 4, 8, 8, 0);
drawRect((canvasW >> 1) - 4, (canvasH >> 1) - 4, 8, 8, 22);
// Show gem count
fontsFont->showString("x", 15, 0);
fontsFont->showNumber(localPlayer->getItems(), 64, 0);
fontsFont->showNumber(items, 117, 0);
// Show time remaining
if (endTime > ticks) x = (endTime - ticks) / 1000;
else x = 0;
fontsFont->showNumber(x / 60, 242, 0);
fontsFont->showNumber(x % 60, 286, 0);
return;
}
int Bonus::play () {
......@@ -206,9 +407,8 @@ int Bonus::play () {
PaletteEffect *levelPE;
bool pmenu, pmessage;
int stats, option;
SDL_Rect src, dst;
int x, y;
int msps;
unsigned int returnTime;
int count;
tickOffset = globalTicks;
......@@ -219,9 +419,6 @@ int Bonus::play () {
option = 0;
stats = S_NONE;
// Arbitrary position
localPlayer->setPosition(TTOF(32) + F16, TTOF(7) + F16);
while (true) {
if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT;
......@@ -294,104 +491,43 @@ int Bonus::play () {
timeCalcs();
// Milliseconds per step
msps = ticks - prevStepTicks;
prevStepTicks = ticks;
// Check if level has been won
if (returnTime && (ticks > returnTime)) {
if (!paused) {
if (localPlayer->getItems() >= items) return WON;
// Apply controls to local player
for (x = 0; x < PCONTROLS; x++)
localPlayer->setControl(x, controls.getState(x));
// Process players
for (x = 0; x < nPlayers; x++) players[x].bonusStep(ticks, msps);
return LOST;
}
src.x = 0;
src.w = 32;
src.h = 32;
int vX = FTOI(localPlayer->getX()) - (canvasW >> 1);
int vY = FTOI(localPlayer->getY()) - (canvasH >> 1);
for (y = 0; y <= ITOT(canvasH - 1) + 1; y++) {
for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) {
src.y = TTOI(tiles[(y + ITOT(vY) + BLH) % BLH][(x + ITOT(vX) + BLW) % BLW]);
dst.x = TTOI(x) - (vX & 31);
dst.y = TTOI(y) - (vY & 31);
SDL_BlitSurface(tileSet, &src, canvas, &dst);
dst.x = 12 + TTOI(x) - (vX & 31);
dst.y = 12 + TTOI(y) - (vY & 31);
switch (events[(y + ITOT(vY) + BLH) % BLH][(x + ITOT(vX) + BLW) % BLW]) {
case 0: // No event
break;
case 1: // Extra time
drawRect(dst.x, dst.y, 8, 8, 60);
// Process frame-by-frame activity
break;
case 2: // Gem
if (!paused && (ticks >= prevStepTicks + 16) && (stage == LS_NORMAL)) {
drawRect(dst.x, dst.y, 8, 8, 67);
count = step();
break;
if (count < 0) return count;
else if (count) {
case 3: // Hand
drawRect(dst.x, dst.y, 8, 8, 15);
break;
case 4: // Exit
drawRect(dst.x, dst.y, 8, 8, 45);
break;
default:
drawRect(dst.x, dst.y, 8, 8, 0);
break;
}
stage = LS_END;
firstPE = new WhiteOutPaletteEffect(T_BONUS_END, firstPE);
returnTime = ticks + T_BONUS_END;
}
}
}
// Draw the "player"
drawRect(
(canvasW >> 1) + fixed(sin(localPlayer->getDirection() * 6.283185 / 1024.0) * 3) - 4,
(canvasH >> 1) - fixed(cos(localPlayer->getDirection() * 6.283185 / 1024.0) * 3) - 4, 8, 8, 0);
drawRect((canvasW >> 1) - 4, (canvasH >> 1) - 4, 8, 8, 22);
// Draw the graphics
// Show time remaining
if (endTime > ticks) x = endTime - ticks;
else x = 0;
y = x / (60 * 1000);
fontmn1->showNumber(y, 144, 8);
x -= (y * 60 * 1000);
y = x / 1000;
fontmn1->showNumber(y, 192, 8);
draw();
// If paused, draw "PAUSE"
if (paused && !pmenu)
fontmn1->showString("pause", (canvasW >> 1) - 44, 32);
if (pmessage && !pmenu)
fontsFont->showString("pause", (canvasW >> 1) - 44, 32);
// Draw statistics
drawStats(stats);
......@@ -403,12 +539,12 @@ int Bonus::play () {
drawRect((canvasW >> 2) - 8, (canvasH >> 1) - 46, 144, 60, 0);
for (x = 0; x < 3; x++) {
for (count = 0; count < 3; count++) {
if (x == option) fontmn2->mapPalette(240, 8, 31, 16);
if (count == option) fontmn2->mapPalette(240, 8, 31, 16);
else fontmn2->mapPalette(240, 8, 0, 16);
fontmn2->showString(options[x], canvasW >> 2, (canvasH >> 1) + (x << 4) - 38);
fontmn2->showString(options[count], canvasW >> 2, (canvasH >> 1) + (count << 4) - 38);
}
......
......@@ -34,16 +34,20 @@
#define BLW 256 /* Bonus level width */
#define BLH 256 /* Bonus level height */
#define T_BONUS_END 1500
// Class
class Bonus : public BaseLevel {
private:
unsigned char tiles[BLH][BLW];
unsigned char events[BLH][BLW];
unsigned char tiles[BLH][BLW];
unsigned char events[BLH][BLW];
int loadTiles (char *fileName);
int loadTiles (char *fileName);
int step ();
void draw ();
public:
Bonus (char * fileName, unsigned char diff);
......
......@@ -148,6 +148,22 @@ int Game::play () {
levelRet = level->play();
if (levelRet < 0) {
delete level;
return levelRet;
} else if (levelRet == E_NONE) {
delete level;
playMusic("menusng.psm");
return E_NONE;
}
} else levelRet = WON;
......@@ -165,16 +181,63 @@ int Game::play () {
}
delete[] bonusFile;
bonusFile = NULL;
if (levelFile) {
delete[] bonusFile;
bonusFile = NULL;
}
bonusRet = bonus->play();
delete bonus;
if (bonusRet == E_QUIT) return E_QUIT;
if (bonusRet == E_QUIT) {
if (level) delete level;
return E_QUIT;
} else if (bonusRet == E_NONE) {
if (level) delete level;
playMusic("menusng.psm");
return E_NONE;
} else if (bonusRet == WON) {
try {
scene = new Scene(F_BONUS_0SC);
} catch (int e) {
scene = NULL;
}
if (scene) {
if (scene->play() == E_QUIT) {
delete scene;
if (level) delete level;
return E_QUIT;
}
if (bonusRet == E_NONE) return E_NONE;
delete scene;
}
// If part of a bonus-only game, go to next level
if (!level) setBonus((bonusFile[10] * 10) + bonusFile[11] - 527);
}
}
......@@ -182,59 +245,51 @@ int Game::play () {
if (!level) continue;
switch (levelRet) {
if (levelRet == WON) {
// Won the level
// If there is no next level, load and play the cutscene
if (!levelFile) {
case E_NONE: // Quit game
scene = level->createScene();
delete level;
if (scene) {
if (scene->play() == E_QUIT) {
delete scene;
return E_QUIT;
}
playMusic("menusng.psm");
delete scene;
}
return E_NONE;
case WON: // Completed level
// If there is no next level, load and play the cutscene
if (!levelFile) {
scene = level->createScene();
delete level;
scene->play();
delete scene;
return E_NONE;
}
}
delete level;
// Do not use old level's checkpoint coordinates
checkpoint = false;
// Do not use old level's checkpoint coordinates
checkpoint = false;
break;
case LOST: // Lost level
delete level;
} else {
if (!localPlayer->getLives()) return E_NONE; // Not really a success...
// Use checkpoint coordinates
checkpoint = true;
// Lost the level
break;
if (!localPlayer->getLives()) return E_NONE;
default: // Error
delete level;
return levelRet;
// Use checkpoint coordinates
checkpoint = true;
}
delete level;
}
return E_NONE;
......@@ -294,10 +349,10 @@ void Game::setCheckpoint (unsigned char gridX, unsigned char gridY) {
}
void Game::resetPlayer (Player *player) {
void Game::resetPlayer (Player *player, bool bonus) {
player->reset();
player->setPosition(TTOF(checkX), TTOF(checkY));
player->setPosition(TTOF(checkX) + (bonus? F16: 0), TTOF(checkY) + (bonus? F16: 0));
return;
......
......@@ -105,7 +105,7 @@ class Game {
virtual int step (unsigned int ticks);
virtual void score (unsigned char team);
virtual void setCheckpoint (unsigned char gridX, unsigned char gridY);
void resetPlayer (Player *player);
void resetPlayer (Player *player, bool bonus);
};
......
......@@ -105,7 +105,7 @@ unsigned char FreeForAllGameMode::chooseTeam () {
void FreeForAllGameMode::drawScore () {
fontmn1->showNumber(localPlayer->teamScore, 64, 4);
fontsFont->showNumber(localPlayer->teamScore, 64, 4);
return;
......@@ -140,7 +140,7 @@ unsigned char TeamGameMode::chooseTeam () {
void TeamGameMode::drawScore () {
fontmn1->showNumber(localPlayer->teamScore, 64, 4);
fontsFont->showNumber(localPlayer->teamScore, 64, 4);
return;
......@@ -199,7 +199,7 @@ bool RaceGameMode::endOfLevel (Player *player, unsigned char gridX,
if (player == localPlayer) game->score(player->getTeam());
game->resetPlayer(player);
game->resetPlayer(player, false);
return false;
......
......@@ -36,7 +36,7 @@
Font::Font (const char * fileName) {
File *file;
unsigned char *pixels;
unsigned char *pixels, *blank;
int fileSize;
int count, size, width, height;
......@@ -52,30 +52,24 @@ Font::Font (const char * fileName) {
}
fileSize = file->getSize();
file->seek(20, true);
lineHeight = file->loadChar() << 1;
nCharacters = 128;
// Create the first character
pixels = new unsigned char[3 * lineHeight];
file->seek(20, true);
lineHeight = file->loadChar() << 1;
memset(pixels, 0, 3 * lineHeight);
characters[0] = createSurface(pixels, 3, lineHeight);
SDL_SetColorKey(characters[0], SDL_SRCCOLORKEY, 0);
delete[] pixels;
// Create blank character data
blank = new unsigned char[3];
memset(blank, 0, 3);
// Create remaining characters
fileSize = file->getSize();
nCharacters = 128;
file->seek(23, true);
// Load characters
for (count = 1; count < 128; count++) {
for (count = 0; count < 128; count++) {
size = file->loadShort();
......@@ -97,13 +91,16 @@ Font::Font (const char * fileName) {
height += pixels[3] << 8;
characters[count] = createSurface(pixels + 4, width, height);
SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 0);
delete[] pixels;
} else characters[count] = createSurface(NULL, 1, 1);
} else characters[count] = createSurface(blank, 3, 1);
SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 0);
}
delete[] blank;
delete file;
......@@ -174,18 +171,19 @@ Font::Font (unsigned char *pixels, bool big) {
delete[] chrPixels;
// Create ASCII->font map
if (big) {
// Goes " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-:."
// Create ASCII->font map
for (count = 0; count < 45; count++) map[count] = 0;
map[45] = 37;
map[46] = 39;
for (count = 47; count < 48; count++) map[count] = 0;
map[count++] = 37;
map[count++] = 39;
for (; count < 48; count++) map[count] = 0;
for (; count < 58; count++) map[count] = count - 47;
map[58] = 38;
for (count = 59; count < 65; count++) map[count] = 0;
map[count++] = 38;
for (; count < 65; count++) map[count] = 0;
for (; count < 91; count++) map[count] = count - 54;
for (; count < 97; count++) map[count] = 0;
for (; count < 123; count++) map[count] = count - 86;
......@@ -194,10 +192,9 @@ Font::Font (unsigned char *pixels, bool big) {
} else {
// Goes " 0123456789oo" (where oo = infinity)
// Use :; to represent the infinity symbol
// Create ASCII->font map
for (count = 0; count < 48; count++) map[count] = 0;
// Use :; to represent the infinity symbol
for (; count < 60; count++) map[count] = count - 47;
for (; count < 128; count++) map[count] = 0;
......@@ -208,6 +205,98 @@ Font::Font (unsigned char *pixels, bool big) {
}
Font::Font () {
File *file;
unsigned char *pixels, *sorted;
int fileSize;
int count, width, height;
// Load font from FONTS.000
try {
file = new File(F_FONTS, false);
} catch (int e) {
throw e;
}
fileSize = file->getSize();
nCharacters = file->loadShort();
// Load characters
for (count = 0; count < nCharacters; count++) {
width = file->loadShort() << 2;
height = file->loadShort();
file->seek(4, false);
if (file->tell() >= fileSize) {
nCharacters = count;
break;
}
pixels = file->loadBlock(width * height);
sorted = sortPixels(pixels, width * height);
characters[count] = createSurface(sorted, width, height);
SDL_SetColorKey(characters[count], SDL_SRCCOLORKEY, 254);
delete[] sorted;
delete[] pixels;
}
delete file;
lineHeight = characters[0]->h;
// Create blank character data
pixels = new unsigned char[3];
memset(pixels, 254, 3);
characters[nCharacters] = createSurface(pixels, 3, 1);
SDL_SetColorKey(characters[nCharacters], SDL_SRCCOLORKEY, 254);
delete[] pixels;
// Create ASCII->font map
for (count = 0; count < 37; count++) map[count] = nCharacters;
map[count++] = 36;
for (; count < 48; count++) map[count] = nCharacters;
for (; count < 58; count++) map[count] = count - 22;
for (; count < 65; count++) map[count] = nCharacters;
for (; count < 91; count++) map[count] = count - 65;
for (; count < 97; count++) map[count] = nCharacters;
for (; count < 123; count++) map[count] = count - 97;
for (; count < 128; count++) map[count] = nCharacters;
nCharacters++;
for (count = 0; count < 128; count++) {
if (map[count] >= nCharacters) map[count] = 0;
}
return;
}
Font::~Font () {
int count;
......
......@@ -44,6 +44,7 @@ class Font {
public:
Font (const char *fileName);
Font (unsigned char *pixels, bool big);
Font ();
~Font ();
int showString (const char *s, int x, int y);
......@@ -56,6 +57,7 @@ class Font {
int getSceneStringWidth (const unsigned char *string);
};
// Variables
......@@ -64,8 +66,9 @@ EXTERN Font *fontbig; /* Taken from .0FN file name */
EXTERN Font *fontiny; /* Taken from .0FN file name */
EXTERN Font *fontmn1; /* Taken from .0FN file name */
EXTERN Font *fontmn2; /* Taken from .0FN file name */
EXTERN Font *panelBigFont; /* Not a font file, found in PANEL.000 */
EXTERN Font *panelSmallFont; /* Not a font file, found in PANEL.000 */
EXTERN Font *panelBigFont; /* Found in PANEL.000 */
EXTERN Font *panelSmallFont; /* Found in PANEL.000 */
EXTERN Font *fontsFont; /* Found in FONTS.000 */
#endif
......@@ -59,11 +59,17 @@ void Sprite::clearPixels () {
void Sprite::setPixels (unsigned char *data, int width, int height) {
unsigned char *sorted;
if (pixels) SDL_FreeSurface(pixels);
sorted = sortPixels(data, width * height);
pixels = createSurface(data, width, height);
pixels = createSurface(sorted, width, height);
SDL_SetColorKey(pixels, SDL_SRCCOLORKEY, SKEY);
delete[] sorted;
return;
......
......@@ -31,6 +31,25 @@
#include <string.h>
unsigned char * sortPixels (unsigned char * pixels, int length) {
unsigned char *sorted;
int count;
sorted = new unsigned char[length];
// Rearrange pixels in correct order
for (count = 0; count < length; count++) {
sorted[count] = pixels[(count >> 2) + ((count & 3) * (length >> 2))];
}
return sorted;
}
SDL_Surface * createSurface (unsigned char * pixels, int width, int height) {
SDL_Surface *ret;
......
......@@ -75,12 +75,13 @@ EXTERN SDL_Surface *panelAmmo[5];
// Functions
EXTERN SDL_Surface * createSurface (unsigned char *pixels, int width, int height);
EXTERN void createScreen ();
EXTERN void usePalette (SDL_Color *palette);
EXTERN void restorePalette (SDL_Surface *surface);
EXTERN void clearScreen (int index);
EXTERN void drawRect (int x, int y, int width, int height, int index);
EXTERN unsigned char * sortPixels (unsigned char *pixels, int length);
EXTERN SDL_Surface * createSurface (unsigned char *pixels, int width, int height);
EXTERN void createScreen ();
EXTERN void usePalette (SDL_Color *palette);
EXTERN void restorePalette (SDL_Surface *surface);
EXTERN void clearScreen (int index);
EXTERN void drawRect (int x, int y, int width, int height, int index);
#endif
......
......@@ -171,7 +171,7 @@ int DemoLevel::play () {
drawStats(stats);
fontmn1->showString("demo", (canvasW >> 1) - 36, 32);
fontsFont->showString("demo", (canvasW >> 1) - 36, 32);
}
......
......@@ -130,8 +130,6 @@ Level::~Level () {
delete[] spriteSet;
fontmn1->restorePalette();
delete[] sceneFile;
return;
......@@ -371,31 +369,6 @@ Anim * Level::getMiscAnim (unsigned char anim) {
}
void Level::addTimer () {
unsigned char buffer[MTL_L_PROP];
if (stage != LS_NORMAL) return;
endTime += 2 * 60 * 1000; // 2 minutes. Is this right?
if (gameMode) {
buffer[0] = MTL_L_PROP;
buffer[1] = MT_L_PROP;
buffer[2] = 2; // add timer
buffer[3] = 0;
buffer[4] = 0; // Don't really matter
game->send(buffer);
}
return;
}
void Level::setWaterLevel (unsigned char gridY) {
unsigned char buffer[MTL_L_PROP];
......@@ -417,6 +390,7 @@ void Level::setWaterLevel (unsigned char gridY) {
return;
}
fixed Level::getWaterLevel () {
......@@ -464,8 +438,16 @@ LevelStage Level::getStage () {
Scene * Level::createScene () {
return new Scene(sceneFile);
try {
return new Scene(sceneFile);
} catch (int e) {
return NULL;
}
}
......@@ -626,7 +608,6 @@ int Level::play () {
timeCalcs();
// Check if level has been won
if (game && returnTime && (ticks > returnTime)) {
......@@ -648,36 +629,16 @@ int Level::play () {
// Process frame-by-frame activity
if (!paused) {
if (!paused && (ticks >= prevStepTicks + 16)) {
// Apply controls to local player
for (count = 0; count < PCONTROLS; count++)
localPlayer->setControl(count, controls.getState(count));
// Process step
if (ticks >= prevStepTicks + 16) {
count = step();
if (count < 0) return count;
}
// Handle player reactions
for (count = 0; count < nPlayers; count++) {
if (players[count].reacted(ticks) == PR_KILLED) {
if (!gameMode) return LOST;
game->resetPlayer(players + count);
}
}
// Apply controls to local player
for (count = 0; count < PCONTROLS; count++)
localPlayer->setControl(count, controls.getState(count));
count = step();
if (count) return count;
}
......@@ -687,8 +648,8 @@ int Level::play () {
// If paused, draw "PAUSE"
if (paused && !pmenu)
fontmn1->showString("pause", (canvasW >> 1) - 44, 32);
if (pmessage && !pmenu)
fontsFont->showString("pause", (canvasW >> 1) - 44, 32);
// If this is a competitive game, draw the score
......@@ -744,28 +705,30 @@ int Level::play () {
// Display statistics & bonuses
// TODO: Display percentage symbol
fontmn1->showString("time", (canvasW >> 1) - 152, (canvasH >> 1) - 60);
fontmn1->showNumber(timeBonus, (canvasW >> 1) + 124, (canvasH >> 1) - 60);
fontsFont->showString("time", (canvasW >> 1) - 152, (canvasH >> 1) - 60);
fontsFont->showNumber(timeBonus, (canvasW >> 1) + 124, (canvasH >> 1) - 60);
fontmn1->showString("enemies", (canvasW >> 1) - 152, (canvasH >> 1) - 40);
fontsFont->showString("enemies", (canvasW >> 1) - 152, (canvasH >> 1) - 40);
if (enemies)
fontmn1->showNumber((localPlayer->getEnemies() * 100) / enemies, (canvasW >> 1) + 124, (canvasH >> 1) - 40);
fontsFont->showNumber((localPlayer->getEnemies() * 100) / enemies, (canvasW >> 1) + 124, (canvasH >> 1) - 40);
else
fontmn1->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 40);
fontsFont->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 40);
fontsFont->showString("%", (canvasW >> 1) + 124, (canvasH >> 1) - 40);
fontmn1->showString("items", (canvasW >> 1) - 152, (canvasH >> 1) - 20);
fontsFont->showString("items", (canvasW >> 1) - 152, (canvasH >> 1) - 20);
if (items)
fontmn1->showNumber((localPlayer->getItems() * 100) / items, (canvasW >> 1) + 124, (canvasH >> 1) - 20);
fontsFont->showNumber((localPlayer->getItems() * 100) / items, (canvasW >> 1) + 124, (canvasH >> 1) - 20);
else
fontmn1->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 20);
fontsFont->showNumber(0, (canvasW >> 1) + 124, (canvasH >> 1) - 20);
fontsFont->showString("%", (canvasW >> 1) + 124, (canvasH >> 1) - 20);
fontmn1->showString("perfect", (canvasW >> 1) - 152, canvasH >> 1);
fontmn1->showNumber(perfect, (canvasW >> 1) + 124, canvasH >> 1);
fontsFont->showString("perfect", (canvasW >> 1) - 152, canvasH >> 1);
fontsFont->showNumber(perfect, (canvasW >> 1) + 124, canvasH >> 1);
fontmn1->showString("score", (canvasW >> 1) - 152, (canvasH >> 1) + 40);
fontmn1->showNumber(localPlayer->getScore(), (canvasW >> 1) + 124, (canvasH >> 1) + 40);
fontsFont->showString("score", (canvasW >> 1) - 152, (canvasH >> 1) + 40);
fontsFont->showNumber(localPlayer->getScore(), (canvasW >> 1) + 124, (canvasH >> 1) + 40);
}
......
......@@ -57,15 +57,6 @@
#define T_END 1000
// Enum
enum LevelStage {
LS_NORMAL = 0, LS_SUDDENDEATH = 1, LS_END = 2
};
// Datatypes
typedef struct {
......@@ -119,7 +110,6 @@ class Level : public BaseLevel {
fixed waterLevelTarget;
fixed waterLevelSpeed;
fixed energyBar;
LevelStage stage;
int loadSprites (char *fileName);
int loadTiles (char *fileName);
......@@ -153,7 +143,6 @@ class Level : public BaseLevel {
Sprite * getSprite (unsigned char sprite);
Anim * getAnim (unsigned char anim);
Anim * getMiscAnim (unsigned char anim);
void addTimer ();
void setWaterLevel (unsigned char gridY);
fixed getWaterLevel ();
void playSound (int sound);
......
......@@ -34,6 +34,7 @@
#include "game/game.h"
#include "game/gamemode.h"
#include "io/controls.h"
#include "io/gfx/font.h"
#include "io/gfx/video.h"
#include "player/player.h"
......@@ -169,6 +170,20 @@ int Level::step () {
waterLevel += (waterLevelSpeed * msps) >> 10;
// Handle player reactions
for (x = 0; x < nPlayers; x++) {
if (players[x].reacted(ticks) == PR_KILLED) {
if (!gameMode) return LOST;
game->resetPlayer(players + x, false);
}
}
return E_NONE;
}
......@@ -184,17 +199,11 @@ void Level::draw () {
int vX, vY;
int x, y, bgScale;
unsigned int change;
// Set tile drawing dimensions
src.w = TTOI(1);
src.h = TTOI(1);
src.x = 0;
// Calculate viewport
if (game && (stage == LS_END)) game->view((ticks - prevTicks) * 160);
else localPlayer->view(ticks, ticks - prevTicks);
if (game && (stage == LS_END)) game->view(paused? 0: ((ticks - prevTicks) * 160));
else localPlayer->view(ticks, paused? 0: (ticks - prevTicks));
// Ensure the new viewport is within the level
if (viewX < 0) viewX = 0;
......@@ -211,9 +220,15 @@ void Level::draw () {
dst.h = viewH;
SDL_SetClipRect(canvas, &dst);
if ((viewW < canvasW) || (viewH < canvasH)) clearScreen(15);
// Set tile drawing dimensions
src.w = TTOI(1);
src.h = TTOI(1);
src.x = 0;
// If there is a sky, draw it
if (sky) {
......
......@@ -50,7 +50,7 @@
int Level::loadSprites (char * fileName) {
File *file, *mainFile, *specFile;
unsigned char *pixels, *sorted;
unsigned char *pixels, *mask;
int mainPos, specPos;
int count, x, y, width, height, m;
......@@ -157,11 +157,10 @@ int Level::loadSprites (char * fileName) {
}
// m is for MAGIC
m = file->loadShort();
// Allocate space for descrambling
sorted = new unsigned char[width * height];
// Allocate space for mask
mask = new unsigned char[width * height];
// Actually, m is for mask offset.
// Sprites can be either masked or not masked.
......@@ -219,9 +218,7 @@ int Level::loadSprites (char * fileName) {
for (x = 0; x < width; x++) {
sorted[(((y >> 2) + ((x & 3) * (height >> 2))) * width) +
(x >> 2) +
(((y & 3) + ((height & 3) * (x & 3))) * (width >> 2))] =
mask[((y + ((x & 3) * height)) * (width >> 2)) + (x >> 2)] =
pixels[(y * width) + x];
}
......@@ -240,7 +237,7 @@ int Level::loadSprites (char * fileName) {
for (x = 0; x < width; x++) {
if (sorted[(y * width) + x] == 1) {
if (mask[(y * width) + x] == 1) {
// The unmasked portions are transparent, so no masked
// portion should be transparent.
......@@ -265,27 +262,13 @@ int Level::loadSprites (char * fileName) {
}
// Rearrange pixels in correct order
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
sorted[(y * width) + x] =
pixels[(((y >> 2) + ((x & 3) * (height >> 2))) * width) +
(x >> 2) +
(((y & 3) + ((height & 3) * (x & 3))) * (width >> 2))];
}
}
// Convert the sprite to an SDL surface
spriteSet[count].setPixels(sorted, width, height);
// Convert the scrambled sprite to an SDL surface
spriteSet[count].setPixels(pixels, width, height);
// Free redundant data
delete[] pixels;
delete[] sorted;
delete[] mask;
// Check if the next sprite exists
......@@ -829,7 +812,7 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
if (game) {
for (count = 0; count < nPlayers; count++)
game->resetPlayer(players + count);
game->resetPlayer(players + count, false);
} else {
......@@ -1016,16 +999,10 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
// Apply the palette to surfaces that already exist, e.g. fonts
usePalette(palette);
// Adjust fontmn1 to use level palette
fontmn1->mapPalette(224, 8, 14, -16);
// Set the tick at which the level will end
endTime = (5 - difficulty) * 2 * 60 * 1000;
// Set the level stage
stage = LS_NORMAL;
firstBullet = NULL;
firstEvent = NULL;
......
......@@ -403,16 +403,18 @@ int loadMain (int argc, char *argv[]) {
try {
fontsFont = new Font();
panelBigFont = new Font(pixels + (40 * 320), true);
panelSmallFont = new Font(pixels + (48 * 320), false);
font2 = new Font("font2.0fn");
fontbig = new Font("fontbig.0fn");
fontiny = new Font("fontiny.0fn");
fontmn1 = new Font("fontmn1.0fn");
fontmn2 = new Font("fontmn2.0fn");
font2 = new Font(F_FONT2_0FN);
fontbig = new Font(F_FONTBIG_0FN);
fontiny = new Font(F_FONTINY_0FN);
fontmn1 = new Font(F_FONTMN1_0FN);
fontmn2 = new Font(F_FONTMN2_0FN);
} catch (int e) {
if (fontsFont) delete fontsFont;
if (panelBigFont) delete panelBigFont;
if (panelSmallFont) delete panelSmallFont;
if (font2) delete font2;
......@@ -568,25 +570,52 @@ int loop (LoopType type) {
SDL_Color shownPalette[256];
SDL_Event event;
int prevTicks, ret;
// Show everything that has been drawn so far
#ifdef SCALE
if (canvas != screen) {
scale(scaleFactor,
screen->pixels, screen->pitch,
canvas->pixels, canvas->pitch,
screen->format->BytesPerPixel, canvas->w, canvas->h);
}
#endif
#ifdef SCALE
if (canvas != screen) {
// Copy everything that has been drawn so far
scale(scaleFactor,
screen->pixels, screen->pitch,
canvas->pixels, canvas->pitch,
screen->format->BytesPerPixel, canvas->w, canvas->h);
}
#endif
// Update tick count
prevTicks = globalTicks;
globalTicks = SDL_GetTicks();
// Apply palette effects
if (firstPE) {
/* If the palette is being emulated, compile all palette changes and
apply them all at once.
If the palette is being used directly, apply all palette effects
directly. */
if (fakePalette) {
memcpy(shownPalette, currentPalette, sizeof(SDL_Color) * 256);
firstPE->apply(shownPalette, false, globalTicks - prevTicks);
SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette, 0, 256);
} else {
firstPE->apply(shownPalette, true, globalTicks - prevTicks);
}
}
// Show what has been drawn
SDL_Flip(screen);
prevTicks = globalTicks;
globalTicks = SDL_GetTicks();
// Process system events
while (SDL_PollEvent(&event)) {
......@@ -665,31 +694,6 @@ int loop (LoopType type) {
controls.loop();
// Apply palette effects
if (firstPE) {
/* If the palette is being emulated, compile all palette changes and
apply them all at once.
If the palette is being used directly, apply all palette effects
directly. */
if (fakePalette) {
memcpy(shownPalette, currentPalette, sizeof(SDL_Color) * 256);
firstPE->apply(shownPalette, false, globalTicks - prevTicks);
SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette, 0, 256);
} else {
firstPE->apply(shownPalette, true, globalTicks - prevTicks);
}
}
#if defined(WIZ) || defined(GP2X)
WIZ_AdjustVolume( volume_direction );
#endif
......
......@@ -110,7 +110,7 @@ int Menu::main () {
try {
scene = new Scene("instruct.0sc");
scene = new Scene(F_INSTRUCT_0SC);
} catch (int e) {
......@@ -142,7 +142,7 @@ int Menu::main () {
try {
scene = new Scene("order.0sc");
scene = new Scene(F_ORDER_0SC);
} catch (int e) {
......
......@@ -602,6 +602,15 @@ void Player::kill (Player *source, unsigned int ticks) {
}
void Player::addItem () {
items++;
return;
}
void Player::addScore (int addedScore) {
score += addedScore * 10;
......
......@@ -198,7 +198,7 @@ class Player : public Movable {
int enemies, items;
unsigned char team;
void addAmmo (int type, int amount);
void addAmmo (int type, int amount);
public:
int teamScore;
......@@ -219,6 +219,7 @@ class Player : public Movable {
void clearEvent (unsigned char gridX, unsigned char gridY);
bool hit (Player *source, unsigned int ticks);
void kill (Player *source, unsigned int ticks);
void addItem ();
void addScore (int addedScore);
int getScore ();
int getEnergy ();
......
......@@ -132,6 +132,7 @@ Scene::Scene (const char * fileName) {
}
background = NULL;
images = NULL;
palettes = NULL;
......@@ -180,6 +181,8 @@ Scene::~Scene () {
delete[] pages;
if (background) SDL_FreeSurface(background);
if (images) delete images;
if (palettes) delete palettes;
......@@ -194,9 +197,10 @@ int Scene::play () {
unsigned int pageTime = pages[sceneIndex].pageTime;
unsigned int lastTicks = globalTicks;
int newpage = true;
int fadein = false;
SDL_Rect textRect = {0, 0, SW, SH};
clearScreen(0);
while (true) {
if (loop(NORMAL_LOOP) == E_QUIT) return E_QUIT;
......@@ -240,7 +244,9 @@ int Scene::play () {
// usePalette(palette);
currentPalette = palette->palette;
fadein = true;
// Fade in from black
firstPE = new FadeInPaletteEffect(250, firstPE);
} else restorePalette(screen);
......@@ -260,14 +266,20 @@ int Scene::play () {
if (image) {
dst.x = (pages[sceneIndex].bgPos[bg] & 65535)*2 + (canvasW - SW) >> 1;
dst.y = ((pages[sceneIndex].bgPos[bg] & (~65535))>>16)*2 + (canvasH - SH) >> 1;
dst.x = pages[sceneIndex].bgX[bg] + ((canvasW - SW) >> 1);
dst.y = pages[sceneIndex].bgY[bg] + ((canvasH - SH) >> 1);
SDL_BlitSurface(image->image, NULL, canvas, &dst);
}
}
} else if (background) {
dst.x = (canvasW - SW) >> 1;
dst.y = (canvasH - SH) >> 1;
SDL_BlitSurface(background, NULL, canvas, &dst);
} else clearScreen(0);
......@@ -350,16 +362,6 @@ int Scene::play () {
}
// Fade in from black
if (fadein) {
fadein = false;
firstPE = new FadeInPaletteEffect(250, firstPE);
clearScreen(0);
}
}
return E_NONE;
......
......@@ -83,16 +83,17 @@ class SceneText {
class ScenePage {
public:
int backgrounds;
int bgIndex[30];
unsigned int bgPos[30];
int backgrounds;
int bgIndex[30];
unsigned short int bgX[30];
unsigned short int bgY[30];
// Length of the scene in seconds, or if zero = anim complete, or 256 = user interaction
int pageTime;
SceneText texts[100];
int nTexts;
char *musicFile;
int paletteIndex;
int pageTime;
SceneText texts[100];
int nTexts;
char *musicFile;
int paletteIndex;
ScenePage();
~ScenePage();
......@@ -133,7 +134,8 @@ class SceneFont {
class Scene {
private:
private:
SDL_Surface *background;
SceneImage *images;
ScenePalette *palettes;
SceneFont fonts[5];
......@@ -146,9 +148,9 @@ class Scene {
// Scripts all information needed to render script pages, text etc
ScenePage *pages;
void loadScripts (File *f);
void loadData (File *f);
void loadAni (File* f, int dataIndex);
void loadScripts (File *f);
void loadData (File *f);
void loadAni (File* f, int dataIndex);
public:
Scene (const char * fileName);
......
......@@ -111,20 +111,14 @@ void Scene::loadAni (File *f, int dataIndex) {
case 0x3131:
{
// Skip back size header, this is read by the surface reader
f->seek(-2, false);
// Skip back size header, this is read by the surface reader
f->seek(-2, false);
SDL_Surface *image = f->loadSurface(SW, SH);
SDL_BlitSurface(image, NULL, canvas, NULL);
SDL_FreeSurface(image);
if (!background) background = f->loadSurface(SW, SH);
// Use the most recently loaded palette
SDL_SetPalette(screen, SDL_PHYSPAL, palettes->palette, 0, 256);
currentPalette = palettes->palette;
}
// Use the most recently loaded palette
SDL_SetPalette(screen, SDL_PHYSPAL, palettes->palette, 0, 256);
currentPalette = palettes->palette;
break;
......@@ -461,19 +455,15 @@ void Scene::loadScripts (File *f) {
case ESceneBackground:
{
pages[loop].bgX[pages[loop].backgrounds] = f->loadShort();
pages[loop].bgY[pages[loop].backgrounds] = f->loadShort();
pages[loop].bgIndex[pages[loop].backgrounds] = f->loadShort();
unsigned short int xpos = f->loadShort();
unsigned short int ypos = f->loadShort();
unsigned short bgImageIndex = f->loadShort();
LOG("ESceneBackground: index", bgImageIndex);
LOG("ESceneBackground: xpos", xpos);
LOG("ESceneBackground: ypos", ypos);
pages[loop].bgIndex[pages[loop].backgrounds] = bgImageIndex;
pages[loop].bgPos[pages[loop].backgrounds] = xpos | (ypos << 16);
pages[loop].backgrounds++;
LOG("ESceneBackground: xpos", pages[loop].bgX[pages[loop].backgrounds]);
LOG("ESceneBackground: ypos", pages[loop].bgY[pages[loop].backgrounds]);
LOG("ESceneBackground: index", pages[loop].bgIndex[pages[loop].backgrounds]);
}
pages[loop].backgrounds++;
break;
......
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