Updated to Expo 49 and updated other packes as well. Added eslint, still need to clean up linting errors. Fix bugs in the game; uses safe area, floor is now visible, score is now visible. Typed out globals. Added eas.json and updated build scripts.
This commit is contained in:
parent
de0f8a6311
commit
1ca88b176c
|
@ -0,0 +1,30 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
files: [".eslintrc.{js,cjs}"],
|
||||
parserOptions: {
|
||||
sourceType: "script",
|
||||
},
|
||||
},
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["@typescript-eslint", "react"],
|
||||
rules: {},
|
||||
ignorePatterns: ["*.d.ts"],
|
||||
};
|
|
@ -9,6 +9,12 @@ npm-debug.*
|
|||
*.mobileprovision
|
||||
*.orig.*
|
||||
web-build/
|
||||
*.log
|
||||
*.app
|
||||
*.tar.gz
|
||||
*.ipa
|
||||
*.apk
|
||||
*.aab
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
|
25
App.tsx
25
App.tsx
|
@ -1,15 +1,36 @@
|
|||
import React from "react";
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||
import { Logs } from 'expo'
|
||||
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
import AppView from "./AppView";
|
||||
import GameEngine from "./game/systems/GameEngine";
|
||||
|
||||
export default function App() {
|
||||
Logs.enableExpoCliLogging()
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBar backgroundColor="orange" hidden={true} />
|
||||
<SafeAreaProvider>
|
||||
<AppView />
|
||||
<SafeView />
|
||||
</SafeAreaProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SafeView() {
|
||||
const { top, bottom, left, right } = useSafeAreaInsets();
|
||||
const topInset = top.valueOf();
|
||||
global.topInset = topInset;
|
||||
global.bottomInset = bottom;
|
||||
global.leftInset = left;
|
||||
global.rightInset = right;
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<GameEngine />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
94
AppView.tsx
94
AppView.tsx
|
@ -1,94 +0,0 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
||||
import { GameEngine } from "react-native-game-engine";
|
||||
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
import { entities, useEntities } from "@entities";
|
||||
import { GameLoop } from "@systems";
|
||||
import { IGameEngine } from "@types";
|
||||
|
||||
export default function AppView() {
|
||||
const [isRunning, setIsRunning] = React.useState(true);
|
||||
const [score, setScore] = useState(0);
|
||||
const [gameEngine, setGameEngine] = useState<IGameEngine | null>(null);
|
||||
const { entities } = useEntities();
|
||||
const { top } = useSafeAreaInsets();
|
||||
const topInset = top.valueOf();
|
||||
(global as any).topInset = topInset;
|
||||
|
||||
const gameEntities = entities();
|
||||
const { engine, world } = gameEntities.physics;
|
||||
|
||||
// console.log(topInset)
|
||||
|
||||
// const gameEntities = entities();
|
||||
useEffect(() => {
|
||||
(global as any).gameEngine = gameEngine;
|
||||
}, [gameEngine]);
|
||||
|
||||
return (
|
||||
<SafeAreaView edges={['top']} style={[styles.container, {
|
||||
|
||||
}]}>
|
||||
{/* @ts-ignore */}
|
||||
<GameEngine
|
||||
ref={(ref) => setGameEngine(ref as IGameEngine)}
|
||||
systems={[GameLoop]}
|
||||
entities={gameEntities}
|
||||
running={isRunning}
|
||||
onEvent={({ type, ...rest }: any) => {
|
||||
switch (type) {
|
||||
case "addToScore": {
|
||||
setScore(score => score + 1);
|
||||
break;
|
||||
}
|
||||
case "subtractFromScore": {
|
||||
setScore(score => score - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}}
|
||||
style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
// gameEngine?.swap(entities());
|
||||
if (isRunning) {
|
||||
gameEngine?.stop();
|
||||
setIsRunning(false);
|
||||
} else {
|
||||
gameEngine?.start();
|
||||
setIsRunning(true);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: 55,
|
||||
width: "100%",
|
||||
// borderColor: "red",
|
||||
// borderWidth: 1,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
fontSize: 40,
|
||||
fontWeight: "bold",
|
||||
marginTop: topInset / 2,
|
||||
}}
|
||||
>
|
||||
{isRunning ? score : "Press to Resume"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</GameEngine>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
9
app.json
9
app.json
|
@ -18,7 +18,8 @@
|
|||
"**/*"
|
||||
],
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.nightness.reactnativegameengineexpotypescripttemplate"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
|
@ -28,6 +29,12 @@
|
|||
},
|
||||
"web": {
|
||||
"favicon": "./assets/favicon.png"
|
||||
},
|
||||
"jsEngine": "jsc",
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "bb283987-7da9-4a8e-b730-4aebcd816864"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,5 @@ export const BalloonSVG = (props) => {
|
|||
<Path d="M4430 12789 c-921 -59 -1769 -370 -2480 -908 -1067 -807 -1758 -2084 -1914 -3536 -69 -641 -34 -1378 100 -2105 192 -1039 624 -2084 1222 -2955 536 -781 1225 -1439 1919 -1834 140 -79 424 -214 558 -264 215 -80 439 -136 648 -162 60 -7 111 -16 115 -19 8 -9 -15 -237 -34 -326 -35 -167 -134 -411 -198 -487 -33 -40 -33 -73 2 -105 59 -57 173 -82 372 -83 213 0 331 25 393 83 36 34 34 62 -7 116 -114 150 -225 522 -226 758 0 54 -15 47 150 68 889 116 1919 814 2751 1865 480 607 892 1332 1182 2085 466 1210 624 2521 441 3659 -214 1337 -881 2491 -1874 3242 -876 663 -1971 982 -3120 908z" />
|
||||
</G>
|
||||
</Svg>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"cli": {
|
||||
"version": ">= 2.7.1"
|
||||
},
|
||||
"build": {
|
||||
"local": {
|
||||
"distribution": "internal",
|
||||
"android": {
|
||||
"buildType": "apk",
|
||||
"image": "latest"
|
||||
},
|
||||
"ios": {
|
||||
"simulator": true
|
||||
}
|
||||
},
|
||||
"development": {
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"android": {
|
||||
"buildType": "apk",
|
||||
"image": "latest"
|
||||
},
|
||||
"ios": {
|
||||
"simulator": true,
|
||||
"resourceClass": "m-medium"
|
||||
}
|
||||
},
|
||||
"preview": {
|
||||
"channel": "preview",
|
||||
"android": {
|
||||
"buildType": "app-bundle",
|
||||
"image": "latest"
|
||||
},
|
||||
"ios": {
|
||||
"resourceClass": "m-medium"
|
||||
}
|
||||
},
|
||||
"production": {
|
||||
"channel": "production",
|
||||
"android": {
|
||||
"buildType": "app-bundle",
|
||||
"image": "latest"
|
||||
},
|
||||
"ios": {
|
||||
"resourceClass": "m-medium"
|
||||
}
|
||||
}
|
||||
},
|
||||
"submit": {
|
||||
"preview": {
|
||||
"android": {
|
||||
"releaseStatus": "draft"
|
||||
}
|
||||
},
|
||||
"production": {
|
||||
"android": {
|
||||
"track": "production",
|
||||
"releaseStatus": "completed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,61 +1,53 @@
|
|||
import React from 'react'
|
||||
import Matter from 'matter-js'
|
||||
import { ColorValue, View } from 'react-native'
|
||||
|
||||
import { BalloonSVG } from '@svg'
|
||||
import { Position2D, Size2D } from '@types'
|
||||
import { GameEntity, Position2D, Size2D } from '@types'
|
||||
|
||||
const Balloon = ({ body, color }: any) => {
|
||||
const widthBody = body.bounds.max.x - body.bounds.min.x;
|
||||
const heightBody = body.bounds.max.y - body.bounds.min.y;
|
||||
|
||||
const xBody = body.position.x - widthBody / 2;
|
||||
const yBody = body.position.y - heightBody / 2;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: xBody,
|
||||
top: yBody,
|
||||
width: widthBody,
|
||||
height: heightBody,
|
||||
}}
|
||||
>
|
||||
<BalloonSVG color={color} />
|
||||
</View>
|
||||
);
|
||||
const Balloon = ({ body, color }: GameEntity) => {
|
||||
const heightBody = body.bounds.max.y - body.bounds.min.y;
|
||||
const widthBody = body.bounds.max.x - body.bounds.min.x;
|
||||
|
||||
const xBody = body.position.x - widthBody / 2;
|
||||
const yBody = body.position.y - heightBody / 2;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: xBody,
|
||||
top: yBody,
|
||||
width: widthBody,
|
||||
height: heightBody,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<BalloonSVG color={color} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default (
|
||||
label: string,
|
||||
world: Matter.Composite,
|
||||
color: ColorValue,
|
||||
pos: Position2D,
|
||||
size: Size2D
|
||||
) => {
|
||||
const body = Matter.Bodies.rectangle(pos.x, pos.y, size.width, size.height, {
|
||||
label,
|
||||
isStatic: false,
|
||||
id: 5,
|
||||
frictionAir: 0.5,
|
||||
});
|
||||
Matter.Composite.add(world, body);
|
||||
|
||||
return {
|
||||
body,
|
||||
color,
|
||||
pos,
|
||||
renderer: Balloon,
|
||||
};
|
||||
|
||||
export default (
|
||||
label: string,
|
||||
world: Matter.Composite,
|
||||
color: ColorValue,
|
||||
pos: Position2D,
|
||||
size: Size2D
|
||||
) => {
|
||||
const body = Matter.Bodies.circle(pos.x, pos.y, 50, {
|
||||
label,
|
||||
isStatic: false,
|
||||
id: 5,
|
||||
// restitution: 0.4,
|
||||
// friction: 1,
|
||||
frictionAir: 0.5,
|
||||
// mass: 0.1,
|
||||
// inverseMass: 0.1,
|
||||
// bounds: {
|
||||
// min: { x: size.width, y: size.height },
|
||||
// max: { x: size.width, y: size.height },
|
||||
// },
|
||||
// inertia: Infinity,
|
||||
// inverseInertia: Infinity,
|
||||
} as Matter.IChamferableBodyDefinition);
|
||||
Matter.Composite.add(world, body);
|
||||
|
||||
return {
|
||||
body,
|
||||
color,
|
||||
pos,
|
||||
renderer: Balloon,
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -2,9 +2,9 @@ import Matter from 'matter-js'
|
|||
import React from 'react'
|
||||
import { ColorValue, View } from 'react-native'
|
||||
|
||||
import { Position2D, Size2D } from '@types'
|
||||
import { GameEntity, Position2D, Size2D } from '@types'
|
||||
|
||||
const Wall = ({ body, color }: any) => {
|
||||
const Wall = ({ body, color }: GameEntity) => {
|
||||
const widthBody = body.bounds.max.x - body.bounds.min.x
|
||||
const heightBody = body.bounds.max.y - body.bounds.min.y
|
||||
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
import { Dimensions } from "react-native";
|
||||
import Matter from "matter-js";
|
||||
|
||||
import { windowHeight, windowWidth } from "@game";
|
||||
import { Balloon, Wall } from ".";
|
||||
import { GameEngineEntities } from "@types";
|
||||
|
||||
export const entities = (restart: boolean = false) => {
|
||||
let engine = Matter.Engine.create(undefined, {
|
||||
export function entities(): GameEngineEntities {
|
||||
const engine = Matter.Engine.create({
|
||||
enableSleeping: false,
|
||||
gravity: { x: 0, y: 0.001 },
|
||||
gravity: { x: 0, y: 1.75 },
|
||||
} as Matter.IEngineDefinition);
|
||||
|
||||
let world = engine.world;
|
||||
const topInset = (global as any).topInset; // for notch handling
|
||||
const world = engine.world;
|
||||
const [top, bottom] = [
|
||||
global.topInset,
|
||||
global.bottomInset,
|
||||
global.leftInset,
|
||||
global.rightInset,
|
||||
];
|
||||
|
||||
const newBalloon = () =>
|
||||
Balloon(
|
||||
|
@ -20,41 +25,41 @@ export const entities = (restart: boolean = false) => {
|
|||
"red",
|
||||
{
|
||||
x: Math.random() * (windowWidth - 100) + 50,
|
||||
y: 150,
|
||||
y: 200,
|
||||
},
|
||||
{ width: 50, height: 50 }
|
||||
{ width: 40, height: 50 }
|
||||
);
|
||||
|
||||
let entities = {
|
||||
const entities = {
|
||||
physics: { engine, world },
|
||||
Balloon: newBalloon(),
|
||||
LeftWall: Wall(
|
||||
"LeftWall",
|
||||
world,
|
||||
"orange",
|
||||
{ x: 0 - 25, y: windowHeight / 2 },
|
||||
{ height: windowHeight, width: 50 }
|
||||
),
|
||||
RightWall: Wall(
|
||||
"RightWall",
|
||||
world,
|
||||
"orange",
|
||||
{ x: windowWidth + 25, y: windowHeight / 2 },
|
||||
{ height: windowHeight, width: 50 }
|
||||
),
|
||||
// LeftWall: Wall(
|
||||
// "LeftWall",
|
||||
// world,
|
||||
// "orange",
|
||||
// { x: 0 - 25, y: windowHeight / 2 },
|
||||
// { height: windowHeight - topInset - bottomInset + 560, width: 50 }
|
||||
// ),
|
||||
// RightWall: Wall(
|
||||
// "RightWall",
|
||||
// world,
|
||||
// "orange",
|
||||
// { x: windowWidth + 25, y: windowHeight / 2 },
|
||||
// { height: windowHeight - topInset - bottomInset + 560, width: 50 }
|
||||
// ),
|
||||
Ceiling: Wall(
|
||||
"Ceiling",
|
||||
world,
|
||||
"orange",
|
||||
{ x: 0, y: 0 },
|
||||
{ height: 110 + topInset, width: windowWidth * 2 }
|
||||
{ height: 110 + top, width: windowWidth * 2 }
|
||||
),
|
||||
Floor: Wall(
|
||||
"Floor",
|
||||
world,
|
||||
"orange",
|
||||
{ x: windowWidth / 2, y: windowHeight + 60 },
|
||||
{ height: 60, width: windowWidth }
|
||||
{ x: windowWidth / 2, y: windowHeight - top },
|
||||
{ height: 60 + bottom, width: windowWidth }
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -72,23 +77,25 @@ export const entities = (restart: boolean = false) => {
|
|||
Matter.Events.on(
|
||||
engine,
|
||||
"collisionStart",
|
||||
({ pairs, name, source, timestamp }: Matter.IEventCollision<any>) => {
|
||||
for (var i = 0, j = pairs.length; i != j; ++i) {
|
||||
({ pairs }: Matter.IEventCollision<object>) => {
|
||||
for (let i = 0, j = pairs.length; i != j; ++i) {
|
||||
const bodyA = pairs[i].bodyA;
|
||||
const bodyB = pairs[i].bodyB;
|
||||
|
||||
// We only want collisions between the balloon and the floor
|
||||
if ((bodyA.label !== "Balloon" && bodyB.label !== "Balloon") || (bodyA.label !== "Floor" && bodyB.label !== "Floor")) {
|
||||
if (
|
||||
(bodyA.label !== "Balloon" && bodyB.label !== "Balloon") ||
|
||||
(bodyA.label !== "Floor" && bodyB.label !== "Floor")
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const balloonBody = entities.Balloon.body;
|
||||
const floorBody = entities.Floor.body;
|
||||
|
||||
// Remove balloon if it hits the floor
|
||||
Matter.World.remove(world, balloonBody, true);
|
||||
|
||||
// Subtract a point from the score
|
||||
const gameEngine = (global as any).gameEngine;
|
||||
const gameEngine = global.gameEngine!;
|
||||
gameEngine.dispatch({
|
||||
type: "subtractFromScore",
|
||||
});
|
||||
|
@ -102,7 +109,7 @@ export const entities = (restart: boolean = false) => {
|
|||
);
|
||||
|
||||
return entities;
|
||||
};
|
||||
}
|
||||
|
||||
export const useEntities = () => {
|
||||
return {
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
import { Dimensions } from "react-native";
|
||||
|
||||
export { windowHeight, windowWidth } from "@game";
|
||||
|
||||
import Wall from "./Wall";
|
||||
import Balloon from './Balloon';
|
||||
import Balloon from "./Balloon";
|
||||
|
||||
export {
|
||||
Wall,
|
||||
Balloon
|
||||
};
|
||||
export { Wall, Balloon };
|
||||
|
||||
export * from './entities';
|
||||
export * from "./entities";
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { IGameEngine } from "@types";
|
||||
|
||||
declare global {
|
||||
var topInset: number;
|
||||
var bottomInset: number;
|
||||
var leftInset: number;
|
||||
var rightInset: number;
|
||||
var gameEngine: IGameEngine | null;
|
||||
}
|
||||
|
||||
export {};
|
|
@ -0,0 +1,78 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Text, TouchableOpacity } from "react-native";
|
||||
import { GameEngine as ReactGameEngine } from "react-native-game-engine";
|
||||
|
||||
import { entities } from "@entities";
|
||||
import { GameLoop } from "@systems";
|
||||
import { GameEngineEvent, IGameEngine } from "@types";
|
||||
|
||||
export default function GameEngine() {
|
||||
const [isRunning, setIsRunning] = React.useState(true);
|
||||
const [score, setScore] = useState(0);
|
||||
const [gameEngine, setGameEngine] = useState<IGameEngine | null>(null);
|
||||
const [top, bottom, left, right] = [global.topInset, global.bottomInset, global.leftInset, global.rightInset]
|
||||
|
||||
const gameEntities = entities();
|
||||
// const { engine, world } = gameEntities.physics;
|
||||
// const gameEntities = entities();
|
||||
|
||||
useEffect(() => {
|
||||
if (gameEngine) {
|
||||
gameEngine.swap(entities());
|
||||
}
|
||||
global.gameEngine = gameEngine;
|
||||
}, [gameEngine]);
|
||||
|
||||
return (
|
||||
<ReactGameEngine
|
||||
ref={(ref) => setGameEngine(ref as IGameEngine)}
|
||||
systems={[GameLoop]}
|
||||
entities={gameEntities}
|
||||
running={isRunning}
|
||||
onEvent={({ type }: GameEngineEvent) => {
|
||||
switch (type) {
|
||||
case "addToScore": {
|
||||
setScore(score => score + 1);
|
||||
break;
|
||||
}
|
||||
case "subtractFromScore": {
|
||||
setScore(score => score - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}}
|
||||
style={{ position: "absolute", top, left, right, bottom }}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
// gameEngine?.swap(entities());
|
||||
if (isRunning) {
|
||||
gameEngine?.stop();
|
||||
setIsRunning(false);
|
||||
} else {
|
||||
gameEngine?.start();
|
||||
setIsRunning(true);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: 55,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
fontSize: 40,
|
||||
fontWeight: "bold",
|
||||
marginTop: 10,
|
||||
}}
|
||||
>
|
||||
{isRunning ? score : "Press to Resume"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</ReactGameEngine>
|
||||
);
|
||||
}
|
|
@ -1,26 +1,27 @@
|
|||
import Matter, { Vector } from "matter-js";
|
||||
import { GameEngineEntities, GameEntity } from "@types";
|
||||
import Matter from "matter-js";
|
||||
import {
|
||||
GameEngineUpdateEventOptionType,
|
||||
TouchEvent,
|
||||
} from "react-native-game-engine";
|
||||
|
||||
import { windowHeight, windowWidth } from "@game";
|
||||
|
||||
export const GameLoop = (
|
||||
entities: any,
|
||||
entities: GameEngineEntities,
|
||||
{ touches, time, dispatch }: GameEngineUpdateEventOptionType
|
||||
) => {
|
||||
let engine = entities.physics.engine;
|
||||
let world = entities.physics.world;
|
||||
const engine = entities.physics.engine;
|
||||
|
||||
touches
|
||||
.filter((t: TouchEvent) => t.type === "press")
|
||||
.forEach((t: TouchEvent) => {
|
||||
const balloonBody = entities.Balloon.body as Matter.IBodyDefinition;
|
||||
const balloonBody = (entities.Balloon as GameEntity).body;
|
||||
const balloonPos = balloonBody.position as Matter.Vector;
|
||||
|
||||
const { pageX, pageY } = t.event;
|
||||
// if (locationX < 50 && locationY < 50) { // for some reason this works, but the line below is more readable.
|
||||
if (Math.abs(pageX - balloonPos.x) < 50 && Math.abs(pageY - balloonPos.y) < 50) {
|
||||
if (
|
||||
Math.abs(pageX - balloonPos.x) < 100 &&
|
||||
Math.abs(pageY - balloonPos.y) < 100
|
||||
) {
|
||||
dispatch({
|
||||
type: "addToScore",
|
||||
});
|
||||
|
|
|
@ -1,18 +1,39 @@
|
|||
import { ColorValue } from "react-native";
|
||||
import { GameEngine } from "react-native-game-engine";
|
||||
|
||||
export interface Position2D {
|
||||
x: number;
|
||||
y: number;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface Size2D {
|
||||
width: number;
|
||||
height: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface IGameEngine extends GameEngine {
|
||||
stop: () => void;
|
||||
start: () => void;
|
||||
swap: (newEntities: Promise<any> | any) => void;
|
||||
dispatch: (event: string) => void;
|
||||
}
|
||||
export interface IGameEngine<T = never> extends GameEngine {
|
||||
stop: () => void;
|
||||
start: () => void;
|
||||
swap: (newEntities: Promise<GameEngineEntities> | GameEngineEntities) => void;
|
||||
dispatch: (event: GameEngineEvent<T>) => void;
|
||||
}
|
||||
|
||||
export interface GameEngineEvent<T = never> {
|
||||
type: string;
|
||||
[key: string]: T | string;
|
||||
}
|
||||
|
||||
export interface GameEntity {
|
||||
body: Matter.Body;
|
||||
color: ColorValue;
|
||||
pos: Position2D;
|
||||
renderer: React.ComponentType<GameEntity>;
|
||||
}
|
||||
|
||||
export interface GameEngineEntities {
|
||||
physics: {
|
||||
engine: Matter.Engine;
|
||||
world: Matter.World;
|
||||
};
|
||||
[key: string]: GameEntity | { engine: Matter.Engine; world: Matter.World };
|
||||
}
|
||||
|
|
65
package.json
65
package.json
|
@ -3,34 +3,55 @@
|
|||
"version": "1.0.0",
|
||||
"main": "node_modules/expo/AppEntry.js",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "expo start --web",
|
||||
"eject": "expo eject"
|
||||
"start": "npx expo start --dev-client",
|
||||
"android": "npx expo start --android",
|
||||
"ios": "npx expo start --ios",
|
||||
"web": "npx expo start --web",
|
||||
"build:local": "eas build --profile local --local",
|
||||
"build:dev": "eas build --profile development --local",
|
||||
"build:preview": "node scripts/updateVersion.js && eas build --profile preview --local",
|
||||
"build:production": "node scripts/updateVersion.js && eas build --profile production --local",
|
||||
"eas:preview": "eas build --profile preview --auto-submit",
|
||||
"eas:production": "eas build --profile production --auto-submit",
|
||||
"submit:preview": "eas submit --profile preview",
|
||||
"submit:production": "eas submit --profile production",
|
||||
"update": "eas update --auto",
|
||||
"update:preview": "eas update --branch preview --message \"Updating Preview\"",
|
||||
"update:production": "eas update --branch production --message \"Updating Production\"",
|
||||
"pod:update": "pod repo update"
|
||||
},
|
||||
"dependencies": {
|
||||
"expo": "^47.0.0",
|
||||
"expo-status-bar": "~1.4.2",
|
||||
"expo": "^49.0.21",
|
||||
"expo-dev-client": "~2.4.12",
|
||||
"expo-status-bar": "~1.6.0",
|
||||
"matter-js": "^0.18.0",
|
||||
"react": "18.1.0",
|
||||
"react-dom": "18.1.0",
|
||||
"react-native": "0.70.5",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native": "0.72.6",
|
||||
"react-native-game-engine": "^1.2.0",
|
||||
"react-native-reanimated": "~2.12.0",
|
||||
"react-native-safe-area-context": "4.4.1",
|
||||
"react-native-svg": "13.4.0",
|
||||
"react-native-web": "~0.18.7"
|
||||
"react-native-reanimated": "~3.3.0",
|
||||
"react-native-safe-area-context": "4.6.3",
|
||||
"react-native-svg": "13.9.0",
|
||||
"react-native-web": "~0.19.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
||||
"@babel/preset-env": "^7.17.12",
|
||||
"@expo/webpack-config": "^0.17.2",
|
||||
"@types/matter-js": "^0.17.7",
|
||||
"@types/react": "~18.0.24",
|
||||
"@types/react-native": "~0.70.6",
|
||||
"typescript": "^4.6.3"
|
||||
"@babel/core": "^7.23.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.0.0-0",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.0.0-0",
|
||||
"@babel/plugin-transform-template-literals": "^7.0.0-0",
|
||||
"@babel/preset-env": "^7.23.7",
|
||||
"@expo/webpack-config": "^19.0.0",
|
||||
"@types/matter-js": "^0.19.5",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-native": "^0.73.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.0",
|
||||
"@typescript-eslint/parser": "^6.18.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
{
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"importHelpers": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"module": "esnext",
|
||||
"paths": {
|
||||
"@entities": ["game/entities/index.ts"],
|
||||
"@game": ["game/index.ts"],
|
||||
"@svg": ["assets/SVG/index.ts"],
|
||||
"@systems": ["game/systems/index.ts"],
|
||||
"@types": ["game/types.ts"],
|
||||
}
|
||||
}
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"importHelpers": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"module": "esnext",
|
||||
"paths": {
|
||||
"@entities": ["game/entities/index.ts"],
|
||||
"@game": ["game/index.ts"],
|
||||
"@svg": ["assets/SVG/index.ts"],
|
||||
"@systems": ["game/systems/index.ts"],
|
||||
"@types": ["game/types.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["**/*", "game/global.d.ts"],
|
||||
"exclude": ["node_modules", "**/*.spec.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue