react-game-kit icon indicating copy to clipboard operation
react-game-kit copied to clipboard

How to put `Body` inside a different Component?

Open Talor-A opened this issue 7 years ago • 1 comments

Hi, I've looked through the given example code for react native, and I can't find a way to put a Matter.js Body objects inside its own component and render multiple of them in a single World. Here's the code I have so far. The MoveThing component renders inside the world, but doesn't have physics applied to it. Any help would be appreciated. thanks.

import React, { Component } from 'react'
import { Image, Dimensions, PanResponder, View } from 'react-native'
import {
  Body,
  Loop,
  Stage,
  World,
} from 'react-game-kit/native'
import Text from '../basics/text'
import Matter from 'matter-js'

export default class Game extends Component {

  physicsInit = (engine) => {

    const dimensions = Dimensions.get('window')

    const ground = Matter.Bodies.rectangle(
      dimensions.width / 2, dimensions.height,
      dimensions.width, 50,
      {
        isStatic: true,
      },
    )

    const ceiling = Matter.Bodies.rectangle(
      dimensions.width / 2, 0,
      dimensions.width, 50,
      {
        isStatic: true,
      },
    )

    const leftWall = Matter.Bodies.rectangle(
      0, dimensions.height / 2,
      50, dimensions.height,
      {
        isStatic: true,
      },
    )

    const rightWall = Matter.Bodies.rectangle(
      dimensions.width, dimensions.height / 2,
      50, dimensions.height,
      {
        isStatic: true,
      },
    )

    Matter.World.add(engine.world, [ground, leftWall, rightWall, ceiling])
  }

  constructor (props) {
    super(props)

    this.state = {
      gravity: 1,
    }
  }

  render () {
    const dimensions = Dimensions.get('window')
    return (
      <Loop>
        <Stage
          width={dimensions.width}
          height={dimensions.height}
          style={{ backgroundColor: '#fff' }}
        >
          <World
            onInit={this.physicsInit}
            gravity={{ x: 0, y: this.state.gravity, scale: 0.00 }}
          >
            {Array.apply(null, Array(5)).map((_, i) => i)
              .map(item => <MoveThing/>)
            }
          </World>
        </Stage>
      </Loop>
    )
  }
}
class MoveThing extends Component {
  constructor (props) {
    super(props)
    this.state = {
      ballPosition: {
        x: 0,
        y: 0,
      },
      ballAngle: 0,
    }
  }

  componentWillMount () {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderGrant: (evt, gestureState) => {
        this.setState({
          gravity: 0,
        })

        Matter.Body.setAngularVelocity(this.body.body, 0)
        Matter.Body.setVelocity(this.body.body, { x: 0, y: 0 })

        this.startPosition = {
          x: this.body.body.position.x,
          y: this.body.body.position.y,
        }
      },
      onPanResponderMove: (evt, gestureState) => {
        Matter.Body.setPosition(this.body.body, {
          x: this.startPosition.x + gestureState.dx,
          y: this.startPosition.y + gestureState.dy,
        })
      },
      onPanResponderRelease: (evt, gestureState) => {
        this.setState({
          gravity: 1,
        })

        Matter.Body.applyForce(this.body.body, {
          x: this.body.body.position.x,
          y: this.body.body.position.y,
        }, {
          x: gestureState.vx,
          y: gestureState.vy,
        })
      },
    })
  }

  getBallStyles () {
    return {
      backgroundColor: '#444',
      alignItems: 'center',
      justifyContent: 'center',
      borderRadius: 75 / 2,
      height: 75,
      width: 75,
      position: 'absolute',
      transform: [
        { translateX: this.state.ballPosition.x },
        { translateY: this.state.ballPosition.y },
        { rotate: (this.state.ballAngle * (180 / Math.PI)) + 'deg' }
      ],
    }
  }

  render () {
    const dimensions = Dimensions.get('window')

    return (
      <Body
        shape="circle"
        args={[0, dimensions.height - 75, 75]}
        density={1}
        friction={1}
        frictionStatic={0}
        restitution={0}
        ref={(b) => { this.body = b }}
      >
      <View
        style={this.getBallStyles()} {...this._panResponder.panHandlers}
      >
        <Text light size={24}>!!!</Text>
      </View>
      </Body>
    )
  }

}

Talor-A avatar Jun 09 '17 23:06 Talor-A

A bit late to the party, but I think this tutorial and this tutorial will give you all the answers you need. (Had a similar question and found them so thought they might help someone)

waelmas avatar Sep 15 '20 14:09 waelmas