Giter Site home page Giter Site logo

react-native-game-engine's Introduction

React Native Game Engine

React Native Game Engine · npm version mit license

Some components that make it easier to construct dynamic and interactive scenes using React Native.

If you are looking for the React (Web) version of this library, go to react-game-engine.

Table of Contents

Examples

Take a look at Studious Bear, a super-polished puzzle game with great visuals and music. One of the first published games to use RNGE.

See the React Native Game Engine Handbook for a complimentary app, examples and ideas.

Single Touch Preview Multi Touch Preview Rigid Bodies Preview

Quick Start

If you've used react-native-game-engine before and understand the core concepts, take a look at react-native-game-engine-template. It's a sort of game kickstarter project that allows you to prototype ideas quickly and comes preloaded with a bunch of stuff like:

  • A 3D renderer
  • Physics
  • Particle system
  • Crude sound API
  • Sprite support with animations
  • Etc

Otherwise, continue reading the quick start guide below.


Firstly, install the package to your project:

npm install --save react-native-game-engine

Then import the GameEngine component:

import { GameEngine } from "react-native-game-engine"

Let's code a scene that incorporates some multi-touch logic. To start with, let's create some components that can be rendered by React. Create a file called 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 };

Next, let's code our logic in a file called systems.js:

const MoveFinger = (entities, { touches }) => {

  //-- I'm choosing to update the game state (entities) directly for the sake of brevity and simplicity.
  //-- There's nothing stopping you from treating the game state as immutable and returning a copy..
  //-- Example: return { ...entities, t.id: { UPDATED COMPONENTS }};
  //-- That said, it's probably worth considering performance implications in either case.

  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 };

Finally let's bring it all together in our index.ios.js (or index.android.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 {
  constructor() {
    super();
  }

  render() {
    return (
      <GameEngine
        style={styles.container}
        systems={[MoveFinger]}
        entities={{
          1: { position: [40,  200], renderer: <Finger />}, //-- Notice that each entity has a unique id (required)
          2: { position: [100, 200], renderer: <Finger />}, //-- and a renderer property (optional). If no renderer
          3: { position: [160, 200], renderer: <Finger />}, //-- is supplied with the entity - it won't get displayed.
          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);

Build and run. Each entity is a "finger" and is assigned to a particular touch id. The touch ids increase as you place more fingers on the screen. Move your fingers around the screen to move the entities. As an exercise, try add a system that will insert another finger entity into the game state when a "start" touch event is encountered. What about adding a system that removes the closest entity from the game state when a "long-press" is encountered?

If you're curious, our GameEngine component is a loose implementation of the Compenent-Entity-System pattern - we've written up a quick intro here.

GameEngine Properties

Prop Description Default
systems An array of functions to be called on every tick. []
entities An object containing your game's initial entities. This can also be a Promise that resolves to an object containing your entities. This is useful when you need to asynchronously load a texture or other assets during the creation of your entities or level. {} or Promise
renderer A function that receives the entities and needs to render them on every tick. (entities, screen, layout) => { /* DRAW ENTITIES */ } DefaultRenderer
touchProcessor A function that can be used to override the default touch processing behavior DefaultTouchProcessor
timer An object that can be used to override the default timer behavior new DefaultTimer()
running A boolean that can be used to control whether the game loop is running or not true
onEvent A callback for being notified when events are dispatched undefined
style An object containing styles for the root container undefined
children React components that will be rendered after the entities undefined

GameEngine Methods

Method Description Args
stop Stop the game loop NA
start Start the game loop. NA
swap A method that can be called to update your game with new entities. Can be useful for level switching etc. You can also pass a Promise that resolves to an entities object into this method. {} or Promise
dispatch A method that can be called to dispatch events. The event will be received by the systems and any onEvent callbacks event

FAQ

Is React Native Game Engine suitable for production quality games?

This depends on your definition of production quality. You're not going to make a AAA title with RNGE. You could however create some more basic games (doesn't mean they can't be fun games), or even jazz up your existing business applications with some interactive eye candy.

Simple turn-based games, side-scrollers and platformers with a handful of entites and simple physics would be feasible. Bullet-hell style games with many enemies, particles and effects on the screen at one time will struggle with performance - for these sorts of projects React Native is probably not the right choice of technology at the moment.

Lastly, for quick prototyping, self-education, and personal projects - React Native (and RNGE) should be suitable tools. For large projects that are commercial in nature, my recommendation would be to take a look at more established platforms like Godot and Unity first.

Do you know of any apps that currently utilize this library?

Studious Bear and React Native Donkey Kong both use this library. The React Native Game Engine Handbook is a complimentary app that showcases some examples and ideas. If you're aware of any others or wouldn't mind a shameless plug here - please reach out.

How do I manage physics?

RNGE does not come with an out-of-the-box physics engine. We felt that this would be an area where the game designers should be given greater liberty. There are lots of JS-based physics engines out there, each with their pros and cons. Check out Matter JS if you're stuck.

Do I have a choice of renderers?

How you render your entities is up to you. You can use the stand React Native components (View, Image) or try react-native-svg or go full exotic with gl-react-native.

RNGE doesn't give me sensor data out of the box - what gives?

I felt that this would be a nice-to-have and for most use cases it would not be required. Hence, I didn't want to burden RNGE users with any native linking or additional configuration. I was also weary about any unnecessary performance and battery costs. Again, it is easy to integrate into the GameEngine and then RNGE Handbook will have an example using react-native-sensors.

Is this compatible with Android and iOS?

Yes.

Won't this kind of be harsh on the battery?

Well kinda.. But so will any game really! It's a bit of a trade-off, hopefully it's worthwhile!

Introduction

This package contains only two components:

  • GameLoop
  • GameEngine

Both are standalone components. The GameLoop is a subset of the GameEngine and gives you access to an onUpdate callback that fires every 16ms (or roughly 60 fps). On top of this, the GameLoop will supply a reference to the screen (via Dimensions.get("window")), touch events for multiple fingers (start, end, press, long-press, move) and time + deltas. The GameLoop is useful for simple interactive scenes, and pretty much stays out of your way.

The GameEngine is more opinionated and is a react-friendly implementation of the Component-Entity-Systems pattern. It provides the same features out of the box as the GameEngine but also includes a crude event/signaling pipeline for communication between your game and your other React Native components. You probably want to use the GameEngine to implement slightly more complex games and interactive scenes.

The Game Loop

The game loop is a common pattern in game development and other interactive programs. It loosely consists of two main functions that get called over and over again: update and draw.

The update function is responsible for calculating the next state of your game. It updates all of your game objects, taking into consideration physics, ai, movement, input, health/fire/damage etc. We can consider this the logic of your game.

Once the update function has done its thing - the draw function is responsible for taking the current state of the game and rendering it to the screen. Typically, this would include drawing characters, scenery and backgrounds, static or dynamic objects, bad guys, special effects and HUD etc.

Ideally, both functions complete within 16ms, and we start the next iteration of the loop until some loop-breaking condition is encountered: pause, quit, game over etc. This might seem like a lot of processing overhead, but unlike regular applications, games are highly interactive and ever changing. The game loop affords us full control over scenes - even when no user input or external events have fired.

The Game Loop vs React Native

A typical React Native app will only redraw itself when this.setState() is called on a component with some new state (for lack of better words). Often times, this is a direct response to user input (button presses, keystrokes, swipes) or other event (WebSocket callbacks, push notifications, etc).

This works perfectly fine (and is even ideal) for a business-oriented app - but it doesn't give the developer fine grained control to create highly interactive and dynamic scenes.

Unlike most other software, games keep moving even when the user isn’t providing input. If you sit staring at the screen, the game doesn’t freeze. Animations keep animating. Visual effects dance and sparkle. If you’re unlucky, that monster keeps chomping on your hero.

This is the first key part of a real game loop: it processes user input, but doesn’t wait for it. The loop always keeps spinning - Robert Nystrom

That said, React Native and game loops are not mutually exclusive, and we can use React Native Game Engine to bridge the two paradigms.

Using the GameLoop Component

The GameLoop component is suitable for simple scenes and interactions only. For more complex scenes and games, please take a look at the GameEngine component and have a quick read through Managing Complexity with Component Entity Systems

Firstly, install the package to your project:

npm install --save react-native-game-engine

Then import the GameLoop component:

import { GameLoop } from "react-native-game-engine"

Let's code a basic scene with a single moveable game object. Add this into your index.ios.js (or index.android.js):

import React, { PureComponent } from "react";
import { AppRegistry, StyleSheet, Dimensions, View } from "react-native";
import { GameLoop } from "react-native-game-engine";

const { width: WIDTH, height: HEIGHT } = Dimensions.get("window");
const RADIUS = 25;

export default class BestGameEver extends PureComponent {
  constructor() {
    super();
    this.state = {
      x: WIDTH / 2 - RADIUS,
      y: HEIGHT / 2 - RADIUS
    };
  }

  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>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#FFF"
  },
  player: {
    position: "absolute",
    backgroundColor: "pink",
    width: RADIUS * 2,
    height: RADIUS * 2,
    borderRadius: RADIUS * 2
  }
});

AppRegistry.registerComponent("BestGameEver", () => BestGameEver);

Behind the Scenes

  • The GameLoop starts a timer using requestAnimationFrame(fn). Effectively, this is our game loop.
  • Each iteration through the loop, the GameLoop will call the function passed in via props.onUpdate.
  • Our updateHandler looks for any move touches that were made between now and the last time through the loop.
  • If found, we update the position of our lone game object using this.setState().

Where is the Draw Function

Nice observation! Indeed, there is none. The logic of our scene is processed in the updateHandler function, and our drawing is handled by our component's out-of-the-box render() function.

All we've done here is hookup a timer to a function that fires every ~16ms, and used this.setState() to force React Native to diff the changes in our scene and send them across the bridge to the host device. React Native Game Engine only takes care of the game timing and input processing for us.

Managing Complexity with Component Entity Systems

Typically, game developers have used OOP to implement complex game objects and scenes. Each game object is instantiated from a class, and polymorphism allows code re-use and behaviors to be extended through inheritance. As class hierarchies grow, it becomes increasingly difficult to create new types of game entities without duplicating code or seriously re-thinking the entire class hierarchy.

               [GameEntity]
                    |
                    |
                [Vehicle]
               /    |    \
              /     |     \
             /      |      \
            /       |       \
   [Terrestrial] [Marine] [Airborne]
           |        |        |
           |        |        |
         [Tank]   [Boat]   [Jet]

How do we insert a new terrestrial and marine-based vehicle - say a Hovercraft - into the class hierarchy?

One way to address these problems is to favor composition over inheritance. With this approach, we break out the attributes and behaviours of our various game entities into decoupled, encapsulated and atomic components. This allows us to be really imaginative with the sorts of game entities we create because we can easily compose them with components from disparate domains and concerns.

Component entity systems are one way to organize your game entities in a composable manner. To start with, we take the common attributes (data) of our game entities and move them into siloed components. These don't have to be concrete classes, simple hash maps (or equivalent) and scalars will do - but this depends on the data you're storing.

  • Position: { x: 0, y: 0 }
  • Velocity: { x: 0, y: 0 }
  • Acceleration: { x: 0, y: 0 }
  • Mass: 1.0
  • Health: 100
  • Physics: Body b
  • Controls: { jump: 'w', left: 'a', crouch: 's', right: 'd' }

Examples of different types of components in a hypothetical programming language.

Your game entities will be reduced to lists/arrays of components and labeled with a unique identifier. An entity's components are by no means static - you're free to update components and even add or remove them on the fly. If our favourite Italian plumber ingests a mushroom, we simple double his velocity. If our character turns into a ghost - we remove his physics component and let him walk through walls.

  • Player#1: [Position, Velocity, Health, Sprite, Physics, Controls]
  • Enemy#1: [Position, Velocity, Health, Sprite, Physics, AI]
  • Platform#1: [Position, Sprite, Physics]
  • Platform#2: [Position, Sprite, Physics, Velocity] // <-- Moving platform!

All entities are assigned a unique id.

Since our entities are simple data holders now, we must move all our game logic into our systems. At its core, a system is a function that processes related groups of components and is called on each iteration of the game loop. The system will extract entities that contain the necessary components it requires to run, update those entities as necessary, and wait for the next cycle. For example, we could code a "Gravity" component that calculates the force of gravity and applies it to all entities that have an acceleration AND velocity AND mass component. Entities that do not contain these components will not be affected by gravity.

  • Gravity: (Acceleration, Velocity, Mass) => { // Update all matching entities // }
  • Render: (Sprite, Position) => { }
  • Movement: (Position, Velocity, Controls) => { }
  • Damage: (Health) => { }
  • Bot: (Position, Velocity, AI) => { }

The logic in a system is inherently reusable because it can be applied to all entities that meet the system's criteria.

How exactly you choose to define your components, entities and systems is up to you. You'll probably find that coming up with well-defined components and systems will take some practice - but the general pattern is conducive to refactoring and the long term benefits will outweigh the learning curve.

Additional CES Reading Material

Using the GameEngine Component

The GameEngine component is a loose implementation of a Component-Entity-Systems architecture. It is a plain React component that allows us to pass in a map of entities (and their components) and an array of systems that will process the entities on each frame. In addition, the GameEngine will provide touch feedback, screen size, layout and some other niceties to help us code our logic.

To begin with, install the package to your project:

npm install --save react-native-game-engine

Then import the GameEngine component:

import { GameEngine } from "react-native-game-engine"

Let's code a scene that incorporates some multi-touch logic. To start with, let's create some components that can be rendered by React. Create a file called 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 };

Next, let's code our logic in a file called systems.js:

const MoveFinger = (entities, { touches }) => {

  //-- I'm choosing to update the game state (entities) directly for the sake of brevity and simplicity.
  //-- There's nothing stopping you from treating the game state as immutable and returning a copy..
  //-- Example: return { ...entities, t.id: { UPDATED COMPONENTS }};
  //-- That said, it's probably worth considering performance implications in either case.

  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 };

Finally let's bring it all together in our index.ios.js (or index.android.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 {
  constructor() {
    super();
  }

  render() {
    return (
      <GameEngine
        style={styles.container}
        systems={[MoveFinger]} //-- We can add as many systems as needed
        entities={{
          1: { position: [40,  200], renderer: <Finger />}, //-- Notice that each entity has a unique id (required)
          2: { position: [100, 200], renderer: <Finger />}, //-- and a map of components. Each entity has an optional
          3: { position: [160, 200], renderer: <Finger />}, //-- renderer component. If no renderer is supplied with the
          4: { position: [220, 200], renderer: <Finger />}, //-- entity - it won't get displayed.
          5: { position: [280, 200], renderer: <Finger />}
        }}>

        <StatusBar hidden={true} />

      </GameEngine>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#FFF"
  }
});

AppRegistry.registerComponent("BestGameEver", () => BestGameEver);

Build and run. Each entity is a "finger" and is assigned to a particular touch id. The touch ids increase as you place more fingers on the screen. Move your fingers around the screen to move the entities. As an exercise, try add a system that will insert another finger entity into the game state when a "start" touch event is encountered. What about adding a system that removes the closest entity from the game state when a "long-press" is encountered?

Awesome Packages for Game Development

The following is a list of invaluable packages when it comes to coding interactive scenes. Please feel free to nominate others:

License

MIT License

Copyright (c) 2018 Boris Berak

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

react-native-game-engine's People

Contributors

anhba817 avatar bberak avatar bradonzhang avatar ej-sanmartin avatar jasonbristol avatar mchelen avatar sinxwal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-game-engine's Issues

Touch array is empty in iOS

I made an app it is working on android perfectly but on iOS touches array is empty.
I'm using touch to move entities on screen.
react-native: 0.63.2
matter-js: 0.14.2
react-native-game-engine: 1.2.0
Edit: Updated to latest version of react-native-game-engine still having the same issue.

Game lags when adding new bodies to the screen (only in release mode on real device iPhone6 and iPhone5S)

Hi,
Again I want to say thanks for this awesome library. I have been trying to create a simple game where new bodies are added to the screen and there's a main body that tries to catch or avoid incoming bodies. I used React Native Donkey Kong as reference while creating it. Everything works fine on the simulator (even in release mode on simulator), but when I run release mode on real device the game lags whenever a new body is added.

This is my code, please let me know if I am doing anything wrong.

