Skip to content

Commit

Permalink
place: terrain blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
chase-moskal committed Jun 20, 2024
1 parent 6e8c9e2 commit 133faeb
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 9 deletions.
4 changes: 2 additions & 2 deletions s/dom/elements/app.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

import {nexus} from "../nexus.js"
import styles from "./app.css.js"
import {MapEditor} from "../views/map-editor.js"
import {MapEditorView} from "../views/map-editor.js"

export const TinyforgeApp = nexus.shadow_component(use => {
use.styles(styles)

return MapEditor([])
return MapEditorView([])
})

7 changes: 5 additions & 2 deletions s/dom/views/map-editor.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {css} from "@benev/slate"
export default css`
.easel {
display: block;
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
height: 100%;
Expand All @@ -14,11 +16,12 @@ canvas {
width: 100%;
height: 100%;
background: #222;
outline: none;
}
.sidebar {
position: absolute;
width: 3em;
width: 10%;
height: 100%;
background: #333a;
Expand Down
44 changes: 40 additions & 4 deletions s/dom/views/map-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,51 @@ import {html} from "@benev/slate"

import {nexus} from "../nexus.js"
import styles from "./map-editor.css.js"
import {Editor, editing} from "../../game/editor.js"
import {Bestorage, EffectsPanelData, Stage, op_effect} from "@benev/toolbox"

export const MapEditor = nexus.shadow_view(use => () => {
export const MapEditorView = nexus.shadow_view(use => () => {
use.styles(styles)
use.name("map-editor")

const goods = use.op<{
stage: Stage,
editor: Editor,
}>()

use.once(async() => {
await goods.load(async() => {
const stage = await Stage.create({
background: Stage.backgrounds.black(),
allow_webgpu: false,
webgl_options: {
alpha: false,
desynchronized: true,
preserveDrawingBuffer: false,
powerPreference: "high-performance",
},
webgpu_options: {
antialias: true,
audioEngine: true,
powerPreference: "high-performance",
},
bestorage: new Bestorage<EffectsPanelData>({
effects: {},
resolution: 100,
}),
})
const editor = await editing(stage)
return {stage, editor}
})
})

return html`
<div class="easel">
<canvas></canvas>
<div class="sidebar alpha"></div>
<div class="sidebar bravo"></div>
${op_effect.binary(goods.value, ({stage}) => html`
${stage.porthole.canvas}
<div class="sidebar alpha"></div>
<div class="sidebar bravo"></div>
`)}
</div>
`
})
Expand Down
99 changes: 99 additions & 0 deletions s/game/editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

import {Level} from "./level.js"
import {Stage, Vec2, load_glb, scalar} from "@benev/toolbox"
import {ArcRotateCamera, DirectionalLight, HemisphericLight, TransformNode, Vector3} from "@babylonjs/core"

export type Editor = Awaited<ReturnType<typeof editing>>

const tsize = {
width: 6,
height: 4,
}

export async function editing(stage: Stage) {
const {scene} = stage
const level = new Level([12, 8])
const camera = make_camera(stage)

const assets = await load_glb(scene, "/assets/props.glb")

const sun = new DirectionalLight("sun", new Vector3(.234, -1, .123), scene)
sun.intensity = 2

const hemi = new HemisphericLight("hemi", new Vector3(.213, -1, .345), scene)
hemi.intensity = .2

const assetTerrainBlock = assets.transformNodes.find(n => n.name.includes("terrain-block"))!
const originals = new TransformNode("originals", scene)
const terrainBlock = assetTerrainBlock.clone("terrain-block-ready", originals)!

const worldspace = ([tileX, tileY]: Vec2): Vec2 => {
const [extentX, extentY] = level.extent
const midX = extentX / 2
const midY = extentY / 2
const {width} = tsize
const halfwidth = width / 2
const x = ((tileX - midX) * tsize.width) + halfwidth
const y = ((tileY - midY) * tsize.width) + halfwidth
return [x, y]
}

level.setTile([0, 0], {kind: "block", elevation: 1})
level.setTile([1, 1], {kind: "block", elevation: 1})
level.setTile([2, 2], {kind: "block", elevation: 1})

const instances = new TransformNode("instances", scene)

for (const [tile, [x, y]] of level.loop()) {
switch (tile.kind) {
case "block": {
const [worldX, worldZ] = worldspace([x, y])
const worldY = tile.elevation * tsize.height
const n = terrainBlock.instantiateHierarchy(instances)!
n.position = new Vector3(worldX, worldY, worldZ)
console.log([worldX, worldY, worldZ])
break
}
case "ramp": {
break
}
case "corner": {
break
}
}
}

for (const n of assets.transformNodes)
console.log(n.name)

stage.gameloop.start()

return {
level,
camera,
dispose() {
stage.gameloop.stop()
stage.engine.dispose()
stage.scene.dispose()
},
}
}

/////////////////////////////

function make_camera(stage: Stage) {
const alpha = scalar.radians.from.degrees(90)
const beta = scalar.radians.from.degrees(10)
const radius = 70
const camera = new ArcRotateCamera(
"camera",
alpha,
beta,
radius,
new Vector3(0, 0, tsize.width * 0.5),
stage.scene,
)
stage.rendering.setCamera(camera)
return camera
}

101 changes: 101 additions & 0 deletions s/game/level.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

import {Vec2, loop2d} from "@benev/toolbox"

export type Elevation = (
| 0 // water
| 1 // sand
| 2 // dirt
| 4 // grass
| 5 // rock
)

export type Kind = "block" | "corner" | "ramp"

export enum Cardinal {
North,
East,
South,
West,
}

export enum Ordinal {
NorthWest,
NorthEast,
SouthEast,
SouthWest,
}

export type Block = {
kind: "block"
elevation: Elevation
}

export type Corner = {
kind: "corner"
elevation: Elevation
ordinal: Ordinal
}

export type Ramp = {
kind: "ramp"
elevation: Elevation
cardinal: Cardinal
}

export type Tile = Block | Corner | Ramp

export function asTile<T extends Tile>(tile: T) {
return tile
}

export class Level {
readonly extent: Vec2
#tiles: Tile[]

constructor(extent: Vec2) {
this.extent = extent
this.#tiles = [...loop2d(extent)].map(
() => asTile({kind: "block", elevation: 0})
)
}

tileIndex([x, y]: Vec2) {
const [extentX] = this.extent
return (y * extentX) + x
}

getTile(vec: Vec2) {
return this.#tiles[this.tileIndex(vec)]
}

setTile(vec: Vec2, tile: Tile) {
this.#tiles[this.tileIndex(vec)] = tile
}

overwriteTiles(tiles: Tile[]) {
this.#tiles = tiles
}

*loop() {
for (const vec of loop2d(this.extent)) {
const tile = this.getTile(vec)
yield [tile, vec] as [Tile, Vec2]
}
}

save() {
return JSON.stringify({
version: 0,
extent: this.extent,
tiles: this.#tiles,
})
}

static load(json: string) {
const {extent, tiles} = JSON.parse(json) as any
const level = new this(extent)
level.overwriteTiles(tiles)
return new this(extent)
}
}

5 changes: 4 additions & 1 deletion s/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@

html, body {
font-size: 16px;
height: 100%;
background: #111;
color: #fffc;
height: 100%;
}

tinyforge-app {
position: absolute;
inset: 0;
margin: auto;
max-width: 100%;
max-height: 100%;
aspect-ratio: 16 / 9;
}

0 comments on commit 133faeb

Please sign in to comment.