Closed np-eazy closed 1 year ago
I am coding this up in the "graphics" branch, which as of now has basic piece drop markers, base colors, and individual functions for each cell type. The game look much more playable already and doesn't seem to suffer from much performance issues, but I've found that my description above is too difficult to follow.
There really isn't much point separating the cell props from another set of RenderProps, because the former is already basically the latter and has no use for CoreState. We can just kinda think of cell.props, render(cell), and update(cell) as managing props as a single state in themselves, and IMO applying the render-update loop once again to granular elements is more intuitive and scalable.
However, there would still have to be careful organization of the arrow functions we are using to introduce new cells, and we have to gradually refactor graphics-related dependencies; entry points are all over the place and that isn't very sustainable.
Another thing worth noting is that helper functions under drawCell() will act as entry points for Rust functions; we want to have the JS drawCell() function call a corresponding Rust routine container-style, and also multithread these drawCell() calls. Once this is in place, we have room to implement a lot more complex graphics without much processing cost.
After I work out PR #48 I will take down this issue and reincarnate it as a wiki page, my PR really deviated from this issue description, but they share the same backbone
As of now, this is backlogged until all game rules and controls are set in place. Fix ALL non-DevOps issues before working on these in case we can further refactor in anticipation of the features listed in this issue.
Setting some ground rules and infrastructure ideas for dealing with graphics from the ground up with just HTML Canvas and no game/render engine. The GameState is lightweight enough to handle purely in JS, so we don't have to deal with any Rust listeners; in fact, render algorithms tend to be as straightforward as it gets, so Rust/WASM would be perfect for dealing with the many particles.
The GameState is the single source of truth, and the GameCanvas is the single point of entry.
GlobalProps: Every rendered object and GameState can have control of GlobalProps which include:
shakeParam
: a number that tells how much to oscillate a global offsetflashParam
: a Color that tells is globally added to every Color usedgravityMagnitude
: the magnitude of particle velocity accelerationgravityAngle
: the direction of the above as wellRenderProps: Any rendered object must follow a universal RenderProps schema
parent
: a pointer to a parent RenderPropsneighborList
: a list of pointers to neighbor RenderPropsbaseColor
: a Color() objecttStroke
: a transient value between 0 and 1. This is reserved for stroke graphicsstrokeFunc(canvas, tStroke, x0, y0, xSize, ySize)
: a 6-arg function that tells us how to draw the stroke of this objectglowAddProbability
: a value that controls how frequently we add to the glowBufferglowDecayRate
: a value that controls how quickly each element in the glowBuffer decays decaysglowBuffer
: a list of Colors gathered from neighbors at random; items in the list have coefficients that decay, and when a threshold is hit they are removed from the list. This linear combination is added to the BaseColor to create a glow effectxOffset
: to facilitate "falling" animationsyOffset
: to facilitate "falling" animationsscale
: to facilitate growing/shrinking animationscontrolParams
: another Object to hold extra variablesRenderables: The only objects we are dealing with are Cells. Corresponding to each Cell's lifecycle in the core state, we should have the following available methods in GameState:
createRenderProps(cell)
based on its types and props, to be called upon the creation of a new CellgetRenderProps(cell)
: get the right RenderProps from the cell by accessing the PIDcreateLoop(cell)
: When a cell is created, it is given a timeToLive flag to count frames in an animation associated with introducing the cell.updateLoop(cell)
: an unconditional update that only takes in a cell and nothing else; it shouldn't need any extra argumentsdeleteLoop(cell)
: When a cell is destroyed, its RenderProps live on in GameState but will have a deleteLoop flag up and a set timeToLive which keeps incrementing downParticle: An object that once spawned is completely independent of CoreState objects. These can only be generated in createLoops and deleteLoops.
baseColor
: a Color() objectx
y
dx
dy
size
timeToLive
vibrationAmplitude
: an animation parametervibrationPhase
: an animation parameterCalling Convention
Render Domains: Rendered objects are grouped into RenderDomains, which have global x-y positions and contain their own localized coordinate systems. We have the following domains:
Some more references for later: https://dev.to/fallenstedt/making-a-canvas-based-game-with-rust-and-webassembly-2l46.