`const { width, height } = Dimensions.get("screen");
const logoSize = Math.trunc(Math.max(width, height) * 0.075);
const engine = Matter.Engine.create({ enableSleeping: false });

engine.world.gravity.y = 0;

const world = engine.world;
const logoBody = Matter.Bodies.rectangle(width / 2, height / 1.15, logoSize, logoSize,
{
isStatic: true,
label: "logo",
collisionFilter: {
category: 1,
mask: 2,
},
}
);

Matter.World.add(world, [logoBody]);

const Physics = (entities, { time }) => {
let engine = entities.physics.engine;
Matter.Engine.update(engine, time.delta);
return entities;
};

let boxIds = 0;

let counter = 0;

let speed = 4;

let speedCounter = 0;

let running = true;

let gameOver = false;

let gravity = 1;

let Entities = {
physics: { engine: engine, world: world },
logoBody: { body: logoBody, size: [logoSize, logoSize], color: '#daa520', renderer: Box, render: { visible: true, opacity: 1, }, },
camera: { offsetY: 0 }
};

const MoveLogo = (entities, { touches, screen }) => {

speed = gameOver ? 4 : speedCounter%2===0 ? speed + 0.01 : speed;

running && Matter.Body.translate(logoBody, {x: 0, y: -parseFloat(speed).toFixed(2)});

running && touches.filter(t => t.type === "press").forEach(t => {

speedCounter += 1;

if (t.event.pageX > logoBody.bounds.max.x - (logoSize/2) && logoBody.bounds.max.x < width-(width/10)) {

  return Matter.Body.translate(logoBody, {x: Math.trunc(width/3), y: 0});

} else if (t.event.pageX < logoBody.bounds.min.x + (logoSize/2) && logoBody.bounds.min.x > width/10) {

  return Matter.Body.translate(logoBody, {x: -Math.trunc(width/3), y: 0});

}

});
return entities;
};

const Camera = (entities, { screen, animations }) => {

let logoBody = entities.logoBody;
let camera = entities.camera;
let targetY = logoBody.body.position.y + camera.offsetY;

let anchorY = screen.height * 0.85;
let diff = anchorY - logoBody.body.position.y - camera.offsetY;

camera.offsetY += diff * 0.85;

return entities;

};

const RemoveBodies = (entities, {events}) => {
let world = entities.physics.world;

let camera = entities.camera;

let logoBody = entities.logoBody;

let stopped = events.find(e => e.type === "stopped");

if (stopped) {
Object.values(entities).forEach(e => {
// e.body && console.log("STOPPPED", e.body.label);
e.body && e.body.label !== "logo" && Matter.World.remove(world, e.body);
// e.body && e.body.label !== "logo" && Matter.Body.scale(e.body, 0.1, 0.1, {x: e.body.bounds.min.x-1000, y: e.body.bounds.max.y});
});
logoBody.render.visible = true;
logoBody.render.opacity = 1;
Matter.Engine.clear(engine);
// camera.offsetY = 0;
gameOver = true;
running = false;
entities = Entities;
boxIds = 0;
speedCounter = 0;
}

let restart = events.find(e => e.type === "restart");

if (restart) {
Object.values(entities).forEach(e => {
// e.body && console.log("RESTARTING", e.body.label);
e.body && e.body.label !== "logo" && Matter.World.remove(world, e.body);
e.body && e.body.label !== "logo" && Matter.Body.scale(e.body, 0.1, 0.1, {x: e.body.bounds.min.x-1000, y: e.body.bounds.max.y});
});
// camera.offsetY = 0;
Matter.Engine.clear(engine);
gameOver = false;
entities = Entities;
boxIds = 0;
speedCounter = 0;
}

let cancel = events.find(e => e.type === "cancel");

if (cancel) {
Object.values(entities).forEach(e => {
// e.body && console.log("Cancel", e.body.label);
e.body && e.body.label !== "logo" && Matter.World.remove(world, e.body);
e.body && e.body.label !== "logo" && Matter.Body.scale(e.body, 0.1, 0.1, {x: e.body.bounds.min.x-1000, y: e.body.bounds.max.y});
});
// camera.offsetY = 0;
Matter.Engine.clear(engine);
entities = Entities;
boxIds = 0;
speedCounter = 0;
}

// console.log("entities", entities);

return entities;
};

let lastWp = null, lastAp = null, lastBlock = null, lastNull = null; lastGhost = null, lastSunglasses = null, lastLaugh = null;

const Dispatcher = (entities, {events, time, dispatch}) => {

if (running && lastBlock === null) {
lastBlock = time.current;
setTimeout(() => {
dispatch({type: "block"});
}, 300);
}

if (time.current - lastBlock > 1500) {
lastBlock = running ? time.current : null;
running && dispatch({type: "block"});
}

if (running && lastAp === null) {
lastAp = time.current;
setTimeout(() => {
dispatch({type: "coin"});
}, 2000);
}

if (time.current - lastAp > 6000) {
lastAp = running ? time.current : null;
dispatch({type: "coin"});
}

return entities;
};

const AddBodies = (entities, {events, screen}) => {

let world = entities.physics.world;

let camera = entities.camera;

let logoBody = entities.logoBody;

let coin = events.find(e => e.type === "coin");

if (coin) {
let rand = Math.trunc(Math.random()*10);

let coinBody = Matter.Bodies.circle(
  rand % 3 === 0 ? width/6 : rand % 7 === 1 ? width/2 : width-(width/6),
  -camera.offsetY,
  // 0,
  logoSize/1.25,
  {
    label: rand % 2 === 0 ? "AP-1" : "Spinner",
    collisionFilter: {
      category: 2,
      mask: 1,
    },
  }
);

Matter.World.add(world, [coinBody]);

entities[++boxIds] = {
  body: coinBody,
  size: [logoSize/1.25, logoSize/1.25],
  color: "#daa520",
  renderer: Box,
};

counter += 1;
}

let block = events.find(e => e.type === "block");

if (block) {
let rand = Math.trunc(Math.random()*10);

let blockBody = Matter.Bodies.rectangle(
  rand % 2 === 0 ? logoBody.body.position.x : rand % 3 === 0 ? width/6 : rand % 5 === 1 ? width/2 : width-(width/6),
  -camera.offsetY,
  // 0,
  logoSize*2,
  logoSize*2/5,
  {
    label: "Block-red",
    collisionFilter: {
      category: 2,
      mask: 1,
    },
  }
);

Matter.World.add(world, [blockBody]);

entities[++boxIds] = {
  body: blockBody,
  size: [logoSize*2, logoSize*2/5],
  color: "red",
  renderer: Box,
};

counter += 1;
}

return entities;
};

const CameraRenderer = (state, screen) => {
return (
<View style={{marginTop: state.camera.offsetY}}>
{Object.keys(state)
.filter(key => state[key].renderer)
.map(key => {
let entity = state[key];
if (typeof entity.renderer === "object")
return (
<entity.renderer.type
key={key}
{...entity}
screen={screen}
/>
);
else if (typeof entity.renderer === "function")
return (
<entity.renderer
key={key}
{...entity}
screen={screen}
/>
);
})}

);
};`

This is the GameEngine component:

<GameEngine ref={g => this.game = g} style={styles.container} systems={[Physics, MoveLogo, AddBodies, Camera, RemoveBodies, Dispatcher]} // Array of Systems entities={Entities} running={this.state.running} touchProcessor={DefaultTouchProcessor({ triggerPressEventBefore: 150, triggerLongPressEventAfter: 151 })} renderer={CameraRenderer} onEvent={this._handleEvent}> <StatusBar hidden={true} /> </GameEngine>

This lag only happens on release mode on a real device iPhone6 and iPhone5S. Release mode on simulator works find. Any help would be highly appreciated. Thank you in advance.

UPDATE: the game works fine on iPhone7, iPhoneX and iPhoneXS Max

Game Engine with sprite sheet package

Hi,

I would like to know if it's possible to add sprites sheets to game engine. I see rn-sprite-sheet package but i dont understand how combinate them. If someone did it or have any idea to how make it or any substitute, i'll take it!!

Thanks a lot,

Sincerely Yours!

Can't destroy previous entities when game reloads

I've got system function to handle events like this way:

export default (entities, { events }) => {
  events.forEach((event) => {
    switch (event.type) {
      case EV_CONTROL_CAMERA_SCALE:
        world_scale(entities, event.value, event.duration);
        break;
      default:
        break;
    }
  });

  return entities;
};

And function world_scale looks like:

const world_scale = (entities, scale_value, duration) => {
  const interval_timing = 30;
  const tick = Math.floor(duration / interval_timing);
  const ratio = (scale_value - 1) / tick;
  let counter = 0;
  const interval = setInterval(() => {
    Object.keys(entities).map((objectKey) => {
      entities[objectKey].body.scale += ratio;
    });
    counter++;
    if (counter === tick) {
      clearInterval(interval);
    }
  }, interval_timing);
};

