xxxxxxxxxx
let video; // Video capture for webcam
let handPose; // ML5 hand tracking model
let hands = []; // Array to store detected hand data
let score = 0; // Game score
let startTime; // Timer for elapsed time
let enemies = []; // Array to store enemy objects
let lastSpawnTime = 0; // Track the last time an enemy was spawned
let spawnInterval = 2000; // Time interval (milliseconds) for enemy spawning
let player; // The player object
// Load hand tracking
function preload() {
handPose = ml5.handPose({ flipped: true });
}
function setup() {
createCanvas(windowWidth, windowHeight);
video = createCapture(VIDEO, { flipped: true });
video.hide();
handPose.detectStart(video, gotHands);
startTime = millis(); // Timer starts
player = new Player(); // Create player instance
}
function draw() {
background(0);
image(video, 0, 0); // Draw video feed
// If hands are detected
if (hands.length > 0) {
let hand = hands[0]; // Only considering the first hand (right hand for now)
// Get thumb and index positions for gesture detection
let thumb = hand.thumb_tip;
let index = hand.index_finger_tip;
// Draw a line between the thumb and index finger
stroke(139, 148, 255);
strokeWeight(5);
line(thumb.x, thumb.y, index.x, index.y);
// Detect gestures and trigger actions
detectGestures(thumb, index, hand);
}
// Spawn enemies at regular intervals
if (millis() - lastSpawnTime > spawnInterval) {
spawnEnemy();
lastSpawnTime = millis();
}
// Update and display enemies
for (let enemy of enemies) {
enemy.update();
enemy.display();
}
// Display the HUD (Score & Time)
displayHUD();
}
function detectGestures(thumb, index, hand) {
let distance = dist(thumb.x, thumb.y, index.x, index.y);
// Pinch gesture: Fireball
if (distance < 50) {
textSize(32);
fill(255, 0, 0);
text("Fireball Activated!", width / 2, height / 2);
console.log("Fireball Gesture Detected");
fireball(thumb, index); // Fireball action
}
// Swipe gesture: Wind Blast (if thumb and index are far apart and swipe detected)
if (distance > 150) {
textSize(32);
fill(0, 0, 255);
text("Wind Blast Activated!", width / 2, height / 2);
console.log("Wind Blast Gesture Detected");
windBlast(thumb, index); // Wind Blast action
}
// Open palm: Shield (using the full hand, checking if fingers are extended)
if (hand.index_finger_tip && hand.middle_finger_tip && hand.ring_finger_tip && hand.pinky_tip) {
textSize(32);
fill(0, 255, 0);
text("Shield Activated!", width / 2, height / 2);
console.log("Shield Gesture Detected");
shield(thumb, index); // Shield action
}
}
function fireball(thumb, index) {
// Fireball behavior: Cast from the thumb towards the index and move
let fireball = new Spell(thumb.x, thumb.y, "fireball");
fireball.moveTo(index.x, index.y);
// Interact with enemies (collide, damage them)
for (let enemy of enemies) {
if (fireball.isColliding(enemy)) {
enemy.hit();
}
}
}
function windBlast(thumb, index) {
// Wind Blast pushes enemies away from the player (simulate with velocity)
for (let enemy of enemies) {
let d = dist(thumb.x, thumb.y, enemy.x, enemy.y);
if (d < 100) { // Push enemies that are close
enemy.pushAway(thumb.x, thumb.y);
}
}
}
function shield(thumb, index) {
// Temporary Shield protection
player.protect(); // Protect the player with a shield
textSize(32);
fill(0, 255, 0);
text("Shield Active!", 20, 100);
}
// Function to spawn a new enemy
function spawnEnemy() {
enemies.push(new Enemy());
}
function displayHUD() {
fill(255);
textSize(20);
text("Score: " + score, 20, 30);
let elapsedTime = floor((millis() - startTime) / 1000);
text("Time: " + elapsedTime + "s", 20, 60);
}
// Hand tracking results
function gotHands(results) {
hands = results;
}
// Player class to represent the magic orb
class Player {
constructor() {
this.health = 100;
this.x = width / 2;
this.y = height - 100;
}
update() {
// Track hand position to move player (could add more controls later)
if (hands.length > 0) {
let hand = hands[0];
this.x = hand.index_finger_tip.x;
this.y = hand.index_finger_tip.y;
}
}
display() {
fill(255, 204, 0);
noStroke();
ellipse(this.x, this.y, 50, 50); // The magic orb
}
protect() {
// Temporary shield activation logic
fill(0, 0, 255, 50);
ellipse(this.x, this.y, 100, 100); // Draw shield around the player
}
}
// Enemy class to represent enemy orbs that move toward the player
class Enemy {
constructor() {
this.x = random(width); // Spawn at a random x-position
this.y = 0; // Start from the top of the screen
this.size = random(20, 50); // Random size for variety
this.speed = random(2, 5); // Random falling speed
}
update() {
this.y += this.speed; // Move downward
}
display() {
fill(255, 0, 0); // Red color for enemies
noStroke();
ellipse(this.x, this.y, this.size, this.size); // Draw enemy orb
}
hit() {
this.size -= 10; // Reduce enemy size on hit
if (this.size <= 0) {
this.remove(); // Remove from screen when hit
}
}
remove() {
let index = enemies.indexOf(this);
if (index !== -1) {
enemies.splice(index, 1);
}
}
pushAway(x, y) {
let angle = atan2(this.y - y, this.x - x);
this.x += cos(angle) * 10; // Push enemy away
this.y += sin(angle) * 10; // Push enemy away
}
isColliding(enemy) {
let d = dist(this.x, this.y, enemy.x, enemy.y);
return d < this.size / 2 + enemy.size / 2; // Collision detection
}
}
// Spell class to manage fireball and other spells
class Spell {
constructor(x, y, type) {
this.x = x;
this.y = y;
this.type = type;
this.size = 20;
}
moveTo(tx, ty) {
this.x += (tx - this.x) * 0.05; // Move toward target (index finger)
this.y += (ty - this.y) * 0.05;
}
display() {
if (this.type === "fireball") {
fill(255, 100, 0);
noStroke();
ellipse(this.x, this.y, this.size, this.size); // Display the fireball
}
}
isColliding(enemy) {
let d = dist(this.x, this.y, enemy.x, enemy.y);
return d < this.size / 2 + enemy.size / 2; // Collision detection
}
}