Add click sound

This commit is contained in:
Miloslav Ciz 2025-01-07 20:01:36 +01:00
parent 5d30b9d600
commit a9f0a6885a
3 changed files with 86 additions and 42 deletions

View file

@ -2,10 +2,57 @@
- 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.
- maybe each map could have a target time embedded: when beaten, the map would
be marked as such
- player name (modifyable via resource file) - player name (modifyable via resource file)
- popup messages? would be useful for several things: showing checkpoint times, - popup messages? would be useful for several things: showing checkpoint times,
showing changes in menu etc. showing changes in menu etc.
- prevent time overflow! stop incrementing level frame once it's at maximum - prevent time overflow! stop incrementing level frame once it's at maximum
- make the racing module usable by itself, e.g. to allow making tools for
verifying replays etc., i.e. make the module measure time, count checkpoints
etc.
- allow slowing down in air like in TM?
- compile time option to choose how many maps to include (for platforms with
lower memory)
- at the end check error handling, make sure the game handles garbage data in
resource file etc.
- replay format
=========== BUGS =================
- drawing dithered transparent objects fills z-buffer in the transparent parts
and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW
=========== HANDLED ==============
- allow stopping car rotation in air like in Trackmania
- car shadow? probably would have to be done as screen space effect with
z-buffer (shadow as 3D model would require collision detection and would make
renderer depend on physics engine). Maybe like this:
- project some point below the car to screen
- fill a dithered oval around this point, but only as long as the point's
Z coord is close to the value in Z-buffer
^ PROBABLY NOT, tried it and looked weird
- music?
- probably just make one long track, literally OGG or something, then make
that be played by the frontend just ALL the time (maybe with the option in
menu to just turn music off) -- simple frontends can just ignore music
- sound engine: probably all SFX will be procedurally generated, ok?
- make a simple rendering setting:
- will exclude images and only draw solid colors, let's say only 16, so that
memory usage is reduced, CPU rendering is relieved, executable is smaller
AND frontend doesn't have to use RGB565 (it can basically choose any mode).
- drifting: passing some upper threshold on steering force should reduce
steering friction until reaching some some lower threshold again probably
- Environments: just different textures for a cube inside which the tarck is,
the cube won't have the top side, texture can have transparency (sky see
through) <-- NO
- UPDATE: tho rasterization of the big cube could take whole screen: too slow.
Maybe just have a model + texture for each env? (still could allow transp).
- OR: environment could just be a sky texture (or just sky color?) plus a
floor texture? pretty KISS. SKY DOESN'T HAVE TO BE SPHERICALLY MAPPED, it
can simply rotate horizontally and shift vertically (camera will never
roll) -- not accurate but good enough. <-- YES
- asset system: - asset system:
- assets are to be loaded from one BIG string consisting of substrings, each - assets are to be loaded from one BIG string consisting of substrings, each
substring adds a map, replay, setting etc. substring adds a map, replay, setting etc.
@ -27,43 +74,6 @@
- map hash - map hash
- data: frame, input state - data: frame, input state
- record time: decimal time in ms - record time: decimal time in ms
- make the racing module usable by itself, e.g. to allow making tools for
verifying replays etc., i.e. make the module measure time, count checkpoints
etc.
- car shadow?
- allow slowing down in air like in TM?
- compile time option to choose how many maps to include (for platforms with
lower memory)
- Environments: just different textures for a cube inside which the tarck is,
the cube won't have the top side, texture can have transparency (sky see
through) <-- NO
- UPDATE: tho rasterization of the big cube could take whole screen: too slow.
Maybe just have a model + texture for each env? (still could allow transp).
- OR: environment could just be a sky texture (or just sky color?) plus a
floor texture? pretty KISS. SKY DOESN'T HAVE TO BE SPHERICALLY MAPPED, it
can simply rotate horizontally and shift vertically (camera will never
roll) -- not accurate but good enough. <-- YES
- replay format
=========== BUGS =================
- drawing dithered transparent objects fills z-buffer in the transparent parts
and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW
=========== HANDLED ==============
- allow stopping car rotation in air like in Trackmania
- music?
- probably just make one long track, literally OGG or something, then make
that be played by the frontend just ALL the time (maybe with the option in
menu to just turn music off) -- simple frontends can just ignore music
- sound engine: probably all SFX will be procedurally generated, ok?
- make a simple rendering setting:
- will exclude images and only draw solid colors, let's say only 16, so that
memory usage is reduced, CPU rendering is relieved, executable is smaller
AND frontend doesn't have to use RGB565 (it can basically choose any mode).
- drifting: passing some upper threshold on steering force should reduce
steering friction until reaching some some lower threshold again probably
- maybe allow some more air control, like slowing down with brakes, like in TM - maybe allow some more air control, like slowing down with brakes, like in TM
- map actually in ASCII format? how will humans edit it? - map actually in ASCII format? how will humans edit it?
- racing update step should return events that happened, e.g.: - racing update step should return events that happened, e.g.:

18
audio.h
View file

@ -97,6 +97,24 @@ uint8_t LCR_audioGetNextSample(void)
break; break;
} }
case LCR_SOUND_CLICK:
{
int v = ((LCR_audio.soundPlayedFrame >> 6) *
(LCR_audio.soundPlayedFrame >> 1)
+ LCR_audio.soundPlayedFrame * 35) & 0x1c;
if (LCR_audio.soundPlayedFrame < 250)
result = v;
else if (LCR_audio.soundPlayedFrame < 400)
result = (v + 128) / 2;
else if (LCR_audio.soundPlayedFrame < 600)
result = (v + 3 * 128) / 4;
else
LCR_audio.soundPlayed = LCR_SOUND_NONE;
break;
}
default: default:
break; break;
} }

26
game.h
View file

@ -574,7 +574,7 @@ void LCR_gameDraw3DView(void)
LCR_rendererDrawText(str, LCR_rendererDrawText(str,
(LCR_EFFECTIVE_RESOLUTION_X - LCR_rendererComputeTextWidth(str,8)) / 2, (LCR_EFFECTIVE_RESOLUTION_X - LCR_rendererComputeTextWidth(str,8)) / 2,
LCR_EFFECTIVE_RESOLUTION_Y / 2,0x0707,8); LCR_EFFECTIVE_RESOLUTION_Y / 2,0x0707,8);
break; break;
default: default:
@ -630,6 +630,7 @@ void LCR_gameHandleInput(void)
(LCR_game.menuSelectedTab + 1) % LCR_MENU_TABS; (LCR_game.menuSelectedTab + 1) % LCR_MENU_TABS;
tabSwitchedTo = LCR_game.menuSelectedTab; tabSwitchedTo = LCR_game.menuSelectedTab;
LCR_game.menuSelectedItem = 0; LCR_game.menuSelectedItem = 0;
LCR_audioPlaySound(LCR_SOUND_CLICK);
} }
else if (LCR_game.keyStates[LCR_KEY_LEFT] == 1) else if (LCR_game.keyStates[LCR_KEY_LEFT] == 1)
{ {
@ -638,17 +639,22 @@ void LCR_gameHandleInput(void)
(LCR_game.menuSelectedTab + LCR_MENU_TABS - 1) % LCR_MENU_TABS; (LCR_game.menuSelectedTab + LCR_MENU_TABS - 1) % LCR_MENU_TABS;
tabSwitchedTo = LCR_game.menuSelectedTab; tabSwitchedTo = LCR_game.menuSelectedTab;
LCR_game.menuSelectedItem = 0; LCR_game.menuSelectedItem = 0;
LCR_audioPlaySound(LCR_SOUND_CLICK);
} }
else if (LCR_game.keyStates[LCR_KEY_UP] == 1) else if (LCR_game.keyStates[LCR_KEY_UP] == 1)
{ {
LCR_LOG1("menu item up"); LCR_LOG1("menu item up");
if (LCR_game.menuSelectedItem != 0) if (LCR_game.menuSelectedItem != 0)
{
LCR_game.menuSelectedItem--; LCR_game.menuSelectedItem--;
LCR_audioPlaySound(LCR_SOUND_CLICK);
}
else if (LCR_game.menuSelectedTab != 0 && else if (LCR_game.menuSelectedTab != 0 &&
LCR_game.resourceFile.firstItemIndex != 0) LCR_game.resourceFile.firstItemIndex != 0)
{ {
LCR_game.menuSelectedItem = LCR_RESOURCE_ITEM_CHUNK - 1; LCR_game.menuSelectedItem = LCR_RESOURCE_ITEM_CHUNK - 1;
LCR_audioPlaySound(LCR_SOUND_CLICK);
scrolled = -1; scrolled = -1;
} }
} }
@ -659,14 +665,21 @@ void LCR_gameHandleInput(void)
if (LCR_game.menuSelectedTab == 0) if (LCR_game.menuSelectedTab == 0)
{ {
if (LCR_game.menuSelectedItem < 4) if (LCR_game.menuSelectedItem < 4)
{
LCR_game.menuSelectedItem++; LCR_game.menuSelectedItem++;
LCR_audioPlaySound(LCR_SOUND_CLICK);
}
} }
else if (LCR_game.menuSelectedItem < LCR_game.menuItemCount - 1) else if (LCR_game.menuSelectedItem < LCR_game.menuItemCount - 1)
{
LCR_game.menuSelectedItem++; LCR_game.menuSelectedItem++;
LCR_audioPlaySound(LCR_SOUND_CLICK);
}
else if (LCR_game.resourceFile.firstItemIndex + else if (LCR_game.resourceFile.firstItemIndex +
LCR_RESOURCE_ITEM_CHUNK < LCR_game.resourceFile.itemsTotal) LCR_RESOURCE_ITEM_CHUNK < LCR_game.resourceFile.itemsTotal)
{ {
LCR_game.menuSelectedItem = 0; LCR_game.menuSelectedItem = 0;
LCR_audioPlaySound(LCR_SOUND_CLICK);
scrolled = 1; scrolled = 1;
} }
} }
@ -678,6 +691,7 @@ void LCR_gameHandleInput(void)
else if (LCR_game.keyStates[LCR_KEY_A] == 1) else if (LCR_game.keyStates[LCR_KEY_A] == 1)
{ {
LCR_LOG1("menu confirm"); LCR_LOG1("menu confirm");
LCR_audioPlaySound(LCR_SOUND_CLICK);
switch (LCR_game.menuSelectedTab) switch (LCR_game.menuSelectedTab)
{ {
@ -742,8 +756,6 @@ void LCR_gameHandleInput(void)
(tabSwitchedTo > 0) ? 0 : (LCR_game.resourceFile.firstItemIndex + (tabSwitchedTo > 0) ? 0 : (LCR_game.resourceFile.firstItemIndex +
scrolled * LCR_RESOURCE_ITEM_CHUNK), scrolled * LCR_RESOURCE_ITEM_CHUNK),
LCR_game.menuSelectedTab == 1 ? 'M' : 'R'); LCR_game.menuSelectedTab == 1 ? 'M' : 'R');
} }
uint8_t LCR_gameStep(uint32_t time) uint8_t LCR_gameStep(uint32_t time)
@ -827,10 +839,12 @@ uint8_t LCR_gameStep(uint32_t time)
LCR_racingGetCarBlockCoords(carBlock); LCR_racingGetCarBlockCoords(carBlock);
LCR_LOG1("CP taken"); LCR_LOG1("CP taken");
LCR_rendererMarkTakenCP(carBlock[0],carBlock[1],carBlock[2]); LCR_rendererMarkTakenCP(carBlock[0],carBlock[1],carBlock[2]);
LCR_audioPlaySound(LCR_SOUND_CLICK);
} }
else if (events & LCR_RACING_EVENT_FINISHED) else if (events & LCR_RACING_EVENT_FINISHED)
{ {
LCR_LOG1("finished"); LCR_LOG1("finished");
LCR_audioPlaySound(LCR_SOUND_CLICK);
} }
if (events & LCR_RACING_EVENT_CRASH_SMALL) if (events & LCR_RACING_EVENT_CRASH_SMALL)
@ -877,11 +891,13 @@ uint8_t LCR_gameStep(uint32_t time)
if (LCR_game.state == LCR_GAME_STATE_LOADING_MAP) if (LCR_game.state == LCR_GAME_STATE_LOADING_MAP)
{ {
// show the "loading" screen
LCR_rendererDrawRect( LCR_rendererDrawRect(
LCR_EFFECTIVE_RESOLUTION_X / 8, LCR_EFFECTIVE_RESOLUTION_X / 8,
LCR_EFFECTIVE_RESOLUTION_Y / 8, LCR_EFFECTIVE_RESOLUTION_Y / 3,
LCR_EFFECTIVE_RESOLUTION_X - LCR_EFFECTIVE_RESOLUTION_X / 4, LCR_EFFECTIVE_RESOLUTION_X - LCR_EFFECTIVE_RESOLUTION_X / 4,
LCR_EFFECTIVE_RESOLUTION_Y - LCR_EFFECTIVE_RESOLUTION_Y / 4, LCR_EFFECTIVE_RESOLUTION_Y - 2 * LCR_EFFECTIVE_RESOLUTION_Y / 3,
0xffff,0); 0xffff,0);
LCR_rendererDrawText(LCR_texts[9], LCR_rendererDrawText(LCR_texts[9],