Add map beating
This commit is contained in:
parent
2172fcedd1
commit
ea105ba3f3
6 changed files with 119 additions and 18 deletions
26
TODO.txt
26
TODO.txt
|
@ -1,13 +1,19 @@
|
||||||
=========== GENERAL ==============
|
=========== GENERAL ==============
|
||||||
|
|
||||||
- make a small txt game menual
|
- make a small txt game menual
|
||||||
- test if the replay stretching works
|
- test:
|
||||||
|
- long replay
|
||||||
|
- replay stretching works
|
||||||
|
- replay with input not occuring for more that LCR_SETTING_GHOST_STEP
|
||||||
- replay validation
|
- replay validation
|
||||||
- ghosts: if the replay for the ghost is too long (too many samples for the
|
|
||||||
preallocated array), we can subdivide the sample resolution (i.e. "stretch"
|
|
||||||
the samples) to cover the whole replay (ofc for the price of worse quality).
|
|
||||||
- add argc/argv to gameInit? could be used to quickly start maps, verify
|
- add argc/argv to gameInit? could be used to quickly start maps, verify
|
||||||
replays etc.
|
replays etc. Options:
|
||||||
|
-sN: sound (0/1)
|
||||||
|
-mN: music (0/1)
|
||||||
|
-cN: set camera
|
||||||
|
-M: load last map in resource files (good for making maps)
|
||||||
|
-R: load last replay in resource files (good for making TASes)
|
||||||
|
-P: load and play against last replay in resource files
|
||||||
- maybe each map could have a target time embedded: when beaten, the map would
|
- maybe each map could have a target time embedded: when beaten, the map would
|
||||||
be marked as such
|
be marked as such
|
||||||
- player name (modifiable via resource file)
|
- player name (modifiable via resource file)
|
||||||
|
@ -24,13 +30,15 @@
|
||||||
|
|
||||||
=========== BUGS =================
|
=========== BUGS =================
|
||||||
|
|
||||||
- starting test replay two twice in a row breaks it
|
|
||||||
- drawing dithered transparent objects fills z-buffer in the transparent parts
|
|
||||||
and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW
|
|
||||||
|
|
||||||
=========== HANDLED ==============
|
=========== HANDLED ==============
|
||||||
|
|
||||||
- allow stopping car rotation in air like in Trackmania
|
- allow stopping car rotation in air like in Trackmania
|
||||||
|
- drawing dithered transparent objects fills z-buffer in the transparent parts
|
||||||
|
and then the geometry behind it isn't drawn <- PARTIALLY FIXED, LOOKS GOOD
|
||||||
|
- starting test replay two twice in a row breaks it
|
||||||
|
- ghosts: if the replay for the ghost is too long (too many samples for the
|
||||||
|
preallocated array), we can subdivide the sample resolution (i.e. "stretch"
|
||||||
|
the samples) to cover the whole replay (ofc for the price of worse quality).
|
||||||
- force chunk reload upon map restart so that there's no blinking at start
|
- force chunk reload upon map restart so that there's no blinking at start
|
||||||
- ghost visible distance -- maybe even car should have this (watching rep with
|
- ghost visible distance -- maybe even car should have this (watching rep with
|
||||||
free camera)? maybe generalize setCar/GhostVisibility to
|
free camera)? maybe generalize setCar/GhostVisibility to
|
||||||
|
|
1
assets.h
1
assets.h
|
@ -172,6 +172,7 @@ uint16_t LCR_getFontChar(char c)
|
||||||
case '_': _F( 8,10,10,10,10,10,10,10,10,10)
|
case '_': _F( 8,10,10,10,10,10,10,10,10,10)
|
||||||
case '|': _F( 5, 7, 7, 7, 7, 7, 7, 7, 7, 7)
|
case '|': _F( 5, 7, 7, 7, 7, 7, 7, 7, 7, 7)
|
||||||
case '=': _F( 4, 6, 0, 2, 2, 2, 2, 2, 2, 2)
|
case '=': _F( 4, 6, 0, 2, 2, 2, 2, 2, 2, 2)
|
||||||
|
case '#': _F( 5, 7,14,14,14,14,14,14,14,14) // used for "check"
|
||||||
default: return 0; break;
|
default: return 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
data
2
data
|
@ -1,2 +1,4 @@
|
||||||
#Mmap2;4321 1 :*H1k0J :,s0s0 :fd190
|
#Mmap2;4321 1 :*H1k0J :,s0s0 :fd190
|
||||||
|
#Bnomap
|
||||||
#Rrep2;testmap;482f70f9 00000843:0173:0081:0029:0111:0039:0071:00a3:0061:0169:0051:00b3:0041:0073:0081:0033:0041:0033:0231:0030:0098:0029:0011:0163:00f1:0053:0081:0033:0051:0023:0031:00f0:0032:0023:0131:00b9:0081:0023:00a1:0119:00e1:00c9:0071:0039:00a1:00d3:0021:01f9:0091:0079:0091:0039:0051:0049:0021:0083:0031:0083:0031:0083:0061:0089:0121:00a0:0058:002c:0048:0061:0013:0150:0052:00c0:00a1:0053:0041:0043:0031:0020:0092:0063:0181:0010:00a2:0013:0071:00e0:0028:00e9:0078:00a9:0043:0032:0123:0042:0080:0038:004c:01a8:0050:0032:0033:0101
|
#Rrep2;testmap;482f70f9 00000843:0173:0081:0029:0111:0039:0071:00a3:0061:0169:0051:00b3:0041:0073:0081:0033:0041:0033:0231:0030:0098:0029:0011:0163:00f1:0053:0081:0033:0051:0023:0031:00f0:0032:0023:0131:00b9:0081:0023:00a1:0119:00e1:00c9:0071:0039:00a1:00d3:0021:01f9:0091:0079:0091:0039:0051:0049:0021:0083:0031:0083:0031:0083:0061:0089:0121:00a0:0058:002c:0048:0061:0013:0150:0052:00c0:00a1:0053:0041:0043:0031:0020:0092:0063:0181:0010:00a2:0013:0071:00e0:0028:00e9:0078:00a9:0043:0032:0123:0042:0080:0038:004c:01a8:0050:0032:0033:0101
|
||||||
|
#Btestmap;
|
||||||
|
|
67
game.h
67
game.h
|
@ -838,13 +838,71 @@ void LCR_gameLoadDataFileChunk(unsigned int startIndex, char magicNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Assumes maps are loaded in menu items, checks (in the resource file) which
|
||||||
|
ones have been marked as beaten and marks corresponding menu items as such.
|
||||||
|
*/
|
||||||
|
void LCR_checkBeatenMaps(void)
|
||||||
|
{
|
||||||
|
LCR_LOG2("checking beaten maps");
|
||||||
|
|
||||||
|
char name[LCR_MAP_NAME_MAX_LEN + 1];
|
||||||
|
LCR_gameRewindDataFile();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char c = LCR_gameGetNextDataFileChar();
|
||||||
|
|
||||||
|
if (c == 'B')
|
||||||
|
{
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
while (i < LCR_MAP_NAME_MAX_LEN + 1)
|
||||||
|
{
|
||||||
|
c = LCR_gameGetNextDataFileChar();
|
||||||
|
|
||||||
|
if (c < ' ' || c == LCR_RESOURCE_FILE_SEPARATOR ||
|
||||||
|
c == LCR_RESOURCE_FILE_SEPARATOR2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
name[i] = c;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
name[i] = 0;
|
||||||
|
|
||||||
|
for (uint8_t j = 0; j < LCR_game.menu.itemCount; ++j)
|
||||||
|
if (_LCR_strCmp(name,LCR_game.menu.itemNamePtrs[j]))
|
||||||
|
{
|
||||||
|
for (uint8_t k = 0; k < LCR_MENU_STRING_SIZE; ++k)
|
||||||
|
if (LCR_game.menu.itemNames[j][k] == 0)
|
||||||
|
{
|
||||||
|
LCR_game.menu.itemNames[j]
|
||||||
|
[k - (k == LCR_MENU_STRING_SIZE - 1)] = '#';
|
||||||
|
LCR_game.menu.itemNames[j]
|
||||||
|
[k + (k != LCR_MENU_STRING_SIZE - 1)] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
while (c != 0 && c != LCR_RESOURCE_FILE_SEPARATOR)
|
||||||
|
c = LCR_gameGetNextDataFileChar();
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LCR_gameEnd(void)
|
void LCR_gameEnd(void)
|
||||||
{
|
{
|
||||||
LCR_LOG0("ending");
|
LCR_LOG0("ending");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LCR_gameTimeToStr(uint32_t timeMS, char *str)
|
void LCR_gameTimeToStr(uint32_t timeMS, char *str)
|
||||||
{
|
{
|
||||||
str[9] = 0;
|
str[9] = 0;
|
||||||
|
@ -1168,10 +1226,15 @@ void LCR_gameHandleInput(void)
|
||||||
if (tabSwitchedTo == 0)
|
if (tabSwitchedTo == 0)
|
||||||
LCR_gameLoadMainMenuItems();
|
LCR_gameLoadMainMenuItems();
|
||||||
else if (tabSwitchedTo > 0 || scrolled != 0)
|
else if (tabSwitchedTo > 0 || scrolled != 0)
|
||||||
|
{
|
||||||
LCR_gameLoadDataFileChunk(
|
LCR_gameLoadDataFileChunk(
|
||||||
(tabSwitchedTo > 0) ? 0 : (LCR_game.dataFile.firstItemIndex +
|
(tabSwitchedTo > 0) ? 0 : (LCR_game.dataFile.firstItemIndex +
|
||||||
scrolled * LCR_RESOURCE_ITEM_CHUNK),
|
scrolled * LCR_RESOURCE_ITEM_CHUNK),
|
||||||
LCR_game.menu.selectedTab == 1 ? 'M' : 'R');
|
LCR_game.menu.selectedTab == 1 ? 'M' : 'R');
|
||||||
|
|
||||||
|
if (LCR_game.menu.selectedTab == 1)
|
||||||
|
LCR_checkBeatenMaps();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t LCR_gameStep(uint32_t time)
|
uint8_t LCR_gameStep(uint32_t time)
|
||||||
|
|
17
general.h
17
general.h
|
@ -66,4 +66,21 @@ uint16_t _LCR_simpleStrHash(char (*nextChar)(void), char endChar)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _LCR_strCmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (*s1 != *s2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (*s1 == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|
24
renderer.h
24
renderer.h
|
@ -1789,8 +1789,8 @@ void LCR_rendererBlitImage(uint8_t index, unsigned int x, unsigned int y,
|
||||||
void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
||||||
unsigned char itemCount,char selectedItem)
|
unsigned char itemCount,char selectedItem)
|
||||||
{
|
{
|
||||||
int stripHeight = LCR_EFFECTIVE_RESOLUTION_Y / 4;
|
int stripHeight = (2 * LCR_EFFECTIVE_RESOLUTION_Y) / 7;
|
||||||
int stripHeight2 = LCR_EFFECTIVE_RESOLUTION_Y / 10;
|
int stripHeight2 = LCR_EFFECTIVE_RESOLUTION_Y / 9;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint16_t effect = LCR_renderer.frame >> 1;
|
uint16_t effect = LCR_renderer.frame >> 1;
|
||||||
|
|
||||||
|
@ -1798,13 +1798,13 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
||||||
|
|
||||||
while (i < stripHeight * LCR_EFFECTIVE_RESOLUTION_X)
|
while (i < stripHeight * LCR_EFFECTIVE_RESOLUTION_X)
|
||||||
{
|
{
|
||||||
LCR_drawPixel(i,0xd69b
|
LCR_drawPixel(i,0x4a8c
|
||||||
#if LCR_SETTING_POTATO_GRAPHICS
|
#if LCR_SETTING_POTATO_GRAPHICS
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
^ (effect & 0x18e3));
|
^ (effect & 0x1827));
|
||||||
|
|
||||||
effect += 7;
|
effect += 3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
|
@ -1850,6 +1850,16 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
||||||
for (int j = 0; j < itemCount + 1; ++j)
|
for (int j = 0; j < itemCount + 1; ++j)
|
||||||
{
|
{
|
||||||
const char *s = j ? items[j - 1] : tabName;
|
const char *s = j ? items[j - 1] : tabName;
|
||||||
|
const char *s2 = s;
|
||||||
|
uint16_t textColor = 0x5aeb;
|
||||||
|
|
||||||
|
while (*s2) // if the item contains '#' (check), we draw it as green
|
||||||
|
{
|
||||||
|
if (*s2 == '#')
|
||||||
|
textColor = 0x0700;
|
||||||
|
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
|
||||||
if (j == selectedItem + 1)
|
if (j == selectedItem + 1)
|
||||||
for (int y = i - 10; y < i + LCR_rendererComputeTextHeight(3) + 10; ++y)
|
for (int y = i - 10; y < i + LCR_rendererComputeTextHeight(3) + 10; ++y)
|
||||||
|
@ -1859,7 +1869,7 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
||||||
|
|
||||||
LCR_rendererDrawText(s,(LCR_EFFECTIVE_RESOLUTION_X -
|
LCR_rendererDrawText(s,(LCR_EFFECTIVE_RESOLUTION_X -
|
||||||
LCR_rendererComputeTextWidth(s,3)) / 2,i,
|
LCR_rendererComputeTextWidth(s,3)) / 2,i,
|
||||||
(j == 0 || j == selectedItem + 1) ? 0xf79c : 0x5aeb,3);
|
(j == 0 || j == selectedItem + 1) ? 0xf79c : textColor,3);
|
||||||
|
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
i = stripHeight + stripHeight2;
|
i = stripHeight + stripHeight2;
|
||||||
|
@ -1873,7 +1883,7 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
|
||||||
stripHeight / LCR_IMAGE_SIZE,0xffff);
|
stripHeight / LCR_IMAGE_SIZE,0xffff);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LCR_rendererDrawText(LCR_texts[LCR_TEXTS_VERSION],5,5,0xffff,2);
|
LCR_rendererDrawText(LCR_texts[LCR_TEXTS_VERSION],5,5,0xe71c,2);
|
||||||
|
|
||||||
LCR_renderer.frame++;
|
LCR_renderer.frame++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue