Fish Folk: Jumpy
đ Live on Kickstarter! đ
Introduction
Fish Folk: Jumpy is a tactical 2D shooter, played by up to 4 players online or on a shared screen. Aim either left or right; the rest is up to clever movement and positioning in this fish-on-fish brawler! For more information about our origin story (Duck Game et.al.) and big-picture plans, see our design document.
Web Demo
Jumpy runs in the browser! You can play web demo to try out the game, without needing to install anything on your computer.
We recommend using the Chrome browser or other derivatives for best performance, or if you have issues with other browsers.
Key Features (WIP)
- 2 to 4 players in either Local Multiplayer or Online Play
- Easy to pick up, emphasizing strategy over twitch reaction
- Customize characters with hats, saved to your cross-platform profile
- Create & explore user-made weapons, levels, audio and other scripted extensions
- Smart level creation tools
- Tournaments & matchmaking built in
Community
Contributing
Anyone involved in the Fish Folk community must follow our code of conduct.
If you'd like to make something for Fish Folk, check out our help-wanted issues or just ask us on Discord. We'll soon post an updated roadmap for the next month or two of work ahead.
Before committing and opening a PR, please run the following commands and follow their instructions:
cargo clippy -- -W clippy::correctness -D warnings
cargo fmt
Development Build Profiles
By default, Jumpy will build without optimizations for the jumpy_core
and jumpy
crates. This helps reduce re-compile times at the expense of some runtime performance. If you need increased runtime performance during development, you can build with the --profile dev-optimized
option, to optimize all of the crates:
cargo r --profile dev-optimized
Learning Materials
Rust
Bevy
Download & play
- Download the latest version from the releases page.
- Extract the archive and run the executable. (e.g.
./jumpy
orjumpy.exe
)
Launcher
A cross-platform launcher is also available for downloading and launching the game easily.
Distro Packages
Arch Linux
pacman -S jumpy
Building
- Install Rust with rustup.rs
- Clone this repository:
git clone https://github.com/fishfolk/jumpy.git
cd jumpy
cargo run
Credits
- Fish Folk: Jumpy Credits
- Input Icons: Kadith's Icons by Kadith
Contributor Covenant Code of Conduct
Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at @erlend-sh (e.soghe@gmail.com / erlend#1111) All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
1. Correction
Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
2. Warning
Community Impact: A violation through a single incident or series of actions.
Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
3. Temporary Ban
Community Impact: A serious violation of community standards, including sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
4. Permanent Ban
Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the community.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
Contributing Art
This guide will show you the steps to draw art using the Fish Fight style. Following these steps will help your custom art fit better in the Fish Fight world. For this example, we will focus on creating a cannon weapon, but these principles can be applied to other assets as well. If you are completely new to pixel art, make sure to take a look at the Additional Resources section first.
Concept
Before you start drawing, you need to have a clear idea of what it is you are creating. We recommend finding a few reference images that you can look at while creating your art. Even the best artists do this. Drawing something completely from memory tends to not give the best results. Below are some reference images we found for cannons.
Outline
Now that you have some references, you can start drawing your art! To start off, draw an outline of the object's prominent features. Keep outlining more details until it is recognizable as the object you are creating. Below is the outline for the cannon weapon:
Here are the guidelines we use for outlining:
- All details for the object should be completely surrounded by outlines
- All outlines should be 1 pixel thick
- Outlines should use a dark color
- Generally, all outlines should be the same color
- Only non-solid materials like smoke, fire, etc. should be drawn without outlines
- If the object has holes, make them the same color as the outline
Color
After you've finished outlining your object you are ready to begin coloring. Below is the cannon weapon after being colored:
Here are the guidelines we use for applying color:
- Use colors that have a similar saturation level with game's existing assets
- Use contrasting colors to distinguish different parts of the object
- The entire object should be filled with color (no transparency)
Shadows and Details
After coloring, shadows and details can be added to the object, but try to keep it clean and recognizable. Below is the cannon after adding shadows and details.
Here are the guidelines we use for adding shadows and details:
- For contrasting shadows, use one light and one dark color
- Use hue shifting to create color ramps
- Avoid anti-aliasing
Conclusion
Below is the full process for creating the cannon art:
Additional Resources
If you are new to pixel art, we recommend that you take a look at these tutorials to learn the basics first.
We hope this guide was helpful for understanding the Fish Fight art style. If you have any more questions feel free to ask on the #pixels Discord channel.
Architecture
The Jumpy architecture is documented in the project Rustdoc.
Our Rustdoc isn't just API documentation, but also includes guide-level explanations of various aspects of the game, such as networking. It's the best way to get in deep and understand how the game is put together from a code perspective.
Contributing Code to Fish Fight
Proposing code changes has 3 main steps:
- Setting up your development environment
- Pick an issue to work on
- Write code and submitting for review
1. Setting up your development environment
Before starting
Make sure Rust is installed with Rustup.rs.
Have an account on GitHub: this is where you'll find the source code for Fish Fight.
Getting the source code
Fish Fight uses git as its established choice of version control. You'll be using it to clone, track, and manage the source code locally on your machine.
To get a copy of the code, you'll first need to fork the repository. The GitHub repository for Fight Fight is available here. This will allow you to make changes to the project without affecting the original one.
Once you've forked the Fish Fight repository, you can now clone it:
git clone https://github.com/fishfolk/jumpy.git
It's also possible to clone the repo using SSH or GitHub CLI. For more information on how to do this, see the official GitHub documentation.
Depending on your connection, the clone can take around 1 minute.
By the end of this step, you should have successfully forked and downloaded a clone of Fish Fight on your machine.
Build and run
You can now build your forked copy of Fish Fight:
cargo build
This process should take about a minute or two depending on your machine. You can also build and run the game with a single command:
cargo run
2. Finding a good first issue
Now that you can build and run Fish Fight source code, let's find something to work on! We recommend all newcomers start with our Development Tracks. You can also browse project's issues list and pick something with a help wanted label. In general, you can comment on an issue expressing interest and someone will assign it to you.
Additionally, if there's a track or issue you're particularly interested in, but you don't know where to start, feel free to reach out to the Fish Fight Discord community with your questions and someone should reach out shortly!
3. Write code and submitting for review
In general, Fish Fight uses a branch-based workflow (or GitHub flow) for submitting changes to the project.
Create a new branch
You'll want to create a new branch off main
:
git checkout -b <branch_name> main
You'll replace <branch-name>
with something short and descriptive. For example, if you're adding a new
item to Fish Fight, your branch name might look like this:
git checkout -b add_new_weapon main
Commit your changes
Once you've made the desired changes to the code and you're ready for someone on the Fish Fight team to review, you need to commit your work. But first, we have to run a few commands to ensure the code you're submitting is properly formatted:
cargo clippy -- -W clippy::correctness -D warnings
cargo fmt
Now we can start committing your work. First, stage your changes:
git add
Now commit. It's always good practice to provide a short message that details what the changes are. For example:
git commit -m "Add a new weapon"
Submitting for review
You can now start submitting your work for review. First, push your changes:
git push
This will create a new branch on your forked copy of Fish Fight. You can then proceed making a pull request. This is how the Fish Fight team will review and provide feedback on your work.
More information on contributing using GitHub.
Juice and Feel
Juice, or game feel, is the science and art of making pushing a button viscerally satisfying. Well, more precisely it's about giving feedback to confirm the player's actions. For games where flow and feeling matter, juice is the thing that makes the player understand your game without reading dials and processing numbers. Juice gives a game life and soul that makes the player feel like a part of the world. Juice is what makes a game feel fun without actually making any mechanical difference. And juice might just be what makes or breaks your game.
Whenever you do something in real life you get a wide range of sensory input in return indicating that what you tried to do actually happened. That response grounds you and makes you realise the reality and weight of things. As you might guess, replicating that kind of feedback on a flatscreen is hard. To get anywhere near reality you need hyperreal effects and nerve-blasting feedback to fill in for all the missing senses, all the while walking the fine line of overloading your player and making a dry, unresponsive world.
Of course, not all games need equal amounts of juice. Some games are played mostly in your head, and therefore all that visual feedback is not needed. Civilization has little more than flavour animations when a unit attacks, a town is built or a nuke blows up (actually the last one is pretty nice, but the real juice is your enemyâs tears). These are rather abstract both mechanically and visually, rarely pertaining to situations and perspectives we encounter in our everyday life. These games would still work with nothing but coloured circles and lines, because the strategy and the story exists in the playerâs head. These games are planning games, where the payoff is to after thousands of years of careful strategising triumph over your enemy.
On the other side of the spectrum are execution games that test your reflexes and motor skills. These are played visually with the game continually telling the player what is going on. Here, the payoff is landing that single-frame-margin combo and watching your enemy explode into a glorious cloud of gibs. The juice that in a planning game exists in the playerâs head must here be given by the game.
For realistic first-person games, juicing is difficult and labour-intensive in practice but easier in concept, as you can model the feedback off reality to align with the playerâs expectations. But a side-scrolling shooter like Fish Fight is more difficult in theory. Iâd doubt you have a clear picture of how stylised two-dimensional fish running and shooting each other would look in real life. For something so far detached from reality, you must work a lot in the same way as with symbol drawing: finding effects that represent their real-life counterparts without actually being them. You'll have to unhinge your expectations and think out of the box to find the feel you need.
Working with game feel
The worst part about working with game feel is that it is only ever noticed if it is bad. Good game feel is only felt, never seen. If the juice is so grandiose that the player starts thinking of it, it will wear them out and possibly even make them sick if too much stuff is moving onscreen. But if there is not enough of it, the game will feel dry and lifeless. The juice is there to constantly trigger and must therefore be just right. On that matter, juicing games is more artsy compared to, for instance, UI design. There are certain guidelines to follow, but mostly it's lots of tuning and testing. The easiest way to try the feel is simply to play the game! If even mundane actions like walking feels nice, you have really succeeded.
Juicing also regards making the world feel alive by making it respond, cause and effect, to the player's actions. Whipping up dust while running or jostling foliage when walking through it are common effects that give the impression of a breathing coherent world in which all its separate parts coexist and interact. This doesn't do anything mechanically, but is equivalent to hitting a wooden crate and it not breaking. Now you maybe even shudder a bit at the thought of how lifeless, bland and plain wrong it would feel. Well, the player too has expectations on how the world should respond. Your task is to meet and feed into those expectations on all levels, from the core greyboxed mechanics to minute tweens and particle effects. Now, for some ways to actually squeeze some juice out of your games!
Screen Shake
Screen shake is an immensely powerful tool for giving heavy, visceral feedback that disorients the player as if their whole body was actually rumbling. When the entire scene shakes the player feels it, usually without thinking of it. Regular flatscreen games are only connected to two of the players senses, vision and hearing, and that is all you have to work with. The ears can be shaken about with some explosion noises, but to equally rustle the playerâs eyes you need screen shake.
Screen shake moves the playerâs viewpoint around, translationally and/or rotationally, to make it appear the world is rumbling. Adding the right amount of shake is an art; it is crucial to not overdo screen shake as it can hamper readability and even make sensitive players motion sick, but at the same time it must be significant enough to be felt. People usually have very split opinions on screen shake. Some love the punch it gives, others detest the blurry jostling. Try to take a step back and don't get too caught up in the looks, the game must still be playable.
Screen shake in practice in Fish Fight
Screen shake is a lot about feel, and as such requires a lot of dialling in. In jumpy we will have three kinds of screen shake: noise (Perlin) translational, sinusoidal translational and rotational. Translational noise moves the world up- and sideways, while the rotational noise rotates the world around the screen midpoint. To that, you can also make the screen shake only in a certain axis to give it directionality. Omnidirectional shaking is the most common and can be used for pretty much everything. It fits explosions really well, but won't feel out of place for anything else either. The directional type on the other hand is more specialised and can for example be used vertically for jump impacts or horizontally for guns firing sideways. This further enhances feedback and narrows its meaning down, increasing clarity and readability.
To those types thereâs three parameters: magnitude, frequency and length. Magnitude affects how far the screen moves when shaking (the amplitude of the oscillation) while frequency controls how âmanyâ shakes happen per second. The length decides for how long the shake will last for, and the magnitude decreases over this time to zero.
By mixing and matching different values for these parameters different effects can be made. Here are a few examples:
- Gunshot: a short omnidirectional shake with low amplitude and high frequency. This gives a small kick that doesnât move the screen too much, just enough to confirm the firing. Fish Fight supports setting multipliers for X/Y movement, so a 1 for X and a smaller number for Y makes the player feel the direction of the action.
- Explosion: a medium-length omnidirectional shake with decent amplitude and lower frequency. This makes a kind of rumble that seriously jostles the screen. The bigger the explosive the lower the frequency!
- Jump impact: a directional sinusoidal shake makes the world bounce like a spring.
To calculate the final scene position, the current position of every active shake is added together. That value is then capped using a logarithmic function so that if many explosives go off at once, the scene does not fly off-screen. The second logarithm (log2x) is useful for this, as it is almost linear from 0-1 and then quickly flattens.
Particles
Particles like those in games rarely occur in real life, as most of us go through our daily routine avoiding high-impact situations. But games tend to be a bit more forceful and violent, and that of course means heaps of particles! Particles are a great way to create dynamic and exciting effects that further give impact and weight to actions, but also make the world seem more alive and responsive. Some examples are sparks flying when a bullet hits a wall or dust blowing around in a storm.
Legacy Documentation
After the Bevy rewrite, the Jumpy book was revised, but not all of the old pages have been migrated to the new revision.
The legacy documentation can still be read here, and while much of it is now out of date, some of the pages still have useful thoughts, and may be good to migrate to this book.