Skip to content

Commit

Permalink
Merge pull request #21 from cyrus2281/drone
Browse files Browse the repository at this point in the history
Drone System
  • Loading branch information
cyrus2281 committed Aug 27, 2023
2 parents ce06054 + c9585eb commit cabe98e
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 43 deletions.
3 changes: 3 additions & 0 deletions public/blob/audio/guy/bridge.wav
Git LFS file not shown
File renamed without changes.
File renamed without changes.
File renamed without changes
3 changes: 3 additions & 0 deletions public/blob/model/drone.glb
Git LFS file not shown
3 changes: 3 additions & 0 deletions public/blob/model/night-city.glb
Git LFS file not shown
3 changes: 0 additions & 3 deletions public/blob/night-city.glb

This file was deleted.

2 changes: 2 additions & 0 deletions src/experience/Experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Effects from "./effects/Effects";
import Character from "./character/Character";
import World from "./world/World";
import CanvasInterface from "./interface/CanvasInterface";
import Drone from "./character/Drone";

function Experience() {
return (
Expand All @@ -15,6 +16,7 @@ function Experience() {
<Lights />

<Character />
<Drone />
<World />
</Physics>
</>
Expand Down
181 changes: 181 additions & 0 deletions src/experience/character/Drone.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { useFrame } from "@react-three/fiber";
import { RapierRigidBody, RigidBody } from "@react-three/rapier";
import { useRef } from "react";
import { ASSETS } from "../utils/constants";
import { useGLTF } from "@react-three/drei";

const minmax = {
x: { min: -22, max: 9, middle: -6 },
y: { min: 3, max: 10 },
z: { min: -12, max: 9, middle: -1 },
};
const step = 0.002;

let prev = { x: minmax.x.min, y: minmax.y.max, z: minmax.z.min };

let xCoord = 4.8;
let yCoord = 2;
let zCoord = 3;

let hDirection = false;
let passedMiddle = true;

const getCoordinates = () => {
const prevX = Math.floor(prev.x);
const prevZ = Math.floor(prev.z);
const prevY = Math.floor(prev.y);

if (hDirection) {
if (prevX === 3 && prevZ === minmax.z.max && prevY > minmax.y.min) {
// Come down by bridge
yCoord += step * 2;
} else if (prevX === 3 && prevZ === minmax.z.min && prevY < minmax.y.max) {
// Go up by Tech Center roof
yCoord += step * 2;
} else if (prevZ > 7 && prevX > -17 && prevX < -13) {
// Slow down by post office roof
xCoord += step / 5;
} else {
xCoord += step;
}
// Passed the middle point (good to turn)
if (prevX === minmax.x.middle && !passedMiddle) {
passedMiddle = true;
}
} else {
zCoord += step;
// Passed the middle point (good to turn)
if (prevZ === minmax.z.middle && !passedMiddle) {
passedMiddle = true;
}
}
// Change direction (turn)
if (
((hDirection && (prevX === minmax.x.min || prevX === minmax.x.max)) ||
(!hDirection && (prevZ === minmax.z.max || prevZ === minmax.z.min))) &&
passedMiddle
) {
hDirection = !hDirection;
passedMiddle = false;
}

prev = {
x: Math.sin(xCoord) * 15.5 - 6,
y: Math.sin(yCoord) * 3.5 + 7,
z: Math.cos(zCoord) * 10.6 - 1.2,
};
return prev;
};

const cabin = {
opacity: 1,
thickness: 0.2,
height: 0.7,
length: 2.5,
width: 1.5,
depth: 0.5,
mass: 20,
color: "white",
};

function Drone() {
const bodyRef = useRef<RapierRigidBody>();
const drone = useGLTF(ASSETS.MODELS.DRONE);

useFrame((state) => {
if (!bodyRef.current) return;
bodyRef.current.setTranslation(getCoordinates(), false);
});

return (
<>
<RigidBody
ref={bodyRef as React.Ref<RapierRigidBody>}
colliders={"hull"}
type="fixed"
position={[10, 100, 10]}
linearDamping={0}
angularDamping={0}
friction={0.5}
restitution={0}
mass={cabin.mass}
>
<group position={[0, 0, 0.5]}>
<group name="cabin">
<mesh rotation={[0, 0, 0]} position={[-0.25, 0, 0]}>
<boxGeometry args={[cabin.length, 0.4, cabin.width]} />
<meshStandardMaterial
color={cabin.color}
opacity={cabin.opacity}
transparent
/>
</mesh>
<mesh
rotation={[0, 0, -Math.PI / 2]}
position={[0.65, cabin.depth, 0]}
>
<boxGeometry
args={[cabin.height, cabin.thickness, cabin.width]}
/>
<meshStandardMaterial
color={cabin.color}
opacity={cabin.opacity}
transparent
/>
</mesh>
<mesh
rotation={[0, 0, Math.PI / 2]}
position={[-1.65, cabin.depth, 0]}
>
<boxGeometry
args={[cabin.height, cabin.thickness, cabin.width]}
/>
<meshStandardMaterial
color={cabin.color}
opacity={cabin.opacity}
transparent
/>
</mesh>
<mesh
rotation={[Math.PI / 2, 0, 0]}
position={[-0.5, cabin.depth, 0.85]}
>
<boxGeometry
args={[cabin.length, cabin.thickness, cabin.height]}
/>
<meshStandardMaterial
color={cabin.color}
opacity={cabin.opacity}
transparent
/>
</mesh>
<mesh
rotation={[-Math.PI / 2, 0, 0]}
position={[-0.5, cabin.depth, -0.85]}
>
<boxGeometry
args={[cabin.length, cabin.thickness, cabin.height]}
/>
<meshStandardMaterial
color={cabin.color}
opacity={cabin.opacity}
transparent
/>
</mesh>
</group>
<primitive
name="drone"
object={drone.scene}
scale={[9.5, 4, 9.5]}
rotation={[0, Math.PI / 2, 0]}
position={[-0.47, -0.05, 0]}
/>
</group>
</RigidBody>
</>
);
}

useGLTF.preload(ASSETS.MODELS.DRONE);

export default Drone;
4 changes: 2 additions & 2 deletions src/experience/interface/TerritoryInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import useLocation from "../stores/useLocation";
import { useEffect, useState } from "react";
import useGlobal from "../stores/useGlobal";
import { Vector3 } from "three";
import { TERRITORIES_NAMES } from "../utils/enums";
import { MAIN_TERRITORIES_NAMES } from "../utils/enums";
import { TERRITORY_AUDIOS } from "../utils/guyAudios";
import useSound from "../stores/useSound";

Expand Down Expand Up @@ -80,7 +80,7 @@ function TerritoryInterfaceDebug({
}

type VisitedTerritoriesInterface = {
[key in TERRITORIES_NAMES]?: {
[key in MAIN_TERRITORIES_NAMES]?: {
lastVisited: number;
};
};
Expand Down
8 changes: 4 additions & 4 deletions src/experience/interface/ui/StatsView.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useEffect, useState } from "react";
import useLocation from "../../stores/useLocation";
import "./StatsView.scss";
import { TERRITORIES_NAMES } from "../../utils/enums";
import { MAIN_TERRITORIES_NAMES } from "../../utils/enums";
import { ASSETS, LOCAL_STORAGE_KEYS } from "../../utils/constants";
import useSound from "../../stores/useSound";
import { GUY_AUDIOS, TERRITORY_AUDIOS } from "../../utils/guyAudios";
import useGlobal from "../../stores/useGlobal";

const totalTerritories = Object.values(TERRITORIES_NAMES);
const totalTerritories = Object.values(MAIN_TERRITORIES_NAMES);
const totalAudios = Object.values(TERRITORY_AUDIOS).map((audio) =>
audio.path.replace(ASSETS.GUY_AUDIO, "")
);
Expand All @@ -26,7 +26,7 @@ function StatsView() {
// Update places count
const visitedPlaces = JSON.parse(
localStorage.getItem(LOCAL_STORAGE_KEYS.VISITED_PLACES) || "[]"
).filter((place: TERRITORIES_NAMES) => totalTerritories.includes(place));
).filter((place: MAIN_TERRITORIES_NAMES) => totalTerritories.includes(place));
visitedPlaces.push(...territoriesName);
const uniquePlaces = [...new Set(visitedPlaces)];
setPlaces(uniquePlaces.length);
Expand All @@ -40,7 +40,7 @@ function StatsView() {
// Update audios count
const discoveredAudios = JSON.parse(
localStorage.getItem(LOCAL_STORAGE_KEYS.DISCOVERED_AUDIOS) || "[]"
).filter((audio: TERRITORIES_NAMES) => totalAudios.includes(audio));
).filter((audio: MAIN_TERRITORIES_NAMES) => totalAudios.includes(audio));
discoveredAudios.push(
...activeSounds
.filter((audio) =>
Expand Down
8 changes: 7 additions & 1 deletion src/experience/interface/ui/TitleBar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { useEffect, useState } from "react";
import "./TitleBar.scss";
import useLocation from "../../stores/useLocation";
import { MAIN_TERRITORIES_NAMES } from "../../utils/enums";

const mainTerritories = Object.values(MAIN_TERRITORIES_NAMES);

function TitleBar() {
const territoriesName = useLocation((state) => state.territoriesName);
const [text, setText] = useState("");
const [isHidden, setIsHidden] = useState(true);

useEffect(() => {
if (territoriesName.length) {
if (
territoriesName.length &&
mainTerritories.includes(territoriesName.at(-1) as MAIN_TERRITORIES_NAMES)
) {
setText(territoriesName.at(-1) as string);
}
}, [territoriesName]);
Expand Down
2 changes: 1 addition & 1 deletion src/experience/lights/Lights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function Lights() {
return (
<>
<Environment map={window.map} background resolution={256} blur={0.05} />
<ambientLight intensity={0.06} />
<ambientLight intensity={0.09} />
</>
);
}
Expand Down
6 changes: 4 additions & 2 deletions src/experience/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Vector3 } from "three";

// export const CHARACTER_INITIAL_POSITION = new Vector3(-20, 0.01, 11);
// export const CHARACTER_INITIAL_POSITION = new Vector3(5.5, 9, 12);
export const CHARACTER_INITIAL_POSITION = new Vector3(21, 0.01, 7);

export const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
Expand All @@ -21,8 +22,9 @@ export const WORLD_THRESHOLD = {

export const ASSETS = {
MODELS: {
FOX: "/blob/Fox/Fox.gltf",
CITY: "/blob/night-city.glb",
FOX: "/blob/model/Fox/Fox.gltf",
CITY: "/blob/model/night-city.glb",
DRONE: "/blob/model/drone.glb",
},
ENV_MAP: "/blob/envMap/night_city.jpg",
BACKGROUND_MUSIC: {
Expand Down
8 changes: 7 additions & 1 deletion src/experience/utils/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export enum TerritoryType {
RECTANGULAR_ALTITUDE = "rectangular-altitude",
}

export enum TERRITORIES_NAMES {
export enum MAIN_TERRITORIES_NAMES {
BAR = "Space Bar",
PARK = "Park",
PARK_FOUNTAIN = "Park Fountain",
Expand All @@ -17,6 +17,12 @@ export enum TERRITORIES_NAMES {
POST_OFFICE = "Post Office",
}

export enum OTHER_TERRITORIES_NAMES {
PIPES = "Duct Pipes",
}

export type TERRITORIES_NAMES = MAIN_TERRITORIES_NAMES | OTHER_TERRITORIES_NAMES;

export enum MODEL_ANIMATIONS {
IDLE = "Survey",
WALK = "Walk",
Expand Down
Loading

0 comments on commit cabe98e

Please sign in to comment.