react-native-game-engine

repository·master·Indexed 25 days ago

https://github.com/bberak/react-native-game-engine

A library providing React Native components to construct interactive scenes using an update and draw lifecycle. It features the GameEngine component, which implements a Component-Entity-System (CES) pattern to manage game loops and entity systems, and the GameLoop component for simpler interactive scenes. The engine allows for custom renderers using standard React Native components, react-native-svg, or gl-react-native, and supports integration with external JavaScript physics engines like Matter JS.

Tokens
1.8K
Snippets
5
Records
10
Agent score
35%

What's inside react-native-game-engine

  1. Manage Physics and Renderers

    master

    Physics

    react-native-game-engine does not include a built-in physics engine. You are encouraged to integrate a JavaScript-based physics engine of your choice, such as Matter JS.

    Renderers

    You can choose how to render your entities. Supported options include:

    • Standard React Native components (View, Image)
    • react-native-svg for vector graphics
    • gl-react-native for WebGL/OpenGL rendering
  2. Implement a Component-Entity-System (CES) with GameEngine

    master

    The GameEngine component follows a Component-Entity-System architecture.

    • Entities: A map of objects where each key is a unique ID. Each entity contains a set of components (data) and an optional renderer (a React component).
    • Systems: Functions that process entities on every frame. A system receives entities and a second argument containing metadata like touches. Systems should return the updated entities object.
    • Renderers: React components that receive entity data via props to draw the entity on screen.

    Example Implementation

    1. Define a Renderer (renderers.js):
    import React, { PureComponent } from "react";
    import { StyleSheet, View } from "react-native";
    
    const RADIUS = 20;
    
    class Finger extends PureComponent {
      render() {
        const x = this.props.position[0] - RADIUS / 2;
        const y = this.props.position[1] - RADIUS / 2;
        return (
          <View style={[styles.finger, { left: x, top: y }]} />
        );
      }
    }
    
    const styles = StyleSheet.create({
      finger: {
        borderColor: "#CCC",
        borderWidth: 4,
        borderRadius: RADIUS * 2,
        width: RADIUS * 2,
        height: RADIUS * 2,
        backgroundColor: "pink",
        position: "absolute"
      }
    });
    
    export { Finger };
    1. Define a System (systems.js):
    const MoveFinger = (entities, { touches }) => {
      touches.filter(t => t.type === "move").forEach(t => {
        let finger = entities[t.id];
        if (finger && finger.position) {
          finger.position = [
            finger.position[0] + t.delta.pageX,
            finger.position[1] + t.delta.pageY
          ];
        }
      });
    
      return entities;
    };
    
    export { MoveFinger };
    1. Initialize the GameEngine (index.js):
    import React, { PureComponent } from "react";
    import { AppRegistry, StyleSheet, StatusBar } from "react-native";
    import { GameEngine } from "react-native-game-engine";
    import { Finger } from "./renderers";
    import { MoveFinger } from "./systems"
    
    export default class BestGameEver extends PureComponent {
      render() {
        return (
          <GameEngine
            style={styles.container}
            systems={[MoveFinger]}
            entities={{
              1: { position: [40,  200], renderer: <Finger />},
              2: { position: [100, 200], renderer: <Finger />},
              3: { position: [160, 200], renderer: <Finger />},
              4: { position: [220, 200], renderer: <Finger />},
              5: { position: [280, 200], renderer: <Finger />}
            }}>
            <StatusBar hidden={true} />
          </GameEngine>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: "#FFF"
      }
    });
    
    AppRegistry.registerComponent("BestGameEver", () => BestGameEver);
    import { GameEngine } from "react-native-game-engine"
  3. Quick Start with GameEngine

    master

    The GameEngine component is a React-friendly implementation of the Component-Entity-System (CES) pattern. It manages a game loop and provides an event/signaling pipeline.

    To use it, you need to define:

    1. Renderers: React components that represent your entities.
    2. Systems: Functions that contain your game logic (e.g., movement, collision).
    3. Entities: An object where each key is a unique ID and the value contains the entity's state and its renderer.

    Example implementation:

    import { GameEngine } from "react-native-game-engine";
    import { Finger } from "./renderers";
    import { MoveFinger } from "./systems";
    
    // ... inside a component render method
    <GameEngine
      style={styles.container}
      systems={[MoveFinger]}
      entities={{
        1: { position: [40, 200], renderer: <Finger />},
        2: { position: [100, 200], renderer: <Finger />}
      }}
    />
  4. Use the GameLoop component for simple scenes

    master

    The GameLoop component is a subset of GameEngine suitable for simple interactive scenes. It provides an onUpdate callback that fires approximately every 16ms (60 fps) and supplies access to touches, screen, layout, and time. Unlike GameEngine, it does not use a formal Entity-System pattern; instead, you typically use React state to drive the rendering of your components.

    import { GameLoop } from "react-native-game-engine";
    
    // ... inside a component
    updateHandler = ({ touches, screen, layout, time }) => {
      let move = touches.find(x => x.type === "move");
      if (move) {
        this.setState({
          x: this.state.x + move.delta.pageX,
          y: this.state.y + move.delta.pageY
        });
      }
    };
    
    render() {
      return (
        <GameLoop style={styles.container} onUpdate={this.updateHandler}>
          <View style={[styles.player, { left: this.state.x, top: this.state.y }]} />
        </GameLoop>
      );
    }
  5. Use default processors and renderers

    master

    The library exports several default implementations for common game engine tasks:

    • DefaultTouchProcessor: A default implementation for handling touch input.
    • DefaultRenderer: A default implementation for rendering entities.
    • DefaultTimer: A default implementation for managing time within the engine.
    import {
    	DefaultTouchProcessor,
    	DefaultRenderer,
    	DefaultTimer
    } from 'react-native-game-engine';