A hackable template for creating small and fast browser games.
1import {instantiate} from "../../lib/game.js";
2import {pointer_clicked} from "../../lib/input.js";
3import {mat4_get_translation} from "../../lib/mat4.js";
4import {path_find} from "../../lib/pathfind.js";
5import {GL_ARRAY_BUFFER} from "../../lib/webgl.js";
6import {Entity} from "../../lib/world.js";
7import {disable} from "../components/com_disable.js";
8import {RenderVertices, render_vertices} from "../components/com_render.js";
9import {transform} from "../components/com_transform.js";
10import {Game} from "../game.js";
11import {Has} from "../world.js";
12import {Picked} from "./sys_pick.js";
13
14const QUERY = Has.ControlPlayer | Has.NavAgent;
15
16let line: Entity;
17
18export function sys_control_player(game: Game, delta: number) {
19 if (!line) {
20 line = instantiate(game, [
21 transform([0, 1, 0]),
22 render_vertices(game.MaterialColoredLine, 512, [1, 1, 0, 1]),
23 disable(Has.Render),
24 ]);
25 }
26
27 if (game.Picked) {
28 for (let i = 0; i < game.World.Signature.length; i++) {
29 if ((game.World.Signature[i] & QUERY) == QUERY) {
30 update(game, i, game.Picked);
31 }
32 }
33 }
34}
35
36function update(game: Game, entity: Entity, pick: Picked) {
37 let agent = game.World.NavAgent[entity];
38 let node = pick.TriIndex;
39 let goal;
40
41 if (node !== undefined && agent.NavMesh.Graph[node]) {
42 // The cursor is over a pickable mesh and over a navigable triangle?
43 goal = node;
44 if (pointer_clicked(game, 0, 0)) {
45 agent.Goal = {Node: goal, Position: pick.Point};
46 }
47 }
48
49 // The path line for debugging.
50 if (goal !== undefined) {
51 let path = path_find(agent.NavMesh, goal, agent.Origin);
52 if (path) {
53 let transform = game.World.Transform[entity];
54 let world_pos = mat4_get_translation([0, 0, 0], transform.World);
55
56 // Remove the origin and the goal from the path.
57 path = path.slice(1, path.length - 1);
58 // Centroids are in the world space.
59 let waypoints = path.map((x) => agent.NavMesh.Centroids[x]);
60 // Add the entity's current position and the exact goal destination.
61 waypoints = [world_pos, ...waypoints, pick.Point];
62
63 game.World.Signature[line] |= Has.Render;
64 let render = game.World.Render[line] as RenderVertices;
65 render.IndexCount = waypoints.length;
66 game.Gl.bindBuffer(GL_ARRAY_BUFFER, render.VertexBuffer);
67 game.Gl.bufferSubData(GL_ARRAY_BUFFER, 0, Float32Array.from(waypoints.flat()));
68 }
69 }
70}