230 lines
6.2 KiB
JavaScript
230 lines
6.2 KiB
JavaScript
export class GameObjManager {
|
|
map;
|
|
opts = {
|
|
textColor: "FFFFFF",
|
|
bgColor: "303030",
|
|
bgFocusColor: "505030",
|
|
bgHoverColor: "505050",
|
|
bgFocusHoverColor: "707050",
|
|
bgClickColor: "202020",
|
|
bgFocusClickColor: "404020",
|
|
borderColor: "000000",
|
|
borderFocusColor: "808000",
|
|
font: "monospace",
|
|
fontSize: 24,
|
|
maxFontWidth: 16,
|
|
floorOpacity: 0.75,
|
|
roomOpacity: 0.75,
|
|
};
|
|
|
|
mainmanager;
|
|
|
|
floorObject;
|
|
roomObjects = new Map([]);
|
|
|
|
constructor(map, opts = {}) {
|
|
this.map = map;
|
|
this.opts = {
|
|
...this.opts,
|
|
...opts,
|
|
};
|
|
}
|
|
|
|
generateFloor() {
|
|
if (this.floorObject) this.floorObject.destroy();
|
|
|
|
const currentFloor = this.mainmanager.getCurrentFocusObject("floor");
|
|
|
|
const polygon = new this.map.kp.Polygon(
|
|
currentFloor.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
|
);
|
|
|
|
this.floorObject = this.map.kp.make([
|
|
this.map.kp.polygon(polygon.pts),
|
|
this.map.kp.color(this.map.kp.Color.fromHex(this.opts.bgColor)),
|
|
this.map.kp.opacity(this.opts.floorOpacity),
|
|
this.map.kp.pos(),
|
|
this.map.kp.z(5),
|
|
]);
|
|
|
|
const bounds = polygon.bbox();
|
|
|
|
this.map.camBounds = bounds;
|
|
|
|
this.floorObject.onDraw(() => {
|
|
const camScale = 1 / this.map.kp.camScale().y;
|
|
|
|
this.map.kp.drawPolygon({
|
|
pts: polygon.pts,
|
|
pos: this.map.kp.vec2(0),
|
|
fill: false,
|
|
outline: {
|
|
color: this.map.kp.Color.fromHex(this.opts.borderColor),
|
|
width: 8 * camScale,
|
|
},
|
|
});
|
|
|
|
this.map.kp.drawText({
|
|
text: currentFloor.name,
|
|
size: 24 * camScale,
|
|
pos: this.map.kp.vec2(-4 * camScale, -8 * camScale),
|
|
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
|
anchor: "botleft",
|
|
});
|
|
});
|
|
|
|
this.map.kp.add(this.floorObject);
|
|
}
|
|
|
|
zoomToBounds(boundingBox) {
|
|
// Get screen size
|
|
const width = this.map.kp.width();
|
|
const height = this.map.kp.height();
|
|
|
|
// Get bbox size
|
|
const bBoxWidth = boundingBox.width * 2;
|
|
const bBoxHeight = boundingBox.height * 2;
|
|
|
|
// Compare bounds
|
|
const scaledWidth = width / bBoxWidth;
|
|
const scaledHeight = height / bBoxHeight;
|
|
|
|
// Whichever one is biggest
|
|
const scale = Math.min(scaledWidth, scaledHeight);
|
|
|
|
this.map.zoomToAbs(
|
|
Math.log2(scale), // log scale
|
|
boundingBox.center()
|
|
);
|
|
}
|
|
|
|
zoomToFloor() {
|
|
const objectBounds = this.floorObject.renderArea().bbox();
|
|
|
|
this.zoomToBounds(objectBounds);
|
|
}
|
|
|
|
zoomToRoom(id) {
|
|
const selectedObject = this.roomObjects.get(id);
|
|
if (selectedObject == null) return;
|
|
|
|
const objectBounds = selectedObject.renderArea().bbox();
|
|
|
|
this.zoomToBounds(objectBounds);
|
|
}
|
|
|
|
generateRooms() {
|
|
if (this.roomObjects.size > 0) {
|
|
this.roomObjects.forEach((x) => x.destroy());
|
|
this.roomObjects.clear();
|
|
}
|
|
|
|
const currentRooms = this.mainmanager.getAllFocusObject("room");
|
|
|
|
currentRooms.forEach((room) => {
|
|
const polygon = new this.map.kp.Polygon(
|
|
room.poly.map(([x, y]) => this.map.kp.vec2(x, y))
|
|
);
|
|
|
|
const obj = this.map.kp.make([
|
|
this.map.kp.polygon(polygon.pts),
|
|
this.map.kp.color(this.map.kp.Color.fromHex(this.opts.bgColor)),
|
|
this.map.kp.opacity(this.opts.roomOpacity),
|
|
this.map.kp.area(),
|
|
this.map.kp.pos(),
|
|
this.map.kp.z(6),
|
|
{
|
|
clickForgiveness: 5,
|
|
startClickPosition: null,
|
|
},
|
|
]);
|
|
|
|
this.roomObjects.set(room.id, obj);
|
|
|
|
obj.onUpdate(() => {
|
|
const roomFocused = this.mainmanager.getCurrentFocus("room") == room.id;
|
|
|
|
if (roomFocused) {
|
|
obj.z = 7;
|
|
} else {
|
|
obj.z = 6;
|
|
}
|
|
|
|
if (obj.isHovering()) {
|
|
if (roomFocused)
|
|
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusHoverColor);
|
|
else obj.color = this.map.kp.Color.fromHex(this.opts.bgHoverColor);
|
|
} else {
|
|
if (roomFocused)
|
|
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusColor);
|
|
else obj.color = this.map.kp.Color.fromHex(this.opts.bgColor);
|
|
}
|
|
|
|
if (this.map.kp.isMousePressed() && obj.isHovering()) {
|
|
obj.startClickPosition = this.map.kp.mousePos();
|
|
}
|
|
|
|
if (this.map.kp.isMouseDown() && obj.isHovering()) {
|
|
if (roomFocused)
|
|
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusClickColor);
|
|
else obj.color = this.map.kp.Color.fromHex(this.opts.bgClickColor);
|
|
}
|
|
|
|
if (this.map.kp.isMouseReleased() && obj.isHovering()) {
|
|
const endClickPosition = this.map.kp.mousePos();
|
|
if (
|
|
obj.startClickPosition &&
|
|
obj.startClickPosition.dist(endClickPosition) < obj.clickForgiveness
|
|
) {
|
|
window.location.hash = room.id;
|
|
}
|
|
if (roomFocused)
|
|
obj.color = this.map.kp.Color.fromHex(this.opts.bgFocusHoverColor);
|
|
this.map.clearMouseMode();
|
|
}
|
|
});
|
|
|
|
obj.onDraw(() => {
|
|
const camScale = 1 / this.map.kp.camScale().y;
|
|
const roomFocused = this.mainmanager.getCurrentFocus("room") == room.id;
|
|
|
|
this.map.kp.drawPolygon({
|
|
pts: polygon.pts,
|
|
pos: this.map.kp.vec2(0),
|
|
fill: false,
|
|
outline: {
|
|
color: this.map.kp.Color.fromHex(
|
|
roomFocused ? this.opts.borderFocusColor : this.opts.borderColor
|
|
),
|
|
width: 8 * camScale,
|
|
},
|
|
});
|
|
|
|
if (
|
|
this.opts.maxFontWidth * camScale * room.name.length >
|
|
polygon.bbox().width
|
|
)
|
|
this.map.kp.drawText({
|
|
text: room.shortName + "…",
|
|
size: this.opts.fontSize * camScale,
|
|
pos: polygon.bbox().center(),
|
|
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
|
align: "center",
|
|
anchor: "center",
|
|
});
|
|
else
|
|
this.map.kp.drawText({
|
|
text: room.name,
|
|
width: polygon.bbox().width,
|
|
size: this.opts.fontSize * camScale,
|
|
pos: polygon.bbox().center(),
|
|
color: this.map.kp.Color.fromHex(this.opts.textColor),
|
|
align: "center",
|
|
anchor: "center",
|
|
});
|
|
});
|
|
|
|
this.floorObject.add(obj);
|
|
});
|
|
}
|
|
}
|