Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AsCent — a money clicker (C++/WebAssembly + Supabase)

Tap to earn money. Every tap adds $0.01 to your balance (spendable cash) and your net worth (total ever earned). Spend the balance on upgrades, boosters, and new payment methods (Piggy Bank, Wallet, QR DuitSekarang, Debit Card, Bank, Vault). Auto-investment keeps earning while you're away. Net worth goes on a global leaderboard.

The important part: the client has no authority. Balance, net worth, upgrades, and level all live in Supabase and are only ever changed by server-side functions that validate and rate-limit every action. Editing anything in devtools changes what you see, never what you have. (See Security.)

index.html          the page shell
styles/main.css      all styling
src/                 front-end ES modules (no bundler needed)
  config.js            <-- YOU EDIT THIS: Supabase URL + anon key
  supabase.js          shared client
  auth.js              sign up / sign in / session
  api.js               the only file that calls the server functions
  store.js             tiny reactive state store
  engine.js            WASM bridge, canvas render loop, click batching
  sky.js               falling cash drops
  hud.js  shop.js  leaderboard.js  idle.js   UI modules
  main.js              entry point
wasm/
  engine.cpp           the C++ visual engine (compile this)
  game.js  game.wasm   GENERATED by the build — do not edit
db/                  SQL, run in order in the Supabase SQL editor
  01_schema.sql  02_config_data.sql  03_rls.sql  04_functions.sql
  05_leaderboard.sql  06_feedback.sql
  reset_players.sql    admin: wipe all player PROGRESS (keeps accounts)
  wipe_all_users.sql   admin: delete all accounts and their data
assets/              images (method-*.png objects, coin, background, icons, logo)
design/              optional sprite-generation prompts

1. Install Emscripten (one time)

The emsdk/ toolchain is already in this repo. If you ever need a fresh copy:

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest

2. Build the WASM

You must activate emsdk in every new terminal — that's what puts emcc on your PATH. If emcc says "command not found", you skipped this step.

Windows (PowerShell) — activate, then run the build as a single line (the \ line-continuations further down are Bash-only and break in PowerShell):

.\emsdk\emsdk_env.ps1
emcc wasm/engine.cpp -O2 -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME=createGame -s "EXPORTED_FUNCTIONS=['_engine_init','_engine_reconcile','_engine_tap','_engine_tick','_engine_display_cash','_engine_pulse','_engine_method_index','_engine_coin_count','_engine_coin_x','_engine_coin_y','_engine_coin_life']" -s "EXPORTED_RUNTIME_METHODS=['cwrap']" -o wasm/game.js

(Old Command Prompt: use emsdk\emsdk_env.bat instead of the .ps1.)

macOS / Linux (Bash):

source ./emsdk/emsdk_env.sh
emcc wasm/engine.cpp -O2 \
  -s WASM=1 \
  -s MODULARIZE=1 \
  -s EXPORT_NAME=createGame \
  -s "EXPORTED_FUNCTIONS=['_engine_init','_engine_reconcile','_engine_tap','_engine_tick','_engine_display_cash','_engine_pulse','_engine_method_index','_engine_coin_count','_engine_coin_x','_engine_coin_y','_engine_coin_life']" \
  -s "EXPORTED_RUNTIME_METHODS=['cwrap']" \
  -o wasm/game.js

This produces wasm/game.js and wasm/game.wasm. Re-run the emcc line any time you change wasm/engine.cpp. The first build is slow (Emscripten compiles and caches its system libraries once); later builds are quick.


3. Set up Supabase

  1. Create a project (free tier is fine).
  2. SQL Editor → run these files in order, each as a new query: db/01_schema.sql02_config_data.sql03_rls.sql04_functions.sql05_leaderboard.sql06_feedback.sql.
  3. Authentication → Providers → Email: make sure Email is enabled. For a quick start you can turn off "Confirm email" so sign-ups log in instantly; leave it on for a real deploy (users then confirm via email before signing in).
  4. Project Settings → API: copy the Project URL and the anon public key into src/config.js.

The signup trigger creates each player's profile and starting state automatically (everyone starts at the Piggy Bank).

Admin scripts (db/reset_players.sql, db/wipe_all_users.sql) are optional maintenance tools — run them by hand only when you want to reset progress or clear accounts. They are destructive and have no undo.


4. Run locally

WASM won't load from a file:// path, so serve the folder:

python3 -m http.server 8000
# open http://localhost:8000

Create an account, and start tapping.


5. Deploy

These are static files (index.html, styles/, src/, wasm/, assets/) plus your Supabase project. Drop the folder on any static host:

  • Vercel / Netlify / Cloudflare Pages: drag the folder in, or connect the repo.
  • Point your subdomain at it via the CNAME the host gives you.

One requirement: wasm/game.wasm must be served as application/wasm. Vercel, Netlify, and Cloudflare Pages all do this automatically.


Security

The design in one line: the client sends actions, never values.

  • No direct writes. RLS (db/03_rls.sql) lets a user read only their own row and gives no insert/update/delete on balance/net worth. The only way those change is through the SECURITY DEFINER functions in db/04_functions.sql.
  • Server-authoritative economy. do_click(n) credits at most elapsed_seconds × 20 clicks using the server clock, so autoclickers and "claim a huge number" attempts are both capped to human speed. Purchases recompute their price server-side and run in one atomic, row-locked transaction, so parallel requests can't double-spend.
  • Money model. Earning adds the same amount to both net_worth (total earned, never drops, the leaderboard score) and balance (spendable). Buying deducts from balance only, so spending never hurts your rank.
  • Idle income uses the server clock only (now() - last_idle_at, capped at 8h), so lying about time away earns nothing extra. Cash drops pay a fixed, cooldown-limited reward server-side.
  • The anon key is public on purpose. It only grants what RLS allows. The secret service_role key is never in the frontend.
  • The C++/WASM code has no authority. It runs in the browser and only drives visuals and an optimistic on-screen number; the server value always wins.

Honest limit: a human-speed autoclicker or a dedicated bot can still farm at a human rate, and someone can make multiple accounts. What's fully closed is the "edit a variable to set balance = 999999" class of cheat.


Make it yours

  • Balance / prices: edit the numbers in db/02_config_data.sql (method costs, multipliers, upgrade base costs, booster durations) and re-run that one file. Server constants (click cap, base tap, idle cap, cash-drop reward) are commented at the top of db/04_functions.sql.
  • Look: colors are CSS variables at the top of styles/main.css; per-method glow colors are in src/config.js; the wood texture is the --wood variable.
  • Sprites: optional — see design/ for ready-to-use generation prompts.
  • Donations: a Buy Me a Coffee button is in index.html (search "Buy Me a Coffee"). Replace YOUR_USERNAME in the link with your handle.

About

Mini game wrote in C++ and used Emscripten to convert it to WebAssembly

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages