Closed tomekzaw closed 1 year ago
Hey @tomekzaw cool that someone else is also making use of that code 😄 I don't really have time right now to test the changes, but they look good, so I'll just merge it for now 😊 May I ask what you are using the code for? Just curios (I tried to build a react native game engine)
Hey @hannojg, thanks for this lib! I'm using it for Reanimated 3 examples, will post it on Twitter soon 😄 I'll submit two or three more PRs, just wanted to keep things organized 😄
This PR exposes
b2CircleShape
andSetRadius
method.Example:
SpawnCirclesScreen.tsx
```tsx import * as React from 'react'; import { StyleSheet, Dimensions, StatusBar, Platform } from 'react-native'; import { b2World, Box2d } from 'react-native-box2d'; import { Skia, Canvas, Group, Rect, useClockValue, useValue, useComputedValue, useTouchHandler, Circle, } from '@shopify/react-native-skia'; import StaticSafeAreaInsets from 'react-native-static-safe-area-insets'; const { width: screenWidth, height: _screenHeight } = Dimensions.get('window'); // TODO: probably better to do that with onLayout const screenHeight = Platform.select({ ios: _screenHeight, android: // note: my hack of getting the correct screen height on android Dimensions.get('screen').height - StaticSafeAreaInsets.safeAreaInsetsBottom - // only needed bc status bar not translucent! (StatusBar.currentHeight ?? 0), }) ?? 0; const widthInMm = 8; const mmToPxFactor = screenWidth / widthInMm; const pxToMmFactor = widthInMm / screenWidth; const heightInMm = screenHeight * pxToMmFactor; const boxSizeMm = 1; const boxSizePx = Math.ceil(boxSizeMm * mmToPxFactor); const degreeToRadFactor = Math.PI / 180; // random int inclusive const randomInt = (min: number, max: number) => Math.random() * (max - min + 1) + min; const Box = ({ world, registerStepListener, }: { world: b2World; registerStepListener: (listener: () => unknown) => () => void; }) => { const boxWorldPos = useValue({ y: 4, x: randomInt(boxSizeMm, widthInMm - boxSizeMm), angle: randomInt(0, 180) * degreeToRadFactor, }); const boxMatrix = useComputedValue(() => { const matrix = Skia.Matrix(); // important, translate first matrix.translate( boxWorldPos.current.x * mmToPxFactor, boxWorldPos.current.y * mmToPxFactor ); return matrix; }, [boxWorldPos]); React.useEffect(() => { // create a dynamic body const bodyDef = Box2d.b2BodyDef(); bodyDef.type = 2; // b2_dynamicBody bodyDef.position = Box2d.b2Vec2( boxWorldPos.current.x, boxWorldPos.current.y ); bodyDef.angle = boxWorldPos.current.angle; const body = world.CreateBody(bodyDef); // attach const dynamicCircle = Box2d.b2CircleShape(); dynamicCircle.SetRadius(boxSizeMm / 2); // fixture const fixtureDef = Box2d.b2FixtureDef(); fixtureDef.shape = dynamicCircle; fixtureDef.density = 1; fixtureDef.friction = 0.3; body.CreateFixture(fixtureDef); return registerStepListener(() => { // update the binding const pos = body.GetPosition(); boxWorldPos.current = { x: pos.x, y: pos.y, angle: body.GetAngle(), }; // console.log( // `x: ${boxWorldPos.current.x.toFixed( // 2 // )}, y: ${boxWorldPos.current.y.toFixed( // 2 // )}, rotation: ${boxWorldPos.current.angle.toFixed(2)}` // ); }); }, [boxWorldPos, registerStepListener, world]); return (Video recording:
https://user-images.githubusercontent.com/20516055/223060740-bd74c120-9a80-4fb6-a043-7159ef460bd6.mp4