https://github.com/libsdl-org/Maelstrom/commit/909055a684c27e086960fe9d923cb88560bf8926
From 909055a684c27e086960fe9d923cb88560bf8926 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 19 Nov 2011 20:34:52 -0500
Subject: [PATCH] Removed gNumPlayers since we will be able to have a sparse
player array.
---
game/game.cpp | 121 ++++++++++++++++++++++++++++++++++------------
game/gameinfo.cpp | 18 +++++++
game/gameinfo.h | 2 +
game/make.cpp | 12 ++++-
game/netplay.cpp | 17 ++++---
game/netplay.h | 1 -
game/objects.h | 38 ++++++++++-----
game/player.cpp | 32 +++++++++---
game/player.h | 10 ++++
game/shinobi.h | 21 ++++----
10 files changed, 202 insertions(+), 70 deletions(-)
diff --git a/game/game.cpp b/game/game.cpp
index be66e008..e4de1107 100644
--- a/game/game.cpp
+++ b/game/game.cpp
@@ -71,8 +71,8 @@ void NewGame(void)
SeedRandom(gGameInfo.seed);
/* Send a "NEW_GAME" packet onto the network */
- if ( gNumPlayers > 1 ) {
- if ( gOurPlayer == 0 ) {
+ if ( gGameInfo.IsMultiplayer() ) {
+ if ( gGameInfo.IsHosting() ) {
if ( Send_NewGame() < 0)
return;
} else {
@@ -80,6 +80,13 @@ void NewGame(void)
return;
}
}
+ for (int i = 0; i < MAX_PLAYERS; ++i) {
+ if (gGameInfo.IsValidPlayer(i)) {
+ gPlayers[i]->SetControlType(gGameInfo.GetPlayer(i)->controlMask);
+ } else {
+ gPlayers[i]->SetControlType(CONTROL_NONE);
+ }
+ }
ui->ShowPanel(PANEL_GAME);
#ifdef USE_TOUCHCONTROL
@@ -154,13 +161,17 @@ GamePanelDelegate::OnShow()
gGameOn = 1;
gPaused = 0;
gWave = gGameInfo.wave - 1;
- for ( i=gNumPlayers; i--; )
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->NewGame(gGameInfo.lives, gGameInfo.deathMatch);
+ }
gLastStar = STAR_DELAY;
gLastDrawn = 0L;
gNumSprites = 0;
- if ( gNumPlayers > 1 ) {
+ if ( gGameInfo.IsMultiplayer() ) {
if (m_multiplayerCaption) {
m_multiplayerCaption->Show();
}
@@ -228,8 +239,12 @@ GamePanelDelegate::OnTick()
gGameOn = 0;
return;
}
- OBJ_LOOP(i, gNumPlayers)
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->HandleKeys();
+ }
if ( gPaused ) {
return;
@@ -248,7 +263,10 @@ GamePanelDelegate::OnTick()
}
/* -- Do all hit detection */
- OBJ_LOOP(j, gNumPlayers) {
+ OBJ_LOOP(j, MAX_PLAYERS) {
+ if (!gPlayers[j]->IsValid()) {
+ continue;
+ }
if ( ! gPlayers[j]->Alive() )
continue;
@@ -264,7 +282,10 @@ GamePanelDelegate::OnTick()
}
}
if ( gGameInfo.deathMatch ) {
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
if ( i == j ) // Don't shoot ourselves. :)
continue;
(void) gPlayers[i]->HitBy(gPlayers[j]);
@@ -272,7 +293,10 @@ GamePanelDelegate::OnTick()
}
}
if ( gEnemySprite ) {
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
if ( ! gPlayers[i]->Alive() )
continue;
(void) gPlayers[i]->HitBy(gEnemySprite);
@@ -291,7 +315,10 @@ GamePanelDelegate::OnTick()
if ( gShakeTime && (gShakeTime-- > 0) ) {
int shakeV;
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
shakeV = FastRandom(SHAKE_FACTOR);
if ( ! gPlayers[i]->Alive() )
continue;
@@ -304,8 +331,12 @@ GamePanelDelegate::OnTick()
}
/* -- Move all of the sprites */
- OBJ_LOOP(i, gNumPlayers)
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->Move(0);
+ }
OBJ_LOOP(i, gNumSprites) {
if ( gSprites[i]->Move(gFreezeTime) < 0 ) {
delete gSprites[i];
@@ -339,13 +370,21 @@ GamePanelDelegate::OnDraw()
/* -- Blit all the sprites */
OBJ_LOOP(i, gNumSprites)
gSprites[i]->BlitSprite();
- OBJ_LOOP(i, gNumPlayers)
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->BlitSprite();
+ }
/* -- Show the player dots */
- if ( gNumPlayers > 1 ) {
- OBJ_LOOP(i, gNumPlayers)
+ if ( gGameInfo.IsMultiplayer() ) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->ShowDot();
+ }
}
}
@@ -364,12 +403,12 @@ GamePanelDelegate::DrawStatus(Bool first)
/* -- Draw the status display */
if (first && gWave == 1) {
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
lastLife[i] = lastScores[i] = 0;
}
}
- if ( gNumPlayers > 1 ) {
+ if ( gGameInfo.IsMultiplayer() ) {
char caption[BUFSIZ];
sprintf(caption, "You are player %d --- displaying player %d",
@@ -443,7 +482,10 @@ GamePanelDelegate::DrawStatus(Bool first)
}
/* Check for everyone else's new lives */
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
Score = gPlayers[i]->GetScore();
if ( i == gDisplayed && m_score ) {
@@ -537,7 +579,10 @@ GamePanelDelegate::DoHousekeeping()
/* -- Make sure someone is still playing... */
bool PlayersLeft = false;
- for ( i=0; i < gNumPlayers; ++i ) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
if ( gPlayers[i]->Kicking() ) {
PlayersLeft = true;
break;
@@ -605,7 +650,10 @@ GamePanelDelegate::DoBonus()
bonus = panel->GetElement<UIElement>("bonus");
score = panel->GetElement<UIElement>("score");
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
if ( i != gOurPlayer ) {
gPlayers[i]->MultBonus();
continue;
@@ -662,7 +710,10 @@ GamePanelDelegate::DoBonus()
Delay(SOUND_DELAY);
/* -- Count the score down */
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
if ( i != gOurPlayer ) {
while ( gPlayers[i]->GetBonus() > 500 ) {
gPlayers[i]->IncrScore(500);
@@ -726,7 +777,7 @@ GamePanelDelegate::DoBonus()
void
GamePanelDelegate::NextWave()
{
- int index, x, y;
+ int i, x, y;
int NewRoids;
short temp;
@@ -809,12 +860,16 @@ GamePanelDelegate::NextWave()
gWhenDone = 0;
/* -- Create the ship's sprite */
- for ( index=gNumPlayers; index--; )
- gPlayers[index]->NewWave();
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+ gPlayers[i]->NewWave();
+ }
DrawStatus(true);
/* -- Create some asteroids */
- for (index = 0; index < NewRoids; index++) {
+ for (i = 0; i < NewRoids; i++) {
int randval;
x = FastRandom(SCREEN_WIDTH) * SCALE_FACTOR;
@@ -862,16 +917,16 @@ static void DoGameOver(void)
Bool done = false;
/* Get the final scoring */
- struct FinalScore *final = new struct FinalScore[gNumPlayers];
- for ( i=0; i<gNumPlayers; ++i ) {
+ struct FinalScore *final = new struct FinalScore[MAX_PLAYERS];
+ for ( i=0; i<MAX_PLAYERS; ++i ) {
final[i].Player = i+1;
final[i].Score = gPlayers[i]->GetScore();
final[i].Frags = gPlayers[i]->GetFrags();
}
if ( gGameInfo.deathMatch )
- qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byfrags);
+ qsort(final,MAX_PLAYERS,sizeof(struct FinalScore),cmp_byfrags);
else
- qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byscore);
+ qsort(final,MAX_PLAYERS,sizeof(struct FinalScore),cmp_byscore);
panel = ui->GetPanel(PANEL_GAMEOVER);
if (!panel) {
@@ -885,8 +940,12 @@ static void DoGameOver(void)
}
/* Show the player ranking */
- if ( gNumPlayers > 1 ) {
- for ( i=0; i<gNumPlayers; ++i ) {
+ if ( gGameInfo.IsMultiplayer() ) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+
char name[32];
char buffer[BUFSIZ], num1[12], num2[12];
@@ -927,7 +986,7 @@ static void DoGameOver(void)
/* -- They got a high score! */
gLastHigh = which;
- if ((which != -1) && (gNumPlayers == 1) &&
+ if ((which != -1) && !gGameInfo.IsMultiplayer() &&
(gGameInfo.wave == 1) && (gGameInfo.lives == 3)) {
sound->PlaySound(gBonusShot, 5);
@@ -1007,7 +1066,7 @@ static void DoGameOver(void)
sound->PlaySound(gGotPrize, 6);
SaveScores();
} else
- if ( gNumPlayers > 1 ) /* Let them watch their ranking */
+ if ( gGameInfo.IsMultiplayer() ) /* Let them watch their ranking */
SDL_Delay(3000);
while ( sound->Playing() )
diff --git a/game/gameinfo.cpp b/game/gameinfo.cpp
index c7643a49..2059b22a 100644
--- a/game/gameinfo.cpp
+++ b/game/gameinfo.cpp
@@ -317,6 +317,12 @@ GameInfo::IsHosting() const
return localID == gameID;
}
+bool
+GameInfo::IsMultiplayer() const
+{
+ return (GetNumPlayers() > 1);
+}
+
bool
GameInfo::IsLocalNode(int index) const
{
@@ -362,6 +368,18 @@ GameInfo::IsNetworkPlayer(int index) const
return (players[index].nodeID != localID);
}
+int
+GameInfo::GetNumPlayers() const
+{
+ int numPlayers = 0;
+ for (int i = 0; i < MAX_PLAYERS; ++i) {
+ if (players[i].nodeID) {
+ ++numPlayers;
+ }
+ }
+ return numPlayers;
+}
+
bool
GameInfo::IsFull() const
{
diff --git a/game/gameinfo.h b/game/gameinfo.h
index 372baa9c..ae2b9ded 100644
--- a/game/gameinfo.h
+++ b/game/gameinfo.h
@@ -148,12 +148,14 @@ class GameInfo
void RemovePlayer(int index);
bool IsHosting() const;
+ bool IsMultiplayer() const;
bool IsLocalNode(int index) const;
bool IsNetworkNode(int index) const;
bool IsValidPlayer(int index) const;
bool IsLocalPlayer(int index) const;
bool IsNetworkPlayer(int index) const;
+ int GetNumPlayers() const;
bool IsFull() const;
diff --git a/game/make.cpp b/game/make.cpp
index 0a0d7ea9..d20abb82 100644
--- a/game/make.cpp
+++ b/game/make.cpp
@@ -135,7 +135,11 @@ void MakeNova(void)
// -- Make sure it isn't appearing right next to the ship
- for ( i=gNumPlayers; i--; ) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+
int xDist, yDist;
/* Make sure the player is alive. :) */
@@ -266,7 +270,11 @@ void MakeGravity(void)
// -- Make sure it isn't appearing right next to the ship
- for ( i=gNumPlayers; i--; ) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+
int xDist, yDist;
/* Make sure the player is alive. :) */
diff --git a/game/netplay.cpp b/game/netplay.cpp
index f3d2acad..0d25eb52 100644
--- a/game/netplay.cpp
+++ b/game/netplay.cpp
@@ -108,7 +108,6 @@ int InitNetData(bool hosting)
}
/* Initialize network game variables */
- gNumPlayers = 0;
gOurPlayer = -1;
for ( i=0; i<MAX_PLAYERS; ++i ) {
SyncPtrs[0][i] = NULL;
@@ -147,22 +146,24 @@ int CheckPlayers(void)
{
int i;
- gNumPlayers = 0;
+ if (gGameInfo.GetNumPlayers() == 0) {
+ error("No players specified!\r\n");
+ return(-1);
+ }
+
+ gNumPlayers = gGameInfo.GetNumPlayers();
gOurPlayer = -1;
for ( i=0; i<MAX_PLAYERS; ++i ) {
if (gGameInfo.IsValidPlayer(i)) {
if (gGameInfo.IsLocalPlayer(i)) {
- gOurPlayer = i;
+ if (gOurPlayer < 0) {
+ gOurPlayer = i;
+ }
} else {
PlayAddr[i] = gGameInfo.GetPlayerAddress(i);
}
- ++gNumPlayers;
}
}
- if (gNumPlayers == 0) {
- error("No players specified!\r\n");
- return(-1);
- }
if (gOurPlayer < 0) {
error("Which player are you?\r\n");
return(-1);
diff --git a/game/netplay.h b/game/netplay.h
index d44f3289..74e78b72 100644
--- a/game/netplay.h
+++ b/game/netplay.h
@@ -34,5 +34,4 @@ extern int Await_NewGame();
/* Variables from netplay.cpp */
extern int gOurPlayer;
-extern int gNumPlayers;
extern UDPsocket gNetFD;
diff --git a/game/objects.h b/game/objects.h
index 881f89df..58a69922 100644
--- a/game/objects.h
+++ b/game/objects.h
@@ -78,8 +78,12 @@ class Prize : public Object {
gSprites[i] = gSprites[gNumSprites];
}
}
- OBJ_LOOP(i, gNumPlayers)
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->CutThrust(SHAKE_DURATION);
+ }
gShakeTime = SHAKE_DURATION;
break;
}
@@ -144,8 +148,12 @@ class Nova : public Object {
gSprites[i] = gSprites[gNumSprites];
}
}
- OBJ_LOOP(i, gNumPlayers)
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->CutThrust(SHAKE_DURATION);
+ }
gShakeTime = SHAKE_DURATION;
}
return(-1);
@@ -298,7 +306,10 @@ class Gravity : public Object {
return(Object::Move(Frozen));
/* Warp the courses of the players */
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
int X, Y, xAccel, yAccel;
if ( ! gPlayers[i]->Alive() )
@@ -337,18 +348,21 @@ class Homing : public Object {
/* This is duplicated in the Shinobi class */
virtual int AcquireTarget(void) {
- int i, newtarget=(-1);
+ int targets[MAX_PLAYERS];
+ int numTargets = 0;
- for ( i=0; i<gNumPlayers; ++i ) {
- if ( gPlayers[i]->Alive() )
- break;
+ for ( int i=0; i < MAX_PLAYERS; ++i ) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+ if ( gPlayers[i]->Alive() ) {
+ targets[numTargets++] = i;
+ }
}
- if ( i != gNumPlayers ) { // Player(s) alive!
- do {
- newtarget = FastRandom(gNumPlayers);
- } while ( ! gPlayers[newtarget]->Alive() );
+ if (numTargets > 0) {
+ return targets[FastRandom(numTargets)];
}
- return(newtarget);
+ return -1;
}
int Move(int Frozen) {
diff --git a/game/player.cpp b/game/player.cpp
index 4b2ad845..ebe6062e 100644
--- a/game/player.cpp
+++ b/game/player.cpp
@@ -50,6 +50,7 @@ Player:: Player(int index) : Object(0, 0, 0, 0, gPlayerShip, NO_PHASE_CHANGE)
{
int i;
+ Valid = 0;
Index = index;
Score = 0;
for ( i=0; i<MAX_SHOTS; ++i ) {
@@ -103,8 +104,7 @@ Player::NewWave(void)
WasShielded = 0;
Sphase = 0;
SetPos(
- ((SCREEN_WIDTH/2-((gNumPlayers/2-Index)*(2*SPRITES_WIDTH)))
- *SCALE_FACTOR),
+ ((SCREEN_WIDTH/2-((gGameInfo.GetNumPlayers()/2-Index)*(2*SPRITES_WIDTH)))*SCALE_FACTOR),
((SCREEN_HEIGHT/2)*SCALE_FACTOR)
);
xvec = yvec = 0;
@@ -159,7 +159,10 @@ Player::IncrFrags(void)
if ( gGameInfo.deathMatch && (Frags >= gGameInfo.deathMatch) ) {
/* Game over, we got a stud. :) */
int i;
- OBJ_LOOP(i, gNumPlayers) {
+ OBJ_LOOP(i, MAX_PLAYERS) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
gPlayers[i]->IncrLives(-1);
gPlayers[i]->Explode();
#ifdef DEBUG
@@ -241,8 +244,7 @@ Player::BeenTimedOut(void)
{
Exploding = 0;
SetPos(
- ((SCREEN_WIDTH/2-((gNumPlayers/2-Index)*(2*SPRITES_WIDTH)))
- *SCALE_FACTOR),
+ ((SCREEN_WIDTH/2-((gGameInfo.GetNumPlayers()/2-Index)*(2*SPRITES_WIDTH)))*SCALE_FACTOR),
((SCREEN_HEIGHT/2)*SCALE_FACTOR)
);
if ( gGameInfo.deathMatch )
@@ -647,6 +649,17 @@ Player::ExplodeSound(void)
sound->PlaySound(gShipHitSound, 3);
}
+void
+Player::SetControlType(Uint8 controlType)
+{
+ if (controlType == CONTROL_NONE) {
+ Valid = 0;
+ } else {
+ Valid = 1;
+ }
+ this->controlType = controlType;
+}
+
void
Player::SetControl(unsigned char which, int toggle)
{
@@ -745,6 +758,11 @@ int InitPlayerSprites(void)
/* Function to switch the displayed player */
void RotatePlayerView()
{
- if ( ++gDisplayed == gNumPlayers )
- gDisplayed = 0;
+ for (int i = 0; i < MAX_PLAYERS; ++i) {
+ if ( ++gDisplayed == MAX_PLAYERS )
+ gDisplayed = 0;
+
+ if (gPlayers[gDisplayed]->IsValid())
+ break;
+ }
}
diff --git a/game/player.h b/game/player.h
index f7fdffc5..f468341b 100644
--- a/game/player.h
+++ b/game/player.h
@@ -37,6 +37,9 @@ class Player : public Object {
Player(int index);
~Player();
+ virtual int IsValid(void) {
+ return(Valid);
+ }
virtual int IsPlayer(void) {
return(1);
}
@@ -134,9 +137,14 @@ class Player : public Object {
}
}
+ void SetControlType(Uint8 controlType);
+ Uint8 GetControlType() {
+ return controlType;
+ }
void SetControl(unsigned char which, int toggle);
private:
+ int Valid;
int Index;
int Lives;
int Score;
@@ -167,6 +175,8 @@ class Player : public Object {
int numshots;
Uint32 ship_color;
+ Uint8 controlType;
+
/* Create a new shot */
int MakeShot(int offset);
/* Rubout a flying shot */
diff --git a/game/shinobi.h b/game/shinobi.h
index 9675abdb..6157fe2a 100644
--- a/game/shinobi.h
+++ b/game/shinobi.h
@@ -51,18 +51,21 @@ class Shinobi : public Object {
/* This is duplicated in the Homing class */
virtual int AcquireTarget(void) {
- int i, newtarget=(-1);
+ int targets[MAX_PLAYERS];
+ int numTargets = 0;
- for ( i=0; i<gNumPlayers; ++i ) {
- if ( gPlayers[i]->Alive() )
- break;
+ for ( int i=0; i < MAX_PLAYERS; ++i ) {
+ if (!gPlayers[i]->IsValid()) {
+ continue;
+ }
+ if ( gPlayers[i]->Alive() ) {
+ targets[numTargets++] = i;
+ }
}
- if ( i != gNumPlayers ) { // Player(s) alive!
- do {
- newtarget = FastRandom(gNumPlayers);
- } while ( ! gPlayers[newtarget]->Alive() );
+ if (numTargets > 0) {
+ return targets[FastRandom(numTargets)];
}
- return(newtarget);
+ return -1;
}