Spaces:
Running
Running
File size: 14,538 Bytes
5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 5faa8a4 3154d99 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS Coding Game - Professional Template with Monaco Editor</title>
<!-- Monaco Editor Loader -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs/loader.js"></script>
<!-- Matter.js Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f9f9f9; }
#container { max-width: 1000px; margin: auto; }
#guide { background: #ffffff; border: 1px solid #ccc; padding: 15px; margin-bottom: 20px; }
#guide h3, #guide h4 { margin-top: 0; }
#taskPanel { background: #ffffff; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
#editor { width: 100%; height: 250px; border: 1px solid #ccc; }
#runBtn { padding: 10px 20px; margin-top: 10px; font-size: 16px; cursor: pointer; }
#gameCanvas { display: block; margin-top: 20px; border: 1px solid #333; background: #e0f7fa; }
</style>
</head>
<body>
<div id="container">
<!-- How To Play Guide -->
<div id="guide">
<h3>How to Play</h3>
<p>
Control the hero by writing JavaScript commands in the editor below.
When you click "Run Code," your commands will be executed and affect the game in real time.
</p>
<h4>Basic Commands</h4>
<ul>
<li><code>console.log("move 5");</code> β Moves the hero to the right (sets heroβs x velocity to 5).</li>
<li><code>console.log("jump 0.05");</code> β Makes the hero jump by applying an upward force.</li>
<li><code>console.log("attack sword");</code> β Attacks with the sword (removes an enemy if in range).</li>
<li><code>console.log("attack bow");</code> β Fires an arrow from the hero.</li>
<li><code>console.log("attack bomb");</code> β Throws a bomb that explodes after a short delay.</li>
</ul>
<h4>Advanced Logic</h4>
<p>
You can access global game variables directly to build advanced logic. For example:
</p>
<pre style="background:#eee; padding:10px;">if (hero.velocity.x > 4) {
console.log("Hero is speeding!");
}</pre>
<p>The following game variables are available:</p>
<ul>
<li><code>hero</code> β The heroβs Matter.js body (position, velocity, etc.).</li>
<li><code>engine</code> β The Matter.js engine instance.</li>
<li><code>world</code> β The Matter.js world containing all game bodies.</li>
<li><code>enemies</code> β An array of enemy bodies.</li>
<li><code>sword</code> β The sword body used for melee attacks.</li>
</ul>
</div>
<!-- Task Display Panel -->
<div id="taskPanel">
<strong>Current Task:</strong> <span id="taskText"></span>
</div>
<!-- Monaco Editor Container -->
<div id="editor"></div>
<button id="runBtn">Run Code</button>
<!-- Game Canvas -->
<canvas id="gameCanvas" width="600" height="300"></canvas>
</div>
<script>
// --- Initialize Monaco Editor ---
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs' }});
let monacoEditor;
require(['vs/editor/editor.main'], function() {
monacoEditor = monaco.editor.create(document.getElementById('editor'), {
value: `// Example Commands:
// Basic movement:
console.log("move 5");
console.log("jump 0.05");
// Advanced logic example:
// if (hero.velocity.x > 4) { console.log("Hero is speeding!"); }
// To attack using different weapons:
// console.log("attack sword");
// console.log("attack bow");
// console.log("attack bomb");`,
language: "javascript",
theme: "vs-light",
automaticLayout: true
});
});
// --- Matter.js Game Setup ---
const Engine = Matter.Engine,
Render = Matter.Render,
World = Matter.World,
Bodies = Matter.Bodies,
Body = Matter.Body;
const engine = Engine.create();
const render = Render.create({
canvas: document.getElementById("gameCanvas"),
engine: engine,
options: { width: 600, height: 300, wireframes: false }
});
// --- Create Game Bodies ---
const ground = Bodies.rectangle(300, 290, 600, 20, { isStatic: true });
const hero = Bodies.rectangle(100, 250, 40, 40, { restitution: 0.5 });
// Weapons:
const sword = Bodies.rectangle(140, 250, 30, 10, { isStatic: true, render: { visible: false } });
let arrows = [];
let bombs = [];
// Enemies:
const enemies = [
Bodies.rectangle(400, 250, 40, 40, { isStatic: false }),
Bodies.rectangle(550, 250, 40, 40, { isStatic: false })
];
World.add(engine.world, [ground, hero, sword, ...enemies]);
Engine.run(engine);
Render.run(render);
// --- Expose Key Variables for Advanced Access ---
window.engine = engine;
window.render = render;
window.world = engine.world;
window.hero = hero;
window.sword = sword;
window.enemies = enemies;
// --- Task System: 50 Tasks ---
const tasks = [
{ id: 1, text: "Reach x = 200", condition: () => hero.position.x >= 200 },
{ id: 2, text: "Defeat at least one enemy", condition: () => enemies.some(e => e.isRemoved) },
{ id: 3, text: "Defeat all enemies", condition: () => enemies.every(e => e.isRemoved) },
{ id: 4, text: "Jump above y = 180", condition: () => hero.position.y <= 180 },
{ id: 5, text: "Reach x = 300", condition: () => hero.position.x >= 300 },
{ id: 6, text: "Reach x = 400", condition: () => hero.position.x >= 400 },
{ id: 7, text: "Reach x = 500", condition: () => hero.position.x >= 500 },
{ id: 8, text: "Move with speed > 3", condition: () => Math.abs(hero.velocity.x) > 3 },
{ id: 9, text: "Move left with speed > 3", condition: () => hero.velocity.x < -3 },
{ id: 10, text: "Land with low y-velocity (< 2)", condition: () => Math.abs(hero.velocity.y) < 2 },
{ id: 11, text: "Stay on ground (y > 240)", condition: () => hero.position.y > 240 },
{ id: 12, text: "Achieve x = 150", condition: () => hero.position.x >= 150 },
{ id: 13, text: "Achieve x = 250", condition: () => hero.position.x >= 250 },
{ id: 14, text: "Achieve x = 350", condition: () => hero.position.x >= 350 },
{ id: 15, text: "Achieve x = 450", condition: () => hero.position.x >= 450 },
{ id: 16, text: "Perform a moderate jump (y between 240 and 260)", condition: () => hero.position.y >= 240 && hero.position.y <= 260 },
{ id: 17, text: "Move 100 units from start", condition: () => hero.position.x - 100 >= 100 },
{ id: 18, text: "Hero's x velocity is nearly 0", condition: () => Math.abs(hero.velocity.x) < 0.1 },
{ id: 19, text: "Hero's y velocity is nearly 0", condition: () => Math.abs(hero.velocity.y) < 0.1 },
{ id: 20, text: "Attack using sword to defeat an enemy", condition: () => enemies.some(e => e.isRemoved) },
{ id: 21, text: "Attack using bow to defeat an enemy", condition: () => enemies.some(e => e.isRemoved) },
{ id: 22, text: "Attack using bomb to defeat an enemy", condition: () => enemies.some(e => e.isRemoved) },
{ id: 23, text: "Move and jump simultaneously", condition: () => hero.position.x >= 120 && hero.position.y <= 240 },
{ id: 24, text: "Achieve a sprint speed (|velocity.x| >= 7)", condition: () => Math.abs(hero.velocity.x) >= 7 },
{ id: 25, text: "Perform a duck action", condition: () => hero.render && hero.render.fillStyle === "blue" },
{ id: 26, text: "Perform a dash move (|velocity.x| >= 5)", condition: () => Math.abs(hero.velocity.x) >= 5 },
{ id: 27, text: "Change direction (velocity.x becomes negative)", condition: () => hero.velocity.x < 0 },
{ id: 28, text: "Move upward quickly (velocity.y < -2)", condition: () => hero.velocity.y < -2 },
{ id: 29, text: "Stay completely still", condition: () => Math.abs(hero.velocity.x) < 0.1 && Math.abs(hero.velocity.y) < 0.1 },
{ id: 30, text: "Reach far right (x >= 550)", condition: () => hero.position.x >= 550 },
{ id: 31, text: "Reach far left (x <= 50)", condition: () => hero.position.x <= 50 },
{ id: 32, text: "Perform a combo attack (all enemies defeated)", condition: () => enemies.every(e => e.isRemoved) },
{ id: 33, text: "Attack with bow and bomb consecutively", condition: () => enemies.every(e => e.isRemoved) },
{ id: 34, text: "Show high energy (dummy condition)", condition: () => hero.position.x > 0 },
{ id: 35, text: "Perform a precise jump (y < 230)", condition: () => hero.position.y < 230 },
{ id: 36, text: "Land softly (|velocity.y| < 1)", condition: () => Math.abs(hero.velocity.y) < 1 },
{ id: 37, text: "Achieve horizontal acceleration > 4", condition: () => Math.abs(hero.velocity.x) > 4 },
{ id: 38, text: "Avoid enemy collision", condition: () => enemies.every(e => !Matter.Bounds.overlaps(hero.bounds, e.bounds)) },
{ id: 39, text: "Come near an enemy (within 50 units) without attacking", condition: () => enemies.some(e => Math.abs(hero.position.x - e.position.x) < 50 && !e.isRemoved) },
{ id: 40, text: "Reset near starting point (x < 120)", condition: () => hero.position.x < 120 },
{ id: 41, text: "Jump height exceeds 30 units", condition: () => (250 - hero.position.y) >= 30 },
{ id: 42, text: "Maintain steady movement (velocity.x ~ 3)", condition: () => Math.abs(hero.velocity.x - 3) < 1 },
{ id: 43, text: "Attack then move (enemy defeated and x > 150)", condition: () => enemies.some(e => e.isRemoved) && hero.position.x > 150 },
{ id: 44, text: "Keep speed constant (velocity.x ~ 3)", condition: () => Math.abs(hero.velocity.x - 3) < 0.5 },
{ id: 45, text: "Show agility (jump and dash with |velocity.x| > 4)", condition: () => hero.position.y < 240 && Math.abs(hero.velocity.x) > 4 },
{ id: 46, text: "Combo move achieves x >= 350", condition: () => hero.position.x >= 350 },
{ id: 47, text: "Recover from an attack (x >= 100)", condition: () => hero.position.x >= 100 },
{ id: 48, text: "Dodge enemy attack (no overlap with any enemy)", condition: () => enemies.every(e => !Matter.Bounds.overlaps(hero.bounds, e.bounds)) },
{ id: 49, text: "Exhibit erratic movement (|velocity.x| > 5)", condition: () => Math.abs(hero.velocity.x) > 5 },
{ id: 50, text: "Final Task: Overcome all challenges (x >= 550 and all enemies defeated)", condition: () => hero.position.x >= 550 && enemies.every(e => e.isRemoved) }
];
let currentTaskIndex = 0;
function updateTaskText() {
document.getElementById("taskText").innerText = tasks[currentTaskIndex].text;
}
updateTaskText();
// --- Enemy Movement (Simple AI) ---
function moveEnemies() {
enemies.forEach((enemy) => {
if (enemy.isRemoved) return;
const dx = hero.position.x - enemy.position.x;
const speed = dx > 0 ? 1.5 : -1.5;
Body.setVelocity(enemy, { x: speed, y: 0 });
});
}
setInterval(moveEnemies, 100);
// --- Command Parser (No debug console output) ---
function handleGameAction(command) {
const parts = command.split(" ");
const action = parts[0];
const param = parts[1];
const value = parseFloat(parts[1]);
if (action === "move" && !isNaN(value)) {
Body.setVelocity(hero, { x: value, y: hero.velocity.y });
} else if (action === "jump" && !isNaN(value)) {
Body.applyForce(hero, hero.position, { x: 0, y: -value });
} else if (action === "attack") {
if (param === "sword") performSwordAttack();
if (param === "bow") fireArrow();
if (param === "bomb") throwBomb();
}
}
function performSwordAttack() {
Body.setPosition(sword, { x: hero.position.x + 30, y: hero.position.y });
sword.render.visible = true;
enemies.forEach((enemy) => {
if (!enemy.isRemoved && Matter.Bounds.overlaps(sword.bounds, enemy.bounds)) {
World.remove(engine.world, enemy);
enemy.isRemoved = true;
}
});
setTimeout(() => { sword.render.visible = false; }, 500);
}
function fireArrow() {
const arrow = Bodies.rectangle(hero.position.x + 20, hero.position.y, 20, 5, { restitution: 0.2 });
Body.setVelocity(arrow, { x: 5, y: 0 });
arrows.push(arrow);
World.add(engine.world, arrow);
setTimeout(() => { World.remove(engine.world, arrow); }, 3000);
}
function throwBomb() {
const bomb = Bodies.circle(hero.position.x, hero.position.y - 10, 10, { restitution: 0.5 });
Body.setVelocity(bomb, { x: 3, y: -3 });
bombs.push(bomb);
World.add(engine.world, bomb);
setTimeout(() => {
bombs = bombs.filter(b => b !== bomb);
World.remove(engine.world, bomb);
enemies.forEach((enemy) => {
if (!enemy.isRemoved && Matter.Bounds.overlaps(bomb.bounds, enemy.bounds)) {
World.remove(engine.world, enemy);
enemy.isRemoved = true;
}
});
}, 2000);
}
// --- Check Task Completion ---
function checkTaskCompletion() {
if (tasks[currentTaskIndex].condition()) {
alert(`β
Task Completed: ${tasks[currentTaskIndex].text}`);
currentTaskIndex++;
if (currentTaskIndex < tasks.length) {
updateTaskText();
resetHeroPosition();
} else {
alert("π All Tasks Completed!");
}
}
}
// --- Run Code Button Event ---
document.getElementById("runBtn").addEventListener("click", () => {
// Retrieve user code from Monaco Editor
const userCode = monacoEditor.getValue();
try {
// Override console.log temporarily to capture commands (without on-screen debug)
const oldConsoleLog = console.log;
console.log = function(msg) {
handleGameAction(msg);
};
new Function(userCode)();
console.log = oldConsoleLog;
setTimeout(checkTaskCompletion, 1000);
} catch (error) {
alert("Error: " + error.message);
}
});
function resetHeroPosition() {
Body.setPosition(hero, { x: 100, y: 250 });
Body.setVelocity(hero, { x: 0, y: 0 });
}
</script>
</body>
</html>
|