Page MenuHomePhabricator (Chris)

No OneTemporary

Size
114 KB
Referenced Files
None
Subscribers
None
diff --git a/src/Backend.cpp b/src/Backend.cpp
index 0f82f2a..a06b7d0 100644
--- a/src/Backend.cpp
+++ b/src/Backend.cpp
@@ -1,329 +1,382 @@
/***************************************************************************
Backend.cpp - description
-------------------
begin : Mon Dec 9 2002
copyright : (C) 2002 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include "common.h"
#include "Backend.h"
#include "Audio.h"
#include <string>
#include <stdarg.h>
+#include <EXTERN.h>
+#include <perl.h>
/***************************************************************************
PUBLIC EXPORTED VARIABLES
***************************************************************************/
PerlInterpreter* my_perl;
Backend g_oBackend;
/***************************************************************************
PRIVATE VARIABLES (perl variable space)
***************************************************************************/
SV
*perl_bgx, *perl_bgy,
*perl_p1x, *perl_p1y, *perl_p1f, *perl_p1h,
*perl_p2x, *perl_p2y, *perl_p2f, *perl_p2h,
*perl_time, *perl_over, *perl_ko;
SV
*perl_doodad_x, *perl_doodad_y,
*perl_doodad_t, *perl_doodad_f,
*perl_doodad_text;
SV
*perl_sound;
/***************************************************************************
BACKEND CLASS IMPLEMENTATION
***************************************************************************/
+
+#define PERLEVAL(A) eval_pv(A, TRUE);
+
+#define PERLCALL(PROC,A,B) { \
+ dSP; \
+ ENTER; \
+ SAVETMPS; \
+ PUSHMARK(SP); \
+ XPUSHs(sv_2mortal(newSViv(A))); \
+ XPUSHs(sv_2mortal(newSViv(B))); \
+ PUTBACK ; \
+ \
+ call_pv( (PROC), G_DISCARD ); \
+ \
+ FREETMPS; \
+ LEAVE; \
+}
+
+
Backend::Backend()
{
m_iBgX = m_iBgY = 0;
m_iNumDoodads = m_iNumSounds = 0;
for ( int i=0; i<2; ++i )
{
m_aoPlayers[i].m_iX = m_aoPlayers[i].m_iY = 0;
m_aoPlayers[i].m_iFrame = 0;
m_aoPlayers[i].m_iHitPoints = 0;
}
}
Backend::~Backend()
{
if ( NULL != my_perl )
{
perl_destruct( my_perl );
perl_free( my_perl );
my_perl = NULL;
}
}
bool Backend::Construct()
{
if ( my_perl != NULL )
{
// Already inited
return false;
}
perl_bgx = NULL;
perl_doodad_x = NULL;
std::string sFileName = DATADIR;
sFileName += "/script";
chdir( sFileName.c_str() );
char *perl_argv[] = {"", "Backend.pl"};
my_perl = perl_alloc();
if ( my_perl == NULL )
{
return false;
}
perl_construct( my_perl );
if ( perl_parse( my_perl, NULL, 2, perl_argv, (char**)NULL ) )
{
char *error = SvPV_nolen(get_sv("@", FALSE));
fprintf( stderr, "%s", error );
return false;
}
if ( perl_run( my_perl ) )
{
char *error = SvPV_nolen(get_sv("@", FALSE));
fprintf( stderr, "%s", error );
return false;
}
return true;
}
-void Backend::PerlEvalF( const char* a_pcFormat, ... )
+const char* Backend::PerlEvalF( const char* a_pcFormat, ... )
{
va_list ap;
va_start( ap, a_pcFormat );
char acBuffer[1024];
vsnprintf( acBuffer, 1023, a_pcFormat, ap );
acBuffer[1023] = 0;
PERLEVAL(acBuffer);
+ const char *pcError = SvPV_nolen(get_sv("@", FALSE));
+ if ( pcError )
+ {
+ fprintf( stderr, "%s", pcError );
+ }
+
va_end( ap );
+
+ return pcError;
+}
+
+
+const char* Backend::GetPerlString( const char* acScalarName )
+{
+ SV* poScalar = get_sv( acScalarName, FALSE );
+ if ( NULL == poScalar )
+ {
+ return "";
+ }
+
+ return SvPV_nolen( poScalar );
+}
+
+
+int Backend::GetPerlInt( const char* acScalarName )
+{
+ SV* poScalar = get_sv( acScalarName, FALSE );
+ if ( NULL == poScalar )
+ {
+ return 0;
+ }
+
+ return SvIV( poScalar );
}
void Backend::AdvancePerl()
{
PERLEVAL("GameAdvance();");
}
void Backend::ReadFromPerl()
{
if ( perl_bgx == NULL )
{
perl_bgx = get_sv("bgx", TRUE);
perl_bgy = get_sv("bgy", TRUE);
perl_p1x = get_sv("p1x", TRUE);
perl_p1y = get_sv("p1y", TRUE);
perl_p1f = get_sv("p1f", TRUE);
perl_p1h = get_sv("p1h", TRUE);
perl_p2x = get_sv("p2x", TRUE);
perl_p2y = get_sv("p2y", TRUE);
perl_p2f = get_sv("p2f", TRUE);
perl_p2h = get_sv("p2h", TRUE);
perl_time= get_sv("time", TRUE);
perl_over= get_sv("over", TRUE);
perl_ko = get_sv("ko", TRUE);
}
m_iBgX = SvIV( perl_bgx );
m_iBgY = SvIV( perl_bgy );
m_aoPlayers[0].m_iX = SvIV( perl_p1x );
m_aoPlayers[0].m_iY = SvIV( perl_p1y );
m_aoPlayers[0].m_iFrame = SvIV( perl_p1f );
m_aoPlayers[0].m_iHitPoints = SvIV( perl_p1h ) / 10;
m_aoPlayers[1].m_iX = SvIV( perl_p2x );
m_aoPlayers[1].m_iY = SvIV( perl_p2y );
m_aoPlayers[1].m_iFrame = SvIV( perl_p2f );
m_aoPlayers[1].m_iHitPoints = SvIV( perl_p2h ) / 10;
m_iGameTime = SvIV( perl_time );
m_iGameOver = SvIV( perl_over );
m_bKO = SvIV( perl_ko );
// READ DOODAD DATA
if ( perl_doodad_x == NULL )
{
perl_doodad_x = get_sv("doodad_x", TRUE);
perl_doodad_y = get_sv("doodad_y", TRUE);
perl_doodad_t = get_sv("doodad_t", TRUE);
perl_doodad_f = get_sv("doodad_f", TRUE);
perl_doodad_text = get_sv("doodad_text", TRUE);
}
for ( m_iNumDoodads=0; m_iNumDoodads<MAXDOODADS; ++m_iNumDoodads )
{
PERLEVAL("GetNextDoodadData();");
SDoodad& oDoodad = m_aoDoodads[m_iNumDoodads];
oDoodad.m_iType = SvIV(perl_doodad_t);
if ( oDoodad.m_iType < 0 )
{
break;
}
oDoodad.m_iX = SvIV(perl_doodad_x);
oDoodad.m_iY = SvIV(perl_doodad_y);
oDoodad.m_iFrame = SvIV(perl_doodad_f);
if ( oDoodad.m_iType == 0 )
{
oDoodad.m_sText = SvPV_nolen(perl_doodad_text);
}
else
{
oDoodad.m_sText.clear();
}
}
// READ SOUND DATA
if ( perl_sound == NULL )
{
perl_sound = get_sv("sound", TRUE);
}
for ( m_iNumSounds=0; m_iNumSounds<MAXSOUNDS; ++m_iNumSounds )
{
PERLEVAL("GetNextSoundData();");
const char* pcSound = SvPV_nolen(perl_sound);
if ( NULL == pcSound
|| 0 == *pcSound )
{
break;
}
m_asSounds[ m_iNumSounds ] = pcSound;
//Audio->PlaySample( pcSound );
}
}
void Backend::PlaySounds()
{
for ( int i=0; i<m_iNumSounds; ++i )
{
Audio->PlaySample( m_asSounds[i].c_str() );
}
}
/***************************************************************************
PLAYBACK STRING CONVERSION ROUTINES
***************************************************************************/
void Backend::WriteToString( std::string& a_rsOutString )
{
char acBuffer[2048];
int iNumChars = sprintf( acBuffer, "%d %d %d %d %d %d %d %d %d %d %d ",
m_iBgX, m_iBgY,
m_aoPlayers[0].m_iX, m_aoPlayers[0].m_iY, m_aoPlayers[0].m_iFrame, m_aoPlayers[0].m_iHitPoints,
m_aoPlayers[1].m_iX, m_aoPlayers[1].m_iY, m_aoPlayers[1].m_iFrame, m_aoPlayers[1].m_iHitPoints,
m_iNumDoodads );
int i;
for ( i = 0; i<m_iNumDoodads; ++i )
{
SDoodad& roDoodad = m_aoDoodads[i];
iNumChars += sprintf( acBuffer+iNumChars, "%d %d %d %d %d %s ",
roDoodad.m_iX, roDoodad.m_iY, roDoodad.m_iType, roDoodad.m_iFrame,
roDoodad.m_sText.size(), roDoodad.m_sText.c_str() );
}
iNumChars += sprintf( acBuffer+iNumChars, "%d ", m_iNumSounds );
for ( i = 0; i<m_iNumSounds; ++i )
{
iNumChars += sprintf( acBuffer+iNumChars, " %d %s",
m_asSounds[i].size(), m_asSounds[i].c_str() );
}
// debug( "Frame: '%s'\n", acBuffer );
a_rsOutString = acBuffer;
}
void Backend::ReadFromString( const std::string& a_rsString )
{
const char* pcBuffer = a_rsString.c_str();
int iNumMatches;
int iOffset, iTotal;
iNumMatches = sscanf( pcBuffer, "%d %d %d %d %d %d %d %d %d %d %d%n",
&m_iBgX, &m_iBgY,
&m_aoPlayers[0].m_iX, &m_aoPlayers[0].m_iY, &m_aoPlayers[0].m_iFrame, &m_aoPlayers[0].m_iHitPoints,
&m_aoPlayers[1].m_iX, &m_aoPlayers[1].m_iY, &m_aoPlayers[1].m_iFrame, &m_aoPlayers[1].m_iHitPoints,
&m_iNumDoodads, &iTotal );
if ( m_iNumDoodads > MAXDOODADS )
{
m_iNumDoodads = m_iNumSounds = 0;
return;
}
int i, j;
for ( i=0; i<m_iNumDoodads; ++i )
{
SDoodad& roDoodad = m_aoDoodads[i];
iNumMatches += sscanf( pcBuffer+iTotal, "%d %d %d %d %d %n",
&roDoodad.m_iX, &roDoodad.m_iY, &roDoodad.m_iType, &roDoodad.m_iFrame,
&j, &iOffset );
iTotal += iOffset;
roDoodad.m_sText.assign( pcBuffer + iTotal, j );
iTotal += j;
}
iNumMatches += sscanf( pcBuffer + iTotal, "%d%n",
&m_iNumSounds, &iOffset );
if ( m_iNumSounds > MAXSOUNDS )
{
m_iNumSounds = 0;
return;
}
iTotal += iOffset;
for ( i=0; i<m_iNumSounds; ++i )
{
iNumMatches += sscanf( pcBuffer+iTotal, "%d %n",
&j, &iOffset );
iTotal += iOffset;
m_asSounds[i].assign( pcBuffer + iTotal, j );
iTotal += j;
}
}
diff --git a/src/Backend.h b/src/Backend.h
index 1b5302c..7f49862 100644
--- a/src/Backend.h
+++ b/src/Backend.h
@@ -1,138 +1,77 @@
/***************************************************************************
Backend.h - description
-------------------
begin : Sun Dec 8 2002
copyright : (C) 2002 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
-#include <EXTERN.h>
-#include <perl.h>
+#ifndef BACKEND_H
+#define BACKEND_H
+
#include <string>
+#include "FighterEnum.h"
class RlePack;
-extern PerlInterpreter *my_perl;
-
-
-#define PERLEVAL(A) eval_pv(A, TRUE);
-
-#define PERLCALL(PROC,A,B) { \
- dSP; \
- ENTER; \
- SAVETMPS; \
- PUSHMARK(SP); \
- XPUSHs(sv_2mortal(newSViv(A))); \
- XPUSHs(sv_2mortal(newSViv(B))); \
- PUTBACK ; \
- \
- call_pv( (PROC), G_DISCARD ); \
- \
- FREETMPS; \
- LEAVE; \
-}
-
#define MAXDOODADS 20
#define MAXSOUNDS 20
class Backend
{
public:
// Lifecycle
Backend();
~Backend();
bool Construct();
// Miscellaneous
- void PerlEvalF( const char* a_pcFormat, ... );
+ const char* PerlEvalF( const char* a_pcFormat, ... );
+ const char* GetPerlString( const char* acScalarName );
+ int GetPerlInt( const char* acScalarName );
// Game data
void AdvancePerl();
void ReadFromPerl();
void PlaySounds();
void WriteToString( std::string& a_rsOutString );
void ReadFromString( const std::string& a_rsString );
+
public:
int m_iGameTime;
int m_iGameOver;
bool m_bKO;
int m_iBgX, m_iBgY;
int m_iNumDoodads;
int m_iNumSounds;
struct SPlayer
{
int m_iX, m_iY, m_iFrame, m_iHitPoints;
} m_aoPlayers[2];
struct SDoodad
{
int m_iX, m_iY, m_iType, m_iFrame;
std::string m_sText;
} m_aoDoodads[ MAXDOODADS ];
std::string m_asSounds[ MAXSOUNDS ];
};
extern Backend g_oBackend;
-// FIGHTER ENUMERABLE
-enum FighterEnum {
- UNKNOWN = 0,
-
- ULMAR,
- UPI,
- ZOLI,
- CUMI,
- SIRPI,
- MACI,
- BENCE,
- GRIZLI,
- DESCANT,
- SURBA,
- AMBRUS,
- DANI,
- KINGA,
- MISI,
-
- LASTFIGHTER
-};
-
-
-enum TintEnum {
- NO_TINT = 0,
- RANDOM_TINT,
- ZOMBIE_TINT,
- GRAY_TINT,
- DARK_TINT,
- INVERTED_TINT,
-};
-
-
-bool IsFighterAvailable( FighterEnum a_enFighter );
-RlePack* LoadFighter( FighterEnum fighter, int offset );
-void TintFighter( RlePack* fighter, TintEnum tint, int offset );
int DoGame( char* replay, bool isReplay, bool bDebug );
-void PlayerSelect();
-void SetPlayer( int player, FighterEnum fighter );
-
-
-
-extern FighterEnum Fighter1;
-extern FighterEnum Fighter2;
-extern TintEnum FingerTint1;
-extern TintEnum FingerTint2;
-extern RlePack* pack1;
-extern RlePack* pack2;
+#endif
diff --git a/src/FighterEnum.h b/src/FighterEnum.h
new file mode 100644
index 0000000..1536492
--- /dev/null
+++ b/src/FighterEnum.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ FighterEnum.h - description
+ -------------------
+ begin : 2003-09-03
+ copyright : (C) 2003 by upi
+ email : upi@apocalypse.rulez.org
+ ***************************************************************************/
+
+
+#ifndef FIGHTERENUM_H
+#define FIGHTERENUM_H
+
+
+/// FIGHTER ENUMERABLE
+
+enum FighterEnum {
+ UNKNOWN = 0, ///< Must be the first element, must be 0 (used by iterations)
+
+ ULMAR,
+ UPI,
+ ZOLI,
+ CUMI,
+ SIRPI,
+ MACI,
+ BENCE,
+ GRIZLI,
+ DESCANT,
+ SURBA,
+ AMBRUS,
+ DANI,
+ KINGA,
+ MISI,
+
+ LASTFIGHTER, ///< This must terminate the list, iterations use it.
+};
+
+
+
+
+
+/** The TintEnum contains values that can be passed to RlePack::SetTint.
+
+The tint is some modification of the original palette of an RlePack. This
+is used for two things:
+
+\li In case both players choose the same fighter, player 2's fighter is
+tinted so they won't get confused.
+\li Some special effects (e.g. frozen) make the figther tinted as well.
+
+The Tint of players is stored by PlayerSelect and applied by RlePack::SetTint().
+*/
+
+enum TintEnum {
+ NO_TINT = 0,
+ ZOMBIE_TINT,
+ GRAY_TINT,
+ DARK_TINT,
+ INVERTED_TINT,
+ FROZEN_TINT,
+};
+
+#endif // FIGHTERENUM_H
diff --git a/src/FighterStats.cpp b/src/FighterStats.cpp
index 3dd09a1..61c2f11 100644
--- a/src/FighterStats.cpp
+++ b/src/FighterStats.cpp
@@ -1,232 +1,242 @@
/***************************************************************************
FighterStats.cpp - description
-------------------
begin : Tue Dec 10 2002
copyright : (C) 2002 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include <stdio.h>
#include <string>
+#include "PlayerSelect.h"
#include "FlyingChars.h"
#include "SDL.h"
#include "SDL_video.h"
#include "SDL_image.h"
#include "sge_tt_text.h"
#include "common.h"
#include "gfx.h"
#include "RlePack.h"
#include "Backend.h"
#include "Demo.h"
+#include <EXTERN.h>
+#include <perl.h>
+
+
+extern PerlInterpreter* my_perl;
+
+
+
+
#define LEFTMARGIN 160
#define TOPMARGIN 70
#define RIGHTMARGIN 630
#define LINEHEIGHT 35
#define GAPWIDTH 20
#define DESCMARGIN 50
#define LEFTMARGIN2 ((LEFTMARGIN+RIGHTMARGIN+GAPWIDTH)/2)
/*
void DrawMultiLineText( const char* text, _sge_TTFont* font, int x, int y,
int fg, SDL_Surface* target )
{
const char* s1, * s2;
char line[1024];
s1 = s2 = text;
while (1)
{
while ( isspace(*s2) ) s2++;
if ( !*s2 )
break;
s1 = s2; // s1: start of line.
while ( (*s2 != '\n') && *s2 ) s2++;
strncpy( line, s1, s2-s1 );
line[s2-s1] = 0;
DrawTextMSZ( line, font, x, y, 0, fg, target );
y += sge_TTF_FontLineSkip( font );
}
}
*/
int FighterStatsDemo::mg_iLastFighter = -1;
FighterEnum FighterStatsDemo::mg_aenFighterOrder[LASTFIGHTER-1];
FighterStatsDemo::FighterStatsDemo()
{
m_iTimeLeft = 500;
m_poStaff = NULL;
m_poBackground = LoadBackground( "FighterStats.png", 64 );
DrawGradientText( "Figher Stats", titleFont, 10, m_poBackground );
SDL_BlitSurface( m_poBackground, NULL, gamescreen, NULL );
SDL_Flip( gamescreen );
if ( mg_iLastFighter < 0 )
{
// First run; create shuffled array of figthers.
mg_iLastFighter = 0;
int i, j;
FighterEnum k;
for ( i=0; i<LASTFIGHTER-1; ++i )
{
mg_aenFighterOrder[i] = (FighterEnum)(i+1);
}
for ( i=0; i<LASTFIGHTER-1; ++i )
{
j = rand() % (LASTFIGHTER-1);
k = mg_aenFighterOrder[i];
mg_aenFighterOrder[i] = mg_aenFighterOrder[j];
mg_aenFighterOrder[j] = k;
}
}
mg_iLastFighter = (mg_iLastFighter+1) % (LASTFIGHTER-1);
m_enFighter = mg_aenFighterOrder[mg_iLastFighter];
- if ( IsFighterAvailable( m_enFighter ) )
+ if ( g_oPlayerSelect.IsFighterAvailable( m_enFighter ) )
{
- SetPlayer( 0, m_enFighter );
- PERLEVAL("SelectStart();");
+ g_oPlayerSelect.SetPlayer( 0, m_enFighter );
+ g_oBackend.PerlEvalF( "SelectStart();" );
}
else
{
std::string sStaffFilename = DATADIR;
sStaffFilename += "/characters/STAFF.DAT";
- m_poStaff = new RlePack( sStaffFilename.c_str() );
+ m_poStaff = new RlePack( sStaffFilename.c_str(), 240 );
}
- PERLCALL("GetFighterStats", m_enFighter, 0 );
+ g_oBackend.PerlEvalF("GetFighterStats(%d);", m_enFighter );
_sge_TTFont* font = impactFont;
int y = TOPMARGIN;
AV *StatTags = get_av( "StatTags", FALSE );
char *s, *sTag;
s = SvPV_nolen(get_sv("Name", FALSE));
DrawTextMSZ( s, inkFont, (LEFTMARGIN + RIGHTMARGIN)/2, y, AlignHCenter, C_WHITE, m_poBackground );
y+= 10;
s = SvPV_nolen(get_sv("Team", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 1, false ) );
int i = DrawTextMSZ( sTag, font, LEFTMARGIN, y+=LINEHEIGHT, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Style", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 2, false ) );
i = DrawTextMSZ( sTag, font, LEFTMARGIN2, y, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN2+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Age", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 3, false ) );
i = DrawTextMSZ( sTag, font, LEFTMARGIN, y+=LINEHEIGHT, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Weight", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 4, false ) );
i = DrawTextMSZ( sTag, font, LEFTMARGIN2, y, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN2+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Height", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 5, false ) );
i = DrawTextMSZ( sTag, font, LEFTMARGIN, y+=LINEHEIGHT, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Shoe", FALSE ));
sTag = SvPV_nolen( *av_fetch( StatTags, 6, false ) );
i = DrawTextMSZ( sTag, font, LEFTMARGIN2, y, 0, C_YELLOW, m_poBackground );
DrawTextMSZ( s, font, LEFTMARGIN2+i, y, 0, C_ORANGE, m_poBackground );
s = SvPV_nolen(get_sv("Story", FALSE ));
SDL_Rect oFlyingRect;
oFlyingRect.x = LEFTMARGIN;
oFlyingRect.y = y+DESCMARGIN;
oFlyingRect.w = gamescreen->w - oFlyingRect.x - 20;
oFlyingRect.h = gamescreen->h - oFlyingRect.y - 10;
m_poFlyingChars = new FlyingChars( creditsFont, oFlyingRect );
m_poFlyingChars->AddText( s, FlyingChars::FC_AlignJustify, false );
- if ( IsFighterAvailable( m_enFighter ) )
+ if ( g_oPlayerSelect.IsFighterAvailable( m_enFighter ) )
{
s = SvPV_nolen(get_sv("Keys", TRUE ));
m_poFlyingChars->AddText( "\nKEYS\n", FlyingChars::FC_AlignCenter, true );
m_poFlyingChars->AddText( s, FlyingChars::FC_AlignCenter, true );
}
else
{
m_poFlyingChars->AddText( "Unfortunately this figther is not yet playable.",
FlyingChars::FC_AlignLeft, true );
}
}
FighterStatsDemo::~FighterStatsDemo()
{
delete m_poStaff;
}
int FighterStatsDemo::Advance( int a_iNumFrames, bool a_bFlip )
{
if ( a_iNumFrames > 5 ) a_iNumFrames = 5;
if ( m_poFlyingChars->IsDone() )
{
m_iTimeLeft -= a_iNumFrames;
}
AdvanceFlyingChars( a_iNumFrames );
SDL_BlitSurface( m_poBackground, NULL, gamescreen, NULL );
m_poFlyingChars->Draw();
// 2. Advance as many ticks as necessary..
- if ( IsFighterAvailable( m_enFighter ) )
+ if ( g_oPlayerSelect.IsFighterAvailable( m_enFighter ) )
{
for (int i=0; i<a_iNumFrames; ++i )
{
g_oBackend.AdvancePerl();
}
int p1x = SvIV(get_sv("p1x", TRUE));
int p1y = SvIV(get_sv("p1y", TRUE));
int p1f = SvIV(get_sv("p1f", TRUE));
- if (p1f) pack1->draw( ABS(p1f)-1, p1x, p1y, p1f<0 );
+ if (p1f) g_oPlayerSelect.GetPlayerInfo(0).m_poPack->Draw( ABS(p1f)-1, p1x, p1y, p1f<0 );
}
else
{
static FighterEnum f[14] = {
UPI, ZOLI, SURBA, ULMAR, MISI, BENCE,
DESCANT, KINGA, GRIZLI, SIRPI, MACI, DANI, CUMI,
AMBRUS };
for ( int i=0; i<14; ++i )
{
if ( m_enFighter == f[i] )
{
//m_poStaff->draw( i, 10, 120 );
break;
}
}
}
SDL_Flip( gamescreen );
return (m_iTimeLeft > 0) ? 0 : 1;
}
diff --git a/src/Game.cpp b/src/Game.cpp
index 6dbeb72..1c6674f 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,728 +1,737 @@
/***************************************************************************
Game.cpp - description
-------------------
begin : Mon Sep 24 2001
copyright : (C) 2001 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include <string.h>
#include <stdio.h>
#include "SDL_image.h"
#include "sge_surface.h"
#include "sge_primitives.h"
#include "sge_bm_text.h"
#include "SDL_events.h"
#include "SDL_keysym.h"
#include <fstream>
+#include "PlayerSelect.h"
#include "common.h"
#include "gfx.h"
#include "Backend.h"
#include "RlePack.h"
#include "State.h"
#include "Game.h"
#include "Audio.h"
+#include <EXTERN.h>
+#include <perl.h>
+
+
+extern PerlInterpreter* my_perl;
+
/*
GAME PALETTE
From To Num Desc
---------------------------------------
0 .. 63 64 Background
64 .. 111 48 Doodads
112 .. 175 64 1st Fighter
176 .. 239 64 2nd Fighter
240 .. 255 16 basic colors
*/
#define MAXFRAMESKIP 5
struct SFpsCounter
{
int m_iLastCheck; // Last second then Tick() was called
int m_iFrames; // The number of frames in this second so far
int m_iFps; // The number of frames in the last second
void Reset()
{
m_iLastCheck = m_iFrames = m_iFps = 0;
}
void Tick()
{
int iSecond = SDL_GetTicks() / 1000;
if ( iSecond > m_iLastCheck )
{
m_iLastCheck = iSecond;
m_iFps = m_iFrames;
m_iFrames = 0;
fprintf( stderr, "%d ", m_iFps);
}
++m_iFrames;
}
} oFpsCounter;
/***************************************************************************
GAME PUBLIC METHODS
***************************************************************************/
Game::Game( bool a_bIsReplay, bool a_bDebug)
{
m_bIsReplay = a_bIsReplay;
m_bDebug = a_bDebug;
m_poBackground = LoadBackground( "level1.png", 64 );
m_poDoodads = LoadBackground( "Doodads.png", 48, 64 );
m_aiRoundsWonByPlayer[0] = m_aiRoundsWonByPlayer[1] = 0;
m_iNumberOfRounds = 0;
}
Game::~Game()
{
SDL_FreeSurface( m_poBackground );
m_poBackground = NULL;
SDL_FreeSurface( m_poDoodads );
m_poDoodads = NULL;
}
int Game::Run()
{
do
{
m_sReplayString.clear();
m_aReplayOffsets.clear();
DoOneRound();
if ( g_oState.m_bQuitFlag
|| SState::IN_DEMO == g_oState.m_enGameMode )
{
return -1;
}
} while ( m_aiRoundsWonByPlayer[0] < 2
&& m_aiRoundsWonByPlayer[1] < 2
&& m_iNumberOfRounds < 3 );
if ( m_aiRoundsWonByPlayer[1] > m_aiRoundsWonByPlayer[0] ) return 1;
if ( m_aiRoundsWonByPlayer[1] < m_aiRoundsWonByPlayer[0] ) return 0;
return -1;
}
std::string& Game::GetReplay()
{
return m_sReplayString;
}
/***************************************************************************
GAME DRAWING METHODS
***************************************************************************/
void Game::DrawHitPointDisplay()
{
int hp1 = g_oBackend.m_aoPlayers[0].m_iHitPoints;// * 100 / g_oState.m_iHitPoints;
int hp2 = g_oBackend.m_aoPlayers[1].m_iHitPoints;// * 100 / g_oState.m_iHitPoints;
SDL_Rect src, dst;
src.y = 154;
src.h = 20;
dst.y = 15;
// Player 1, green part.
dst.x = 40;
src.x = 0;
src.w = hp1*2;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
// Player 1, red part.
dst.x += hp1*2;
src.x = (100 + hp1)*2;
src.w = (100-hp1)*2;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
// Player 2, red part.
dst.x = 400;
src.x = 200;
src.w = (100-hp2)*2;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
// Player 2, green part.
dst.x = 400 + (100-hp2)*2;
src.x = (100-hp2)*2;
src.w = hp2*2;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
// "Won" icon for Player 1
src.x = 0; src.y = 276; src.w = 32; src.h = 32;
if ( m_aiRoundsWonByPlayer[0] > 0 )
{
dst.x = 4; dst.y = 11;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
}
if ( m_aiRoundsWonByPlayer[1] > 0 )
{
dst.x = 604; dst.y = 11;
SDL_BlitSurface( m_poDoodads, &src, gamescreen, &dst );
}
}
void Game::DrawBackground()
{
sge_Blit( m_poBackground, gamescreen,
g_oBackend.m_iBgX, g_oBackend.m_iBgY,
0, 0, SCREENWIDTH, SCREENHEIGHT );
}
void Game::DrawPoly( const char* sName, int color )
{
AV *iList;
int n;
iList = get_av( sName, FALSE );
if ( iList == NULL )
{
return;
}
n = av_len( iList ) + 1;
if ( n< 2 )
{
return;
}
for ( int i=0; i<n; i += 2 )
{
int j = (i+2) % n;
int x1 = SvIV( *av_fetch( iList, i, false) );
int y1 = SvIV( *av_fetch( iList, i+1, false) );
int x2 = SvIV( *av_fetch( iList, j, false) );
int y2 = SvIV( *av_fetch( iList, j+1, false) );
sge_Line( gamescreen, x1, y1, x2, y2, color ) ;
}
}
void Game::DrawDoodads()
{
for ( int i=0; i<g_oBackend.m_iNumDoodads; ++i )
{
Backend::SDoodad& roDoodad = g_oBackend.m_aoDoodads[i];
if ( 0 == roDoodad.m_iType )
{
// Handle text doodads
const char *s = roDoodad.m_sText.c_str();
int iWidth = sge_BF_TextSize(fastFont, s).w;
int iDoodadX = roDoodad.m_iX - iWidth/2;
if ( iDoodadX + iWidth > 640 ) iDoodadX = 640 - iWidth;
if ( iDoodadX < 0 ) iDoodadX = 0;
int iDoodadY = roDoodad.m_iY;
sge_BF_textout( gamescreen, fastFont, s, iDoodadX, iDoodadY );
continue;
}
SDL_Rect rsrc, rdst;
rdst.x = roDoodad.m_iX;
rdst.y = roDoodad.m_iY;
rsrc.x = 64 * roDoodad.m_iFrame;
rsrc.y = 0;
rsrc.w = 64;
rsrc.h = 64;
SDL_BlitSurface( m_poDoodads, &rsrc, gamescreen, &rdst );
//debug( "Doodad x: %d, y: %d, t: %d, f: %d\n", dx, dy, dt, df );
}
}
void Game::Draw()
{
DrawBackground();
for ( int i=0; i<2; ++i )
{
int iFrame = g_oBackend.m_aoPlayers[i].m_iFrame;
if ( 0 != iFrame )
{
- (i ? pack2 : pack1)->draw( ABS(iFrame)-1,
+ g_oPlayerSelect.GetPlayerInfo(i).m_poPack->Draw(
+ ABS(iFrame)-1,
g_oBackend.m_aoPlayers[i].m_iX,
g_oBackend.m_aoPlayers[i].m_iY,
iFrame<0 );
}
}
if ( m_bDebug )
{
DrawPoly( "p1head", C_LIGHTRED );
DrawPoly( "p1body", C_LIGHTGREEN );
DrawPoly( "p1legs", C_LIGHTBLUE );
DrawPoly( "p1hit", C_YELLOW );
DrawPoly( "p2head", C_LIGHTRED );
DrawPoly( "p2body", C_LIGHTGREEN );
DrawPoly( "p2legs", C_LIGHTBLUE );
DrawPoly( "p2hit", C_YELLOW );
}
DrawDoodads();
DrawHitPointDisplay();
if ( Ph_NORMAL == m_enGamePhase )
{
char s[100];
sprintf( s, "%d", g_oBackend.m_iGameTime );
DrawTextMSZ( s, inkFont, 320, 10, AlignHCenter, C_LIGHTCYAN, gamescreen );
}
else if ( Ph_START == m_enGamePhase )
{
char s[100];
sprintf( s, "Round %d", m_iNumberOfRounds+1 );
DrawTextMSZ( s, inkFont, 320, 200, AlignHCenter, C_WHITE, gamescreen );
}
else if ( Ph_REWIND == m_enGamePhase )
{
DrawTextMSZ( "REW", inkFont, 320, 10, AlignHCenter, C_WHITE, gamescreen );
}
else if ( Ph_SLOWFORWARD == m_enGamePhase )
{
DrawTextMSZ( "REPLAY", inkFont, 320, 10, AlignHCenter, C_WHITE, gamescreen );
}
else if ( Ph_REPLAY == m_enGamePhase )
{
DrawTextMSZ( "DEMO", inkFont, 320, 10, AlignHCenter, C_WHITE, gamescreen );
}
if ( oFpsCounter.m_iFps > 0 )
{
sge_BF_textoutf( gamescreen, fastFont, 2, 2, "%d fps", oFpsCounter.m_iFps );
}
SDL_Flip( gamescreen );
}
/***************************************************************************
GAME PROTECTED METHODS
***************************************************************************/
/**
This method reads and updates the game's variables. In replay mode,
this is done by parsing the replay string. Otherwise the perl
backend is advanced the given number of steps.
Whichever the case, the variables will be available in g_oBackend.
*/
void Game::Advance( int a_iNumFrames )
{
if ( m_bIsReplay )
{
// Replay mode...
m_iFrame += a_iNumFrames;
if ( m_iFrame >= ((int)m_aReplayOffsets.size())-1 ) m_iFrame = m_aReplayOffsets.size() - 2;
if ( m_iFrame <= 0 ) m_iFrame = 0;
std::string sFrameDesc = m_sReplayString.substr(
m_aReplayOffsets[m_iFrame],
m_aReplayOffsets[m_iFrame+1] - m_aReplayOffsets[m_iFrame] );
g_oBackend.ReadFromString( sFrameDesc );
return;
}
while ( a_iNumFrames > 0 )
{
-- a_iNumFrames;
std::string sFrameDesc;
g_oBackend.AdvancePerl();
g_oBackend.ReadFromPerl();
g_oBackend.PlaySounds();
g_oBackend.WriteToString( sFrameDesc );
m_sReplayString += sFrameDesc;
m_sReplayString += '\n';
m_aReplayOffsets.push_back( m_sReplayString.size() );
}
}
/** ProcessEvents reads events from the SDL event system.
Relevant key events are fed to the backend.
Esc brings up the menu.
Returns 1 on quit event, 0 otherwise.
*/
int Game::ProcessEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
g_oState.m_bQuitFlag = true;
return 1;
case SDL_KEYDOWN:
{
if ( event.key.keysym.sym == SDLK_ESCAPE )
return 1;
if ( Ph_NORMAL != m_enGamePhase )
break;
for (int i=0; i<2; i++)
{
for (int j=0; j<9; j++ )
{
if (g_oState.m_aiPlayerKeys[i][j] == event.key.keysym.sym)
{
- PERLCALL( "KeyDown", i, j );
+ g_oBackend.PerlEvalF( "KeyDown(%d,%d);", i, j );
}
}
}
break;
}
case SDL_KEYUP:
{
if ( Ph_NORMAL != m_enGamePhase )
break;
for (int i=0; i<2; i++)
{
for (int j=0; j<9; j++ )
{
if (g_oState.m_aiPlayerKeys[i][j] == event.key.keysym.sym)
{
- PERLCALL( "KeyUp", i, j );
+ g_oBackend.PerlEvalF( "KeyUp(%d,%d);", i, j );
}
}
}
break;
}
} // End of switch
} // End of while SDL_PollEvent;
return 0;
}
void Game::HurryUp()
{
Audio->PlaySample( "aroooga.voc" );
DrawGradientText( "HURRY UP!", titleFont, 200, gamescreen );
SDL_Delay( 1000 );
Audio->PlaySample( "machine_start.voc" );
}
void Game::TimeUp()
{
DrawGradientText( "TIME IS UP!", titleFont, 200, gamescreen );
SDL_Delay( 1000 );
}
void Game::InstantReplay( int a_iKoAt )
{
int iCurrentFrame = m_aReplayOffsets.size() - 200;
int iThisTick, iLastTick, iGameSpeed;
m_enGamePhase = Ph_REWIND;
iGameSpeed = 8;
iThisTick = SDL_GetTicks() / iGameSpeed;
iLastTick = iThisTick - 1;
while ( iCurrentFrame < (int)m_aReplayOffsets.size() - 150 )
{
// 1. Wait for the next tick (on extremely fast machines..)
while (iThisTick == iLastTick)
{
iThisTick = SDL_GetTicks() / iGameSpeed;
if ( iThisTick==iLastTick ) SDL_Delay(1);
}
// 2. Advance as many ticks as necessary..
int iNumTicks = iThisTick - iLastTick;
if ( iNumTicks > 10 ) iNumTicks = 10;
if ( iNumTicks < 0 ) iNumTicks = 0;
iCurrentFrame += ( Ph_REWIND == m_enGamePhase ) ? -iNumTicks : +iNumTicks ;
if ( Ph_REWIND == m_enGamePhase
&& ( iCurrentFrame < a_iKoAt - 200 || iCurrentFrame <= 0 )
)
{
m_enGamePhase = Ph_SLOWFORWARD;
iGameSpeed = 16;
SDL_Delay(500);
}
iLastTick = iThisTick;
if ( iCurrentFrame < 0 ) iCurrentFrame = 0;
m_iFrame = iCurrentFrame;
if ( m_iFrame >= ((int)m_aReplayOffsets.size())-1 ) m_iFrame = m_aReplayOffsets.size() - 2;
if ( m_iFrame <= 0 ) m_iFrame = 0;
std::string sFrameDesc = m_sReplayString.substr(
m_aReplayOffsets[m_iFrame],
m_aReplayOffsets[m_iFrame+1] - m_aReplayOffsets[m_iFrame] );
//debug( "PB: Frame %d ofs %d-%d; data: '%s'\n", m_iFrame,
// m_aReplayOffsets[m_iFrame], m_aReplayOffsets[m_iFrame+1], sFrameDesc.c_str() );
g_oBackend.ReadFromString( sFrameDesc );
if ( ProcessEvents() )
{
break;
}
oFpsCounter.Tick();
// 3. Draw the next game screen..
Draw();
if ( g_oState.m_bQuitFlag )
{
break;
}
}
}
void Game::DoOneRound()
{
m_enGamePhase = Ph_START;
g_oBackend.PerlEvalF( "GameStart(%d);", g_oState.m_iHitPoints );
int iKoFrame = -1;
double dGameTime = 2 * 1000;
int iThisTick, iLastTick, iGameSpeed;
bool bHurryUp = false;
iGameSpeed = 12;
iThisTick = SDL_GetTicks() / iGameSpeed;
iLastTick = iThisTick - 1;
oFpsCounter.Reset();
// 1. DO THE NORMAL GAME ROUND and HURRYUP
while ( dGameTime > 0 )
{
// 1. Wait for the next tick (on extremely fast machines..)
while (iThisTick == iLastTick)
{
iThisTick = SDL_GetTicks() / iGameSpeed;
if ( iThisTick==iLastTick ) SDL_Delay(1);
}
// 2. Advance as many ticks as necessary..
int iNumTicks = iThisTick - iLastTick;
if ( iNumTicks > MAXFRAMESKIP ) iNumTicks = MAXFRAMESKIP;
Advance( iNumTicks );
dGameTime -= iNumTicks * iGameSpeed;
if ( Ph_START == m_enGamePhase )
{
if ( dGameTime < 0 )
{
m_enGamePhase = Ph_NORMAL;
dGameTime = g_oState.m_iGameTime * 1000;
}
}
else if ( Ph_NORMAL == m_enGamePhase )
{
if ( dGameTime < 10 * 1000
&& !bHurryUp )
{
bHurryUp = true;
HurryUp();
iGameSpeed = iGameSpeed * 3 / 4;
}
if ( g_oBackend.m_bKO )
{
m_enGamePhase = Ph_KO;
dGameTime = 10 * 1000;
iKoFrame = m_aReplayOffsets.size();
}
else if ( dGameTime < 0 )
{
m_enGamePhase = Ph_TIMEUP;
TimeUp();
break;
}
}
g_oBackend.m_iGameTime = (int) ((dGameTime + 500.0) / 1000.0);
iLastTick = iThisTick;
if ( ProcessEvents() )
{
break;
}
oFpsCounter.Tick();
// 3. Draw the next game screen..
Draw();
if ( g_oBackend.m_iGameOver || g_oState.m_bQuitFlag )
{
break;
}
}
// 3. DO THE REPLAY (IF THERE WAS A KO)
if ( iKoFrame>0 )
{
InstantReplay( iKoFrame );
}
// 4. END OF ROUND
int p1h = g_oBackend.m_aoPlayers[0].m_iHitPoints;
int p2h = g_oBackend.m_aoPlayers[1].m_iHitPoints;
debug( "Game over; p1h = %d; p2h = %d\n", p1h, p2h );
if ( p1h > p2h ) ++m_aiRoundsWonByPlayer[0];
if ( p2h > p1h ) ++m_aiRoundsWonByPlayer[1];
++m_iNumberOfRounds;
}
void Game::DoReplay( const char* a_pcReplayFile )
{
std::ifstream oInput( a_pcReplayFile );
int iPlayer1, iPlayer2;
oInput >> iPlayer1 >> iPlayer2;
std::string sLine;
std::getline( oInput, sLine );
- SetPlayer( 0, (FighterEnum) iPlayer1 );
- SetPlayer( 1, (FighterEnum) iPlayer2 );
+ g_oPlayerSelect.SetPlayer( 0, (FighterEnum) iPlayer1 );
+ g_oPlayerSelect.SetPlayer( 1, (FighterEnum) iPlayer2 );
- int iCurrentFrame = 0;
int iThisTick, iLastTick, iGameSpeed;
m_enGamePhase = Ph_REPLAY;
iGameSpeed = 12;
iThisTick = SDL_GetTicks() / iGameSpeed;
iLastTick = iThisTick - 1;
while ( !oInput.eof() )
{
// 1. Wait for the next tick (on extremely fast machines..)
while (iThisTick == iLastTick)
{
iThisTick = SDL_GetTicks() / iGameSpeed;
if ( iThisTick==iLastTick ) SDL_Delay(1);
}
// 2. Advance as many ticks as necessary..
int iNumTicks = iThisTick - iLastTick;
if ( iNumTicks > 5 ) iNumTicks = 5;
for ( int i=0; i< iNumTicks; ++i )
{
std::getline( oInput, sLine );
}
if ( 0 == sLine.size() )
{
break;
}
iLastTick = iThisTick;
g_oBackend.ReadFromString( sLine );
if ( ProcessEvents() )
{
break;
}
oFpsCounter.Tick();
// 3. Draw the next game screen..
Draw();
if ( g_oState.m_bQuitFlag )
{
break;
}
}
}
int DoGame( char* a_pcReplayFile, bool a_bIsReplay, bool a_bDebug )
{
Game oGame( a_bIsReplay, a_bDebug );
if ( a_bIsReplay )
{
if ( NULL == a_pcReplayFile )
{
return 0;
}
oGame.DoReplay( a_pcReplayFile );
return 0;
}
else
{
int iRetval = oGame.Run();
if ( NULL != a_pcReplayFile )
{
std::ofstream oOutput( a_pcReplayFile );
- oOutput << Fighter1 << ' ' << Fighter2 << '\n' << oGame.GetReplay();
+ oOutput <<
+ g_oPlayerSelect.GetPlayerInfo(0).m_enFighter << ' ' <<
+ g_oPlayerSelect.GetPlayerInfo(1).m_enFighter << '\n' << oGame.GetReplay();
}
return iRetval;
}
}
diff --git a/src/GameOver.cpp b/src/GameOver.cpp
index 31c28c4..f8686b1 100644
--- a/src/GameOver.cpp
+++ b/src/GameOver.cpp
@@ -1,213 +1,218 @@
/***************************************************************************
GameOver.cpp - description
-------------------
begin : Wed Aug 21 20:25:30 CEST 2003
copyright : (C) 2003 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
+#include "PlayerSelect.h"
#include "SDL.h"
#include "gfx.h"
#include "Backend.h"
#include "common.h"
#include "State.h"
#include "RlePack.h"
#include "Audio.h"
#include <stdio.h>
void DoMenu( bool );
+
+void DrawPlayer( int i )
+{
+ int iFrame = g_oBackend.m_aoPlayers[i].m_iFrame;
+ if ( 0 != iFrame )
+ {
+ g_oPlayerSelect.GetPlayerInfo(i).m_poPack->Draw(
+ ABS(iFrame)-1,
+ g_oBackend.m_aoPlayers[i].m_iX,
+ g_oBackend.m_aoPlayers[i].m_iY - 15,
+ iFrame<0 );
+ }
+}
+
+
+
void GameOver( int a_iPlayerWon )
{
SDL_Surface* poBackground = LoadBackground( "GameOver.png", 112 );
DrawGradientText( "Final Judgement", titleFont, 20, poBackground );
DrawTextMSZ( "Continue?", inkFont, 320, 100, AlignHCenter, C_LIGHTCYAN, poBackground );
-
SDL_Surface* poFoot = LoadBackground( "Foot.png", 112 );
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
- char acString[100];
- sprintf( acString, "JudgementStart(%d);", a_iPlayerWon );
- PERLEVAL( acString );
+ g_oBackend.PerlEvalF( "JudgementStart(%d);", a_iPlayerWon );
int thisTick, lastTick, firstTick, iGameSpeed;
iGameSpeed = 14 ;
firstTick = thisTick = SDL_GetTicks() / iGameSpeed;
lastTick = thisTick - 1;
+ char acString[100];
int iTimeLeft = 8000 / iGameSpeed;
int FOOTHEIGHT = poFoot->h;
int GROUNDLEVEL = 440;
int iFootY = -FOOTHEIGHT;
bool bTimeUp = false;
bool bKeyPressed = false;
int iCounter = -1;
SDL_Event event;
while (1)
{
// 1. Wait for the next tick (on extremely fast machines..)
while (1)
{
thisTick = SDL_GetTicks() / iGameSpeed;
if ( thisTick==lastTick )
{
SDL_Delay(1);
}
else
{
break;
}
}
// 2. Advance as many ticks as necessary..
if ( thisTick - lastTick > 5 )
{
iTimeLeft -= 5;
}
else
{
iTimeLeft = iTimeLeft - thisTick + lastTick;
}
if ( iTimeLeft < 0 && !bTimeUp )
{
bTimeUp = true;
Audio->FadeMusic( 1500 );
}
if ( bTimeUp )
{
iFootY += 12 * (thisTick - lastTick );
if ( iFootY > GROUNDLEVEL - FOOTHEIGHT )
{
break;
}
}
int iNumFrames = thisTick - lastTick;
for ( int i=0; i<iNumFrames; ++i )
{
g_oBackend.AdvancePerl();
};
lastTick = thisTick;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
g_oState.m_bQuitFlag = true;
break;
case SDL_KEYDOWN:
{
if ( event.key.keysym.sym == SDLK_ESCAPE )
{
DoMenu( true );
break;
}
for (int j=4; j<9; j++ )
{
if (g_oState.m_aiPlayerKeys[1-a_iPlayerWon][j] == event.key.keysym.sym)
{
bKeyPressed = true;
break;
}
}
}
break;
} // switch statement
} // Polling events
+ /*
int p1x = SvIV(get_sv("p1x", FALSE));
int p1y = SvIV(get_sv("p1y", FALSE)) - 15;
int p1f = SvIV(get_sv("p1f", FALSE));
int p2x = SvIV(get_sv("p2x", FALSE));
int p2y = SvIV(get_sv("p2y", FALSE)) - 15;
- int p2f = SvIV(get_sv("p2f", FALSE));
+ int p2f = SvIV(get_sv("p2f", FALSE));*/
+ g_oBackend.ReadFromPerl();
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
-
- if ( a_iPlayerWon )
- {
- if (p2f) pack2->draw( ABS(p2f)-1, p2x, p2y, p2f<0 );
- }
- else
- {
- if (p1f) pack1->draw( ABS(p1f)-1, p1x, p1y, p1f<0 );
- }
+
+ DrawPlayer( a_iPlayerWon );
if ( bTimeUp )
{
SDL_Rect oRect;
oRect.x = 0;
oRect.y = iFootY + FOOTHEIGHT - 10;
oRect.w = gamescreen->w;
oRect.h = gamescreen->h - oRect.y;
SDL_SetClipRect(gamescreen, &oRect);
}
- if ( a_iPlayerWon )
- {
- if (p1f) pack1->draw( ABS(p1f)-1, p1x, p1y, p1f<0 );
- }
- else
- {
- if (p2f) pack2->draw( ABS(p2f)-1, p2x, p2y, p2f<0 );
- }
+
+ DrawPlayer( 1-a_iPlayerWon );
+
SDL_SetClipRect( gamescreen, NULL );
if ( !bTimeUp )
{
int iNewCounter = iTimeLeft * iGameSpeed / 1000;
sprintf( acString, "%d", iNewCounter );
DrawTextMSZ( acString, inkFont, 320, 130, AlignHCenter, C_LIGHTCYAN, gamescreen );
if ( iNewCounter != iCounter )
{
Audio->PlaySample( "alarm.voc" );
iCounter = iNewCounter;
}
}
else
{
SDL_Rect oRect;
oRect.x = 40;
oRect.y = iFootY;
SDL_BlitSurface( poFoot, NULL, gamescreen, &oRect );
}
SDL_Flip( gamescreen );
if ( g_oState.m_bQuitFlag || bKeyPressed )
{
break;
}
}
SDL_FillRect( gamescreen, NULL, C_BLACK );
if ( bTimeUp )
{
SDL_UnlockSurface( gamescreen );
DrawGradientText( "SPLAT!", titleFont, 220, gamescreen );
Audio->PlaySample( "splat2.voc" );
SDL_Flip( gamescreen );
SDL_Delay( 1500 );
g_oState.m_enGameMode = SState::IN_DEMO;
}
else
{
SDL_Flip( gamescreen );
}
SDL_FreeSurface( poBackground );
return;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index ad681cd..2e68a36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,27 +1,27 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = openmortal
openmortal_SOURCES = Audio.cpp Backend.cpp common.cpp \
Demo.cpp FighterStats.cpp FlyingChars.cpp Game.cpp gfx.cpp main.cpp \
menu.cpp PlayerSelect.cpp RlePack.cpp sge_bm_text.cpp \
sge_primitives.cpp sge_surface.cpp sge_tt_text.cpp State.cpp \
GameOver.cpp
EXTRA_DIST = Audio.h Backend.h common.h Demo.h FlyingChars.h gfx.h \
menu.h RlePack.h sge_bm_text.h sge_config.h sge_internal.h \
sge_primitives.h sge_surface.h sge_tt_text.h State.h \
- Game.h \
+ Game.h FighterEnum.h PlayerSelect.h\
Audio.cpp Backend.cpp common.cpp \
Demo.cpp FighterStats.cpp FlyingChars.cpp Game.cpp gfx.cpp main.cpp \
menu.cpp PlayerSelect.cpp RlePack.cpp sge_bm_text.cpp \
sge_primitives.cpp sge_surface.cpp sge_tt_text.cpp State.cpp \
GameOver.cpp
CXXFLAGS= @CXXFLAGS@ -DDATADIR=\"${pkgdatadir}\" -Wall
# set the include path found by configure
#INCLUDES= $(all_includes)
# the library search path.
#msz_LDFLAGS = $(all_libraries)
diff --git a/src/PlayerSelect.cpp b/src/PlayerSelect.cpp
index 644005b..c0d9bf7 100644
--- a/src/PlayerSelect.cpp
+++ b/src/PlayerSelect.cpp
@@ -1,497 +1,473 @@
/***************************************************************************
PlayerSelect.cpp - description
-------------------
begin : Sun Dec 8 2002
copyright : (C) 2002 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include <stdio.h>
+
+#include "PlayerSelect.h"
#include "SDL.h"
#include "SDL_video.h"
#include "SDL_image.h"
#include "sge_primitives.h"
#include "common.h"
#include "Audio.h"
#include "gfx.h"
#include "RlePack.h"
#include "Backend.h"
#include "State.h"
#define CHOOSERLEFT 158
#define CHOOSERTOP 98
#define CHOOSERHEIGHT 80
#define CHOOSERWIDTH 80
#define CHOOSERROWS 4
#define CHOOSERCOLS 4
#ifndef NULL
#define NULL 0
#endif
/***************************************************************************
PUBLIC EXPORTED VARIABLES
***************************************************************************/
-FighterEnum Fighter1 = ZOLI;
-FighterEnum Fighter2 = ZOLI;
-RlePack* pack1;
-RlePack* pack2;
+
+PlayerSelect g_oPlayerSelect;
/***************************************************************************
PRIVATE VARIABLES (perl variable space)
***************************************************************************/
+/*
int p1 = 0;
int p2 = 3;
bool done1 = false;
bool done2 = false;
-
+*/
FighterEnum ChooserCells[CHOOSERROWS][CHOOSERCOLS] = {
{ ZOLI, UPI, CUMI, SIRPI },
{ ULMAR, MACI, BENCE, GRIZLI },
{ AMBRUS, DESCANT, SURBA, DANI },
{ UNKNOWN, KINGA, MISI, UNKNOWN },
};
+PlayerSelect::PlayerSelect()
+{
+ for ( int i=0; i<2; ++i )
+ {
+ m_aoPlayers[i].m_enFighter = UNKNOWN;
+ m_aoPlayers[i].m_enTint = NO_TINT;
+ m_aoPlayers[i].m_poPack = NULL;
+ }
+
+ m_iP1 = 0;
+ m_iP2 = CHOOSERCOLS-1;
+}
+
-bool IsFighterAvailable( FighterEnum a_enFighter )
+const PlayerInfo& PlayerSelect::GetPlayerInfo( int a_iPlayer )
+{
+ return m_aoPlayers[ a_iPlayer ? 1 : 0 ];
+}
+
+
+bool PlayerSelect::IsFighterAvailable( FighterEnum a_enFighter )
{
static bool g_abFighterAvailable[ LASTFIGHTER ] =
{
false,
true, true, true, true,
true, true, true, true,
true, false, false, false,
false, false
};
if ( a_enFighter < UNKNOWN
|| a_enFighter >= LASTFIGHTER )
{
return false;
}
return g_abFighterAvailable[ a_enFighter ];
}
-RlePack* LoadFighter( FighterEnum fighter, int offset )
+/** LoadFighter simply looks up the filename associated with the given
+fighter, loads it, and returns the RlePack.
+
+\return The freshly loaded RlePack, or NULL if it could not be loaded.
+*/
+
+RlePack* PlayerSelect::LoadFighter( FighterEnum m_enFighter ) // static
{
- char filename[FILENAME_MAX+1];
+ char a_pcFilename[FILENAME_MAX+1];
const char* s;
- switch (fighter)
+ switch (m_enFighter)
{
case ZOLI: s = "ZOLIDATA.DAT"; break;
case UPI: s = "UPIDATA.DAT"; break;
case ULMAR: s = "ULMARDATA.DAT"; break;
case CUMI: s = "CUMIDATA.DAT"; break;
case SIRPI: s = "SIRPIDATA.DAT"; break;
case MACI: s = "MACIDATA.DAT"; break;
case BENCE: s = "BENCEDATA.DAT"; break;
case DESCANT: s = "DESCANTDATA.DAT"; break;
case GRIZLI: s = "GRIZLIDATA.DAT"; break;
- default: s = "ZOLIDATA.DAT"; break;
+ default: return NULL; break;
}
- strcpy( filename, DATADIR );
- strcat( filename, "/characters/" );
- strcat( filename, s );
-
- RlePack* pack = new RlePack( filename );
- pack->offsetSprites( offset );
- SDL_SetColors( gamescreen, pack->getPalette(), offset, 64 );
- return pack;
-}
+ strcpy( a_pcFilename, DATADIR );
+ strcat( a_pcFilename, "/characters/" );
+ strcat( a_pcFilename, s );
-
-void TintFighter( RlePack* fighter, TintEnum tint, int offset )
-{
- if ( tint == RANDOM_TINT )
+ RlePack* pack = new RlePack( a_pcFilename, COLORSPERPLAYER );
+ if ( pack->Count() <= 0 )
{
- switch (rand() % 4 )
- {
- case 0: tint = ZOMBIE_TINT; break;
- case 1: tint = GRAY_TINT; break;
- case 2: tint = DARK_TINT; break;
- case 3: tint = INVERTED_TINT; break;
- }
+ debug( "Couldn't load RlePack: '%s'\n", a_pcFilename );
+ delete pack;
+ return NULL;
}
+
+ return pack;
+}
- SDL_Color palette[64];
- int i;
-
- memcpy( palette, fighter->getPalette(), sizeof(palette) );
-
- switch( tint )
- {
- case ZOMBIE_TINT:
- {
- for ( i=0; i<64; ++i )
- {
- palette[i].r = 0;
- palette[i].b = 0;
- }
- break;
- }
-
- case GRAY_TINT:
- {
- int j;
- for ( i=0; i<64; ++i )
- {
- j = (palette[i].r + palette[i].g + palette[i].b)/4;
- palette[i].r = j;
- palette[i].g = j;
- palette[i].b = j;
- }
- break;
- }
-
- case DARK_TINT:
- {
- for ( i=0; i<64; ++i )
- {
- palette[i].r = int(palette[i].r) * 2 / 3;
- palette[i].g = int(palette[i].g) * 2 / 3;
- palette[i].b = int(palette[i].b) * 2 / 3;
- }
- break;
- }
-
- case INVERTED_TINT:
- {
- for ( i=0; i<64; ++i )
- {
- palette[i].r = 255 - palette[i].r;
- palette[i].g = 255 - palette[i].g;
- palette[i].b = 255 - palette[i].b;
- }
- break;
- }
-
- default:
- break;
- }
- SDL_SetColors( gamescreen, palette, offset, 64 );
-}
+/** SetPlayer loads the given fighter for the given player.
+The RlePack is loaded first. If that succeeds, then the perl backend is
+set too. The tint and palette of both players are set. */
-void SetPlayer( int player, FighterEnum fighter )
+void PlayerSelect::SetPlayer( int a_iPlayer, FighterEnum a_enFighter )
{
- int offset = player ? 176 : 112;
- RlePack* pack = LoadFighter( fighter, offset );
+ if ( a_iPlayer ) a_iPlayer = 1; // It's 0 or 1.
- if ( player )
+ if ( m_aoPlayers[a_iPlayer].m_enFighter == a_enFighter )
{
- delete pack2;
- pack2 = pack;
+ return;
}
- else
+
+ int iOffset = a_iPlayer ? COLOROFFSETPLAYER2 : COLOROFFSETPLAYER1;
+ RlePack* poPack = LoadFighter( a_enFighter );
+ poPack->OffsetSprites( iOffset );
+
+ if ( NULL == poPack )
{
- delete pack1;
- pack1 = pack;
- }
- PERLCALL( "SetPlayerNumber", player, fighter );
-
- FighterEnum& thisPlayer = player ? Fighter2 : Fighter1;
-
- thisPlayer = fighter;
- if ( pack2 )
+ debug( "SetPlayer(%d,%d): Couldn't load RlePack\n", a_iPlayer, a_enFighter );
+ return;
+ }
+
+ delete m_aoPlayers[a_iPlayer].m_poPack;
+ m_aoPlayers[a_iPlayer].m_poPack = poPack;
+ m_aoPlayers[a_iPlayer].m_enFighter = a_enFighter;
+
+ g_oBackend.PerlEvalF( "SetPlayerNumber(%d,%d);", a_iPlayer, a_enFighter );
+
+ TintEnum enTint = NO_TINT;
+
+ if ( m_aoPlayers[0].m_enFighter == m_aoPlayers[1].m_enFighter )
{
- TintFighter( pack2, Fighter1 == Fighter2 ? RANDOM_TINT : NO_TINT, 176 );
+ enTint = TintEnum( (rand() % 4) + 1 );
}
+ SetTint( 1, enTint );
+ m_aoPlayers[a_iPlayer].m_poPack->ApplyPalette();
}
+void PlayerSelect::SetTint( int a_iPlayer, TintEnum a_enTint )
+{
+ m_aoPlayers[a_iPlayer].m_enTint = a_enTint;
+ if ( m_aoPlayers[a_iPlayer].m_poPack )
+ {
+ m_aoPlayers[a_iPlayer].m_poPack->SetTint( a_enTint );
+ m_aoPlayers[a_iPlayer].m_poPack->ApplyPalette();
+ }
+}
-void handleKey( int player, int key )
+void PlayerSelect::HandleKey( int a_iPlayer, int a_iKey )
{
- int& p = player ? p2 : p1;
- int oldp = p;
- bool& done = player ? done2 : done1;
- if ( done )
+ int& riP = a_iPlayer ? m_iP2 : m_iP1;
+ int iOldP = riP;
+
+ bool& rbDone = a_iPlayer ? m_bDone2 : m_bDone1;
+ if ( rbDone )
{
return;
}
- switch ( key )
+ switch ( a_iKey )
{
case 0: // up
- if ( p >= CHOOSERCOLS ) p -= CHOOSERCOLS;
+ if ( riP >= CHOOSERCOLS ) riP -= CHOOSERCOLS;
break;
case 1: // down
- if ( (p/CHOOSERCOLS) < (CHOOSERROWS-1) ) p += CHOOSERCOLS;
+ if ( (riP/CHOOSERCOLS) < (CHOOSERROWS-1) ) riP += CHOOSERCOLS;
break;
case 2: // left
- if ( (p % CHOOSERCOLS) > 0 ) p--;
+ if ( (riP % CHOOSERCOLS) > 0 ) riP--;
break;
case 3: // right
- if ( (p % CHOOSERCOLS) < (CHOOSERCOLS-1) ) p++;
+ if ( (riP % CHOOSERCOLS) < (CHOOSERCOLS-1) ) riP++;
break;
default:
- if ( ChooserCells[p/4][p%4] )
+ if ( ChooserCells[riP/4][riP%4] )
{
- done = true;
- PERLCALL( "PlayerSelected", player, 0 );
+ rbDone = true;
+
+ g_oBackend.PerlEvalF( "PlayerSelected(%d);", a_iPlayer );
Audio->PlaySample("magic.voc");
return;
}
}
- if ( !IsFighterAvailable( ChooserCells[p/CHOOSERCOLS][p%CHOOSERCOLS] ) )
+ if ( !IsFighterAvailable( ChooserCells[riP/CHOOSERCOLS][riP%CHOOSERCOLS] ) )
{
- p = oldp;
+ riP = iOldP;
}
- if ( oldp != p )
+ if ( iOldP != riP )
{
Audio->PlaySample("strange_quack.voc");
- SetPlayer( player, ChooserCells[p/CHOOSERCOLS][p%CHOOSERCOLS] );
+ SetPlayer( a_iPlayer, ChooserCells[riP/CHOOSERCOLS][riP%CHOOSERCOLS] );
}
}
-void drawRect( int pos, int color )
+void PlayerSelect::DrawRect( int a_iPos, int a_iColor )
{
- int row = pos / CHOOSERCOLS;
- int col = pos % CHOOSERCOLS;
+ int iRow = a_iPos / CHOOSERCOLS;
+ int iCol = a_iPos % CHOOSERCOLS;
SDL_Rect r, r1;
- r.x = CHOOSERLEFT + col * CHOOSERWIDTH;
- r.y = CHOOSERTOP + row * CHOOSERHEIGHT;
+ r.x = CHOOSERLEFT + iCol * CHOOSERWIDTH;
+ r.y = CHOOSERTOP + iRow * CHOOSERHEIGHT;
r.w = CHOOSERWIDTH + 5;
r.h = 5;
r1 = r;
- SDL_FillRect( gamescreen, &r1, color );
+ SDL_FillRect( gamescreen, &r1, a_iColor );
r.y += CHOOSERHEIGHT;
r1 = r;
- SDL_FillRect( gamescreen, &r1, color );
+ SDL_FillRect( gamescreen, &r1, a_iColor );
r.y -= CHOOSERHEIGHT;
r.w = 5;
r.h = CHOOSERHEIGHT + 5;
r1 = r;
- SDL_FillRect( gamescreen, &r1, color );
+ SDL_FillRect( gamescreen, &r1, a_iColor );
r.x += CHOOSERWIDTH;
r1 = r;
- SDL_FillRect( gamescreen, &r1, color );
+ SDL_FillRect( gamescreen, &r1, a_iColor );
}
-void checkPlayer( SDL_Surface* background, int row, int col )
+void PlayerSelect::CheckPlayer( SDL_Surface* a_poBackground, int a_iRow, int a_iCol )
{
int x1, y1;
- x1 = CHOOSERLEFT + col * CHOOSERWIDTH +5;
- y1 = CHOOSERTOP + row * CHOOSERHEIGHT +5;
+ x1 = CHOOSERLEFT + a_iCol * CHOOSERWIDTH +5;
+ y1 = CHOOSERTOP + a_iRow * CHOOSERHEIGHT +5;
- sge_Line(background, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
- sge_Line(background, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
x1++;
- sge_Line(background, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
- sge_Line(background, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
y1++;
- sge_Line(background, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
- sge_Line(background, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
x1--;
- sge_Line(background, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
- sge_Line(background, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1+5, y1+5, x1 + CHOOSERWIDTH-10, y1 + CHOOSERHEIGHT-10, 252);
+ sge_Line(a_poBackground, x1 + CHOOSERWIDTH-10, y1+5, x1+5, y1 + CHOOSERHEIGHT-10, 252);
}
-void PlayerSelect()
+void PlayerSelect::DoPlayerSelect()
{
+ // 1. Set up: Load background, mark unavailable fighters
+
SDL_FillRect( gamescreen, NULL, C_BLACK );
SDL_Flip( gamescreen );
- char filename[FILENAME_MAX+1];
- strcpy( filename, DATADIR );
- strcat( filename, "/gfx/" );
- strcat( filename, "PlayerSelect.png" );
-
- SDL_Surface* background = IMG_Load( filename );
- if (!background)
- {
- debug( "Can't load file: %s\n", filename );
- g_oState.m_bQuitFlag = true;
- return;
- }
-
- SDL_Palette* pal = background->format->palette;
- if ( pal )
- {
- int ncolors = pal->ncolors;
- if (ncolors>111) ncolors = 111;
- SDL_SetColors( gamescreen, pal->colors, 0, ncolors );
- }
- background = SDL_DisplayFormat( background );
+ SDL_Surface* poBackground = LoadBackground( "PlayerSelect.png", 111 );
- DrawGradientText( "Choose A Fighter Dammit", titleFont, 10, background );
+ DrawGradientText( "Choose A Fighter Dammit", titleFont, 10, poBackground );
- int i;
+ int i, j;
for ( i=0; i<CHOOSERROWS; ++i )
{
for ( int j=0; j<CHOOSERCOLS; ++j )
{
if ( !IsFighterAvailable(ChooserCells[i][j]) &&
UNKNOWN != ChooserCells[i][j] )
{
- checkPlayer( background, i, j );
+ CheckPlayer( poBackground, i, j );
}
}
}
-
- if (pack1) SDL_SetColors( gamescreen, pack1->getPalette(), 112, 64 );
- if (pack2) SDL_SetColors( gamescreen, pack2->getPalette(), 176, 64 );
- PERLEVAL( "SelectStart();" );
+ for ( i=0; i<2; ++i )
+ {
+ if ( m_aoPlayers[i].m_poPack ) m_aoPlayers[i].m_poPack->ApplyPalette();
+ }
+
+ SetPlayer( 0, ChooserCells[m_iP1/CHOOSERCOLS][m_iP1%CHOOSERCOLS] );
+ SetPlayer( 1, ChooserCells[m_iP2/CHOOSERCOLS][m_iP2%CHOOSERCOLS] );
+
+ // 2. Run selection screen
+
+ g_oBackend.PerlEvalF( "SelectStart();" );
- done1 = done2 = false;
+ m_bDone1 = m_bDone2 = false;
int thisTick, lastTick, gameSpeed;
gameSpeed = 12 ;
thisTick = SDL_GetTicks() / gameSpeed;
lastTick = thisTick - 1;
i = 0;
- bool bDraw = true;
int over = 0;
int iCourtain = 0;
int iCourtainSpeed = 0;
int iCourtainTime = 80;
SDL_Event event;
while (1)
{
// 1. Wait for the next tick (on extremely fast machines..)
while (1)
{
thisTick = SDL_GetTicks() / gameSpeed;
if ( thisTick==lastTick )
{
SDL_Delay(1);
}
else
{
break;
}
}
// 2. Advance as many ticks as necessary..
if ( iCourtainTime > 0 )
{
int iAdvance = thisTick - lastTick;
if ( iAdvance > 5 ) iAdvance = 5;
if ( iCourtain + iCourtainSpeed * iCourtainTime /2 < 320 * 4 )
iCourtainSpeed += iAdvance;
else
iCourtainSpeed -= iAdvance;
iCourtain += iCourtainSpeed * iAdvance;
iCourtainTime -= iAdvance;
if ( iCourtainTime > 0 )
{
SDL_Rect oRect;
oRect.x = 320 - iCourtain/4; oRect.y = 0;
oRect.w = iCourtain / 2; oRect.h = gamescreen->h;
if ( oRect.x < 0 ) oRect.x = 0;
if ( oRect.w > gamescreen->w ) oRect.w = gamescreen->w;
SDL_SetClipRect( gamescreen, &oRect );
}
else
{
SDL_SetClipRect( gamescreen, NULL );
}
}
int iNumFrames = thisTick - lastTick;
if ( iNumFrames>5 ) iNumFrames = 5;
- for ( int i=0; i<iNumFrames; ++i )
+ for ( i=0; i<iNumFrames; ++i )
{
g_oBackend.AdvancePerl();
}
lastTick = thisTick;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
g_oState.m_bQuitFlag = true;
break;
case SDL_KEYDOWN:
{
if ( event.key.keysym.sym == SDLK_ESCAPE )
{
DoMenu( false );
break;
}
- for (int i=0; i<2; i++)
+ for ( i=0; i<2; i++ )
{
- for (int j=0; j<9; j++ )
+ for ( j=0; j<9; j++ )
{
if (g_oState.m_aiPlayerKeys[i][j] == event.key.keysym.sym)
{
- drawRect( p1, 240 );
- drawRect( p2, 240 );
- handleKey( i, j );
+ DrawRect( m_iP1, 240 );
+ DrawRect( m_iP2, 240 );
+ HandleKey( i, j );
}
}
}
}
break;
} // switch statement
} // Polling events
- int p1x = SvIV(get_sv("p1x", FALSE));
- int p1y = SvIV(get_sv("p1y", FALSE));
- int p1f = SvIV(get_sv("p1f", FALSE));
- int p2x = SvIV(get_sv("p2x", FALSE));
- int p2y = SvIV(get_sv("p2y", FALSE));
- int p2f = SvIV(get_sv("p2f", FALSE));
- over = SvIV(get_sv("over", FALSE));
+ g_oBackend.ReadFromPerl();
+
+ over = g_oBackend.m_iGameOver;
- SDL_BlitSurface( background, NULL, gamescreen, NULL );
- if (p1f) pack1->draw( ABS(p1f)-1, p1x, p1y, p1f<0 );
- if (p2f) pack2->draw( ABS(p2f)-1, p2x, p2y, p2f<0 );
+ SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
+
+ for ( i=0; i<2; ++i )
+ {
+ if ( g_oBackend.m_aoPlayers[i].m_iFrame )
+ {
+ m_aoPlayers[i].m_poPack->Draw(
+ ABS(g_oBackend.m_aoPlayers[i].m_iFrame)-1,
+ g_oBackend.m_aoPlayers[i].m_iX, g_oBackend.m_aoPlayers[i].m_iY,
+ g_oBackend.m_aoPlayers[i].m_iFrame < 0 );
+ }
+ }
- if ( !done1) drawRect( p1, 250 );
- if ( !done2) drawRect( p2, 253 );
+ if ( !m_bDone1) DrawRect( m_iP1, 250 );
+ if ( !m_bDone2) DrawRect( m_iP2, 253 );
SDL_Flip( gamescreen );
if (over || g_oState.m_bQuitFlag || SState::IN_DEMO == g_oState.m_enGameMode) break;
}
- SDL_FreeSurface( background );
+ SDL_FreeSurface( poBackground );
SDL_SetClipRect( gamescreen, NULL );
return;
}
diff --git a/src/PlayerSelect.h b/src/PlayerSelect.h
new file mode 100644
index 0000000..f8819a6
--- /dev/null
+++ b/src/PlayerSelect.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ PlayerSelect.h - description
+ -------------------
+ begin : 2003-09-05
+ copyright : (C) 2003 by upi
+ email : upi@apocalypse.rulez.org
+ ***************************************************************************/
+
+
+#ifndef PLAYERSELECT_H
+#define PLAYERSELECT_H
+
+#define COLORSPERPLAYER 64
+#define COLOROFFSETPLAYER1 112
+#define COLOROFFSETPLAYER2 (COLOROFFSETPLAYER1+64)
+
+
+
+#include "FighterEnum.h"
+
+class RlePack;
+struct SDL_Surface;
+
+/** PlayerInfo structure stores information about a PLAYER.
+
+In OpenMortal, the term PLAYER refers to one of the two guys playing the
+game, as opposed to FIGHTER, which refers to one of the many playable
+characters.
+
+PlayerInfo stores: the player's selected fighter, the fighters tint and
+RlePack. */
+
+struct PlayerInfo
+{
+ FighterEnum m_enFighter;
+ TintEnum m_enTint;
+ RlePack* m_poPack;
+};
+
+
+
+/** This class implements services that allows players to select their
+fighters. It also stores info about which player is available, and
+allows other parts of the program to programmatically assign a fighter
+to a player, and set fighter tints (this is used by e.g. the "frozen"
+effect. */
+
+class PlayerSelect
+{
+public:
+ PlayerSelect();
+
+ const PlayerInfo& GetPlayerInfo( int a_iPlayer );
+
+ void DoPlayerSelect();
+ void SetPlayer( int a_iPlayer, FighterEnum a_enFighter );
+ void SetTint( int a_iPlayer, TintEnum a_enFighter );
+ bool IsFighterAvailable( FighterEnum a_enFighter );
+
+protected:
+
+ void HandleKey( int a_iPlayer, int a_iKey );
+ void DrawRect( int a_iPos, int a_iColor );
+ void CheckPlayer( SDL_Surface* a_poBackground, int a_iRow, int a_iCol );
+ static RlePack* LoadFighter( FighterEnum m_enFighter );
+
+protected:
+ PlayerInfo m_aoPlayers[2];
+ int m_iP1, m_iP2; // Chooser cells for player 1 and 2
+ bool m_bDone1, m_bDone2; // Has player n chosen a player?
+
+};
+
+
+extern PlayerSelect g_oPlayerSelect;
+
+#endif // PLAYERSELECT_H
diff --git a/src/RlePack.cpp b/src/RlePack.cpp
index 6e58f47..7a8d3dc 100644
--- a/src/RlePack.cpp
+++ b/src/RlePack.cpp
@@ -1,544 +1,809 @@
/***************************************************************************
RlePack.cpp - description
-------------------
begin : Mon Sep 24 2001
copyright : (C) 2001 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
+#include "RlePack.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "SDL.h"
-#include "SDL_video.h"
+#include "SDL.h"
#include "common.h"
-#include "RlePack.h"
+
+
+/// Sanity: This is the maximal number of entries in a .DAT file.
+#define MAXDATACOUNT 65530
+
+
+inline void ChangeEndian32( Uint32& a_riArg )
+{
+ char* pcArg = (char*)&a_riArg;
+ char cTemp;
+ cTemp = pcArg[0]; pcArg[0] = pcArg[3]; pcArg[3] = cTemp;
+ cTemp = pcArg[1]; pcArg[1] = pcArg[2]; pcArg[2] = cTemp;
+}
+
+
+inline void ChangeEndian16( Uint16& a_riArg )
+{
+ char* pcArg = (char*)&a_riArg;
+ char cTemp;
+ cTemp = pcArg[0]; pcArg[0] = pcArg[1]; pcArg[1] = cTemp;
+}
+
+
+inline Uint32 ConvertEndian32( Uint32 a_iArg )
+{
+ char* pcArg = (char*)&a_iArg;
+ char cTemp;
+ cTemp = pcArg[0]; pcArg[0] = pcArg[3]; pcArg[3] = cTemp;
+ cTemp = pcArg[1]; pcArg[1] = pcArg[2]; pcArg[2] = cTemp;
+ return a_iArg;
+}
+
+
+inline Uint16 ConvertEndian16( Uint16 a_iArg )
+{
+ char* pcArg = (char*)&a_iArg;
+ char cTemp;
+ cTemp = pcArg[0]; pcArg[0] = pcArg[1]; pcArg[1] = cTemp;
+ return a_iArg;
+}
+
typedef struct RLE_SPRITE /* a RLE compressed sprite */
{
- int w, h; /* width and height in pixels */
- int color_depth; /* color depth of the image */
- int size; /* size of sprite data in bytes */
- signed char dat[0];
+ Uint16 dummy; // For better alignment... NASTY NASTY HACK!!
+ Uint16 color_depth; /* color depth of the image */
+ Uint16 w, h; /* width and height in pixels */
+ Uint32 size;
+ signed char dat[0];
} RLE_SPRITE;
struct RlePack_P
{
- SDL_Color palette[256];
- int count, arraysize;
- RLE_SPRITE** sprites;
+ SDL_Color m_aoPalette[256];
+ SDL_Color m_aoTintedPalette[256];
+ TintEnum m_enTint;
+ int m_iCount;
+ int m_iArraysize;
+ RLE_SPRITE** m_pSprites;
+ void* m_pData;
+
+ int m_iColorCount;
+ int m_iColorOffset;
};
-RlePack::RlePack( const char* filename )
+
+
+RlePack::RlePack( const char* a_pcFilename, int a_iNumColors )
{
p = new RlePack_P;
- p->count = p->arraysize = 0;
- p->sprites = NULL;
+ p->m_enTint = NO_TINT;
+ p->m_iCount = 0;
+ p->m_iArraysize = 0;
+ p->m_pSprites = NULL;
+ p->m_pData = NULL;
+
+ p->m_iColorCount = 0;
+ p->m_iColorOffset = 0;
+
+ // Load file and stuff
+
+ LoadFile( a_pcFilename, a_iNumColors );
+}
+
+
+RlePack::~RlePack()
+{
+ if (!p)
+ return;
+
+ if (p->m_pSprites)
+ {
+ delete[] p->m_pSprites;
+ p->m_pSprites = NULL;
+ }
- //@ Load file and stuff
+ free( p->m_pData );
+ delete( p );
+ p = NULL;
+}
+
+
+void RlePack::Clear()
+{
+ if ( p && p->m_pSprites )
+ {
+ delete[] p->m_pSprites;
+ p->m_pSprites = NULL;
+ }
+}
+
+
+int RlePack::LoadFile( const char* a_pcFilename, int a_iNumColors )
+{
FILE* f;
- f = fopen( filename, "rb" );
+ f = fopen( a_pcFilename, "rb" );
if (f==NULL)
{
- debug( "Can't open file '%s'.\n", filename );
- return;
+ debug( "Can't open file '%s'.\n", a_pcFilename );
+ return -1;
+ }
+
+ fseek( f, 0, SEEK_END );
+ long iFileSize = ftell ( f );
+ p->m_pData = malloc( iFileSize );
+ if ( NULL == p->m_pData )
+ {
+ fclose( f );
+ return -1;
+ }
+
+ fseek( f, 0, SEEK_SET );
+ int iRead = fread( p->m_pData, 1, iFileSize, f );
+ fclose( f );
+
+ p->m_iColorCount = a_iNumColors;
+
+ if ( iFileSize != iRead )
+ {
+ debug( "Warning RlePack(): iFileSize=%d, iRead=%d\n", iFileSize, iRead );
}
+ struct SHeader
+ {
+ char acDummy[8];
+ Uint32 iDatacount;
+ } *poHeader = (SHeader*) p->m_pData;
+
+ ChangeEndian32( poHeader->iDatacount );
+ debug( "File '%s' contains %d entries.\n", a_pcFilename, poHeader->iDatacount );
+
+ if (poHeader->iDatacount>MAXDATACOUNT) poHeader->iDatacount = MAXDATACOUNT; // Sanity
+
+ p->m_iArraysize = poHeader->iDatacount;
+ p->m_pSprites = new RLE_SPRITE*[ poHeader->iDatacount ];
+
+ char* pcNext = ((char*)p->m_pData) + sizeof(SHeader);
+ char* pcEnd = ((char*)p->m_pData) + iFileSize;
+
+ while ( pcNext < pcEnd )
+ {
+ if ( 0 == strncmp( pcNext, "prop", 4 ) )
+ {
+ struct SProperty
+ {
+ char acName[4];
+ Uint32 iSize;
+ } *poProperty = (SProperty*) (pcNext+4);
+ ChangeEndian32( poProperty->iSize );
+
+ pcNext += 4 + sizeof(SProperty) + poProperty->iSize;
+ }
+ else if ( 0 == strncmp( pcNext, "RLE ", 4 ) )
+ {
+ struct SRLE
+ {
+ RLE_SPRITE oSprite;
+ } *poRle = (SRLE*) (pcNext+10);
+ poRle->oSprite.color_depth = ConvertEndian16(poRle->oSprite.color_depth);
+ poRle->oSprite.w = ConvertEndian16(poRle->oSprite.w);
+ poRle->oSprite.h = ConvertEndian16(poRle->oSprite.h);
+ poRle->oSprite.size = ConvertEndian32(poRle->oSprite.size);
+
+ p->m_pSprites[p->m_iCount] = &(poRle->oSprite);
+ p->m_iCount++;
+ pcNext += 10 + sizeof( SRLE ) + poRle->oSprite.size;
+ }
+ else if ( 0 == strncmp( pcNext, "PAL ", 4 ) )
+ {
+ struct SPAL
+ {
+ Uint32 iLength1;
+ Uint32 iLength;
+ SDL_Color aoColors[256];
+ } *poPal = (SPAL*) (pcNext+4);
+ ChangeEndian32( poPal->iLength );
+
+ int iNumColors = poPal->iLength>1024 ? 1024 : poPal->iLength;
+ iNumColors /= 4;
+
+ for (int i=0; i< iNumColors; i++)
+ {
+ p->m_aoPalette[i].r = poPal->aoColors[i].r*4;
+ p->m_aoPalette[i].g = poPal->aoColors[i].g*4;
+ p->m_aoPalette[i].b = poPal->aoColors[i].b*4;
+ p->m_aoPalette[i].unused = 0;
+ p->m_aoTintedPalette[i] = p->m_aoPalette[i];
+ }
+
+ pcNext += 4 + 8 + poPal->iLength;
+ }
+ else
+ {
+ struct SUnknown
+ {
+ Uint32 iSize;
+ } *poUnknown = (SUnknown*) (pcNext+4);
+ ChangeEndian32( poUnknown->iSize );
+
+ debug( "Unknown: '%4s', size: %d\n", pcNext, poUnknown->iSize );
+
+ pcNext += 4 + sizeof(SUnknown) + poUnknown->iSize;
+ }
+ }
+
+ return p->m_iCount;
+
+#if 0
+
int datacount;
#define READDW(I) { \
unsigned char data[4]; \
fread( data, 4, 1, f ); \
(I) = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; }
#define READW(I) { \
unsigned char data[2]; \
fread( data, 2, 1, f ); \
(I) = (data[0]<<8) + data[1]; }
#define READCH(S,C) { \
fread( S, C, 1, f ); S[C] = 0; }
fseek( f, 8, SEEK_SET ); // Skip header
READDW( datacount );
debug( "File '%s' contains %d entries.\n", filename, datacount );
if (datacount>500) datacount = 500; // Sanity
p->arraysize = datacount;
p->sprites = new RLE_SPRITE*[ datacount ];
while( (!feof(f)) && (!ferror(f)) && (datacount>0) )
{
char s[10];
READCH( s, 4 );
if ( !strcmp( s, "prop" )) // Found a property
{
fseek( f, 4, SEEK_CUR );
unsigned int propsize;
READDW( propsize );
fseek( f, propsize, SEEK_CUR );
}
else if (!strcmp( s, "RLE " )) // Found an RLE_SPRITE
{
datacount--;
unsigned int length, bpp, width, height, size;
READDW( length );
READDW( length );
READW( bpp );
READW( width );
READW( height );
READDW( size );
RLE_SPRITE* sprite = (RLE_SPRITE*) malloc( sizeof(RLE_SPRITE) + size );
p->sprites[ p->count ] = sprite;
(p->count)++;
sprite->w = width;
sprite->h = height;
sprite->color_depth = bpp;
sprite->size = size;
fread( sprite->dat, 1, size, f );
}
else if (!strcmp( s, "PAL ")) // Found a palette
{
datacount--;
unsigned int length, pallength;
READDW( length );
READDW( length );
pallength = length>1024 ? 1024 : length;
pallength /= 4;
for (unsigned int i=0; i< pallength; i++)
{
char c[4];
fread( c, 4, 1, f );
p->palette[i].r = c[0]*4;
p->palette[i].g = c[1]*4;
p->palette[i].b = c[2]*4;
p->palette[i].unused = 0;
}
fseek( f, length - pallength*4, SEEK_CUR );
}
else // Found something else
{
debug( "Unknown: %s.", s );
datacount--;
-
+
unsigned int length;
READDW( length );
READDW( length );
fseek( f, length, SEEK_CUR );
}
}
fclose( f );
+#endif
}
-RlePack::~RlePack()
+
+
+
+int RlePack::Count()
{
- if (!p)
- return;
-
- if (p->sprites)
- {
- for ( int i=0; i<p->count; ++i )
- {
- delete p->sprites[i];
- p->sprites[i] = NULL;
- }
- delete[] p->sprites;
- p->sprites = NULL;
- }
-
- delete( p );
- p = NULL;
+ return p->m_iCount;
}
-void OffsetRLESprite( RLE_SPRITE* spr, int offset )
+
+void OffsetRLESprite( RLE_SPRITE* spr, int offset ) // Static method
{
if (!spr || !offset) return;
-
+
signed char *s = spr->dat;
signed char c;
int y;
for (y=0; y<spr->h; y++)
{
c = *s++;
while (c)
{
// For positive c: solid pixels.
for ( ; c>0; c-- )
{
*s = (*s) + offset;
s++;
}
c = *s++;
}
}
}
-void RlePack::offsetSprites( int offset )
+void RlePack::OffsetSprites( int a_iOffset )
{
- if ( (offset<=0) || (offset>255) )
+ if ( (a_iOffset<=0) || (a_iOffset>255) )
return;
+ p->m_iColorOffset = a_iOffset;
+
int i;
// Offset every RLE_SPRITE
- for ( i=0; i<p->count; ++i )
+ for ( i=0; i<p->m_iCount; ++i )
{
- OffsetRLESprite( p->sprites[i], offset );
+ OffsetRLESprite( p->m_pSprites[i], a_iOffset );
}
}
+
+void RlePack::SetTint( TintEnum a_enTint )
+{
+ int i;
+
+ switch( a_enTint )
+ {
+ case ZOMBIE_TINT:
+ {
+ for ( i=0; i<p->m_iColorCount; ++i )
+ {
+ p->m_aoTintedPalette[i].r = 0;
+ p->m_aoTintedPalette[i].g = p->m_aoPalette[i].g;
+ p->m_aoTintedPalette[i].b = 0;
+ }
+ break;
+ }
+
+ case GRAY_TINT:
+ {
+ int j;
+ for ( i=0; i<p->m_iColorCount; ++i )
+ {
+ j = (p->m_aoPalette[i].r + p->m_aoPalette[i].g + p->m_aoPalette[i].b)/4;
+ p->m_aoTintedPalette[i].r = j;
+ p->m_aoTintedPalette[i].g = j;
+ p->m_aoTintedPalette[i].b = j;
+ }
+ break;
+ }
+
+ case DARK_TINT:
+ {
+ for ( i=0; i<p->m_iColorCount; ++i )
+ {
+ p->m_aoTintedPalette[i].r = int(p->m_aoPalette[i].r) * 2 / 3;
+ p->m_aoTintedPalette[i].g = int(p->m_aoPalette[i].g) * 2 / 3;
+ p->m_aoTintedPalette[i].b = int(p->m_aoPalette[i].b) * 2 / 3;
+ }
+ break;
+ }
+
+ case INVERTED_TINT:
+ {
+ for ( i=0; i<p->m_iColorCount; ++i )
+ {
+ p->m_aoTintedPalette[i].r = 255 - p->m_aoPalette[i].r;
+ p->m_aoTintedPalette[i].g = 255 - p->m_aoPalette[i].g;
+ p->m_aoTintedPalette[i].b = 255 - p->m_aoPalette[i].b;
+ }
+ break;
+ }
+
+ case NO_TINT:
+ default:
+ {
+ for ( i=0; i<p->m_iColorCount; ++i )
+ {
+ p->m_aoTintedPalette[i] = p->m_aoPalette[i];
+ }
+ break;
+ }
+
+ } // end of switch( a_enTint )
+
+}
+
+
+void RlePack::ApplyPalette()
+{
+ SDL_SetColors( gamescreen, p->m_aoTintedPalette, p->m_iColorOffset, p->m_iColorCount );
+}
+
+/*
SDL_Color* RlePack::getPalette()
{
return p->palette;
}
+*/
-void draw_rle_sprite_v_flip( RLE_SPRITE* src, int dx, int dy )
+void draw_rle_sprite_v_flip( RLE_SPRITE* src, int dx, int dy ) // static method
{
#define RLE_PTR signed char*
#define RLE_IS_EOL(c) ((c) == 0)
#define PIXEL_PTR unsigned char*
#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x))
#define INC_PIXEL_PTR(p) ((p)++)
#define DEC_PIXEL_PTR(p) ((p)--)
#define PUT_PIXEL(p,c) (*((unsigned char *)(p)) = (c))
//#define PUT_PIXEL(p,c) bmp_write8((unsigned long) (p), (c))
int x, y, w, h; // width and height of visible area
int dxbeg, dybeg; // beginning in destination
int sxbeg, sybeg; // beginning in source
RLE_PTR s;
SDL_Surface* dst = gamescreen;
// Clip to dst->clip_rect
int dst_cl = dst->clip_rect.x;
int dst_cr = dst->clip_rect.w + dst_cl;
int dst_ct = dst->clip_rect.y;
int dst_cb = dst->clip_rect.h + dst_ct;
// if (dst->clip)
if (1)
{
int tmp;
dxbeg = dx;
if ( dst_cl > dx ) dxbeg = dst_cl;
tmp = dx + src->w - dst_cr;
sxbeg = ((tmp < 0) ? 0 : tmp);
tmp = dx + src->w;
if (tmp > dst_cr ) tmp = dst_cr;
w = tmp - dxbeg;
if (w <= 0)
return;
tmp = dst_ct - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst_cb - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if (h <= 0)
return;
}
else {
w = src->w;
h = src->h;
sxbeg = 0;
sybeg = 0;
dxbeg = dx;
dybeg = dy;
}
s = (RLE_PTR) (src->dat);
dxbeg += w;
/* Clip top. */
for (y = sybeg - 1; y >= 0; y--) {
long c = *s++;
while (!RLE_IS_EOL(c)) {
if (c > 0)
s += c;
c = *s++;
}
}
//@@@ bmp_select(dst);
/* Visible part. */
for (y = 0; y < h; y++) {
//@@@ PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
PIXEL_PTR d = (PIXEL_PTR) dst->pixels;
d += (dybeg+y)*dst->pitch;
d = OFFSET_PIXEL_PTR( d, dxbeg );
long c = *s++;
/* Clip left. */
for (x = sxbeg; x > 0; ) {
if (RLE_IS_EOL(c))
goto next_line;
else if (c > 0) {
/* Run of solid pixels. */
if ((x - c) >= 0) {
/* Fully clipped. */
x -= c;
s += c;
}
else {
/* Visible on the right. */
c -= x;
s += x;
break;
}
}
else {
/* Run of transparent pixels. */
if ((x + c) >= 0) {
/* Fully clipped. */
x += c;
}
else {
/* Visible on the right. */
c += x;
break;
}
}
c = *s++;
}
/* Visible part. */
for (x = w; x > 0; ) {
if (RLE_IS_EOL(c))
goto next_line;
else if (c > 0) {
/* Run of solid pixels. */
if ((x - c) >= 0) {
/* Fully visible. */
x -= c;
for (c--; c >= 0; s++, DEC_PIXEL_PTR(d), c--) {
unsigned long col = *s;
PUT_PIXEL(d, col);
}
}
else {
/* Clipped on the right. */
c -= x;
for (x--; x >= 0; s++, DEC_PIXEL_PTR(d), x--) {
unsigned long col = *s;
PUT_PIXEL(d, col);
}
break;
}
}
else {
/* Run of transparent pixels. */
x += c;
d = OFFSET_PIXEL_PTR(d, c);
}
c = *s++;
}
/* Clip right. */
while (!RLE_IS_EOL(c)) {
if (c > 0)
s += c;
c = *s++;
}
next_line: ;
}
//@@@bmp_unwrite_line(dst);
}
-void draw_rle_sprite( RLE_SPRITE* src, int dx, int dy )
+void draw_rle_sprite( RLE_SPRITE* src, int dx, int dy ) // static method
{
#define RLE_PTR signed char*
#define RLE_IS_EOL(c) ((c) == 0)
#define PIXEL_PTR unsigned char*
#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x))
#define INC_PIXEL_PTR(p) ((p)++)
#define DEC_PIXEL_PTR(p) ((p)--)
#define PUT_PIXEL(p,c) (*((unsigned char *)(p)) = (c))
//#define PUT_PIXEL(p,c) bmp_write8((unsigned long) (p), (c))
int x, y, w, h; // width and height of visible area
int dxbeg, dybeg; // beginning in destination
int sxbeg, sybeg; // beginning in source
RLE_PTR s;
SDL_Surface* dst = gamescreen;
// Clip to dst->clip_rect
int dst_cl = dst->clip_rect.x;
int dst_cr = dst->clip_rect.w + dst_cl;
int dst_ct = dst->clip_rect.y;
int dst_cb = dst->clip_rect.h + dst_ct;
// if (dst->clip)
if (1)
{
int tmp;
tmp = dst_cl - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst_cr - dx;
w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
if ( w<=0 ) return;
tmp = dst_ct - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst_cb - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if ( h<=0 ) return;
}
else {
w = src->w;
h = src->h;
sxbeg = 0;
sybeg = 0;
dxbeg = dx;
dybeg = dy;
}
s = (RLE_PTR) (src->dat);
/* Clip top. */
for (y = sybeg - 1; y >= 0; y--) {
long c = *s++;
while (!RLE_IS_EOL(c)) {
if (c > 0)
s += c;
c = *s++;
}
}
//@@@ bmp_select(dst);
/* Visible part. */
for (y = 0; y < h; y++) {
//@@@ PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
PIXEL_PTR d = (PIXEL_PTR) dst->pixels;
d += (dybeg+y)*dst->pitch;
d = OFFSET_PIXEL_PTR( d, dxbeg );
long c = *s++;
/* Clip left. */
for (x = sxbeg; x > 0; ) {
if (RLE_IS_EOL(c))
goto next_line;
else if (c > 0) {
/* Run of solid pixels. */
if ((x - c) >= 0) {
/* Fully clipped. */
x -= c;
s += c;
}
else {
/* Visible on the right. */
c -= x;
s += x;
break;
}
}
else {
/* Run of transparent pixels. */
if ((x + c) >= 0) {
/* Fully clipped. */
x += c;
}
else {
/* Visible on the right. */
c += x;
break;
}
}
c = *s++;
}
/* Visible part. */
for (x = w; x > 0; ) {
if (RLE_IS_EOL(c))
goto next_line;
else if (c > 0) {
/* Run of solid pixels. */
if ((x - c) >= 0) {
/* Fully visible. */
x -= c;
for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) {
unsigned long col = *s;
PUT_PIXEL(d, col);
}
}
else {
/* Clipped on the right. */
c -= x;
for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
unsigned long col = *s;
PUT_PIXEL(d, col);
}
break;
}
}
else {
/* Run of transparent pixels. */
x += c;
d = OFFSET_PIXEL_PTR(d, -c);
}
c = *s++;
}
/* Clip right. */
while (!RLE_IS_EOL(c)) {
if (c > 0)
s += c;
c = *s++;
}
next_line: ;
}
//@@@bmp_unwrite_line(dst);
}
-void RlePack::draw( int index, int x, int y, bool flipped )
+void RlePack::Draw( int a_iIndex, int a_iX, int a_iY, bool a_bFlipped )
{
- if ( (index<0) || (index>=p->count) )
+ if ( (a_iIndex<0) || (a_iIndex>=p->m_iCount) )
return;
- RLE_SPRITE* sprite = p->sprites[index];
- if (!sprite)
+ RLE_SPRITE* poSprite = p->m_pSprites[a_iIndex];
+ if (!poSprite)
return;
- if ( flipped )
- draw_rle_sprite_v_flip( sprite, x, y );
+ if ( a_bFlipped )
+ draw_rle_sprite_v_flip( poSprite, a_iX, a_iY );
else
- draw_rle_sprite( sprite, x, y );
+ draw_rle_sprite( poSprite, a_iX, a_iY );
}
diff --git a/src/RlePack.h b/src/RlePack.h
index 91c2f32..198f470 100644
--- a/src/RlePack.h
+++ b/src/RlePack.h
@@ -1,28 +1,57 @@
/***************************************************************************
RlePack.h - description
-------------------
begin : Mon Sep 24 2001
copyright : (C) 2001 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#ifndef __RLEPACK_H
#define __RLEPACK_H
+#include "FighterEnum.h"
+
struct RlePack_P;
+
+/**
+\class RlePack
+\brief RlePack is responsible for loading and drawing "sprites" from a .DAT file.
+
+RlePack loads the sprites from a .DAT file in its constructor. If there is
+an error (e.g. file doesn't exist), the number of sprites loaded will be 0.
+RlePack is usually used to store the many frames of a fighter in MSZ. It is
+also used for the 'cast' in the MainScreenDemo.
+
+The palette by default ranges from 1 to N (the number of colors). This,
+however, can be changed with OffsetSprites(). This is used to make sure that
+the two loaded fighters don't overwrite each others palettes or the background
+palette.
+
+The 'tint' can be set with the SetTint method. It will not immediately appear
+until ApplyPalette() is called. For an explanation about tints, please see the
+TintEnum documentation.
+
+\sa TintEnum
+*/
+
class RlePack
{
public:
- RlePack( const char* filename );
+ RlePack( const char* a_pcFilename, int a_iNumColors );
~RlePack();
+
+ void Clear();
+ int LoadFile( const char* a_pcFilename, int a_iNumColors );
+ int Count();
+ void OffsetSprites( int a_iOffset );
+ void SetTint( TintEnum a_enTint );
+ void ApplyPalette();
- void offsetSprites( int offset );
- SDL_Color* getPalette();
- void draw( int index, int x, int y, bool flipped=false );
+ void Draw( int a_iIndex, int a_iX, int a_iY, bool a_bFlipped=false );
private:
RlePack_P* p;
};
#endif
diff --git a/src/State.cpp b/src/State.cpp
index a86b926..0a802d0 100644
--- a/src/State.cpp
+++ b/src/State.cpp
@@ -1,137 +1,143 @@
/***************************************************************************
State.cpp - description
-------------------
begin : Mon Aug 12 2003
copyright : (C) 2003 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include "../config.h"
#include "SDL.h"
#include "common.h"
#include "State.h"
#include <string>
#include <fstream>
#include "Backend.h"
+
+#include <EXTERN.h>
+#include <perl.h>
+
+extern PerlInterpreter* my_perl;
+
SState g_oState;
std::string GetConfigHeader()
{
std::string sHeader( "Simple config file " );
sHeader += PACKAGE " " VERSION;
return sHeader;
}
std::string GetConfigFilename()
{
#ifdef _WINDOWS
if ( NULL != g_oState.m_pcArgv0 )
{
return std::string(g_oState.m_pcArgv0) + ".ini";
}
return "c:\\openmortal.ini";
#else
return std::string(getenv("HOME")) + "/.openmortalrc";
#endif
}
void SState::ToggleFullscreen()
{
m_bFullscreen = !m_bFullscreen;
bool bPaletted = ( gamescreen->format->BitsPerPixel <= 8 );
SDL_Color aoPalette[256];
int iNumColors = 0;
if ( bPaletted )
{
iNumColors = gamescreen->format->palette->ncolors;
if ( iNumColors > 256 ) iNumColors = 256;
for ( int i=0; i<iNumColors; ++i )
{
aoPalette[i].r = gamescreen->format->palette->colors[i].r;
aoPalette[i].g = gamescreen->format->palette->colors[i].g;
aoPalette[i].b = gamescreen->format->palette->colors[i].b;
aoPalette[i].unused = 0;
}
}
gamescreen = SDL_SetVideoMode( gamescreen->w, gamescreen->h,
gamescreen->format->BitsPerPixel,
m_bFullscreen ? SDL_FULLSCREEN : SDL_SWSURFACE );
if ( bPaletted )
{
SDL_SetPalette( gamescreen, SDL_LOGPAL | SDL_PHYSPAL, aoPalette, 0, iNumColors );
}
}
void SState::Load()
{
std::string sFilename = GetConfigFilename();
g_oBackend.PerlEvalF( "ParseConfig('%s');", sFilename.c_str() );
SV* poSv;
poSv = get_sv("GAMETIME", FALSE); if (poSv) m_iGameTime = SvIV( poSv );
poSv = get_sv("HITPOINTS", FALSE); if (poSv) m_iHitPoints = SvIV( poSv );
poSv = get_sv("FULLSCREEN", FALSE); if (poSv) m_bFullscreen = SvIV( poSv );
poSv = get_sv("CHANNELS", FALSE); if (poSv) m_iChannels = SvIV( poSv );
poSv = get_sv("MIXINGRATE", FALSE); if (poSv) m_iMixingRate = SvIV( poSv );
poSv = get_sv("MIXINGBITS", FALSE); if (poSv) m_iMixingBits = SvIV( poSv );
poSv = get_sv("MUSICVOLUME", FALSE); if (poSv) m_iMusicVolume = SvIV( poSv );
poSv = get_sv("SOUNDVOLUME", FALSE); if (poSv) m_iSoundVolume = SvIV( poSv );
char pcBuffer[1024];
for ( int i=0; i<2; ++i )
{
for ( int j=0; j<9; ++j )
{
sprintf( pcBuffer, "PLAYER%dKEY%d", i, j );
poSv = get_sv(pcBuffer, FALSE); if (poSv) m_aiPlayerKeys[i][j] = SvIV( poSv );
}
}
}
void SState::Save()
{
std::string sFilename = GetConfigFilename();
std::ofstream oStream( sFilename.c_str(), std::ios_base::out | std::ios_base::trunc );
if ( oStream.rdstate() & std::ios::failbit )
{
debug( "Unable to open config file: %s\n", sFilename.c_str() );
return;
}
oStream << GetConfigHeader() << '\n';
oStream << "GAMETIME=" << m_iGameTime << '\n';
oStream << "HITPOINTS=" << m_iHitPoints << '\n';
oStream << "FULLSCREEN=" << m_bFullscreen << '\n';
oStream << "CHANNELS=" << m_iChannels << '\n';
oStream << "MIXINGRATE=" << m_iMixingRate << '\n';
oStream << "MIXINGBITS=" << m_iMixingBits << '\n';
oStream << "MUSICVOLUME=" << m_iMusicVolume << '\n';
oStream << "SOUNDVOLUME=" << m_iSoundVolume << '\n';
for ( int i=0; i<2; ++i )
{
for ( int j=0; j<9; ++j )
{
oStream << "PLAYER" <<i<< "KEY" <<j<< '=' << m_aiPlayerKeys[i][j] << '\n';
}
}
oStream.flush();
oStream.close();
}
diff --git a/src/common.h b/src/common.h
index a02f4e3..9341380 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,58 +1,57 @@
/***************************************************************************
common.h - description
-------------------
begin : Fri Aug 24 2001
copyright : (C) 2001 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#ifndef __COMMON_H
#define __COMMON_H
struct SDL_Surface;
#define SCREENWIDTH 640
#define SCREENHEIGHT 480
#define GAMEBITS 3
#define GAMEBITS2 (1<<GAMEBITS)
void debug( const char* format, ... );
#define ABS(A) ( (A>=0) ? (A) : -(A) )
#ifdef _SDL_video_h
extern SDL_Surface* gamescreen;
void DoMenu( bool a_bDrawBackground );
void GameOver( int a_iPlayerWon );
void DoDemos();
-void PlayerSelect();
#define C_BLACK 240
#define C_BLUE 241
#define C_GREEN 242
#define C_CYAN 243
#define C_RED 244
#define C_MAGENTA 245
#define C_ORANGE 246
#define C_LIGHTGRAY 247
#define C_DARKGRAY 248
#define C_LIGHTBLUE 249
#define C_LIGHTGREEN 250
#define C_LIGHTCYAN 251
#define C_LIGHTRED 252
#define C_LIGHTMAGENTA 253
#define C_YELLOW 254
#define C_WHITE 255
#endif
#endif
diff --git a/src/main.cpp b/src/main.cpp
index ccd0365..4a0b2ec 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,376 +1,346 @@
/***************************************************************************
main.cpp - description
-------------------
begin : Wed Aug 22 10:18:47 CEST 2001
copyright : (C) 2001 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#include "FlyingChars.h"
+#include "PlayerSelect.h"
#include "SDL_video.h"
#include "sge_tt_text.h"
#include "sge_bm_text.h"
#include "sge_surface.h"
#include "SDL.h"
#include "SDL_image.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <string>
#include "common.h"
#include "gfx.h"
#include "Audio.h"
#include "RlePack.h"
#include "Backend.h"
#include "State.h"
_sge_TTFont* inkFont;
_sge_TTFont* impactFont;
_sge_TTFont* titleFont;
sge_bmpFont* fastFont;
sge_bmpFont* creditsFont;
sge_bmpFont* storyFont;
SDL_Color Colors[] =
{
{ 0, 0, 0, 0 }, { 0, 0, 42, 0 }, { 0, 42, 0, 0 }, { 0, 42, 42, 0 },
{ 42, 0, 0, 0 }, { 42, 0, 42, 0 }, { 63, 42, 0, 0 }, { 42, 42, 42, 0 },
{ 21, 21, 21, 0 }, { 21, 21, 63, 0 }, { 21, 63, 21, 0 }, { 21, 63, 63, 0 },
{ 63, 21, 21, 0 }, { 63, 21, 63, 0 }, { 63, 63, 21, 0 }, { 63, 63, 63, 0 }
};
void Complain( const char* a_pcError )
{
#ifdef _WINDOWS
::MessageBoxA( 0, a_pcError, "OpenMortal", MB_ICONEXCLAMATION );
#else
fprintf( stderr, "%s", a_pcError );
#endif
}
_sge_TTFont* LoadTTF( const char* a_pcFilename, int a_iSize )
{
std::string sPath = std::string(DATADIR) + "/fonts/" + a_pcFilename;
_sge_TTFont* poFont = sge_TTF_OpenFont( sPath.c_str(), a_iSize );
if ( NULL == poFont )
{
Complain( ("Couldn't load font: " + sPath).c_str() );
}
return poFont;
}
sge_bmpFont* LoadBMPFont( const char* a_pcFilename )
{
std::string sPath = std::string(DATADIR) + "/fonts/" + a_pcFilename;
sge_bmpFont* poFont = sge_BF_OpenFont( sPath.c_str(), SGE_BFSFONT | SGE_BFTRANSP );
if ( NULL == poFont )
{
Complain( ("Couldn't load font: " + sPath).c_str() );
}
return poFont;
}
int init( int iFlags )
{
if (SDL_Init(SDL_INIT_VIDEO /*| SDL_INIT_AUDIO*/) < 0)
{
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
return -1;
}
atexit(SDL_Quit);
int d = SDL_VideoModeOK(640, 480, 8, iFlags);
if (d == 0)
{
fprintf(stderr, "requested video mode not available\n");
// return -1;
}
gamescreen = SDL_SetVideoMode(640, 480, 8, iFlags);
if (gamescreen == NULL)
{
fprintf(stderr, "failed to set video mode: %s\n", SDL_GetError());
return -1;
}
SDL_WM_SetCaption( "OpenMortal", "OpenMortal" );
std::string sPath = std::string(DATADIR) + "/gfx/icon.png";
SDL_WM_SetIcon(IMG_Load(sPath.c_str()), NULL);
SDL_ShowCursor( SDL_DISABLE );
for ( int i=0; i<16; ++i ) { Colors[i].r *=4; Colors[i].g *=4; Colors[i].b *=4; }
SDL_SetColors( gamescreen, Colors, 256-16, 16 );
if ( sge_TTF_Init() )
{
fprintf(stderr, "couldn't start ttf engine: %s\n", SDL_GetError());
return -1;
}
sge_TTF_AAOff();
inkFont = LoadTTF( "aardvark.ttf", 24 );
if ( !inkFont ) return -1;
impactFont = LoadTTF( "gooddogc.ttf", 20 );
if ( !impactFont ) return -1;
titleFont = LoadTTF( "manslem.ttf", 40 );
if ( !titleFont ) return -1;
fastFont = LoadBMPFont( "impactfont2.png" );
if ( !fastFont ) return -1;
//SDL_SetColorKey( fastFont->FontSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
// sge_GetPixel(fastFont->FontSurface,0,fastFont->FontSurface->h-1) );
creditsFont = LoadBMPFont( "fangfont.png" );
storyFont = LoadBMPFont( "glossyfont.png" );
if ( !creditsFont ) return -1;
return 0;
}
int init2()
{
if ( !g_oBackend.Construct() )
{
fprintf(stderr, "couldn't start backend.\n" );
return -1;
}
return 0;
}
int DrawMainScreen()
{
SDL_Surface* background = LoadBackground( "Mortal.png", 240 );
SDL_Rect r;
r.x = r.y = 0;
std::string sStaffFilename = DATADIR;
sStaffFilename += "/characters/STAFF.DAT";
- RlePack pack( sStaffFilename.c_str() );
- SDL_SetColors( gamescreen, pack.getPalette(), 0, 240 );
+ RlePack pack( sStaffFilename.c_str(), 240 );
+ pack.ApplyPalette();
+ //SDL_SetColors( gamescreen, pack.getPalette(), 0, 240 );
SDL_BlitSurface( background, NULL, gamescreen, &r );
SDL_Flip( gamescreen );
FighterEnum f[14] = {
UPI, ZOLI, SURBA, ULMAR, MISI, BENCE,
DESCANT, KINGA, GRIZLI, SIRPI, MACI, DANI, CUMI,
AMBRUS };
- char* filename[14] = {
- "UPi.pl", "Zoli.pl", NULL, "Ulmar.pl", NULL, "Bence.pl",
- "Descant.pl", NULL, "Grizli.pl", "Sirpi.pl", "Maci.pl", NULL, "Cumi.pl",
- NULL };
- int x[14] = {
- 0, 26, 67, 125, 159, 209,
- 249, 289, 358, 397, 451, 489, 532, 161 };
- int y[14] = {
- 5, 4, 5, 5, 5, 7,
- 4, 0, 7, 5, 5, 6, 5, 243 };
-
- char s[100];
+ char* filename[14] = {
+ "UPi.pl", "Zoli.pl", NULL, "Ulmar.pl", NULL, "Bence.pl",
+ "Descant.pl", NULL, "Grizli.pl", "Sirpi.pl", "Maci.pl", NULL, "Cumi.pl",
+ NULL };
+ int x[14] = {
+ 0, 26, 67, 125, 159, 209,
+ 249, 289, 358, 397, 451, 489, 532, 161 };
+ int y[14] = {
+ 5, 4, 5, 5, 5, 7,
+ 4, 0, 7, 5, 5, 6, 5, 243 };
+
int i;
-
- for ( i=0; i<14; ++i )
- {
- pack.draw( i, x[i], y[i], false );
- SDL_Flip( gamescreen );
- if ( filename[i] != NULL )
- {
- debug( "Loading fighter %s", filename[i] );
- sprintf( s, "require '%s';", filename[i] );
- PERLEVAL(s);
- char *error = SvPV_nolen(get_sv("@", FALSE));
- if ( error )
- {
- fprintf( stderr, "%s", error );
- }
- }
- }
-
+
+ for ( i=0; i<14; ++i )
+ {
+ pack.Draw( i, x[i], y[i], false );
+ SDL_Flip( gamescreen );
+ if ( filename[i] != NULL )
+ {
+ debug( "Loading fighter %s", filename[i] );
+ g_oBackend.PerlEvalF( "require '%s';", filename[i] );
+ }
+ }
+
int retval = 0;
i = 0;
SDL_Event event;
-
- /*
- while (retval == 0)
- {
- while (SDL_PollEvent(&event))
- {
- switch (event.type)
- {
- case SDL_QUIT:
- SDL_FreeSurface( background );
- retval = -1;
- case SDL_KEYDOWN:
- SDL_FreeSurface( background );
- retval = -1;
-
- }
- }
- SDL_Delay( 100 );
- i ++;
- if ( i > 30 )
- break;
- }
- */
-
- SDL_FreeSurface( background );
- return retval;
-
-}
+
+ SDL_FreeSurface( background );
+ return retval;
+
+}
int main(int argc, char *argv[])
{
srand( (unsigned int)time(NULL) );
if ( 0 != init2() )
{
fprintf( stderr, "init2() failed." );
return -1;
}
g_oState.m_pcArgv0 = argv[0];
g_oState.Load();
bool bDebug = false;
int iFlags = SDL_SWSURFACE | SDL_HWPALETTE;
if ( g_oState.m_bFullscreen )
{
iFlags |= SDL_FULLSCREEN;
}
int i;
for ( i=1; i<argc; ++i )
{
if ( !strcmp(argv[i], "-debug") )
{
bDebug = true;
}
else if ( !strcmp(argv[i], "-fullscreen") )
{
iFlags |= SDL_FULLSCREEN;
}
else if ( !strcmp(argv[i], "-hwsurface") )
{
iFlags |= SDL_HWSURFACE;
}
else if ( !strcmp(argv[i], "-doublebuf") )
{
iFlags |= SDL_DOUBLEBUF;
}
else if ( !strcmp(argv[i], "-anyformat") )
{
iFlags |= SDL_ANYFORMAT;
}
else
{
printf( "Usage: %s [-debug] [-fullscreen] [-hwsurface] [-doublebuf] [-anyformat]\n", argv[0] );
return 0;
}
}
if (init( iFlags )<0)
{
return -1;
}
new MszAudio;
Audio->LoadMusic( "Last_Ninja_-_The_Wilderness.mid", "DemoMusic" );
Audio->PlayMusic( "DemoMusic" );
Audio->LoadMusic( "2nd_pm.s3m", "GameMusic" );
DrawMainScreen();
- //game.execute();
- SetPlayer( 0, ZOLI );
- SetPlayer( 1, SIRPI );
+ g_oPlayerSelect.SetPlayer( 0, ZOLI );
+ g_oPlayerSelect.SetPlayer( 1, SIRPI );
int nextFighter = 0;
int describeOrder[ (int)LASTFIGHTER ];
for ( i=0; i<(int)LASTFIGHTER; ++i ) describeOrder[i] = i;
for ( i=0; i<100; ++i )
{
int j = rand() % (int)LASTFIGHTER;
int k = rand() % (int)LASTFIGHTER;
int l;
l = describeOrder[j];
describeOrder[j] = describeOrder[k];
describeOrder[k] = l;
}
/*
{
int iGameNumber=0;
char acReplayFile[1024];
for ( i=0; i<15; ++i )
{
sprintf( acReplayFile, DATADIR "/msz%i.replay", i );
DrawTextMSZ( acReplayFile, impactFont, 10, 10, 0, C_WHITE, gamescreen );
SDL_Delay(5000 );
DoGame( acReplayFile, true, bDebug );
}
}
*/
while ( 1 )
{
if ( g_oState.m_bQuitFlag ) break;
DoDemos();
if ( g_oState.m_bQuitFlag ) break;
Audio->PlaySample( "car_start.voc" );
Audio->PlayMusic( "GameMusic" );
while ( g_oState.m_enGameMode != SState::IN_DEMO
&& !g_oState.m_bQuitFlag )
{
- PlayerSelect();
+ g_oPlayerSelect.DoPlayerSelect();
if ( g_oState.m_bQuitFlag || g_oState.m_enGameMode == SState::IN_DEMO ) break;
//sprintf( acReplayFile, "/tmp/msz%d.replay", ++iGameNumber );
int iGameResult = DoGame( NULL, false, bDebug );
//int iGameResult = DoGame( acReplayFile, false, bDebug );
//DoGame( acReplayFile, true, bDebug );
if ( g_oState.m_bQuitFlag || g_oState.m_enGameMode == SState::IN_DEMO ) break;
debug ( "iGameResult = %d\n", iGameResult );
if ( iGameResult >= 0 )
{
GameOver( iGameResult );
}
if ( g_oState.m_bQuitFlag || g_oState.m_enGameMode == SState::IN_DEMO ) break;
}
if ( g_oState.m_bQuitFlag ) break;
Audio->PlayMusic( "DemoMusic" );
}
g_oState.Save();
return EXIT_SUCCESS;
}
diff --git a/src/menu.cpp b/src/menu.cpp
index eb23e3d..73b1f01 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -1,751 +1,751 @@
/***************************************************************************
menu.cpp - description
-------------------
begin : Sun Aug 3 2003
copyright : (C) 2003 by upi
email : upi@apocalypse.rulez.org
***************************************************************************/
#include "SDL.h"
#include "SDL_video.h"
#include "menu.h"
#include "gfx.h"
#include "State.h"
#include "common.h"
#include "Audio.h"
#include "Backend.h"
enum
{
/* Master menu structure:
MAIN MENU
*/
MENU_UNKNOWN,
MENU_SURRENDER,
MENU_SINGLE_PLAYER,
MENU_EASY,
MENU_MEDIUM,
MENU_HARD,
MENU_MULTI_PLAYER,
MENU_OPTIONS,
MENU_GAME_TIME, // ( :30 - 5:00 )
MENU_TOTAL_HIT_POINTS, // ( 25 - 1000 )
MENU_SOUND,
MENU_CHANNELS, // MONO / STEREO
MENU_MIXING_RATE, // 11kHz / 22kHz / 44.1 kHz
MENU_BITS, // 8 bit / 16 bit
MENU_MUSIC_VOLUME, // (0% - 100%)
MENU_SOUND_VOLUME, // (0% - 100%)
MENU_SOUND_OK,
MENU_FULLSCREEN,
MENU_KEYS_RIGHT,
MENU_KEYS_LEFT,
MENU_OPTIONS_OK,
MENU_INFO,
MENU_QUIT, // (confirm)
};
const char* g_ppcGameTime[] = { "0:30", "0:45", "1:00", "1:15", "1:30", "1:45", "2:00", "3:00", "5:00", NULL };
const int g_piGameTime[] = { 30, 45, 60, 75, 90, 105, 120, 180, 300 };
const char* g_ppcHitPoints[] = { "BABY", "VERY LOW", "LOW", "NORMAL", "HIGH", "VERY HIGH", "NEAR IMMORTAL", NULL };
const int g_piHitPoints[] = { 1, 10, 50, 100, 150, 200, 500 };
const char* g_ppcChannels[] = { "MONO", "STEREO", NULL };
const int g_piChannels[] = { 1, 2 };
const char* g_ppcMixingRate[] = { "LOW", "MEDIUM", "HIGH", NULL };
const int g_piMixingRate[] = { 1, 2, 3 };
const char* g_ppcMixingBits[] = { "8 bit", "16 bit", NULL };
const int g_piMixingBits[] = { 1, 2 };
const char* g_ppcVolume[] = { "OFF", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%", NULL };
const int g_piVolume[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
SDL_Surface* poBackground = NULL;
void InputKeys( int a_iPlayerNumber )
{
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
DrawGradientText( "Input keys", titleFont, 20, gamescreen );
SDL_Flip( gamescreen );
static const char* apcKeyNames[9] = { "up", "down", "left", "right", "block",
"low punch", "high punch", "low kick", "high kick" };
char acBuffer[1024];
int iY = 70;
for ( int i=0; i<9; ++i )
{
sprintf( acBuffer, "%s player-'%s'?", a_iPlayerNumber ? "Left" : "Right", apcKeyNames[i] );
DrawTextMSZ( acBuffer, inkFont, 10, iY, UseShadow, C_WHITE, gamescreen );
SDLKey enKey = GetKey();
if ( SDLK_ESCAPE == enKey )
{
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
SDL_Flip( gamescreen );
return;
}
g_oBackend.PerlEvalF( "GetKeysym(%d);", enKey );
- DrawTextMSZ( SvPV_nolen(get_sv("keysym",TRUE)), inkFont, 530, iY, UseShadow, C_WHITE, gamescreen );
+ DrawTextMSZ( g_oBackend.GetPerlString("keysym"), inkFont, 530, iY, UseShadow, C_WHITE, gamescreen );
g_oState.m_aiPlayerKeys[a_iPlayerNumber][i] = enKey;
iY += 35;
}
DrawTextMSZ( "Thanks!", inkFont, 320, iY + 20, UseShadow | AlignCenter, C_WHITE, gamescreen );
GetKey();
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
SDL_Flip( gamescreen );
}
/***************************************************************************
MENUITEM DEFINITION
***************************************************************************/
MenuItem::MenuItem( Menu* a_poMenu, const char* a_pcUtf8Text, int a_iCode )
: m_sUtf8Text( a_pcUtf8Text )
{
m_poMenu = a_poMenu;
m_iCode = a_iCode;
m_oPosition.x = m_oPosition.y = 100;
m_oPosition.w = m_oPosition.h = 100;
m_bCenter = true;
m_iHighColor = C_WHITE;
m_iLowColor = C_LIGHTGRAY;
m_iInactiveColor = C_DARKGRAY;
m_iBackgroundColor = C_BLACK;
m_bActive = false;
m_bEnabled = true;
}
MenuItem::~MenuItem()
{
}
void MenuItem::Draw()
{
if ( NULL != poBackground )
{
SDL_BlitSurface( poBackground, &m_oPosition, gamescreen, &m_oPosition );
}
else
{
SDL_FillRect( gamescreen, &m_oPosition, 0 );
}
int iX = m_oPosition.x;
int iY = m_oPosition.y;
if ( m_bCenter )
{
iX += m_oPosition.w / 2;
}
DrawTextMSZ( m_sUtf8Text.c_str(), inkFont, iX, iY,
UseTilde | UseShadow | (m_bCenter ? AlignHCenter : 0),
m_bEnabled ? (m_bActive ? m_iHighColor : m_iLowColor) : m_iInactiveColor,
gamescreen );
SDL_UpdateRect( gamescreen, m_oPosition.x, m_oPosition.y, m_oPosition.w, m_oPosition.h );
}
void MenuItem::Clear()
{
// debug( "Clear: %d:%d %dx%d\n", m_oPosition.x, m_oPosition.y, m_oPosition.w, m_oPosition.h );
if (poBackground )
{
SDL_Rect oDest = m_oPosition;
SDL_BlitSurface( poBackground, &m_oPosition, gamescreen, &oDest );
}
else
{
SDL_FillRect( gamescreen, &m_oPosition, C_WHITE );
}
SDL_UpdateRect( gamescreen, m_oPosition.x, m_oPosition.y, m_oPosition.w, m_oPosition.h );
}
void MenuItem::Activate()
{
if ( m_poMenu )
{
m_poMenu->ItemActivated( m_iCode, this );
}
}
void MenuItem::SetText( const char* a_pcUtf8Text, bool a_bCenter )
{
m_sUtf8Text = a_pcUtf8Text;
m_bCenter = a_bCenter;
Draw();
}
void MenuItem::SetPosition( const SDL_Rect& a_roPosition )
{
m_oPosition = a_roPosition;
}
void MenuItem::SetActive( bool a_bActive )
{
if ( m_bActive == a_bActive )
{
return;
}
m_bActive = a_bActive;
Draw();
}
void MenuItem::SetEnabled( bool a_bEnabled )
{
if ( m_bEnabled == a_bEnabled )
{
return;
}
m_bEnabled = a_bEnabled;
Draw();
}
/***************************************************************************
ENUMMENUITEM DEFINITION
***************************************************************************/
EnumMenuItem::EnumMenuItem( Menu* a_poMenu, int a_iInitialValue, const char* a_pcUtf8Text, int a_iCode )
: MenuItem( a_poMenu, a_pcUtf8Text, a_iCode )
{
m_sUtf8Title = a_pcUtf8Text;
m_iMax = -1;
m_iValue = a_iInitialValue;
}
EnumMenuItem::~EnumMenuItem()
{
}
void EnumMenuItem::Draw()
{
m_sUtf8Text = m_sUtf8Title;
if ( m_iValue <= m_iMax )
{
m_sUtf8Text += m_ppcNames[m_iValue];
}
if ( m_iValue > 0 )
{
m_sUtf8Text = "< " + m_sUtf8Text;
}
if ( m_iValue < m_iMax )
{
m_sUtf8Text += " >";
}
MenuItem::Draw();
}
void EnumMenuItem::Increment()
{
if ( m_iValue < m_iMax )
{
++m_iValue;
Draw();
m_poMenu->ItemChanged( m_iCode, m_piValues[m_iValue], this );
Audio->PlaySample( "ding.voc" );
}
}
void EnumMenuItem::Decrement()
{
if ( m_iValue > 0 )
{
--m_iValue;
Draw();
m_poMenu->ItemChanged( m_iCode, m_piValues[m_iValue], this );
Audio->PlaySample( "ding.voc" );
}
}
void EnumMenuItem::SetEnumValues( const char ** a_ppcNames, const int * a_piValues )
{
m_ppcNames = a_ppcNames;
m_piValues = a_piValues;
int i;
bool bFoundValue = false;
for ( i=0; NULL != a_ppcNames[i]; ++i )
{
if ( !bFoundValue &&
m_iValue == a_piValues[i] )
{
bFoundValue = true;
m_iValue = i;
}
}
if ( !bFoundValue )
{
m_iValue = 0;
}
m_iMax = i-1;
}
/***************************************************************************
MENU DEFINITION
***************************************************************************/
Menu::Menu( const char* a_pcTitle )
: m_sTitle( a_pcTitle )
{
m_iCurrentItem = 0;
m_iReturnCode = -1;
m_bDone = false;
}
Menu::~Menu()
{
ItemIterator it;
for ( it = m_oItems.begin(); it != m_oItems.end(); ++it )
{
delete *it;
}
}
MenuItem* Menu::AddMenuItem( const char* a_pcUtf8Text, SDLKey a_tShortcut, int a_iCode )
{
MenuItem* poItem = new MenuItem( this, a_pcUtf8Text, a_iCode );
return AddMenuItem( poItem );
}
EnumMenuItem* Menu::AddEnumMenuItem( const char* a_pcUtf8Text, int a_iInitialValue,
const char** a_ppcNames, const int* a_piValues, int a_iCode )
{
EnumMenuItem* poItem = new EnumMenuItem( this, a_iInitialValue, a_pcUtf8Text, a_iCode );
poItem->SetEnumValues( a_ppcNames, a_piValues );
AddMenuItem( poItem );
return poItem;
}
MenuItem* Menu::AddMenuItem( MenuItem* a_poItem )
{
m_oItems.push_back( a_poItem );
SDL_Rect oRect;
oRect.x = 0; oRect.w = gamescreen->w;
oRect.y = m_oItems.size() * 45 + 100;
oRect.h = 45;
a_poItem->SetPosition( oRect );
return a_poItem;
}
void Menu::AddOkCancel( int a_iOkCode )
{
SDL_Rect oRect;
oRect.x = 0; oRect.w = 150;
oRect.y = gamescreen->h - 50; oRect.h = 30;
MenuItem* poItem = AddMenuItem( "~OK", SDLK_o, a_iOkCode );
poItem->SetPosition( oRect );
// poItem = AddMenuItem( "Cancel", SDLK_UNKNOWN, 0 );
oRect.x = gamescreen->w - 150;
poItem->SetPosition( oRect );
}
void Menu::InvokeSubmenu( Menu* a_poMenu )
{
Audio->PlaySample( "strange_button.voc" );
Clear();
m_iReturnCode = a_poMenu->Run();
if ( m_iReturnCode < 0 )
{
Audio->PlaySample( "pop.voc" );
Draw();
}
else
{
m_iReturnCode --;
m_bDone = true;
}
}
void Menu::ItemActivated( int a_iItemCode, MenuItem* a_poMenuItem )
{
debug( "Menu::ItemActivated( %d )\n", a_iItemCode );
switch ( a_iItemCode )
{
case MENU_QUIT:
m_bDone = true;
m_iReturnCode = 100;
g_oState.m_bQuitFlag = true;
break;
case MENU_SURRENDER:
m_bDone = true;
m_iReturnCode = 100;
g_oState.m_enGameMode = SState::IN_DEMO;
break;
case MENU_MULTI_PLAYER:
m_bDone = true;
m_iReturnCode = 100;
g_oState.m_enGameMode = SState::IN_MULTI;
break;
case MENU_FULLSCREEN:
Audio->PlaySample( "strange_button.voc" );
g_oState.ToggleFullscreen();
if ( NULL != poBackground )
{
SDL_BlitSurface( poBackground, NULL, gamescreen, NULL );
}
else
{
SDL_FillRect( gamescreen, NULL, 0 );
}
a_poMenuItem->SetText( g_oState.m_bFullscreen ? "~FULLSCREEN ON" : "~FULLSCREEN OFF", true );
Draw();
break;
case MENU_OPTIONS_OK:
m_bDone = true;
m_iReturnCode = -1;
break;
case MENU_OPTIONS:
{
Menu* poMenu = new Menu( "Options" );
poMenu->AddEnumMenuItem( "GAME TIME: ", g_oState.m_iGameTime, g_ppcGameTime, g_piGameTime, MENU_GAME_TIME );
poMenu->AddEnumMenuItem( "HIT POINTS: ", g_oState.m_iHitPoints, g_ppcHitPoints, g_piHitPoints, MENU_TOTAL_HIT_POINTS );
poMenu->AddMenuItem( "~SOUND", SDLK_s, MENU_SOUND );
poMenu->AddMenuItem( g_oState.m_bFullscreen ? "~FULLSCREEN ON" : "~FULLSCREEN OFF", SDLK_f, MENU_FULLSCREEN );
poMenu->AddMenuItem( "~RIGHT PLAYER KEYS", SDLK_r, MENU_KEYS_RIGHT );
poMenu->AddMenuItem( "~LEFT PLAYER KEYS", SDLK_l, MENU_KEYS_LEFT );
poMenu->AddOkCancel( MENU_OPTIONS_OK );
InvokeSubmenu( poMenu );
delete poMenu;
break;
}
case MENU_SOUND:
{
Menu* poMenu = new Menu( "Sound" );
poMenu->AddEnumMenuItem( "CHANNELS: ", 1, g_ppcChannels, g_piChannels, MENU_CHANNELS )->SetEnabled(false);
poMenu->AddEnumMenuItem( "SOUND QUALITY: ", 2, g_ppcMixingRate, g_piMixingRate, MENU_MIXING_RATE )->SetEnabled(false);
poMenu->AddEnumMenuItem( "SOUND FIDELITY: ", 2, g_ppcMixingBits, g_piMixingBits, MENU_BITS )->SetEnabled(false);
poMenu->AddEnumMenuItem( "MUSIC VOLUME: ", g_oState.m_iMusicVolume, g_ppcVolume, g_piVolume, MENU_MUSIC_VOLUME );
poMenu->AddEnumMenuItem( "EFFECTS VOLUME: ", g_oState.m_iSoundVolume, g_ppcVolume, g_piVolume, MENU_SOUND_VOLUME );
poMenu->AddOkCancel( MENU_SOUND_OK );
InvokeSubmenu( poMenu );
delete poMenu;
break;
}
case MENU_SOUND_OK:
m_bDone = true;
m_iReturnCode = -1;
break;
case MENU_KEYS_LEFT:
InputKeys(1);
Draw();
break;
case MENU_KEYS_RIGHT:
InputKeys(0);
Draw();
break;
default:
break;
}
}
void Menu::ItemChanged( int a_iItemCode, int a_iValue, MenuItem* a_poMenuItem )
{
debug( "Menu::ItemActivated( %d )\n", a_iItemCode );
switch ( a_iItemCode )
{
case MENU_MUSIC_VOLUME:
g_oState.m_iMusicVolume = a_iValue;
Audio->SetMusicVolume( a_iValue );
break;
case MENU_SOUND_VOLUME:
g_oState.m_iSoundVolume = a_iValue;
break;
case MENU_GAME_TIME:
g_oState.m_iGameTime = a_iValue;
break;
case MENU_TOTAL_HIT_POINTS:
g_oState.m_iHitPoints = a_iValue;
break;
} // end of switch a_iItemCode
}
/** Run executes the menus, maybe invoking submenus as well. The
menus modify the global game state.
Returns 0, or the number of parent menus that should be cleared. */
int Menu::Run()
{
if ( m_oItems[m_iCurrentItem]->GetEnabled() )
{
m_oItems[m_iCurrentItem]->SetActive(true);
}
else
{
FocusNext();
}
Draw();
while ( !m_bDone )
{
SDLKey enKey = GetKey();
if ( g_oState.m_bQuitFlag ||
SDLK_ESCAPE == enKey )
{
m_bDone = true;
m_iReturnCode = -1;
break;
}
switch ( enKey )
{
case SDLK_UP:
{
FocusPrev();
break;
} // end of SDLK_UP
case SDLK_DOWN:
{
FocusNext();
break;
} // end of SDLK_DOWN
case SDLK_LEFT:
{
MenuItem* poItem = m_oItems[m_iCurrentItem];
poItem->Decrement();
break;
}
case SDLK_RIGHT:
{
MenuItem* poItem = m_oItems[m_iCurrentItem];
poItem->Increment();
break;
}
case SDLK_RETURN:
{
MenuItem* poItem = m_oItems[m_iCurrentItem];
if ( poItem->GetEnabled() )
{
poItem->Activate();
}
}
default:
break;
} // end of switch
}
Clear();
return m_iReturnCode;
}
void Menu::Draw()
{
DrawGradientText( m_sTitle.c_str(), titleFont, 20, gamescreen );
for ( ItemIterator it=m_oItems.begin(); it!=m_oItems.end(); ++it )
{
(*it)->Draw();
}
SDL_Flip( gamescreen );
}
void Menu::FocusNext()
{
MenuItem* poItem = NULL;
int iNextItem;
for ( iNextItem = m_iCurrentItem+1; iNextItem < (int) m_oItems.size(); ++iNextItem )
{
poItem = m_oItems[iNextItem];
if ( poItem->GetEnabled() )
{
break;
}
poItem = NULL;
}
if ( NULL != poItem )
{
Audio->PlaySample("strange_quack.voc");
m_oItems[m_iCurrentItem]->SetActive(false);
m_oItems[iNextItem]->SetActive(true);
m_iCurrentItem = iNextItem;
}
}
void Menu::FocusPrev()
{
MenuItem* poItem = NULL;
int iPrevItem;
for ( iPrevItem = m_iCurrentItem-1; iPrevItem >= 0; --iPrevItem )
{
poItem = m_oItems[iPrevItem];
if ( poItem->GetEnabled() )
{
break;
}
poItem = NULL;
}
if ( NULL != poItem )
{
Audio->PlaySample("strange_quack.voc");
m_oItems[m_iCurrentItem]->SetActive(false);
m_oItems[iPrevItem]->SetActive(true);
m_iCurrentItem = iPrevItem;
}
}
void Menu::Clear()
{
if (poBackground)
{
SDL_BlitSurface( poBackground, 0, gamescreen, 0 );
}
else
{
SDL_FillRect( gamescreen, NULL, 0 );
}
}
void DoMenu( bool a_bDrawBackground )
{
Audio->PlaySample( "crashhh.voc" );
poBackground = SDL_ConvertSurface( gamescreen, gamescreen->format, SDL_SWSURFACE );
if ( NULL == poBackground )
{
debug( "DoMenu: Couldn't allocate background.\n" );
}
else
{
int i;
SDL_Rect oRect;
oRect.x = 0; oRect.w = poBackground->w; oRect.h = 1;
for ( i=0; i<poBackground->h; i += 2 )
{
oRect.y = i;
SDL_FillRect( poBackground, &oRect, C_BLACK );
}
oRect.w = 1; oRect.y = 0; oRect.h = poBackground->h;
for ( i=0; i<poBackground->w; i+=2 )
{
oRect.x = i;
SDL_FillRect(poBackground, &oRect, C_BLACK );
}
SDL_BlitSurface( poBackground, 0, gamescreen, 0 );
SDL_Flip( gamescreen );
}
Menu oMenu( "Main Menu" );
if ( SState::IN_DEMO == g_oState.m_enGameMode )
{
oMenu.AddMenuItem( "~SINGLE PLAYER GAME", SDLK_s, MENU_SINGLE_PLAYER )->SetEnabled(false);
oMenu.AddMenuItem( "~MULTI PLAYER GAME", SDLK_m, MENU_MULTI_PLAYER );
}
else
{
oMenu.AddMenuItem( "~SURRENDER GAME", SDLK_s, MENU_SURRENDER );
}
oMenu.AddMenuItem( "~OPTIONS", SDLK_o, MENU_OPTIONS );
oMenu.AddMenuItem( "~INFO", SDLK_i, MENU_INFO )->SetEnabled(false);
oMenu.AddMenuItem( "QUIT", SDLK_UNKNOWN, MENU_QUIT );
oMenu.Run();
Audio->PlaySample("shades_rollup.voc");
//SDL_BlitSurface( poBackground, 0, gamescreen, 0 );
//SDL_Flip( gamescreen );
SDL_FreeSurface( poBackground );
poBackground = NULL;
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Feb 4, 2:16 PM (6 h, 47 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55656
Default Alt Text
(114 KB)

Event Timeline