- Apply optimizations mentioned in https://youtu.be/40JzyaOYJeY (some of which seem pretty nice).
- Measure time taken by chunk management alone and make it better (stuff like deciding which chunk to mesh or generate is so bad currently that it is easy to speed up).
- Minimize iterations over large numbers of chunks at every frame.
- Ray casting by player to target a block is neither correct nor performant, do it right.
- Use
RenderPassDescriptor::timestamp_writes
to query timestamps for renderpass beginning and end and display renderpass performances for each renderpass. - Look into the
crossbeam
crate to see if it can help with better multithreading architecture than our homemade thread pool. - Add options to run benchmarks (on the user hardware) to optimize for some settings like the number of worker threads or the chunk size. These should run with graphics on and sample the setting space at random, measure the time it takes to have meshed all the chunks for one same seed. Once all the setting space have been sample for one same seed, start again with an other seed, and go on until the user stops the benchmark.
- Make the distribution of noise values at nodes of the noise implementation to be uniform by using the same technique that random number generators use to generate floats in uniform distrucbutions. A certain crate does this and cite this as a source which links to this. The we could actually assume that sampling the noise at the nodes (all integer parameters) would pick values in a uniform distribution.
- Faster noise.
- Allow to generate N values at once (to sample vectors instead of single values) in one sampling call.
- Cache some node values?
- Add a node at the center of the lattice cells to divide the cubic cells in 2*N regions (where N is the number of dimensions) so that there is only 2^N/2+1 to interpolate between when sampling instead of 2^N, while keeing the math simple. The ideal would be to get a lattice of the simplest N-dimensional shape for each N to only have to sample N+1 points but that may be way harder.
- PRNG.
- Use noise and a value on a single axis sample space as the PRNG state to get a type that is easy to use to get integer and float random values.
- Replace the improvised PRNGs in the texture generation code with the proper PRNG type.
- Variety in noise functions and implementations.
- Gradient noise implementation. It has a different (better?) feel.
- Look into simplex noise.
- Get some unified implementation for noise used to place points in the sample space and return them or return distance to closest, etc.
- Slowly rotating skybox.
- Smooth transition between skyboxes, like when the better skybox finishes to generate it should fade in instead of replacing the old one in an instant.
- Procedural sky texture with nice variety.
- Small stars and stuff like wierd celestial bodies on the skybox.
- Sun. It could look like a 4-branch star in the style of star effects in Kill la Kill.
- God rays effect when looking at sun. I recall it can be done by rendering just the sun in white and all the world in black and doing some motion blur on the result, maybe?
- Glow effect.
- If there is a way (simple enough to be worth it) to get shadows to be semi-transparent as the casters fade in the fog, then do it, but note that naive solutions do not work as there is a problem: a semi-transparent caster block A casts on an opaque block B that casts on an other block C, the shadow from A to B should be semi-transparent and the shadow from B to C should be full but a single shadow map per cascade does not support multiple casters per texel, and both the shadow from A to B and the shadow from B to C must be preserved as the player could see both so we cannot discard one of these.
- Seems possible with only twice the shadow maps. One shadow map for opaque casters, and one shadow map for semi-transparent casters (discading the second traversal of the fog by sun rays).
- Fix the fact that some block types appear slightly transparent (visible on some block types in a worlds generated by the
structures-generated-blocks
generator). This happened since adding the fog. Disableing the fog doesn't remove the transparency on these blocks (but disableing the fog actually just expands it a lot).
- Maybe introduce type aliases to better label weather we are after or before the correction by
2.0/window_with
. - Better and more general loading bar widget.
- Add some menus.
- Save selection.
- Save creation.
- Text bar widgets for the name, the seed, etc.
- Selector widget to allow to select the world generator.
- Checkbox widgets for settings like
only_save_modified_chunks
.
- Settings, like vsync and fps cap, playing mode, loading distance, fog margin, shadow map cascades number, sizes and common resolution, etc.
- When we pickup a block or place it back, instead of an instantaneous teleportation of the block into our hand, it should rather be a very quick but still visible animation of the block moving and rotating from its original position to where it must now be (our hand (in 3D) or aligned on the grid in the world).
- Add controler support (see the
gilrs
crate). - Add customization of some controls not currently customizable, such as the mouse wheel (both vertical and horizontal) or the escape key.
- Add mouse back and forward button names (they were added in the last major winit release).
- Auto default configure the walking keys to ZQSD or WASD by detecting the keyboard layout.
- Differentiate between left and right same keys (like left shift and right shift) by adding a
winit::keyboardKeyLocation
inControl::KeyboardKey
.
- Allow to provide qwy script commands at binary invocation time that are to be executed during loading or after the first frame or something.
- Add commands to interface with the game.
- Add strings.
- Add a logging function.
- Add a way to define new typed global variables.
- Add a way to set variables.
- Add floating point numbers.
- Consider getting Lua or some already implemented scripting language in there.
- Consider setting up a simpler language with less static typing.
- Structure engine.
- Set a maximum bounding box dimensions, then allow structures to declare their (potentially smaller) bounding box to already eliminate small structures too far from the chunk while still allowing very big structures.
- Procedurally generated types of block.
- Procedurally generated textures for these types of blocks (that actually are somewhat related to the block vibes, like if the block is made to be like wood or leaf the texture should at least try to feel like wood or something).
- Procedurally generated properties.
- Generation of (procedurally generated types of) structures.
- Structure types are procedurally generated (meaning that a type of tree found in a world will not be found in other worlds).
- This can be done by making the structure type be an algorithm that can be procedurally generated (it is just a tree).
- Factorize ot of the world generators that uses structures the structure generation "engine"! And make it actually readable.
- Structure types are procedurally generated (meaning that a type of tree found in a world will not be found in other worlds).
- Procedurally generated biome types, and actually using them in some world generators.
- For faster world gen:
- Generate multiple chunks (close enough to eachother) at once when possible, so that structure generation does less redundant work, and for less threading overhead.
- The chunk loader could decide to give multiple chunks (close to eachother) to one loading/generation task.
- It could also be that the chunk loaded gives a larger list of neighbors not yet assigned to other tasks to the task so that the task can decide to also generate them or not based on culling. (This is a very good idea I think!)
- Generate chunks partially, leaving not-yet-generated blocks. That would require changing the
ChunkBlocks
data structure. That could be nice, like we could avoid generating the underground part of the terrain (and maybe save large ammounts of noise samples to run for that).- That would require to support finishing the generation of partially generated chunks (in case a not-yet-generated block is exposed to air or interacted with or gets close to the player).
- Maybe even have one (or more?) bounding box inside a partially generated chunk that says what area was generated, and only represent that in memory (so that
block_keys_grid
can be smaller in number of cells).
- Generate multiple chunks (close enough to eachother) at once when possible, so that structure generation does less redundant work, and for less threading overhead.
- Make it so that chunks load ahead of the entities instead of waiting for entities to get "stuck" in unloaded chunks to start loading them.
- Support the throwing of X-shaped blocks, and text blocks, and any kind of mesh block.
- Better hitboxes, with shapes that actually correspond to the entity part models.
- Have a ball hitbox.
AlignedPhysBox::on_faces
might have to be extended to also support block edges and block vertices (after all, a ball touching only an edge or even a vertex acts differently than if it was touching a face).
- Have a ball hitbox.
- Particles, like when breaking blocks.
- Fix the fact that block entities can't place themselves nor are pushed out of bushes, because bushes are not air but also not colliding.
- Animals >w< or something (in progress).
- Procedurally generated types of animals.
- Procedurally generated anatomy.
- Procedurally generated abilities.
- Procedurally generated goals.
- Make the number of threads on which entities run on adaptative to their performance (that should be an opt-out setting).
- Make sure that the number of threads the entities want to run on are not taken by loading, kind of like how meshing prevents loading from taking one thread, but adaptative.
- When entity performance gets bad, run far chunks physics less frequently (like physics LOD).
- Subdivide entity chunks when a chunk holds many entities (into 8, 27, etc. sub chunks) to reduce the number of iterations on potentially colliding pairs of entities.
- Get some sound going!
- Consider using https://crates.io/crates/kira
- Play a sound effect.
- Make it so that sounds comming from farer have lower volume (inverse square distance law?).
- Decouple the graphics and interface from the rest. This will allow to run the graphics only on clients and not on servers (when we will have clients and servers), and it will also allow to run the game at some clock rate that is not influenced and that does not influence the framerate of the window.
- Put the interface in its own thread, while everything else runs in the thread pool and an other main thread. The interface thread shall hold all the wgpu stuff and winit stuff and widgets and all.
- Combat (to have some stakes, some danger, which at least gives the goal to survive).
- Allow some animals to pick and throw blocks at the player.
- Get blocks impact to deal damage.
- When no more hearts in the life bar of the status grid (see below), then the player dies (if in "play" mode).
- Magic system!!
- Runes, typing runes, casting.
- Procedural grammar and mapping of elementary spells to their effects.
- Make sure there are plenty of effects thta can be generated procedurally in the elementary spell map.
- Mana.
- Etc. (magic circles, engraving runes on blocks, etc.)
- "Play" playing mode with health and limitations and stuff (as opposed to the "free" playing mode that has no challenge and hands all the tools to cheat).
- Can only carry one block at a time. Once a block is broken it falls and can be picked up without any tool. Breaking a block doesn't take any time. (Kind of done ^^.)
- Respawns from eggs. Eggs are generated by the world gen.
- Status grid in "play" mode.
- There is a life bar and a food bar and a mana bar. They are not just bars, but instead lines in a grid of square cells. For example, the life bar can have hearts in it (they align themselves on the right to that there is no gap), but the hearts can be different and all. The food bar is one line above the life bar and iteracts with it: When food is eaten, a food symbol gets to try to fit in the food bar, and if the food bar gets bigger than the life bar then it is processed, emptied, and a new heart gets added to the life bar. The objects in this grid can interact with eachother and the player's properties. Some types of symbols can be procedurally generated (like special hearts and special foods that interact with the status grid in new procedurally generated ways).
- Liquids!!
- Pools of liquid, keeping track of the volume of the pool, all the block coordinates that has some of it, the height of the liquid (z-coord of its surface), etc.
- Handle the case when a pool of liquid has to flow due to a hole in a neighboring block.
- Handle gigantic pools of liquid (like a sea or an ocean) that cannot be generated all at once and all and that we can safely consider to contain an infinite amount of liquid.
- Gods.
- Through some mechanic (to be decided, like a command or a spell or finding a temple or an altar or building an altar or performing some ritual or something), the player can pray to one god among a pool of possible gods.
- Praying to a god grants a divine blessing that depends on the god, like more jumps or flying, infinite or more mana, always being able to see owns organ tree, some other abilities, etc.
- Divine blessings come at some cost that depends on the god too, like some bosses that are summoned later to challenge you.
- Can pray to multiple gods, the effects can stack.
- Portals.
- Opened via magic and/or found in the world.
- A surface streched along a small flat hole with the same flat hole shape and the same blocks on the edges at the other end, so that the transition is unnoticeable. It should just look and feel like a hole that lead to elsewhere than what is actually behind the hole if we look behind.
- Chunks must load on the other side as well, and entities that are near or overlapping the portal must be carefully handled so that it looks and feel good.
- When there is no save, save the non-modified chunk blocks and the entities in RAM to at least get persistence going until the game is closed. This would also allow the used to decide after launching the game to bind the world to a save (we would simply have to save on the disk what was saved in RAM).
- Make the saves be more resistant to panics. For now, even the
StateSavable
is lost if the game panics before being closed for the first time in a save. Loaded entities are lost on a panic. Changes made to the blocks of the loaded chunks are lost on a panic. This is too fragile and may lead to lots of frustration. - Consider (maybe or maybe not) using the
sqlx
crate to put a save in a.db
file instead of creating lots (too much) files for each save.sqlx
is pure Rust and has compile-time verified queries (which is epic!). - For super small save files, the blocks we save (even in
only_save_modified_chunks
mode) could be even fewer: When chunk blocks get modified, we could record that modification in a vec in the chunk blocks, and eventually forget about it if that vec gets longer than some (small) length. Then when we save that chunk (because it was modified), if the list of modifications is still there then it means it was not forgotten and is still small, so we take it and save just that small list of modifications instead of the chunk blocks. When loading the blocks, if what we load is a list of modifications then we can restore the chunk blocks by generating its blocks again and applying the list of modifications (that is small). This could work sooo well because most chunks marked as modified only underwent small changes.
- Multiplayer. Allow the game to become a client or a server.
- At least play on the same world generated by the server only. Use something like https://github.com/TimonPost/laminar to send chunk data from the server to clients (it allows for reliable but unordered channels that seem fast (but still reliable!)!).
- Events should be broadcasted.
- Decouple graphics from game logic entirely, so that the server can focus on game logic (as it doesn't need any graphics, and graphics take time and memory).
- Make an opt-in cargo feature that removes entirely all traces of graphic-related code, that could allow for lighter builds that can only run a server and maybe tests.
- Allow the client to generate a few chunks that the server sent and said that they were not modified, so that it (the client) can compare the blocks. If it matches exactly on some number of non-trivial chunks, then the client can consider its generator to really be the same as the server's (for blocks only, the server should always remain in charge of the entities) and generate its chunk blocks for chunks that the server tells it where not modified. If the client tells the server so, then the server can just tell the client that this and that chunks were not modified, which saves traffic (because the server doesn't have to send all these non-modified chunk blocks to that client).
- Have mods be wasm modules, loaded and executed by https://crates.io/crates/wasmtime (it compiles into machine code jit or ahead of time!).
- I don't know wasm, look into https://github.com/bytecodealliance/wit-bindgen as well.
- Provide an API to allow mods to interact with lots of aspects of the game.
- Allow to record inputs in a file and then replay these inputs, as requested by #2.
- Profile (maybe with https://github.com/killercup/cargo-flamegraph or something else).
- Profile but with https://github.com/plasma-umass/coz maybe?
- Reduce the length of
game_loop.rs
and theStateUsedInEventLoop::about_to_wait
method. - More info in the README, like control bindings syntax, default controls, command line arguments, etc.
- Find a better name? Idk.. Probably not tho, I like it that way ^^
- Write somewhere that the assets in the assert directory were made by me and are covered by the license of this project.