mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
adding intro animation
This commit is contained in:
parent
3d6524bee2
commit
168fe2cb9f
10 changed files with 157 additions and 105 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -21,3 +21,6 @@
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
.idea
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
|
||||||
import Game from "./components/Game";
|
import Game from "./components/Game";
|
||||||
import "./static/css/hub.css";
|
import "./static/css/hub.css";
|
||||||
import "./static/css/main.css";
|
import "./static/css/main.css";
|
||||||
|
import { Canvas } from "react-three-fiber";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [moveToGame, setMoveToGame] = useState(false);
|
const [moveToGame, setMoveToGame] = useState(false);
|
||||||
|
@ -18,7 +19,9 @@ const App = () => {
|
||||||
<div id="game-root" className="game">
|
<div id="game-root" className="game">
|
||||||
{/* {moveToGame ? <Game /> : <Intro setMoveToGame={setMoveToGame} />} */}
|
{/* {moveToGame ? <Game /> : <Intro setMoveToGame={setMoveToGame} />} */}
|
||||||
{/* <Intro /> */}
|
{/* <Intro /> */}
|
||||||
<Game />
|
<Canvas concurrent>
|
||||||
|
<Game />
|
||||||
|
</Canvas>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { a, useSpring } from "@react-spring/three";
|
import { a, useSpring } from "@react-spring/three";
|
||||||
import { OrbitControls } from "drei";
|
import { OrbitControls } from "drei";
|
||||||
import React, { Suspense, useCallback, useEffect, useState } from "react";
|
import React, {
|
||||||
import { Canvas } from "react-three-fiber";
|
Suspense,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { useFrame } from "react-three-fiber";
|
||||||
import lain_animations from "../resources/lain_animations.json";
|
import lain_animations from "../resources/lain_animations.json";
|
||||||
import level_sprite_directions from "../resources/level_sprite_directions.json";
|
import level_sprite_directions from "../resources/level_sprite_directions.json";
|
||||||
import level_sprite_huds from "../resources/level_sprite_huds.json";
|
import level_sprite_huds from "../resources/level_sprite_huds.json";
|
||||||
|
@ -12,11 +18,13 @@ import Lain, {
|
||||||
LainMoveRight,
|
LainMoveRight,
|
||||||
LainMoveUp,
|
LainMoveUp,
|
||||||
LainStanding,
|
LainStanding,
|
||||||
|
LainIntro,
|
||||||
} from "./Lain";
|
} from "./Lain";
|
||||||
import Lights from "./Lights";
|
import Lights from "./Lights";
|
||||||
import OrthoCamera from "./OrthoCamera";
|
import OrthoCamera from "./OrthoCamera";
|
||||||
import Preloader from "./Preloader";
|
import Preloader from "./Preloader";
|
||||||
import Starfield from "./Starfield";
|
import Starfield from "./Starfield";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
type KeyCodeAssociations = {
|
type KeyCodeAssociations = {
|
||||||
[keyCode: number]: string;
|
[keyCode: number]: string;
|
||||||
|
@ -36,12 +44,14 @@ type LainAnimations = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Game = () => {
|
const Game = () => {
|
||||||
|
const [isIntro, setIsIntro] = useState(true);
|
||||||
|
|
||||||
const [isLainMoving, setLainMoving] = useState(false);
|
const [isLainMoving, setLainMoving] = useState(false);
|
||||||
const [lainMoveState, setLainMoveState] = useState(<LainStanding />);
|
const [lainMoveState, setLainMoveState] = useState(<LainStanding />);
|
||||||
|
|
||||||
const [orthoCameraPosY, setOrthoCameraPosY] = useState(0);
|
const [orthoCameraPosY, setOrthoCameraPosY] = useState(0);
|
||||||
|
|
||||||
const [currentSprite, setCurrentSprite] = useState("0506");
|
const [currentSprite, setCurrentSprite] = useState("0422");
|
||||||
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)]
|
||||||
);
|
);
|
||||||
|
@ -169,8 +179,8 @@ const Game = () => {
|
||||||
(key: string) => {
|
(key: string) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "down":
|
case "down":
|
||||||
moveCamera(0.3);
|
moveCamera(0.6);
|
||||||
moveLain(-0.3);
|
moveLain(-0.6);
|
||||||
setLainMoveState(<LainMoveDown />);
|
setLainMoveState(<LainMoveDown />);
|
||||||
break;
|
break;
|
||||||
case "left":
|
case "left":
|
||||||
|
@ -290,21 +300,51 @@ const Game = () => {
|
||||||
};
|
};
|
||||||
}, [handleKeyPress]);
|
}, [handleKeyPress]);
|
||||||
|
|
||||||
|
const groupRef = useRef();
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (isIntro) {
|
||||||
|
if ((groupRef.current as any).rotation.x > 0) {
|
||||||
|
if ((groupRef.current as any).position.z > -1) {
|
||||||
|
(groupRef.current as any).rotation.x -= 0.015;
|
||||||
|
} else {
|
||||||
|
(groupRef.current as any).rotation.x -= 0.01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((groupRef.current as any).position.y > 0) {
|
||||||
|
(groupRef.current as any).position.y -= 0.015;
|
||||||
|
}
|
||||||
|
if ((groupRef.current as any).position.z < 0) {
|
||||||
|
(groupRef.current as any).position.z += 0.04;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLainMoving(true);
|
||||||
|
setLainMoveState(<LainIntro />);
|
||||||
|
updateHUD();
|
||||||
|
setTimeout(() => {
|
||||||
|
setLainMoving(false);
|
||||||
|
setLainMoveState(<LainStanding />);
|
||||||
|
setIsIntro(false);
|
||||||
|
updateHUD();
|
||||||
|
}, (lain_animations as LainAnimations)["intro"]["duration"]);
|
||||||
|
}, [updateHUD]);
|
||||||
|
|
||||||
|
// pos-z ? => 3
|
||||||
|
// rot-x 1.5 => 0
|
||||||
|
// grp rot/pos both 0,0,0 => ?
|
||||||
return (
|
return (
|
||||||
<Canvas concurrent>
|
<a.perspectiveCamera
|
||||||
<a.perspectiveCamera
|
position-z={3}
|
||||||
position-z={3}
|
position-y={camPosY}
|
||||||
position-y={camPosY}
|
rotation-y={camRotY}
|
||||||
rotation-y={camRotY}
|
>
|
||||||
>
|
<group rotation={[2.3, 0, 0]} position={[0, 1.5, -7.5]} ref={groupRef}>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<OrbitControls />
|
<OrbitControls />
|
||||||
<Preloader />
|
<Preloader />
|
||||||
<Lain
|
|
||||||
isLainMoving={isLainMoving}
|
|
||||||
lainMoveState={lainMoveState}
|
|
||||||
lainPosY={lainPosY}
|
|
||||||
/>
|
|
||||||
<Hub currentSprite={currentSprite} />
|
<Hub currentSprite={currentSprite} />
|
||||||
<OrthoCamera
|
<OrthoCamera
|
||||||
longHUDPosX={longHUDPosX}
|
longHUDPosX={longHUDPosX}
|
||||||
|
@ -330,13 +370,18 @@ const Game = () => {
|
||||||
bigHUDScale={currentSpriteHUD!["big"]["scale"]}
|
bigHUDScale={currentSpriteHUD!["big"]["scale"]}
|
||||||
orthoCameraPosY={orthoCameraPosY}
|
orthoCameraPosY={orthoCameraPosY}
|
||||||
id={currentSpriteHUD!["id"]}
|
id={currentSpriteHUD!["id"]}
|
||||||
|
orbVisibility={!isIntro}
|
||||||
/>
|
/>
|
||||||
<OrbitControls />
|
|
||||||
<Starfield starfieldPosY={camPosY} />
|
<Starfield starfieldPosY={camPosY} />
|
||||||
<Lights />
|
<Lights />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</a.perspectiveCamera>
|
</group>
|
||||||
</Canvas>
|
<Lain
|
||||||
|
isLainMoving={isLainMoving}
|
||||||
|
lainMoveState={lainMoveState}
|
||||||
|
lainPosY={lainPosY}
|
||||||
|
/>
|
||||||
|
</a.perspectiveCamera>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default Game;
|
export default Game;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import moveUpSpriteSheet from "../static/sprites/jump_up.png";
|
||||||
import moveLeftSpriteSheet from "../static/sprites/move_left.png";
|
import moveLeftSpriteSheet from "../static/sprites/move_left.png";
|
||||||
import moveRightSpriteSheet from "../static/sprites/move_right.png";
|
import moveRightSpriteSheet from "../static/sprites/move_right.png";
|
||||||
import standingSpriteSheet from "../static/sprites/standing.png";
|
import standingSpriteSheet from "../static/sprites/standing.png";
|
||||||
|
import introSpriteSheet from "../static/sprites/intro.png";
|
||||||
|
|
||||||
type LainProps = {
|
type LainProps = {
|
||||||
isLainMoving: boolean;
|
isLainMoving: boolean;
|
||||||
|
@ -47,10 +48,10 @@ const LainConstructor = (props: LainConstructorProps) => {
|
||||||
export const LainIntro = () => {
|
export const LainIntro = () => {
|
||||||
return (
|
return (
|
||||||
<LainConstructor
|
<LainConstructor
|
||||||
sprite={standingSpriteSheet}
|
sprite={introSpriteSheet}
|
||||||
frameCount={1}
|
frameCount={50}
|
||||||
framesHorizontal={8}
|
framesHorizontal={10}
|
||||||
framesVertical={6}
|
framesVertical={5}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,11 @@ import orbSprite from "../static/sprites/orb.png";
|
||||||
let orbIdx = 0;
|
let orbIdx = 0;
|
||||||
let orbDirectionChangeCount = 0;
|
let orbDirectionChangeCount = 0;
|
||||||
|
|
||||||
const Orb = memo(() => {
|
type OrbProps = {
|
||||||
|
orbVisibility: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Orb = memo((props: OrbProps) => {
|
||||||
const orbRef = useRef();
|
const orbRef = useRef();
|
||||||
const [orbDirection, setOrbDirection] = useState("left");
|
const [orbDirection, setOrbDirection] = useState("left");
|
||||||
const [currentCurve, setCurrentCurve] = useState("first");
|
const [currentCurve, setCurrentCurve] = useState("first");
|
||||||
|
@ -29,79 +33,81 @@ const Orb = memo(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
let orbPosFirst = firstCurve.getPoint(orbIdx / 250);
|
if (props.orbVisibility) {
|
||||||
let orbPosSecond = secondCurve.getPoint(orbIdx / 250);
|
let orbPosFirst = firstCurve.getPoint(orbIdx / 250);
|
||||||
|
let orbPosSecond = secondCurve.getPoint(orbIdx / 250);
|
||||||
|
|
||||||
if (orbPosFirst.x < -1.4) {
|
if (orbPosFirst.x < -1.4) {
|
||||||
switch (currentCurve) {
|
switch (currentCurve) {
|
||||||
case "first":
|
case "first":
|
||||||
setOrbDirection("right");
|
setOrbDirection("right");
|
||||||
break;
|
break;
|
||||||
case "second":
|
case "second":
|
||||||
setOrbDirection("left");
|
setOrbDirection("left");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
orbDirectionChangeCount++;
|
||||||
}
|
}
|
||||||
orbDirectionChangeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orbPosFirst.x > 1.4) {
|
if (orbPosFirst.x > 1.4) {
|
||||||
switch (currentCurve) {
|
switch (currentCurve) {
|
||||||
case "first":
|
case "first":
|
||||||
setOrbDirection("left");
|
setOrbDirection("left");
|
||||||
break;
|
break;
|
||||||
case "second":
|
case "second":
|
||||||
setOrbDirection("right");
|
setOrbDirection("right");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
orbDirectionChangeCount++;
|
||||||
}
|
}
|
||||||
orbDirectionChangeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orbDirection === "left") {
|
if (orbDirection === "left") {
|
||||||
switch (currentCurve) {
|
switch (currentCurve) {
|
||||||
case "first":
|
case "first":
|
||||||
orbIdx++;
|
orbIdx++;
|
||||||
break;
|
break;
|
||||||
case "second":
|
case "second":
|
||||||
orbIdx--;
|
orbIdx--;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (currentCurve) {
|
||||||
|
case "first":
|
||||||
|
orbIdx--;
|
||||||
|
break;
|
||||||
|
case "second":
|
||||||
|
orbIdx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
switch (currentCurve) {
|
|
||||||
case "first":
|
|
||||||
orbIdx--;
|
|
||||||
break;
|
|
||||||
case "second":
|
|
||||||
orbIdx++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orbDirectionChangeCount % 6 === 0 && orbDirectionChangeCount !== 0) {
|
if (orbDirectionChangeCount % 6 === 0 && orbDirectionChangeCount !== 0) {
|
||||||
orbDirectionChangeCount = 0;
|
orbDirectionChangeCount = 0;
|
||||||
switch (currentCurve) {
|
switch (currentCurve) {
|
||||||
case "first":
|
case "first":
|
||||||
orbIdx = 250;
|
orbIdx = 250;
|
||||||
setCurrentCurve("second");
|
setCurrentCurve("second");
|
||||||
break;
|
break;
|
||||||
case "second":
|
case "second":
|
||||||
orbIdx = 0;
|
orbIdx = 0;
|
||||||
setCurrentCurve("first");
|
setCurrentCurve("first");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
setOrbDirection("left");
|
||||||
}
|
}
|
||||||
setOrbDirection("left");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentCurve === "first") {
|
if (currentCurve === "first") {
|
||||||
(orbRef.current as any).position.x = orbPosFirst.x;
|
(orbRef.current as any).position.x = orbPosFirst.x;
|
||||||
(orbRef.current as any).position.y = orbPosFirst.y;
|
(orbRef.current as any).position.y = orbPosFirst.y;
|
||||||
} else {
|
} else {
|
||||||
(orbRef.current as any).position.x = orbPosSecond.x;
|
(orbRef.current as any).position.x = orbPosSecond.x;
|
||||||
(orbRef.current as any).position.y = orbPosSecond.y;
|
(orbRef.current as any).position.y = orbPosSecond.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group position={[0, -0.1, -9]}>
|
<group position={[0, -0.1, -9]} visible={props.orbVisibility}>
|
||||||
<sprite scale={[0.5, 0.5, 0.5]} ref={orbRef}>
|
<sprite scale={[0.5, 0.5, 0.5]} ref={orbRef}>
|
||||||
<spriteMaterial attach="material" map={orbSpriteTexture} />
|
<spriteMaterial attach="material" map={orbSpriteTexture} />
|
||||||
</sprite>
|
</sprite>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Orb from "./Orb";
|
||||||
interface OrthoCameraProps extends HUDElementProps {
|
interface OrthoCameraProps extends HUDElementProps {
|
||||||
id: string;
|
id: string;
|
||||||
orthoCameraPosY: number;
|
orthoCameraPosY: number;
|
||||||
|
orbVisibility:boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OrthoCamera = (props: OrthoCameraProps) => {
|
const OrthoCamera = (props: OrthoCameraProps) => {
|
||||||
|
@ -43,7 +44,7 @@ const OrthoCamera = (props: OrthoCameraProps) => {
|
||||||
bigHUDScale={props.bigHUDScale}
|
bigHUDScale={props.bigHUDScale}
|
||||||
key={props.id}
|
key={props.id}
|
||||||
/>
|
/>
|
||||||
<Orb />
|
<Orb orbVisibility={props.orbVisibility}/>
|
||||||
</orthographicCamera>
|
</orthographicCamera>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { a, useSpring } from "@react-spring/three";
|
|
||||||
import { draco } from "drei";
|
import { draco } from "drei";
|
||||||
import React, { memo } from "react";
|
import React, { memo, useRef } 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";
|
||||||
|
@ -17,13 +16,7 @@ type GLTFResult = GLTF & {
|
||||||
};
|
};
|
||||||
|
|
||||||
const PurpleRing = memo((props: PurpleRingProps) => {
|
const PurpleRing = memo((props: PurpleRingProps) => {
|
||||||
const [{ purpleRingRotationY }, setPurpleRingRotationY] = useSpring(
|
const purpleRingRef = useRef();
|
||||||
() => ({
|
|
||||||
purpleRingRotationY: 0,
|
|
||||||
config: { precision: 0.0001, duration: 1200 },
|
|
||||||
}),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { nodes } = useLoader<GLTFResult>(
|
const { nodes } = useLoader<GLTFResult>(
|
||||||
GLTFLoader,
|
GLTFLoader,
|
||||||
|
@ -32,18 +25,14 @@ const PurpleRing = memo((props: PurpleRingProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
setPurpleRingRotationY(() => ({
|
(purpleRingRef.current as any).rotation.y += 0.01;
|
||||||
purpleRingRotationY: purpleRingRotationY.get() + 0.15,
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const purpleRingRotY = purpleRingRotationY.to([0, 1], [0, Math.PI]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a.group
|
<group
|
||||||
position={[0, props.purpleRingPosY, 0]}
|
position={[0, props.purpleRingPosY, 0]}
|
||||||
rotation-y={purpleRingRotY}
|
|
||||||
scale={[1.3, 1.3, 1.3]}
|
scale={[1.3, 1.3, 1.3]}
|
||||||
|
ref={purpleRingRef}
|
||||||
>
|
>
|
||||||
<mesh geometry={nodes.Circle002.geometry} rotation={[0, Math.PI / 4, 0]}>
|
<mesh geometry={nodes.Circle002.geometry} rotation={[0, Math.PI / 4, 0]}>
|
||||||
<meshLambertMaterial
|
<meshLambertMaterial
|
||||||
|
@ -52,7 +41,7 @@ const PurpleRing = memo((props: PurpleRingProps) => {
|
||||||
side={THREE.DoubleSide}
|
side={THREE.DoubleSide}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
</a.group>
|
</group>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ const Starfield = memo((props: StarfieldProps) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group position={[-0.7, -1.5, -4]} >
|
<group position={[-0.7, -1.5, -4]} rotation={[0,0,0]}>
|
||||||
{posesBlueFromRight.map((pos: any, idx: number) => {
|
{posesBlueFromRight.map((pos: any, idx: number) => {
|
||||||
return (
|
return (
|
||||||
<mesh
|
<mesh
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"intro": {
|
||||||
|
"frame_count": 50,
|
||||||
|
"duration": 3944.033
|
||||||
|
},
|
||||||
"up": {
|
"up": {
|
||||||
"frame_count": 36,
|
"frame_count": 36,
|
||||||
"duration": 3703.704
|
"duration": 3703.704
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
},
|
},
|
||||||
"0506": {
|
"0506": {
|
||||||
"up": "0413",
|
"up": "0413",
|
||||||
"down": "0422",
|
"down": "+0422",
|
||||||
"left": "0405",
|
"left": "0405",
|
||||||
"right": "0513"
|
"right": "0513"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue