started working on switching hud and general cursor movement

This commit is contained in:
ad044 2020-08-28 17:49:58 +04:00
parent 2d08a67ae6
commit f318cee7ed
12 changed files with 195 additions and 142 deletions

5
package-lock.json generated
View file

@ -1649,6 +1649,11 @@
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-7.2.1.tgz", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-7.2.1.tgz",
"integrity": "sha512-oZ0Ib5I4Z2pUEcoo95cT1cr6slco9WY7yiPpG+RGNkj8YcYgJnM7pXmYmorNOReh8MIGcKSqXyeGjxnr8YiZbA==" "integrity": "sha512-oZ0Ib5I4Z2pUEcoo95cT1cr6slco9WY7yiPpG+RGNkj8YcYgJnM7pXmYmorNOReh8MIGcKSqXyeGjxnr8YiZbA=="
}, },
"@tweenjs/tween.js": {
"version": "18.6.0",
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.0.tgz",
"integrity": "sha512-z45HU0G0e/SenbvGdAlTpUR5Hur5zwZXQcqfI+f7EnVHdeb2oMI2rQghEePu7uXuvBC0nuKWG5YtZ1nWbuvqzQ=="
},
"@types/babel__core": { "@types/babel__core": {
"version": "7.1.9", "version": "7.1.9",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz",

View file

@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0", "@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1", "@testing-library/user-event": "^7.2.1",
"@tweenjs/tween.js": "^18.6.0",
"@types/jest": "^24.9.1", "@types/jest": "^24.9.1",
"@types/node": "^12.12.54", "@types/node": "^12.12.54",
"@types/react": "^16.9.47", "@types/react": "^16.9.47",

Binary file not shown.

View file

@ -1,19 +1,5 @@
import React, { import React, { useState, Suspense, useCallback, useEffect } from "react";
useState, import { Canvas } from "react-three-fiber";
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
} from "react";
import {
useFrame,
Canvas,
useLoader,
useThree,
createPortal,
useCamera,
} from "react-three-fiber";
import Lain, { import Lain, {
LainIntro, LainIntro,
LainMoveDown, LainMoveDown,
@ -22,24 +8,32 @@ import Lain, {
LainMoveUp, LainMoveUp,
LainStanding, LainStanding,
} from "./Lain"; } from "./Lain";
import Hub from "./Hub"; import Hub, { PositionAndScaleProps } from "./Hub";
//import Orb from "./Orb"; //import Orb from "./Orb";
import { import { OrbitControls, PerspectiveCamera } from "drei";
OrbitControls,
PerspectiveCamera,
OrthographicCamera,
Octahedron,
} from "drei";
import Lights from "./Lights"; import Lights from "./Lights";
import { Matrix4, Scene } from "three";
import OrthoCamera from "./OrthoCamera"; import OrthoCamera from "./OrthoCamera";
import TWEEN from "@tweenjs/tween.js";
import level_sprite_directions from "../resources/level_sprite_directions.json";
import lain_animations from "../resources/lain_animations.json";
import level_sprite_huds from "../resources/level_sprite_huds.json";
type KeyCodeAssociations = { type KeyCodeAssociations = {
[keyCode: number]: string; [keyCode: number]: string;
}; };
type FrameCounts = { type SpriteDirections = {
[animation: string]: number; [key: string]: Record<string, string>;
};
// will fix the typing on this later
type SpriteHuds = {
[key: string]: Record<string, any>;
};
type LainAnimations = {
[key: string]: Record<string, number>;
}; };
const Game = () => { const Game = () => {
@ -50,6 +44,25 @@ const Game = () => {
const [cameraPosY, setCameraPosY] = useState(0); const [cameraPosY, setCameraPosY] = useState(0);
const [cameraRotationY, setCameraRotationY] = useState(0); const [cameraRotationY, setCameraRotationY] = useState(0);
const [currentSprite, setCurrentSprite] = useState("043");
// we separate positions of the hud sprites into the state since we need to animate thme
const [longHudPosition, setLongHudPosition] = useState<
PositionAndScaleProps
>();
const [boringHudPosition, setBoringHudPosition] = useState<
PositionAndScaleProps
>();
const [bigHudPosition, setBigHudPosition] = useState<PositionAndScaleProps>();
const getMove = (currentLoc: string, key: string): string => {
return (level_sprite_directions as SpriteDirections)[currentLoc][key];
};
const getHudData = (sprite: string) => {
return (level_sprite_huds as SpriteHuds)[sprite];
};
const moveCamera = (value: number, duration: number) => { const moveCamera = (value: number, duration: number) => {
const moveInterval = setInterval(() => { const moveInterval = setInterval(() => {
setCameraPosY((prev: number) => prev + value); setCameraPosY((prev: number) => prev + value);
@ -71,76 +84,67 @@ const Game = () => {
}, duration); }, duration);
}; };
const getKeyValue = <U extends keyof T, T extends object>(key: U) => (
obj: T
) => obj[key];
const getKeyCodeAssociation = (keyCode: number): string => { const getKeyCodeAssociation = (keyCode: number): string => {
return getKeyValue<keyof KeyCodeAssociations, KeyCodeAssociations>(keyCode)( return ({
{ 40: "down",
40: "down", 37: "left",
37: "left", 38: "up",
38: "up", 39: "right",
39: "right", } as KeyCodeAssociations)[keyCode];
};
const setAnimationState = useCallback(
(key: string) => {
const move = getMove(currentSprite, key);
switch (key) {
case "down":
// "+" in the json denotes that the sprite chosen by getMove is not currently on screen,
// therefore lain should first do a move (up/down/left/right) and then that sprite
// will be chosen.
if (move[0] !== "+") setCurrentSprite(move);
else {
setLainMoveState(<LainMoveDown />);
setTimeout(() => {
setCurrentSprite(move);
}, (lain_animations as LainAnimations)[key]["duration"] + 200);
}
break;
case "left":
setLainMoveState(<LainMoveLeft />);
break;
case "up":
setLainMoveState(<LainMoveUp />);
break;
case "right":
setLainMoveState(<LainMoveRight />);
break;
default:
break;
} }
);
};
const getFrameCount = (animation: string): number => { // set moving to true to avoid player from overlapping animations and stuff
return getKeyValue<keyof FrameCounts, FrameCounts>(animation)({ // by waiting for the anim to finish
up: 36, setLainMoving(true);
down: 36,
left: 47,
right: 47,
});
};
// frameCount / FPS * 1000 to turn it into seconds // wait for the anim to finish, set lain to standing state, release the move lock
// 0.27 is a proportional value i calculated from the avg duration of an animation setTimeout(() => {
// in the original game setLainMoving(false);
const getAnimationDuration = (animation: string): number => { setLainMoveState(<LainStanding />);
const frameCount = getFrameCount(animation); }, (lain_animations as LainAnimations)[key]["duration"]);
return (frameCount / (frameCount * 0.27)) * 1000; },
}; [currentSprite]
);
const setAnimationState = (key: string) => {
switch (key) {
case "down":
setLainMoveState(<LainMoveDown />);
break;
case "left":
setLainMoveState(<LainMoveLeft />);
break;
case "up":
setLainMoveState(<LainMoveUp />);
break;
case "right":
setLainMoveState(<LainMoveRight />);
break;
default:
break;
}
// set moving to true to avoid player from overlapping animations and stuff
// by waiting for the anim to finish
setLainMoving(true);
// wait for the anim to finish, set lain to standing state, release the move lock
setTimeout(() => {
setLainMoving(false);
setLainMoveState(<LainStanding />);
}, getAnimationDuration(key));
};
const handleUserKeyPress = useCallback( const handleUserKeyPress = useCallback(
(event) => { (event) => {
const { _, keyCode } = event; const { keyCode } = event;
const key = getKeyCodeAssociation(keyCode); const key = getKeyCodeAssociation(keyCode);
console.log(key); console.log(key);
if (!isLainMoving) { if (!isLainMoving && key) {
setAnimationState(key); setAnimationState(key);
switch (key) { switch (key) {
case "left": case "left":
@ -168,7 +172,7 @@ const Game = () => {
} }
} }
}, },
[isLainMoving] [isLainMoving, setAnimationState]
); );
useEffect(() => { useEffect(() => {
@ -182,6 +186,21 @@ const Game = () => {
}; };
}, [handleUserKeyPress]); }, [handleUserKeyPress]);
const animateSpriteHUDIn = () => {
//wip
const initialLongPos = getHudData(currentSprite)["long"]["initial"];
const finalLongPos = getHudData(currentSprite)["long"]["initial"];
const pos = getHudData(currentSprite)["long"]["position"];
const pos1 = getHudData(currentSprite)["big"]["position"];
const pos2 = getHudData(currentSprite)["boring"]["position"];
setBigHudPosition(pos1);
setLongHudPosition(pos);
setBoringHudPosition(pos2);
};
useEffect(animateSpriteHUDIn, []);
return ( return (
<> <>
<Canvas> <Canvas>
@ -198,7 +217,18 @@ const Game = () => {
<Hub /> <Hub />
<Lights /> <Lights />
<Suspense fallback={null}> <Suspense fallback={null}>
<OrthoCamera /> <OrthoCamera
bigHudPosition={bigHudPosition!}
boringHudPosition={boringHudPosition!}
longHudPosition={longHudPosition!}
longHudType={getHudData(currentSprite)["long"]["type"]}
boringHudType={getHudData(currentSprite)["boring"]["type"]}
bigHudType={getHudData(currentSprite)["big"]["type"]}
longHudScale={getHudData(currentSprite)["long"]["scale"]}
boringHudScale={getHudData(currentSprite)["boring"]["scale"]}
bigHudScale={getHudData(currentSprite)["big"]["scale"]}
id={getHudData(currentSprite)["id"]}
/>
</Suspense> </Suspense>
</PerspectiveCamera> </PerspectiveCamera>
</Canvas> </Canvas>

View file

@ -30,6 +30,7 @@ const GrayRing = (props: any) => {
"/models/ring0.glb", "/models/ring0.glb",
draco("/draco-gltf/") draco("/draco-gltf/")
); );
return ( return (
<group <group
scale={[1.3, 1.3, 1.3]} scale={[1.3, 1.3, 1.3]}

View file

@ -4,24 +4,21 @@ import * as THREE from "three";
import longHud from "../static/sprites/long_hud.png"; import longHud from "../static/sprites/long_hud.png";
import boringHud from "../static/sprites/long_hud_boring.png"; import boringHud from "../static/sprites/long_hud_boring.png";
import bigHud from "../static/sprites/big_hud.png"; import bigHud from "../static/sprites/big_hud.png";
import { PositionAndScaleProps } from "./Hub";
type HUDElementProps = { export type HUDElementProps = {
longHudType: string; longHudType: string;
boringHudType: string; boringHudType: string;
bigHudType: string; bigHudType: string;
longHudPosition: [number, number, number]; longHudPosition: PositionAndScaleProps;
longHudScale: [number, number, number]; longHudScale: PositionAndScaleProps;
boringHudPosition: [number, number, number]; boringHudPosition: PositionAndScaleProps;
boringHudScale: [number, number, number]; boringHudScale: PositionAndScaleProps;
bigHudPosition: [number, number, number]; bigHudPosition: PositionAndScaleProps;
bigHudScale: [number, number, number]; bigHudScale: PositionAndScaleProps;
};
type SpriteTypeToSprite = {
[key: string]: string;
}; };
const HUDElement = (props: HUDElementProps) => { const HUDElement = (props: HUDElementProps) => {
@ -51,6 +48,7 @@ const HUDElement = (props: HUDElementProps) => {
THREE.TextureLoader, THREE.TextureLoader,
spriteTypeToSprite(props.boringHudType, "boring")! spriteTypeToSprite(props.boringHudType, "boring")!
); );
const bigHudTexture: any = useLoader( const bigHudTexture: any = useLoader(
THREE.TextureLoader, THREE.TextureLoader,
spriteTypeToSprite(props.bigHudType, "big")! spriteTypeToSprite(props.bigHudType, "big")!
@ -65,10 +63,7 @@ const HUDElement = (props: HUDElementProps) => {
transparent={true} transparent={true}
/> />
</sprite> </sprite>
<sprite <sprite position={props.boringHudPosition} scale={props.boringHudScale}>
position={props.boringHudPosition}
scale={props.boringHudScale}
>
<spriteMaterial <spriteMaterial
attach="material" attach="material"
map={longHudBoringTexture} map={longHudBoringTexture}

View file

@ -4,8 +4,8 @@ import PurpleRing from "./PurpleRing";
import LevelSprite from "./LevelSprite"; import LevelSprite from "./LevelSprite";
import level_sprites from "../resources/level_sprites.json"; import level_sprites from "../resources/level_sprites.json";
type PositionAndScaleProps = [number, number, number]; export type PositionAndScaleProps = [number, number, number];
type RotationProps = [number, number, number, (string | undefined)?]; export type RotationProps = [number, number, number, (string | undefined)?];
const Hub = (props: any) => { const Hub = (props: any) => {
return ( return (

View file

@ -45,7 +45,6 @@ const LevelSprite = (props: LevelSpriteConstructorProps) => {
> >
<planeBufferGeometry attach="geometry" /> <planeBufferGeometry attach="geometry" />
<meshStandardMaterial <meshStandardMaterial
color={0xffffff}
side={THREE.DoubleSide} side={THREE.DoubleSide}
attach="material" attach="material"
map={spriteTexture} map={spriteTexture}

View file

@ -18,12 +18,13 @@ import {
import { OrthographicCamera, Octahedron } from "drei"; import { OrthographicCamera, Octahedron } from "drei";
import { Matrix4, Scene, BasicDepthPacking } from "three"; import { Matrix4, Scene, BasicDepthPacking } from "three";
import * as THREE from "three"; import * as THREE from "three";
import HUDElement from "./HUDElement"; import HUDElement, { HUDElementProps } from "./HUDElement";
import level_sprite_huds from "../resources/level_sprite_huds.json";
type PositionAndScaleProps = [number, number, number]; interface OrthoCameraProps extends HUDElementProps {
id: string;
}
const OrthoCamera = () => { const OrthoCamera = (props: OrthoCameraProps) => {
const { gl, scene, camera } = useThree(); const { gl, scene, camera } = useThree();
const virtualScene = useMemo(() => new Scene(), []); const virtualScene = useMemo(() => new Scene(), []);
const virtualCam = useRef(); const virtualCam = useRef();
@ -42,23 +43,18 @@ const OrthoCamera = () => {
makeDefault={false} makeDefault={false}
position={[0, 0, 10]} position={[0, 0, 10]}
> >
{Object.values(level_sprite_huds.level04).map((spriteHud) => { <HUDElement
return ( longHudType={props.longHudType}
<HUDElement boringHudType={props.boringHudType}
longHudType={spriteHud.long.type} bigHudType={props.bigHudType}
boringHudType={spriteHud.boring.type} longHudPosition={props.longHudPosition}
bigHudType={spriteHud.big.type} longHudScale={props.longHudScale}
longHudPosition={spriteHud.long.position as PositionAndScaleProps} boringHudPosition={props.boringHudPosition}
longHudScale={spriteHud.long.scale as PositionAndScaleProps} boringHudScale={props.boringHudScale}
boringHudPosition={ bigHudPosition={props.bigHudPosition}
spriteHud.boring.position as PositionAndScaleProps bigHudScale={props.bigHudScale}
} key={props.id}
boringHudScale={spriteHud.boring.scale as PositionAndScaleProps} />
bigHudPosition={spriteHud.big.position as PositionAndScaleProps}
bigHudScale={spriteHud.big.scale as PositionAndScaleProps}
/>
);
})}
</OrthographicCamera> </OrthographicCamera>
); );
}; };

View file

@ -0,0 +1,18 @@
{
"up": {
"frame_count": 36,
"duration": 3703.704
},
"down": {
"frame_count": 36,
"duration": 3703.704
},
"left": {
"frame_count": 47,
"duration": 3703.704
},
"right": {
"frame_count": 47,
"duration": 3703.704
}
}

View file

@ -0,0 +1,8 @@
{
"043": {
"up": "+",
"down": "042",
"left": "+",
"right": ""
}
}

View file

@ -1,21 +1,21 @@
{ {
"level04": { "043": {
"043": { "id": "043hud",
"long": { "long": {
"position": [-0.45, 0.15, -8.6], "position": [-0.45, 0.15, -8.6],
"scale": [1, 0.03, 1], "scale": [1, 0.03, 1],
"type": "normal" "type": "normal",
}, "initial_position": [-1.45, 0.15, -8.6]
"boring": { },
"position": [0.48, 0.174, -8.6], "boring": {
"scale": [1, 0.03, 1], "position": [0.48, 0.174, -8.6],
"type": "normal" "scale": [1, 0.03, 1],
}, "type": "normal"
"big": { },
"position": [0.36, 0.13, -8.6], "big": {
"scale": [0.5, 0.06, 1], "position": [0.36, 0.13, -8.6],
"type": "normal" "scale": [0.5, 0.06, 1],
} "type": "normal"
} }
} }
} }