Page MenuHomePhabricator (Chris)

No OneTemporary

Size
94 KB
Referenced Files
None
Subscribers
None
This document is not UTF8. It was detected as JIS and converted to UTF8 for display.
diff --git a/src/Game.cpp b/src/Game.cpp
index 641cec1..49b720c 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,1008 +1,1035 @@
/***************************************************************************
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 "Background.h"
#include "common.h"
#include "gfx.h"
#include "Backend.h"
#include "RlePack.h"
#include "State.h"
#include "Game.h"
#include "Audio.h"
#include "MortalNetwork.h"
#include "MszPerl.h"
extern PerlInterpreter* my_perl;
int Game::mg_iBackgroundNumber = 1;
/*
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_enInitialGameMode = g_oState.m_enGameMode;
m_poBackground = new Background();
m_poBackground->Load(mg_iBackgroundNumber++);
if ( !m_poBackground->IsOK() )
{
m_poBackground->Load(1);
mg_iBackgroundNumber = 1;
}
m_poDoodads = LoadBackground( "Doodads.png", 48, 64 );
m_aiRoundsWonByPlayer[0] = m_aiRoundsWonByPlayer[1] = 0;
m_iNumberOfRounds = 0;
}
Game::~Game()
{
delete m_poBackground;
m_poBackground = NULL;
SDL_FreeSurface( m_poDoodads );
m_poDoodads = NULL;
}
/** Runs a whole game, with two or three rounds.
\retval 0 if player 1 has won.
\retval 1 if player 2 has won.
\retval -1 if the game was a draw.
*/
int Game::Run()
{
do
{
m_sReplayString = "";
m_aReplayOffsets.clear();
DoOneRound();
if ( g_oState.m_bQuitFlag
|| m_enInitialGameMode != 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;
}
/** Returns the replay string of the last round.
*/
std::string& Game::GetReplay()
{
return m_sReplayString;
}
/***************************************************************************
GAME DRAWING METHODS
***************************************************************************/
/** Draws the hitpoint bars that are displayed on the top of the screen.
Also draws the fighter names below the bars.
Input variables:
\li g_oBackend.m_aoPlayers[x].m_iHitPoints
\li g_oPlayerSelect.GetFighterName
*/
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 );
}
int iTextX = 230 - g_oPlayerSelect.GetFighterNameWidth(0);
if ( iTextX < 5 ) iTextX = 5;
sge_BF_textout( gamescreen, fastFont, g_oPlayerSelect.GetFighterName(0),
iTextX, 38 );
iTextX = g_oPlayerSelect.GetFighterNameWidth(1);
iTextX = iTextX < (635-410) ? 410 : 635-iTextX;
sge_BF_textout( gamescreen, fastFont, g_oPlayerSelect.GetFighterName(1),
iTextX, 38 );
}
/** Draws the background, using the m_poBackground object.
*/
void Game::DrawBackground()
{
m_poBackground->Draw( g_oBackend.m_iBgX, g_oBackend.m_iBgY );
}
/** In debug mode, this method is used to draw the frame of the fighters.
\param a_sName The name of the polygon (in the perl namespace)
\param a_iColor The game color to draw the polygon with.
*/
void Game::DrawPoly( const char* a_pcName, int a_iColor )
{
AV *poList;
int n;
poList = get_av( a_pcName, FALSE );
if ( poList == NULL )
{
return;
}
n = av_len( poList ) + 1;
if ( n< 2 )
{
return;
}
for ( int i=0; i<n; i += 2 )
{
int j = (i+2) % n;
int x1 = SvIV( *av_fetch( poList, i, false) );
int y1 = SvIV( *av_fetch( poList, i+1, false) );
int x2 = SvIV( *av_fetch( poList, j, false) );
int y2 = SvIV( *av_fetch( poList, j+1, false) );
sge_Line( gamescreen, x1, y1, x2, y2, a_iColor ) ;
}
}
/** Draws every doodad that is currently defined in the backend.
*/
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;
}
if ( roDoodad.m_iGfxOwner < 2 )
{
g_oPlayerSelect.GetPlayerInfo(roDoodad.m_iGfxOwner).m_poPack->Draw(
roDoodad.m_iFrame, roDoodad.m_iX, roDoodad.m_iY, roDoodad.m_iDir < 1 );
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 );
}
}
/** Draws the entire game screen:
\li First, the background.
\li The players.
\li The debug wireframes (if debugging is turned on)
\li The doodads.
\li The hitpoint display.
\li The gametime display.
\li The FPS display.
\li The "Round x" text during Ph_Start
Input:
\li m_enGamePhase
\li g_oBackend.m_iGameTime
\li m_iNumberOfRounds
\li oFpsCounter
*/
void Game::Draw()
{
+ #define GROUNDZERO 440
+
DrawBackground();
+ // DRAW THE SHADOWS
+
+ int i;
+
+ for ( i=0; i<2; ++i )
+ {
+ Backend::SPlayer& roPlayer = g_oBackend.m_aoPlayers[i];
+ int iFrame = roPlayer.m_iFrame;
+ if ( iFrame == 0 )
+ continue;
+
+ RlePack* poPack = g_oPlayerSelect.GetPlayerInfo(i).m_poPack;
+ int w = poPack->GetWidth( ABS(iFrame)-1 );
+ int h = poPack->GetHeight( ABS(iFrame)-1 );
+
+ h = GROUNDZERO - ( h + roPlayer.m_iY ); // Distance of feet from ground
+ if ( h < 0 ) h = 0;
+ if ( h > 500 ) h = 500;
+ h = 500 - h;
+ int h2 = 15 * h / 500;
+ h = ( w / 2 ) * h / 500;
+
+ sge_FilledEllipse( gamescreen,
+ g_oBackend.m_aoPlayers[i].m_iX + w/2, GROUNDZERO,
+ h, h2, C_BLACK );
+ }
+
for ( int i=0; i<2; ++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,
- iFrame<0 );
- }
+ Backend::SPlayer& roPlayer = g_oBackend.m_aoPlayers[i];
+ int iFrame = roPlayer.m_iFrame;
+ if ( iFrame == 0 )
+ continue;
+
+ RlePack* poPack = g_oPlayerSelect.GetPlayerInfo(i).m_poPack;
+ poPack->Draw( ABS(iFrame)-1, roPlayer.m_iX, roPlayer.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", m_iGameTime ); // m_iGameTime is maintained by DoGame
DrawTextMSZ( s, inkFont, 320, 10, AlignHCenter, C_LIGHTCYAN, gamescreen, false );
}
else if ( Ph_START == m_enGamePhase )
{
char s[100];
const char* format = Translate( "Round %d" );
sprintf( s, format, m_iNumberOfRounds+1 );
DrawTextMSZ( s, inkFont, 320, 200, AlignHCenter, C_WHITE, gamescreen, false );
}
else if ( Ph_REWIND == m_enGamePhase )
{
DrawTextMSZ( "REW", inkFont, 320, 10, AlignHCenter, C_WHITE, gamescreen );
sge_BF_textout( gamescreen, fastFont, Translate("Press F1 to skip..."), 230, 450 );
}
else if ( Ph_SLOWFORWARD == m_enGamePhase )
{
DrawTextMSZ( "REPLAY", inkFont, 320, 10, AlignHCenter, C_WHITE, gamescreen );
sge_BF_textout( gamescreen, fastFont, Translate("Press F1 to skip..."), 230, 450 );
}
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
***************************************************************************/
bool Game::IsNetworkGame()
{
return SState::IN_NETWORK == g_oState.m_enGameMode;
}
/** Returns true if we control our own data, or false if the network supplies
us with game data. */
bool Game::IsMaster()
{
return !IsNetworkGame() || g_poNetwork->IsMaster();
}
/**
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.
Only the backend-driven variables are modified, the GamePhase and
GameTime remain unchanged; these are up for DoOneRound and friends
to modify.
*/
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;
}
if ( IsNetworkGame() )
{
bool bMaster = g_poNetwork->IsMaster();
g_poNetwork->Update();
if (!bMaster)
{
// We don't run our own backend, just pull the data from the network.
const char* pcRemoteBackend = g_poNetwork->GetLatestGameData();
g_oBackend.ReadFromString( pcRemoteBackend );
g_oBackend.PlaySounds();
return;
}
}
// OK. The trick here is to collect the sound information, and then
// inject it into the last frame to send it to the remote side.
static std::string sFrameDesc;
int iSounds = 0;
std::string asSounds[ MAXSOUNDS ];
int i;
while ( a_iNumFrames > 0 )
{
-- a_iNumFrames;
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() );
for ( i=0;
IsNetworkGame() && i<g_oBackend.m_iNumSounds && iSounds<MAXSOUNDS;
++i, ++iSounds )
{
asSounds[iSounds] = g_oBackend.m_asSounds[i];
}
}
if ( IsNetworkGame() && sFrameDesc.size() )
{
g_oBackend.m_iNumSounds = iSounds;
for ( i=0; i<iSounds; ++i )
{
g_oBackend.m_asSounds[i] = asSounds[i];
}
g_oBackend.WriteToString( sFrameDesc );
g_poNetwork->SendGameData( sFrameDesc.c_str() );
}
}
/** A helper method of ProcessEvents; it manages keypresses and releases of
players.
*/
void Game::HandleKey( int a_iPlayer, int a_iKey, bool a_bDown )
{
if ( IsMaster() )
{
if ( IsNetworkGame() )
{
a_iPlayer = 0;
}
g_oBackend.PerlEvalF( a_bDown ? "KeyDown(%d,%d);" : "KeyUp(%d,%d);", a_iPlayer, a_iKey );
}
else
{
g_poNetwork->SendKeystroke( a_iKey, a_bDown );
}
}
/** 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 (e.g. if the current game or replay should be aborted), 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 && !IsNetworkGame() )
{
SState::TGameMode enMode = g_oState.m_enGameMode;
::DoMenu( true );
return g_oState.m_enGameMode == enMode ? 0 : 1;
}
if ( event.key.keysym.sym == SDLK_F1 /*&& !IsNetworkGame()*/ )
{
// shortcut: abort the current round. This shall is here
// to ease testing, and will be removed from the final
// version.
return 1;
}
if ( Ph_NORMAL != m_enGamePhase &&
Ph_REPLAY != 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)
{
if (g_oState.m_enGameMode == SState::IN_DEMO)
{
g_oState.m_enGameMode = SState::IN_MULTI;
return 1;
}
HandleKey( i, j, true );
//g_oBackend.PerlEvalF( "KeyDown(%d,%d);", i, j );
return 0;
}
}
}
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)
{
HandleKey( i, j, false );
g_oBackend.PerlEvalF( "KeyUp(%d,%d);", i, j );
return 0;
}
}
}
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 );
}
/** This methods starts and runs the "instant replay" mode that is done
at the end of a game round. This means doing phases Ph_REWIND and Ph_SLOWFORWARD.
Rewind will go back in time 200 ticks before the parameter a_iKoAt.
*/
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
|| SState::IN_DEMO == g_oState.m_enGameMode )
{
break;
}
}
}
/** This methods executes one round of gameplay.
The game progresses through phases Ph_START, Ph_NORMAL, and
Ph_KO. If a KO happened, it will invoke InstantReplay. At the end of
the round m_aiRoundsWonByPlayer[x] will be incremented depending on the
outcome. m_iNumberOfRounds will also increase by 1.
*/
void Game::DoOneRound()
{
m_enGamePhase = Ph_START;
g_oBackend.PerlEvalF( "GameStart(%d,%d);", g_oState.m_iHitPoints, m_bDebug );
if ( IsNetworkGame() )
{
g_poNetwork->SynchStartRound();
}
int iKoFrame = -1;
double dGameTime = 2 * 1000; // Only for the "greeting phase", the real gametime will be set after.
int iThisTick, iLastTick, iGameSpeed;
bool bHurryUp = false;
bool bReplayAfter = true;
iGameSpeed = g_oState.m_iGameSpeed;
iThisTick = SDL_GetTicks() / iGameSpeed;
iLastTick = iThisTick - 1;
oFpsCounter.Reset();
// 1. DO THE NORMAL GAME ROUND (START, NORMAL, KO, TIMEUP)
while ( dGameTime >= 0 )
{
if ( m_enInitialGameMode != g_oState.m_enGameMode )
{
return;
}
// 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;
// 3. Check for state transitions and game time.
// START -> NORMAL
// NORMAL -> KO
// NORMAL -> TIMEUP
// bHurryUp flag can be set during NORMAL phase
if ( IsMaster() )
{
if ( Ph_START == m_enGamePhase ) // Check for the end of the START phase
{
if ( dGameTime <= 0 )
{
m_enGamePhase = Ph_NORMAL;
dGameTime = g_oState.m_iGameTime * 1000;
}
}
else if ( Ph_NORMAL == m_enGamePhase ) // Check for the end of the NORMAL phase
{
if ( dGameTime < 10 * 1000
&& !bHurryUp )
{
bHurryUp = true;
g_poNetwork->SendHurryup( 1 );
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;
g_poNetwork->SendHurryup( 2 );
TimeUp();
break;
}
}
m_iGameTime = (int) ((dGameTime + 500.0) / 1000.0);
if ( IsNetworkGame() )
{
g_poNetwork->SendGameTime( m_iGameTime, m_enGamePhase );
}
}
else
{
m_iGameTime = g_poNetwork->GetGameTime();
m_enGamePhase = (TGamePhaseEnum) g_poNetwork->GetGamePhase();
dGameTime = 1000.0; // ignored.
switch (g_poNetwork->GetHurryup() )
{
case 1: HurryUp(); break;
case 2: TimeUp(); break;
}
}
iLastTick = iThisTick;
if ( ProcessEvents() || g_oState.m_bQuitFlag )
{
bReplayAfter = false;
break;
}
if ( IsNetworkGame() && IsMaster() )
{
int iKey;
bool bPressed;
while ( g_poNetwork->GetKeystroke( iKey, bPressed ) )
{
debug( "Got GetKeystroke: %d, %d\n", iKey, bPressed );
g_oBackend.PerlEvalF( bPressed ? "KeyDown(%d,%d);" : "KeyUp(%d,%d);", 1, iKey );
}
}
oFpsCounter.Tick();
// 3. Draw the next game screen..
Draw();
// 4. Check 'end of round' condition.
if ( !IsMaster() )
{
if ( g_poNetwork->IsRoundOver() )
{
break;
}
}
else if ( g_oBackend.m_iGameOver )
{
break;
}
}
int p1h = g_oBackend.m_aoPlayers[0].m_iHitPoints;
int p2h = g_oBackend.m_aoPlayers[1].m_iHitPoints;
// 3. DO THE REPLAY (IF THERE WAS A KO)
if ( iKoFrame>0 && bReplayAfter && !IsNetworkGame() )
{
InstantReplay( iKoFrame );
}
// 4. END OF ROUND
debug( "Game over; p1h = %d; p2h = %d\n", p1h, p2h );
if ( IsMaster() )
{
int iWhoWon = -1;
if ( p1h > p2h ) { ++m_aiRoundsWonByPlayer[0]; iWhoWon = 0; }
if ( p2h > p1h ) { ++m_aiRoundsWonByPlayer[1]; iWhoWon = 1; }
if ( IsNetworkGame() )
{
g_poNetwork->SendRoundOver( iWhoWon, m_iNumberOfRounds > 0 );
}
}
else
{
int iWhoWon = g_poNetwork->GetWhoWon();
if ( iWhoWon>=0 )
{
++m_aiRoundsWonByPlayer[iWhoWon];
}
}
++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 );
g_oPlayerSelect.SetPlayer( 0, (FighterEnum) iPlayer1 );
g_oPlayerSelect.SetPlayer( 1, (FighterEnum) iPlayer2 );
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;
}
}
}
/** Public static function.
Other parts of OpenMortal need not include "Game.h" so long as they have
the definition of this method (defined in "common.h"). The method runs
a cycle of the game (either a normal game, or replay).
In replay mode, DoReplay() is called, and the replay file is required.
In normal mode, Run() is called. The replay file is recorded, if it is not NULL.
*/
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 <<
g_oPlayerSelect.GetPlayerInfo(0).m_enFighter << ' ' <<
g_oPlayerSelect.GetPlayerInfo(1).m_enFighter << '\n' << oGame.GetReplay();
}
return iRetval;
}
}
diff --git a/src/RlePack.cpp b/src/RlePack.cpp
index 5fd6cc6..d00bebd 100644
--- a/src/RlePack.cpp
+++ b/src/RlePack.cpp
@@ -1,817 +1,837 @@
/***************************************************************************
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 "common.h"
/// Sanity: This is the maximal number of entries in a .DAT file.
#define MAXDATACOUNT 65530
inline void ChangeEndian32( Uint32& a_riArg )
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
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;
#endif
}
inline void ChangeEndian16( Uint16& a_riArg )
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
char* pcArg = (char*)&a_riArg;
char cTemp;
cTemp = pcArg[0]; pcArg[0] = pcArg[1]; pcArg[1] = cTemp;
#endif
}
inline Uint32 ConvertEndian32( Uint32 a_iArg )
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
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;
#endif
return a_iArg;
}
inline Uint16 ConvertEndian16( Uint16 a_iArg )
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
char* pcArg = (char*)&a_iArg;
char cTemp;
cTemp = pcArg[0]; pcArg[0] = pcArg[1]; pcArg[1] = cTemp;
#endif
return a_iArg;
}
typedef struct RLE_SPRITE /* a RLE compressed sprite */
{
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 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* a_pcFilename, int a_iNumColors )
{
p = new RlePack_P;
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;
}
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( a_pcFilename, "rb" );
if (f==NULL)
{
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 - 4 )
{
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
}
int RlePack::Count()
{
return p->m_iCount;
}
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 a_iOffset )
{
if ( (a_iOffset<=0) || (a_iOffset>255) )
return;
p->m_iColorOffset = a_iOffset;
int i;
// Offset every RLE_SPRITE
for ( i=0; i<p->m_iCount; ++i )
{
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()
+
+int RlePack::GetWidth( int a_iIndex )
+{
+ if ( (a_iIndex<0) || (a_iIndex>=p->m_iCount) )
+ return -1;
+
+ RLE_SPRITE* poSprite = p->m_pSprites[a_iIndex];
+ if (!poSprite)
+ return -1;
+
+ return poSprite->w;
+}
+
+
+int RlePack::GetHeight( int a_iIndex )
{
- return p->palette;
+ if ( (a_iIndex<0) || (a_iIndex>=p->m_iCount) )
+ return -1;
+
+ RLE_SPRITE* poSprite = p->m_pSprites[a_iIndex];
+ if (!poSprite)
+ return -1;
+
+ return poSprite->h;
}
-*/
+
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 - 1;
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 ) // 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 a_iIndex, int a_iX, int a_iY, bool a_bFlipped )
{
if ( (a_iIndex<0) || (a_iIndex>=p->m_iCount) )
return;
RLE_SPRITE* poSprite = p->m_pSprites[a_iIndex];
if (!poSprite)
return;
if ( a_bFlipped )
draw_rle_sprite_v_flip( poSprite, a_iX, a_iY );
else
draw_rle_sprite( poSprite, a_iX, a_iY );
}
diff --git a/src/RlePack.h b/src/RlePack.h
index 198f470..13a95cf 100644
--- a/src/RlePack.h
+++ b/src/RlePack.h
@@ -1,57 +1,59 @@
/***************************************************************************
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* 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();
+ int GetWidth( int a_iIndex );
+ int GetHeight( int a_iIndex );
void Draw( int a_iIndex, int a_iX, int a_iY, bool a_bFlipped=false );
private:
RlePack_P* p;
};
#endif
diff --git a/src/sge_primitives.cpp b/src/sge_primitives.cpp
index 5278ca4..8e802f9 100644
--- a/src/sge_primitives.cpp
+++ b/src/sge_primitives.cpp
@@ -1,1660 +1,1657 @@
/*
* SDL Graphics Extension
* Drawing primitives
*
* Started 990815 (split from sge_draw 010611)
*
* License: LGPL v2+ (see the file LICENSE)
* (c)1999-2001 Anders Lindstr?m
*/
/*********************************************************************
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
*********************************************************************/
/*
* Some of this code is taken from the "Introduction to SDL" and
* John Garrison's PowerPak
*/
#include "SDL.h"
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include "sge_primitives.h"
#include "sge_surface.h"
/* Globals used for sge_Update/sge_Lock (defined in sge_surface) */
extern Uint8 _sge_update;
extern Uint8 _sge_lock;
/**********************************************************************************/
/** Line functions **/
/**********************************************************************************/
//==================================================================================
// Internal draw horizontal line
//==================================================================================
void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
{
if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
return;
if(x1<Surface->clip_minx)
x1=Surface->clip_minx;
if(x2>Surface->clip_maxx)
x2=Surface->clip_maxx;
#endif
SDL_Rect l;
l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
SDL_FillRect(Surface, &l, Color);
}
//==================================================================================
// Draw horizontal line
//==================================================================================
void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
{
if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
return;
if(x1<Surface->clip_minx)
x1=Surface->clip_minx;
if(x2>Surface->clip_maxx)
x2=Surface->clip_maxx;
#endif
SDL_Rect l;
l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
SDL_FillRect(Surface, &l, Color);
sge_UpdateRect(Surface, x1, y, x2-x1+1, 1);
}
//==================================================================================
// Draw horizontal line (RGB)
//==================================================================================
void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B)
{
sge_HLine(Surface,x1,x2,y, SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Internal draw horizontal line (alpha)
//==================================================================================
void _HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
{
Uint8 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_sge_lock = 0;
sge_FilledRectAlpha(Surface, x1,y,x2,y, Color, alpha);
_sge_update = update;
_sge_lock = lock;
}
//==================================================================================
// Draw horizontal line (alpha)
//==================================================================================
void sge_HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
{
sge_FilledRectAlpha(Surface, x1,y,x2,y, Color, alpha);
}
//==================================================================================
// Draw horizontal line (alpha RGB)
//==================================================================================
void sge_HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_HLineAlpha(Surface,x1,x2,y, SDL_MapRGB(Surface->format, R, G, B), alpha);
}
//==================================================================================
// Internal draw vertical line
//==================================================================================
void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
{
if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
return;
if(y1<Surface->clip_miny)
y1=Surface->clip_miny;
if(y2>Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect l;
l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
SDL_FillRect(Surface, &l, Color);
}
//==================================================================================
// Draw vertical line
//==================================================================================
void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
{
if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
return;
if(y1<Surface->clip_miny)
y1=Surface->clip_miny;
if(y2>Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect l;
l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
SDL_FillRect(Surface, &l, Color);
sge_UpdateRect(Surface, x, y1, 1, y2-y1+1);
}
//==================================================================================
// Draw vertical line (RGB)
//==================================================================================
void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
sge_VLine(Surface,x,y1,y2, SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Internal draw vertical line (alpha - no update)
//==================================================================================
void _VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
{
Uint8 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_sge_lock = 0;
sge_FilledRectAlpha(Surface, x,y1,x,y2, Color, alpha);
_sge_update = update;
_sge_lock = lock;
}
//==================================================================================
// Draw vertical line (alpha)
//==================================================================================
void sge_VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
{
sge_FilledRectAlpha(Surface, x,y1,x,y2, Color, alpha);
}
//==================================================================================
// Draw vertical line (alpha RGB)
//==================================================================================
void sge_VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_VLineAlpha(Surface,x,y1,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}
//==================================================================================
// Performs Callback at each line point. (From PowerPak)
//==================================================================================
void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
Sint16 dx, dy, sdx, sdy, x, y, px, py;
dx = x2 - x1;
dy = y2 - y1;
sdx = (dx < 0) ? -1 : 1;
sdy = (dy < 0) ? -1 : 1;
dx = sdx * dx + 1;
dy = sdy * dy + 1;
x = y = 0;
px = x1;
py = y1;
if (dx >= dy){
for (x = 0; x < dx; x++){
Callback(Surface, px, py, Color);
y += dy;
if (y >= dx){
y -= dx;
py += sdy;
}
px += sdx;
}
}
else{
for (y = 0; y < dy; y++){
Callback(Surface, px, py, Color);
x += dx;
if (x >= dy){
x -= dy;
px += sdx;
}
py += sdy;
}
}
}
//==================================================================================
// Performs Callback at each line point. (RGB)
//==================================================================================
void sge_DoLine(SDL_Surface *Surface, Sint16 X1, Sint16 Y1, Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
sge_DoLine(Surface,X1,Y1,X2,Y2, SDL_MapRGB(Surface->format, R, G, B),Callback);
}
//==================================================================================
// Draws a line
//==================================================================================
void _Line(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
/* Clipping */
if(x2<sge_clip_xmin(surface) || x1>sge_clip_xmax(surface) || y2<sge_clip_ymin(surface) || y1>sge_clip_ymax(surface))
return;
if (x1 < sge_clip_xmin(surface))
x1 = sge_clip_xmin(surface);
if (x2 > sge_clip_xmax(surface))
x2 = sge_clip_xmax(surface);
if (y1 < sge_clip_ymin(surface))
y1 = sge_clip_ymin(surface);
if (y2 > sge_clip_ymax(surface))
y2 = sge_clip_ymax(surface);
Sint16 dx, dy, sdx, sdy, x, y;
dx = x2 - x1;
dy = y2 - y1;
sdx = (dx < 0) ? -1 : 1;
sdy = (dy < 0) ? -1 : 1;
dx = sdx * dx + 1;
dy = sdy * dy + 1;
x = y = 0;
Sint16 pixx = surface->format->BytesPerPixel;
Sint16 pixy = surface->pitch;
Uint8 *pixel = (Uint8*)surface->pixels + y1*pixy + x1*pixx;
pixx *= sdx;
pixy *= sdy;
if (dx < dy) {
Sint32 tmp = dx; dx = dy; dy = Sint16(tmp);
tmp = pixx; pixx = pixy; pixy = tmp;
}
switch(surface->format->BytesPerPixel) {
case 1: {
for(x=0; x < dx; x++) {
*pixel = color;
y += dy;
if (y >= dx) {
y -= dx;
pixel += pixy;
}
pixel += pixx;
}
}
break;
case 2: {
for(x=0; x < dx; x++) {
*(Uint16*)pixel = color;
y += dy;
if (y >= dx) {
y -= dx;
pixel += pixy;
}
pixel += pixx;
}
}
break;
case 3: {
Uint8 rshift8 = surface->format->Rshift/8;
Uint8 gshift8 = surface->format->Gshift/8;
Uint8 bshift8 = surface->format->Bshift/8;
Uint8 ashift8 = surface->format->Ashift/8;
Uint8 R = (color>>surface->format->Rshift)&0xff;
Uint8 G = (color>>surface->format->Gshift)&0xff;
Uint8 B = (color>>surface->format->Bshift)&0xff;
Uint8 A = (color>>surface->format->Ashift)&0xff;
for(x=0; x < dx; x++) {
*(pixel+rshift8) = R;
*(pixel+gshift8) = G;
*(pixel+bshift8) = B;
*(pixel+ashift8) = A;
y += dy;
if (y >= dx) {
y -= dx;
pixel += pixy;
}
pixel += pixx;
}
}
break;
case 4: {
for(x=0; x < dx; x++) {
*(Uint32*)pixel = color;
y += dy;
if (y >= dx) {
y -= dx;
pixel += pixy;
}
pixel += pixx;
}
}
break;
}
}
void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
/* Draw the line */
_Line(Surface, x1,y1, x2,y2, Color);
/* unlock the display */
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
//==================================================================================
// Draws a line (RGB)
//==================================================================================
void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
sge_Line(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// A quick hack to get alpha working with callbacks
//==================================================================================
Uint8 _sge_alpha_hack = 0;
void callback_alpha_hack(SDL_Surface *surf, Sint16 x, Sint16 y, Uint32 color)
{
_PutPixelAlpha(surf,x,y,color,_sge_alpha_hack);
}
//==================================================================================
// Draws a line (alpha)
//==================================================================================
void sge_LineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_sge_alpha_hack = alpha;
/* Draw the line */
sge_DoLine(Surface, x1, y1, x2, y2, Color, callback_alpha_hack);
/* unlock the display */
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
//==================================================================================
// Draws a line (alpha - RGB)
//==================================================================================
void sge_LineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_LineAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}
//==================================================================================
// Anti-aliased line
// From SDL_gfxPrimitives written by A. Schiffler (aschiffler@home.com)
//==================================================================================
#define AAbits 8
#define AAlevels 256 /* 2^AAbits */
void sge_AALineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
Sint32 xx0,yy0,xx1,yy1;
Uint32 intshift, erracc=0, erradj;
Uint32 erracctmp, wgt, wgtcompmask;
Sint16 dx, dy, tmp, xdir, y0p1, x0pxdir;
/* Keep on working with 32bit numbers */
xx0=x1;
yy0=y1;
xx1=x2;
yy1=y2;
/* Reorder points if required */
if (yy0 > yy1) {
tmp = yy0; yy0 = yy1; yy1 = tmp;
tmp = xx0; xx0 = xx1; xx1 = tmp;
}
/* Calculate distance */
dx = xx1 - xx0;
dy = yy1 - yy0;
/* Adjust for negative dx and set xdir */
if (dx >= 0) {
xdir=1;
} else {
xdir=-1;
dx=(-dx);
}
/* Check for special cases */
if (dx==0) {
/* Vertical line */
sge_VLineAlpha(dst, x1,y1,y2,color,alpha);
return;
} else if (dy==0) {
/* Horizontal line */
sge_HLineAlpha(dst, x1,x2,y1,color,alpha);
return;
} else if (dx==dy) {
/* Diagonal line */
if(alpha==255)
sge_Line(dst,x1,y1,x2,y2,color);
else
sge_LineAlpha(dst,x1,y1,x2,y2,color,alpha);
return;
}
Uint8 a = 255-alpha;
/* Lock surface */
if ( SDL_MUSTLOCK(dst) && _sge_lock )
if ( SDL_LockSurface(dst) < 0 )
return;
intshift = 32 - AAbits; /* # of bits by which to shift erracc to get intensity level */
wgtcompmask = AAlevels - 1; /* Mask used to flip all bits in an intensity weighting */
if(alpha==255)
_PutPixel(dst,x1,y1, color); /* Draw the initial pixel in the foreground color */
else
_PutPixelAlpha(dst,x1,y1, color, alpha);
/* x-major or y-major? */
if (dy > dx) {
/* y-major. Calculate 16-bit fixed point fractional part of a pixel that
X advances every time Y advances 1 pixel, truncating the result so that
we won't overrun the endpoint along the X axis */
erradj = ((dx << 16) / dy)<<16;
/* draw all pixels other than the first and last */
x0pxdir=xx0+xdir;
while (--dy) {
erracctmp = erracc;
erracc += erradj;
if (erracc <= erracctmp) {
/* rollover in error accumulator, x coord advances */
xx0=x0pxdir;
x0pxdir += xdir;
}
yy0++; /* y-major so always advance Y */
/* the AAbits most significant bits of erracc give us the intensity
weighting for this pixel, and the complement of the weighting for
the paired pixel. */
wgt = (erracc >> intshift) & 255;
tmp = 255-wgt-a;
if(tmp<0)
tmp=0;
_PutPixelAlpha(dst,xx0,yy0,color,Uint8(tmp));
tmp = wgt-a;
if(tmp<0)
tmp=0;
_PutPixelAlpha(dst,x0pxdir,yy0,color,Uint8(tmp));
}
} else {
/* x-major line. Calculate 16-bit fixed-point fractional part of a pixel
that Y advances each time X advances 1 pixel, truncating the result so
that we won't overrun the endpoint along the X axis. */
erradj = ((dy << 16) / dx)<<16;
/* draw all pixels other than the first and last */
y0p1=yy0+1;
while (--dx) {
erracctmp = erracc;
erracc += erradj;
if (erracc <= erracctmp) {
/* Accumulator turned over, advance y */
yy0=y0p1;
y0p1++;
}
xx0 += xdir; /* x-major so always advance X */
/* the AAbits most significant bits of erracc give us the intensity
weighting for this pixel, and the complement of the weighting for
the paired pixel. */
wgt = (erracc >> intshift) & 255;
tmp = 255-wgt-a;
if(tmp<0)
tmp=0;
_PutPixelAlpha(dst,xx0,yy0,color,tmp);
tmp = wgt-a;
if(tmp<0)
tmp=0;
_PutPixelAlpha(dst,xx0,y0p1,color,tmp);
}
}
/* Draw final pixel, always exactly intersected by the line and doesn't
need to be weighted. */
if(alpha==255)
_PutPixel(dst,x2,y2, color);
else
_PutPixelAlpha(dst,x2,y2, color, alpha);
/* unlock the display */
if (SDL_MUSTLOCK(dst) && _sge_lock) {
SDL_UnlockSurface(dst);
}
sge_UpdateRect(dst, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
void sge_AALineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 alpha)
{
sge_AALineAlpha(dst,x1,y1,x2,y2,SDL_MapRGB(dst->format, r, g, b),alpha);
}
void sge_AALine(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
sge_AALineAlpha(dst, x1,y1, x2,y2, color, 255);
}
void sge_AALine(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b)
{
sge_AALineAlpha(dst,x1,y1,x2,y2,SDL_MapRGB(dst->format, r, g, b),255);
}
/**********************************************************************************/
/** Figure functions **/
/**********************************************************************************/
//==================================================================================
// Draws a rectangle
//==================================================================================
void sge_Rect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
_HLine(Surface,x1,x2,y1,color);
_HLine(Surface,x1,x2,y2,color);
_VLine(Surface,x1,y1,y2,color);
_VLine(Surface,x2,y1,y2,color);
sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
}
//==================================================================================
// Draws a rectangle (RGB)
//==================================================================================
void sge_Rect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
sge_Rect(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws a rectangle (alpha)
//==================================================================================
void sge_RectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_HLineAlpha(Surface,x1,x2,y1,color,alpha);
_HLineAlpha(Surface,x1,x2,y2,color,alpha);
_VLineAlpha(Surface,x1,y1,y2,color,alpha);
_VLineAlpha(Surface,x2,y1,y2,color,alpha);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
}
//==================================================================================
// Draws a rectangle (RGB)
//==================================================================================
void sge_RectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_RectAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}
//==================================================================================
// Draws a filled rectangle
//==================================================================================
void sge_FilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
Sint16 tmp;
if(x1>x2){
tmp=x1; x1=x2; x2=tmp;
}
if(y1>y2){
tmp=y1; y1=y2; y2=tmp;
}
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x2<Surface->clip_minx || x1>Surface->clip_maxx || y2<Surface->clip_miny || y1>Surface->clip_maxy)
return;
if (x1 < Surface->clip_minx)
x1=Surface->clip_minx;
if (x2 > Surface->clip_maxx)
x2=Surface->clip_maxx;
if (y1 < Surface->clip_miny)
y1=Surface->clip_miny;
if (y2 > Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect area;
area.x=x1; area.y=y1;
area.w=x2-x1+1; area.h=y2-y1+1;
SDL_FillRect(Surface,&area,color);
sge_UpdateRect(Surface, x1, y1, x2-x1+1, y2-y1+1);
}
//==================================================================================
// Draws a filled rectangle (RGB)
//==================================================================================
void sge_FilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
sge_FilledRect(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws a filled rectangle (alpha)
//==================================================================================
void sge_FilledRectAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
/*if( alpha == 255 ){
sge_FilledRect(surface,x1,y1,x2,y2,color);
return;
}*/
/* Fix coords */
Sint16 tmp;
if(x1>x2){
tmp=x1; x1=x2; x2=tmp;
}
if(y1>y2){
tmp=y1; y1=y2; y2=tmp;
}
/* Clipping */
if(x2<sge_clip_xmin(surface) || x1>sge_clip_xmax(surface) || y2<sge_clip_ymin(surface) || y1>sge_clip_ymax(surface))
return;
if (x1 < sge_clip_xmin(surface))
x1 = sge_clip_xmin(surface);
if (x2 > sge_clip_xmax(surface))
x2 = sge_clip_xmax(surface);
if (y1 < sge_clip_ymin(surface))
y1 = sge_clip_ymin(surface);
if (y2 > sge_clip_ymax(surface))
y2 = sge_clip_ymax(surface);
Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
Uint32 R,G,B,A=0;
Sint16 x,y;
if (SDL_MUSTLOCK(surface) && _sge_lock)
if (SDL_LockSurface(surface) < 0)
return;
switch (surface->format->BytesPerPixel) {
case 1: { /* Assuming 8-bpp */
Uint8 *row, *pixel;
Uint8 dR, dG, dB;
Uint8 sR = surface->format->palette->colors[color].r;
Uint8 sG = surface->format->palette->colors[color].g;
Uint8 sB = surface->format->palette->colors[color].b;
for(y = y1; y<=y2; y++){
row = (Uint8 *)surface->pixels + y*surface->pitch;
for(x = x1; x <= x2; x++){
pixel = row + x;
dR = surface->format->palette->colors[*pixel].r;
dG = surface->format->palette->colors[*pixel].g;
dB = surface->format->palette->colors[*pixel].b;
dR = dR + ((sR-dR)*alpha >> 8);
dG = dG + ((sG-dG)*alpha >> 8);
dB = dB + ((sB-dB)*alpha >> 8);
*pixel = SDL_MapRGB(surface->format, dR, dG, dB);
}
}
}
break;
case 2: { /* Probably 15-bpp or 16-bpp */
Uint16 *row, *pixel;
Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
for(y = y1; y<=y2; y++){
row = (Uint16 *)surface->pixels + y*surface->pitch/2;
for(x = x1; x <= x2; x++){
pixel = row + x;
R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
if( Amask )
A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
*pixel= R | G | B | A;
}
}
}
break;
case 3: { /* Slow 24-bpp mode, usually not used */
Uint8 *row,*pix;
Uint8 dR, dG, dB, dA;
Uint8 rshift8=surface->format->Rshift/8;
Uint8 gshift8=surface->format->Gshift/8;
Uint8 bshift8=surface->format->Bshift/8;
Uint8 ashift8=surface->format->Ashift/8;
Uint8 sR = (color>>surface->format->Rshift)&0xff;
Uint8 sG = (color>>surface->format->Gshift)&0xff;
Uint8 sB = (color>>surface->format->Bshift)&0xff;
Uint8 sA = (color>>surface->format->Ashift)&0xff;
for(y = y1; y<=y2; y++){
row = (Uint8 *)surface->pixels + y * surface->pitch;
for(x = x1; x <= x2; x++){
pix = row + x*3;
dR = *((pix)+rshift8);
dG = *((pix)+gshift8);
dB = *((pix)+bshift8);
dA = *((pix)+ashift8);
dR = dR + ((sR-dR)*alpha >> 8);
dG = dG + ((sG-dG)*alpha >> 8);
dB = dB + ((sB-dB)*alpha >> 8);
dA = dA + ((sA-dA)*alpha >> 8);
*((pix)+rshift8) = dR;
*((pix)+gshift8) = dG;
*((pix)+bshift8) = dB;
*((pix)+ashift8) = dA;
}
}
}
break;
case 4: { /* Probably 32-bpp */
Uint32 *row, *pixel;
Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
for(y = y1; y<=y2; y++){
row = (Uint32 *)surface->pixels + y*surface->pitch/4;
for(x = x1; x <= x2; x++){
pixel = row + x;
R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
if( Amask )
A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
*pixel= R | G | B | A;
}
}
}
break;
}
if (SDL_MUSTLOCK(surface) && _sge_lock) {
SDL_UnlockSurface(surface);
}
sge_UpdateRect(surface, x1, y1, x2-x1+1, y2-y1+1);
}
void sge_FilledRectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_FilledRectAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}
//==================================================================================
// Performs Callback at each ellipse point.
// (from Allegro)
//==================================================================================
void sge_DoEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color) )
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
if (rx < 1)
rx = 1;
if (ry < 1)
ry = 1;
h = i = j = k = 0xFFFF;
if (rx > ry) {
ix = 0;
iy = rx * 64;
do {
oh = h;
oi = i;
oj = j;
ok = k;
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * ry) / rx;
k = (i * ry) / rx;
if (((h != oh) || (k != ok)) && (h < oi)) {
Callback(Surface, x+h, y+k, color);
if (h)
Callback(Surface, x-h, y+k, color);
if (k) {
Callback(Surface, x+h, y-k, color);
if (h)
Callback(Surface, x-h, y-k, color);
}
}
if (((i != oi) || (j != oj)) && (h < i)) {
Callback(Surface, x+i, y+j, color);
if (i)
Callback(Surface, x-i, y+j, color);
if (j) {
Callback(Surface, x+i, y-j, color);
if (i)
Callback(Surface, x-i, y-j, color);
}
}
ix = ix + iy / rx;
iy = iy - ix / rx;
} while (i > h);
}
else {
ix = 0;
iy = ry * 64;
do {
oh = h;
oi = i;
oj = j;
ok = k;
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * rx) / ry;
k = (i * rx) / ry;
if (((j != oj) || (i != oi)) && (h < i)) {
Callback(Surface, x+j, y+i, color);
if (j)
Callback(Surface, x-j, y+i, color);
if (i) {
Callback(Surface, x+j, y-i, color);
if (j)
Callback(Surface, x-j, y-i, color);
}
}
if (((k != ok) || (h != oh)) && (h < oi)) {
Callback(Surface, x+k, y+h, color);
if (k)
Callback(Surface, x-k, y+h, color);
if (h) {
Callback(Surface, x+k, y-h, color);
if (k)
Callback(Surface, x-k, y-h, color);
}
}
ix = ix + iy / ry;
iy = iy - ix / ry;
} while(i > h);
}
}
//==================================================================================
// Performs Callback at each ellipse point. (RGB)
//==================================================================================
void sge_DoEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color) )
{
sge_DoEllipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),Callback);
}
//==================================================================================
// Draws an ellipse
//==================================================================================
void sge_Ellipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
sge_DoEllipse(Surface, x, y, rx, ry, color, _PutPixel);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws an ellipse (RGB)
//==================================================================================
void sge_Ellipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
sge_Ellipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws an ellipse (alpha)
//==================================================================================
void sge_EllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_sge_alpha_hack = alpha;
sge_DoEllipse(Surface, x, y, rx, ry, color, callback_alpha_hack);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws an ellipse (alpha - RGB)
//==================================================================================
void sge_EllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_EllipseAlpha(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws a filled ellipse
//==================================================================================
void sge_FilledEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
if (rx < 1)
rx = 1;
if (ry < 1)
ry = 1;
oh = oi = oj = ok = 0xFFFF;
if (rx > ry) {
ix = 0;
iy = rx * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * ry) / rx;
k = (i * ry) / rx;
if ((k!=ok) && (k!=oj)) {
if (k){
_HLine(Surface,x-h,x+h,y-k,color);
_HLine(Surface,x-h,x+h,y+k,color);
}else
_HLine(Surface,x-h,x+h,y,color);
ok=k;
}
if ((j!=oj) && (j!=ok) && (k!=j)) {
if (j){
_HLine(Surface,x-i,x+i,y-j,color);
_HLine(Surface,x-i,x+i,y+j,color);
}else
_HLine(Surface,x-i,x+i,y,color);
oj=j;
}
ix = ix + iy / rx;
iy = iy - ix / rx;
} while (i > h);
}
else {
ix = 0;
iy = ry * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * rx) / ry;
k = (i * rx) / ry;
if ((i!=oi) && (i!=oh)) {
if (i){
_HLine(Surface,x-j,x+j,y-i,color);
_HLine(Surface,x-j,x+j,y+i,color);
}else
_HLine(Surface,x-j,x+j,y,color);
oi=i;
}
if ((h!=oh) && (h!=oi) && (i!=h)) {
if (h){
_HLine(Surface,x-k,x+k,y-h,color);
_HLine(Surface,x-k,x+k,y+h,color);
}else
_HLine(Surface,x-k,x+k,y,color);
oh=h;
}
ix = ix + iy / ry;
iy = iy - ix / ry;
} while(i > h);
}
-
- sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws a filled ellipse (RGB)
//==================================================================================
void sge_FilledEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
sge_FilledEllipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws a filled ellipse (alpha)
//==================================================================================
void sge_FilledEllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
if (rx < 1)
rx = 1;
if (ry < 1)
ry = 1;
oh = oi = oj = ok = 0xFFFF;
if (rx > ry) {
ix = 0;
iy = rx * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * ry) / rx;
k = (i * ry) / rx;
if ((k!=ok) && (k!=oj)) {
if (k){
_HLineAlpha(Surface,x-h,x+h,y-k,color,alpha);
_HLineAlpha(Surface,x-h,x+h,y+k,color,alpha);
}else
_HLineAlpha(Surface,x-h,x+h,y,color,alpha);
ok=k;
}
if ((j!=oj) && (j!=ok) && (k!=j)) {
if (j){
_HLineAlpha(Surface,x-i,x+i,y-j,color,alpha);
_HLineAlpha(Surface,x-i,x+i,y+j,color,alpha);
}else
_HLineAlpha(Surface,x-i,x+i,y,color,alpha);
oj=j;
}
ix = ix + iy / rx;
iy = iy - ix / rx;
} while (i > h);
}
else {
ix = 0;
iy = ry * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * rx) / ry;
k = (i * rx) / ry;
if ((i!=oi) && (i!=oh)) {
if (i){
_HLineAlpha(Surface,x-j,x+j,y-i,color,alpha);
_HLineAlpha(Surface,x-j,x+j,y+i,color,alpha);
}else
_HLineAlpha(Surface,x-j,x+j,y,color,alpha);
oi=i;
}
if ((h!=oh) && (h!=oi) && (i!=h)) {
if (h){
_HLineAlpha(Surface,x-k,x+k,y-h,color,alpha);
_HLineAlpha(Surface,x-k,x+k,y+h,color,alpha);
}else
_HLineAlpha(Surface,x-k,x+k,y,color,alpha);
oh=h;
}
ix = ix + iy / ry;
iy = iy - ix / ry;
} while(i > h);
}
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
- sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws a filled ellipse (alpha - RGB)
//==================================================================================
void sge_FilledEllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_FilledEllipseAlpha(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),alpha);
}
//==================================================================================
// Performs Callback at each circle point.
//==================================================================================
void sge_DoCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
Sint16 cx = 0;
Sint16 cy = r;
Sint16 df = 1 - r;
Sint16 d_e = 3;
Sint16 d_se = -2 * r + 5;
do {
Callback(Surface, x+cx, y+cy, color);
Callback(Surface, x-cx, y+cy, color);
Callback(Surface, x+cx, y-cy, color);
Callback(Surface, x-cx, y-cy, color);
Callback(Surface, x+cy, y+cx, color);
Callback(Surface, x+cy, y-cx, color);
Callback(Surface, x-cy, y+cx, color);
Callback(Surface, x-cy, y-cx, color);
if (df < 0) {
df += d_e;
d_e += 2;
d_se += 2;
}
else {
df += d_se;
d_e += 2;
d_se += 4;
cy--;
}
cx++;
}while(cx <= cy);
}
//==================================================================================
// Performs Callback at each circle point. (RGB)
//==================================================================================
void sge_DoCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
sge_DoCircle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),Callback);
}
//==================================================================================
// Draws a circle
//==================================================================================
void sge_Circle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
sge_DoCircle(Surface, x, y, r, color, _PutPixel);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a circle (RGB)
//==================================================================================
void sge_Circle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
{
sge_Circle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws a circle (alpha)
//==================================================================================
void sge_CircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_sge_alpha_hack = alpha;
sge_DoCircle(Surface, x, y, r, color, callback_alpha_hack);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a circle (alpha - RGB)
//==================================================================================
void sge_CircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_CircleAlpha(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws a filled circle
//==================================================================================
void sge_FilledCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
{
Sint16 cx = 0;
Sint16 cy = r;
bool draw=true;
Sint16 df = 1 - r;
Sint16 d_e = 3;
Sint16 d_se = -2 * r + 5;
do {
if(draw){
_HLine(Surface,x-cx,x+cx,y+cy,color);
_HLine(Surface,x-cx,x+cx,y-cy,color);
draw=false;
}
if(cx!=cy){
if(cx){
_HLine(Surface,x-cy,x+cy,y-cx,color);
_HLine(Surface,x-cy,x+cy,y+cx,color);
}else
_HLine(Surface,x-cy,x+cy,y,color);
}
if (df < 0) {
df += d_e;
d_e += 2;
d_se += 2;
}
else {
df += d_se;
d_e += 2;
d_se += 4;
cy--;
draw=true;
}
cx++;
}while(cx <= cy);
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a filled circle (RGB)
//==================================================================================
void sge_FilledCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
{
sge_FilledCircle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B));
}
//==================================================================================
// Draws a filled circle (alpha)
//==================================================================================
void sge_FilledCircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
{
Sint16 cx = 0;
Sint16 cy = r;
bool draw=true;
Sint16 df = 1 - r;
Sint16 d_e = 3;
Sint16 d_se = -2 * r + 5;
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
do {
if(draw){
_HLineAlpha(Surface,x-cx,x+cx,y+cy,color,alpha);
_HLineAlpha(Surface,x-cx,x+cx,y-cy,color,alpha);
draw=false;
}
if(cx!=cy){
if(cx){
_HLineAlpha(Surface,x-cy,x+cy,y-cx,color,alpha);
_HLineAlpha(Surface,x-cy,x+cy,y+cx,color,alpha);
}else
_HLineAlpha(Surface,x-cy,x+cy,y,color,alpha);
}
if (df < 0) {
df += d_e;
d_e += 2;
d_se += 2;
}
else {
df += d_se;
d_e += 2;
d_se += 4;
cy--;
draw=true;
}
cx++;
}while(cx <= cy);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a filled circle (alpha - RGB)
//==================================================================================
void sge_FilledCircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_FilledCircleAlpha(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws a bezier line
//==================================================================================
/* Macro to do the line... 'function' is the line drawing routine */
#define DO_BEZIER(function)\
/*
* Note: I don't think there is any great performance win in translating this to fixed-point integer math,
* most of the time is spent in the line drawing routine.
*/\
float x = float(x1), y = float(y1);\
float xp = x, yp = y;\
float delta;\
float dx, d2x, d3x;\
float dy, d2y, d3y;\
float a, b, c;\
int i;\
int n = 1;\
Sint16 xmax=x1, ymax=y1, xmin=x1, ymin=y1;\
\
/* compute number of iterations */\
if(level < 1)\
level=1;\
if(level >= 15)\
level=15; \
while (level-- > 0)\
n*= 2;\
delta = 1.0 / float(n);\
\
/* compute finite differences */\
/* a, b, c are the coefficient of the polynom in t defining the parametric curve */\
/* The computation is done independently for x and y */\
a = float(-x1 + 3*x2 - 3*x3 + x4);\
b = float(3*x1 - 6*x2 + 3*x3);\
c = float(-3*x1 + 3*x2);\
\
d3x = 6 * a * delta*delta*delta;\
d2x = d3x + 2 * b * delta*delta;\
dx = a * delta*delta*delta + b * delta*delta + c * delta;\
\
a = float(-y1 + 3*y2 - 3*y3 + y4);\
b = float(3*y1 - 6*y2 + 3*y3);\
c = float(-3*y1 + 3*y2);\
\
d3y = 6 * a * delta*delta*delta;\
d2y = d3y + 2 * b * delta*delta;\
dy = a * delta*delta*delta + b * delta*delta + c * delta;\
\
if (SDL_MUSTLOCK(surface) && _sge_lock) {\
if (SDL_LockSurface(surface) < 0)\
return;\
}\
\
/* iterate */\
for (i = 0; i < n; i++) {\
x += dx; dx += d2x; d2x += d3x;\
y += dy; dy += d2y; d2y += d3y;\
if(Sint16(xp) != Sint16(x) || Sint16(yp) != Sint16(y)){\
function;\
if(_sge_update==1){\
xmax= (xmax>Sint16(xp))? xmax : Sint16(xp); ymax= (ymax>Sint16(yp))? ymax : Sint16(yp);\
xmin= (xmin<Sint16(xp))? xmin : Sint16(xp); ymin= (ymin<Sint16(yp))? ymin : Sint16(yp);\
xmax= (xmax>Sint16(x))? xmax : Sint16(x); ymax= (ymax>Sint16(y))? ymax : Sint16(y);\
xmin= (xmin<Sint16(x))? xmin : Sint16(x); ymin= (ymin<Sint16(y))? ymin : Sint16(y);\
}\
}\
xp = x; yp = y;\
}\
\
/* unlock the display */\
if (SDL_MUSTLOCK(surface) && _sge_lock) {\
SDL_UnlockSurface(surface);\
}\
\
/* Update the area */\
sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
//==================================================================================
// Draws a bezier line
//==================================================================================
void sge_Bezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color)
{
DO_BEZIER(_Line(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color));
}
//==================================================================================
// Draws a bezier line (RGB)
//==================================================================================
void sge_Bezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
{
sge_Bezier(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B));
}
//==================================================================================
// Draws a bezier line (alpha)
//==================================================================================
void sge_BezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color, Uint8 alpha)
{
_sge_alpha_hack = alpha;
DO_BEZIER(sge_DoLine(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color, callback_alpha_hack));
}
//==================================================================================
// Draws a bezier line (alpha - RGB)
//==================================================================================
void sge_BezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_BezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),alpha);
}
//==================================================================================
// Draws an AA bezier line (alpha)
//==================================================================================
void sge_AABezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color, Uint8 alpha)
{
Uint8 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_sge_lock = 0;
if (SDL_MUSTLOCK(surface) && lock)
if (SDL_LockSurface(surface) < 0)
return;
DO_BEZIER(sge_AALineAlpha(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color, alpha));
if (SDL_MUSTLOCK(surface) && lock) {
SDL_UnlockSurface(surface);
}
_sge_update = update;
_sge_lock = lock;
sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
}
//==================================================================================
// Draws an AA bezier line (alpha - RGB)
//==================================================================================
void sge_AABezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_AABezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),alpha);
}
//==================================================================================
// Draws an AA bezier line
//==================================================================================
void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color)
{
sge_AABezierAlpha(surface, x1,y1, x2,y2, x3,y3, x4,y4, level, color, 255);
}
//==================================================================================
// Draws an AA bezier line (RGB)
//==================================================================================
void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
{
sge_AABezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),255);
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Feb 2, 8:55 PM (2 d, 15 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55537
Default Alt Text
(94 KB)

Event Timeline