Add: Slider customization & fix black spots showing up on map
This commit is contained in:
parent
38ee14524f
commit
a17146fee9
webradar
@ -50,6 +50,12 @@
|
||||
<div>
|
||||
<input type="checkbox" onclick="toggleCentered()" id="centerCheck" name="center" checked />
|
||||
<label for="centerCheck">Player Centered</label>
|
||||
<div id="zoomLevelContainer" style="margin-top: 5px; margin-left: 20px; display: none;">
|
||||
<label for="zoomLevelSlider">Zoom Level: </label>
|
||||
<span id="zoomLevelValue">1.0</span><br>
|
||||
<input type="range" id="zoomLevelSlider" min="1.0" max="5.0" step="0.1" value="1.0"
|
||||
style="width: 100%; margin: 5px 0;" oninput="updateZoomLevel(this.value)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-focus">
|
||||
<label for="playerSelect">Focus Player:</label>
|
||||
@ -57,6 +63,21 @@
|
||||
<option value="local">YOU</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="sizeControlsContainer"
|
||||
style="margin-top: 10px; padding: 5px; border-top: 1px solid rgba(255, 255, 255, 0.2);">
|
||||
<div class="size-control" style="margin-bottom: 8px;">
|
||||
<label for="textSizeSlider">Text Size: </label>
|
||||
<span id="textSizeValue">1.0</span><br>
|
||||
<input type="range" id="textSizeSlider" min="0.1" max="2.0" step="0.1" value="1.0"
|
||||
style="width: 100%; margin: 5px 0;" oninput="updateTextSize(this.value)">
|
||||
</div>
|
||||
<div class="size-control">
|
||||
<label for="entitySizeSlider">Player Size: </label>
|
||||
<span id="entitySizeValue">1.0</span><br>
|
||||
<input type="range" id="entitySizeSlider" min="0.5" max="2.0" step="0.1" value="1.0"
|
||||
style="width: 100%; margin: 5px 0;" oninput="updateEntitySize(this.value)">
|
||||
</div>
|
||||
</div>
|
||||
<button id="showDangerousBtn" onclick="toggleDangerousOptions()">Show Dangerous Options</button>
|
||||
<div class="dangerous-options" id="dangerousOptions">
|
||||
<div>
|
||||
@ -71,6 +92,6 @@
|
||||
</div>
|
||||
<script src="script.js"></script>
|
||||
<script src="webstuff.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -17,10 +17,23 @@ let drawNames = true;
|
||||
let drawGuns = true;
|
||||
let drawMoney = true;
|
||||
|
||||
let canvasScale = 1;
|
||||
let minTextSize = 16;
|
||||
let minEntitySize = 10;
|
||||
let textSizeMultiplier = 1.0;
|
||||
let entitySizeMultiplier = 1.0;
|
||||
|
||||
const DEFAULT_TEXT_SIZE = 0.4;
|
||||
const DEFAULT_ENTITY_SIZE = 1.2;
|
||||
const DEFAULT_ZOOM_LEVEL = 2.4;
|
||||
|
||||
const NETWORK_SETTINGS = {
|
||||
useInterpolation: true,
|
||||
interpolationAmount: 0.6,
|
||||
pingInterval: 3000
|
||||
pingInterval: 3000,
|
||||
maxRetries: 5,
|
||||
requestTimeout: 5000,
|
||||
reconnectDelay: 1000
|
||||
};
|
||||
|
||||
let connectionHealthy = true;
|
||||
@ -40,7 +53,6 @@ let lastKnownPositions = {};
|
||||
let entityInterpolationData = {};
|
||||
let lastUpdateTime = 0;
|
||||
let networkLatencyHistory = [];
|
||||
let lastPingSent = 0;
|
||||
|
||||
let focusedPlayerYaw = 0;
|
||||
let focusedPlayerName = "YOU";
|
||||
@ -231,6 +243,7 @@ function render() {
|
||||
|
||||
renderFrame();
|
||||
}
|
||||
|
||||
function sendRequest() {
|
||||
isRequestPending = true;
|
||||
pingTracker.startRequest();
|
||||
@ -280,7 +293,8 @@ function renderFrame() {
|
||||
|
||||
drawBombTimer();
|
||||
} else if (!loaded) {
|
||||
ctx.font = "40px Arial";
|
||||
const fontSize = Math.max(40 * canvasScale, 16);
|
||||
ctx.font = `${fontSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = textColor;
|
||||
@ -288,14 +302,15 @@ function renderFrame() {
|
||||
}
|
||||
|
||||
if (drawStats) {
|
||||
ctx.font = "16px Arial";
|
||||
const fontSize = Math.max(16 * canvasScale, 12);
|
||||
ctx.font = `${fontSize}px Arial`;
|
||||
ctx.textAlign = "left";
|
||||
ctx.fillStyle = "#00FF00";
|
||||
let rotationStatus = "Active";
|
||||
if (temporarilyDisableRotation) rotationStatus = "Manually Disabled";
|
||||
else if (rotationDisabledUntilRespawn) rotationStatus = "Disabled (Death)";
|
||||
|
||||
ctx.fillText(`${currentFps} FPS | ${freq} Hz | Ping: ${Math.round(pingTracker.getAveragePing())}ms | Rotation: ${rotationStatus}`, 10, 20);
|
||||
ctx.fillText(`${currentFps} FPS | ${freq} Hz | Ping: ${Math.round(pingTracker.getAveragePing())}ms | Rotation: ${rotationStatus}`, 10, fontSize + 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,43 +376,47 @@ function drawImage() {
|
||||
|
||||
ctx.save();
|
||||
|
||||
const shouldRotate = rotateMap &&
|
||||
if (playerCentered && focusedPlayerPos) {
|
||||
if (playerCenteredZoom !== 1.0) {
|
||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||
ctx.scale(playerCenteredZoom, playerCenteredZoom);
|
||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||
}
|
||||
|
||||
if (rotateMap &&
|
||||
focusedPlayerPos &&
|
||||
!temporarilyDisableRotation &&
|
||||
!rotationDisabledUntilRespawn) {
|
||||
|
||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||
ctx.rotate(degreesToRadians(focusedPlayerYaw + 270));
|
||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||
}
|
||||
|
||||
const playerX = (focusedPlayerPos.x - map.pos_x) / map.scale;
|
||||
const playerY = (focusedPlayerPos.y - map.pos_y) / -map.scale;
|
||||
|
||||
const playerCanvasX = (playerX / image.width) * canvas.width;
|
||||
const playerCanvasY = (playerY / image.height) * canvas.height;
|
||||
|
||||
const translateX = (canvas.width / 2) - playerCanvasX;
|
||||
const translateY = (canvas.height / 2) - playerCanvasY;
|
||||
|
||||
ctx.translate(translateX, translateY);
|
||||
} else if (rotateMap &&
|
||||
focusedPlayerPos &&
|
||||
!temporarilyDisableRotation &&
|
||||
!rotationDisabledUntilRespawn;
|
||||
|
||||
if (shouldRotate) {
|
||||
!rotationDisabledUntilRespawn) {
|
||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||
ctx.rotate(degreesToRadians(focusedPlayerYaw + 270));
|
||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||
}
|
||||
|
||||
if (playerCentered && focusedPlayerPos) {
|
||||
const playerX = (focusedPlayerPos.x - map.pos_x) / map.scale;
|
||||
const playerY = (focusedPlayerPos.y - map.pos_y) / -map.scale;
|
||||
|
||||
const zoomLevel = 0.5;
|
||||
const viewWidth = image.width * zoomLevel;
|
||||
const viewHeight = image.height * zoomLevel;
|
||||
|
||||
ctx.drawImage(
|
||||
image,
|
||||
playerX - (viewWidth / 2), playerY - (viewHeight / 2), viewWidth, viewHeight,
|
||||
0, 0, canvas.width, canvas.height
|
||||
);
|
||||
} else if (zoomSet && boundingRect?.x != null) {
|
||||
ctx.drawImage(
|
||||
image,
|
||||
boundingRect.x, boundingRect.y, boundingRect.width, boundingRect.height,
|
||||
0, 0, canvas.width, canvas.height
|
||||
);
|
||||
} else {
|
||||
ctx.drawImage(
|
||||
image,
|
||||
0, 0, image.width, image.height,
|
||||
0, 0, canvas.width, canvas.height
|
||||
);
|
||||
}
|
||||
ctx.drawImage(
|
||||
image,
|
||||
0, 0, image.width, image.height,
|
||||
0, 0, canvas.width, canvas.height
|
||||
);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
@ -408,12 +427,119 @@ function toggleHealth() {
|
||||
localStorage.setItem('drawHealth', drawHealth ? 'true' : 'false');
|
||||
}
|
||||
|
||||
function mapAndTransformCoordinates(pos) {
|
||||
const canvasWidth = canvas.width;
|
||||
const canvasHeight = canvas.height;
|
||||
const imageWidth = image ? image.width : 1;
|
||||
const imageHeight = image ? image.height : 1;
|
||||
|
||||
if (!map || !pos) return {
|
||||
pos: { x: 0, y: 0 },
|
||||
textSize: minTextSize * textSizeMultiplier
|
||||
};
|
||||
|
||||
const posX = (pos.x - map.pos_x) / map.scale;
|
||||
const posY = (pos.y - map.pos_y) / -map.scale;
|
||||
|
||||
let screenX = (posX / imageWidth) * canvasWidth;
|
||||
let screenY = (posY / imageHeight) * canvasHeight;
|
||||
|
||||
if (playerCentered && focusedPlayerPos) {
|
||||
const playerX = (focusedPlayerPos.x - map.pos_x) / map.scale;
|
||||
const playerY = (focusedPlayerPos.y - map.pos_y) / -map.scale;
|
||||
|
||||
const playerRelX = playerX / imageWidth;
|
||||
const playerRelY = playerY / imageHeight;
|
||||
|
||||
const centerX = canvasWidth / 2;
|
||||
const centerY = canvasHeight / 2;
|
||||
|
||||
const playerScreenX = (playerX / imageWidth) * canvasWidth;
|
||||
const playerScreenY = (playerY / imageHeight) * canvasHeight;
|
||||
|
||||
const deltaX = screenX - playerScreenX;
|
||||
const deltaY = screenY - playerScreenY;
|
||||
|
||||
const zoomedDeltaX = deltaX * playerCenteredZoom;
|
||||
const zoomedDeltaY = deltaY * playerCenteredZoom;
|
||||
|
||||
screenX = centerX + zoomedDeltaX;
|
||||
screenY = centerY + zoomedDeltaY;
|
||||
|
||||
if (rotateMap &&
|
||||
!temporarilyDisableRotation &&
|
||||
!rotationDisabledUntilRespawn) {
|
||||
|
||||
const relX = screenX - centerX;
|
||||
const relY = screenY - centerY;
|
||||
|
||||
const angle = degreesToRadians(focusedPlayerYaw + 270);
|
||||
const cos = Math.cos(angle);
|
||||
const sin = Math.sin(angle);
|
||||
|
||||
const rotX = relX * cos - relY * sin;
|
||||
const rotY = relX * sin + relY * cos;
|
||||
|
||||
screenX = rotX + centerX;
|
||||
screenY = rotY + centerY;
|
||||
}
|
||||
} else if (rotateMap &&
|
||||
focusedPlayerPos &&
|
||||
!temporarilyDisableRotation &&
|
||||
!rotationDisabledUntilRespawn) {
|
||||
|
||||
const centerX = canvasWidth / 2;
|
||||
const centerY = canvasHeight / 2;
|
||||
|
||||
const relX = screenX - centerX;
|
||||
const relY = screenY - centerY;
|
||||
|
||||
const angle = degreesToRadians(focusedPlayerYaw + 270);
|
||||
const cos = Math.cos(angle);
|
||||
const sin = Math.sin(angle);
|
||||
|
||||
const rotX = relX * cos - relY * sin;
|
||||
const rotY = relX * sin + relY * cos;
|
||||
|
||||
screenX = rotX + centerX;
|
||||
screenY = rotY + centerY;
|
||||
}
|
||||
|
||||
const finalTextSize = playerCentered ?
|
||||
minTextSize * textSizeMultiplier * playerCenteredZoom :
|
||||
minTextSize * textSizeMultiplier;
|
||||
|
||||
return {
|
||||
pos: { x: screenX, y: screenY },
|
||||
textSize: finalTextSize
|
||||
};
|
||||
}
|
||||
|
||||
function updateZoomLevel(value) {
|
||||
playerCenteredZoom = parseFloat(value);
|
||||
const valueDisplay = document.getElementById('zoomLevelValue');
|
||||
if (valueDisplay) valueDisplay.textContent = value;
|
||||
localStorage.setItem('playerCenteredZoom', value);
|
||||
}
|
||||
|
||||
function toggleCentered() {
|
||||
playerCentered = !playerCentered;
|
||||
updateZoomSliderVisibility();
|
||||
}
|
||||
|
||||
function updateZoomSliderVisibility() {
|
||||
const zoomSliderContainer = document.getElementById('zoomLevelContainer');
|
||||
if (zoomSliderContainer) {
|
||||
zoomSliderContainer.style.display = playerCentered ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function drawPlayerHealth(pos, playerType, health, hasBomb) {
|
||||
if (!map) return;
|
||||
|
||||
const transformed = mapAndTransformCoordinates(pos);
|
||||
const mapPos = transformed.pos;
|
||||
const textSize = transformed.textSize * 0.8;
|
||||
const textSize = transformed.textSize;
|
||||
|
||||
let extraOffset = 0;
|
||||
if (drawNames) extraOffset += 15;
|
||||
@ -432,8 +558,9 @@ function drawPlayerHealth(pos, playerType, health, hasBomb) {
|
||||
healthColor = "#FF0000";
|
||||
}
|
||||
|
||||
const barWidth = 40;
|
||||
const barHeight = 5;
|
||||
const barWidth = Math.max(60, 40 * textSizeMultiplier);
|
||||
const barHeight = Math.max(8, 5 * textSizeMultiplier);
|
||||
|
||||
ctx.fillStyle = "#444444";
|
||||
ctx.fillRect(mapPos.x - barWidth / 2, textY, barWidth, barHeight);
|
||||
|
||||
@ -441,15 +568,15 @@ function drawPlayerHealth(pos, playerType, health, hasBomb) {
|
||||
const healthWidth = (health / 100) * barWidth;
|
||||
ctx.fillRect(mapPos.x - barWidth / 2, textY, healthWidth, barHeight);
|
||||
|
||||
ctx.font = `${textSize}px Arial`;
|
||||
ctx.font = `bold ${textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.strokeText(`${health}HP`, mapPos.x, textY + barHeight + 1);
|
||||
ctx.strokeText(`${health}HP`, mapPos.x, textY + barHeight + 2);
|
||||
ctx.fillStyle = healthColor;
|
||||
ctx.fillText(`${health}HP`, mapPos.x, textY + barHeight + 1);
|
||||
ctx.fillText(`${health}HP`, mapPos.x, textY + barHeight + 2);
|
||||
}
|
||||
|
||||
function drawEntities() {
|
||||
@ -577,8 +704,12 @@ function drawBombTimer() {
|
||||
const maxWidth = 1024 - 128 - 128;
|
||||
const timeleft = radarData.bombDefuseTimeleft;
|
||||
|
||||
const timerHeight = Math.max(16, 10 * canvasScale);
|
||||
const timerY = Math.max(16, 10 * canvasScale);
|
||||
const fontSize = Math.max(24, 18 * canvasScale);
|
||||
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(128, 16, maxWidth, 16);
|
||||
ctx.fillRect(128, timerY, maxWidth, timerHeight);
|
||||
|
||||
if (radarData.bombBeingDefused) {
|
||||
ctx.fillStyle = radarData.bombCanDefuse ? teamColor : enemyColor;
|
||||
@ -586,32 +717,32 @@ function drawBombTimer() {
|
||||
ctx.fillStyle = bombColor;
|
||||
}
|
||||
|
||||
ctx.fillRect(130, 18, (maxWidth - 2) * (timeleft / 40), 12);
|
||||
ctx.fillRect(130, timerY + 2, (maxWidth - 2) * (timeleft / 40), timerHeight - 4);
|
||||
|
||||
ctx.font = "24px Arial";
|
||||
ctx.font = `bold ${fontSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = textColor;
|
||||
ctx.fillText(`${timeleft.toFixed(1)}s`, 1024 / 2, 28 + 24);
|
||||
ctx.fillText(`${timeleft.toFixed(1)}s`, 1024 / 2, timerY + timerHeight + fontSize / 2 + 4);
|
||||
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineWidth = 2;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(128 + (maxWidth * (5 / 40)), 16);
|
||||
ctx.lineTo(128 + (maxWidth * (5 / 40)), 32);
|
||||
ctx.moveTo(128 + (maxWidth * (5 / 40)), timerY);
|
||||
ctx.lineTo(128 + (maxWidth * (5 / 40)), timerY + timerHeight);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(130 + (maxWidth - 2) * (10 / 40), 16);
|
||||
ctx.lineTo(130 + (maxWidth - 2) * (10 / 40), 32);
|
||||
ctx.moveTo(130 + (maxWidth - 2) * (10 / 40), timerY);
|
||||
ctx.lineTo(130 + (maxWidth - 2) * (10 / 40), timerY + timerHeight);
|
||||
ctx.stroke();
|
||||
|
||||
if (radarData.bombCanDefuse) {
|
||||
ctx.strokeStyle = "green";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(130 + (maxWidth - 2) * (radarData.bombDefuseEnd / 40), 16);
|
||||
ctx.lineTo(130 + (maxWidth - 2) * (radarData.bombDefuseEnd / 40), 32);
|
||||
ctx.moveTo(130 + (maxWidth - 2) * (radarData.bombDefuseEnd / 40), timerY);
|
||||
ctx.lineTo(130 + (maxWidth - 2) * (radarData.bombDefuseEnd / 40), timerY + timerHeight);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
@ -670,79 +801,6 @@ function mapCoordinates(coordinates) {
|
||||
return { x: offset_x, y: offset_y };
|
||||
}
|
||||
|
||||
function mapAndTransformCoordinates(pos) {
|
||||
const canvasWidth = canvas.width;
|
||||
const canvasHeight = canvas.height;
|
||||
const imageWidth = image ? image.width : 1;
|
||||
const imageHeight = image ? image.height : 1;
|
||||
|
||||
if (!map || !pos) return { pos: { x: 0, y: 0 }, textSize: 12 };
|
||||
|
||||
const offset_x = (pos.x - map.pos_x) / map.scale;
|
||||
const offset_y = (pos.y - map.pos_y) / -map.scale;
|
||||
|
||||
let mapPos = { x: offset_x, y: offset_y };
|
||||
let textSize = 12;
|
||||
|
||||
if (zoomSet && boundingRect && boundingRect.x != null) {
|
||||
const xScale = boundingRect.width / imageWidth;
|
||||
const yScale = boundingRect.height / imageHeight;
|
||||
mapPos = {
|
||||
x: (mapPos.x - boundingRect.x) / xScale,
|
||||
y: (mapPos.y - boundingRect.y) / yScale
|
||||
};
|
||||
textSize = (imageWidth / boundingRect.width) * 12;
|
||||
}
|
||||
else if (playerCentered && focusedPlayerPos) {
|
||||
const zoomLevel = 0.5;
|
||||
const viewWidth = imageWidth * zoomLevel;
|
||||
const viewHeight = imageHeight * zoomLevel;
|
||||
|
||||
let playerMapPos;
|
||||
if (focusedPlayerName === "YOU" && localPlayerPos) {
|
||||
const lpx = (localPlayerPos.x - map.pos_x) / map.scale;
|
||||
const lpy = (localPlayerPos.y - map.pos_y) / -map.scale;
|
||||
playerMapPos = { x: lpx, y: lpy };
|
||||
} else if (focusedPlayerPos) {
|
||||
const fpx = (focusedPlayerPos.x - map.pos_x) / map.scale;
|
||||
const fpy = (focusedPlayerPos.y - map.pos_y) / -map.scale;
|
||||
playerMapPos = { x: fpx, y: fpy };
|
||||
} else {
|
||||
playerMapPos = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
mapPos.x = (mapPos.x - (playerMapPos.x - viewWidth / 2)) * canvasWidth / viewWidth;
|
||||
mapPos.y = (mapPos.y - (playerMapPos.y - viewHeight / 2)) * canvasHeight / viewHeight;
|
||||
}
|
||||
else {
|
||||
mapPos.x = mapPos.x * canvasWidth / imageWidth;
|
||||
mapPos.y = mapPos.y * canvasHeight / imageHeight;
|
||||
}
|
||||
|
||||
const shouldRotate = rotateMap &&
|
||||
typeof focusedPlayerYaw === 'number' &&
|
||||
!temporarilyDisableRotation &&
|
||||
!rotationDisabledUntilRespawn;
|
||||
|
||||
if (shouldRotate) {
|
||||
const canvasCenter = { x: canvasWidth / 2, y: canvasHeight / 2 };
|
||||
const rotationYaw = focusedPlayerName === "YOU" ? localYaw : focusedPlayerYaw;
|
||||
const angle = rotationYaw + 270;
|
||||
|
||||
const radians = angle * (Math.PI / 180);
|
||||
const cos = Math.cos(radians);
|
||||
const sin = Math.sin(radians);
|
||||
|
||||
const nx = mapPos.x - canvasCenter.x;
|
||||
const ny = mapPos.y - canvasCenter.y;
|
||||
|
||||
mapPos.x = nx * cos - ny * sin + canvasCenter.x;
|
||||
mapPos.y = nx * sin + ny * cos + canvasCenter.y;
|
||||
}
|
||||
|
||||
return { pos: mapPos, textSize: textSize };
|
||||
}
|
||||
|
||||
function drawPlayerName(pos, playerName, playerType, hasAwp, hasBomb, isScoped) {
|
||||
if (!map) return;
|
||||
|
||||
@ -766,11 +824,11 @@ function drawPlayerName(pos, playerName, playerType, hasAwp, hasBomb, isScoped)
|
||||
displayName += " [SCOPED]";
|
||||
}
|
||||
|
||||
ctx.font = `${textSize}px Arial`;
|
||||
ctx.font = `bold ${textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.strokeText(displayName, mapPos.x, textY);
|
||||
ctx.fillText(displayName, mapPos.x, textY);
|
||||
@ -800,11 +858,11 @@ function drawPlayerMoney(pos, playerType, money, hasBomb) {
|
||||
ctx.fillStyle = "#FF4500";
|
||||
}
|
||||
|
||||
ctx.font = `${textSize}px Arial`;
|
||||
ctx.font = `bold ${textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.strokeText(formattedMoney, mapPos.x, textY);
|
||||
ctx.fillText(formattedMoney, mapPos.x, textY);
|
||||
@ -827,11 +885,11 @@ function drawPlayerWeapon(pos, playerType, weaponId) {
|
||||
ctx.fillStyle = textColor;
|
||||
}
|
||||
|
||||
ctx.font = `${textSize}px Arial`;
|
||||
ctx.font = `bold ${textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.strokeText(`[${weaponName}]`, mapPos.x, textY);
|
||||
ctx.fillText(`[${weaponName}]`, mapPos.x, textY);
|
||||
@ -847,11 +905,11 @@ function drawPlayerBomb(pos, playerType) {
|
||||
const textY = mapPos.y + (drawNames ? (drawGuns ? 50 : 35) : (drawGuns ? 35 : 20));
|
||||
|
||||
ctx.fillStyle = bombColor;
|
||||
ctx.font = `${textSize}px Arial`;
|
||||
ctx.font = `bold ${textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.strokeText("[C4]", mapPos.x, textY);
|
||||
ctx.fillText("[C4]", mapPos.x, textY);
|
||||
@ -862,18 +920,18 @@ function drawBomb(pos, planted) {
|
||||
|
||||
const transformed = mapAndTransformCoordinates(pos);
|
||||
const mapPos = transformed.pos;
|
||||
const size = transformed.textSize * 0.7;
|
||||
const size = minEntitySize * entitySizeMultiplier;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(mapPos.x, mapPos.y, size, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = bombColor;
|
||||
ctx.fill();
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.stroke();
|
||||
|
||||
ctx.font = size * 1.2 + "px Arial";
|
||||
ctx.font = `bold ${Math.max(size * 1.2, minTextSize)}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = "white";
|
||||
@ -895,7 +953,8 @@ function drawEntity(pos, fillStyle, dormant, hasBomb, yaw, hasAwp, playerType, i
|
||||
|
||||
const transformed = mapAndTransformCoordinates(pos);
|
||||
const mapPos = transformed.pos;
|
||||
let circleRadius = transformed.textSize * 0.6;
|
||||
|
||||
let circleRadius = minEntitySize * entitySizeMultiplier;
|
||||
const distance = circleRadius + 2;
|
||||
const radius = distance + 5;
|
||||
const arrowWidth = 35;
|
||||
@ -918,7 +977,7 @@ function drawEntity(pos, fillStyle, dormant, hasBomb, yaw, hasAwp, playerType, i
|
||||
}
|
||||
|
||||
if (dormant) {
|
||||
ctx.font = "20px Arial";
|
||||
ctx.font = `bold ${transformed.textSize}px Arial`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillStyle = fillStyle;
|
||||
ctx.fillText("?", mapPos.x, mapPos.y);
|
||||
@ -977,7 +1036,7 @@ function drawEntity(pos, fillStyle, dormant, hasBomb, yaw, hasAwp, playerType, i
|
||||
ctx.lineTo(lineOfSightX, lineOfSightY);
|
||||
|
||||
ctx.strokeStyle = playerType == "Enemy" ? enemyColor : teamColor;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
@ -1198,6 +1257,34 @@ function connect() {
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextSize(value) {
|
||||
textSizeMultiplier = parseFloat(value);
|
||||
const valueDisplay = document.getElementById('textSizeValue');
|
||||
if (valueDisplay) valueDisplay.textContent = value;
|
||||
localStorage.setItem('textSizeMultiplier', value);
|
||||
}
|
||||
|
||||
function updateEntitySize(value) {
|
||||
entitySizeMultiplier = parseFloat(value);
|
||||
const valueDisplay = document.getElementById('entitySizeValue');
|
||||
if (valueDisplay) valueDisplay.textContent = value;
|
||||
localStorage.setItem('entitySizeMultiplier', value);
|
||||
}
|
||||
|
||||
function resetSizes() {
|
||||
const textSlider = document.getElementById('textSizeSlider');
|
||||
const entitySlider = document.getElementById('entitySizeSlider');
|
||||
const zoomSlider = document.getElementById('zoomLevelSlider');
|
||||
|
||||
if (textSlider) textSlider.value = DEFAULT_TEXT_SIZE.toString();
|
||||
if (entitySlider) entitySlider.value = DEFAULT_ENTITY_SIZE.toString();
|
||||
if (zoomSlider) zoomSlider.value = DEFAULT_ZOOM_LEVEL.toString();
|
||||
|
||||
updateTextSize(DEFAULT_TEXT_SIZE.toString());
|
||||
updateEntitySize(DEFAULT_ENTITY_SIZE.toString());
|
||||
updateZoomLevel(DEFAULT_ZOOM_LEVEL.toString());
|
||||
}
|
||||
|
||||
function toggleZoom() {
|
||||
shouldZoom = !shouldZoom;
|
||||
}
|
||||
@ -1218,10 +1305,6 @@ function toggleRotate() {
|
||||
rotateMap = !rotateMap;
|
||||
}
|
||||
|
||||
function toggleCentered() {
|
||||
playerCentered = !playerCentered;
|
||||
}
|
||||
|
||||
function toggleMoneyReveal() {
|
||||
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
||||
console.log("[radarflow] Sending toggleMoneyReveal command");
|
||||
@ -1264,12 +1347,26 @@ function togglePerformanceMode() {
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
if (canvas) {
|
||||
const canvasRect = canvas.getBoundingClientRect();
|
||||
canvasScale = Math.min(canvasRect.width, canvasRect.height) / 1024;
|
||||
}
|
||||
});
|
||||
|
||||
addEventListener("DOMContentLoaded", () => {
|
||||
const savedDrawHealth = localStorage.getItem('drawHealth');
|
||||
drawHealth = savedDrawHealth !== null ? savedDrawHealth === 'true' : true;
|
||||
|
||||
const savedDrawMoney = localStorage.getItem('drawMoney');
|
||||
drawMoney = savedDrawMoney !== null ? savedDrawMoney === 'true' : true;
|
||||
|
||||
const savedTextSize = localStorage.getItem('textSizeMultiplier');
|
||||
textSizeMultiplier = savedTextSize !== null ? parseFloat(savedTextSize) : DEFAULT_TEXT_SIZE;
|
||||
|
||||
const savedEntitySize = localStorage.getItem('entitySizeMultiplier');
|
||||
entitySizeMultiplier = savedEntitySize !== null ? parseFloat(savedEntitySize) : DEFAULT_ENTITY_SIZE;
|
||||
|
||||
const checkboxes = {
|
||||
"zoomCheck": false,
|
||||
"statsCheck": true,
|
||||
@ -1278,7 +1375,8 @@ addEventListener("DOMContentLoaded", () => {
|
||||
"moneyDisplay": drawMoney,
|
||||
"moneyReveal": false,
|
||||
"rotateCheck": true,
|
||||
"centerCheck": true
|
||||
"centerCheck": true,
|
||||
"healthCheck": drawHealth
|
||||
};
|
||||
|
||||
Object.entries(checkboxes).forEach(([id, state]) => {
|
||||
@ -1286,12 +1384,41 @@ addEventListener("DOMContentLoaded", () => {
|
||||
if (checkbox) checkbox.checked = state;
|
||||
});
|
||||
|
||||
const textSizeSlider = document.getElementById('textSizeSlider');
|
||||
if (textSizeSlider) {
|
||||
textSizeSlider.value = textSizeMultiplier;
|
||||
const textSizeValue = document.getElementById('textSizeValue');
|
||||
if (textSizeValue) textSizeValue.textContent = textSizeMultiplier;
|
||||
}
|
||||
|
||||
const entitySizeSlider = document.getElementById('entitySizeSlider');
|
||||
if (entitySizeSlider) {
|
||||
entitySizeSlider.value = entitySizeMultiplier;
|
||||
const entitySizeValue = document.getElementById('entitySizeValue');
|
||||
if (entitySizeValue) entitySizeValue.textContent = entitySizeMultiplier;
|
||||
}
|
||||
|
||||
const savedZoom = localStorage.getItem('playerCenteredZoom');
|
||||
playerCenteredZoom = savedZoom !== null ? parseFloat(savedZoom) : DEFAULT_ZOOM_LEVEL;
|
||||
|
||||
const zoomSlider = document.getElementById('zoomLevelSlider');
|
||||
if (zoomSlider) {
|
||||
zoomSlider.value = playerCenteredZoom;
|
||||
const zoomValue = document.getElementById('zoomLevelValue');
|
||||
if (zoomValue) zoomValue.textContent = playerCenteredZoom;
|
||||
}
|
||||
|
||||
updateZoomSliderVisibility();
|
||||
|
||||
canvas = document.getElementById('canvas');
|
||||
if (canvas) {
|
||||
canvas.width = 1024;
|
||||
canvas.height = 1024;
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
const canvasRect = canvas.getBoundingClientRect();
|
||||
canvasScale = Math.min(canvasRect.width, canvasRect.height) / 1024;
|
||||
|
||||
connect();
|
||||
} else {
|
||||
console.error("[radarflow] Canvas element not found");
|
||||
|
@ -23,6 +23,8 @@ body {
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
#settingsHolder {
|
||||
@ -47,6 +49,25 @@ canvas {
|
||||
background-color: rgba(25, 25, 25, 0.7);
|
||||
border-radius: 5px;
|
||||
transition: opacity 0.3s ease;
|
||||
font-size: 14px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#settingsHolder .settings {
|
||||
font-size: 16px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#settingsHolder .settings input[type="checkbox"] {
|
||||
transform: scale(1.2);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#settingsHolder .settings>div {
|
||||
padding: 6px 0;
|
||||
}
|
||||
}
|
||||
|
||||
#settingsHolder:hover .settings {
|
||||
@ -92,31 +113,67 @@ canvas {
|
||||
background-color: #8a0000;
|
||||
}
|
||||
|
||||
.size-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.size-control label {
|
||||
display: inline-block;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
-webkit-appearance: none;
|
||||
height: 6px;
|
||||
background: #555;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #68a3e5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #68a3e5;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@media (max-width: 600px),
|
||||
(max-height: 600px) {
|
||||
#settingsHolder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#showMenuBtn {
|
||||
display: block !important;
|
||||
font-size: 16px !important;
|
||||
padding: 8px 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px),
|
||||
(max-height: 400px) {
|
||||
#canvasContainer::before {
|
||||
content: 'settings';
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
background-color: rgba(25, 25, 25, 0.7);
|
||||
color: white;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
z-index: 101;
|
||||
content: '';
|
||||
display: none;
|
||||
}
|
||||
|
||||
#showMenuBtn {
|
||||
padding: 6px 10px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,6 +186,7 @@ canvas {
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
min-width: 150px;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
#playerSelect:hover {
|
||||
@ -147,19 +205,23 @@ canvas {
|
||||
|
||||
.player-focus {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#hideMenuBtn {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
padding: 8px 10px;
|
||||
margin-top: 10px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
transition: background-color 0.3s;
|
||||
width: 100%;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
#hideMenuBtn:hover {
|
||||
@ -170,19 +232,64 @@ canvas {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
background-color: rgba(25, 25, 25, 0.7);
|
||||
background-color: rgba(25, 25, 25, 0.9);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 15px;
|
||||
font-size: 14px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
z-index: 101;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
transition: opacity 0.3s;
|
||||
opacity: 0.6;
|
||||
opacity: 0.8;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#showMenuBtn:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.settings>div {
|
||||
margin-bottom: 5px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.touch-device input[type="checkbox"] {
|
||||
transform: scale(1.3);
|
||||
margin: 2px 10px 2px 2px;
|
||||
}
|
||||
|
||||
.touch-device input[type="range"]::-webkit-slider-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.touch-device input[type="range"]::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.touch-device .settings>div {
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#settingsHolder .settings {
|
||||
background-color: rgba(15, 15, 15, 0.85);
|
||||
}
|
||||
|
||||
#showMenuBtn {
|
||||
background-color: rgba(15, 15, 15, 0.9);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user