{"id":45157244,"url":"https://github.com/davidmonterocrespo24/esp32s3-arcade-3d","last_synced_at":"2026-02-20T05:00:38.219Z","repository":{"id":338249814,"uuid":"1157175751","full_name":"davidmonterocrespo24/esp32s3-arcade-3d","owner":"davidmonterocrespo24","description":"An OutRun-style pseudo-3D racing game for the ESP32-S3 microcontroller with an ILI9341 320×240 SPI display. The same source compiles for both ESP32 hardware and Windows (via a Raylib-based emulator).","archived":false,"fork":false,"pushed_at":"2026-02-13T15:48:02.000Z","size":51407,"stargazers_count":47,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"road","last_synced_at":"2026-02-19T07:41:49.297Z","etag":null,"topics":["3d","arduino","esp32","game"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidmonterocrespo24.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T14:19:05.000Z","updated_at":"2026-02-19T06:11:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/davidmonterocrespo24/esp32s3-arcade-3d","commit_stats":null,"previous_names":["davidmonterocrespo24/esp32s3-arcade-3d"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidmonterocrespo24/esp32s3-arcade-3d","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmonterocrespo24%2Fesp32s3-arcade-3d","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmonterocrespo24%2Fesp32s3-arcade-3d/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmonterocrespo24%2Fesp32s3-arcade-3d/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmonterocrespo24%2Fesp32s3-arcade-3d/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidmonterocrespo24","download_url":"https://codeload.github.com/davidmonterocrespo24/esp32s3-arcade-3d/tar.gz/refs/heads/road","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmonterocrespo24%2Fesp32s3-arcade-3d/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29641927,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T03:21:14.183Z","status":"ssl_error","status_checked_at":"2026-02-20T03:18:24.455Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","arduino","esp32","game"],"created_at":"2026-02-20T05:00:26.441Z","updated_at":"2026-02-20T05:00:38.212Z","avatar_url":"https://github.com/davidmonterocrespo24.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ESP32 Pseudo-3D Racing Game\n\nAn OutRun-style pseudo-3D racing game for the ESP32-S3 microcontroller with an ILI9341 320×240 SPI display. The same source compiles for both ESP32 hardware and Windows (via a Raylib-based emulator).\n\n---\n\n## Screenshots\n\n### Video Demo\n\n![Game Demo](img/game.gif)\n\n### Images\n\n\u003cimg src=\"img/hardesp32.png\" alt=\"ESP32 Hardware\" \u003e\n\n![Game Screenshot 1](img/Captura%20de%20pantalla%202026-02-13%20112753.png)\n\n![Game Screenshot 2](img/Captura%20de%20pantalla%202026-02-13%20112759.png)\n\n![Game Screenshot 3](img/image.png)\n\n---\n\n## Features\n\n- **Pseudo-3D road rendering** — segment-based back-to-front painter's algorithm, classic arcade style\n- **3D player car** — OBJ mesh (428 vertices, 312 triangles) with scanline affine texture mapping and shadow\n- **Traffic system** — 6 AI cars with independent speeds and lane positions\n- **Procedural track** — randomized curves, elevation changes, tunnels, and buildings generated at startup\n- **Dynamic scenery** — pine trees, bushes, rocks, lamp posts, and 3D buildings with window patterns\n- **Day / sunset / night cycle** — smooth color palette transitions every ~180 km of distance\n- **Atmospheric fog** — exponential density toward the horizon\n- **Physics** — acceleration, friction coast-down, centrifugal drift on curves, hill gravity effects\n- **Collision detection** — crash with 2-second recovery\n- **Lap timing** — current and best lap displayed on the HUD\n- **HUD** — circular speedometer (0–300 km/h) with needle\n\n---\n\n## Hardware\n\n| Component | Details |\n| --------- | ------- |\n| MCU | ESP32-S3, 240 MHz dual-core, 8 MB PSRAM |\n| Display | ILI9341 TFT, 320×240, 16-bit RGB565 |\n| Input | 2 pushbuttons — GPIO 17 (left), GPIO 16 (right) |\n| Backlight | GPIO 39 PWM |\n| SPI | SCK=12, MOSI=11, MISO=13, CS=10, DC=9, RST=8 |\n\nCompiling for hardware: open in **Arduino IDE**, select **ESP32-S3 Dev Module**, install the **TFT_eSPI** library, then compile and upload.\n\n---\n\n## Controls\n\n| Action | Hardware | Emulator |\n| ------ | -------- | -------- |\n| Steer left | GPIO 17 button | Left arrow key |\n| Steer right | GPIO 16 button | Right arrow key |\n| Throttle | Automatic (autopilot) | Automatic |\n\n---\n\n## Build — Emulator (Windows)\n\nThe emulator uses [Raylib](https://www.raylib.com/) to render the display and mock the Arduino API.\n\n```bash\ncd emulator/\nmake\n./car_game_emu.exe\n```\n\nKill and rebuild:\n\n```bash\ntaskkill /F /IM car_game_emu.exe 2\u003enul\nrm -f car_game_emu.exe \u0026\u0026 make\n```\n\n---\n\n## Project Structure\n\n```text\ncar_game/\n├── car_game.ino           # Main game loop\n├── config.h               # All tunable constants\n├── structs.h              # Segment, RenderPt, TrafficCar data structures\n├── physics.cpp/.h         # Speed, drift, gravity, collisions, lap timing\n├── track.cpp/.h           # Procedural track generation\n├── render_road.cpp/.h     # Road, tunnel, buildings, fog\n├── render_player.cpp/.h   # 3D player car (OBJ + scanline texture)\n├── render_traffic.cpp/.h  # Traffic car geometry\n├── render_building.cpp/.h # 3D buildings with window styles\n├── render_hud.cpp/.h      # Speedometer and lap times\n├── colors.cpp/.h          # RGB565 palette, day/night/sunset lerp\n├── utils.cpp/.h           # easeInOut, expFog, lerpF, clampF, findSegIdx\n├── car2_mesh.h            # Generated: OBJ mesh as C static array\n├── car2_texture.h         # Generated: 128x128 RGB565 texture\n├── assets/\n│   ├── Car2.obj\n│   ├── car2.png\n│   ├── obj_to_header.py\n│   └── png_to_rgb565.py\n└── emulator/\n    ├── Arduino.h              # Mock Arduino API (millis, random, digitalRead)\n    ├── TFT_eSPI.cpp           # Maps sprite draw calls to Raylib\n    └── car_game_wrapper.cpp   # Includes ../car_game.ino as C++\n```\n\n---\n\n## Key Constants (`config.h`)\n\n| Constant | Default | Description |\n| -------- | ------- | ----------- |\n| `SPEED_MULTIPLIER` | 65.0 | Max speed (~246 km/h) |\n| `FRICTION` | 0.996 | Coast-down rate (~3.3 s from max) |\n| `CENTRIFUGAL` | — | Curve lateral drift force |\n| `GRAVITY_FACTOR` | — | Hill acceleration effect |\n| `ROAD_W` | 2000 | Road half-width in world units (~10.5 m real) |\n| `SEG_LEN` | 200 | Segment length in world units |\n\nBuilding density: `BUILDING_H_MIN/MAX`, `BUILDING_SEG_MIN/MAX`, `BUILDING_GAP_MIN/MAX`.\n\n---\n\n## Regenerating Asset Headers\n\nIf `assets/Car2.obj` or `assets/car2.png` change, regenerate the C headers:\n\n```bash\n# OBJ mesh -\u003e C header (requires Python 3)\npython assets/obj_to_header.py assets/Car2.obj \u003e car2_mesh.h\n\n# PNG texture -\u003e RGB565 C header (requires Pillow)\npython assets/png_to_rgb565.py assets/car2.png \u003e car2_texture.h\n```\n\n---\n\n## Architecture Notes\n\n**Rendering pipeline** — one back-to-front loop per frame:\n\n1. Sky (parallax background with road-curve offset)\n2. Road segments with fog, curb stripes, lane markings\n3. Tunnels and buildings (painter's order, farthest first)\n4. Traffic cars\n5. Player car — OBJ mesh, Z-sorted triangles, scanline affine texture mapping\n6. HUD overlay\n7. `spr.pushSprite(0,0)` — flip double buffer to display\n\n**Double buffering** — the full 320×240 RGB565 frame is composed in PSRAM before being pushed to the display, eliminating tearing.\n\n**World scale** — `ROAD_W = 2000` units ~= 10.5 m, so 1 unit ~= 5.25 mm.\n\n**Emulator internals** — `emulator/car_game_wrapper.cpp` `#include`s `../car_game.ino` so it compiles as C++ without modification. All Arduino API calls and TFT draw calls are transparently remapped to Raylib.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidmonterocrespo24%2Fesp32s3-arcade-3d","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidmonterocrespo24%2Fesp32s3-arcade-3d","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidmonterocrespo24%2Fesp32s3-arcade-3d/lists"}