code-game / index.html
Ramesh-vani's picture
Update index.html
3154d99 verified
raw
history blame
14.5 kB
<!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 &gt; 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>