This function scales all the entities smoothly in given duration, constantly. Like camera zooming. Function works perfectly until i exit the game by navigating into the other component and re-enter to the game component. (I'm using react-native-router-flux to navigate)
The problem is when i re-navigate into the game and dispatch the event EV_CONTROL_CAMERA_SCALE, then function world_scale will be working with previous entities (which should be not existing). But in the meantime entities already rendered on the screen and not scaling.
I think navigation is not the problem source. Every time when i navigate, i clear the previous state by using Actions.reset

Custom fonts used inside GameEngine not working

Not able to use custom fonts inside custom renderers for entities.
Fonts default to system default.
When rendered outside GameEngine component it works fine.
Also when used in GameEngine children it works fine. ----> <Text style={{ fontFamily: "Inter-Black" }}>Inter Black
react-native-cli: 2.0.1
react-native: 0.63.2
expo: 4.4.7
react-native-game-engine : 1.2.0

Best way to detect touch target

Hello. I tried to use your method to detect touch target:

let boxId = Object.keys(state).find(key => {
let body = state[key].body;
return (
body &&
distance([body.position.x, body.position.y], startPos) < 25
);
});

It works, but I think this is not better way to find object during each iteration. In same time your documentation has wrong approach

touches.filter(t => t.type === "move").forEach(t => {
let finger = entities[t.id];

This is don't work.

I noticed that every touch object has touch.event.target field. This is a number. An it's unique for each of object. But I can't combine this index and object from entities. Could you please help me?

Thanks a lot.

iOS Release build fails after adding RNGE

with following error: .../node_modules/rx/dist/rx.all.js: Cannot convert object to primitive value

Background
I am currently working on a little game and lately I tested a release build which failed. I tried to figure out the reason for the error and after stepping back my commits I noticed it was happening just after adding RNGE to my project. I am using newest Version of React Native (0.56.0) and React (16.4.1).

What exactly is failing?
Xcode Release Build fails with: error: File .../testproject.app/main.jsbundle does not exist.

The Error occurs at one of the last build steps: Run custom shell script 'Bundle React Native code and Images' when .../testproject/node_modules/react-native/scripts/react-native-xcode.sh is executed to build the main.jsbundle file.

It produces the following Error: .../testproject/node_modules/rx/dist/rx.all.js: Cannot convert object to primitive value which seems to happen in rx.all.js.

On debug builds no main.jsbundle is created because the metro-packager delivers it while run, so the error doesn't occur.

Steps to reproduce

It can also be reproduced by copying only the bundling command and run it in terminal:
node .../testproject/node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --reset-cache --bundle-output .../testproject.app/main.jsbundle --assets-dest .../testproject.app

Note
I shortened all paths with .../ due to privacy and better readability.

After reseting a level, getting random collisions in game

👋I'm not sure if this is an issue with Matter JS, or with RNGE, but I've got an issue that is plaguing me.

I've got a game, where a spacecraft dodges objects in space. Upon a collision, I reset the game. Note: I'm using Matter for physics.

I do the following upon reset...

Matter.World.clear(engine.world);
Matter.Engine.clear(engine);

// recreate world and swap game engine with new entities
this.refs.engine.swap(newEntities);

BUT when playing the reset game, my collision handler will register collisions with objects that aren't appearing on the screen. Almost like there is an object there and the image isn't being rendered. Just reaching out to see if I'm missing something basic. Thank you!

Trouble with Swap

Hi,

I am trying to build a game that has entities. Upon changing the level, there is a new main character, a new maze, and a new goal. I presume that to change entities for the Game Engine component I have to use swap(), but I can't seem to find the object that possesses this method. I've looked through some of the other posts and I tried to place refs inside the component and then to call it, but it doesn't seem to update my components, or it produces a can't find swap from undefined object error.

How do I use the swap() method, or any other method to switch out the entities?

This is my GameEngine component:

<GameEngine
         systems={[this.physics, this.updateGame]}
         entities={this._getEntities()}
         style={{paddingLeft: widthWindow * .05}}
         running={this.state.running}
         ref="engine"
         onEvent={this.handleEvent}
>
                </GameEngine>

And this is my swap use case at the bottom:

updateGame = (entities, {touches}) => {
        let move = touches.find(x => x.type === 'move');

        if (move) {
            // if (move.delta.pageX + move.delta.pageY > 3) {
            //     return entities;
            // }

            let newX = this.state.currentBall.position.x + move.delta.pageX;
            let newY = this.state.currentBall.position.y + move.delta.pageY;

            const newPosition = {x: newX, y: newY};
            Matter.Body.setPosition(this.state.currentBall, newPosition);

        }

        if (this.state.notTransitioning) {
            var collision = Matter.SAT.collides(
                this.state.currentBall,
                this.state.currentGoal);
            if (collision.collided) {

                this._addObjectsToWorld();
                let engine = Matter.Engine.create({enableSleeping: false});
                let world = engine.world;

                this.setState({
                    engine: engine,
                    world: world,
                });

                Matter.World.add(this.state.world, [
                    this.state.currentMaze,
                    this.state.currentBall,
                    this.state.currentGoal])

                this.refs.engine.swap(this._getEntities())

                this.setState({  // -- GameEngine 'running' property gets this state
                    running: true
                });

            }
        }
        return entities;
    };

Thanks!!!

Addition touch events to GameEngine

Is there a way to pass additional touch events to GameEngine? Or in other words can we configure GameEngine to receive inputs other than the default touch events?

If we are using game controllers with the device, we may need to handle these events instead of relying on touch events.

Currently systems components are invoked if there is any touch event and I would like to know if there is any way to send additional events along with it?

Question: Pausing and restarting a game

Greetings. I am a novice at game design and have two questions. I have a Modal component that exists outside of the GameEngine. It acts as a menu when you pause the game and is shown when this.state.pause is true

For pausing, I save it as this.state.pause on my React component containing the GameEngine which can be read by my gameSettings entity:
gameSettings: { getState: ()=>this.state }
This way, in my systems I can check if entities['gameSettings'].getState().pause is false before doing any further game logic.

  1. Is this the correct way of pausing a game or is there suppose to be some way to just stop the engine from updating somehow?

  2. If this same menu has a restart game button, what's the best way to restart the game to the beginning? Am I suppose to have a system that just resets the entities to initial or is there some way to reboot the GameEngine to the beginning?

I guess the crux of my problem is that I feel like a Game Menu shouldn't be considered an entity within the GameEngine, hence trying to make menu navigations exist at the react native level yet interact with the GameEngine somehow.

Great library and thanks for any feedback.

Handle non-fullscreen games

Currently the lib only supports fullscreen games, but what if we don't want the game to be fullscreen and display for example a bottom or top bar ?
This section could look more like:

  onLayoutHandler = ({ nativeEvent: { layout: { width, height }}}) => {
    this.screen = { ...Dimensions.get("window"), width, height, layout: true };
    this.forceUpdate();
  };

I would add something like this layout variable because between initialization and layout, screen is still equal to Dimensions.get("window") so you can check the variable to know if you must hide entities while it doesn't have the final dimensions

Game engine reference is undefined in Matter.js events

I'm following this tutorial on RNGE. However, when there is a collision, I'm met with this bizarre error:

TypeError: Cannot read property 'dispatch' of undefined, js engine: hermes

This is my truncated code in App.js

export default class App extends PureComponent {
  constructor(props) {
    super(props)

    this.state = {
      running: true,
    }

    this.gameEngine = null
    this.entities = this.setupWorld()
  }

  setupWorld = () => {
    const engine = Matter.Engine.create({enableSleeping: false})
    const world = engine.world

    Matter.Events.on(engine, 'collisionStart', function(event) {
      this.gameEngine.dispatch({
        type: 'collision'
      })
    })

    return {
      physics: {engine: engine, world: world},
    }
  }

  onEvent = e => {
    if (e.type === 'collision') {
      // do something
    }
  }

  render() {
    return (
        <GameEngine
          ref={ref => {
            this.gameEngine = ref
          }}
          style={styles.gameContainer}
          onEvent={this.onEvent}
          running={this.state.running}
          systems={[Physics]}
          entities={this.entities}>
          <StatusBar hidden={true} />
        </GameEngine>
    )
  }
}

My environment

"matter-js": "^0.14.2",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-game-engine": "^1.1.1",

I logged the value of this.gameEngine in the collisionStart event and it was always undefined. Any advice on how to proceed with debugging?

Update 1: Same result with Hermes disabled.

How to Pass parameters into a Renderer

Hi,

Thanks for the help with my previous question! I have a simpler question this time around. I am trying to do the following where I pass parameters to a renderer in order to change what images appears:

_getEntities = () => {
    if (this.state.currentLevel === 1) {
        return {
            physics: {engine: this.state.engine, world: this.state.world},
            currentItem: {
                body: this.state.currentItem,
                renderer: Character({body: this.state.currentItem, typeName: "currentItem"})},
            recycleBin: {
                body: this.state.bins.recycleBin,
                renderer: Character({body: this.state.bins.recycleBin, typeName: "recycleBin"})},
            trashCan: {
                body: this.state.bins.trashCan,
                renderer: Character({body: this.state.bins.trashCan, typeName: "trashCan"})}
        };
    }
};

The above code doesn't work. It seems that we pass the class instead of instances of the class. The following is a copy of the renderer file. What do you think I should do to pass options into the renderer class?

const Character = ({ body, typeName }) => {
  const {position} = body;

  const x = position.x;
  const y = position.y;

  if (typeName === "item") {
    return <Image
        source={paperBall}
        style={[styles.head, {left: x, top: y,}]}
    />;
  }
  else if (typeName === "trashCan")
  {
    return <Image
        source={trashCan}
        style={[styles.head, {left: x, top: y,}]}
    />;
  }
  else if (typeName === "recycleBin")
  {
      return <Image
          source={recycleBin}
          style={[styles.head, {left: x, top: y,}]}
      />;
  }

};

Rotation of boxes doesn't work

Hello! I start new project with command npx react-native init AwesomeProject. I inserted code from react-native-game-engine-handbook/app/physics/rigid-bodies/. App work but boxes don't rotate. If I start with expo, boxes rotate. What is the problem?

All code was copied from react-native-game-engine-handbook/app/physics/rigid-bodies/. I don't change nothing

Package.json

{
  "name": "AwesomeProjec",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "react": "16.9.0",
    "react-native": "0.61.5",
    "matter-js": "^0.14.2",
    "react-native-game-engine": "^1.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^0.0.5",
    "babel-jest": "^24.9.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.56.0",
    "react-test-renderer": "16.9.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

Video
Boxes.mov.zip

Android performance

I was very satisfied with my prototype's animation performance on iOS. I used the rigid bodies scene from react-native-game-engine-handbook as my starting point (matter.js physics). I was rendering entities using View and Image components from react-native.

However, after running the app inside an android emulator I noticed pretty terrible performance. Animating a simple cloud image across the screen was not smooth at all. It was also apparent that matter.js was "slowing down" at some points.

In the rigid bodies scene, you update the matter.js engine inside a system. After some messing around, I noticed that updating matter.js outside of a system removed the matter.js "slowing down" issue.

Old:

const Physics = (state, { touches, time }) => {
    let engine = state["physics"].engine;

    Matter.Engine.update(engine, time.delta);

    return state;
};

New:

let now = Date.now();
setInterval(() => {
    Matter.Engine.update(engine, Date.now() - now);
    now = Date.now();
}, 0);

I know close to nothing about game dev. Does moving the physics updater outside of a system seem like an okay approach? I'm not sure how else to provide a playable experience on Android.

Entities not firing the touch event with properly id

I reproduced the example on README, and looks like any touch have the id with value 0. I figured out an attribute t.event.target that change for each touch, but it not corresponds to the entity id. What am I doing wrong?

const MovePup = (entities, { touches }) => {
    touches.filter(t => t.type === "move").forEach(t => {
          console.log(t.id)

output:

0
0
...

Thanks a lot for this project. I'm a starter developer, and this is a good way to learn about game development in React Native.

Entities redraw

Hi!
I am using the react native game engine for making a simple tower defense game. I am a little new to react native and i don't know what am i doing wrong, when i want to move my monsters. The problem is, when my game is running, the monsters with the image doesn't move, only just when i hot reload the page with a source save, or pressing the home then opening the game again.

Here is my logic for moving the entitie group:

const Move  = (state) => {
    Object.keys(state).filter(key => state[key].monster).forEach(key => {
        let sys = state[key];
        sys.monster.forEach(
            m =>{ 
                if(m.position[0] >= 145 && m.position[1] <= 245) {
                        m.velocity = [ 0, 1]
                    }
                    if(m.position[1] > 245 && m.position[0] >= 145 && m.position[0] <= 250 ){
                        m.velocity = [1, 0]
                    }
                    if(m.position[0] > 385 && m.position[1] >= 100  ){
                        m.velocity = [0, -1]
                    }
                    if(m.position[0]> 364 && m.position[1] <= 120){
                        m.velocity = [1, 0]
                    }

                    if (m.position[0] > 600) {
                    m.position = [
                        -10,
                        60
                    ]; 
                    m.velocity = [1, 0]
                    gameStateStore.looseHealth();
                    } else {

                        m.position = [
                            m.position[0] += m.velocity[0] / 1.3,
                            m.position[1] += m.velocity[1] * 1.3
                        ]
                    }
            }
        )
    });

    return state;
}

Here is my renderer for the monsters and the monster group:

class Monster extends PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            x: 0,
            y: 0,
            src: require('./res/monster/hydra.png')
        }
    }

    render() {
        this.state.x = this.props.position[0] - R / 2;
        this.state.y = this.props.position[1] - R / 2;
        if (this.props.type == "hydra" && this.props.health > 0) {
            this.state.src = require('./res/monster/hydra.png')
        } else if (this.props.type == "golem" ) {
            this.state.src = require('./res/monster/Walk1.png')
        } else {
            this.state.src = require('./res/monster/Walk1.png')
        }

        return (
            <Image style={[styles.hydra, { left: this.state.x, top: this.state.y }]}
                source={this.state.src}  onTouchEndCapture={(evt) => this.touch(evt)} 
            />
        )
    }
}
  class MonsterGroup extends PureComponent {
    constructor(props) {
      super(props);
    }
  
    render() {
      return (
        <View>
          {this.props.monster.map((p, i) => (
            <Monster
              key={i}
              position={p.position}
              vector={ p.vector}
            />
          ))}
        </View>
      );
    }
  }

And finally here is my game element, but i don't know if it is important or not for the problem:

<GameLoop onUpdate={this._update}>
      <View style={styles.statBar}>
          <Text style={[{ marginRight: 5 }]}>{gameState.coin}</Text>
          <Image style={[{ height: 15, width: 12 }]} source={require('./res/coin.png')}></Image>
          <Text style={[{ marginLeft:20, marginRight: 5 }]}>{gameState.pHealth}</Text>
          <Image style={[{ height: 15, width: 18 }]} source={require('./res/hearth.png')}></Image>
        </View>
        <GameEngine style={styles.container}
          ref="engine"
          systems={[
            DinamicSpawn,
            Move,
            SpawnMonster,

          ]}
          //  entities = {[this.state.ent]}
          entities={{
            counter: { num: 0 },
            6: { position: [20, 140], renderer: <Tower /> },
            7: { position: [70, 140], renderer: <Tower /> },
            8: { position: [200, 140], renderer: <Tower /> },
            9: { position: [200, 190], renderer: <Tower /> },
            10: { position: [20, 10], renderer: <Tower /> },
            11: { position: [70, 10], renderer: <Tower /> },
            12: { position: [500, 80], renderer: <Tower /> },
            13: { position: [550, 80], renderer: <Tower /> },
            14: { position: [600, 80], renderer: <Tower /> },
            15: { position: [450, 80], renderer: <Tower /> },
            16: { position: [500, 200], renderer: <Tower /> },
            17: { position: [550, 200], renderer: <Tower /> },
            18: { position: [600, 200], renderer: <Tower /> },
            19: { position: [50, 50], renderer: <Road style={{ zIndex: 2 }} /> },
            monsters: {
              monster: [
                {
                  position: [20, 50], velocity: [1, 0], health: 50
                }
              ],
              renderer: MonsterGroup
            }
          }}
        >
          <StatusBar hidden={true} />
        </GameEngine>
        
      </GameLoop>

Additional infos:
The game is running, so i see when the health is dropping because of the monsters reaching their goal and i can activate towers. I done most of the code according to the handbook/table of contents particles entities. Also, i done the moving logic for just 1 entitie and it worked great. I checked with a simple View element, perhaps the problem was with the images element, but still nothing.

Thanks for the help! If need another info just say!

touches long-press does not work properly

Hi,
I'm a newbie of RNGE.
I've read your tutorial about using GameEngine: https://github.com/bberak/react-native-game-engine#using-the-gameengine-component and I want to try all touches event: press, start, end, move and long-press.
Just write to console if the event happen:
touches.filter(t => t.type === "long-press").forEach(t => {
console.log("Long press");
});
It works OK for press, start, end and move but for long-press it seem doesn't work properly. I tested many times but it can only detect some (and totally random, I don't know how to make the event happen).
Do you have any idea why this happen ?
I'm using react-native 0.61 and react-native-cli 2.0.1
Thank you

How to destroy entities?

What is the proper way to destroy entities? I see there is a method for swapping to a new set of entities, but I'm trying to just remove a single entity.

Also, thanks for the awesome engine! Loving it so far!

How to render composite bodies

Is there a way to render composite bodies created with MatterJS?
I'm trying to create a maze game. The walls are created using a composite body made up of rectangle bodies. I'm using a composite body so I can add the walls in one go:

<GameEngine
  style={styles.container}
  systems={[this.physics, this.moveBall]}
  entities={{
    physics: {
      engine: engine,
      world: world
    },
    playerOneBall: {
      body: ball,
      size: [BALL_SIZE, BALL_SIZE],
      renderer: Circle
    },
    mazeWalls: {
      body: maze,
      color: '#ccc',
      size: [10, 15],
      renderer: Rectangle
    }
  }}
>
</GameEngine>

But I couldn't figure out a way to render it properly. It looks like the only way is construct an object consisting of many rectangles to create the walls like so:

<GameEngine
  style={styles.container}
  systems={[this.physics, this.moveBall]}
  entities={{
    physics: {
      engine: engine,
      world: world
    },
    playerOneBall: {
      body: ball,
      size: [BALL_SIZE, BALL_SIZE],
      renderer: Circle
    },
    wall1: {
      body: maze,
      color: '#ccc',
      size: [10, 15],
      renderer: Rectangle
    },
   wall2,
   wall3..
  }}
>
</GameEngine>

Touch event not firing on the canvas

Hi there,

I've been playing around with your engine for a bit and don't quite understand why my clicks are not being registered. They fire properly when hitting sprites but don't when clicking on the canvas. I've tried to reproduce one of the example in your handbook repo (rigid bodies), which works fine on its end, but not on mine... Am I missing something?

import { fireEvent } from './systems';

...

const engine = Matter.Engine.create({ enableSleeping: false });
const world = engine.world;

return (
      <GameEngine
        systems={[fireEvent]}
        entities={{
          physics: { engine: engine, world: world }
        }}
      >
      </GameEngine>
)

and then:

const fireEvent = (state, { touches }) => {
	touches.filter(t => t.type === "press").forEach(t => {
		console.log(t)
	});

	return state;
};

export { fireEvent };

Thanks for your help!

redux?

Do you think is feasible and or interesting integrante with redux?

Renderer rotation issue

Hello everyone 👋

I am trying to rotate one of my elements on the screen and I do this with Matter.js and react-native-game-engine all together.

I have the following logic:

Count angle for rotation manually => set this angle to the Matter.js body => achieve this newly set angle inside my render via props => trying to rotate my View with transform.

So everything works well until the last step when I am trying to rotate my View. It is not rotating at all, but Matter.js body has newly set angle. I think the issue can be inside rendering logic, but still not sure. Tried a lot of solutions already. Any help is appreciated.

This is my code:

This is my renderer component

const Dolphin = props => {
  const width = props.size[0];
  const height = props.size[1];
  const x = props.body.position.x - width / 2;
  const y = props.body.position.y - height / 2;
  
  return (
    <View
      style={[
        {
          position: 'absolute',
          width,
          height,
          backgroundColor: props.color,
          transform: [{ rotate: `${parseInt(props.body.angle)}deg` }],
        },
        { left: x, top: y },
      ]}
    >
      <Text color="white">{props.title}</Text>
    </View>
  );
};

This is how I set angle with Matter.js:

onPress={event => {
        event.persist();
        const dolphin = gameEngineRef.current.state.entities.dolphin;
        const pressEventX = event.nativeEvent.locationX;
        const pressEventY = event.nativeEvent.locationY;

        const angle = countAngle(40, 40, pressEventX, pressEventY);

        Matter.Body.setAngle(dolphin.body, angle);
      }}

Removing bodies not working as expected

First of all thanks for this awesome library. I'm not sure what I'm doing wrong. I'm trying to create a simple game where some coins fall into the world from the top of the screen, and there is a body at the bottom which tries to catch those coins. Everything works fine but when I want to remove those falling bodies after they collide with the body catching them the falling body just freezes in it's place and isn't completely destroyed or removed from the scene. I tried the remove function also the Sleeping.set function but I still got the same result. I even tried to scale the body to 0.1 0.1 but then the body started bouncing off instead of being scaled down.

this is my code to remove the colliding bodies:

`componentDidMount() {
Matter.Events.on(engine, "collisionStart", event => {

  const { bodyA, bodyB } = event.pairs[0];

  console.log("event", event);

  console.log("colliding bodies", bodyA, bodyB);

  if (bodyB.label === "coin-1" || bodyB.label === "coin-2") Matter.Body.remove(world, bodyB);
});

};`

Can anyone help with what am I doing wrong, or how to solve this? Thanks in advance.

Need Typescript types

VS Code is throwing the following error when using in a typescript file:

Could not find a declaration file for module 'react-native-game-engine'. '/Users/...Project/node_modules/react-native-game-engine/index.js' implicitly has an 'any' type.
  Try `npm install @types/react-native-game-engine` if it exists or add a new declaration (.d.ts) file containing `declare module 'react-native-game-engine';`ts(7016)

This will require adding a package @types/react-native-game-engine

What are {touches, screen, time}?

Hi, I'm a newbie of React-native.
When I traced your code from system.js, I found these variables: touches, screen, time
But I don't know how it works since you didn't import or varify them initially.
It could be a silly problem, but I want to ask what can these variables do, and how them comes from.
Thank you.
touches

Multi-touch Support between GameEngine and View

Hello! I am making a game that a user may tap on both the GameEngine component and buttons
(implemented via View::onTouch) that are located outside of GameEngine concurrently.

On iOS, it works as expected: when one finger is placed on the GameEngine component, the user can still tap on a button that is located outside the GameEngine, vice versa.

On Android, however, when one finger is placed on the GameEngine component and the other finger taps on a button that is outside of GameEngine, the additional tap gesture is handled by GameEngine instead of the View button.

Do you have an insight into fixing this issue? Thanks!

Move Entities when user tap on screen.

Hi Admin.
I am using you engine to make a turn-based game.
I want to move character with animation to a point which user touch on screen.
I read your handbook, but it only has a move when user move you finger on screen (not a tab) or its move using applyForce in Matter. My game donot need to use physics.
Any idea for me ?
Sory, i'm a beginner of react native.

Thank for helping.

Xcode error: library not found for -lil2cpp (Linker command failed with exit code 1 (use -v to see invocation))

after built uinity export IOS, I have received UnityExport folder in ios folder, but when I build ios, i get xcode error.
there is my UnityConfig.xcconfig

//  UnityConfig.xcconfig
//  rnunitydemo
//
//  Created by xzper on 2018/3/6.
//  Copyright © 2018年 Facebook. All rights reserved.
//
UNITY_SCRIPTING_BACKEND = il2cpp;
GCC_PREFIX_HEADER = $(SRCROOT)/UnityExport/Classes/Prefix.pch;

HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/UnityExport/Classes" "$(SRCROOT)/UnityExport/Classes/Unity" "$(SRCROOT)/UnityExport/Classes/Native" "$(SRCROOT)/UnityExport/Libraries" "$(SRCROOT)/UnityExport/Libraries/libil2cpp/include" ${PODS_HEADER_PATHS};

LIBRARY_SEARCH_PATHS = $(inherited) "$(SRCROOT)/UnityExport/Libraries" "$(SRCROOT)/UnityExport/Libraries/libil2cpp/include" ${PODS_LIBRARY_PATHS};

// If using .net 4.0 in Unity, append -DNET_4_0 to OTHER_CFLAGS
OTHER_CFLAGS = $(inherited) -DINIT_SCRIPTING_BACKEND=1 -fno-strict-overflow -DRUNTIME_IL2CPP=1;

OTHER_LDFLAGS = $(inherited) -weak-lSystem -weak_framework CoreMotion -weak_framework GameKit -weak_framework iAd -framework AVFoundation -framework AudioToolbox -framework CFNetwork -framework CoreGraphics -framework CoreLocation -framework CoreMedia -framework CoreVideo -framework Foundation -framework MediaPlayer -framework MediaToolbox -framework Metal -framework OpenAL -framework OpenGLES -framework QuartzCore -framework SystemConfiguration -framework UIKit -liconv.2 -liPhone-lib -lil2cpp ${PODS_LIBRARIES};

CLANG_CXX_LANGUAGE_STANDARD = c++0x;
CLANG_CXX_LIBRARY = libc++;
CLANG_ENABLE_MODULES = NO;
CLANG_WARN_BOOL_CONVERSION = NO;
CLANG_WARN_CONSTANT_CONVERSION = NO;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = NO;
CLANG_WARN_ENUM_CONVERSION = NO;
CLANG_WARN_INT_CONVERSION = NO;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = NO;
CLANG_WARN__DUPLICATE_METHOD_MATCH = NO;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_OBJC_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_THUMB_SUPPORT = NO;
GCC_USE_INDIRECT_FUNCTION_CALLS = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64] = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = NO;
GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNUSED_FUNCTION = NO;

ENABLE_BITCODE = NO;

DEAD_CODE_STRIPPING = YES;

Simple game is lagging when i try to render more than 1 on screen

I am trying to implement a simple img tapping game with react native for learning purposes.

What I am trying to do is render some imgs with random locations on screen with small radius then increase it up to a value, after decrease it and finally remove the img from screen (or when tapped) - just like in this game: http://mouseaccuracy.com/

import React, { Component } from "react";
import { AppRegistry, StyleSheet, Dimensions, View,ToastAndroid,TouchableOpacity,Image,Text } from "react-native";

 
const { width: WIDTH, height: HEIGHT } = Dimensions.get("window");
import { GameLoop } from "react-native-game-engine";

export default class BestGameEver extends Component {
  constructor() {
    super();
    this.circleToSpawn;
    this.spawn= false;
    this.circleArray = [];
    this.timerCurrent= 0;
    this.playerHealth=100;
    this.enemyHealth=100;
    this.timerTotal = 1000;
    this.state = {
      circles:[],
    

 
    };
  }

  componentWillMount(){

    
  }

  generateCircle = ()=>{
    var shieldOrSword = Math.random();
    var randomX =Math.floor(Math.random()*(WIDTH-50-0+1)+0);
  var randomY  =  Math.floor(Math.random()*(HEIGHT-50-0+1)+0);
  var randomId = Math.floor(Math.random()*(9999999999-0+1)+0);
  var circle;
  if(shieldOrSword <=0.3){
  circle = {
   type:"sword",
   id:randomId,
   increase:true,
  x:randomX,
  y:randomY,
  width:5,
  height:5,
  borderRadius:5
  }
  }else{
  circle = {
   type:"shield",
   id:randomId,
   increase:true,
  x:randomX,
  y:randomY,
  width:5,
  height:5,
  borderRadius:5
  }
  }
  this.circleArray.push(circle)


    
  }
  
   updateCircle = ({ touches, screen, time })=>{
this.timerCurrent += time.delta
this.circleArray =  this.state.circles;

if(this.timerCurrent >= this.timerTotal) {

  this.generateCircle();

  this.timerCurrent -= this.timerTotal;
}

    this.state.circles.map((circle,i)=>{
if(circle.width <80 && circle.height <80 && circle.borderRadius <80 && circle.increase == true){
circle.width = circle.width+6;
circle.height = circle.height+6;
circle.borderRadius = circle.borderRadius+6;


for(var i=0;i<this.circleArray.length;i++){
  if(this.circleArray[i].id == circle.id){
    this.circleArray.splice(i,1);
    break;

  }
}
this.circleArray.push(circle)





}
 if(circle.width >= 80 && circle.height >= 80 && circle.borderRadius >= 80){
  circle.increase=false;


}
 if(circle.increase == false){

  circle.width = circle.width-6;
  circle.height = circle.height-6;
  circle.borderRadius = circle.borderRadius-6;
  
  
  for(var i=0;i<this.circleArray.length;i++){
    if(this.circleArray[i].id == circle.id){
      this.circleArray.splice(i,1);
      break;
  
    }
  }
  this.circleArray.push(circle)

}

if(circle.width <= 0 && circle.height <= 0 && circle.borderRadius <= 0){
  for(var i=0;i<this.circleArray.length;i++){
    if(this.circleArray[i].id == circle.id){
      this.circleArray.splice(i,1);
      break;
  
    }
  }  
  if(circle.type =="shield"){
    this.playerHealth=this.playerHealth-20;

  }
}
this.setState({circles:this.circleArray})



    })



   }
   spawner = ()=>{
    
 


   }
  
   pressed = (circle)=>{

for(var i=0;i<this.circleArray.length;i++){
  if(this.circleArray[i].id == circle.id){
    this.circleArray.splice(i,1);
    if(circle.type =="sword"){
      this.enemyHealth = this.enemyHealth-10;
       
    }
   
    break;

  }
}

   }
   renderSwordOrCircle = circle => {
    if (circle.type == "sword") {
      return (
        <TouchableOpacity
          style={{
            position: "absolute",
            width: circle.width,
            height: circle.height,
            borderRadius: circle.borderRadius,
            left: circle.x,
            top: circle.y
          }}
          key={circle.id}
          onPress={() => this.pressed(circle)}
        >
        
          <Image
            style={{
              flex: 1,
              width: null,
              height: null,
              resizeMode: "contain"
            }}
            source={require("./assets/sword.png")}
          />
        </TouchableOpacity>
      );
    } else {
      return (
        <TouchableOpacity
        key={circle.id}

          style={{
            position: "absolute",
            width: circle.width,
            height: circle.height,
            borderRadius: circle.borderRadius,
            left: circle.x,
            top: circle.y
          }}
          onPress={() => this.pressed(circle)}
        >
          <Image
            style={{
              flex: 1,
              width: null,
              height: null,
              resizeMode: "contain"
            }}
            source={require("./assets/shield.png")}
          />
        </TouchableOpacity>
      );
    }
  };
   renderCircles = ()=>{
if(this.state.circles.length !=0){
return(
  this.state.circles.map((circle,i)=>{
    return(

      this.renderSwordOrCircle(circle)
    )
    
    
        })




)

 


}


   }

 renderHealth = () =>{
return(
  <View>
 <Text style={{position: "absolute", top: 0, left: 0}}>{this.playerHealth}</Text>
  <Text style={{position: "absolute", top: 0, right: 0}}>{this.enemyHealth}</Text>
  </View>
 

)



 }


  render() {
    return (
      <GameLoop style={styles.container} onUpdate={this.updateCircle}>
 {this.renderHealth()}
 {this.renderCircles()}

    </GameLoop>
    
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#FFF"
  }
});

,How do i optimize this to spawn more than 1 at the same time on screen ?

Define shape for physics body

Hello everyone!

I am using react-native-game-engine and matter-js for my application and I want to render a shape of my SVG element for example. On the react-native side it works great because I just show it inside my renderer component with react-native-svg. But the issue is that I also need a matter-js physic body to have the same shape in order for physics to work correctly.

I tried using Matter.Bodies.fromVertices method, but have a lot of issues during SVG conversion, so that was unsuccessful. I also found this guide https://www.codeandweb.com/physicseditor/tutorials/how-to-create-physics-shapes-for-phaser-3-and-matterjs, but it won't work because it is using Matter.Render and I am using react-native-game-engine instead.

So the question is how to render custom shapes and what is the preferable way to create them? Maybe tree-js will fit better for that?

Is it possible to use phaser with react-native-game-engine?

Hello,
Thanks for this making this package. I'm looking to integrate a game into a react-native app, and i'm little lost as i cant find resources on how to handle things like tile-maps and level generation. I ask if a can use phaser with this lib because there is a lot of resources around it.

It would be great if game dev tutorials are made using react-native-game-engine.

Thank you.

Use Animated with mutiles Images (Sprite)

I try to use Animated with transition transform to anime the image up to down with loop but I need to create animation image, I can do this with .setState but it will update the all component and break my transition, any help?

Donkey Kong animation.js recursive

I've used https://github.com/bberak/react-native-donkey-kong/blob/master/src/systems/animation.js to make timed animation. (Might be irrelevant for Game Engine)

Code looks like:

const time_sequence = [1000, 3000, 4000, 7000];

const outsideRecursiveFunction = (index) => {
  if (time_sequence.length === index) return 0;
  console.log('test ', index);
  outsideRecursiveFunction(++index);
}

const moveSequence = (index) => {
  if (index === time_sequence.length) return 0;
  component.animations.moveSequence = {
    args: {},
    duration: time_sequence[index],
    animate(component, percent, args) {
      // -- Some animation
    },
    complete(component) {
      moveSequence(++index) // -- function returns undefined
      outsideRecursiveFunction(++index); // -- function works fine
    }
  };
};

I don't know this is correct use of animation.js system. But worth trying i think.

TypeError with system args

Hi, i'm new and tried to use react-native-game-engine but i got an error when i create a new systems for . After some research still dont understand why.
Capture d’écran 2020-02-06 à 12 23 08

i'm at the beginning so this is my code.

Capture d’écran 2020-02-06 à 12 25 08

and my systems code

Capture d’écran 2020-02-06 à 12 25 47

How to add svg children?

Hi there, thanks for this great library, I really like the way it separates the concerns and organizes the code.

I am trying to use this with react-native-svg and have it working to some degree. However, when I attempt to go beyond a single entity and dynamically add new svg chilren entities to the parent svg I am stuck at a wall.

Essentially, I am able to make the children available inside the SVG container, however I get the following error when it goes to render:

...ORTCView_Invalidate]: Unrecognized selector sent to instance )x12345678

My latest attempt is below...
In NoteBubble.js:

// imports etc....
class Renderer extends Component {
  render() {
      const { position, width, height } = this.props;
      const x = position[0];
      const y = position[1];
      return (
        <Rect
          x={x}
          y={y}
          width={width}
          height={height}
          fill="yellow"
        />
      );
  }
}

export default (
  position,
  key,
  width = 10,
  height = 10,
) => ({
  position,
  key,
  width,
  height,
  renderer: <Renderer key={key} />,
});

In SvgCanvas.js:

// imports etc ...
class SvgCanvas extends Component {
  render() {
    const { entities } = this.props;
    return (
      <Svg
        width={100}
        height={100}
        viewBox={`0 0 100 100`}
      >
        {entities.map(e => e.renderer)}
      </Svg>
    );
  }
}
export default SvgCanvas;

In systems.js:

import NoteBubble from '../entities/NoteBubble';

function MoveComposition(entities) {
  if (entities.svgCanvas.entities.length) {
    entities.svgCanvas.entities.forEach(bubble => {
      bubble.position[0] += 1;
    });
  }
  return entities;
}

function CreateBubble(entities, { touches }) {
  touches
    .filter(t => t.type === 'press')
    .forEach(t => {
      const bubbleIdx = entities.svgCanvas.entities.length;
      const key = `bubble-${bubbleIdx}`;
      const newBubble = NoteBubble([t.event.pageX, t.event.pageY], key);
      entities.svgCanvas.entities.push(newBubble);
      entities[key] = newBubble;
    });
  return entities;
}

