From b9c6689e37f9e34aa8102e8f84e90ac716ad1dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Tue, 3 Nov 2020 18:44:32 +0100 Subject: [PATCH] Fix comments --- README.md.backup | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ constants.h | 6 ++-- game.h | 18 ++++++------ images.h | 4 +-- levels.h | 14 +++++---- settings.h | 20 ++++++------- sounds.h | 15 +++++----- 7 files changed, 113 insertions(+), 38 deletions(-) create mode 100644 README.md.backup diff --git a/README.md.backup b/README.md.backup new file mode 100644 index 0000000..86693ba --- /dev/null +++ b/README.md.backup @@ -0,0 +1,74 @@ +> well I use discord typically. Gek#9082 + +I never use discord. Things I use or can use: + +- e-mail +- IRC +- Matrix/Riot chat +- Diaspora +- Xonotic ingame chat :) We actually have pretty serious discussions in that game. + +> Question zero: What is "SW" ? + +software :) + +> I've seen that pure C software renderer. In fact, I've spoken with its author. + +It's truly impressive, I think in the video it even has linear filtering for the textures? Full HD on 60 FPS with this stuff must be running on a small supercomputer, or perhaps use some platform specific hacks? I dunno, the performance is awesome as hell. Anyway, the goal for S3L wasn't maximum speed, it tries to be platform independent and simple, which kills some potential performance boosts. + +> (DDA) which is a floating point method. + +I know DDA, it can be done without float (almost anything float can be done with just fixed point). I use it in raycastlib to trace rays. + +At first I used DDA in S3L too, but sincerely I didn't figure out how to make that respect the rules of rasterizing adjacent triangles, i.e. to have no holes or overlapping pixels on triangle borders. I implemented the top-left rule my own way. Perhaps it can be done with DDA or some algorithm I don't know of, I didn't do much research actually. + +> Yes I saw your game anarch + +Yes, it's nearing completion now. I actually want it to be not just a game, but also a potential research/educational tool, a toy for hackers, a basis for other projects etc. + +> physics engine I and a coding group (The C Chads) are designing. We want to *only* depend on SDL2 and an available C99 compiler. + +This is very awesome, +1. + +> Yes, all the software i'm writing is free software. The physics engine will be CC0. + +You're my guy, I am actually planning a CC0 physics engine in the same style as S3L/RCL, but currently am busy with many other projects. I am so glad that someone is doing this stuff. + +> Don't get me wrong, your rasterizer is *BEYOND* cool. + +Thank you :) + +> I'll be straight with you. How could I implement proper near plane culling into your model renderer? Particularly, how could I get the barycentric coordinates interpolating correctly? + + + + +I did some digging around in small3dlib.h while writng this email. You render unsorted on line 2589, in drawScene (Which happens to be the only functionality of your renderer i'm interested in, so I ain't worried about sorted) + +> A near plane clipping will create at most two triangles from a single triangle (If one of the points fall behind the near plane) + +``` + + ________ + \ / + \ / +____\ / + \/ + + +``` + + +Example implementation of near plane clipping from a fairly well-known coding 'tuber's implementation (Albeit in C++, not C99, and he releases under a modified BSD3. We can both agree, not acceptable for my use case) +https://github.com/OneLoneCoder/videos/blob/master/OneLoneCoder_olcEngine3D_Part3.cpp +(Line 322, int Triangle_ClipAgainstPlane) +If you wanted to clip the triangle and have the barycentric attributes come out correctly, you'd need to interpolate them for the new vertices, which would require a change in how S3L_drawTriangle works. + +It'd be neat to *have* this interpolation correct, however it isn't necessary as we plan on doing flat color models. As long as the triangle index and model index passed to S3L_drawTriangle are the same for both clipped triangles (or the one, smaller triangle) it's 100%, totally fine. We'll be able to get ahold of the same normal, and do the same dot product, and get the same resulting flat color for the entirety of the triangle (And per your recommendation, use a per-triangle cache) + +If you came up with a patch yourself for this specific case (Where we don't care about the barycentric attributes, but we want proper near plane culling) i'd switch your renderer immediately. *AND* I would ditch the GL implementation + +Our renderer would already be using S3L_FLAT so you could even write a check to see if this attribute was enabled and provide a compiler error if S3L_CORRECT_NEAR_PLANE_CULL was enabled but S3L_FLAT was not... or forcefully enable it, which seems to be the convention of your library. + +Thanks, +Gek \ No newline at end of file diff --git a/constants.h b/constants.h index 08ae02b..a9fc526 100644 --- a/constants.h +++ b/constants.h @@ -208,7 +208,7 @@ */ #define SFG_BASE_SPRITE_SIZE RCL_UNITS_PER_SQUARE -// ---------------------------- +// ----------------------------------------------------------------------------- // derived constants #define SFG_GAME_RESOLUTION_X \ @@ -414,7 +414,7 @@ #define SFG_HUD_BAR_HEIGHT \ (SFG_FONT_CHARACTER_SIZE * SFG_FONT_SIZE_MEDIUM + SFG_HUD_MARGIN * 2 + 1) -// ---------------------------- +// ----------------------------------------------------------------------------- // monsters #define SFG_MONSTER_ATTACK_MELEE 0 @@ -465,7 +465,7 @@ uint16_t SFG_monsterAttributeTable[SFG_MONSTERS_TOTAL] = /* explod. */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_EXPLODE,255,36,1) }; -// ---------------------------- +// ----------------------------------------------------------------------------- // weapons and projectiles #define SFG_WEAPON_KNIFE 0 diff --git a/game.h b/game.h index 27555db..a1355ae 100755 --- a/game.h +++ b/game.h @@ -85,11 +85,11 @@ int8_t SFG_keyPressed(uint8_t key); /** - Optinal function for mouse/joystick/analog controls, gets mouse x and y offset - in pixels from the game screen center (to achieve classic FPS mouse controls - the platform should center the mouse after this call). If the platform isn't - using a mouse, this function can simply return [0,0] offset at each call, or - even do nothing at all (leave the variables as are). + Optional function for mouse/joystick/analog controls, gets mouse x and y + offset in pixels from the game screen center (to achieve classic FPS mouse + controls the platform should center the mouse after this call). If the + platform isn't using a mouse, this function can simply return [0,0] offset at + each call, or even do nothing at all (leave the variables as are). */ void SFG_getMouseOffset(int16_t *x, int16_t *y); @@ -420,7 +420,7 @@ struct uint16_t headBobFrame; uint8_t weapon; ///< currently selected weapon uint8_t health; - uint32_t weaponCooldownFrames; ///< frames left for weapon cooldow + uint32_t weaponCooldownFrames; ///< frames left for weapon cooldown uint32_t lastHurtFrame; uint32_t lastItemTakenFrame; uint8_t ammo[SFG_AMMO_TOTAL]; @@ -433,7 +433,7 @@ struct } SFG_player; /** - Stores the current level and helper precomputed vaues for better performance. + Stores the current level and helper precomputed values for better performance. */ struct { @@ -550,7 +550,7 @@ static const uint8_t SFG_ditheringPatterns[] = */ /** - Returns a pseudorandom byte. This is a very simple congrent generator, its + Returns a pseudorandom byte. This is a very simple congruent generator, its parameters have been chosen so that each number (0-255) is included in the output exactly once! */ @@ -2471,7 +2471,7 @@ uint8_t SFG_projectileCollides(SFG_ProjectileRecord *projectile, /** Updates a frame of the currently loaded level, i.e. enemies, projectiles, - aimations etc., with the exception of player. + animations etc., with the exception of player. */ void SFG_updateLevel() { diff --git a/images.h b/images.h index fac3efb..569f426 100644 --- a/images.h +++ b/images.h @@ -39,7 +39,7 @@ static inline uint8_t SFG_getTexel(const uint8_t *texture, uint8_t x, uint8_t y) x &= 0x1f; y &= 0x1f; - return SFG_PROGRAM_MEMORY_U8 (texture + + return SFG_PROGRAM_MEMORY_U8(texture + ((SFG_PROGRAM_MEMORY_U8(texture + 16 + (x * SFG_TEXTURE_SIZE + y) / 2) >> (4 * (y % 2 == 0))) & 0x0f)); } @@ -1338,7 +1338,7 @@ uint8_t SFG_charToFontIndex(char c) } } -#define SFG_FONT_CHARACTER_SIZE 4 +#define SFG_FONT_CHARACTER_SIZE 4 ///< width (= height) of font char. in pixels /** 4x4 font, each character stored as 16 bits. diff --git a/levels.h b/levels.h index d2868f1..8ebdd75 100644 --- a/levels.h +++ b/levels.h @@ -17,8 +17,7 @@ #define SFG_MAP_SIZE 64 #define SFG_TILE_DICTIONARY_SIZE 64 -typedef uint16_t SFG_TileDefinition; -/**< +/** Defines a single game map tile. The format is following: MSB aaabbbbb cccddddd LSB @@ -29,6 +28,7 @@ typedef uint16_t SFG_TileDefinition; ccc: floor texture index, 111 means completely transparent texture ddddd: floor height */ +typedef uint16_t SFG_TileDefinition; #define SFG_TILE_CEILING_MAX_HEIGHT 31 #define SFG_TILE_TEXTURE_TRANSPARENT 7 @@ -104,11 +104,11 @@ typedef struct #define SFG_LEVEL_ELEMENT_CARD2 0x0f #define SFG_LEVEL_ELEMENT_LOCK0 0x10 /**< Special level element that must be placed on a tile with door. This door is - then unlocked by taking the corresponding + then locked until taking the corresponding access card. */ #define SFG_LEVEL_ELEMENT_LOCK1 0x11 #define SFG_LEVEL_ELEMENT_LOCK2 0x12 -#define SFG_LEVEL_ELEMENT_BLOCKER 0x13 ///< Invisible wall. +#define SFG_LEVEL_ELEMENT_BLOCKER 0x13 ///< invisible wall #define SFG_LEVEL_ELEMENT_MONSTER_SPIDER 0x20 #define SFG_LEVEL_ELEMENT_MONSTER_DESTROYER 0x21 @@ -143,7 +143,7 @@ typedef struct uint8_t ceilingColor; uint8_t playerStart[3]; /**< Player starting location: square X, square Y, direction (fourths of RCL_Unit). */ - uint8_t backgroundImage; /** Index of level background image. */ + uint8_t backgroundImage; ///< Index of level background image. SFG_LevelElement elements[SFG_MAX_LEVEL_ELEMENTS]; } SFG_Level; @@ -173,6 +173,9 @@ static inline SFG_TileDefinition SFG_getMapTile NOTE: Initially the levels were stored sequentially in one big array, but that caused some issues with Arduino's PROGMEM, so now we store each level in a separate variable and eventually create an array of pointers to these. + + Levels can be designed using bitmap editor and converted to the struct format + with provided tools. */ SFG_PROGRAM_MEMORY SFG_Level SFG_level0 = @@ -1796,7 +1799,6 @@ SFG_PROGRAM_MEMORY SFG_Level SFG_level9 = {SFG_LEVEL_ELEMENT_NONE, {0,0}},{SFG_LEVEL_ELEMENT_NONE, {0,0}} }, // elements } // level - ; static const SFG_Level * SFG_levels[SFG_NUMBER_OF_LEVELS] = diff --git a/settings.h b/settings.h index 83ea8d6..c537b04 100644 --- a/settings.h +++ b/settings.h @@ -38,7 +38,7 @@ integers and rounding errors can occur soon, so don't set this to extreme values (try to keep between 20 to 100). FPS also determines the game simulation step length, so different FPS values may result in very slight - differences in game behavior (not noticeable but affecting demos etc.). + differences in game behavior (not very noticeable but affecting demos etc.). */ #ifndef SFG_FPS #define SFG_FPS 60 @@ -46,7 +46,7 @@ /** On platforms with mouse this sets its horizontal sensitivity. 128 means 1 - RCL_Unit per mouse pixel travelled. + RCL_Unit turn angle per mouse pixel travelled. */ #ifndef SFG_MOUSE_SENSITIVITY_HORIZONTAL #define SFG_MOUSE_SENSITIVITY_HORIZONTAL 32 @@ -62,17 +62,15 @@ /** Width of the screen in pixels. Set this to ACTUAL resolution. If you want the - game to run at smaller resolution (with bigger pixels), do his using - SFG_RESOLUTION_SCALEDOWN; + game to run at smaller resolution (with bigger pixels), do this using + SFG_RESOLUTION_SCALEDOWN. */ #ifndef SFG_SCREEN_RESOLUTION_X #define SFG_SCREEN_RESOLUTION_X 800 #endif /** - Height of the screen in pixels. Set this to ACTUAL resolution. If you want the - game to run at smaller resolution (with bigger pixels), do his using - SFG_RESOLUTION_SCALEDOWN; + Like SFG_SCREEN_RESOLUTION_X, but for y resolution. */ #ifndef SFG_SCREEN_RESOLUTION_Y #define SFG_SCREEN_RESOLUTION_Y 600 @@ -88,7 +86,6 @@ /** Horizontal FOV (field of vision) in RCL_Units (1024 means 360 degrees). */ - #ifndef SFG_FOV_HORIZONTAL #define SFG_FOV_HORIZONTAL 256 #endif @@ -129,7 +126,7 @@ #endif /** - Hint as to whether run in fullscreen, if the platform allows it. + Hint as to whether to run in fullscreen, if the platform allows it. */ #ifndef SFG_FULLSCREEN #define SFG_FULLSCREEN 0 @@ -289,8 +286,9 @@ #endif /** - Says the intensity of background image blur. 0 means no blur, improves - performance and lowers memory usage. + Says the intensity of background image blur. 0 means no blur, which improves + performance and lowers memory usage. Blur doesn't look very good in small + resolutions. */ #ifndef SFG_BACKGROUND_BLUR #define SFG_BACKGROUND_BLUR 0 diff --git a/sounds.h b/sounds.h index c9d3b56..39b4df0 100644 --- a/sounds.h +++ b/sounds.h @@ -2,16 +2,17 @@ @file assets.h This file containts sounds and music that can optionally be used by the game - front end. Every sound effect has 2048 samples, is stored in 8kHz mono format + frontend. Every sound effect has 2048 samples, is stored as 8kHz mono format with 4 bit quantization, meaning every sound effect takes 1024 bytes. Sounds can be converted using a provided python script like this: python snd2array.py sound.raw - by Miloslav Ciz (drummyfish), 2019 - Music is based on bytebeat (procedural waveforms generated by short bitwise - operation formulas). + operation formulas). The formulas were NOT copied from anywhere, they were + discovered from scratch. + + by Miloslav Ciz (drummyfish), 2019 Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/) plus a waiver of all other intellectual property. The goal of this work is @@ -26,7 +27,7 @@ #define SFG_SFX_SIZE (SFG_SFX_SAMPLE_COUNT / 2) /** - Gets a 8-bit sound sample. + Gets an 8bit sound sample. */ #define SFG_GET_SFX_SAMPLE(soundIndex,sampleIndex) \ ((SFG_PROGRAM_MEMORY_U8(SFG_sounds + soundIndex * SFG_SFX_SIZE \ @@ -43,7 +44,7 @@ SFG_PROGRAM_MEMORY uint8_t SFG_musicTrackAverages[SFG_TRACK_COUNT] = {14,7,248,148,6,8}; struct -{ // all should be initialized to 0 +{ // all should be initialized to 0 by default uint8_t track; uint32_t t; // time variable/parameter uint32_t t2; // stores t squared, for better performance @@ -70,7 +71,7 @@ uint8_t SFG_getNextMusicSample() uint32_t result; - #define S SFG_MusicState.t // can't use "T" because of a C++ template + #define S SFG_MusicState.t // can't use "T" because of a C++ template #define S2 SFG_MusicState.t2 #define N11S SFG_MusicState.n11t