memoized some components, added orb

This commit is contained in:
ad044 2020-09-03 23:02:44 +04:00
parent 19560f439e
commit ba98824ad8
12 changed files with 139 additions and 64 deletions

View file

@ -41,5 +41,6 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
} },
"homepage": "."
} }

View file

@ -1,5 +1,4 @@
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
//import Orb from "./Orb";
import { OrbitControls } from "drei"; import { OrbitControls } from "drei";
import React, { Suspense, useCallback, useEffect, useState } from "react"; import React, { Suspense, useCallback, useEffect, useState } from "react";
import { Canvas } from "react-three-fiber"; import { Canvas } from "react-three-fiber";
@ -46,6 +45,7 @@ const Game = () => {
const [currentSpriteHUD, setCurrentSpriteHUD] = useState<SpriteHuds>( const [currentSpriteHUD, setCurrentSpriteHUD] = useState<SpriteHuds>(
(level_sprite_huds as SpriteHuds)[currentSprite.substr(2)] (level_sprite_huds as SpriteHuds)[currentSprite.substr(2)]
); );
const [spriteUpdateCooldown, setSpriteUpdateCooldown] = useState(false);
const [HUDActive, setHUDActive] = useState(1); const [HUDActive, setHUDActive] = useState(1);
@ -218,10 +218,12 @@ const Game = () => {
// therefore lain should first do a move (up/down/left/right) and then that sprite // therefore lain should first do a move (up/down/left/right) and then that sprite
// will be chosen. // will be chosen.
case "+": case "+":
if (!spriteUpdateCooldown) {
// hide the hud // hide the hud
updateHUD(); updateHUD();
// disable glow on current sprite // disable glow on current sprite
setCurrentSprite(""); setCurrentSprite("");
setSpriteUpdateCooldown(true);
setAnimationState(key); setAnimationState(key);
setTimeout(() => { setTimeout(() => {
setOrthoCameraPosY(1.88); setOrthoCameraPosY(1.88);
@ -231,10 +233,16 @@ const Game = () => {
(level_sprite_huds as SpriteHuds)[move.substr(3)] (level_sprite_huds as SpriteHuds)[move.substr(3)]
); );
}, (lain_animations as LainAnimations)[key]["duration"] + 200); }, (lain_animations as LainAnimations)[key]["duration"] + 200);
setTimeout(() => {
setSpriteUpdateCooldown(false);
}, 1000);
break; break;
}
// only change sprite focus // only change sprite focus
default: default:
if (!spriteUpdateCooldown) {
setCurrentSprite(move); setCurrentSprite(move);
setSpriteUpdateCooldown(true);
// toggle hud to go back in // toggle hud to go back in
updateHUD(); updateHUD();
setTimeout(() => { setTimeout(() => {
@ -245,9 +253,13 @@ const Game = () => {
// toggle it again to be shown in the new position // toggle it again to be shown in the new position
updateHUD(); updateHUD();
}, 500); }, 500);
setTimeout(() => {
setSpriteUpdateCooldown(false);
}, 1000);
}
} }
}, },
[setAnimationState, updateHUD] [setAnimationState, updateHUD, spriteUpdateCooldown]
); );
const handleKeyPress = useCallback( const handleKeyPress = useCallback(
@ -320,7 +332,7 @@ const Game = () => {
id={currentSpriteHUD!["id"]} id={currentSpriteHUD!["id"]}
/> />
<OrbitControls /> <OrbitControls />
<Starfield /> <Starfield starfieldPosY={camPosY} />
<Lights /> <Lights />
</Suspense> </Suspense>
</a.perspectiveCamera> </a.perspectiveCamera>

View file

@ -1,5 +1,5 @@
import { draco } from "drei"; import { draco } from "drei";
import React from "react"; import React, { memo } from "react";
import { useLoader } from "react-three-fiber"; import { useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
@ -15,7 +15,7 @@ type GLTFResult = GLTF & {
materials: {}; materials: {};
}; };
const GrayRing = (props: GrayRingProps) => { const GrayRing = memo((props: GrayRingProps) => {
const { nodes } = useLoader<GLTFResult>( const { nodes } = useLoader<GLTFResult>(
GLTFLoader, GLTFLoader,
"/models/ring0.glb", "/models/ring0.glb",
@ -38,6 +38,6 @@ const GrayRing = (props: GrayRingProps) => {
</mesh> </mesh>
</group> </group>
); );
}; });
export default GrayRing; export default GrayRing;

View file

@ -1,4 +1,4 @@
import React from "react"; import React, { memo } from "react";
import { useLoader } from "react-three-fiber"; import { useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import bigHud from "../static/sprites/big_hud.png"; import bigHud from "../static/sprites/big_hud.png";
@ -30,7 +30,7 @@ export type HUDElementProps = {
bigHUDScale: PositionAndScaleProps; 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 // 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 // you name it. this function allows me to specify whether i want a normal texture
// for the sprite or the mirrored/rotated one. // for the sprite or the mirrored/rotated one.
@ -113,6 +113,6 @@ const HUDElement = (props: HUDElementProps) => {
</a.sprite> </a.sprite>
</> </>
); );
}; });
export default HUDElement; export default HUDElement;

View file

@ -1,4 +1,4 @@
import React, { Suspense } from "react"; import React, { Suspense, memo} from "react";
import GrayRing from "./GrayRing"; import GrayRing from "./GrayRing";
import PurpleRing from "./PurpleRing"; import PurpleRing from "./PurpleRing";
import LevelSprite from "./LevelSprite"; import LevelSprite from "./LevelSprite";
@ -24,7 +24,7 @@ const Hub = (props: any) => {
rotation={sprite.rotation as RotationProps} rotation={sprite.rotation as RotationProps}
sprite={sprite.sprite} sprite={sprite.sprite}
key={sprite.id} key={sprite.id}
active={sprite.id === props.currentSprite ? true : false} active={sprite.id === props.currentSprite}
/> />
); );
})} })}

