DEV Community

Cover image for Stellar Pinball ๐Ÿช
Diego Cardoso
Diego Cardoso

Posted on • Edited on

Stellar Pinball ๐Ÿช

This is a submission for the Build Better on Stellar: Smart Contract Challenge : Build a dApp

What I Built ๐Ÿ”จ

A serverless pinball game to play in the browser.
The Scoreboard is stored inside an smart contract on Stellar Network. ๐ŸŒŒ
Cloudflare Pages was used to serve page assets to the client.

Welcome Screen - Stellar PinballGame Screen - Stellar PinballEnd Game Screen - Stellar PinballScoreboard Screen - Stellar Pinball

Demo ๐ŸŽฎ

How to play

Use the keys [spacebar] [A] [D].
To save your progress, at the end of the game use the Freighter Wallet on the Testnet.
Follow the next link to give it a try.

My Code ๐Ÿ“„

The full code can be found on the public repository here: https://github.com/diegocardoso93/stellar-pinball

The Soroban smart contract of this application is simple yet powerful. It explores the built-in SDK datastructures Map and Vec to store data. This allows the Scoreboard to run without needing server-side backend.

#![no_std]
use soroban_sdk::{
    contract, contractimpl, 
    contracttype, Env, vec,
    Vec, Address, Map, map
};

#[contract]
pub struct ScoreboardContract;

#[derive(Clone)]
#[contracttype]
pub enum DataKey {
    Scores
}

#[contractimpl]
impl ScoreboardContract {
    pub fn save_score(env: Env, player: Address, score: u32) -> bool {
        add_score(&env, player, score);
        true
    }
    pub fn show(env: Env) -> Map<Address, Vec<u32>> {
        let scores: Map<Address, Vec<u32>> = env.storage()
            .persistent()
            .get(&DataKey::Scores)
            .unwrap_or(map![&env]);
        scores
    }
}

fn add_score(env: &Env, player: Address, score: u32) {
    let mut scores: Map<Address, Vec<u32>> = env.storage()
        .persistent()
        .get(&DataKey::Scores)
        .unwrap_or(map![&env, (player.clone(), vec![&env])]);
    let mut player_scores = scores.get(player.clone()).unwrap_or(vec![&env]);
    player_scores.push_back(score);
    scores.set(player, player_scores);
    env.storage().persistent().set(&DataKey::Scores, &scores);
}
Enter fullscreen mode Exit fullscreen mode

Journey ๐ŸšŽ

At the beginning of the process of development it was necessary to open several browser tabs, looking for documentation mainly on how to use the SDK.
The official documentation links was used, in particular:

They are written in a very easy to follow way, which makes the learning process smoother.
To find out how to interact with the wallet, the User Guide > Using Freighter in a web app was used, which was also very helpful. Everyone who is starting out (like me) should check it out, huh? ๐Ÿ“–
Furthermore, the Okashi development environment made the mission of learning Soroban Smart Contract enjoyable and interactive.

For the next steps, the aim is to

  • add mobile-friendly controls
  • improve the game, making it more "money-driven-way" โ€” perhaps charging "coins" like a machine โ€” and distributing the value periodically among the players
  • review the contract from a security perspective, to avoid bad actors manipulating data writing
  • replay features for scoreboard plays
  • continue learning more about the Stellar ecosystem to build more complex dApps in the future ๐Ÿš€

Additional Prize Categories: Glorious Game

Thanks for your time!

Top comments (0)