Continue menu

This commit is contained in:
Miloslav Ciz 2025-01-03 01:15:24 +01:00
parent 9e0cb3c944
commit 44f748134f
2 changed files with 204 additions and 94 deletions

View file

@ -33,7 +33,7 @@ static const char *LCR_texts[] =
}; };
static const char *LCR_internalResourceFile = static const char *LCR_internalResourceFile =
"testmap;" "Mtestmap;"
"0 :*H1k0J" "0 :*H1k0J"
":=s0s0 :fd190" // big concrete ":=s0s0 :fd190" // big concrete
@ -76,7 +76,8 @@ static const char *LCR_internalResourceFile =
":-k5k0 :f5120" ":-k5k0 :f5120"
" map end " " map end "
"#map2;1 :*H1k0J :,s0s0 :fd190 " "#Mmap2;1 :*H1k0J :,s0s0 :fd190 "
"#Mmap3;1 :*H1k0J :,s0s0 :fd190 "
; ;
#define LCR_IMAGE_SIZE 64 ///< one-dimension resolution of bitmap image #define LCR_IMAGE_SIZE 64 ///< one-dimension resolution of bitmap image

293
game.h
View file

@ -173,7 +173,7 @@ uint8_t LCR_gameGetNextAudioSample(void);
#define LCR_GAME_STATE_RUN_STARTING 0x01 #define LCR_GAME_STATE_RUN_STARTING 0x01
#define LCR_GAME_STATE_RUN 0x02 #define LCR_GAME_STATE_RUN 0x02
#define LCR_GAME_STATE_RUN_FINISHED 0x03 #define LCR_GAME_STATE_RUN_FINISHED 0x03
#define LCR_GAME_STATE_END 0xff
// TODO: move to consts? // TODO: move to consts?
#define LCR_MENU_MAX_ITEMS 9 #define LCR_MENU_MAX_ITEMS 9
@ -206,10 +206,11 @@ struct
{ {
int state; ///< -1 if reading external res. f., else pos. int state; ///< -1 if reading external res. f., else pos.
// indices and counts are among the resources of the same type
unsigned char loadedItemCount; unsigned char loadedItemCount;
char loadedItemNames[LCR_RESOURCE_ITEM_CHUNK * LCR_MENU_STRING_SIZE]; char loadedItemNames[LCR_RESOURCE_ITEM_CHUNK * LCR_MENU_STRING_SIZE];
unsigned int loadedItemsIndices[LCR_RESOURCE_ITEM_CHUNK]; // absolute unsigned int firstItemIndex;
unsigned int itemsTotal; // total of items of this type unsigned int itemsTotal;
} resourceFile; } resourceFile;
} LCR_game; } LCR_game;
@ -347,7 +348,7 @@ char LCR_gameGetNextResourceStrChar(void)
Seeks to the Nth resource string in the global resource file, after its name, Seeks to the Nth resource string in the global resource file, after its name,
so that the pure resource string will now be available for reading. so that the pure resource string will now be available for reading.
*/ */
void LCR_seekResourceByIndex(unsigned int index) void LCR_seekResourceByIndex(unsigned int index, char magicNumber)
{ {
char c; char c;
@ -357,11 +358,12 @@ void LCR_seekResourceByIndex(unsigned int index)
while (index) while (index)
{ {
if (c == magicNumber)
index--;
do do
c = LCR_gameGetNextResourceFileChar(); c = LCR_gameGetNextResourceFileChar();
while (c != LCR_RESOURCE_FILE_SEPARATOR && c != 0); while (c != LCR_RESOURCE_FILE_SEPARATOR && c != 0);
index--;
} }
do // skip magic number and name do // skip magic number and name
@ -372,7 +374,7 @@ void LCR_seekResourceByIndex(unsigned int index)
void LCR_gameStartRun(void) void LCR_gameStartRun(void)
{ {
LCR_seekResourceByIndex(0); // TODO LCR_seekResourceByIndex(0,'M'); // TODO
LCR_mapLoadFromStr(LCR_gameGetNextResourceStrChar); LCR_mapLoadFromStr(LCR_gameGetNextResourceStrChar);
LCR_rendererLoadMap(); LCR_rendererLoadMap();
@ -396,13 +398,9 @@ LCR_game.resourceFile.loadedItemCount = 0;
LCR_game.resourceFile.itemsTotal = 0; LCR_game.resourceFile.itemsTotal = 0;
for (int i = 0; i < LCR_RESOURCE_ITEM_CHUNK; ++i) for (int i = 0; i < LCR_RESOURCE_ITEM_CHUNK; ++i)
{
for (int j = 0; j < LCR_MENU_STRING_SIZE; ++j) for (int j = 0; j < LCR_MENU_STRING_SIZE; ++j)
LCR_game.resourceFile.loadedItemNames[i * LCR_MENU_STRING_SIZE + j] = 0; LCR_game.resourceFile.loadedItemNames[i * LCR_MENU_STRING_SIZE + j] = 0;
LCR_game.resourceFile.loadedItemsIndices[i] = 0;
}
LCR_game.menuSelectedTab = 0; LCR_game.menuSelectedTab = 0;
LCR_game.menuSelectedItem = 0; LCR_game.menuSelectedItem = 0;
@ -416,12 +414,76 @@ LCR_game.menuSelectedItem = 0;
} }
/** /**
Loads up to LCR_RESOURCE_ITEM_CHUNK items of given type (0 = map, 1 = replay) Loads up to LCR_RESOURCE_ITEM_CHUNK items of given type, starting at given
into RAM, starting at given index (among items of the same type). index (among items of the same type).
*/ */
void LCR_gameLoadResourceFileChunk(uint8_t type, unsigned int startIndex) void LCR_gameLoadResourceFileChunk(unsigned int startIndex, char magicNumber)
{ {
// TODO LCR_LOG1("loading resources");
char c;
unsigned char state = 0;
for (int i = 0; i < LCR_RESOURCE_ITEM_CHUNK * LCR_MENU_STRING_SIZE; ++i)
LCR_game.resourceFile.loadedItemNames[i] = 0;
LCR_game.resourceFile.loadedItemCount = 0;
LCR_game.resourceFile.firstItemIndex = startIndex;
LCR_game.resourceFile.itemsTotal = 0;
LCR_gameRewindResourceFile();
/* 3 iterations: in first we seek to the start index, in second we load the
names, in third we just read the rest to get the total count. */
for (int i = 0; i < 3; ++i)
while (1)
{
if (i == 0 && !startIndex)
break;
c = LCR_gameGetNextResourceFileChar();
if (c == 0)
return;
if (state == 0) // second magic char
{
state = 255;
if (c == magicNumber)
{
LCR_game.resourceFile.itemsTotal++;
if (i == 0)
startIndex--;
else if (i == 1)
state = 1;
}
}
else if (i == 1 && state != 255)
{
if (c == LCR_RESOURCE_FILE_SEPARATOR2 ||
state >= 1 + LCR_MENU_STRING_SIZE - 1)
{
state = 255;
LCR_game.resourceFile.loadedItemCount++;
if (LCR_game.resourceFile.loadedItemCount >= LCR_RESOURCE_ITEM_CHUNK)
break;
}
LCR_game.resourceFile.loadedItemNames[LCR_MENU_STRING_SIZE *
LCR_game.resourceFile.loadedItemCount + state - 1] = c;
state++;
}
if (c == LCR_RESOURCE_FILE_SEPARATOR)
state = 0;
}
} }
void LCR_gameEnd(void) void LCR_gameEnd(void)
@ -512,10 +574,119 @@ void LCR_gameDraw3DView(void)
} }
} }
void LCR_gameHandleInput(void)
{
int tabSwitchedTo = 0;
int scrolled = 0;
switch (LCR_game.state)
{
case LCR_GAME_STATE_MENU:
if (LCR_game.keyStates[LCR_KEY_RIGHT] == 1)
{
LCR_LOG1("menu tab right");
LCR_game.menuSelectedTab =
(LCR_game.menuSelectedTab + 1) % LCR_MENU_TABS;
tabSwitchedTo = LCR_game.menuSelectedTab;
LCR_game.menuSelectedItem = 0;
}
else if (LCR_game.keyStates[LCR_KEY_LEFT] == 1)
{
LCR_LOG1("menu tab left");
LCR_game.menuSelectedTab =
(LCR_game.menuSelectedTab + LCR_MENU_TABS - 1) % LCR_MENU_TABS;
tabSwitchedTo = LCR_game.menuSelectedTab;
LCR_game.menuSelectedItem = 0;
}
else if (LCR_game.keyStates[LCR_KEY_UP] == 1)
{
LCR_LOG1("menu item up");
if (LCR_game.menuSelectedItem != 0)
LCR_game.menuSelectedItem--;
else if (LCR_game.menuSelectedTab != 0 &&
LCR_game.resourceFile.firstItemIndex != 0)
{
LCR_game.menuSelectedItem = LCR_RESOURCE_ITEM_CHUNK - 1;
scrolled = -1;
}
}
else if (LCR_game.keyStates[LCR_KEY_DOWN] == 1)
{
LCR_LOG1("menu item down");
if (LCR_game.menuSelectedTab == 0)
{
if (LCR_game.menuSelectedItem < 4)
LCR_game.menuSelectedItem++;
}
else if (LCR_game.menuSelectedItem <
LCR_game.resourceFile.loadedItemCount - 1)
LCR_game.menuSelectedItem++;
else if (LCR_game.resourceFile.firstItemIndex +
LCR_RESOURCE_ITEM_CHUNK < LCR_game.resourceFile.itemsTotal)
{
LCR_game.menuSelectedItem = 0;
scrolled = 1;
}
}
else if (LCR_game.keyStates[LCR_KEY_B] == 1)
{
LCR_LOG1("menu quit");
LCR_gameSetState(LCR_GAME_STATE_RUN);
}
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
{
LCR_LOG1("menu confirm");
switch (LCR_game.menuSelectedTab)
{
case 0:
switch (LCR_game.menuSelectedItem)
{
case 4:
LCR_gameSetState(LCR_GAME_STATE_END);
break;
default: break;
}
break;
default: break;
}
}
break;
case LCR_GAME_STATE_RUN_STARTING:
if (LCR_game.time - LCR_game.stateStartTime
>= 1000 * LCR_SETTING_COUNTDOWN_SECONDS)
LCR_gameSetState(LCR_GAME_STATE_RUN);
// fall through
default:
if (LCR_game.keyStates[LCR_KEY_B] == 1)
{
LCR_LOG1("menu open");
LCR_gameSetState(LCR_GAME_STATE_MENU);
}
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
LCR_gameResetRun();
break;
}
if (tabSwitchedTo)
LCR_gameLoadResourceFileChunk(0,tabSwitchedTo == 1 ? 'M' : 'R');
}
uint8_t LCR_gameStep(uint32_t time) uint8_t LCR_gameStep(uint32_t time)
{ {
uint32_t sleep = 0; uint32_t sleep = 0;
int paused = 0; int paused =
LCR_game.state == LCR_GAME_STATE_MENU ||
LCR_game.state == LCR_GAME_STATE_RUN_STARTING;
LCR_LOG2("game step start"); LCR_LOG2("game step start");
@ -525,71 +696,7 @@ uint8_t LCR_gameStep(uint32_t time)
LCR_game.keyStates[i] = LCR_keyPressed(i) ? LCR_game.keyStates[i] = LCR_keyPressed(i) ?
(LCR_game.keyStates[i] < 255 ? LCR_game.keyStates[i] + 1 : 255) : 0; (LCR_game.keyStates[i] < 255 ? LCR_game.keyStates[i] + 1 : 255) : 0;
switch (LCR_game.state) LCR_gameHandleInput();
{
case LCR_GAME_STATE_MENU:
paused = 1;
if (LCR_game.keyStates[LCR_KEY_RIGHT] == 1)
{
LCR_LOG1("menu tab right");
LCR_game.menuSelectedTab =
(LCR_game.menuSelectedTab + 1) % LCR_MENU_TABS;
LCR_game.menuSelectedItem = 0;
}
else if (LCR_game.keyStates[LCR_KEY_LEFT] == 1)
{
LCR_LOG1("menu tab left");
LCR_game.menuSelectedTab =
(LCR_game.menuSelectedTab + LCR_MENU_TABS - 1) % LCR_MENU_TABS;
LCR_game.menuSelectedItem = 0;
}
else if (LCR_game.keyStates[LCR_KEY_UP] == 1)
{
LCR_LOG1("menu item up");
LCR_game.menuSelectedItem -= LCR_game.menuSelectedItem ? 1 : 0;
}
else if (LCR_game.keyStates[LCR_KEY_DOWN] == 1)
{
LCR_LOG1("menu item down");
LCR_game.menuSelectedItem +=
(LCR_game.menuSelectedItem < (LCR_game.menuSelectedTab ?
LCR_game.resourceFile.loadedItemCount : 5) - 1) ? 1 : 0;
}
else if (LCR_game.keyStates[LCR_KEY_B] == 1)
{
LCR_LOG1("menu quit");
LCR_gameSetState(LCR_GAME_STATE_RUN);
}
break;
case LCR_GAME_STATE_RUN_STARTING:
paused = 1;
if (LCR_game.time - LCR_game.stateStartTime
>= 1000 * LCR_SETTING_COUNTDOWN_SECONDS)
LCR_gameSetState(LCR_GAME_STATE_RUN);
// fall through
default:
if (LCR_game.keyStates[LCR_KEY_B] == 1)
LCR_gameSetState(LCR_GAME_STATE_MENU);
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
LCR_gameResetRun();
break;
}
/*
if (LCR_game.keyStates[LCR_KEY_B] == 1)
LCR_game.controlMode = LCR_game.controlMode == LCR_CONTROL_MODE_FREECAM ?
LCR_CONTROL_MODE_DRIVE : LCR_CONTROL_MODE_FREECAM;
else if (LCR_game.keyStates[LCR_KEY_B] == 30)
LCR_gameResetRun();
*/
LCR_GameUnit offsets[5]; LCR_GameUnit offsets[5];
@ -627,7 +734,6 @@ uint8_t LCR_gameStep(uint32_t time)
} }
*/ */
// handle simulation: // handle simulation:
while (time >= LCR_game.nextRacingTickTime) while (time >= LCR_game.nextRacingTickTime)
{ {
@ -690,17 +796,20 @@ uint8_t LCR_gameStep(uint32_t time)
items[0] = LCR_texts[LCR_game.menuSelectedTab]; items[0] = LCR_texts[LCR_game.menuSelectedTab];
switch (LCR_game.menuSelectedTab) if (LCR_game.menuSelectedTab == 0)
{ {
case 0: for (int i = 0; i < 5; ++i)
for (int i = 0; i < 5; ++i) items[1 + i] = LCR_texts[4 + i];
items[1 + i] = LCR_texts[4 + i];
itemCount = 6; itemCount = 6;
break; }
else
{
for (int i = 0; i < LCR_game.resourceFile.loadedItemCount; ++i)
items[i + 1] = LCR_game.resourceFile.loadedItemNames + i * LCR_MENU_STRING_SIZE;
default: break; itemCount = LCR_game.resourceFile.loadedItemCount + 1;
} }
LCR_rendererDrawMenu(items,itemCount,LCR_game.menuSelectedItem); LCR_rendererDrawMenu(items,itemCount,LCR_game.menuSelectedItem);
} }
@ -723,7 +832,7 @@ uint8_t LCR_gameStep(uint32_t time)
LCR_game.frame++; LCR_game.frame++;
LCR_LOG2("game step end"); LCR_LOG2("game step end");
return 1; return LCR_game.state != LCR_GAME_STATE_END;
} }
uint8_t LCR_gameGetNextAudioSample(void) uint8_t LCR_gameGetNextAudioSample(void)