Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vertical map features #101

Merged
merged 12 commits into from
Jul 2, 2024
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
Loading