Skip to content

Commit

Permalink
Merge pull request #101 from bananu7/vertical-map-features
Browse files Browse the repository at this point in the history
Vertical map features
  • Loading branch information
bananu7 committed Jul 2, 2024
2 parents a4789c3 + 2146b81 commit 1ee7f99
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 70 deletions.
80 changes: 14 additions & 66 deletions packages/client/src/gfx/Map3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import * as THREE from 'three';
import { Board, Unit, GameMap, UnitId, Position } from '@bananu7-rts/server/src/types'

import { SelectionBox } from './SelectionBox'
import { mapColor, mapHeight, explode } from './map_display'
import { MapBorder } from './MapBorder'

type Click = (originalEvent: ThreeEvent<MouseEvent>, p: Position, button: number, shift: boolean) => void;
type RawClick = (e: ThreeEvent<MouseEvent>) => void;
Expand All @@ -24,58 +26,6 @@ type Map3DProps = {
pointerMove: (p: {x: number, y: number}) => void;
}

function tileTypeToColor(tileType: number, vec3Color: THREE.Color) {
const isPassable = tileType === 0;

switch (tileType) {
case 0: {
const color = 0x11aa11;
vec3Color.set(color);
const f = 0.06;
vec3Color.r += (Math.random() - 0.5) * f;
vec3Color.g += (Math.random() - 0.5) * f;
vec3Color.b += (Math.random() - 0.5) * f;
break;
}

case 2: {
const color = 0x3377cc;
vec3Color.set(color);
const f = 0.06;
vec3Color.r += (Math.random() - 0.5) * f;
vec3Color.g += (Math.random() - 0.5) * f;
vec3Color.b += (Math.random() - 0.5) * f;
break;
}

case 1:
default: {
const color = 0x888888;
vec3Color.set(color);
const d = (Math.random() - 0.5) * 0.1;
vec3Color.r += d;
vec3Color.g += d;
vec3Color.b += d;
}
}
}

function tileTypeToHeight(tileType: number): number {
const correction = 0.01;
switch (tileType) {
case 0:
return 0 - correction;

case 2:
return -0.5 - Math.random() * 0.7 - correction

case 1:
default:
return 0.8 + Math.random() * 0.7 - correction;
}
}


