mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-13 12:45:13 +00:00
add new skill game-engine
This commit is contained in:
343
skills/game-engine/references/basics.md
Normal file
343
skills/game-engine/references/basics.md
Normal file
@@ -0,0 +1,343 @@
|
||||
# Game Development Basics
|
||||
|
||||
A comprehensive reference covering web game development technologies, game architecture, and the anatomy of a game loop.
|
||||
|
||||
Sources:
|
||||
- https://developer.mozilla.org/en-US/docs/Games/Introduction
|
||||
- https://developer.mozilla.org/en-US/docs/Games/Anatomy
|
||||
|
||||
---
|
||||
|
||||
## Web Technologies for Game Development
|
||||
|
||||
### Graphics and Rendering
|
||||
|
||||
- **WebGL** -- Hardware-accelerated 2D and 3D graphics based on OpenGL ES 2.0. Provides direct GPU access for high-performance rendering.
|
||||
- **Canvas API** -- 2D drawing surface via the `<canvas>` element. Suitable for 2D games, sprite rendering, and pixel manipulation.
|
||||
- **SVG** -- Scalable Vector Graphics for resolution-independent visuals. Useful for UI elements and simple vector-based games.
|
||||
- **HTML/CSS** -- Standard web technologies for building game UI, menus, HUDs, and overlays.
|
||||
|
||||
### Audio
|
||||
|
||||
- **Web Audio API** -- Advanced audio engine supporting real-time playback, synthesis, spatial audio, effects processing, and dynamic mixing.
|
||||
- **HTML Audio Element** -- Simple sound playback for background music and basic sound effects.
|
||||
|
||||
### Input and Controls
|
||||
|
||||
- **Gamepad API** -- Support for game controllers and gamepads, including button mapping and analog stick input.
|
||||
- **Touch Events API** -- Multi-touch input handling for mobile devices.
|
||||
- **Pointer Lock API** -- Locks the mouse cursor within the game area and provides raw coordinate deltas for precise camera/aiming control.
|
||||
- **Device Sensors** -- Accelerometer and gyroscope access for motion-based input.
|
||||
- **Full Screen API** -- Enables immersive full-screen game experiences.
|
||||
|
||||
### Networking and Multiplayer
|
||||
|
||||
- **WebSockets API** -- Persistent, bidirectional communication channel for real-time multiplayer, chat, and live updates.
|
||||
- **WebRTC API** -- Peer-to-peer connections for low-latency multiplayer, voice chat, and data channels.
|
||||
- **Fetch API** -- HTTP requests for downloading game assets, loading level data, and transmitting non-real-time game state.
|
||||
|
||||
### Data Storage and Performance
|
||||
|
||||
- **IndexedDB API** -- Client-side structured storage for save games, cached assets, and offline play support.
|
||||
- **Typed Arrays** -- Direct access to raw binary data buffers for GL textures, audio samples, and compact game data.
|
||||
- **Web Workers API** -- Background thread execution for offloading heavy computations (physics, pathfinding, AI) without blocking the main thread.
|
||||
|
||||
### Languages and Compilation
|
||||
|
||||
- **JavaScript** -- The primary language for web game development.
|
||||
- **C/C++ via Emscripten** -- Compile existing native game code to JavaScript or WebAssembly for web deployment.
|
||||
- **WebAssembly (Wasm)** -- Near-native execution speed for performance-critical game code.
|
||||
|
||||
---
|
||||
|
||||
## Types of Games You Can Build
|
||||
|
||||
The modern web platform supports a full range of game types:
|
||||
|
||||
- 3D action games and shooters
|
||||
- Role-playing games (RPGs)
|
||||
- 2D platformers and side-scrollers
|
||||
- Puzzle and strategy games
|
||||
- Card and board games
|
||||
- Casual and mobile-friendly games
|
||||
- Multiplayer experiences with real-time networking
|
||||
|
||||
---
|
||||
|
||||
## Advantages of Web-Based Game Development
|
||||
|
||||
1. **Universal reach** -- Games run on smartphones, tablets, PCs, and Smart TVs through the browser.
|
||||
2. **No app store dependency** -- Deploy directly on the web without store approval processes.
|
||||
3. **Full revenue control** -- No mandatory revenue share; use any payment processing system.
|
||||
4. **Instant updates** -- Push updates immediately without waiting for store review.
|
||||
5. **Own your analytics** -- Collect your own data or choose any analytics provider.
|
||||
6. **Direct player relationships** -- Engage players without intermediaries.
|
||||
7. **Inherent shareability** -- Games are linkable and discoverable via standard web mechanisms.
|
||||
|
||||
---
|
||||
|
||||
## Anatomy of a Game Loop
|
||||
|
||||
Every game operates through a continuous cycle of steps:
|
||||
|
||||
1. **Present** -- Display the current game state to the player.
|
||||
2. **Accept** -- Receive user input (keyboard, mouse, gamepad, touch).
|
||||
3. **Interpret** -- Process raw input into meaningful game actions.
|
||||
4. **Calculate** -- Update the game state based on actions, physics, AI, and time.
|
||||
5. **Repeat** -- Loop back to present the updated state.
|
||||
|
||||
Games may be **event-driven** (turn-based, waiting for player action) or **per-frame** (continuously updating via a main loop).
|
||||
|
||||
---
|
||||
|
||||
## Building a Game Loop with requestAnimationFrame
|
||||
|
||||
### Basic Main Loop
|
||||
|
||||
```javascript
|
||||
window.main = () => {
|
||||
window.requestAnimationFrame(main);
|
||||
|
||||
// Your game logic here: update state, render frame
|
||||
};
|
||||
|
||||
main(); // Start the cycle
|
||||
```
|
||||
|
||||
Key points:
|
||||
- `requestAnimationFrame()` synchronizes callbacks to the browser's repaint schedule (typically 60 Hz).
|
||||
- Schedule the next frame **before** performing loop work to maximize available computation time.
|
||||
|
||||
### Self-Contained Main Loop (IIFE)
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main() {
|
||||
window.requestAnimationFrame(main);
|
||||
|
||||
// Game logic here
|
||||
}
|
||||
|
||||
main();
|
||||
})();
|
||||
```
|
||||
|
||||
### Stoppable Main Loop
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main() {
|
||||
MyGame.stopMain = window.requestAnimationFrame(main);
|
||||
|
||||
// Game logic here
|
||||
}
|
||||
|
||||
main();
|
||||
})();
|
||||
|
||||
// To stop the loop:
|
||||
window.cancelAnimationFrame(MyGame.stopMain);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Timing and Frame Rate
|
||||
|
||||
### DOMHighResTimeStamp
|
||||
|
||||
`requestAnimationFrame` passes a `DOMHighResTimeStamp` to your callback, providing timing precision to 1/1000th of a millisecond.
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main(tFrame) {
|
||||
MyGame.stopMain = window.requestAnimationFrame(main);
|
||||
|
||||
// tFrame is a high-resolution timestamp in milliseconds
|
||||
// Use it for delta-time calculations
|
||||
}
|
||||
|
||||
main();
|
||||
})();
|
||||
```
|
||||
|
||||
### Frame Time Budget
|
||||
|
||||
At 60 Hz, each frame has approximately **16.67ms** of available processing time. The browser's frame cycle is:
|
||||
|
||||
1. Start new frame (previous frame displayed to screen)
|
||||
2. Execute `requestAnimationFrame` callbacks
|
||||
3. Perform garbage collection and per-frame browser tasks
|
||||
4. Sleep until VSync, then repeat
|
||||
|
||||
---
|
||||
|
||||
## Simple Update and Render Pattern
|
||||
|
||||
The simplest approach when your game can sustain the target frame rate:
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main(tFrame) {
|
||||
MyGame.stopMain = window.requestAnimationFrame(main);
|
||||
|
||||
update(tFrame); // Process game logic
|
||||
render(); // Draw the frame
|
||||
}
|
||||
|
||||
main();
|
||||
})();
|
||||
```
|
||||
|
||||
Assumptions:
|
||||
- Each frame can process input and update state within the time budget.
|
||||
- The simulation runs at the same rate as the display refresh (typically ~60 FPS).
|
||||
- No frame interpolation is needed.
|
||||
|
||||
---
|
||||
|
||||
## Decoupled Update and Render with Fixed Timestep
|
||||
|
||||
For robust handling of variable refresh rates and consistent simulation behavior:
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main(tFrame) {
|
||||
MyGame.stopMain = window.requestAnimationFrame(main);
|
||||
const nextTick = MyGame.lastTick + MyGame.tickLength;
|
||||
let numTicks = 0;
|
||||
|
||||
// Calculate how many simulation updates are needed
|
||||
if (tFrame > nextTick) {
|
||||
const timeSinceTick = tFrame - MyGame.lastTick;
|
||||
numTicks = Math.floor(timeSinceTick / MyGame.tickLength);
|
||||
}
|
||||
|
||||
queueUpdates(numTicks);
|
||||
render(tFrame);
|
||||
MyGame.lastRender = tFrame;
|
||||
}
|
||||
|
||||
function queueUpdates(numTicks) {
|
||||
for (let i = 0; i < numTicks; i++) {
|
||||
MyGame.lastTick += MyGame.tickLength;
|
||||
update(MyGame.lastTick);
|
||||
}
|
||||
}
|
||||
|
||||
MyGame.lastTick = performance.now();
|
||||
MyGame.lastRender = MyGame.lastTick;
|
||||
MyGame.tickLength = 50; // 20 Hz simulation rate (50ms per tick)
|
||||
|
||||
setInitialState();
|
||||
main(performance.now());
|
||||
})();
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- **Deterministic simulation** -- Game logic runs at a fixed frequency regardless of display refresh rate.
|
||||
- **Smooth rendering** -- Rendering can interpolate between simulation states for visual smoothness.
|
||||
- **Portable behavior** -- Game behaves the same on 60 Hz, 120 Hz, and 144 Hz displays.
|
||||
|
||||
---
|
||||
|
||||
## Alternative Architecture Patterns
|
||||
|
||||
### Separate setInterval for Updates
|
||||
|
||||
```javascript
|
||||
// Game logic updates at a fixed rate
|
||||
setInterval(() => {
|
||||
update();
|
||||
}, 50); // 20 Hz
|
||||
|
||||
// Rendering synchronized to display
|
||||
requestAnimationFrame(function render(tFrame) {
|
||||
requestAnimationFrame(render);
|
||||
draw();
|
||||
});
|
||||
```
|
||||
|
||||
Drawback: `setInterval` continues running even when the tab is not visible, wasting resources.
|
||||
|
||||
### Web Worker for Updates
|
||||
|
||||
```javascript
|
||||
// Heavy game logic runs in a background thread
|
||||
const updateWorker = new Worker('game-update-worker.js');
|
||||
|
||||
requestAnimationFrame(function render(tFrame) {
|
||||
requestAnimationFrame(render);
|
||||
updateWorker.postMessage({ ticks: numTicksNeeded });
|
||||
draw();
|
||||
});
|
||||
```
|
||||
|
||||
Benefits: Does not block the main thread. Ideal for physics-heavy or AI-intensive games.
|
||||
Drawback: Communication overhead between worker and main thread.
|
||||
|
||||
### requestAnimationFrame Driving a Web Worker
|
||||
|
||||
```javascript
|
||||
;(() => {
|
||||
function main(tFrame) {
|
||||
MyGame.stopMain = window.requestAnimationFrame(main);
|
||||
|
||||
// Signal worker to compute updates
|
||||
updateWorker.postMessage({
|
||||
lastTick: MyGame.lastTick,
|
||||
numTicks: calculatedNumTicks
|
||||
});
|
||||
|
||||
render(tFrame);
|
||||
}
|
||||
|
||||
main();
|
||||
})();
|
||||
```
|
||||
|
||||
Benefits: No reliance on legacy timers. Worker performs computation in parallel.
|
||||
|
||||
---
|
||||
|
||||
## Handling Tab Focus Loss
|
||||
|
||||
When a browser tab loses focus, `requestAnimationFrame` slows down or stops entirely. Strategies:
|
||||
|
||||
| Strategy | Description | Best For |
|
||||
|---|---|---|
|
||||
| Treat gap as pause | Skip elapsed time; do not update | Single-player games |
|
||||
| Simulate the gap | Run all missed updates on regain | Simple simulations |
|
||||
| Sync from server/peer | Fetch authoritative state | Multiplayer games |
|
||||
|
||||
Monitor the `numTicks` value after a focus-regain event. A very large value indicates the game was suspended and may need special handling rather than trying to simulate all missed frames.
|
||||
|
||||
---
|
||||
|
||||
## Comparison of Timing Approaches
|
||||
|
||||
| Approach | Pros | Cons |
|
||||
|---|---|---|
|
||||
| Simple update/render per frame | Easy to implement, responsive | Breaks on slow/fast hardware |
|
||||
| Fixed timestep + interpolation | Consistent simulation, smooth visuals | More complex to implement |
|
||||
| Quality scaling | Maintains frame rate dynamically | Requires adaptive quality systems |
|
||||
|
||||
---
|
||||
|
||||
## Performance Best Practices
|
||||
|
||||
- **Detach non-frame-critical code** from the main loop. Use events and callbacks for UI, network responses, and other asynchronous operations.
|
||||
- **Use Web Workers** for computationally expensive tasks like physics, pathfinding, and AI.
|
||||
- **Leverage GPU acceleration** through WebGL for rendering.
|
||||
- **Stay within the frame budget** -- monitor your update + render time to keep it under 16.67ms for 60 FPS.
|
||||
- **Throttle garbage collection pressure** by reusing objects and avoiding per-frame allocations.
|
||||
- **Plan your timing strategy early** -- changing the game loop architecture mid-development is difficult and error-prone.
|
||||
|
||||
---
|
||||
|
||||
## Popular 3D Frameworks and Libraries
|
||||
|
||||
- **Three.js** -- General-purpose 3D library with a large ecosystem.
|
||||
- **Babylon.js** -- Full-featured 3D game engine with physics, audio, and scene management.
|
||||
- **A-Frame** -- Declarative 3D/VR framework built on Three.js.
|
||||
- **PlayCanvas** -- Cloud-hosted 3D game engine with a visual editor.
|
||||
- **Phaser** -- Popular 2D game framework with physics and input handling.
|
||||
Reference in New Issue
Block a user