https://github.com/libsdl-org/Maelstrom/commit/a7bf340a67ac6e9de469bc7e84c6cbcd29d462fc
From a7bf340a67ac6e9de469bc7e84c6cbcd29d462fc Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 26 Oct 2011 19:40:06 -0400
Subject: [PATCH] Turned the game screen into a UIPanel
---
UI/game.xml | 2 +
UIPanels.cpp | 3 +
main.cpp | 8 +-
main.h | 1 +
netlogic/Makefile.am | 2 +-
netlogic/about.cpp | 10 --
netlogic/blit.cpp | 156 -----------------------------
netlogic/game.cpp | 215 ++++++++++++++++++++++++++++++++--------
netlogic/game.h | 17 ++++
screenlib/UIManager.cpp | 17 ++--
screenlib/UIPanel.cpp | 8 ++
screenlib/UIPanel.h | 4 +
12 files changed, 222 insertions(+), 221 deletions(-)
create mode 100644 UI/game.xml
delete mode 100644 netlogic/blit.cpp
create mode 100644 netlogic/game.h
diff --git a/UI/game.xml b/UI/game.xml
new file mode 100644
index 00000000..98cb3218
--- /dev/null
+++ b/UI/game.xml
@@ -0,0 +1,2 @@
+<UIPanel cursor="false" delegate="GamePanel">
+</UIPanel>
diff --git a/UIPanels.cpp b/UIPanels.cpp
index 07bd71cb..986d6277 100644
--- a/UIPanels.cpp
+++ b/UIPanels.cpp
@@ -3,6 +3,7 @@
#include "UIPanels.h"
#include "main.h"
#include "netlogic/about.h"
+#include "netlogic/game.h"
static UIPanelDelegate *
@@ -12,6 +13,8 @@ CreateMaelstromUIDelegate(UIPanel *panel, const char *delegate)
return new MainPanelDelegate(panel);
} else if (strcasecmp(delegate, "AboutPanel") == 0) {
return new AboutPanelDelegate(panel);
+ } else if (strcasecmp(delegate, "GamePanel") == 0) {
+ return new GamePanelDelegate(panel);
} else {
fprintf(stderr, "Warning: Couldn't find delegate '%s'\n", delegate);
return NULL;
diff --git a/main.cpp b/main.cpp
index 8d726313..b943afb9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -461,11 +461,15 @@ MainPanelDelegate::OnLoad()
button->SetButtonDelegate(new SetVolumeDelegate(8));
}
- gUpdateBuffer = true;
-
return true;
}
+void
+MainPanelDelegate::OnShow()
+{
+ gUpdateBuffer = true;
+}
+
void
MainPanelDelegate::OnTick()
{
diff --git a/main.h b/main.h
index d36f987b..2869527a 100644
--- a/main.h
+++ b/main.h
@@ -8,6 +8,7 @@ class MainPanelDelegate : public UIPanelDelegate
MainPanelDelegate(UIPanel *panel) : UIPanelDelegate(panel) { }
virtual bool OnLoad();
+ virtual void OnShow();
virtual void OnTick();
};
diff --git a/netlogic/Makefile.am b/netlogic/Makefile.am
index 1ddb28bc..831206dc 100644
--- a/netlogic/Makefile.am
+++ b/netlogic/Makefile.am
@@ -3,8 +3,8 @@ noinst_LIBRARIES = liblogic.a
liblogic_a_SOURCES = \
about.cpp \
- blit.cpp \
game.cpp \
+ game.h \
globals.h \
logic.cpp \
make.cpp \
diff --git a/netlogic/about.cpp b/netlogic/about.cpp
index a0dcb855..149b544b 100644
--- a/netlogic/about.cpp
+++ b/netlogic/about.cpp
@@ -4,16 +4,6 @@
#include "about.h"
-AboutPanelDelegate::AboutPanelDelegate(UIPanel *panel) : UIPanelDelegate(panel)
-{
- numsprites = 0;
-}
-
-AboutPanelDelegate::~AboutPanelDelegate()
-{
- assert(numsprites == 0);
-}
-
void
AboutPanelDelegate::OnShow()
{
diff --git a/netlogic/blit.cpp b/netlogic/blit.cpp
deleted file mode 100644
index 0b6bcce6..00000000
--- a/netlogic/blit.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-
-/* Note well: The order that things are done is very important to prevent
- bugs. Several optimizing assumptions are done in player.cc
- and object.cc that require this order. For example, I assume
- that all sprites are erased when object->Move() is called,
- that object->HitBy() is called before the move, and that
- object->Move() is called EVERY timestep!
-*/
-
-#include "Maelstrom_Globals.h"
-#include "netplay.h"
-#include "object.h"
-#include "player.h"
-#include "globals.h"
-
-/* Returns the number of players left in the game */
-int RunFrame(void)
-{
- int i, j, PlayersLeft;
-
- /* Read in keyboard input for our ship */
- HandleEvents(0);
-
- /* Send Sync! signal to all players, and handle keyboard. */
- if ( SyncNetwork() < 0 ) {
- error("Game aborted!\n");
- return(0);
- }
- OBJ_LOOP(i, gNumPlayers)
- gPlayers[i]->HandleKeys();
-
- if ( gPaused > 0 )
- return(1);
-
- /* Play the boom sounds */
- if ( --gNextBoom == 0 ) {
- if ( gBoomPhase ) {
- sound->PlaySound(gBoom1, 0);
- gBoomPhase = 0;
- } else {
- sound->PlaySound(gBoom2, 0);
- gBoomPhase = 1;
- }
- gNextBoom = gBoomDelay;
- }
-
- /* Do all hit detection */
- OBJ_LOOP(j, gNumPlayers) {
- if ( ! gPlayers[j]->Alive() )
- continue;
-
- /* This loop looks funny because gNumSprites can change
- dynamically during the loop as sprites are killed/created.
- This same logic is used whenever looping where sprites
- might be destroyed.
- */
- OBJ_LOOP(i, gNumSprites) {
- if ( gSprites[i]->HitBy(gPlayers[j]) < 0 ) {
- delete gSprites[i];
- gSprites[i] = gSprites[gNumSprites];
- }
- }
- OBJ_LOOP(i, gNumPlayers) {
- if ( i == j ) // Don't shoot ourselves. :)
- continue;
- (void) gPlayers[i]->HitBy(gPlayers[j]);
- }
- }
- if ( gEnemySprite ) {
- OBJ_LOOP(i, gNumPlayers) {
- if ( ! gPlayers[i]->Alive() )
- continue;
- (void) gPlayers[i]->HitBy(gEnemySprite);
- }
- OBJ_LOOP(i, gNumSprites) {
- if ( gSprites[i] == gEnemySprite )
- continue;
- if ( gSprites[i]->HitBy(gEnemySprite) < 0 ) {
- delete gSprites[i];
- gSprites[i] = gSprites[gNumSprites];
- }
- }
- }
-
- /* Handle all the shimmy and the shake. :-) */
- if ( gShakeTime && (gShakeTime-- > 0) ) {
- int shakeV;
-
- OBJ_LOOP(i, gNumPlayers) {
- shakeV = FastRandom(SHAKE_FACTOR);
- if ( ! gPlayers[i]->Alive() )
- continue;
- gPlayers[i]->Shake(FastRandom(SHAKE_FACTOR));
- }
- OBJ_LOOP(i, gNumSprites) {
- shakeV = FastRandom(SHAKE_FACTOR);
- gSprites[i]->Shake(FastRandom(SHAKE_FACTOR));
- }
- }
-
- /* Move all of the sprites */
- OBJ_LOOP(i, gNumPlayers)
- gPlayers[i]->Move(0);
- OBJ_LOOP(i, gNumSprites) {
- if ( gSprites[i]->Move(gFreezeTime) < 0 ) {
- delete gSprites[i];
- gSprites[i] = gSprites[gNumSprites];
- }
- }
- if ( gFreezeTime )
- --gFreezeTime;
-
- /* Now Blit them all again */
- OBJ_LOOP(i, gNumSprites)
- gSprites[i]->BlitSprite();
- OBJ_LOOP(i, gNumPlayers)
- gPlayers[i]->BlitSprite();
-
- /* Make sure someone is still playing... */
- for ( i=0, PlayersLeft=0; i < gNumPlayers; ++i ) {
- if ( gPlayers[i]->Kicking() )
- ++PlayersLeft;
- }
- if ( gNumPlayers > 1 ) {
- OBJ_LOOP(i, gNumPlayers)
- gPlayers[i]->ShowDot();
- }
-
-#ifdef SERIOUS_DEBUG
-printf("Player listing: ");
-OBJ_LOOP(i, gNumPlayers) {
- int x, y;
- gPlayers[i]->GetPos(&x, &y);
- printf(" %d = (%d,%d)", i, x, y);
-}
-printf("\n");
-
-printf("Object listing: ");
-OBJ_LOOP(i, gNumSprites) {
- int x, y;
- gSprites[i]->GetPos(&x, &y);
- printf(" %d = (%d,%d)", i, x, y);
-}
-printf("\n");
-#endif /* SERIOUS_DEBUG */
-
- /* Timing handling -- Delay the FRAME_DELAY */
- if ( ! gNoDelay ) {
- Uint32 ticks;
- while ( ((ticks=Ticks)-gLastDrawn) < FRAME_DELAY ) {
- SDL_Delay(1);
- }
- gLastDrawn = ticks;
- }
- return(PlayersLeft);
-}
diff --git a/netlogic/game.cpp b/netlogic/game.cpp
index ed4af9a2..b3421fe9 100644
--- a/netlogic/game.cpp
+++ b/netlogic/game.cpp
@@ -5,6 +5,7 @@
#include "netplay.h"
#include "make.h"
#include "load.h"
+#include "game.h"
#ifdef MOVIE_SUPPORT
@@ -89,7 +90,6 @@ int SelectMovieRect(void)
}
#endif
-extern int RunFrame(void); /* The heart of blit.cpp */
// Global variables set in this file...
int gGameOn;
@@ -277,15 +277,49 @@ void NewGame(void)
}
}
+ ui->ShowPanel(PANEL_GAME);
+
+ /* Play the game, dammit! */
+ while (gGameOn) {
+ ui->Draw();
+
+ /* Timing handling -- Delay the FRAME_DELAY */
+ if ( ! gNoDelay ) {
+ Uint32 ticks;
+ while ( ((ticks=Ticks)-gLastDrawn) < FRAME_DELAY ) {
+ SDL_Delay(1);
+ }
+ gLastDrawn = ticks;
+ }
+ }
+
+ ui->HidePanel(PANEL_GAME);
+
+/* -- Do the game over stuff */
+
+ screen->HideCursor();
+ DoGameOver();
+ screen->ShowCursor();
+
+ ui->ShowPanel(PANEL_MAIN);
+} /* -- NewGame */
+
+bool
+GamePanelDelegate::OnLoad()
+{
/* Load the font and colors we use everywhere */
geneva = fonts[GENEVA_9];
text_height = fontserv->TextHeight(geneva);
ourGrey = screen->MapRGB(30000>>8, 30000>>8, 0xFF);
ourWhite = screen->MapRGB(0xFF, 0xFF, 0xFF);
- /* Fade into game mode */
- screen->Fade();
- screen->HideCursor();
+ return true;
+}
+
+void
+GamePanelDelegate::OnShow()
+{
+ int i;
/* Initialize some game variables */
gGameOn = 1;
@@ -298,50 +332,24 @@ void NewGame(void)
gNumSprites = 0;
NextWave();
+}
- /* Play the game, dammit! */
- while (gGameOn) {
- screen->Clear();
-
- /* -- Draw the star field */
- for ( i=0; i<MAX_STARS; ++i ) {
- screen->DrawPoint(gTheStars[i]->xCoord,
- gTheStars[i]->yCoord, gTheStars[i]->color);
- }
-
- /* Draw the status frame */
- DrawStatus(false);
-
- if (!RunFrame()) {
- gGameOn = 0;
- }
- screen->Update();
-
- DoHouseKeeping();
- }
-
-/* -- Do the game over stuff */
-
- DoGameOver();
- screen->ShowCursor();
-} /* -- NewGame */
-
-
-/* ----------------------------------------------------------------- */
-/* -- Do some housekeeping! */
+void
+GamePanelDelegate::OnHide()
+{
+}
-static void DoHouseKeeping(void)
+void
+GamePanelDelegate::OnTick()
{
/* Don't do anything if we're paused */
if ( gPaused ) {
- /* Give up the CPU for a frame duration */
- Delay(FRAME_DELAY);
return;
}
#ifdef MOVIE_SUPPORT
if ( gMovie )
- win->ScreenDump("MovieFrame", &gMovieRect);
+ screen->ScreenDump("MovieFrame", &gMovieRect);
#endif
/* -- Maybe throw a multiplier up on the screen */
if (gMultiplierShown && (--gMultiplierShown == 0) )
@@ -388,9 +396,134 @@ static void DoHouseKeeping(void)
else if ( --gWhenDone == 0 )
NextWave();
}
-
-} /* -- DoHouseKeeping */
+}
+
+void
+GamePanelDelegate::OnDraw()
+{
+ int i, j, PlayersLeft;
+
+ /* -- Draw the star field */
+ for ( i=0; i<MAX_STARS; ++i ) {
+ screen->DrawPoint(gTheStars[i]->xCoord,
+ gTheStars[i]->yCoord, gTheStars[i]->color);
+ }
+
+ /* Draw the status frame */
+ DrawStatus(false);
+
+ /* Read in keyboard input for our ship */
+ HandleEvents(0);
+
+ /* Send Sync! signal to all players, and handle keyboard. */
+ if ( SyncNetwork() < 0 ) {
+ error("Game aborted!\n");
+ gGameOn = 0;
+ return;
+ }
+ OBJ_LOOP(i, gNumPlayers)
+ gPlayers[i]->HandleKeys();
+
+ if ( gPaused > 0 )
+ return;
+
+ /* Play the boom sounds */
+ if ( --gNextBoom == 0 ) {
+ if ( gBoomPhase ) {
+ sound->PlaySound(gBoom1, 0);
+ gBoomPhase = 0;
+ } else {
+ sound->PlaySound(gBoom2, 0);
+ gBoomPhase = 1;
+ }
+ gNextBoom = gBoomDelay;
+ }
+
+ /* Do all hit detection */
+ OBJ_LOOP(j, gNumPlayers) {
+ if ( ! gPlayers[j]->Alive() )
+ continue;
+
+ /* This loop looks funny because gNumSprites can change
+ dynamically during the loop as sprites are killed/created.
+ This same logic is used whenever looping where sprites
+ might be destroyed.
+ */
+ OBJ_LOOP(i, gNumSprites) {
+ if ( gSprites[i]->HitBy(gPlayers[j]) < 0 ) {
+ delete gSprites[i];
+ gSprites[i] = gSprites[gNumSprites];
+ }
+ }
+ OBJ_LOOP(i, gNumPlayers) {
+ if ( i == j ) // Don't shoot ourselves. :)
+ continue;
+ (void) gPlayers[i]->HitBy(gPlayers[j]);
+ }
+ }
+ if ( gEnemySprite ) {
+ OBJ_LOOP(i, gNumPlayers) {
+ if ( ! gPlayers[i]->Alive() )
+ continue;
+ (void) gPlayers[i]->HitBy(gEnemySprite);
+ }
+ OBJ_LOOP(i, gNumSprites) {
+ if ( gSprites[i] == gEnemySprite )
+ continue;
+ if ( gSprites[i]->HitBy(gEnemySprite) < 0 ) {
+ delete gSprites[i];
+ gSprites[i] = gSprites[gNumSprites];
+ }
+ }
+ }
+ /* Handle all the shimmy and the shake. :-) */
+ if ( gShakeTime && (gShakeTime-- > 0) ) {
+ int shakeV;
+
+ OBJ_LOOP(i, gNumPlayers) {
+ shakeV = FastRandom(SHAKE_FACTOR);
+ if ( ! gPlayers[i]->Alive() )
+ continue;
+ gPlayers[i]->Shake(FastRandom(SHAKE_FACTOR));
+ }
+ OBJ_LOOP(i, gNumSprites) {
+ shakeV = FastRandom(SHAKE_FACTOR);
+ gSprites[i]->Shake(FastRandom(SHAKE_FACTOR));
+ }
+ }
+
+ /* Move all of the sprites */
+ OBJ_LOOP(i, gNumPlayers)
+ gPlayers[i]->Move(0);
+ OBJ_LOOP(i, gNumSprites) {
+ if ( gSprites[i]->Move(gFreezeTime) < 0 ) {
+ delete gSprites[i];
+ gSprites[i] = gSprites[gNumSprites];
+ }
+ }
+ if ( gFreezeTime )
+ --gFreezeTime;
+
+ /* Now Blit them all again */
+ OBJ_LOOP(i, gNumSprites)
+ gSprites[i]->BlitSprite();
+ OBJ_LOOP(i, gNumPlayers)
+ gPlayers[i]->BlitSprite();
+
+ /* Make sure someone is still playing... */
+ for ( i=0, PlayersLeft=0; i < gNumPlayers; ++i ) {
+ if ( gPlayers[i]->Kicking() )
+ ++PlayersLeft;
+ }
+ if ( gNumPlayers > 1 ) {
+ OBJ_LOOP(i, gNumPlayers)
+ gPlayers[i]->ShowDot();
+ }
+ if ( !PlayersLeft ) {
+ gGameOn = 0;
+ }
+}
/* ----------------------------------------------------------------- */
/* -- Start the next wave! */
@@ -544,12 +677,10 @@ static void DoGameOver(void)
final[i].Score = gPlayers[i]->GetScore();
final[i].Frags = gPlayers[i]->GetFrags();
}
-#ifndef macintosh
if ( gDeathMatch )
qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byfrags);
else
qsort(final,gNumPlayers,sizeof(struct FinalScore),cmp_byscore);
-#endif
screen->Fade();
sound->HaltSound();
diff --git a/netlogic/game.h b/netlogic/game.h
new file mode 100644
index 00000000..adcdd6c8
--- /dev/null
+++ b/netlogic/game.h
@@ -0,0 +1,17 @@
+
+#ifndef _game_h
+#define _game_h
+
+class GamePanelDelegate : public UIPanelDelegate
+{
+public:
+ GamePanelDelegate(UIPanel *panel) : UIPanelDelegate(panel) { }
+
+ virtual bool OnLoad();
+ virtual void OnShow();
+ virtual void OnHide();
+ virtual void OnTick();
+ virtual void OnDraw();
+};
+
+#endif // _game_h
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index 3f2768b8..d5b8a62d 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -184,6 +184,9 @@ UIManager::ShowPanel(UIPanel *panel)
Draw();
m_screen->FadeIn();
}
+ if (!panel->IsCursorVisible()) {
+ m_screen->HideCursor();
+ }
}
}
@@ -192,19 +195,13 @@ UIManager::HidePanel(UIPanel *panel)
{
if (panel && m_visible.remove(panel)) {
panel->Hide();
+
if (panel->IsFullscreen()) {
m_screen->FadeOut();
-
- for (unsigned int i = m_visible.length(); i--; ) {
- if (m_visible[i]->IsFullscreen()) {
- m_visible[i]->Show();
- Draw();
- m_screen->FadeIn();
- break;
- }
- }
}
-
+ if (!panel->IsCursorVisible()) {
+ m_screen->ShowCursor();
+ }
}
}
diff --git a/screenlib/UIPanel.cpp b/screenlib/UIPanel.cpp
index adbf6500..0f97a5c0 100644
--- a/screenlib/UIPanel.cpp
+++ b/screenlib/UIPanel.cpp
@@ -36,6 +36,7 @@ UIPanel::UIPanel(UIManager *ui, const char *name) : UIArea(ui->GetScreen())
m_rect.h = m_screen->Height();
m_shown = false;
m_fullscreen = true;
+ m_cursorVisible = true;
m_enterSound = 0;
m_leaveSound = 0;
m_delegate = NULL;
@@ -70,6 +71,13 @@ UIPanel::Load(rapidxml::xml_node<> *node)
m_fullscreen = false;
}
}
+ attr = node->first_attribute("cursor", 0, false);
+ if (attr) {
+ const char *value = attr->value();
+ if (*value == '0' || *value == 'f' || *value == 'F') {
+ m_cursorVisible = false;
+ }
+ }
attr = node->first_attribute("enterSound", 0, false);
if (attr) {
m_enterSound = atoi(attr->value());
diff --git a/screenlib/UIPanel.h b/screenlib/UIPanel.h
index d21cf9bc..5b398930 100644
--- a/screenlib/UIPanel.h
+++ b/screenlib/UIPanel.h
@@ -65,6 +65,9 @@ class UIPanel : public UIArea
bool IsFullscreen() const {
return m_fullscreen;
}
+ bool IsCursorVisible() const {
+ return m_cursorVisible;
+ }
bool Load(rapidxml::xml_node<> *node);
@@ -97,6 +100,7 @@ class UIPanel : public UIArea
UIManager *m_ui;
char *m_name;
bool m_fullscreen;
+ bool m_cursorVisible;
int m_enterSound;
int m_leaveSound;
UIPanelDelegate *m_delegate;