View file

@ -24,12 +24,12 @@ type LainConstructorProps = {
const LainConstructor = (props: LainConstructorProps) => { const LainConstructor = (props: LainConstructorProps) => {
// any here temporarily // any here temporarily
const spriteTexture: any = useLoader(THREE.TextureLoader, props.sprite); const lainSpriteTexture: any = useLoader(THREE.TextureLoader, props.sprite);
const [animator] = useState( const [animator] = useState(
() => () =>
new PlainSingularAnimator( new PlainSingularAnimator(
spriteTexture, lainSpriteTexture,
props.framesHorizontal, props.framesHorizontal,
props.framesVertical, props.framesVertical,
props.frameCount, props.frameCount,
@ -41,7 +41,7 @@ const LainConstructor = (props: LainConstructorProps) => {
animator.animate(); animator.animate();
}); });
return <spriteMaterial attach="material" map={spriteTexture} />; return <spriteMaterial attach="material" map={lainSpriteTexture} />;
}; };
export const LainIntro = () => { export const LainIntro = () => {

View file

@ -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 { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import Cou from "../static/sprites/Cou.png"; import Cou from "../static/sprites/Cou.png";
@ -22,7 +22,7 @@ type SpriteToPath = {
[key: string]: [string, string]; [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 // the game only has a couple of sprites that it displays in the hub
// dynamically importnig them would be worse for performance, // dynamically importnig them would be worse for performance,
// so we import all of them here and then use this function to // so we import all of them here and then use this function to
@ -114,6 +114,6 @@ const LevelSprite = (props: LevelSpriteConstructorProps) => {
)} )}
</mesh> </mesh>
); );
}; });
export default LevelSprite; export default LevelSprite;

View file

