Pacman and ghost
<!DOCTYPE html> <html> <head> <title>Pac-Man</title> </head>//from www . j a va 2s . c o m <body> <h1>Pac-Man</h1> <canvas id="pacman" width="300" height="300"></canvas> <script> class PacMan { constructor(x, y, radius, speed) { this.x = x; this.y = y; this.radius = radius; this.speed = speed; this.angle = 0; this.x_speed = speed; this.y_speed = 0; this.time = 0; this.mouth = 0; } draw(ctx) { ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); draw_pacman(ctx, this.radius, this.mouth); ctx.restore(); } turn(direction) { if (this.y_speed) { this.x_speed = -direction * this.y_speed; this.y_speed = 0; this.angle = this.x_speed > 0 ? 0 : Math.PI; } else { this.y_speed = direction * this.x_speed; this.x_speed = 0; this.angle = this.y_speed > 0 ? 0.5 * Math.PI : 1.5 * Math.PI; } } turn_left = function() { this.turn(-1); } turn_right = function() { this.turn(1); } update(elapsed, width, height) { if (Math.random() <= 0.01) { if (Math.random() < 0.5) { this.turn_left(); } else { this.turn_right(); } } if (this.x - this.radius + elapsed * this.x_speed > width) { this.x = -this.radius; } if (this.x + this.radius + elapsed * this.x_speed < 0) { this.x = width + this.radius; } if (this.y - this.radius + elapsed * this.y_speed > height) { this.y = -this.radius; } if (this.y + this.radius + elapsed * this.y_speed < 0) { this.y = height + this.radius; } this.x += this.x_speed * elapsed; this.y += this.y_speed * elapsed; this.time += elapsed; this.mouth = Math.abs(Math.sin(2 * Math.PI * this.time)); } } function draw_pacman(ctx, radius, mouth) { angle = 0.2 * Math.PI * mouth; ctx.save(); ctx.fillStyle = "yellow"; ctx.strokeStyle = "black"; ctx.lineWidth = 0.5; ctx.beginPath(); ctx.arc(0, 0, radius, angle, 2 * Math.PI - angle); ctx.lineTo(0, 0); ctx.closePath() ctx.fill(); ctx.stroke(); ctx.restore(); } function draw_ghost(ctx, radius, options) { options = options || {} let feet = options.feet || 4; let head_radius = radius * 0.8; let foot_radius = head_radius / feet; ctx.save(); ctx.strokeStyle = options.stroke || "white"; ctx.fillStyle = options.fill || "red"; ctx.lineWidth = options.lineWidth || radius * 0.05; ctx.beginPath(); for (foot = 0; foot < feet; foot++) { ctx.arc( (2 * foot_radius * (feet - foot)) - head_radius - foot_radius, radius - foot_radius, foot_radius, 0, Math.PI ); } ctx.lineTo(-head_radius, radius - foot_radius); ctx.arc(0, head_radius - radius, head_radius, Math.PI, 2 * Math.PI); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(-head_radius / 2.5, -head_radius / 2, head_radius / 3, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.arc(head_radius / 3.5, -head_radius / 2, head_radius / 3, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle = "black"; ctx.beginPath(); ctx.arc(-head_radius / 2, -head_radius / 2.2, head_radius / 8, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.arc(head_radius / 4, -head_radius / 2.2, head_radius / 8, 0, 2 * Math.PI); ctx.fill(); ctx.restore(); } class Ghost { constructor(x, y, radius, speed, colour) { this.x = x; this.y = y; this.radius = radius; this.speed = speed; this.colour = colour; } draw(ctx) { ctx.save(); ctx.translate(this.x, this.y); draw_ghost(ctx, this.radius, { fill: this.colour }); ctx.restore(); } update = function(target, elapsed) { let angle = Math.atan2(target.y - this.y, target.x - this.x); let x_speed = Math.cos(angle) * this.speed; let y_speed = Math.sin(angle) * this.speed; this.x += x_speed * elapsed; this.y += y_speed * elapsed; } } let context = document.getElementById("pacman").getContext("2d"); let pacman = new PacMan(context.canvas.width / 2, context.canvas.height / 2, 20, 100); let ghosts = [ new Ghost(context.canvas.width * Math.random(), context.canvas.height * Math.random(), 20, 35, 'red'), new Ghost(context.canvas.width * Math.random(), context.canvas.height * Math.random(), 20, 45, 'pink'), new Ghost(context.canvas.width * Math.random(), context.canvas.height * Math.random(), 20, 55, 'cyan'), new Ghost(context.canvas.width * Math.random(), context.canvas.height * Math.random(), 20, 75, 'orange') ]; function draw(ctx, guide) { pacman.draw(ctx); ghosts.forEach(function(ghost) { ghost.draw(context, guide); }); } function update(elapsed) { pacman.update(elapsed, context.canvas.width, context.canvas.height); ghosts.forEach(function(ghost) { ghost.update(pacman, elapsed); }); } let previous, elapsed; function frame(timestamp) { context.clearRect(0, 0, context.canvas.width, context.canvas.height); if (!previous) previous = timestamp; elapsed = timestamp - previous; update(elapsed / 1000); draw(context, true); previous = timestamp; window.requestAnimationFrame(frame); } window.requestAnimationFrame(frame); </script> </body> </html>