export default [CreateBubble, MoveComposition];

in App.js

export class Designer extends PureComponent {
  render() {
    return (
      <Container>
        <Content>
          <GameEngine running systems={Systems} entities={{
              svgCanvas: {
                 entities: [],
                 renderer: <SvgCanvas />,
              },
          }} />
        </Content>
      </Container>
    );
  }
}

Functions not in TypeScript definition files

I haven't checked the other classes, but GameEngine.js does not appear to have its functions referenced in react-native-game-enging.d.ts:

    export interface GameEngineProperties {
      systems?: any[];
      entities?: {} | Promise<any>;
      renderer?: any;
      touchProcessor?: any;
      timer?: any;
      running?: boolean;
      onEvent?: any;
      style?: StyleProp<ViewStyle>;
      children?: React.ReactNode;
    }
  
    export class GameEngine extends React.Component<GameEngineProperties> {}

Should GameEngine not be:

  export class GameEngine extends React.Component<GameEngineProperties> {
      dispatch: (event:any) => void;
      start: () => void;
      stop: () => void;
      swap: ({}:any | Promise) => void | Promise<void>
    }

Or something similar to?

Is this an issue for other classes?

Does it make sense to use the GameEngine between other components like View

When I am trying to add </GameEngine> between other </View> components however its sensibility decreases a lot and also it definitely becomes unable to use. When I define objects for to appear at the beginning of render. They scattering out and sort of teleporting through other components they even can pass through other objects like they never stops.

