diff --git a/TODO.txt b/TODO.txt index 1307d3f..7fb3c44 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,10 +2,57 @@ - add argc/argv to gameInit? could be used to quickly start maps, verify 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) - popup messages? would be useful for several things: showing checkpoint times, showing changes in menu etc. - 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: - assets are to be loaded from one BIG string consisting of substrings, each substring adds a map, replay, setting etc. @@ -27,43 +74,6 @@ - map hash - data: frame, input state - 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 - map actually in ASCII format? how will humans edit it? - racing update step should return events that happened, e.g.: diff --git a/audio.h b/audio.h index 63b7ccf..33179a2 100644 --- a/audio.h +++ b/audio.h @@ -97,6 +97,24 @@ uint8_t LCR_audioGetNextSample(void) 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: break; } diff --git a/game.h b/game.h index ff4ff8a..8da7d29 100644 --- a/game.h +++ b/game.h @@ -574,7 +574,7 @@ void LCR_gameDraw3DView(void) LCR_rendererDrawText(str, (LCR_EFFECTIVE_RESOLUTION_X - LCR_rendererComputeTextWidth(str,8)) / 2, - LCR_EFFECTIVE_RESOLUTION_Y / 2,0x0707,8); + LCR_EFFECTIVE_RESOLUTION_Y / 2,0x0707,8); break; default: @@ -630,6 +630,7 @@ void LCR_gameHandleInput(void) (LCR_game.menuSelectedTab + 1) % LCR_MENU_TABS; tabSwitchedTo = LCR_game.menuSelectedTab; LCR_game.menuSelectedItem = 0; + LCR_audioPlaySound(LCR_SOUND_CLICK); } 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; tabSwitchedTo = LCR_game.menuSelectedTab; LCR_game.menuSelectedItem = 0; + LCR_audioPlaySound(LCR_SOUND_CLICK); } else if (LCR_game.keyStates[LCR_KEY_UP] == 1) { LCR_LOG1("menu item up"); if (LCR_game.menuSelectedItem != 0) + { LCR_game.menuSelectedItem--; + LCR_audioPlaySound(LCR_SOUND_CLICK); + } else if (LCR_game.menuSelectedTab != 0 && LCR_game.resourceFile.firstItemIndex != 0) { LCR_game.menuSelectedItem = LCR_RESOURCE_ITEM_CHUNK - 1; + LCR_audioPlaySound(LCR_SOUND_CLICK); scrolled = -1; } } @@ -659,14 +665,21 @@ void LCR_gameHandleInput(void) if (LCR_game.menuSelectedTab == 0) { if (LCR_game.menuSelectedItem < 4) + { LCR_game.menuSelectedItem++; + LCR_audioPlaySound(LCR_SOUND_CLICK); + } } else if (LCR_game.menuSelectedItem < LCR_game.menuItemCount - 1) + { LCR_game.menuSelectedItem++; + LCR_audioPlaySound(LCR_SOUND_CLICK); + } else if (LCR_game.resourceFile.firstItemIndex + LCR_RESOURCE_ITEM_CHUNK < LCR_game.resourceFile.itemsTotal) { LCR_game.menuSelectedItem = 0; + LCR_audioPlaySound(LCR_SOUND_CLICK); scrolled = 1; } } @@ -678,6 +691,7 @@ void LCR_gameHandleInput(void) else if (LCR_game.keyStates[LCR_KEY_A] == 1) { LCR_LOG1("menu confirm"); + LCR_audioPlaySound(LCR_SOUND_CLICK); switch (LCR_game.menuSelectedTab) { @@ -742,8 +756,6 @@ void LCR_gameHandleInput(void) (tabSwitchedTo > 0) ? 0 : (LCR_game.resourceFile.firstItemIndex + scrolled * LCR_RESOURCE_ITEM_CHUNK), LCR_game.menuSelectedTab == 1 ? 'M' : 'R'); - - } uint8_t LCR_gameStep(uint32_t time) @@ -827,10 +839,12 @@ uint8_t LCR_gameStep(uint32_t time) LCR_racingGetCarBlockCoords(carBlock); LCR_LOG1("CP taken"); LCR_rendererMarkTakenCP(carBlock[0],carBlock[1],carBlock[2]); + LCR_audioPlaySound(LCR_SOUND_CLICK); } else if (events & LCR_RACING_EVENT_FINISHED) { LCR_LOG1("finished"); + LCR_audioPlaySound(LCR_SOUND_CLICK); } 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) { + // show the "loading" screen + LCR_rendererDrawRect( 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_Y - LCR_EFFECTIVE_RESOLUTION_Y / 4, + LCR_EFFECTIVE_RESOLUTION_Y - 2 * LCR_EFFECTIVE_RESOLUTION_Y / 3, 0xffff,0); LCR_rendererDrawText(LCR_texts[9],