This commit is contained in:
TreetopFlyer 2022-11-18 17:09:33 -05:00
parent 4ea26b08a3
commit 34d0c591a9
1 changed files with 24 additions and 21 deletions

45
app.js
View File

@ -6,21 +6,21 @@ import * as RTF from 'https://esm.sh/@react-three/fiber'
import { useGLTF, useAnimations, PerspectiveCamera } from 'https://esm.sh/@react-three/drei' import { useGLTF, useAnimations, PerspectiveCamera } from 'https://esm.sh/@react-three/drei'
import {html} from 'https://esm.sh/htm/react' import {html} from 'https://esm.sh/htm/react'
/**@typedef {[x:number, y:number, z:number]} V3 */
/** /**
* @typedef {{Type:"click", Payload:number}} ActionClick @typedef {[x:number, y:number, z:number]} V3
* @typedef {{Type:"round"}} ActionRound
* @typedef {ActionClick | ActionRound} Action @typedef {{Type:"click", Payload:number}} ActionClick
*/ @typedef {{Type:"round"}} ActionRound
/** @typedef {ActionClick | ActionRound} Action
* @typedef {{Done:boolean, Pos:V3}} StateGoal
*/ @typedef {{Done:boolean, Pos:V3}} StateGoal
/**
* @typedef {{Round:number, Done:boolean, Goals:Array<StateGoal>}} State @typedef {{Round:number, Done:boolean, Goals:Array<StateGoal>}} State
*/
/** @typedef {(inState:State, inAction:Action)=>void} Reducer */ @typedef {(inState:State, inAction:Action)=>void} Reducer
/** @typedef {{Initial:State, Reducer:React.Reducer<State, Action>, Consume:()=>GameBinding}} Game */ @typedef {{Initial:State, Reducer:React.Reducer<State, Action>, Consume:()=>GameBinding}} Game
/** @typedef {[State:State, Dispatcher:React.Dispatch<Action>]} GameBinding */ @typedef {[State:State, Dispatcher:React.Dispatch<Action>]} GameBinding
*/
/** @type Game */ /** @type Game */
const Game = const Game =
@ -28,8 +28,8 @@ const Game =
Initial: Initial:
{ {
Round:0, Round:0,
Goals:[{Done:false, Pos:[0, 0, 0]}, {Done:true, Pos:[2, 0, 0]}], Goals:[],
Done:false Done:true
}, },
Reducer(inState, inAction) Reducer(inState, inAction)
{ {
@ -38,7 +38,7 @@ const Game =
{ {
for(let i=0; i<inGoals.length; i++) for(let i=0; i<inGoals.length; i++)
{ {
if(!clone.Goals[i].Done) if(!inGoals[i].Done)
{ {
return false; return false;
} }
@ -50,6 +50,8 @@ const Game =
{ {
case "click": case "click":
{ {
if(clone.Done){break;}
/**@type StateGoal|undefined*/ /**@type StateGoal|undefined*/
const goal = clone.Goals[inAction.Payload]; const goal = clone.Goals[inAction.Payload];
if(goal) if(goal)
@ -64,7 +66,7 @@ const Game =
clone.Round++; clone.Round++;
clone.Goals = []; clone.Goals = [];
clone.Done = false; clone.Done = false;
for(let i=0; i<1+Math.random()*10; i++) for(let i=0; i<clone.Round; i++)
{ {
/**@type StateGoal*/ const goal = {Done:false, Pos:[ /**@type StateGoal*/ const goal = {Done:false, Pos:[
(Math.random()-0.5)*5, (Math.random()-0.5)*5,
@ -83,7 +85,7 @@ const Game =
} }
}; };
/** @type {(props:{goal:StateGoal, handler:()=>void})=>JSX.Element}*/ /** @type {(props:{goal:StateGoal, handler:()=>void})=>JSX.Element} */
function Model(props) function Model(props)
{ {
const { nodes, animations } = useGLTF("/bounce.gltf"); const { nodes, animations } = useGLTF("/bounce.gltf");
@ -102,13 +104,14 @@ function Model(props)
castShadow castShadow
receiveShadow receiveShadow
geometry=${nodes.Cube.geometry} geometry=${nodes.Cube.geometry}
material=${nodes.Cube.material}
onClick=${e=> onClick=${e=>
{ {
e.stopPropagation(); e.stopPropagation();
props.handler(); props.handler();
} }
} /> }>
<meshStandardMaterial color=${props.goal.Done ? "yellow" : "blue"}/>
</mesh>
</group>` </group>`
} }