export function Map3D(props: Map3DProps) {
// movement
const rawClick = (e: ThreeEvent<MouseEvent>) => {
Expand Down Expand Up @@ -109,9 +59,6 @@ export function Map3D(props: Map3DProps) {
const w = props.map.w;
const h = props.map.h;

const xSize = 1;
const ySize = 1;

const ref = useRef<THREE.InstancedMesh>(null);
useLayoutEffect(() => {
if (!ref.current)
Expand All @@ -122,15 +69,13 @@ export function Map3D(props: Map3DProps) {

for (let y = 0; y < h; y++){
for (let x = 0; x < w; x++) {
const ix = y*props.map.w+x;

const tileType = props.map.tiles[ix];
const color = tileTypeToColor(tileType, vec3Color);
const height = tileTypeToHeight(tileType);
const color = mapColor(props.map, x, y, vec3Color);
const height = mapHeight(props.map, x, y);

// TODO - make sure that everything matches with that corrective offset
mat4Pos.makeTranslation(x * xSize + 0.5, height, y * ySize + 0.5); // TODO -1 to move them down because of their height
mat4Pos.makeTranslation(x + 0.5, height-9, y + 0.5); // TODO -1 to move them down because of their height

const ix = explode(props.map, x, y);
ref.current.setMatrixAt(ix, mat4Pos);
ref.current.setColorAt(ix, vec3Color);
}
Expand All @@ -150,9 +95,9 @@ export function Map3D(props: Map3DProps) {
onPointerDown={pointerDown}
onPointerUp={pointerUp}
onPointerMove={pointerMove}
position={[0.5*w, 0, ySize*0.5*h]}
position={[0.5*w, 0, 0.5*h]}
>
<boxGeometry args={[xSize*w*2, 1, ySize*h*2]} />
<boxGeometry args={[w*2, 1, h*2]} />
<meshBasicMaterial opacity={0} transparent={true} />
</mesh>

Expand All @@ -163,11 +108,14 @@ export function Map3D(props: Map3DProps) {
ref={ref}
args={[undefined, undefined, w*h]}
receiveShadow
castShadow
>
{/*<planeGeometry args={[xSize, ySize]} />*/}
<boxGeometry args={[xSize, 2, ySize]} />
{/*<planeGeometry args={[1, 1]} />*/}
<boxGeometry args={[1, 20, 1]} />
<meshStandardMaterial />
</instancedMesh>

<MapBorder w={w} h={h} />
</group>
);
}
}
137 changes: 137 additions & 0 deletions packages/client/src/gfx/MapBorder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { useRef, useLayoutEffect } from 'react'
import * as THREE from 'three';

import { tileTypeToColor, tileTypeToHeight } from './map_display'

export type MapBorderProps = {
w: number,
h: number,
}

export function MapBorder(props: MapBorderProps) {
const w = props.w;
const h = props.h;

const borderSize = 30;

/*
XAAAAY
CMMMMD
CMMMMD
CMMMMD
CMMMMD
ZBBBBW
*/

const borderTilesCount =
borderSize * w * 2 + // horizontal
borderSize * h * 2 + // vertical
borderSize * borderSize * 4; // corners

const ref = useRef<THREE.InstancedMesh>(null);
useLayoutEffect(() => {
if (!ref.current)
return;

const mat4Pos = new THREE.Matrix4();
const vec3Color = new THREE.Color();
const tileType = 0;

const createRectangle = (
off: number,
x0: number,
y0: number,
x1: number,
y1: number,
f: (x: number, y:number) => number
) => {
if (!ref.current)
return 0;

for (let y = 0; y < y1-y0; y++){
for (let x = 0; x < x1-x0; x++) {
const ix = y*(x1-x0)+x + off;
const color = tileTypeToColor(tileType, vec3Color);

// outline darker
vec3Color.g *= Math.abs(f(x,y));

const height = tileTypeToHeight(tileType);

mat4Pos.makeTranslation(x + 0.5 + x0, height-9, y + 0.5 + y0);

ref.current.setMatrixAt(ix, mat4Pos);
ref.current.setColorAt(ix, vec3Color);
}
}

return (y1-y0) * (x1-x0);
};

// TODO this code is pretty unreadable, but at least it's only called once

let off = 0;
//top
off += createRectangle(off, 0, -borderSize, w, 0, (x,y) => y/borderSize);
//bottom
off += createRectangle(off, 0, h, w, h+borderSize, (x,y) => (borderSize-y)/borderSize);
// left
off += createRectangle(off, -borderSize, 0, 0, h, (x,y) => x/borderSize);
//right
off += createRectangle(off, w, 0, w+borderSize, h, (x,y) => (borderSize-x)/borderSize);

// top-left
off += createRectangle(off, -borderSize, -borderSize, 0, 0,
(x,y) => {
const xi = borderSize-x;
const yi = borderSize-y;
return Math.max(1 - Math.sqrt(xi*xi+yi*yi)/Math.sqrt(borderSize*borderSize), 0);
}
);

// top-right
off += createRectangle(off, w, -borderSize, w+borderSize, 0,
(x,y) => {
const xi = x;
const yi = borderSize-y;
return Math.max(1 - Math.sqrt(xi*xi+yi*yi)/Math.sqrt(borderSize*borderSize), 0);
}
);

// bottom-left
off += createRectangle(off, -borderSize, h, 0, h+borderSize,
(x,y) => {
const xi = borderSize-x;
const yi = y;
return Math.max(1 - Math.sqrt(xi*xi+yi*yi)/Math.sqrt(borderSize*borderSize), 0);
}
);

// bottom-right
off += createRectangle(off, w, h, w+borderSize, h+borderSize,
(x,y) => {
const xi = x;
const yi = y;
return Math.max(1 - Math.sqrt(xi*xi+yi*yi)/Math.sqrt(borderSize*borderSize), 0);
}
);


ref.current.instanceMatrix.needsUpdate = true;
if (ref.current.instanceColor) ref.current.instanceColor.needsUpdate = true;
}, [props.w, props.h])

return (
<instancedMesh
name="Map border mesh"
ref={ref}
args={[undefined, undefined, w*h]}
receiveShadow
>
<boxGeometry args={[1, 20, 1]} />
<meshStandardMaterial />
</instancedMesh>
);
}
4 changes: 2 additions & 2 deletions packages/client/src/gfx/MapLight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ export function MapLight(props: MapLightProps) {
shadow-camera-left={-props.target.z}
shadow-camera-right={props.target.z}

shadow-bias={-0.002}
shadow-bias={-0.00052}
/>
</group>
)
)
}


Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/gfx/Unit3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function Unit3D(props: Unit3DProps) {
})();

const debugPath = props.unit.debug?.pathToNext?.map((a: any) => {
return new THREE.Vector3(a.x, 1, a.y);
return new THREE.Vector3(a.x, 1.2, a.y);
});

const action = props.unit.state.action;
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/gfx/View3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function View3D(props: Props) {
onPointerMissed={ props.onPointerMissed }
dpr={1}
>
<color attach="background" args={[0x11aa11]} />
<color attach="background" args={[0x111111]} />
<CameraControls minPan={minPan} maxPan={maxPan} startTarget={startTarget} />
<ambientLight args={[0xffffff, 2]} />
<MapLight target={middleOfTheMap}/>
Expand Down
Loading

0 comments on commit 1ee7f99

Please sign in to comment.