Below is how I am trying to use the <GameEngine> component

I want to ask that if I should only use <GameEngine> as the most upper JSX component ?

Thanks.

import React from 'react'
import { View, TouchableOpacity, Dimensions
} from 'react-native'
import _ from 'lodash'
import AmountWithCurrency from "../../text/AmountWithCurrency"
import {GameEngine} from "react-native-game-engine"
import {Physics, CreateBox, MoveBox, CleanBoxes} from "./systems"
import {Box} from "./renderers";
import Matter from 'matter-js'
import {Ball2} from "./Ball2"

const isAction = false;

class Balls extends React.Component {
    state = {}

    render() {
        const {currency, data, totalPrice, isAmount, type} = this.props
        //const { coordinate, showTooltip, name, price } = this.state
        const sortedData = _.reverse(_.sortBy(data, ['price']))

        const {width, height} = Dimensions.get("window")
        const engine = Matter.Engine.create({enableSleeping: false})
        const world = engine.world
        const ball1 = Matter.Bodies.circle(60, 80, 25,
            {frictionAir: 0.021})      //first two parameters are for starting position of balls or any other objects
        const ball2 = Matter.Bodies.circle(80, 80, 25,
            {frictionAir: 0.021})
        const ball3 = Matter.Bodies.circle(55, 50, 25,
            {frictionAir: 0.021})
        const floor = Matter.Bodies.rectangle(
            width / 2,  //x
            height + 90, //y
            width, //width
            10, //height
            {isStatic: true}) //options
        const constraint = Matter.Constraint.create({
            label: "Drag Constraint",
            pointA: {x: width, y: height},
            pointB: {x: width, y: height},
            length: 1,
            stiffness: 1,
            angularStiffness: 0,
        })

        Matter.World.add(world, [ball1, floor])
        Matter.World.add(world, [ball2])
        Matter.World.add(world, [ball3])
        Matter.World.addConstraint(world, constraint)

        return (
            <TouchableOpacity
                activeOpacity={1}
                style={{
                    marginHorizontal: -16,
                    marginTop: 15,
                    flexDirection: 'column',
                    justifyContent: 'center',
                    backgroundColor: 'green'
                }}
            >
                <View style={{flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 35}}>
                    {!_.isEmpty(sortedData) &&
                    sortedData.map((item, index) =
                        return index < 3 ? (
                            <View
                                key={index}
                                style={{
                                    flexDirection: 'row',
                                    marginBottom: 20
                                }}
                            >
                                <View
                                    style={{
                                        height: 8,
                                        width: 8,
                                        backgroundColor: color,
                                        borderRadius: 8,
                                        marginTop: 5
                                    }}
                                />
                                <View style={{flexDirection: 'column', marginLeft: 12}}>
                                    <Text style={{color: '#2E3D5C', fontWeight: '600'}}>
                                        {item.name}
                                    </Text>
                                    <Text
                                        style={{
                                            marginTop: 5,
                                            color: 'rgba(46, 61, 92, 0.4)'
                                        }}
                                    >
                                        {(100 * (item.price / totalPrice) || 0).toFixed(1) + ' %'}
                                    </Text>
                                </View>
                            </View>
                        ) : null
                    })}
                </View>
               <GameEngine
                        style={{width: width, height: 500,backgroundColor:'brown'}}
                        systems={[Physics, CreateBox, MoveBox, CleanBoxes]}
                        entities={{
                            physics: {engine: engine, world: world, constraint: constraint},
                            ball1: {body: ball1, size: [50, 50], color: "green", renderer: Ball2},
                            ball2: {body: ball2, size: [50, 50], color: "blue", renderer: Ball2},
                            ball3: {body: ball3, size: [50, 50], color: "yellow", renderer: Ball2},
                            floor: {body: floor, size: [width, 10], color: "#86E9BE", renderer: Box},
                        }}
                    >
                    </GameEngine>
                <View
                    style={{
                        justifyContent: 'center',
                        alignItems: 'center',
                        marginTop: 20
                    }}
                >
                    <AmountWithCurrency
                        currency={currency}
                        currencyColor={'#8992A3'}
                        currencySize={14}
                        amountTextStyle={{fontSize: 15, fontWeight: '600'}}
                        amount={totalPrice}
                        width={180}
                    />
                    <Text style={{color: '#8992A3', fontSize: 11, marginTop: 4}}>
                        total
                    </Text>
                </View>
            </TouchableOpacity>
        )
    }
}

export default Balls

Recommended way for moving the viewport/camera

Hi,

I've started playing around with RNGE and MatterJS, so far i'm really enjoying it. I've hit an issue when trying to move the viewport though. People using MatterJS seems to use Matter.Bounds for this, but it seems to use window/document functions which react-native obviously doesn't have access to.

I could just use an object with x,y in it and offset all other renderers by that amount, wondering if there's a better way though.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.