@ -1,6 +1,6 @@
import React from "react"; import React, { memo } from "react";
const Lights = () => { const Lights = memo(() => {
return ( return (
<> <>
<ambientLight color={0x808080} /> <ambientLight color={0x808080} />
@ -9,6 +9,6 @@ const Lights = () => {
<pointLight color={0xffffff} position={[0, 0, 0]} intensity={0.1} /> <pointLight color={0xffffff} position={[0, 0, 0]} intensity={0.1} />
</> </>
); );
}; });
export default Lights; export default Lights;

55
src/components/Orb.tsx Normal file
View file

@ -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 (
<group position={[0, -0.1, -9]}>
<sprite scale={[0.3, 0.3, 0.3]} ref={orbRef}>
<spriteMaterial attach="material" map={orbSpriteTexture} />
</sprite>
{/* <line>
<bufferGeometry attach="geometry" ref={ref} />
<lineBasicMaterial
attach="material"
color="blue"
linewidth={7}
transparent={false}
/>
</line> */}
</group>
);
});
export default Orb;

View file

@ -1,9 +1,8 @@
//import Orb from "./Orb";
import { OrthographicCamera } from "drei";
import React, { useMemo, useRef } from "react"; import React, { useMemo, useRef } from "react";
import { useFrame, useThree } from "react-three-fiber"; import { useFrame, useThree } from "react-three-fiber";
import { Scene } from "three"; import { Scene } from "three";
import HUDElement, { HUDElementProps } from "./HUDElement"; import HUDElement, { HUDElementProps } from "./HUDElement";
import Orb from "./Orb";
interface OrthoCameraProps extends HUDElementProps { interface OrthoCameraProps extends HUDElementProps {
id: string; id: string;
@ -44,6 +43,7 @@ const OrthoCamera = (props: OrthoCameraProps) => {
bigHUDScale={props.bigHUDScale} bigHUDScale={props.bigHUDScale}
key={props.id} key={props.id}
/> />
<Orb />
</orthographicCamera> </orthographicCamera>
); );
}; };

View file

