Clean
This commit is contained in:
		
							parent
							
								
									e695921c5c
								
							
						
					
					
						commit
						6986028e33
					
				
					 4 changed files with 171 additions and 155 deletions
				
			
		
							
								
								
									
										22
									
								
								audio.h
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								audio.h
									
										
									
									
									
								
							|  | @ -1,5 +1,10 @@ | |||
| /**
 | ||||
|   audio: this file implements the audio system. | ||||
| /*
 | ||||
|   Licar audio | ||||
| 
 | ||||
|   This file implements the audio system. The module only computes audio samples | ||||
|   (playing them must be done by the frontend). The audio format is 8bit, 8 KHz | ||||
|   mono. This module does NOT deal with music (music is stored in a separate | ||||
|   file, left to be optionally loaded and played by the frontend). | ||||
| */ | ||||
| 
 | ||||
| #ifndef _LCR_AUDIO | ||||
|  | @ -26,6 +31,9 @@ struct | |||
|   int engineInc; | ||||
| } LCR_audio; | ||||
| 
 | ||||
| /**
 | ||||
|   Initializes the audio system, only call once. | ||||
| */ | ||||
| void LCR_audioInit(void) | ||||
| { | ||||
|   LCR_LOG0("initializing audio"); | ||||
|  | @ -40,11 +48,18 @@ void LCR_audioInit(void) | |||
|   LCR_audio.engineIntensity = 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Sets the intensity of car engine sound that's constantly played (unless when | ||||
|   intensitiy has been set to 0). Maximum value is 255. | ||||
| */ | ||||
| void LCR_audioSetEngineIntensity(uint8_t value) | ||||
| { | ||||
|   LCR_audio.engineIntensity = value; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Tells the audio system to play certain sound (see the sound constants). | ||||
| */ | ||||
| void LCR_audioPlaySound(uint8_t sound) | ||||
| { | ||||
|   LCR_LOG2("playing sound"); | ||||
|  | @ -58,6 +73,9 @@ uint8_t _LCR_audioNoise(void) | |||
|   return LCR_audio.noise >> 16; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Gets the next audio sample. | ||||
| */ | ||||
| uint8_t LCR_audioGetNextSample(void) | ||||
| { | ||||
|   unsigned char result = 128; | ||||
|  |  | |||
							
								
								
									
										98
									
								
								game.h
									
										
									
									
									
								
							
							
						
						
									
										98
									
								
								game.h
									
										
									
									
									
								
							|  | @ -8,6 +8,9 @@ | |||
|   graphics, sound etc., and is meant to be included and used by specific | ||||
|   frontends (which will handle each platform's hardware details and I/O). See | ||||
|   the frontend info below for help with porting the game to a new platform. | ||||
|   This module (with the help of other modules) will perform all the computations | ||||
|   (physics, graphics, audio, ...) and only use the frontend's quite primitive | ||||
|   functions to actually present the results to the user. | ||||
| 
 | ||||
|   The code uses LCR_ (or _LCR) prefix as a kind of namespace preventing | ||||
|   collision with 3rd party identifiers. | ||||
|  | @ -59,19 +62,21 @@ | |||
| 
 | ||||
| /*
 | ||||
|   FOR FRONTENDS (porting to other platforms): | ||||
|   - Implement the below described functions according to their description. | ||||
|   - Implement the frontend functions given below according to their description. | ||||
|   - Implement the main program and game loop. | ||||
|   - Call the below described functions as described. | ||||
|   - If you want to support music, make your frontend play music from the "music" | ||||
|     file in assets. It is in raw format, storing 8bit unsigned samples at 8000 | ||||
|     Hz. Use the LCR_gameMusicOn to check what the music volume is. If you | ||||
|     don't support music, set LCR_SETTING_MUSIC to 0 in your frontend code so | ||||
|     that the game knows music is disabled. | ||||
|   - Call some of the frontend funtions given below in your main program in | ||||
|     places as described in the description of the function. | ||||
|   - If you want to support music, make your code load and play the "music" | ||||
|     file in the asset directory. It is in raw format, storing 8bit unsigned | ||||
|     samples at 8 KHz mono. Use the LCR_gameMusicOn function to check whether the | ||||
|     music is currently enabled (if not, stop playing it). If you don't want to | ||||
|     support music, set LCR_SETTING_MUSIC to 0 in your frontend code (before | ||||
|     including this module) so that the game knows music is disabled. | ||||
| */ | ||||
| 
 | ||||
| /**
 | ||||
|   Implement this in your frontend. Returns 1 if given key is pressed or 0 | ||||
|   otherwise. | ||||
|   Implement this in your frontend. Returns 1 if given key (see LCR_KEY_* | ||||
|   constants) is pressed or 0 otherwise. | ||||
| */ | ||||
| uint8_t LCR_keyPressed(uint8_t key); | ||||
| 
 | ||||
|  | @ -87,35 +92,40 @@ void LCR_sleep(uint16_t timeMs); | |||
|   to the screen back buffer (i.e. NOT directly to screen, back buffer shall | ||||
|   only be copied to front buffer once the LCR_gameStep function finishes all | ||||
|   rendering). This function should NOT check for out-of-screen coordinates, this | ||||
|   is handled by the game internals and out-of-screen pixels will never be drawn. | ||||
|   The color value depends on game settings but is normally an RGB565 value. | ||||
|   is handled by the game internals and out-of-screen pixels will never be drawn | ||||
|   (your code unnecessarily checking it again would likely slow down rendering a | ||||
|   lot, as drawing pixels is a bottleneck). The color value depends on game | ||||
|   settings but is normally an RGB565 value. The index parameter says the | ||||
|   coordinate at which to write the pixel, assuming the pixels are stored by | ||||
|   rows, from top to bottom. | ||||
| */ | ||||
| void LCR_drawPixel(unsigned long index, uint16_t color); | ||||
| 
 | ||||
| /**
 | ||||
|   Implement this in your frontend. This function will be called to log what the | ||||
|   program is doing. If you want to ignore logging, simply make the function do | ||||
|   nothing. | ||||
|   program is doing. Typically this function should print the string to console. | ||||
|   If you want to ignore logging, simply make the function do nothing. | ||||
| */ | ||||
| void LCR_log(const char *str); | ||||
| 
 | ||||
| /**
 | ||||
|   Implement this in your frontend. This function serves for loading optional | ||||
|   data file that allows to add more maps, replays etc. If your frontend | ||||
|   won't support this, just make the function return 0. Otherwise it must return | ||||
|   characters from the data file one by one; after reaching the end of file | ||||
|   0 must be returned and the reading position will be reset to start again. | ||||
|   data file that allows adding more maps, replays etc. If your frontend won't | ||||
|   support this, just make the function return 0. Otherwise it must return | ||||
|   characters from the data file one by one; after reaching the end of file 0 | ||||
|   must be returned and the reading position will be reset to start from | ||||
|   beginning again. | ||||
| */ | ||||
| char LCR_getNextDataFileChar(void); | ||||
| 
 | ||||
| /**
 | ||||
|   Implement this in your frontend. This serves to store data in the optional | ||||
|   data file, e.g. replays. If your frontend doesn't support this (e.g. | ||||
|   because the file is read only), the function may ignore the append, but if | ||||
|   the file is otherwise supported, a rewind of the read position must still be | ||||
|   done. If appending is supported, the function must append the provided string | ||||
|   to the data file AND then reset the data file reading position back to | ||||
|   the start. | ||||
|   data file (e.g. replays and info about beaten maps). If your frontend doesn't | ||||
|   support this (e.g. because the file is read only), the function may ignore the | ||||
|   append, but if the file is otherwise supported, a rewind of the read position | ||||
|   must still be performed. If appending is supported, the function must append | ||||
|   the provided string to the data file AND then reset the data file reading | ||||
|   position back to the start. | ||||
| */ | ||||
| void LCR_appendDataStr(const char *str); | ||||
| 
 | ||||
|  | @ -134,18 +144,22 @@ void LCR_gameEnd(void); | |||
|   Call this function in your frontend repeatedly inside the main loop, pass the | ||||
|   current time as the number of milliseconds since program start. This function | ||||
|   will perform the game step AND other things such as checking the input states, | ||||
|   rendering or sleeping (all using the above functions you should implement). | ||||
|   Returns 0 if program should end, otherwise 1. | ||||
|   rendering or sleeping (all using the above described functions you should | ||||
|   implement). Returns 0 if program should end, otherwise 1. | ||||
| */ | ||||
| uint8_t LCR_gameStep(uint32_t timeMs); | ||||
| 
 | ||||
| /**
 | ||||
|   Gets the current music volume; | ||||
|   Returns 1 if music is currently on, else 0. If your frontend supports music, | ||||
|   use this function at each frame to know whether you should start/stop playing | ||||
|   music. Otherwise ignore this. | ||||
| */ | ||||
| uint8_t LCR_gameMusicOn(void); | ||||
| 
 | ||||
| /**
 | ||||
|   Gets next audio sample (unsigned 8bit samples, 8 KHz). | ||||
|   Gets the next audio sample (unsigned 8bit samples, 8 KHz mono). If your | ||||
|   frontend supports sound, call this continuously and play the stream of | ||||
|   samples, otherwise ignore this. | ||||
| */ | ||||
| uint8_t LCR_gameGetNextAudioSample(void); | ||||
| 
 | ||||
|  | @ -187,7 +201,7 @@ uint8_t LCR_gameGetNextAudioSample(void); | |||
| // forward decls of pixel drawing functions for the renderer
 | ||||
| 
 | ||||
| /**
 | ||||
|   Internal pixel drawing function that draws pixel at specified screen coords | ||||
|   Internal pixel drawing function that puts a pixel at specified screen coords | ||||
|   without checking for safety (it's faster but can only be done if we know for | ||||
|   sure we're not drawing outside the screen). | ||||
| */ | ||||
|  | @ -213,7 +227,7 @@ static inline void LCR_drawPixelXYSafe(unsigned int x, unsigned int y, | |||
| 
 | ||||
| #if LCR_SETTING_GHOST_MAX_SAMPLES == 0 | ||||
|   #undef LCR_MENU_TABS | ||||
|   #define LCR_MENU_TABS 3 | ||||
|   #define LCR_MENU_TABS 3 // no ghosts => remove the tab for ghosts
 | ||||
| #endif | ||||
| 
 | ||||
| #define LCR_MENU_STRING_SIZE 16 | ||||
|  | @ -241,18 +255,17 @@ struct | |||
| { | ||||
|   uint8_t state; | ||||
|   uint32_t stateStartTime; | ||||
|   uint32_t time; | ||||
|   uint32_t frame; | ||||
|   uint32_t nextRenderFrameTime; | ||||
|   uint32_t nextRacingTickTime; | ||||
|   uint32_t time;                     ///< Current frame's time.
 | ||||
|   uint32_t frame;                    ///< Current frame number.
 | ||||
|   uint32_t nextRenderFrameTime;      ///< At which frame to render next frame.
 | ||||
|   uint32_t nextRacingTickTime;       ///< When to simulate next physics tick.
 | ||||
|   uint8_t cameraMode; | ||||
|   uint8_t debugDraw; | ||||
|   uint8_t musicOn; | ||||
|   uint8_t keyStates[LCR_KEYS_TOTAL]; /**< Assures unchanging key states
 | ||||
|                                           during a single frame, hold number of | ||||
|                                           frames for which the key has been | ||||
|                                           continuously held. */   | ||||
|   uint32_t runTimeMS;                /**< Current time of the run */ | ||||
|                                           continuously held. */  | ||||
|   uint32_t runTimeMS;                ///< Current time of the run
 | ||||
| 
 | ||||
|   struct | ||||
|   { | ||||
|  | @ -260,14 +273,14 @@ struct | |||
|     uint8_t selectedItem; | ||||
|     uint8_t itemCount; | ||||
|     char itemNames[LCR_MENU_MAX_ITEMS][LCR_MENU_STRING_SIZE]; | ||||
|     const char *itemNamePtrs[LCR_MENU_MAX_ITEMS]; ///< helper array
 | ||||
|     const char *itemNamePtrs[LCR_MENU_MAX_ITEMS]; ///< Helper array.
 | ||||
|   } menu; | ||||
| 
 | ||||
|   struct | ||||
|   { | ||||
|     int state;        ///< -1 if reading external res. f., else pos.
 | ||||
|     int state;            ///< -1 if reading external data f., else pos.
 | ||||
| 
 | ||||
|     // indices and counts are among the data of the same type
 | ||||
|     // Indices and counts are among the data of the same type.
 | ||||
|     unsigned int firstItemIndex; | ||||
|     unsigned int itemsTotal; | ||||
|   } dataFile; | ||||
|  | @ -286,7 +299,6 @@ struct | |||
|                            is to allow ghosts for even long replays. */ | ||||
|   } ghost; | ||||
| #endif | ||||
| 
 | ||||
| } LCR_game; | ||||
| 
 | ||||
| uint8_t LCR_gameMusicOn(void) | ||||
|  | @ -448,7 +460,7 @@ void _LCR_gamePrepareGhost(void) | |||
| 
 | ||||
|   LCR_game.ghost.stretch = 0; | ||||
| 
 | ||||
|   while (((int) LCR_replay.achievedTime) > | ||||
|   while (((int) LCR_racing.replay.achievedTime) > | ||||
|     (LCR_SETTING_GHOST_STEP << LCR_game.ghost.stretch) * | ||||
|     LCR_SETTING_GHOST_MAX_SAMPLES) | ||||
|   { | ||||
|  | @ -780,7 +792,7 @@ void LCR_gameInit(int argc, const char **argv) | |||
|   LCR_game.menu.selectedItem = 0; | ||||
| 
 | ||||
|   LCR_game.frame = 0; | ||||
|   LCR_game.musicOn = 1; | ||||
|   LCR_game.musicOn = LCR_SETTING_MUSIC; | ||||
|   LCR_game.nextRenderFrameTime = 0; | ||||
|   LCR_game.nextRacingTickTime = 0; | ||||
|   LCR_game.cameraMode = LCR_CAMERA_MODE_DRIVE; | ||||
|  | @ -1176,9 +1188,11 @@ void LCR_gameHandleInput(void) | |||
|                 LCR_rendererCameraReset(); | ||||
|                 break; | ||||
| 
 | ||||
| #if LCR_SETTING_MUSIC | ||||
|               case 1: | ||||
|                 LCR_game.musicOn = !LCR_game.musicOn; | ||||
|                 break; | ||||
| #endif | ||||
| 
 | ||||
|               case 2: | ||||
|                 LCR_audio.on = !LCR_audio.on; | ||||
|  |  | |||
							
								
								
									
										20
									
								
								map.h
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								map.h
									
										
									
									
									
								
							|  | @ -94,7 +94,7 @@ | |||
| #define LCR_BLOCK_RAMP_34           '/'  ///< plain ramp, 3/4 size
 | ||||
| #define LCR_BLOCK_RAMP_12           '<'  ///< plain ramp, 1/2 size
 | ||||
| #define LCR_BLOCK_RAMP_14           '_'  ///< plain ramp, 1/4 size
 | ||||
| #define LCR_BLOCK_RAMP_CORNER       'v'  ///< corner of ramp
 | ||||
| #define LCR_BLOCK_RAMP_CORNER       'v'  ///< corner of a ramp
 | ||||
| #define LCR_BLOCK_RAMP_CURVED_PLAT  ']'  ///< curved ramp with top platgform
 | ||||
| #define LCR_BLOCK_RAMP_CURVED       ')'  ///< curv. ramp without top platf.
 | ||||
| #define LCR_BLOCK_RAMP_CURVED_WALL  '}'  ///< curved ramp plus small wall
 | ||||
|  | @ -103,6 +103,8 @@ | |||
| #define LCR_BLOCK_CORNER_12         '\\' ///< diagonal corner (1/2 wide)
 | ||||
| #define LCR_BLOCK_HILL              '('  ///< curved "hill"
 | ||||
| #define LCR_BLOCK_BUMP              '~'  ///< small bump on the road
 | ||||
| #define LCR_BLOCK_CORNER_CONVEX     'n'  ///< curved corner (convex)
 | ||||
| #define LCR_BLOCK_CORNER_CONCAVE    'l'  ///< curved corner (concave)
 | ||||
| 
 | ||||
| #define LCR_BLOCK_FULL_ACCEL        '>' | ||||
| #define LCR_BLOCK_BOTTOM_ACCEL      'z' | ||||
|  | @ -111,9 +113,6 @@ | |||
| #define LCR_BLOCK_FULL_FAN          'o' | ||||
| #define LCR_BLOCK_RAMP_FAN          'V' | ||||
| 
 | ||||
| #define LCR_BLOCK_CORNER_CONVEX     'n' | ||||
| #define LCR_BLOCK_CORNER_CONCAVE    'l' | ||||
| 
 | ||||
| #define LCR_BLOCK_CHECKPOINT_0      '+'  ///< checkpoint, not taken
 | ||||
| #define LCR_BLOCK_CHECKPOINT_1      '\'' ///< checkpoint, taken
 | ||||
| 
 | ||||
|  | @ -131,15 +130,10 @@ | |||
| 
 | ||||
| /*
 | ||||
|   TODO: | ||||
|   - ramp corner??? | ||||
|   - curved corner? | ||||
|   - curved out corner? | ||||
|   - curved "hill" | ||||
|   - bumpy road | ||||
|   - bigger structures like a loop, sloped road etc? | ||||
| */ | ||||
| 
 | ||||
| #define LCR_MAP_BLOCK_CACHE_SIZE (8 * 2)   /// do not change
 | ||||
| #define LCR_MAP_BLOCK_CACHE_SIZE (8 * 2) ///< Do not change.
 | ||||
| 
 | ||||
| /**
 | ||||
|   Cache for accelerating LCR_mapGetBlockAtFast, consists of 8 2-item records, | ||||
|  | @ -154,12 +148,12 @@ struct | |||
| { | ||||
|   uint16_t blockCount; | ||||
|   uint8_t blocks[LCR_SETTING_MAP_MAX_BLOCKS * LCR_BLOCK_SIZE]; | ||||
|   uint8_t startPos[4]; ///< Initial position and rotation.
 | ||||
|   uint8_t startPos[4];      ///< Initial position and rotation.
 | ||||
| 
 | ||||
|   uint8_t environment; | ||||
|   uint8_t checkpointCount; | ||||
| 
 | ||||
|   uint32_t hash;       ///< Hash of the processed binary map.
 | ||||
|   uint32_t hash;            ///< Hash of the processed binary map.
 | ||||
|   uint32_t targetTime; | ||||
| 
 | ||||
|   char name[LCR_MAP_NAME_MAX_LEN + 1]; | ||||
|  | @ -249,7 +243,7 @@ void LCR_rampGetDimensions(uint8_t rampType, uint8_t *height4ths, | |||
| 
 | ||||
| uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord) | ||||
| { | ||||
|   // binary search the block:
 | ||||
|   // Binary search the block:
 | ||||
| 
 | ||||
|   uint16_t a = 0, b = LCR_currentMap.blockCount - 1; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										186
									
								
								racing.h
									
										
									
									
									
								
							
							
						
						
									
										186
									
								
								racing.h
									
										
									
									
									
								
							|  | @ -43,8 +43,8 @@ typedef int32_t LCR_GameUnit;  ///< abstract game unit | |||
| 
 | ||||
| #define LCR_PHYSICS_UNIT             4096 ///< len. of square for phys. engine
 | ||||
|    | ||||
| #define TPE_RESHAPE_TENSION_LIMIT 3 | ||||
| #define TPE_RESHAPE_ITERATIONS    8 | ||||
| #define TPE_RESHAPE_TENSION_LIMIT    3 | ||||
| #define TPE_RESHAPE_ITERATIONS       8 | ||||
| 
 | ||||
| #include "general.h" | ||||
| #include "map.h" | ||||
|  | @ -69,10 +69,10 @@ typedef int32_t LCR_GameUnit;  ///< abstract game unit | |||
| #define LCR_CAR_CRASH_SPEED_SMALL 400 | ||||
| #define LCR_CAR_CRASH_SPEED_BIG 800 | ||||
| 
 | ||||
| // multipliers (in 8ths) of friction and acceleration on concrete:
 | ||||
| // Multipliers (in 8ths) of friction and acceleration on concrete:
 | ||||
| #define LCR_CAR_GRASS_FACTOR 5 | ||||
| #define LCR_CAR_DIRT_FACTOR 3 | ||||
| #define LCR_CAR_ICE_FACTOR 1 | ||||
| #define LCR_CAR_DIRT_FACTOR  3 | ||||
| #define LCR_CAR_ICE_FACTOR   1 | ||||
| #define LCR_CAR_DRIFT_FACTOR 2    ///< only affects steering friction
 | ||||
| 
 | ||||
| #define LCR_CAR_JOINTS 5 | ||||
|  | @ -87,7 +87,7 @@ struct | |||
|   TPE_Joint carJoints[LCR_CAR_JOINTS]; | ||||
|   TPE_Connection carConnections[LCR_CAR_CONNECTIONS]; | ||||
| 
 | ||||
|   uint32_t tick; | ||||
|   uint32_t tick;             ///< Physics tick (frame) number.
 | ||||
|   uint8_t wheelCollisions;   /**< In individual bits records for each car wheel
 | ||||
|                                   whether it's currently touching the ground. | ||||
|                                   Lower bits record current collisions, higher | ||||
|  | @ -111,19 +111,19 @@ struct | |||
|   uint16_t crashState; | ||||
| 
 | ||||
|   uint8_t playingReplay; | ||||
| 
 | ||||
|   struct | ||||
|   { | ||||
|     uint16_t eventCount; | ||||
|     uint16_t events[LCR_SETTING_REPLAY_MAX_SIZE];  | ||||
| 
 | ||||
|     // for playing
 | ||||
|     uint16_t currentEvent; | ||||
|     uint16_t currentFrame; | ||||
|     uint32_t achievedTime; | ||||
|   } replay; | ||||
| } LCR_racing; | ||||
| 
 | ||||
| struct | ||||
| { | ||||
|   uint16_t eventCount; | ||||
|   uint16_t events[LCR_SETTING_REPLAY_MAX_SIZE];  | ||||
| 
 | ||||
|   // for playing
 | ||||
|   uint16_t currentEvent; | ||||
|   uint16_t currentFrame; | ||||
|   uint32_t achievedTime; | ||||
| } LCR_replay; // TODO: move inside LCR_racing?
 | ||||
| 
 | ||||
| /**
 | ||||
|   Gets times of the run in milliseconds. | ||||
| */ | ||||
|  | @ -144,15 +144,15 @@ TPE_Vec3 _LCR_TPE_vec3DividePlain(TPE_Vec3 v, TPE_Unit d) | |||
| void LCR_replayInitRecording(void) | ||||
| { | ||||
|   LCR_LOG1("initializing replay recording"); | ||||
|   LCR_replay.eventCount = 0; | ||||
|   LCR_replay.achievedTime = 0; | ||||
|   LCR_racing.replay.eventCount = 0; | ||||
|   LCR_racing.replay.achievedTime = 0; | ||||
| } | ||||
| 
 | ||||
| void LCR_replayInitPlaying(void) | ||||
| { | ||||
|   LCR_LOG1("initializing replay playing"); | ||||
|   LCR_replay.currentEvent = 0; | ||||
|   LCR_replay.currentFrame = 0; | ||||
|   LCR_racing.replay.currentEvent = 0; | ||||
|   LCR_racing.replay.currentFrame = 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -185,14 +185,16 @@ void LCR_replayOutputStr(void (*printChar)(char)) | |||
| 
 | ||||
|   // 8 decimal digits are enough to record 24 hours
 | ||||
| 
 | ||||
| #define PUTD(order) printChar('0' + (LCR_replay.achievedTime / order) % 10); | ||||
| #define PUTD(order) \ | ||||
|   printChar('0' + (LCR_racing.replay.achievedTime / order) % 10); | ||||
| 
 | ||||
|   PUTD(10000000) PUTD(1000000) PUTD(100000) PUTD(10000) | ||||
|   PUTD(1000) PUTD(100) PUTD(10) PUTD(1) | ||||
| #undef PUTD | ||||
| 
 | ||||
|   for (int i = 0; i < LCR_replay.eventCount; ++i) | ||||
|   for (int i = 0; i < LCR_racing.replay.eventCount; ++i) | ||||
|   { | ||||
|     uint16_t e = LCR_replay.events[i]; | ||||
|     uint16_t e = LCR_racing.replay.events[i]; | ||||
|     printChar(':'); | ||||
| 
 | ||||
|     for (int j = 0; j < 4; ++j) | ||||
|  | @ -208,51 +210,35 @@ void LCR_replayOutputStr(void (*printChar)(char)) | |||
| /**
 | ||||
|   Reads replay from string using provided function that returns next character | ||||
|   in the string. The mapHash and nameHash pointers are optional: if non-zero, | ||||
|   they will be filled with the map hash and name hash. Returns 1 on success, | ||||
|   else 0. | ||||
|   the memory they point to will be filled with the map hash and name hash. | ||||
|   Returns 1 on success, else 0. | ||||
| */ | ||||
| int LCR_replayLoadFromStr(char (*nextChar)(void), | ||||
|   uint32_t *mapHash, uint16_t *nameHash) | ||||
| { | ||||
|   char c = ' '; | ||||
| 
 | ||||
|   LCR_replay.eventCount = 0; | ||||
|   LCR_replay.achievedTime = 0; | ||||
|   LCR_racing.replay.eventCount = 0; | ||||
|   LCR_racing.replay.achievedTime = 0; | ||||
| 
 | ||||
| if (nameHash) | ||||
|   *nameHash = _LCR_simpleStrHash(nextChar,';'); | ||||
| else | ||||
|   _LCR_simpleStrHash(nextChar,';'); | ||||
|   if (nameHash) | ||||
|     *nameHash = _LCR_simpleStrHash(nextChar,';'); | ||||
|   else | ||||
|     _LCR_simpleStrHash(nextChar,';'); | ||||
| 
 | ||||
| /*
 | ||||
|   do // map name
 | ||||
|   if (mapHash) | ||||
|     *mapHash = 0; | ||||
| 
 | ||||
|   for (int i = 0; i < 8; ++i) // hash
 | ||||
|   { | ||||
|     c = nextChar(); | ||||
| 
 | ||||
|     if (c == 0) | ||||
|     if (_LCR_hexDigitVal(c) < 0) | ||||
|       return 0; | ||||
|   } while (c != ';'); | ||||
| */ | ||||
| 
 | ||||
| if (mapHash) | ||||
|   *mapHash = 0; | ||||
| 
 | ||||
| for (int i = 0; i < 8; ++i) // hash
 | ||||
| { | ||||
|   c = nextChar(); | ||||
| 
 | ||||
|   if (_LCR_hexDigitVal(c) < 0) | ||||
|     return 0; | ||||
| 
 | ||||
|   if (mapHash) | ||||
|     *mapHash = ((*mapHash) << 4) | _LCR_hexDigitVal(c); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   for (int i = 0; i < 8; ++i) // hash
 | ||||
|     if (_LCR_hexDigitVal(nextChar()) < 0) | ||||
|       return 0; | ||||
| */ | ||||
|     if (mapHash) | ||||
|       *mapHash = ((*mapHash) << 4) | _LCR_hexDigitVal(c); | ||||
|   } | ||||
| 
 | ||||
|   nextChar(); | ||||
| 
 | ||||
|  | @ -263,7 +249,8 @@ for (int i = 0; i < 8; ++i) // hash | |||
|     if (c < '0' || c > '9') | ||||
|       break; | ||||
| 
 | ||||
|     LCR_replay.achievedTime = LCR_replay.achievedTime * 10 + c - '0'; | ||||
|     LCR_racing.replay.achievedTime =  | ||||
|       LCR_racing.replay.achievedTime * 10 + c - '0'; | ||||
|   } | ||||
| 
 | ||||
|   while (c != 0) // events
 | ||||
|  | @ -278,11 +265,11 @@ for (int i = 0; i < 8; ++i) // hash | |||
|       if (e == 0) | ||||
|         break; | ||||
|        | ||||
|       if (LCR_replay.eventCount >= LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|       if (LCR_racing.replay.eventCount >= LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|         return 0; | ||||
| 
 | ||||
|       LCR_replay.events[LCR_replay.eventCount] = e; | ||||
|       LCR_replay.eventCount++; | ||||
|       LCR_racing.replay.events[LCR_racing.replay.eventCount] = e; | ||||
|       LCR_racing.replay.eventCount++; | ||||
|     } | ||||
| 
 | ||||
|     c = nextChar(); | ||||
|  | @ -292,60 +279,61 @@ for (int i = 0; i < 8; ++i) // hash | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   During playing of a replay returns the next input and shifts to next frame. | ||||
|   When playing back a replay this function returns the next recorded input and | ||||
|   shifts to the next frame. | ||||
| */ | ||||
| uint8_t LCR_replayGetNextInput(void) | ||||
| { | ||||
|   if (LCR_replay.currentEvent >= LCR_replay.eventCount) | ||||
|   if (LCR_racing.replay.currentEvent >= LCR_racing.replay.eventCount) | ||||
|   { | ||||
|     LCR_replay.currentFrame++; // has to be here
 | ||||
|     LCR_racing.replay.currentFrame++; // has to be here
 | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   if (LCR_replay.currentFrame == | ||||
|     (LCR_replay.events[LCR_replay.currentEvent] >> 4)) | ||||
|   if (LCR_racing.replay.currentFrame == | ||||
|     (LCR_racing.replay.events[LCR_racing.replay.currentEvent] >> 4)) | ||||
|   { | ||||
|     LCR_replay.currentEvent++; | ||||
|     LCR_replay.currentFrame = 0; | ||||
|     LCR_racing.replay.currentEvent++; | ||||
|     LCR_racing.replay.currentFrame = 0; | ||||
|   } | ||||
|   | ||||
|   LCR_replay.currentFrame++; | ||||
|   LCR_racing.replay.currentFrame++; | ||||
| 
 | ||||
|   return LCR_replay.currentEvent ? | ||||
|     (LCR_replay.events[LCR_replay.currentEvent - 1] & 0x0f) : 0; | ||||
|   return LCR_racing.replay.currentEvent ? | ||||
|     (LCR_racing.replay.events[LCR_racing.replay.currentEvent - 1] & 0x0f) : 0; | ||||
| } | ||||
| 
 | ||||
| int LCR_replayHasFinished(void) | ||||
| { | ||||
|   if (LCR_replay.currentEvent == LCR_replay.eventCount) | ||||
|   if (LCR_racing.replay.currentEvent == LCR_racing.replay.eventCount) | ||||
|   { | ||||
|     uint32_t totalTime = LCR_replay.currentFrame; | ||||
|     uint32_t totalTime = LCR_racing.replay.currentFrame; | ||||
| 
 | ||||
|     for (int i = 0; i < LCR_replay.eventCount; ++i) | ||||
|       totalTime += LCR_replay.events[i] >> 4; | ||||
|     for (int i = 0; i < LCR_racing.replay.eventCount; ++i) | ||||
|       totalTime += LCR_racing.replay.events[i] >> 4; | ||||
| 
 | ||||
|     return totalTime >= LCR_replay.achievedTime; | ||||
|     return totalTime >= LCR_racing.replay.achievedTime; | ||||
|   } | ||||
| 
 | ||||
|   return LCR_replay.currentEvent > LCR_replay.eventCount; | ||||
|   return LCR_racing.replay.currentEvent > LCR_racing.replay.eventCount; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Records another input event. Returns 1 on success, or 0 if the event couldn't | ||||
|   be recorded. The event is only added if necessary, i.e. this function can | ||||
|   (and must) be called every frame without worrying about inflating its size. | ||||
|   When the run ends, the LCR_REPLAY_EVENT_END has to be fed! | ||||
|   Records another input event into a replay. Returns 1 on success, or 0 if the | ||||
|   event couldn't be recorded. The event is only added if necessary, i.e. this | ||||
|   function can, and MUST, be called every frame without worrying about inflating | ||||
|   its size. When the run ends, the LCR_REPLAY_EVENT_END has to be fed! | ||||
| */ | ||||
| int LCR_replayRecordEvent(uint32_t frame, uint8_t input) | ||||
| { | ||||
|   LCR_LOG2("recording replay event"); | ||||
| 
 | ||||
|   if (LCR_replay.achievedTime) | ||||
|   if (LCR_racing.replay.achievedTime) | ||||
|     return 1; // already finished
 | ||||
| 
 | ||||
|   if (input == LCR_REPLAY_EVENT_END) | ||||
|   { | ||||
|     LCR_replay.achievedTime = frame; | ||||
|     LCR_racing.replay.achievedTime = frame; | ||||
|     LCR_LOG1("replay recording finished"); | ||||
|     return 1; | ||||
|   } | ||||
|  | @ -354,10 +342,10 @@ int LCR_replayRecordEvent(uint32_t frame, uint8_t input) | |||
|   uint8_t previousInput = 0; | ||||
|   uint32_t previousFrame = 0; | ||||
| 
 | ||||
|   for (int i = 0; i < LCR_replay.eventCount; ++i) | ||||
|   for (int i = 0; i < LCR_racing.replay.eventCount; ++i) | ||||
|   { | ||||
|     previousInput = LCR_replay.events[i] & 0x0f; | ||||
|     previousFrame += LCR_replay.events[i] >> 4; | ||||
|     previousInput = LCR_racing.replay.events[i] & 0x0f; | ||||
|     previousFrame += LCR_racing.replay.events[i] >> 4; | ||||
|   } | ||||
| 
 | ||||
|   if (input == previousInput) | ||||
|  | @ -368,30 +356,30 @@ int LCR_replayRecordEvent(uint32_t frame, uint8_t input) | |||
| 
 | ||||
|   frame -= previousFrame; // convert to offset
 | ||||
| 
 | ||||
|   while (frame > 4095 && LCR_replay.eventCount < LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|   while (frame > 4095 && LCR_racing.replay.eventCount < LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|   { | ||||
|     // add intermediate events
 | ||||
|     frame -= 4095; | ||||
|     previousFrame += 4095; | ||||
| 
 | ||||
|     LCR_replay.events[LCR_replay.eventCount] = | ||||
|     LCR_racing.replay.events[LCR_racing.replay.eventCount] = | ||||
|       (previousFrame << 4) | previousInput; | ||||
|     LCR_replay.eventCount++; | ||||
|     LCR_racing.replay.eventCount++; | ||||
|   } | ||||
| 
 | ||||
|   if (LCR_replay.eventCount >= LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|   if (LCR_racing.replay.eventCount >= LCR_SETTING_REPLAY_MAX_SIZE) | ||||
|     return 0; | ||||
| 
 | ||||
|   LCR_replay.events[LCR_replay.eventCount] = (frame << 4) | (input & 0x0f); | ||||
|   LCR_replay.eventCount++; | ||||
|   LCR_racing.replay.events[LCR_racing.replay.eventCount] = (frame << 4) | (input & 0x0f); | ||||
|   LCR_racing.replay.eventCount++; | ||||
| #endif | ||||
| 
 | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   Helper function for _LCR_racingEnvironmentFunction, returns closest point | ||||
|   on a map block placed at coordinate origin. | ||||
|   Helper function for _LCR_racingEnvironmentFunction, returns closest point on | ||||
|   a map block placed at coordinate origin. | ||||
| */ | ||||
| TPE_Vec3 _LCR_racingBlockEnvFunc(TPE_Vec3 point, const uint8_t *block) | ||||
| { | ||||
|  | @ -691,8 +679,8 @@ TPE_Vec3 _LCR_racingBlockEnvFunc(TPE_Vec3 point, const uint8_t *block) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|   For tinyphysicsengine, function that defines the shape of physics world, | ||||
|   returns closest point to any given point in space. | ||||
|   For tinyphysicsengine, function that defines the shape of the static physics | ||||
|   world, returns closest point to any given point in space. | ||||
| */ | ||||
| TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist) | ||||
| { | ||||
|  | @ -795,10 +783,10 @@ LCR_GameUnit LCR_racingGetCarSpeedSigned(void) | |||
| uint8_t _LCR_racingCollisionHandler(uint16_t b1, uint16_t j1, uint16_t b2, | ||||
|   uint16_t j2, TPE_Vec3 p) | ||||
| { | ||||
|   // check which wheels are touching the ground.
 | ||||
| 
 | ||||
| #if LCR_SETTING_CRASH_SOUNDS | ||||
|   TPE_Unit speed = TPE_vec3Len( // detect crashes
 | ||||
|   // Detect crashes:
 | ||||
| 
 | ||||
|   TPE_Unit speed = TPE_vec3Len( | ||||
|       TPE_vec3Project( | ||||
|         TPE_vec3( | ||||
|           LCR_racing.carBody.joints[j1].velocity[0], | ||||
|  | @ -811,6 +799,8 @@ uint8_t _LCR_racingCollisionHandler(uint16_t b1, uint16_t j1, uint16_t b2, | |||
|     (speed >= LCR_CAR_CRASH_SPEED_SMALL); | ||||
| #endif | ||||
| 
 | ||||
|   // Check which wheels are touching the ground:
 | ||||
| 
 | ||||
|   if (j1 < 4) // wheel joint?
 | ||||
|     LCR_racing.wheelCollisions |= 0x01 << j1; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue