ref: 30c2d82dffe2d90a3f155e6395e0e36961260102
parent: 9acc208ae7427727a736faf0fe971756a34ae019
author: Iliyas Jorio <iliyas@jor.io>
date: Mon Feb 6 15:12:33 EST 2023
In-game widescreen toggle
--- a/src/SDLU.cpp
+++ b/src/SDLU.cpp
@@ -191,6 +191,8 @@
SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_STREAMING,
640, 480);
+
+ SDL_RenderSetLogicalSize(g_renderer, 640, widescreen ? 360: 480);
}
--- a/src/level.cpp
+++ b/src/level.cpp
@@ -63,12 +63,16 @@
kTitleItemQuit,
};
-struct {
+struct TitleItemDef
+{
const char* name;
MRGBColor color1;
MRGBColor color2;
MRect rect;
-} titleItems[kTitleItems] = {
+};
+
+static const TitleItemDef k_titleItemDefs[kTitleItems] =
+{
{ "\x03 Tutorial Mode", {204, 67,137}, {101, 74,207}, {155, 203, 207, 426} },
{ "\x03 One Player Game", { 35, 31,240}, { 81,237,252}, {225, 179, 281, 451} },
{ "\x03 Two Player Game", {212,194, 48}, {255,196, 56}, {297, 182, 352, 454} },
@@ -82,8 +86,6 @@
const int kCursorWidth = 32;
const int kCursorHeight = 32;
-extern MBoolean useNewTitle;
-
#if USE_CURSOR_SPRITE
static void InsertCursor( MPoint mouseHere, SDL_Surface* scratch, SDL_Surface* surface )
{
@@ -124,6 +126,8 @@
void GameStartMenu( void )
{
+ MBoolean useNewTitle = widescreen;
+
// NOTE: be wary of initializing variables here! This function can run top-to-bottom
// multiple times in a row, thanks to "redo". Put initializations after redo.
SDL_Surface* gameStartSurface;
@@ -144,6 +148,7 @@
SkittlesFontPtr smallFont = GetFont( picFont );
SkittlesFontPtr tinyFont = GetFont( picTinyFont );
SDL_Rect meterRect[2] = { { 30, 360, 110, 20 }, { 530, 360, 110, 20 } };
+ TitleItemDef titleItems[kTitleItems];
int titleGlow[kTitleItems];
int shouldAddBlob;
const int kTitleGlowOff = useNewTitle? 150: 192;
@@ -151,7 +156,9 @@
const int kLeftSide = 0, kRightSide = 1, kGlow = 2, kCursor = 3;
+
redo:
+ memcpy(titleItems, k_titleItemDefs, sizeof(titleItems));
combo[0] = combo[1] = 0;
comboBright[0] = comboBright[1] = 0;
@@ -192,10 +199,13 @@
// make drawing surface
gameStartDrawSurface = SDLU_InitSurface( &backdropSDLRect, 32 );
- if (!useNewTitle) {
+ if (!useNewTitle)
+ {
SDLU_BlitSurface(gameStartSurface, &gameStartSurface->clip_rect,
gameStartDrawSurface, &gameStartDrawSurface->clip_rect);
- } else {
+ }
+ else
+ {
// Prepare new title screen
SDL_FillRect(gameStartDrawSurface, &gameStartDrawSurface->clip_rect, black);
@@ -212,13 +222,15 @@
int left = 225;
dPoint.h = left;
dPoint.v = 215;
- for (int i = 0; i < kTitleItems; i++) {
+ for (int i = 0; i < kTitleItems; i++)
+ {
auto &item = titleItems[i];
item.rect.left = dPoint.h;
item.rect.top = dPoint.v - 6;
item.rect.bottom = dPoint.v + 16 + 6;
auto nameLength = strlen(item.name);
- for (int charNo = 0; charNo < nameLength; charNo++) {
+ for (int charNo = 0; charNo < nameLength; charNo++)
+ {
char c = item.name[charNo];
float p = charNo / (float) (nameLength - 1);
int red = item.color1.red * (1.0f - p) + item.color2.red * p;
@@ -754,14 +766,7 @@
// In widescreen mode, move score/gray windows closer to the playfield
// so they fit in the cropped screen.
- if (widescreen) {
- for (int i = 0; i < 2; i++) {
- grayMonitorRect[i].top = playerWindowRect[i].top - 32 - 4;
- grayMonitorRect[i].bottom = playerWindowRect[i].top - 4;
- scoreWindowRect[i].top = playerWindowRect[i].bottom + 4;
- scoreWindowRect[i].bottom = playerWindowRect[i].bottom + 16 + 4;
- }
- }
+ ResetWidescreenLayout();
nextWindowVisible[0] = ( player1 == kAutoControl )? false: true;
@@ -780,6 +785,19 @@
level = 1;
credits = (player2 == kNobodyControl)? 1: 5;
+}
+
+void ResetWidescreenLayout()
+{
+ int miniWindowOffset = widescreen ? 4 : 16;
+
+ for (int i = 0; i < 2; i++)
+ {
+ grayMonitorRect[i].top = playerWindowRect[i].top - 32 - miniWindowOffset;
+ grayMonitorRect[i].bottom = playerWindowRect[i].top - miniWindowOffset;
+ scoreWindowRect[i].top = playerWindowRect[i].bottom + miniWindowOffset;
+ scoreWindowRect[i].bottom = playerWindowRect[i].bottom + 16 + miniWindowOffset;
+ }
}
MBoolean InitCharacter( int player, int level )
--- a/src/level.h
+++ b/src/level.h
@@ -1,6 +1,7 @@
// level.h
void InitGame( int player1, int player2 );
+void ResetWidescreenLayout( );
MBoolean InitCharacter( int player, int level );
void PrepareStageGraphics( int type );
void BeginRound( MBoolean changeMusic );
binary files a/src/main.cpp b/src/main.cpp differ
--- a/src/pause.cpp
+++ b/src/pause.cpp
@@ -521,8 +521,8 @@
// main pause screen (kEndGame is reused in continue and register)
kMusic = 0, kResume,
kSound, kEndGame,
- kFullscreen, kControls,
- kScalingMode, kWarp,
+ kVideo, kControls,
+ kWarp,
// continue screen
kContinue,
@@ -533,6 +533,12 @@
k1PDrop, k2PDrop,
k1PRotate, k2PRotate,
kControlsOK, kControlsReset,
+
+// video settings screen
+ kFullscreen,
+ kWidescreen,
+ kScalingMode,
+ kVideoOK,
};
static void DrawContinueContents( int *item, int shade )
@@ -721,37 +727,59 @@
static void DrawPauseContents( int *item, int shade )
{
- MPoint dPoint;
- int index;
- const char *line[] = { "\x01 Music", "\x03 Resume",
- "\x01 Sound", "\x03 End Game",
- "\x01 Fullscreen", "\x03 Controls",
- "\x01 Crisp Scaling",
+ const char *line[] =
+ {
+ musicOn ? "\x01 Music" : "\x02 Music",
+ level == kTutorialLevel ? "\x03 Skip Tutorial" : "\x03 Resume",
+ soundOn ? "\x01 Sound" : "\x02 Sound",
+ "\x03 End Game",
+ "\x03 Video",
+ "\x03 Controls",
};
- const int itemCount = arrsize(line);
-
- if( level == kTutorialLevel ) line[kEndGame] = "\x03 Skip Tutorial";
-
- if( !musicOn ) line[kMusic] = "\x02 Music";
- if( !soundOn ) line[kSound] = "\x02 Sound";
- if( !fullscreen ) line[kFullscreen] = "\x02 Fullscreen";
- if( !crispUpscaling ) line[kScalingMode] = "\x02 Crisp Scaling";
-
SDLU_AcquireSurface( drawSurface );
- for( index=0; index<itemCount; index++ )
+ for( int i = 0; i < arrsize(line); i++ )
{
- dPoint.h = (index & 1)? 340: 180;
- dPoint.v = 240 + ((index & ~1) * 15);
+ MPoint dPoint;
+ dPoint.h = (i & 1)? 340: 180;
+ dPoint.v = 240 + ((i & ~1) * 15);
- DrawRainbowText( smallFont, line[index], dPoint, (0.25 * index) + (0.075 * shade), (*item == index)? kTextBrightRainbow: kTextRainbow );
+ DrawRainbowText( smallFont, line[i], dPoint, (0.25 * i) + (0.075 * shade), (*item == i)? kTextBrightRainbow: kTextRainbow );
}
SDLU_ReleaseSurface( drawSurface );
}
+static void DrawVideoSettingsContents(int* item, int shade)
+{
+ struct ZoneLabel
+ {
+ int item;
+ const char* text;
+ }
+ labels[] =
+ {
+ { kFullscreen, fullscreen ? "\x01 Fullscreen" : "\x02 Fullscreen" },
+ { kWidescreen, widescreen ? "\x01 Widescreen" : "\x02 Widescreen" },
+ { kScalingMode, crispUpscaling ? "\x01 Crisp upscaling" : "\x02 Crisp upscaling" },
+ { kVideoOK, "\x03 OK" },
+ };
+ SDLU_AcquireSurface(drawSurface);
+
+ for (int i = 0; i < arrsize(labels); i++)
+ {
+ MPoint dPoint;
+ dPoint.h = 180;
+ dPoint.v = 240 + (i * 30);
+
+ DrawRainbowText(smallFont, labels[i].text, dPoint, (0.25 * i) + (0.075 * shade), (*item == labels[i].item) ? kTextBrightRainbow : kTextRainbow);
+ }
+
+ SDLU_ReleaseSurface(drawSurface);
+}
+
static MBoolean GetClickedZone( int* item, SDL_Keycode inSDLKey, int numZones, const ClickableZone* zones )
{
if( inSDLKey == SDLK_ESCAPE )
@@ -929,8 +957,8 @@
{
{ kMusic, { 240, 180, 260, 320 } }, { kResume, { 240, 340, 260, 480 } },
{ kSound, { 270, 180, 290, 320 } }, { kEndGame, { 270, 340, 290, 480 } },
- { kFullscreen, { 300, 180, 320, 320 } }, { kControls, { 300, 340, 320, 480 } },
- { kScalingMode, { 330, 180, 350, 320 } }, { kWarp, { 330, 340, 350, 480 } },
+ { kVideo, { 300, 180, 320, 320 } }, { kControls, { 300, 340, 320, 480 } },
+ { kWarp, { 330, 180, 350, 320 } },
};
static MBoolean lastDown = false;
@@ -973,6 +1001,7 @@
case kResume:
case kBack:
case kControls:
+ case kVideo:
PlayMono( kClick );
return true;
@@ -1000,6 +1029,74 @@
}
+
+static MBoolean VideoSettingsSelected( int *item, unsigned char inKey, SDL_Keycode inSDLKey )
+{
+ (void) inSDLKey; // is unused
+
+ static const ClickableZone zones[] =
+ {
+ { kFullscreen, { 240, 180, 260, 320 } },
+ { kWidescreen, { 270, 180, 290, 320 } },
+ { kScalingMode, { 300, 180, 320, 320 } },
+ { kVideoOK, { 330, 180, 350, 320 } },
+ };
+
+ static MBoolean lastDown = false;
+
+ int trigger = GetClickedZone( item, inSDLKey, arrsize(zones), zones );
+
+ if( trigger )
+ {
+ if( !lastDown )
+ {
+ lastDown = true;
+
+ switch( *item )
+ {
+ case kNothing:
+ break;
+
+ case kFullscreen:
+ fullscreen = !fullscreen;
+ SetFullscreen( fullscreen );
+ PlayMono( kClick );
+ return false;
+
+ case kScalingMode:
+ crispUpscaling = !crispUpscaling;
+ SDLU_CreateRendererTexture();
+ PlayMono(kClick);
+ return false;
+
+ case kWidescreen:
+ widescreen= !widescreen;
+ ResetWidescreenLayout();
+ SDLU_CreateRendererTexture();
+ SetFullscreen(fullscreen);
+ PlayMono(kClick);
+
+ NeedRefresh();
+ //RefreshAll();
+ //RefreshPlayerWindow(0);
+ //RefreshPlayerWindow(1);
+
+ return false;
+
+ default:
+ PlayMono( kClick );
+ return true;
+ }
+ }
+ }
+ else
+ {
+ lastDown = false;
+ }
+
+ return false;
+}
+
void HandleDialog( int type )
{
const float lighten[4] = { 96.0f, 48.0f, 8.0f, 48.0f };
@@ -1093,6 +1190,7 @@
HiScoreSelected,
ContinueSelected,
ControlsSelected,
+ VideoSettingsSelected,
};
if( DialogSelected[dialogType]( &dialogItem, inASCII, inSDLKey ) )
@@ -1121,6 +1219,7 @@
DrawHiScoreContents,
DrawContinueContents,
DrawControlsContents,
+ DrawVideoSettingsContents,
};
// Refresh screen if necessary
@@ -1136,9 +1235,9 @@
dialogShade += skip;
{
- const MBoolean dialogHasCandyCrisisLogo[kNumDialogs] = { true, true, true, true };
+ bool dialogHasCandyCrisisLogo = true;
- if( dialogHasCandyCrisisLogo[dialogType] )
+ if( dialogHasCandyCrisisLogo )
DrawDialogLogo( &pauseRect, dialogShade );
}
@@ -1195,6 +1294,11 @@
switch( dialogItem )
{
+ case kVideo:
+ HandleDialog( kVideoDialog );
+ HandleDialog( kPauseDialog );
+ break;
+
case kControls:
HandleDialog( kControlsDialog );
HandleDialog( kPauseDialog );
--- a/src/pause.h
+++ b/src/pause.h
@@ -10,5 +10,6 @@
kHiScoreDialog,
kContinueDialog,
kControlsDialog,
+ kVideoDialog,
kNumDialogs
};
--- a/src/prefs.cpp
+++ b/src/prefs.cpp
@@ -112,35 +112,3 @@
stream.write((const char*)pref.valuePtr, pref.valueLength);
}
}
-
-void ParseCommandLine(int argc, char* argv[])
-{
- for (int i = 1; i < argc; i++)
- {
- const char* arg = argv[i];
-
- if (!strcmp(arg, "--crisp")) crispUpscaling = true;
- if (!strcmp(arg, "--fullscreen")) fullscreen = true;
- if (!strcmp(arg, "--widescreen")) widescreen = true;
-
- if (!strcmp(arg, "--no-crisp")) crispUpscaling = false;
- if (!strcmp(arg, "--no-fullscreen")) fullscreen = false;
- if (!strcmp(arg, "--no-widescreen")) widescreen = false;
-
- if (!strcmp(arg, "--help") || !strcmp(arg, "-h"))
- {
- printf(
- "Candy Crisis source port - https://github.com/jorio/candycrisis\n"
- "\n"
- " --crisp pixel-perfect upscaling\n"
- " --no-crisp upscale with bilinear filtering\n"
- " --fullscreen run the game fullscreen\n"
- " --no-fullscreen run the game in a window\n"
- " --widescreen crop viewport to 16:9 aspect ratio\n"
- " --no-widescreen use original 4:3 aspect ratio\n"
- "\n"
- );
- exit(0);
- }
- }
-}
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -2,4 +2,3 @@
void LoadPrefs( void );
void SavePrefs( void );
-void ParseCommandLine(int argc, char* argv[]);