@ -1,6 +1,6 @@
import { a, useSpring } from "@react-spring/three"; import { a, useSpring } from "@react-spring/three";
import { draco } from "drei"; import { draco } from "drei";
import React from "react"; import React, { memo } from "react";
import { useFrame, useLoader } from "react-three-fiber"; import { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
@ -16,7 +16,7 @@ type GLTFResult = GLTF & {
materials: {}; materials: {};
}; };
const PurpleRing = (props: PurpleRingProps) => { const PurpleRing = memo((props: PurpleRingProps) => {
const [{ purpleRingRotationY }, setPurpleRingRotationY] = useSpring( const [{ purpleRingRotationY }, setPurpleRingRotationY] = useSpring(
() => ({ () => ({
purpleRingRotationY: 0, purpleRingRotationY: 0,
@ -54,6 +54,6 @@ const PurpleRing = (props: PurpleRingProps) => {
</mesh> </mesh>
</a.group> </a.group>
); );
}; });
export default PurpleRing; export default PurpleRing;

View file

@ -1,9 +1,13 @@
import React, { useMemo, useReducer, useRef, createRef } from "react"; import { a, Interpolation } from "@react-spring/three";
import * as THREE from "three"; import React, { createRef, memo, useMemo, useRef } from "react";
import { a, useSpring } from "@react-spring/three";
import { useFrame } from "react-three-fiber"; import { useFrame } from "react-three-fiber";
import * as THREE from "three";
const Starfield = () => { type StarfieldProps = {
starfieldPosY: Interpolation<number, number>;
}
const Starfield = memo((props: StarfieldProps) => {
const blueUniforms = useMemo( const blueUniforms = useMemo(
() => ({ () => ({
color1: { color1: {
@ -105,7 +109,7 @@ const Starfield = () => {
const whiteFromLeftRef = useRef(posesWhiteFromleft.map(() => createRef())); const whiteFromLeftRef = useRef(posesWhiteFromleft.map(() => createRef()));
useFrame(() => { useFrame(() => {
blueFromRightRef.current.map((ref) => { blueFromRightRef.current.forEach((ref) => {
if ((ref.current as any).position.x < -1) { if ((ref.current as any).position.x < -1) {
(ref.current as any).position.x += 7.3; (ref.current as any).position.x += 7.3;
(ref.current as any).position.z -= 7.3; (ref.current as any).position.z -= 7.3;
@ -114,16 +118,16 @@ const Starfield = () => {
(ref.current as any).position.z += 0.03; (ref.current as any).position.z += 0.03;
} }
}); });
blueFromLeftRef.current.map((ref) => { blueFromLeftRef.current.forEach((ref) => {
if ((ref.current as any).position.x > 3) { if ((ref.current as any).position.x > 3) {
(ref.current as any).position.x -= 3.3; (ref.current as any).position.x -= 8.3;
(ref.current as any).position.z -= 3.3; (ref.current as any).position.z -= 8.3;
} else { } else {
(ref.current as any).position.x += 0.03; (ref.current as any).position.x += 0.03;
(ref.current as any).position.z += 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) { if ((ref.current as any).position.x < -1) {
(ref.current as any).position.x += 4.3; (ref.current as any).position.x += 4.3;
(ref.current as any).position.z -= 4.3; (ref.current as any).position.z -= 4.3;
@ -132,7 +136,7 @@ const Starfield = () => {
(ref.current as any).position.z += 0.03; (ref.current as any).position.z += 0.03;
} }
}); });
cyanFromLeftRef.current.map((ref) => { cyanFromLeftRef.current.forEach((ref) => {
if ((ref.current as any).position.x > 3) { if ((ref.current as any).position.x > 3) {
(ref.current as any).position.x -= 3.3; (ref.current as any).position.x -= 3.3;
(ref.current as any).position.z -= 3.3; (ref.current as any).position.z -= 3.3;
@ -141,7 +145,7 @@ const Starfield = () => {
(ref.current as any).position.z += 0.03; (ref.current as any).position.z += 0.03;
} }
}); });
whiteFromLeftRef.current.map((ref) => { whiteFromLeftRef.current.forEach((ref) => {
if ((ref.current as any).position.x > 3) { if ((ref.current as any).position.x > 3) {
(ref.current as any).position.x -= 3.3; (ref.current as any).position.x -= 3.3;
(ref.current as any).position.z -= 3.3; (ref.current as any).position.z -= 3.3;
@ -153,7 +157,7 @@ const Starfield = () => {
}); });
return ( return (
<group position={[-0.7, -1.5, -4]}> <a.group position={[-0.7, -1.5, -4]} >
{posesBlueFromRight.map((pos: any, idx: number) => { {posesBlueFromRight.map((pos: any, idx: number) => {
return ( return (
<mesh <mesh
@ -161,7 +165,7 @@ const Starfield = () => {
scale={[0.01, 2, 1]} scale={[0.01, 2, 1]}
rotation={[1.7, 0, 0.9]} rotation={[1.7, 0, 0.9]}
position={[pos[0], pos[1], pos[2]]} position={[pos[0], pos[1], pos[2]]}
key={idx} key={pos[0]}
renderOrder={-1} renderOrder={-1}
> >
<planeGeometry attach="geometry" /> <planeGeometry attach="geometry" />
@ -208,6 +212,7 @@ const Starfield = () => {
position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]}
rotation={[1.7, 0, 0.9]} rotation={[1.7, 0, 0.9]}
renderOrder={-1} renderOrder={-1}
key={pos[0]}
> >
<planeGeometry attach="geometry" /> <planeGeometry attach="geometry" />
<shaderMaterial <shaderMaterial
@ -230,6 +235,7 @@ const Starfield = () => {
position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]}
rotation={[1.7, 0, -0.9]} rotation={[1.7, 0, -0.9]}
renderOrder={-1} renderOrder={-1}
key={pos[0]}
> >
<planeGeometry attach="geometry" /> <planeGeometry attach="geometry" />
<shaderMaterial <shaderMaterial
@ -252,6 +258,7 @@ const Starfield = () => {
position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]} position={[pos[0] - 1.3, pos[1], pos[2] + 1.5]}
rotation={[1.7, 0, -0.9]} rotation={[1.7, 0, -0.9]}
renderOrder={-1} renderOrder={-1}
key={pos[0]}
> >
<planeGeometry attach="geometry" /> <planeGeometry attach="geometry" />
<shaderMaterial <shaderMaterial
@ -266,8 +273,8 @@ const Starfield = () => {
</mesh> </mesh>
); );
})} })}
</group> </a.group>
); );
}; });
export default Starfield; export default Starfield;