About the project Movie Verse is a small arcade-style web game built with Vite + React + TypeScript and styled with Tailwind CSS. Players collect themed "stones", trigger visual effects, and submit scores to a leaderboard backed by Supabase. The app combines a lightweight game loop with UI components for score submission, leaderboards, and responsive gameplay.

Inspiration The project was inspired by cinematic, collectible mechanics (think "infinite" artifacts such as Infinity Stones) and lightweight browser arcade games. I wanted to blend a nostalgic arcade feel with modern web tooling so players could jump in quickly from any device and compete on a global leaderboard.

What I learned Modern frontend toolchains: configuring and optimizing a Vite + TypeScript project. Component-driven UI with React and Tailwind CSS; using shadcn-inspired UI patterns for consistent primitives. Real-time persistence and authentication basics with Supabase (storing scores, migrations, and env config). Building a performant canvas-based game loop and integrating it with React state without causing excessive re-renders. Devops basics: committing, pushing to GitHub, and handling nested repo issues and cleanup. How I built it High-level steps I followed:

Project scaffolding with Vite + React + TypeScript and adding Tailwind CSS. Component layout in src/components: GameCanvas.tsx for the main game loop and rendering. StoneCollection.tsx and InfinityStone.tsx for the collectible logic and visuals. Leaderboard.tsx + SubmitScoreDialog.tsx for score persistence and UX. Integrations: src/integrations/supabase/client.ts for Supabase connection and queries. supabase/migrations for schema versioning. UX polish: responsive layout in src/index.css and App.css, accessible controls, keyboard and touch handling via hooks/use-mobile.tsx. Testing locally (npm install, npm run dev) and pushing the project to GitHub in the movie-verse-craft folder. Scoring model (math) I implemented a scoring formula that rewards combos and speed. A compact example:

Base points for a stone: 𝑏 b Combo multiplier: 𝑐 c (number of consecutive successful collections) Speed factor: 𝑠 ∈ ( 0 , 1 ] s∈(0,1] (faster collections give 𝑠 s closer to 1) A simple scoring function:

score_gain

𝑏 ⋅ ( 1 + 𝛾 ⋅ 𝑐 𝛼 ) ⋅ 𝑠 score_gain=b⋅(1+γ⋅c α )⋅s where 𝛾

0 γ>0 and 𝛼 ∈ ( 0 , 2 ] α∈(0,2] tune how aggressively combos scale. For example, with

𝑏

10 b=10,

𝛾

0.5 γ=0.5,

𝛼

1.2 α=1.2,

𝑐

3 c=3, and

𝑠

0.95 s=0.95:

score_gain

10 ⋅ ( 1 + 0.5 ⋅ 3 1.2 ) ⋅ 0.95 ≈ 10 ⋅ ( 1 + 0.5 ⋅ 3.737 ) ⋅ 0.95 ≈ 10 ⋅ 2.8685 ⋅ 0.95 ≈ 27.25 score_gain=10⋅(1+0.5⋅3 1.2 )⋅0.95≈10⋅(1+0.5⋅3.737)⋅0.95≈10⋅2.8685⋅0.95≈27.25 This formula keeps base rewards predictable while letting skilled play compound rewards without unbounded exponential growth.

Performance and complexity The main render/update loop iterates over active stones; in the naive implementation this is 𝑂 ( 𝑛 ) O(n) per frame where 𝑛 n is the number of active stones. With typical limits (e.g., cap active stones at a small constant), this is performant for browsers. Collision checks are implemented with simple bounding-circle checks; each frame complexity is 𝑂 ( 𝑛 ) O(n) with constant-time checks. If 𝑛 n were to grow large, spatial partitioning (e.g., quadtrees) could reduce checks toward 𝑂 ( 𝑛 log ⁡ 𝑛 ) O(nlogn) in practice. Challenges faced Nested git repositories: I accidentally had a parent repo containing the project repo. I removed the parent .git and kept movie-verse-craft as the primary repo to avoid confusion and VS Code "Publish Branch" noise. State synchronization between a canvas-based game loop and React state: solved by limiting React re-renders (holding transient frame state in refs and writing persistent events to state only when necessary). Cross-device input: balancing touch, mouse, and keyboard controls for consistent UX required multiple testing rounds. Supabase migrations and env management: ensuring sensitive keys are kept out of README.md and .env is added to .gitignore. Files of interest README.md — project docs (can include this story) package.json — scripts and metadata src/components/GameCanvas.tsx — game loop + render src/integrations/supabase/client.ts — Supabase setup supabase/migrations/* — database schema Next steps and ideas Add optional authentication and personalized profiles. Improve leaderboards with pagination and filters (daily/weekly/global). Add replays or shareable clips for top runs. Add accessibility features: ARIA labels, high-contrast mode, and keyboard-only play.

Built With

  • and-storage)-?-see-supabase/-and-src/integrations/supabase/-apis-/-integrations:-@supabase/supabase-js-dev-tools-/-build:-vite
  • any
  • auth
  • builds
  • css-frameworks-/-libraries:-react-18
  • eslint
  • github
  • host
  • html
  • javascript
  • languages:-typescript
  • netlify
  • or
  • prettier-(if-configured)-testing-/-debugging:-browser-devtools
  • react-hook-form-auth-/-database-/-backend:-supabase-(database
  • react-router-rendering-/-ui:-canvas-(game-rendering-in-gamecanvas.tsx)-state-&-data:-@tanstack/react-query
  • shadcn-ui-(component-patterns)
  • simple-local-test-harness-(dev-server)-deployment-options:-vercel
  • static
  • supporting
  • tailwind-css
  • typescript
  • vite
Share this project:

Updates