From ba98824ad82195fad043b9fed0e52762dff197ac Mon Sep 17 00:00:00 2001 From: ad044 Date: Thu, 3 Sep 2020 23:02:44 +0400 Subject: [PATCH] memoized some components, added orb --- package.json | 3 +- src/components/Game.tsx | 64 ++++++++++++++++++++-------------- src/components/GrayRing.tsx | 6 ++-- src/components/HUDElement.tsx | 6 ++-- src/components/Hub.tsx | 4 +-- src/components/Lain.tsx | 6 ++-- src/components/LevelSprite.tsx | 6 ++-- src/components/Lights.tsx | 6 ++-- src/components/Orb.tsx | 55 +++++++++++++++++++++++++++++ src/components/OrthoCamera.tsx | 4 +-- src/components/PurpleRing.tsx | 6 ++-- src/components/Starfield.tsx | 37 ++++++++++++-------- 12 files changed, 139 insertions(+), 64 deletions(-) create mode 100644 src/components/Orb.tsx diff --git a/package.json b/package.json index 7c54ad2..e9cbec8 100644 --- a/package.json +++ b/package.json @@ -41,5 +41,6 @@ "last 1 firefox version", "last 1 safari version" ] - } + }, + "homepage": "." } diff --git a/src/components/Game.tsx b/src/components/Game.tsx index 47ba581..70816a6 100644 --- a/src/components/Game.tsx +++ b/src/components/Game.tsx @@ -1,5 +1,4 @@ import { a, useSpring } from "@react-spring/three"; -//import Orb from "./Orb"; import { OrbitControls } from "drei"; import React, { Suspense, useCallback, useEffect, useState } from "react"; import { Canvas } from "react-three-fiber"; @@ -46,6 +45,7 @@ const Game = () => { const [currentSpriteHUD, setCurrentSpriteHUD] = useState( (level_sprite_huds as SpriteHuds)[currentSprite.substr(2)] ); + const [spriteUpdateCooldown, setSpriteUpdateCooldown] = useState(false); const [HUDActive, setHUDActive] = useState(1); @@ -218,36 +218,48 @@ const Game = () => { // therefore lain should first do a move (up/down/left/right) and then that sprite // will be chosen. case "+": - // hide the hud - updateHUD(); - // disable glow on current sprite - setCurrentSprite(""); - setAnimationState(key); - setTimeout(() => { - setOrthoCameraPosY(1.88); + if (!spriteUpdateCooldown) { + // hide the hud updateHUD(); - setCurrentSprite(move.substr(1)); - setCurrentSpriteHUD( - (level_sprite_huds as SpriteHuds)[move.substr(3)] - ); - }, (lain_animations as LainAnimations)[key]["duration"] + 200); - break; + // disable glow on current sprite + setCurrentSprite(""); + setSpriteUpdateCooldown(true); + setAnimationState(key); + setTimeout(() => { + setOrthoCameraPosY(1.88); + updateHUD(); + setCurrentSprite(move.substr(1)); + setCurrentSpriteHUD( + (level_sprite_huds as SpriteHuds)[move.substr(3)] + ); + }, (lain_animations as LainAnimations)[key]["duration"] + 200); + setTimeout(() => { + setSpriteUpdateCooldown(false); + }, 1000); + break; + } // only change sprite focus default: - setCurrentSprite(move); - // toggle hud to go back in - updateHUD(); - setTimeout(() => { - // change hud while its hidden - setCurrentSpriteHUD( - (level_sprite_huds as SpriteHuds)[move.substr(2)] - ); - // toggle it again to be shown in the new position + if (!spriteUpdateCooldown) { + setCurrentSprite(move); + setSpriteUpdateCooldown(true); + // toggle hud to go back in updateHUD(); - }, 500); + setTimeout(() => { + // change hud while its hidden + setCurrentSpriteHUD( + (level_sprite_huds as SpriteHuds)[move.substr(2)] + ); + // toggle it again to be shown in the new position + updateHUD(); + }, 500); + setTimeout(() => { + setSpriteUpdateCooldown(false); + }, 1000); + } } }, - [setAnimationState, updateHUD] + [setAnimationState, updateHUD, spriteUpdateCooldown] ); const handleKeyPress = useCallback( @@ -320,7 +332,7 @@ const Game = () => { id={currentSpriteHUD!["id"]} /> - + diff --git a/src/components/GrayRing.tsx b/src/components/GrayRing.tsx index cdf6b6d..7f43bcd 100644 --- a/src/components/GrayRing.tsx +++ b/src/components/GrayRing.tsx @@ -1,5 +1,5 @@ import { draco } from "drei"; -import React from "react"; +import React, { memo } from "react"; import { useLoader } from "react-three-fiber"; import * as THREE from "three"; import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; @@ -15,7 +15,7 @@ type GLTFResult = GLTF & { materials: {}; }; -const GrayRing = (props: GrayRingProps) => { +const GrayRing = memo((props: GrayRingProps) => { const { nodes } = useLoader( GLTFLoader, "/models/ring0.glb", @@ -38,6 +38,6 @@ const GrayRing = (props: GrayRingProps) => { ); -}; +}); export default GrayRing; diff --git a/src/components/HUDElement.tsx b/src/components/HUDElement.tsx index 1e03c9e..e82725b 100644 --- a/src/components/HUDElement.tsx +++ b/src/components/HUDElement.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { memo } from "react"; import { useLoader } from "react-three-fiber"; import * as THREE from "three"; import bigHud from "../static/sprites/big_hud.png"; @@ -30,7 +30,7 @@ export type HUDElementProps = { bigHUDScale: PositionAndScaleProps; }; -const HUDElement = (props: HUDElementProps) => { +const HUDElement = memo((props: HUDElementProps) => { // these hud elements come in all shapes and forms, some of them are mirrored, rotated // you name it. this function allows me to specify whether i want a normal texture // for the sprite or the mirrored/rotated one. @@ -113,6 +113,6 @@ const HUDElement = (props: HUDElementProps) => { ); -}; +}); export default HUDElement; diff --git a/src/components/Hub.tsx b/src/components/Hub.tsx index c145841..5df8eca 100644 --- a/src/components/Hub.tsx +++ b/src/components/Hub.tsx @@ -1,4 +1,4 @@ -import React, { Suspense } from "react"; +import React, { Suspense, memo} from "react"; import GrayRing from "./GrayRing"; import PurpleRing from "./PurpleRing"; import LevelSprite from "./LevelSprite"; @@ -24,7 +24,7 @@ const Hub = (props: any) => { rotation={sprite.rotation as RotationProps} sprite={sprite.sprite} key={sprite.id} - active={sprite.id === props.currentSprite ? true : false} + active={sprite.id === props.currentSprite} /> ); })} diff --git a/src/components/Lain.tsx b/src/components/Lain.tsx index f96a8ee..12e81f1 100644 --- a/src/components/Lain.tsx +++ b/src/components/Lain.tsx @@ -24,12 +24,12 @@ type LainConstructorProps = { const LainConstructor = (props: LainConstructorProps) => { // any here temporarily - const spriteTexture: any = useLoader(THREE.TextureLoader, props.sprite); + const lainSpriteTexture: any = useLoader(THREE.TextureLoader, props.sprite); const [animator] = useState( () => new PlainSingularAnimator( - spriteTexture, + lainSpriteTexture, props.framesHorizontal, props.framesVertical, props.frameCount, @@ -41,7 +41,7 @@ const LainConstructor = (props: LainConstructorProps) => { animator.animate(); }); - return ; + return ; }; export const LainIntro = () => { diff --git a/src/components/LevelSprite.tsx b/src/components/LevelSprite.tsx index be645f8..2b59ea4 100644 --- a/src/components/LevelSprite.tsx +++ b/src/components/LevelSprite.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useMemo } from "react"; +import React, { useRef, useMemo, memo } from "react"; import { useFrame, useLoader } from "react-three-fiber"; import * as THREE from "three"; import Cou from "../static/sprites/Cou.png"; @@ -22,7 +22,7 @@ type SpriteToPath = { [key: string]: [string, string]; }; -const LevelSprite = (props: LevelSpriteConstructorProps) => { +const LevelSprite = memo((props: LevelSpriteConstructorProps) => { // the game only has a couple of sprites that it displays in the hub // dynamically importnig them would be worse for performance, // so we import all of them here and then use this function to @@ -114,6 +114,6 @@ const LevelSprite = (props: LevelSpriteConstructorProps) => { )} ); -}; +}); export default LevelSprite; diff --git a/src/components/Lights.tsx b/src/components/Lights.tsx index f6d296b..23d3f10 100644 --- a/src/components/Lights.tsx +++ b/src/components/Lights.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React, { memo } from "react"; -const Lights = () => { +const Lights = memo(() => { return ( <> @@ -9,6 +9,6 @@ const Lights = () => { ); -}; +}); export default Lights; diff --git a/src/components/Orb.tsx b/src/components/Orb.tsx new file mode 100644 index 0000000..fff2334 --- /dev/null +++ b/src/components/Orb.tsx @@ -0,0 +1,55 @@ +import React, { useRef, memo, useState } from "react"; +import * as THREE from "three"; +import { useUpdate, useThree, useFrame, useLoader } from "react-three-fiber"; +import orbSprite from "../static/sprites/orb.png"; + +const curve = new THREE.QuadraticBezierCurve3( + new THREE.Vector3(1.2, 0, 0), + new THREE.Vector3(0.5, -0.8, 0), + new THREE.Vector3(-1.2, 1, 0) +); + +const points = curve.getPoints(100); + +let orbIdx = 0; + +const Orb = memo(() => { + const orbRef = useRef(); + const [orbDirection, setOrbDirection] = useState("left"); + const ref = useUpdate((geometry: any) => { + geometry.setFromPoints(points); + }, []); + + const orbSpriteTexture: any = useLoader(THREE.TextureLoader, orbSprite); + + useFrame(() => { + var orbPos = curve.getPoint(orbIdx / 250); + if (orbPos.x < -1.4) setOrbDirection("right"); + if (orbPos.x > 1.4) setOrbDirection("left"); + if (orbDirection === "left") { + orbIdx++; + } else { + orbIdx--; + } + (orbRef.current as any).position.x = orbPos.x; + (orbRef.current as any).position.y = orbPos.y; + }); + return ( + + + + + {/* + + + */} + + ); +}); + +export default Orb; diff --git a/src/components/OrthoCamera.tsx b/src/components/OrthoCamera.tsx index 73a2249..0a11bad 100644 --- a/src/components/OrthoCamera.tsx +++ b/src/components/OrthoCamera.tsx @@ -1,9 +1,8 @@ -//import Orb from "./Orb"; -import { OrthographicCamera } from "drei"; import React, { useMemo, useRef } from "react"; import { useFrame, useThree } from "react-three-fiber"; import { Scene } from "three"; import HUDElement, { HUDElementProps } from "./HUDElement"; +import Orb from "./Orb"; interface OrthoCameraProps extends HUDElementProps { id: string; @@ -44,6 +43,7 @@ const OrthoCamera = (props: OrthoCameraProps) => { bigHUDScale={props.bigHUDScale} key={props.id} /> + ); }; diff --git a/src/components/PurpleRing.tsx b/src/components/PurpleRing.tsx index 378fd60..b18c9ad 100644 --- a/src/components/PurpleRing.tsx +++ b/src/components/PurpleRing.tsx @@ -1,6 +1,6 @@ import { a, useSpring } from "@react-spring/three"; import { draco } from "drei"; -import React from "react"; +import React, { memo } from "react"; import { useFrame, useLoader } from "react-three-fiber"; import * as THREE from "three"; import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; @@ -16,7 +16,7 @@ type GLTFResult = GLTF & { materials: {}; }; -const PurpleRing = (props: PurpleRingProps) => { +const PurpleRing = memo((props: PurpleRingProps) => { const [{ purpleRingRotationY }, setPurpleRingRotationY] = useSpring( () => ({ purpleRingRotationY: 0, @@ -54,6 +54,6 @@ const PurpleRing = (props: PurpleRingProps) => { ); -}; +}); export default PurpleRing; diff --git a/src/components/Starfield.tsx b/src/components/Starfield.tsx index 687df47..2bf2d7b 100644 --- a/src/components/Starfield.tsx +++ b/src/components/Starfield.tsx @@ -1,9 +1,13 @@ -import React, { useMemo, useReducer, useRef, createRef } from "react"; -import * as THREE from "three"; -import { a, useSpring } from "@react-spring/three"; +import { a, Interpolation } from "@react-spring/three"; +import React, { createRef, memo, useMemo, useRef } from "react"; import { useFrame } from "react-three-fiber"; +import * as THREE from "three"; -const Starfield = () => { +type StarfieldProps = { + starfieldPosY: Interpolation; +} + +const Starfield = memo((props: StarfieldProps) => { const blueUniforms = useMemo( () => ({ color1: { @@ -105,7 +109,7 @@ const Starfield = () => { const whiteFromLeftRef = useRef(posesWhiteFromleft.map(() => createRef())); useFrame(() => { - blueFromRightRef.current.map((ref) => { + blueFromRightRef.current.forEach((ref) => { if ((ref.current as any).position.x < -1) { (ref.current as any).position.x += 7.3; (ref.current as any).position.z -= 7.3; @@ -114,16 +118,16 @@ const Starfield = () => { (ref.current as any).position.z += 0.03; } }); - blueFromLeftRef.current.map((ref) => { + blueFromLeftRef.current.forEach((ref) => { if ((ref.current as any).position.x > 3) { - (ref.current as any).position.x -= 3.3; - (ref.current as any).position.z -= 3.3; + (ref.current as any).position.x -= 8.3; + (ref.current as any).position.z -= 8.3; } else { (ref.current as any).position.x += 0.03; (ref.current as any).position.z += 0.03; } }); - cyanFromRightRef.current.map((ref) => { + cyanFromRightRef.current.forEach((ref) => { if ((ref.current as any).position.x < -1) { (ref.current as any).position.x += 4.3; (ref.current as any).position.z -= 4.3; @@ -132,7 +136,7 @@ const Starfield = () => { (ref.current as any).position.z += 0.03; } }); - cyanFromLeftRef.current.map((ref) => { + cyanFromLeftRef.current.forEach((ref) => { if ((ref.current as any).position.x > 3) { (ref.current as any).position.x -= 3.3; (ref.current as any).position.z -= 3.3; @@ -141,7 +145,7 @@ const Starfield = () => { (ref.current as any).position.z += 0.03; } }); - whiteFromLeftRef.current.map((ref) => { + whiteFromLeftRef.current.forEach((ref) => { if ((ref.current as any).position.x > 3) { (ref.current as any).position.x -= 3.3; (ref.current as any).position.z -= 3.3; @@ -153,7 +157,7 @@ const Starfield = () => { }); return ( - + {posesBlueFromRight.map((pos: any, idx: number) => { return ( { scale={[0.01, 2, 1]} rotation={[1.7, 0, 0.9]} position={[pos[0], pos[1], pos[2]]} - key={idx} + key={pos[0]} renderOrder={-1} > @@ -208,6 +212,7 @@ const Starfield = () => { position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} rotation={[1.7, 0, 0.9]} renderOrder={-1} + key={pos[0]} > { position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} rotation={[1.7, 0, -0.9]} renderOrder={-1} + key={pos[0]} > { position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} rotation={[1.7, 0, -0.9]} renderOrder={-1} + key={pos[0]} > { ); })} - + ); -}; +}); export default Starfield;