tiehuis / tetrs Goto Github PK
View Code? Open in Web Editor NEWA Tetris Engine in Rust
Home Page: https://tiehuis.github.io/tetrs/tetrs/
License: Apache License 2.0
A Tetris Engine in Rust
Home Page: https://tiehuis.github.io/tetrs/tetrs/
License: Apache License 2.0
Statistics should have a time associated with them so we can construct time-based charts of a games lifetime.
Events can then be updated on the engine though something such as engine.note_event(Event::Tetris)
. This can then call statistics.add_event(engine.ticks, Event::Tetris)
which would save the particular event in the queue of events.
Events could be stored in a complete vector, however it may also be useful to subdivide events into their own arrays as well if we require repeated querying and need a more performant structure.
The initial implementation should just iterate through a vector of events (ordered by when they occurred) and count them this way.
Another bonus is that this removes the number of different fields required for the statistics struct, and we can instead rely on a single event vector (minus some special-case events like time etc).
This should still remain separate from the history struct, since this is dealing with input events as compared to the statistics game events.
SRS rotations are not as expected using "srs" rotation and wallkick settings. This was correct in an earlier revision, but this was (unfortunately) before any tests were specified.
The interface exposed uses a mix of usize
and i32
types depending on the function. Internally there is a fair bit of casting between the two and it is likely that there could be some unforeseen errors on some inputs.
It could be a thought to change over to only signed types for simplicity, but then we do not get compile-time restrictions on various input. Rust's required explicit casting should be ample enough warning for wrong input anyway.
We require a number of specific timers on each block for things such as gravity, lock delay and any other delay that is encountered. This needs to be decided whether or not to exist on an actual block instance (leaning against) or having another struct which is managed by the engine which manages these timers. This could also hold other timers unrelated to a block as well, such as ARE countdown etc.
As an example, an Engine
requires a number of fields (Randomizer
, Wallkick
, Field
) each of which have their own optional arguments.
These could likely be replaced with some type of builder pattern to limit the number of possible constructor calls. The default parameters need to be determined however). For example, would a be required to be tied to a field or is this optional?
Currently we use one set of block data with fixed rotations. If another rotation system is wanted, this would require refactoring the current block data to use this.
We should instead hide this behind some common interface like wallkick
and randomizer
do currently. It is still undecided yet how to implement this, do we take an argument for the rotation type on block creation, for example?
Being able to write AI opponents would be interesting.
What would be helpful for this is a module which provides some convenience functions for moving the piece to the specified location and determining whether or not moves are possible based on the current ruleset.
Extending this to allow for machine learning algorithms would be of interest also.
It would be useful to load an engine state from a configuration file. On this note, it is also a question on how we want to structure initialization of structures. For example, would we store field options separately and if so how do we initialization a field from a json array? One possibility would be having separate Options
structures in place of the builder functions present, and use these for initialization.
let field = Field::new(FieldOptions { width: 9, height: 20, ..Default::default() });
Using default fields makes this fairly nice, and it would work nicely with serialization. Further, this supports adding of new fields much easier and ensures the builder functions aren't called on constructed instances. This is quite appealing and would be worth exploring before putting configuration loading in.
This would likely apply to Field
and Engine
structures for the moment, as these require the most internal options.
One downside is that initialization of default parameters is more cumbersome, but since Field
and Engine
initialization is limited, this may be worthwhile.
let engine = Engine {
field: Field { FieldOptions { width: 9, ..Default::default() },
options: Options { das: 130, ..Default::default() },
randomizer: randomizer::new("SRS", 8)
}
Serde is only used for serializing GameSettings
and inhibits compilation time plus adds another dependency on a nightly feature that can be avoided.
This should be removed and managed manually. We only require serialization of a game engine settings itself, and doing it manually allows us to structure the input/output slightly differently (i.e. group randomizer options as an object etc).
A C api would be an interesting addition to provide. Partly as a learning exercise, but it would beneficial for interfacing from different languages.
This can be written directly in rust.
Currently we can specify the required internal ms rate per frame which is nice, however when specifying DAS and other options as milliseconds, we technically can only get a minimum granularity based on the tick rate.
For example, if the tick rate was 16ms and lock delay was set to 31ms, this would occur every frame and be rounded down to 16ms.
This may just be an inherent limitation in the current engine. There are ways to improve this, such as having actions occurring at odd intervals, however this may introduce some unneeded complexity and make the internal code harder to reason about.
This is only a minor limitation, as we still gain on a traditional 60hz gameplay anyway.
Saving replay data would be great. This is already partially done in another branch, but storing the game options and how these were changed over time is required.
This would require computing a list of events (input and state changes) and being able to replay these.
We could just rely on input events if we could duplicate the rule, and this would likely be the more prudent way of going about it.
Currently lookahead in the Randomizer
structs are managed internally. This is quite nice from an API perspective, but adds extra complexity (and potential overhead?) to the underlying mechanisms required.
In particular, preview lookaheads would be required to be fixed length, or at least have some extra parameter to specify the lookahead provided.
The main question is whether a preview lookahead buffer should be found internally in each Randomizer
or whether this is the callers responsibility.
If I can find a way to perform a generic impl for every randomizer class, I would most definitely put it as part of each Randomizer
, but this may prove slightly tricky in the current stage (no inheritance).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.