Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c9a3c06fe |
174
index.html
Normal file
174
index.html
Normal file
@@ -0,0 +1,174 @@
|
||||
<!doctype html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Symulacja minigierki z rzucaniem zaklęć z Reksio i Czarodzieje</title>
|
||||
<style>
|
||||
body { margin: 0; display:flex; height:100vh; align-items:center; justify-content:center; background:#f0f0f0; }
|
||||
canvas { background: #ffffff; border:1px solid #ccc; }
|
||||
#coords { position:fixed; left:10px; top:10px; background:rgba(0,0,0,0.6); color:#fff; padding:6px 8px; border-radius:4px; font-family:monospace; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="coords">x: -, y: - | down: false</div>
|
||||
<canvas id="canvas" width="800" height="600"></canvas>
|
||||
|
||||
<script>
|
||||
const canvas = document.getElementById('canvas');
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const coordsEl = document.getElementById('coords');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
const spellDirections = {
|
||||
'Sen': [270,45,315,90],
|
||||
'Zamiana w żabę': [90,0,270,180,45,135],
|
||||
'Plaga much': [90,225,0,225],
|
||||
'Kula budyniu': [180,90,0,90,180],
|
||||
'Koła i wiry': [270,45,270,135,0],
|
||||
'Ciemność': [0,225,315,180],
|
||||
'Obrona przed Snem': [0,90,180,270,0],
|
||||
'Obrona przed Zamianą w żabę': [280,0,90,0,270,135], // nope, that 280 is not a typo, that was in the original code
|
||||
'Obrona przed Plagą much': [225,135,45,315,180],
|
||||
'Obrona przed Kulą budyniu': [270,180,90,180,270],
|
||||
'Obrona przed Kołami i wirami': [45,180,315,180],
|
||||
'Obrona przed Ciemnością': [180,45,135,0]
|
||||
};
|
||||
|
||||
const ANGLE_TOLERANCE = 35.5; // used in shape comparison, not in point probing
|
||||
const POINT_DISTANCE_THRESHOLD = 30;
|
||||
let lastPoint = null;
|
||||
let drawnAngles = [];
|
||||
|
||||
clearCanvas();
|
||||
|
||||
let isDown = false;
|
||||
|
||||
function updateDisplay(x, y) {
|
||||
coordsEl.textContent = `x: ${x}, y: ${y} | down: ${isDown}`;
|
||||
}
|
||||
|
||||
function clearCanvas() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
function getPos(evt) {
|
||||
const r = canvas.getBoundingClientRect();
|
||||
return {
|
||||
x: Math.round(evt.clientX - r.left),
|
||||
y: Math.round(evt.clientY - r.top)
|
||||
};
|
||||
}
|
||||
|
||||
function compareAngle(a, b) {
|
||||
return (a - b + 540.0) % 360.0 - 180.0;
|
||||
}
|
||||
|
||||
function angleNear(angle, target, margin) {
|
||||
return Math.abs(compareAngle(angle, target)) <= margin;
|
||||
}
|
||||
|
||||
function probePoint(p) {
|
||||
// probing by >= 30 pixels
|
||||
if (lastPoint) {
|
||||
const dx = p.x - lastPoint.x;
|
||||
const dy = p.y - lastPoint.y;
|
||||
const distance = Math.hypot(dx, dy);
|
||||
if (distance >= POINT_DISTANCE_THRESHOLD) {
|
||||
const angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||
|
||||
// normalize angle to [0, 360) (ATAN2 in Piklib was normalized)
|
||||
const normalizedAngle = (angle + 360) % 360;
|
||||
|
||||
// calculate the difference between the last angle and the current angle
|
||||
if (drawnAngles.length > 0) {
|
||||
const lastAngle = drawnAngles[drawnAngles.length - 1];
|
||||
const angleDifference = Math.abs(compareAngle(normalizedAngle, lastAngle));
|
||||
if (angleDifference > 45) {
|
||||
drawnAngles.push(normalizedAngle);
|
||||
}
|
||||
} else {
|
||||
// technically game scripts force the first angle to have difference of 46 degrees, so it pushes the first angle regardless of the tolerance
|
||||
drawnAngles.push(normalizedAngle);
|
||||
}
|
||||
|
||||
// draw a line from lastPoint to current point
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(lastPoint.x, lastPoint.y);
|
||||
ctx.lineTo(p.x, p.y);
|
||||
ctx.strokeStyle = '#ff0000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// override last point
|
||||
lastPoint = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canvas.addEventListener('mousedown', (e) => {
|
||||
// left button is a 0
|
||||
if (e.button === 0) {
|
||||
isDown = true;
|
||||
const p = getPos(e);
|
||||
lastPoint = p;
|
||||
drawnAngles = [];
|
||||
clearCanvas();
|
||||
updateDisplay(p.x, p.y);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('mouseup', (e) => {
|
||||
if (e.button === 0) {
|
||||
isDown = false;
|
||||
const p = getPos(e);
|
||||
probePoint(p);
|
||||
|
||||
console.log('Drawn angles:', drawnAngles);
|
||||
|
||||
// break a spell and compare with the known spell directions
|
||||
const spellName = Object.keys(spellDirections).find(name => {
|
||||
const directions = spellDirections[name];
|
||||
|
||||
// when lengths of array are different, it cancels the comparison
|
||||
if (directions.length !== drawnAngles.length) {
|
||||
console.log(`Spell "${name}" rejected due to length mismatch: expected ${directions.length}, got ${drawnAngles.length}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// compare each angle with the corresponding drawn angle with angle tolerance
|
||||
for (let i = 0; i < directions.length; i++) {
|
||||
const expectedAngle = directions[i];
|
||||
const drawnAngle = drawnAngles[i];
|
||||
if (!angleNear(drawnAngle, expectedAngle, ANGLE_TOLERANCE)) {
|
||||
console.log(`Spell "${name}" rejected due to angle mismatch at index ${i}: expected ${expectedAngle}, got ${drawnAngle}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
console.log(spellName);
|
||||
if (spellName) {
|
||||
console.log(`Spell cast: ${spellName}`);
|
||||
}
|
||||
|
||||
updateDisplay(p.x, p.y);
|
||||
}
|
||||
});
|
||||
|
||||
canvas.addEventListener('mousemove', (e) => {
|
||||
const p = getPos(e);
|
||||
updateDisplay(p.x, p.y);
|
||||
if (isDown) {
|
||||
probePoint(p);
|
||||
}
|
||||
});
|
||||
|
||||
// zapobiegaj zaznaczaniu tekstu/dragowaniu
|
||||
canvas.addEventListener('dragstart', e => e.preventDefault());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user