Inspiration

I have always enjoyed minimalist games with simple mechanics and ever-increasing difficulty. I believe that small actions, when done collectively, can generate huge impact. The average person generates around 4.9 pounds of trash per day, so separating trash is a small decision that anyone can take that in the long term, has a great impact on the environment. Hence, I wanted to develop a game that both educates people into the correct separation of litter, and encourages them to apply their learnings in the real world. With that in mind, I developed TrashBall, a minimalist game consisting on placing each trash item on the respective bin, and allowing users to upload pictures of littered trash to regain lives.

What it does

The game shows four labeled containers at the bottom, and a falling item. The user should move it horizontally so that it lands on the correct bin. Each time the item misses its correct bin, the trash level increases, reducing the vertical space and making each level harder. The game ends when the trash level is too high. However, the user might upload a picture of litter to regain lives. This picture is classified as trash/not-trash using a Machine Learning model. Additionally, on Android devises that support it, the high score can be saved as a collectible Google Wallet Pass.

How we built it

The game was developed using Flame, a Flutter package for easily creating games. Each item was created using the SpriteComponent class, which custom designs saved as images. This includes: trash balls and trash cans. The main game is called TrashGame and handles several aspects such as sizing of the elements (for responsive designs across several screens), falling, speed, etc.

  • On onLoad, items are placed on the screen and their sizes are calculated into a global variable
  • A currentTrashItem is generated, and a MoveByEffect effect is applied to it with variable speed. This causes the item to fall
  • Several responders for touch, pan, keyboard and mouse/trackpad move the item horizontally
  • Both TrashCans and TrashItems have CollisionFeedback such that when the types correspond (e.g., plastic with plastic), the method addScore is called on TrashGame, otherwise the missedScore method is called.
  • The update method checks the height of the trash mountain. When it exceeds certain height, it adds a GameOver screen.

The GameOverScreen is an overlay widget that (1) stores the high score in the device's storage and (2) allows the user to process an image. The package google_ml_kit is used for image labeling. The base model contains 400 entities, of which the following were picked to detect (soon to be) trash:

Set<String> trashLabels = {
      'Comics', 'Cheeseburger', 'Petal', 'Fast Food', 'Hot dog', 'Junk', 'Juice', 'Icicle', 'Flesh', 'Food', 'Fruit', 'Shell', 'Newspaper', 'Plant', 'Paper', 'Pizza', 'Sushi', 'Cup', 'Wine', 'Soil', 'Branch', 'Garden', 'Flower', 'Vegetable', 'Glasses', 'Bag'
    };

Whenever the classification model detects any of said entities, the label is resumed with half the penalization (mountain height reduced)

Lastly, using the library add_to_google_wallet, an Add To Google Wallet Button is shown. This allows to save passes with custom imagery.

Challenges we ran into

While Flame makes it very easy to develop games in Flutter, the controls needed lots of refinements. For example, originally tapping on the left half of the screen would move the item to the left and viceversa. However I soon found that the expected behavior should be relative to the item, not the screen (i.e., tapping to the left of the item should move it). Implementing the ML model also posed a challenge, mostly because of the bindings to local code on iOS (cocoapods), and permissions to access the camera and the gallery. Finally, the integration with Google Wallet was also a challenge as it involved a lot of steps outside for development (generating classes, setting up account, requesting approval, etc), especially since I do not have experience developing for the Play Store.

Accomplishments that we're proud of

I am very proud of how the game worked out, and had lots of fun playing it. Likewise, I am very proud of the visual style that was put together and the emphasis on player experience. This includes adding delightful animations, or drawing on the Google Wallet Passes. I think the inclusion of image classification not only makes the game more interesting, but also encourages people to go outside and actually help the environment in an active manner.

What we learned

While I had previously developed apps in Flutter (I won honorable mention in the Flutter Puzzle Hack a couple of years ago), and deployed them to the App Store, this challenge taught me a lot of new things. Firstly, I discovered Flame, an amazing library that handles some of the most tedious aspects of game development for you, so that the developer can focus on the game mechanics instead of boilerplate. I also learned about Google ML Kit library, which allows to perform Machine Learning operations on device (which I found to be really impressive). And since Flutter is cross-platform, it allows to have a single trained model to run anywhere. Finally, I learned about Google Wallet and how it can be used for more than just boarding passes and event tickets. I learned about all the different integrations it could have and how to customize passes to reflect a brand identity. Most importantly, while developing the game, I was very conscious of the different small ways in which we all can save the environment, and why it is important to spread that feeling to others.

What's next for Trash Ball

In the future I would like to add more levels (maybe with obstacles) and more trash items. Additionally, I would like to replace the current image classification model with CircularNet, a model trained on different types of waste. Also, I would like to bring feature parity across platforms, such as integrating with Apple Wallet, or bringing the image classification feature to the desktop. Finally, I would like to homogenise the visual style of the game.

Built With

Share this project:

Updates