fixed bugs

This commit is contained in:
Vasyl Kazakov
2026-06-03 11:49:30 +03:00
parent e14b97b5e7
commit adf4e4b9bf
15 changed files with 523 additions and 149 deletions
+3 -3
View File
@@ -88,7 +88,7 @@ export const globalSettings: ConfigUiParamsCategories[] = [
values: [ values: [
30, 30,
150, 150,
30 33
] ]
}, },
{ {
@@ -106,7 +106,7 @@ export const globalSettings: ConfigUiParamsCategories[] = [
[ [
0, 0,
15, 15,
9 8
], ],
[ [
-10, -10,
@@ -125,7 +125,7 @@ export const globalSettings: ConfigUiParamsCategories[] = [
[ [
-360, -360,
360, 360,
5 7
], ],
[ [
-360, -360,
+2
View File
@@ -2,6 +2,7 @@ import { EasyEvent, JoystickC, UpdateController } from "@24tools/playable_templa
import { Vector3 } from "three"; import { Vector3 } from "three";
import { PhysicsTriggerC } from "./PhysicsTriggerC"; import { PhysicsTriggerC } from "./PhysicsTriggerC";
import { PropC, PropRegistry } from "./PropC"; import { PropC, PropRegistry } from "./PropC";
import { PropHpUIC } from "./PropHpUIC";
import { Player } from "../Presets/Player"; import { Player } from "../Presets/Player";
export class GatherC { export class GatherC {
@@ -119,6 +120,7 @@ export class GatherC {
if (Player.isMoving() || Player.isCombatBusy()) return; if (Player.isMoving() || Player.isCombatBusy()) return;
const targetPosition = this.getTargetPosition(props); const targetPosition = this.getTargetPosition(props);
PropHpUIC.showFor(props);
Player.startAutoAttack( Player.startAutoAttack(
() => this.onAttackStrike(), () => this.onAttackStrike(),
() => {}, () => {},
+5
View File
@@ -57,7 +57,12 @@ export class InteractiveZoneC {
if ("color" in cloned) { if ("color" in cloned) {
this.baseColors.set(cloned, (cloned.color as Color).clone()); this.baseColors.set(cloned, (cloned.color as Color).clone());
} }
cloned.depthWrite = true;
cloned.polygonOffset = true;
cloned.polygonOffsetFactor = 2;
cloned.polygonOffsetUnits = 2;
mesh.material = cloned; mesh.material = cloned;
mesh.renderOrder = 0;
}); });
this.refreshFillVisual(); this.refreshFillVisual();
+6
View File
@@ -22,12 +22,18 @@ export class Map {
mapObject.position.set(0, 0, 0); mapObject.position.set(0, 0, 0);
ThreeC.setShadowsStateForChildren(mapObject, true, true); ThreeC.setShadowsStateForChildren(mapObject, true, true);
ThreeC.addToScene(mapObject); ThreeC.addToScene(mapObject);
this.hideReferenceHpUi(mapObject);
PhysicsTriggerC.init(); PhysicsTriggerC.init();
this.buildPhysics(mapObject); this.buildPhysics(mapObject);
InteractiveZoneC.init(mapObject); InteractiveZoneC.init(mapObject);
} }
private static hideReferenceHpUi(mapObject: Object3D) {
const ui = mapObject.getObjectByName("UI");
if (ui) ui.visible = false;
}
private static buildPhysics(mapObject: Object3D) { private static buildPhysics(mapObject: Object3D) {
for (const layerName of MAP_PHYSICS_LAYERS) { for (const layerName of MAP_PHYSICS_LAYERS) {
const layer = mapObject.getObjectByName(layerName); const layer = mapObject.getObjectByName(layerName);
+243 -81
View File
@@ -1,42 +1,108 @@
import { Box3, Mesh, Object3D, Vector3 } from "three"; import {
import { CameraC } from "../CameraC"; Box3,
Color,
DoubleSide,
Material,
Matrix4,
Mesh,
MeshBasicMaterial,
MeshStandardMaterial,
Object3D,
Quaternion,
Vector3,
} from "three";
import { ResourcesC } from "@24tools/playable_template";
import { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
import { ThreeC } from "../ThreeC";
import { ResourcesType } from "../Presets/Enums/ResourcesType";
import { PropC } from "./PropC"; import { PropC } from "./PropC";
const BAR_Y_OFFSET = 0.8; const HP_BAR_MESH = "hpBar";
const BAR_X_OFFSET = -0.3; const NODE_UI = "UI";
const NODE_BACKGROUND = "UI_Background";
const NODE_FOREGROUND = "UI_Foreground";
const NODE_MIDDLEGROUND = "UI_Middleground";
const BAR_Y_OFFSET = 0.55;
const BAR_X_OFFSET = -0.2;
const CATCHUP_SPEED = 2.5; const CATCHUP_SPEED = 2.5;
const BAR_WORLD_SCALE = 1;
/** Transparent pass + renderOrder above all map decals. */
export const OVERLAY_RENDER_ORDER = 10000;
const RENDER_ORDER_BACKGROUND = OVERLAY_RENDER_ORDER;
const RENDER_ORDER_MIDDLEGROUND = OVERLAY_RENDER_ORDER + 1;
const RENDER_ORDER_FOREGROUND = OVERLAY_RENDER_ORDER + 2;
type FillPart = {
node: Object3D;
baseScaleX: number;
basePosX: number;
/** Local mesh min.x (negative); keeps left edge fixed when scaling. */
anchorMinX: number;
};
export class PropHpBar { export class PropHpBar {
static readonly OVERLAY_RENDER_ORDER = OVERLAY_RENDER_ORDER;
private static readonly identityMatrix = new Matrix4();
private static readonly tempMatrix = new Matrix4();
private static readonly tempPosition = new Vector3();
private static readonly tempQuaternion = new Quaternion();
private static readonly tempScale = new Vector3();
private static readonly worldAnchor = new Vector3();
private readonly prop: PropC; private readonly prop: PropC;
private readonly root: HTMLElement; private readonly root: Object3D;
private readonly currentEl: HTMLElement; private readonly foreground: FillPart | null;
private readonly delayedEl: HTMLElement; private readonly middleground: FillPart | null;
private readonly anchor = new Vector3();
private readonly bounds = new Box3(); private readonly bounds = new Box3();
private displayedHealth: number; private displayedHealth: number;
private visible = false; private visible = false;
constructor(prop: PropC, parent: HTMLElement) { static getPrefab(): Object3D | null {
const fromScene = ThreeC.getObject(HP_BAR_MESH);
if (fromScene) return fromScene;
const gltf = ResourcesC.getResource<GLTF>(ResourcesType.Mesh, HP_BAR_MESH);
return gltf?.scene ?? null;
}
constructor(prop: PropC, parent: Object3D) {
const template = PropHpBar.getPrefab();
if (!template) {
throw new Error(`HP bar mesh resource not found: ${HP_BAR_MESH}`);
}
const sourceUi = template.getObjectByName(NODE_UI);
if (!sourceUi) {
throw new Error(`HP bar node not found: ${NODE_UI}`);
}
this.prop = prop; this.prop = prop;
this.displayedHealth = prop.health; this.displayedHealth = prop.health;
this.root = document.createElement("div"); this.root = new Object3D();
this.root.className = "prop-hp-bar"; this.root.visible = false;
this.root.scale.setScalar(BAR_WORLD_SCALE);
this.root.frustumCulled = false;
this.root.renderOrder = RENDER_ORDER_FOREGROUND;
const track = document.createElement("div"); const ui = sourceUi.clone(true);
track.className = "prop-hp-bar__track"; this.bakeMatrices(ui);
this.centerGroup(ui);
this.prepareMeshes(ui);
this.delayedEl = document.createElement("div"); this.root.add(ui);
this.delayedEl.className = "prop-hp-bar__delayed"; parent.add(this.root);
this.currentEl = document.createElement("div"); const fgNode = ui.getObjectByName(NODE_FOREGROUND);
this.currentEl.className = "prop-hp-bar__current"; const mgNode = ui.getObjectByName(NODE_MIDDLEGROUND);
this.foreground = fgNode ? this.createFillPart(fgNode) : null;
this.middleground = mgNode ? this.createFillPart(mgNode) : null;
track.appendChild(this.delayedEl); const background = ui.getObjectByName(NODE_BACKGROUND);
track.appendChild(this.currentEl); if (background) background.visible = true;
this.root.appendChild(track);
parent.appendChild(this.root);
this.applyWidths(); this.applyWidths();
} }
@@ -61,32 +127,68 @@ export class PropHpBar {
); );
} }
this.delayedEl.style.width = `${this.getHealthRatio(this.displayedHealth) * 100}%`; if (this.middleground) {
this.applyFill(this.middleground, this.getHealthRatio(this.displayedHealth));
}
if (!this.visible) return; if (!this.visible) return;
this.updatePosition(); this.updateTransform();
} }
setVisible(value: boolean) { setVisible(value: boolean) {
this.visible = value; this.visible = value;
this.root.classList.toggle("is-visible", value); this.root.visible = value;
if (value) { if (value) {
this.displayedHealth = this.prop.health; this.displayedHealth = this.prop.health;
this.applyWidths(); this.applyWidths();
this.updatePosition(); this.updateTransform();
} }
} }
destroy() { destroy() {
this.root.remove(); this.root.removeFromParent();
} }
private applyWidths() { private applyWidths() {
const ratio = this.getHealthRatio(this.prop.health); if (this.foreground) {
this.currentEl.style.width = `${ratio * 100}%`; this.applyFill(this.foreground, this.getHealthRatio(this.prop.health));
this.delayedEl.style.width = `${this.getHealthRatio(this.displayedHealth) * 100}%`; }
if (this.middleground) {
this.applyFill(this.middleground, this.getHealthRatio(this.displayedHealth));
}
}
private applyFill(part: FillPart, ratio: number) {
const clamped = Math.max(0, Math.min(1, ratio));
part.node.scale.x = part.baseScaleX * clamped;
part.node.position.x =
part.basePosX + part.anchorMinX * part.baseScaleX * (1 - clamped);
}
private createFillPart(node: Object3D): FillPart {
const meshMinX = this.getMeshMinX(node);
const isForeground = node.name.includes(NODE_FOREGROUND);
node.renderOrder = isForeground
? RENDER_ORDER_FOREGROUND
: RENDER_ORDER_MIDDLEGROUND;
return {
node,
baseScaleX: node.scale.x,
basePosX: node.position.x,
anchorMinX: meshMinX,
};
}
private getMeshMinX(node: Object3D) {
const mesh = node as Mesh;
if (!mesh.isMesh || !mesh.geometry) return -0.935;
mesh.geometry.computeBoundingBox();
return mesh.geometry.boundingBox?.min.x ?? -0.935;
} }
private getHealthRatio(health: number) { private getHealthRatio(health: number) {
@@ -94,78 +196,138 @@ export class PropHpBar {
return Math.max(health, 0) / this.prop.maxHealth; return Math.max(health, 0) / this.prop.maxHealth;
} }
private updatePosition() { private updateTransform() {
if (!this.computeVisualBounds()) { if (!this.computeVisualBounds()) {
this.root.style.display = "none"; this.root.visible = false;
return; return;
} }
this.bounds.getCenter(this.anchor); PropHpBar.worldAnchor.set(
this.anchor.x += BAR_X_OFFSET; (this.bounds.min.x + this.bounds.max.x) * 0.5 + BAR_X_OFFSET,
this.anchor.y = this.bounds.max.y + BAR_Y_OFFSET; this.bounds.max.y + BAR_Y_OFFSET,
(this.bounds.min.z + this.bounds.max.z) * 0.5,
);
const camera = CameraC.camera; this.root.position.copy(PropHpBar.worldAnchor);
const projected = this.anchor.project(camera); this.root.quaternion.set(0, 0, 0, 1);
this.root.visible = this.visible;
if (projected.z > 1) {
this.root.style.display = "none";
return;
}
const screenPos = PropHpBar.worldToLayerPosition(projected, this.root.parentElement);
if (!screenPos) {
this.root.style.display = "none";
return;
}
this.root.style.display = "";
this.root.style.left = `${screenPos.x}px`;
this.root.style.top = `${screenPos.y}px`;
}
private static worldToLayerPosition(
projected: Vector3,
layer: HTMLElement | null,
): { x: number; y: number } | null {
const canvas = document.querySelector("canvas");
if (!canvas || !layer) return null;
const canvasRect = canvas.getBoundingClientRect();
const layerRect = layer.getBoundingClientRect();
return {
x:
(projected.x * 0.5 + 0.5) * canvasRect.width +
canvasRect.left -
layerRect.left,
y:
(-projected.y * 0.5 + 0.5) * canvasRect.height +
canvasRect.top -
layerRect.top,
};
} }
private computeVisualBounds() { private computeVisualBounds() {
this.prop.object.updateWorldMatrix(true, true); this.prop.object.updateWorldMatrix(true, true);
this.bounds.makeEmpty(); this.bounds.makeEmpty();
const includeMesh = (node: Object3D) => { this.prop.object.traverse((child) => {
if (!(node as Mesh).isMesh) return; if (!(child as Mesh).isMesh) return;
const name = node.name.toLowerCase(); const name = child.name.toLowerCase();
if (name.includes("collider") || name.includes("trigger") || name.includes("gathertrigger")) { if (name.includes("collider") || name.includes("trigger") || name.includes("gathertrigger")) {
return; return;
} }
this.bounds.expandByObject(node); this.bounds.expandByObject(child);
}; });
includeMesh(this.prop.object);
this.prop.object.traverse((child) => includeMesh(child));
if (!this.bounds.isEmpty()) return true; if (!this.bounds.isEmpty()) return true;
this.bounds.setFromObject(this.prop.object); this.bounds.setFromObject(this.prop.object);
return !this.bounds.isEmpty(); return !this.bounds.isEmpty();
} }
private bakeMatrices(ui: Object3D) {
this.decomposeNodeMatrix(ui);
ui.traverse((child) => {
if (child === ui) return;
this.decomposeNodeMatrix(child);
});
}
private decomposeNodeMatrix(node: Object3D) {
node.updateMatrix();
PropHpBar.tempMatrix.copy(node.matrix);
if (PropHpBar.tempMatrix.equals(PropHpBar.identityMatrix)) return;
PropHpBar.tempMatrix.decompose(
PropHpBar.tempPosition,
PropHpBar.tempQuaternion,
PropHpBar.tempScale,
);
node.matrix.identity();
node.position.copy(PropHpBar.tempPosition);
node.quaternion.copy(PropHpBar.tempQuaternion);
node.scale.copy(PropHpBar.tempScale);
node.matrixAutoUpdate = true;
}
private centerGroup(group: Object3D) {
const box = new Box3().setFromObject(group);
const center = new Vector3();
box.getCenter(center);
group.position.sub(center);
}
private prepareMeshes(root: Object3D) {
root.traverse((child) => {
child.frustumCulled = false;
if (!(child as Mesh).isMesh) return;
const mesh = child as Mesh;
mesh.castShadow = false;
mesh.receiveShadow = false;
if (child.name.includes(NODE_BACKGROUND)) {
child.renderOrder = RENDER_ORDER_BACKGROUND;
} else if (child.name.includes(NODE_MIDDLEGROUND)) {
child.renderOrder = RENDER_ORDER_MIDDLEGROUND;
} else if (child.name.includes(NODE_FOREGROUND)) {
child.renderOrder = RENDER_ORDER_FOREGROUND;
}
if (Array.isArray(mesh.material)) {
mesh.material = mesh.material.map((material) => this.toVisibleMaterial(material));
} else {
mesh.material = this.toVisibleMaterial(mesh.material);
}
});
}
/** Keeps GLB map/color; unlit basic material renders reliably in playable. */
private toVisibleMaterial(source: Material) {
if (source instanceof MeshBasicMaterial) {
const cloned = source.clone();
cloned.side = DoubleSide;
cloned.depthTest = false;
cloned.depthWrite = false;
cloned.toneMapped = false;
cloned.transparent = true;
return cloned;
}
const src = source as MeshStandardMaterial;
const material = new MeshBasicMaterial({
side: DoubleSide,
depthTest: false,
depthWrite: false,
toneMapped: false,
transparent: true,
opacity: src.opacity ?? 1,
});
if (src.map) {
material.map = src.map;
}
if (src.color) {
material.color.copy(src.color);
} else {
material.color = new Color(0xffffff);
}
if (src.alphaTest) {
material.alphaTest = src.alphaTest;
material.transparent = true;
}
return material;
}
} }
+52 -11
View File
@@ -1,4 +1,6 @@
import { Object3D } from "three";
import { UpdateController } from "@24tools/playable_template"; import { UpdateController } from "@24tools/playable_template";
import { ThreeC } from "../ThreeC";
import { PropC } from "./PropC"; import { PropC } from "./PropC";
import { PropHpBar } from "./PropHpBar"; import { PropHpBar } from "./PropHpBar";
@@ -7,20 +9,15 @@ const DEBUG_ALWAYS_VISIBLE_HP_BARS = false;
export class PropHpUIC { export class PropHpUIC {
private static inited = false; private static inited = false;
private static root: HTMLElement | null = null; private static overlayLayer: Object3D | null = null;
private static bars = new Map<PropC, PropHpBar>(); private static bars = new Map<PropC, PropHpBar>();
static init() { static init() {
if (this.inited) return; if (this.inited) return;
this.inited = true; this.inited = true;
const uiRoot = document.getElementById("ui"); this.hideSceneTemplate();
if (!uiRoot) return; this.ensureOverlayLayer();
this.root = document.createElement("div");
this.root.id = "prop-hp-layer";
this.root.className = "prop-hp-layer";
uiRoot.appendChild(this.root);
UpdateController.Instance.onUpdate.addDelegate((delta) => { UpdateController.Instance.onUpdate.addDelegate((delta) => {
for (const bar of this.bars.values()) { for (const bar of this.bars.values()) {
@@ -29,10 +26,31 @@ export class PropHpUIC {
}); });
} }
static createBar(prop: PropC): PropHpBar | undefined { /** Call after map/scene objects are added so overlay renders last. */
if (!this.root || this.bars.has(prop)) return this.bars.get(prop); static bringOverlayToFront() {
this.ensureOverlayLayer();
const layer = this.overlayLayer;
if (!layer) return;
const bar = new PropHpBar(prop, this.root); let parent = layer.parent;
if (!parent) {
ThreeC.addToScene(layer);
parent = layer.parent;
if (!parent) return;
}
parent.remove(layer);
parent.add(layer);
}
static createBar(prop: PropC): PropHpBar | undefined {
if (!PropHpBar.getPrefab()) {
console.warn("HP bar prefab not loaded");
return undefined;
}
if (this.bars.has(prop)) return this.bars.get(prop);
const bar = new PropHpBar(prop, this.getOverlayLayer());
this.bars.set(prop, bar); this.bars.set(prop, bar);
if (DEBUG_ALWAYS_VISIBLE_HP_BARS) { if (DEBUG_ALWAYS_VISIBLE_HP_BARS) {
@@ -79,4 +97,27 @@ export class PropHpUIC {
bar.destroy(); bar.destroy();
this.bars.delete(prop); this.bars.delete(prop);
} }
private static hideSceneTemplate() {
const template = PropHpBar.getPrefab();
if (!template || !template.parent) return;
template.visible = false;
template.removeFromParent();
}
private static ensureOverlayLayer() {
if (!this.overlayLayer) {
this.overlayLayer = new Object3D();
this.overlayLayer.name = "prop-hp-overlay";
this.overlayLayer.frustumCulled = false;
this.overlayLayer.renderOrder = PropHpBar.OVERLAY_RENDER_ORDER;
ThreeC.addToScene(this.overlayLayer);
}
}
private static getOverlayLayer() {
this.ensureOverlayLayer();
return this.overlayLayer!;
}
} }
+4
View File
@@ -9,17 +9,21 @@ import { ResourceDepositC } from "./Resources/ResourceDepositC";
import { PropHpUIC } from "./Map/PropHpUIC"; import { PropHpUIC } from "./Map/PropHpUIC";
import { PropVfxC } from "./Map/PropVfxC"; import { PropVfxC } from "./Map/PropVfxC";
import { InvasionProgressUIC } from "./UI/InvasionProgressUIC"; import { InvasionProgressUIC } from "./UI/InvasionProgressUIC";
import { PreGameplayUIC } from "./UI/PreGameplayUIC";
export class TestSceneC { export class TestSceneC {
static init() { static init() {
InvasionProgressUIC.init(); InvasionProgressUIC.init();
ResourceUIC.init(); ResourceUIC.init();
PreGameplayUIC.init();
ResourceFlyC.init(); ResourceFlyC.init();
PropHpUIC.init(); PropHpUIC.init();
PropVfxC.Init(); PropVfxC.Init();
Map.init(); Map.init();
PropHpUIC.bringOverlayToFront();
GatherC.init(); GatherC.init();
Player.init(); Player.init();
PropHpUIC.bringOverlayToFront();
const mapObject = ThreeC.getObject("map"); const mapObject = ThreeC.getObject("map");
if (mapObject) { if (mapObject) {
+45
View File
@@ -0,0 +1,45 @@
export class PreGameplayUIC {
private static root: HTMLElement | null = null;
static init() {
const ui = document.getElementById("ui");
if (!ui) return;
ui.classList.add("is-pre-gameplay");
const root = document.createElement("div");
root.className = "pre-gameplay";
const hurry = document.createElement("p");
hurry.className = "pre-gameplay__hurry";
hurry.textContent = "HURRY UP";
const bottom = document.createElement("div");
bottom.className = "pre-gameplay__bottom";
const drag = document.createElement("p");
drag.className = "pre-gameplay__drag";
drag.textContent = "DRAG TO MOVE";
const joystick = document.createElement("div");
joystick.className = "pre-gameplay-joystick";
const base = document.createElement("div");
base.className = "pre-gameplay-joystick__base";
const knob = document.createElement("div");
knob.className = "pre-gameplay-joystick__knob";
joystick.append(base, knob);
bottom.append(drag, joystick);
root.append(hurry, bottom);
ui.appendChild(root);
this.root = root;
}
static dismiss() {
document.getElementById("ui")?.classList.remove("is-pre-gameplay");
this.root?.remove();
this.root = null;
}
}
+154
View File
@@ -0,0 +1,154 @@
#ui.is-pre-gameplay .hud-invasion-title,
#ui.is-pre-gameplay .hud-progress,
#ui.is-pre-gameplay .hud-top-right {
display: none !important;
}
.pre-gameplay {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 11;
}
.pre-gameplay__hurry {
position: absolute;
top: 14vh;
left: 50%;
transform: translateX(-50%);
margin: 0;
font-size: 5vh;
font-weight: 700;
color: #ffffff;
text-transform: uppercase;
letter-spacing: 0.04em;
text-align: center;
line-height: 1;
white-space: nowrap;
-webkit-text-stroke: 0.14vh #000000;
paint-order: stroke fill;
animation: pre-gameplay-pulse 1.2s ease-in-out infinite;
}
.pre-gameplay__bottom {
position: absolute;
left: 50%;
bottom: 10vh;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 2.5vh;
}
.pre-gameplay__drag {
margin: 0;
font-size: 4.2vh;
font-weight: 700;
color: #ffffff;
text-transform: uppercase;
letter-spacing: 0.04em;
text-align: center;
line-height: 1;
white-space: nowrap;
-webkit-text-stroke: 0.12vh #000000;
paint-order: stroke fill;
}
.pre-gameplay-joystick {
position: relative;
width: 22vh;
height: 22vh;
}
.pre-gameplay-joystick__base {
position: absolute;
inset: 0;
border-radius: 50%;
border: 0.35vh solid rgba(255, 255, 255, 0.55);
background: rgba(255, 255, 255, 0.12);
box-sizing: border-box;
}
.pre-gameplay-joystick__knob {
position: absolute;
left: 50%;
top: 50%;
width: 8vh;
height: 8vh;
margin-left: -4vh;
margin-top: -4vh;
border-radius: 50%;
background: #ffffff;
animation: pre-gameplay-joystick-knob 2.4s ease-in-out infinite;
}
@keyframes pre-gameplay-pulse {
0%,
100% {
transform: translateX(-50%) scale(1);
}
50% {
transform: translateX(-50%) scale(1.06);
}
}
@keyframes pre-gameplay-joystick-knob {
0%,
100% {
transform: translate(0, 0);
}
25% {
transform: translate(5vh, 0);
}
50% {
transform: translate(0, -3.5vh);
}
75% {
transform: translate(-5vh, 0);
}
}
@media (orientation: landscape) {
.pre-gameplay__hurry {
top: 8vh;
font-size: 4vh;
}
.pre-gameplay__bottom {
bottom: 6vh;
gap: 1.5vh;
}
.pre-gameplay__drag {
font-size: 3.2vh;
}
.pre-gameplay-joystick {
width: 18vh;
height: 18vh;
}
.pre-gameplay-joystick__knob {
width: 6.5vh;
height: 6.5vh;
margin-left: -3.25vh;
margin-top: -3.25vh;
}
@keyframes pre-gameplay-joystick-knob {
0%,
100% {
transform: translate(0, 0);
}
25% {
transform: translate(4vh, 0);
}
50% {
transform: translate(0, -2.8vh);
}
75% {
transform: translate(-4vh, 0);
}
}
}
-52
View File
@@ -184,58 +184,6 @@
z-index: 20; z-index: 20;
} }
.prop-hp-layer {
position: absolute;
inset: 0;
pointer-events: none;
}
.prop-hp-bar {
position: absolute;
width: 8vh;
height: 1.2vh;
transform: translate(-50%, -100%);
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 15;
transition: opacity 0.15s ease;
}
.prop-hp-bar.is-visible {
opacity: 1;
visibility: visible;
}
.prop-hp-bar__track {
position: relative;
width: 100%;
height: 100%;
background: #000000;
border-radius: 0.25vh;
overflow: hidden;
}
.prop-hp-bar__delayed,
.prop-hp-bar__current {
position: absolute;
left: 0;
top: 0;
height: 100%;
border-radius: 0.25vh;
width: 100%;
}
.prop-hp-bar__delayed {
background: #ffffff;
z-index: 1;
}
.prop-hp-bar__current {
background: #3b8bff;
z-index: 2;
}
@media (orientation: landscape) { @media (orientation: landscape) {
.hud-top-center { .hud-top-center {
top: 1.2vh; top: 1.2vh;
+1
View File
@@ -12,6 +12,7 @@
<link href="./css/loader.css" rel="stylesheet" /> <link href="./css/loader.css" rel="stylesheet" />
<link href="./css/main.css" rel="stylesheet" /> <link href="./css/main.css" rel="stylesheet" />
<link href="./css/ui.css" rel="stylesheet" /> <link href="./css/ui.css" rel="stylesheet" />
<link href="./css/preGameplay.css" rel="stylesheet" />
<style id="animations"></style> <style id="animations"></style>
</head> </head>
<body> <body>
Binary file not shown.
+4
View File
@@ -17,6 +17,10 @@ export const meshes : ConvertResourceType = {
name: "wood", name: "wood",
value: ConvertToBase64WhenRelease("./wood.glb"), value: ConvertToBase64WhenRelease("./wood.glb"),
}, },
{
name: "hpBar",
value: ConvertToBase64WhenRelease("./hpBar.glb"),
},
], ],
loader: Template3d.meshLoader loader: Template3d.meshLoader
} }
+3 -1
View File
@@ -1,5 +1,7 @@
import { InvasionProgressUIC } from "../controllers/UI/InvasionProgressUIC"; import { InvasionProgressUIC } from "../controllers/UI/InvasionProgressUIC";
import { PreGameplayUIC } from "../controllers/UI/PreGameplayUIC";
export const firstClickCb: () => void = () => { export const firstClickCb: () => void = () => {
PreGameplayUIC.dismiss();
InvasionProgressUIC.startTimer(); InvasionProgressUIC.startTimer();
}; };
+1 -1
View File
File diff suppressed because one or more lines are too long