Skip to content

Latest commit

 

History

History
178 lines (144 loc) · 6.18 KB

File metadata and controls

178 lines (144 loc) · 6.18 KB

Flappy G2 — Project Plan

A Flappy Bird clone for Even Realities G2 smart glasses.

Hardware Constraints

Constraint Value Impact
Display 576×288 px Full canvas, but...
Image container 200×100 px max Game renders in this window
Color depth 4-bit greyscale (16 levels) Simple sprites
Input Tap (click event) Single action = flap
Frame rate ~10-15 FPS realistic BLE bandwidth limited

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    G2 Display (576×288)                      │
│  ┌──────────────────────────────────────────────────────┐   │
│  │                 Text Container (ID: 1)               │   │
│  │          [Hidden behind image, captures events]      │   │
│  │                                                      │   │
│  │    ┌────────────────────────────────────────┐        │   │
│  │    │       Image Container (ID: 2)          │        │   │
│  │    │          200×100 px game area          │        │   │
│  │    │                                        │        │   │
│  │    │   ●                    ┃               │        │   │
│  │    │                        ┃     ┃         │        │   │
│  │    │           ┃            ┃     ┃         │        │   │
│  │    │           ┃                            │        │   │
│  │    └────────────────────────────────────────┘        │   │
│  │                                                      │   │
│  │              Score: 7       TAP TO FLAP              │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Container Strategy:

  1. Text container (full screen, isEventCapture: 1) — receives tap events, displays score/instructions
  2. Image container (200×100, centered) — game graphics rendered via Canvas → greyscale BMP

Game Design (scaled for 200×100)

Element Size Notes
Bird 8×8 px Simple circle or square
Pipe width 15 px Thick enough to see
Pipe gap 30 px Generous for small screen
Scroll speed 2 px/frame Slower for playability
Gravity 0.3 px/frame² Gentle
Flap velocity -4 px Upward impulse

File Structure

flappy-g2/
├── PLAN.md              # This file
├── README.md            # User-facing docs
├── LICENSE              # MIT
├── package.json         # Dependencies
├── vite.config.ts       # Vite config
├── app.json             # Even Hub manifest
├── index.html           # Entry point
├── src/
│   ├── main.ts          # App bootstrap, SDK init
│   ├── game.ts          # Game loop, physics, rendering
│   ├── renderer.ts      # Canvas → greyscale conversion
│   ├── types.ts         # Type definitions
│   └── styles.css       # Minimal styles
└── assets/
    └── (optional sprites)

Implementation Phases

Phase 1: Scaffold & Hello World

  • Initialize npm project
  • Configure Vite + TypeScript
  • Create app.json manifest
  • Display "Hello G2" on text container
  • Verify event capture works

Phase 2: Image Container

  • Create 200×100 Canvas
  • Convert Canvas → 4-bit greyscale buffer
  • Send to image container via updateImageRawData
  • Display static test image

Phase 3: Game Loop

  • Bird with gravity physics
  • Tap event → flap (negative velocity)
  • Ground collision detection
  • Basic game over state

Phase 4: Pipes

  • Pipe generation (random gap position)
  • Pipe scrolling (right to left)
  • Collision detection (bird vs pipes)
  • Score increment on pass

Phase 5: Polish

  • Start screen ("TAP TO START")
  • Game over screen with score
  • High score persistence (localStorage)
  • Sound effects (if audio API available)

Phase 6: Package & Publish

  • Test on real G2 hardware
  • Create .ehpk package
  • Write README with install instructions
  • Publish to GitHub

Technical Notes

Canvas → Greyscale Conversion

function canvasToGreyscale(ctx: CanvasRenderingContext2D): Uint8Array {
  const imageData = ctx.getImageData(0, 0, 200, 100);
  const pixels = imageData.data; // RGBA
  const grey = new Uint8Array(200 * 100);
  
  for (let i = 0; i < grey.length; i++) {
    const r = pixels[i * 4];
    const g = pixels[i * 4 + 1];
    const b = pixels[i * 4 + 2];
    // Convert to 4-bit (0-15)
    grey[i] = Math.round((0.299 * r + 0.587 * g + 0.114 * b) / 255 * 15);
  }
  
  return grey;
}

Event Handling Quirk

// CLICK_EVENT = 0 becomes undefined due to SDK bug
if (event.textEvent?.eventType === OsEventTypeList.CLICK_EVENT || 
    event.textEvent?.eventType === undefined) {
  bird.flap();
}

Frame Timing

Target ~100ms per frame (10 FPS). Use setTimeout not requestAnimationFrame since we're not rendering to browser canvas directly.

const FRAME_MS = 100;

function gameLoop() {
  update();
  render();
  sendToGlasses();
  setTimeout(gameLoop, FRAME_MS);
}

Dependencies

{
  "@evenrealities/even_hub_sdk": "^0.0.7",
  "typescript": "^5.x",
  "vite": "^7.x"
}

Testing

  1. Simulator: Use even-dev environment
  2. Real device: Sideload via QR code from Even Hub

License

MIT — open source for the Even Realities community.