some changes
This commit is contained in:
parent
dd9c35d3bd
commit
51a2396d9a
@ -96,7 +96,7 @@ export class Game {
|
||||
8,
|
||||
0.5,
|
||||
8,
|
||||
this.world.getInterpolatedHeight.bind(this.world),
|
||||
this.world.getHeight.bind(this.world),
|
||||
);
|
||||
|
||||
const flowerfield = Grass.getInstance().createGrassPatch(
|
||||
@ -104,7 +104,7 @@ export class Game {
|
||||
8,
|
||||
4,
|
||||
3,
|
||||
this.world.getInterpolatedHeight.bind(this.world),
|
||||
this.world.getHeight.bind(this.world),
|
||||
);
|
||||
|
||||
const flowerfield2 = Grass.getInstance().createGrassPatch(
|
||||
@ -112,7 +112,7 @@ export class Game {
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
this.world.getInterpolatedHeight.bind(this.world),
|
||||
this.world.getHeight.bind(this.world),
|
||||
);
|
||||
|
||||
const grass = Grass.getInstance().createInstance(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { CanvasTexture, LinearFilter, ClampToEdgeWrapping } from 'three';
|
||||
import { rgbToHex, to1D } from '../../common/convert';
|
||||
|
||||
/**
|
||||
* Draws a rounded rectangle using the current state of the canvas.
|
||||
@ -172,4 +173,49 @@ export class CanvasUtils {
|
||||
|
||||
return { texture, width, height };
|
||||
}
|
||||
|
||||
public readPixelDataRGB(image: HTMLImageElement): number[] {
|
||||
const array = new Array(image.width * image.height);
|
||||
const ctx = document.createElement('canvas').getContext('2d');
|
||||
ctx.canvas.width = image.width;
|
||||
ctx.canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
|
||||
// pixel data
|
||||
const data = ctx.getImageData(0, 0, image.width, image.height);
|
||||
for (let x = 0; x < image.width; x++) {
|
||||
for (let y = 0; y < image.height; y++) {
|
||||
const index = to1D(x, y, image.width);
|
||||
array[index] = rgbToHex(
|
||||
data.data[index * 4],
|
||||
data.data[index * 4 + 1],
|
||||
data.data[index * 4 + 2],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public readPixelDataRScaled(
|
||||
image: HTMLImageElement,
|
||||
scale: number,
|
||||
): number[] {
|
||||
const array = new Array(image.width * image.height);
|
||||
const ctx = document.createElement('canvas').getContext('2d');
|
||||
ctx.canvas.width = image.width;
|
||||
ctx.canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
|
||||
// pixel data
|
||||
const data = ctx.getImageData(0, 0, image.width, image.height);
|
||||
for (let x = 0; x < image.width; x++) {
|
||||
for (let y = 0; y < image.height; y++) {
|
||||
const index = to1D(x, y, image.width);
|
||||
array[index] = (data.data[index * 4] * scale) / 255;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ const nameTagBuilder = new CanvasUtils({
|
||||
export class PonyEntity {
|
||||
public velocity = new Vector3(0, 0, 0);
|
||||
public angularVelocity = new Vector3(0, 0, 0);
|
||||
public onFloor = true;
|
||||
public remote = false;
|
||||
public gravity = -50;
|
||||
public jumpPower = 16;
|
||||
public mixer!: AnimationMixer;
|
||||
public container!: Object3D;
|
||||
public model!: Object3D;
|
||||
@ -58,6 +62,14 @@ export class PonyEntity {
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
this.mixer.update(dt);
|
||||
|
||||
if (this.remote) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.velocity.y += this.gravity * dt;
|
||||
|
||||
this.container.position.add(this.velocity.clone().multiplyScalar(dt));
|
||||
this.container.rotation.setFromVector3(
|
||||
new Vector3(
|
||||
@ -69,13 +81,18 @@ export class PonyEntity {
|
||||
|
||||
// Put pony on the terrain
|
||||
const terrainFloorHeight =
|
||||
this.heightSource?.getInterpolatedHeight(
|
||||
this.heightSource?.getHeight(
|
||||
this.container.position.x,
|
||||
this.container.position.z,
|
||||
) || 0;
|
||||
this.container.position.y = terrainFloorHeight;
|
||||
|
||||
this.mixer.update(dt);
|
||||
if (this.container.position.y <= terrainFloorHeight) {
|
||||
this.onFloor = true;
|
||||
this.velocity.y = 0;
|
||||
this.container.position.y = terrainFloorHeight;
|
||||
} else {
|
||||
this.onFloor = false;
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@ -106,6 +123,10 @@ export class PonyEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public jump() {
|
||||
this.velocity.y = 16;
|
||||
}
|
||||
|
||||
public setColor(color: number | string) {
|
||||
this.material.color = new Color(color);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ export class PlayerEntity extends PonyEntity {
|
||||
private _targetFrame: any = null;
|
||||
private _lastFrame: any = null;
|
||||
private _chats: ChatBubble[] = [];
|
||||
public remote = true;
|
||||
|
||||
private _p1 = new Vector3();
|
||||
private _p2 = new Vector3();
|
||||
|
@ -97,14 +97,17 @@ export class Player extends PonyEntity {
|
||||
}
|
||||
|
||||
if (vector.y !== 0) {
|
||||
this.velocity.copy(this._lookVector.clone().multiplyScalar(vector.y * 5));
|
||||
const directional = this._lookVector
|
||||
.clone()
|
||||
.multiplyScalar(vector.y * 2.5);
|
||||
this.velocity.set(directional.x, this.velocity.y, directional.z);
|
||||
this.changes.velocity = this.velocity.toArray();
|
||||
|
||||
this._wasMoving = true;
|
||||
this.setWalkAnimationState(1);
|
||||
} else if (this._wasMoving && !wasExternalForce) {
|
||||
this._wasMoving = false;
|
||||
this.velocity.set(0, 0, 0);
|
||||
this.velocity.set(0, this.velocity.y, 0);
|
||||
this.changes.velocity = this.velocity.toArray();
|
||||
this.changes.position = this.container.position.toArray();
|
||||
this.setWalkAnimationState(0);
|
||||
@ -133,6 +136,10 @@ export class Player extends PonyEntity {
|
||||
this._direction.x = 0;
|
||||
}
|
||||
|
||||
if (this.keydownMap[' '] && !this._prevKeydownMap[' '] && this.onFloor) {
|
||||
this.jump();
|
||||
}
|
||||
|
||||
this.moveCharacter(dt);
|
||||
super.update(dt);
|
||||
|
||||
|
@ -17,10 +17,10 @@ export class ClientWorld extends WorldManager {
|
||||
private _shader = new ClientWorldChunkShader(this._worldTextures);
|
||||
|
||||
getNormalVector(x: number, y: number): Vector3 {
|
||||
const heightL = this.getHeight(x - 1, y);
|
||||
const heightR = this.getHeight(x + 1, y);
|
||||
const heightD = this.getHeight(x, y - 1);
|
||||
const heightU = this.getHeight(x, y + 1);
|
||||
const heightL = this.getPointHeight(x - 1, y);
|
||||
const heightR = this.getPointHeight(x + 1, y);
|
||||
const heightD = this.getPointHeight(x, y - 1);
|
||||
const heightU = this.getPointHeight(x, y + 1);
|
||||
const normalized = new Vector3(heightL - heightR, 2, heightD - heightU);
|
||||
normalized.normalize();
|
||||
return normalized;
|
||||
@ -75,7 +75,7 @@ export class ClientWorld extends WorldManager {
|
||||
material,
|
||||
);
|
||||
|
||||
root.getHeight = this.getInterpolatedHeight.bind(this);
|
||||
root.getHeight = this.getHeight.bind(this);
|
||||
root.getNormal = this.getNormalVector.bind(this);
|
||||
root.initialize();
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { ImageLoader } from 'three';
|
||||
import { to1D } from '../../../common/convert';
|
||||
import { WorldLoader } from '../../../common/world/WorldLoader';
|
||||
import { CanvasUtils } from '../canvas-utils';
|
||||
|
||||
const loader = new ImageLoader();
|
||||
const worldPath = '/assets/terrain/region/';
|
||||
const canvasUtil = new CanvasUtils();
|
||||
const worldPath = '/assets/terrain/region';
|
||||
|
||||
export class ClientWorldLoader implements WorldLoader {
|
||||
async loadHeightMap(
|
||||
@ -14,7 +15,7 @@ export class ClientWorldLoader implements WorldLoader {
|
||||
return new Promise((resolve, reject) => {
|
||||
loader.load(
|
||||
`${worldPath}/height-${chunkX}-${chunkY}.png`,
|
||||
(data) => resolve(ClientWorldLoader.heightFromImage(data, scale)),
|
||||
(data) => resolve(canvasUtil.readPixelDataRScaled(data, scale)),
|
||||
undefined,
|
||||
(err) => {
|
||||
reject(err);
|
||||
@ -22,26 +23,4 @@ export class ClientWorldLoader implements WorldLoader {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public static heightFromImage(
|
||||
image: HTMLImageElement,
|
||||
scale: number,
|
||||
): number[] {
|
||||
const array = new Array(image.width * image.height);
|
||||
const ctx = document.createElement('canvas').getContext('2d');
|
||||
ctx.canvas.width = image.width;
|
||||
ctx.canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
|
||||
// pixel data
|
||||
const data = ctx.getImageData(0, 0, image.width, image.height);
|
||||
for (let x = 0; x < image.width; x++) {
|
||||
for (let y = 0; y < image.height; y++) {
|
||||
const index = to1D(x, y, image.width);
|
||||
array[index] = (data.data[index * 4] * scale) / 255;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ export class QuadtreeNode {
|
||||
);
|
||||
|
||||
if (this._leaf) {
|
||||
if (abs.distanceTo(camera) < size && this._canSubdivide()) {
|
||||
if (this._canSubdivide() && abs.distanceTo(camera) < size) {
|
||||
this._subdivide();
|
||||
this.root.actionsLeft -= 1;
|
||||
return;
|
||||
|
@ -6,6 +6,10 @@ export function convertHex(hex: number): { r: number; g: number; b: number } {
|
||||
};
|
||||
}
|
||||
|
||||
export function rgbToHex(r: number, g: number, b: number): number {
|
||||
return (1 << 24) + (r << 16) + (g << 8) + b;
|
||||
}
|
||||
|
||||
export function hexToString(hex: number): string {
|
||||
const { r, g, b } = convertHex(hex);
|
||||
return `#${r.toString(16).padStart(2, '0')}${g
|
||||
|
@ -46,7 +46,7 @@ export class WorldManager {
|
||||
}
|
||||
}
|
||||
|
||||
getHeight(x: number, y: number): number {
|
||||
getPointHeight(x: number, y: number): number {
|
||||
const chunkX = Math.floor(x / this.worldChunkSize);
|
||||
const chunkY = Math.floor(y / this.worldChunkSize);
|
||||
if (
|
||||
@ -64,7 +64,7 @@ export class WorldManager {
|
||||
);
|
||||
}
|
||||
|
||||
getInterpolatedHeight(x: number, y: number): number {
|
||||
getHeight(x: number, y: number): number {
|
||||
const chunkX = Math.floor(x / this.worldChunkSize);
|
||||
const chunkY = Math.floor(y / this.worldChunkSize);
|
||||
if (
|
||||
|
Loading…
Reference in New Issue
Block a user