- Zig 100%
| resources | switch to using tsv download | |
| src | make parseFramedataTsv() test error output more useful | |
| .gitignore | initial commit | |
| .pre-commit-config.yaml | add pre-commit config | |
| build.zig | clean up build.zig and build.zig.zon | |
| build.zig.zon | update to new raylib-zig function with bugfix | |
| LICENSE | Add LICENSE | |
| README.md | add License section to README | |
Riddim
Riddim is a rhythm game inspired tool for practicing Street Fighter 6 combos.
It is inspired by regular posts online wishing for such a training mode as well as about similarities between rhythm and fighting games, like this one: https://www.youtube.com/watch?v=bGAG6WTOkVI&t=215s
Features:
- Get a visual guide for button timings instead of having to guess off of animations
- Use fighting game notation, directly paste and practice shared combos
- Overlays over your game so you can see the combo in action too
- Very portable (though mainly developed and tested on Linux)
The goal is to have inputs handled as closely as possible to how they work in street fighter 6, in order to give an accurate experience. To do that, this document is being referenced.
In order to generate the combos, I am utilizing the amazing work done by the people at fullmeter.com. The framedata they compile on their platform is handily available as a google sheet which I can download as a csv.
Installation
This project basically only has two dependencies:
- zig 0.13
- raylib (with raylib-zig bindings)
Of which you only need to manually provide zig. It should exist in package managers of every major OS (pacman, brew, winget, ...) or you can download a standalone version directly from the zig website.
Then run, for example:
zig build run
This should launch the application. The binary should reside at
zig-out/bin/riddim
Configuration
If your controller isn't working, make sure it shows up and is selected in the first drop-down menu on the title screen.
If you want to remap the controls, check button_keyboard_mappings and
button_controller_mappings in src/input.zig.
To change the combo you could manually overwrite combo.steps in main.zig in
a format similar to the one in the test at the bottom of src/combo.zig.
Though note that currently the only implemented motions are quarter circle
forward and dash.
Development
The current actual usage of the application is quite limited. There is only one combo you can attempt. However most major systems are in place, so extending this should be rather straightforward.
Contributing
I tend to litter TODO comments throughout the code during development. If you
want to work on any of those, feel free to reach out, in case I may
already be working on that particular one. Otherwise PR's are welcome :)
Open Questions
What combo Notations will be supported?
The current goal would be to support the common syntax used sites like
supercombo.gg or fullmeter.com. As those are a bit more standardized than
whatever community members use.
You can find a guide for it on the top of this page
with examples below it. In theory it shouldn't be too hard to at least support
all possible move names that FAT provides.
How are motions done?
I keep going back and forth on this but the problem lies with how situational
"correct" motion inputs are. They depend a lot on what comes before it and how
much time you have to actually enter what part of the motion.
Sometimes they can be entered as part of other moves inputs (for example when
cancelling a DP into a super or using one of the directions for a command
normal) or it may situationally be better to use some "technically correct"
input shortcut like a particular way to do a DP.
That is a lot to figure out from just some framedata. So it may just be better
to show at what point a motion should be fully entered? But then again this is
a program to help you train your inputs, so it seems like showing you what to
actually do should be part of it. Perhaps there is some easy way to add this to
the notation?
Right now I'm just showing the maximum possible input window if everything is
spaced out perfectly, however this hardly seems ideal.
How should input be handled?
There is a lot of room for improvement here:
Right now the game runs at a locked 60 FPS and updates once every frame. From
the input engine document I know that Street Fighter 6 does this 3 times a
frame. Rhythm games also figured out a lot of tricks for getting accurate
inputs, like having having a separate input thread, storing precise timestamps
with your inputs. As well as allowing you to calibrate and configure an offset
to account for physical input delay. In general the games logical frames should
be decoupled from the actual rendered FPS.
How accurate can this really be?
During development I eventually encountered the problem, that the framedata of
moves in Street Fighter 6 unfortunately don't necessarily equate to actual
frames (one sixtieth of a second passing) due to the existence of "hitstop"
when moves connect or other causes of screen freezes. Fortunately at some point
during the conception of this project, FAT started adding data for hitstop as
well as me learning that their provide a value for hit confirm windows, which
takes this into account. I have not yet fully investigated this question to the
end yet, but I am hopeful that all issues like this are solvable.
Otherwise an open issue is that moves can be cancelled on a later active frame,
which could then shift the entire combo backwards afterwards in unpredictable
ways. Not taking this into account will unfortunately make Riddim less
forgiving than the actual game.
Also Street Fighter 6 has a lot of custom corner cases for moves regarding
input buffers and such.
So I am afraid there will likely always be combos for which this program just
can't account for. In general, looking forward, I will most likely more closely
align my code structure with what FAT provides.
Are too early inputs a mistake?
Right now they don't but the problem is that it depends. Usually, when buffering links or cancels, this is not an issue but occasionally there are important delays needed or pressing some button during a gap will make you input a wrong move which locks you out from performing the move you want. This could perhaps be handled at some point down the road but would be more complicated, so for now I just make sure that the necessary inputs are done on time.
Could this support other games?
I initially thought of building this less game dependent. But in the end I noticed that just Street Fighter 6 would already complex and intricate enough. Also I can't guarantee that others games provide the same amount of resources on framedata in order to build some generic interface around it. However it could probably still be implemented eventually
Good Graphics?
I am currently using a lot of basic shapes, default UI and basic textures I
traced and recreated. This is really not my forte so I'm not sure how much
looks or the design will improve. I'm still unsure if the design of how I am
visualising the inputs and the combo even make sense. Especially for cases
where there are multiple options for what button can be pressed. Especially
once it becomes complex, like with Terries OD Burning Knuckle.
More as a note to myself, I was considering using this for the controls.
License
Riddim is licensed under the GPL license. See LICENSE for more information.