skip to content

มาเรียน Canvas ผ่าน Pong game กัน

/ 4 min read

Share on social media

canvas-pong-game สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video

มาเรียนรู้ canvas ผ่านการสร้าง Pong game กัน ว่า

  • animation ที่เคลื่อนได้บน canvas ทำได้ยังไง
  • ตำแหน่งบน canvas ดูยังไง
  • เราทำอะไรบน canvas ได้บ้าง

Canvas คืออะไร ?

Ref: https://www.w3schools.com/html/html5_canvas.asp

Canvas เป็น feature ด้านกราฟฟิคที่เตรียมมาไว้ใน HTML5 ที่สามารถทำให้เรา “วาดภาพ” บน html ได้ (ตามชื่อของมันเลยคือ ผ้าใบที่วาดภาพได้)

<canvas width="200" height="100"></canvas>

วาดของบน Canvas ได้ยังไง ?

คำสั่ง Javascript นั้นสามารถ access เข้าถึง Canvas และสามารถวาดลงไปบน Canvas ได้ มันก็จะมีตั้งแต่

  • วาดเส้น
const ctx = canvas.getContext("2d");
ctx.moveTo(0, 0);
ctx.lineTo(200, 100);
ctx.stroke();
  • วาดวงกลม
const ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
  • วาดสี่เหลี่ยม
const ctx = canvas.getContext("2d");
// Filled Rectangle
ctx.fillStyle = "blue";
ctx.fillRect(10, 10, 100, 50);
// Stroked Rectangle
ctx.strokeStyle = "red";
ctx.strokeRect(120, 10, 100, 50);
// Clear a section of the canvas
ctx.clearRect(50, 30, 30, 20);
  • วาดเส้นโค้ง
const ctx = canvas.getContext("2d");
// Elliptical arc using quadratic curves
ctx.beginPath();
ctx.moveTo(300, 100);
ctx.quadraticCurveTo(350, 50, 400, 100);
ctx.quadraticCurveTo(350, 150, 300, 100);
ctx.fillStyle = "purple";
ctx.fill();
  • ลงตัวอักษร
const ctx = canvas.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World", 10, 50);
  • ลงสี
// Create gradient
const ctx = canvas.getContext("2d");
const grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 150, 80);
  • ลงรูป
const ctx = canvas.getContext("2d");
// access ไปยังรูป
const img = document.getElementById("scream");
// วาดรูปลง canvas
ctx.drawImage(img, 10, 10);

Animation ใน canvas เกิดขึ้นได้ยังไง ?

คำสั่งที่ทำให้เราสามารถวาดได้คือ requestAnimationFrame()

  • canvas ฮิตมากสำหรับใช้คู่กับการทำ Animation (มันให้อารมณ์วาดการตูนบนแผ่นกระดาษแล้วซ้อน frame กัน)
  • คำสั่ง requestAnimationFrame() คือคำสั่งสำหรับการทำ loop คำสั่งแบบ 60 fps (60 execute ใน 1 วินาที)
  • ดีกว่า setInterval ตรงที่มันจะ “ไม่” ทำงานเมื่อไม่อยู่ใน tab อื่น = ประหยัดการทำงานมากกว่า

มาลองทำ Pong game กัน

สิ่งที่เราจะทำ

  • ปู canvas ออกมา
  • สร้าง paddle (แผ่นตี pong game) และ ลูกปิงปองขึ้นมา
  • สร้างให้ปิงปองและ cpu paddle เคลื่อนไหวได้ด้วย requestAnimationFrame()
  • สร้าง การชนของ paddle ออกมา เพื่อให้เกิดการเด้งกลับ
  • ทำให้ paddle ตัวเองให้เคลื่อนไหวด้วย เมาส์

= เราก็จะได้ pong game หน้าตาแบบนี้ออกมา

pong-01

เรามาเริ่มทำกันในแต่ละ step

สร้าง canvas และ selector ออกมาก่อน

!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pong Game</title>
<style>
canvas {
background-color: #000
display: block
margin: 0 auto
}
</style>
</head>
<body>
<canvas id="pong" width="800" height="400"></canvas>
<script>
const canvas = document.getElementById("pong");
const ctx = canvas.getContext("2d");
/* ที่เหลือเราจะมาใส่ code ตรงนี้กัน */
</script>
</body>
</html>

สร้าง paddle (แผ่นตี pong game) และ ลูกปิงปองขึ้นมา

<script>
// สร้าง canvas ball
const ball = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 10,
speed: 4,
dx: 4,
dy: 4,
color: "WHITE",
};
// สร้าง canvas ฝั่ง user
const userPaddle = {
x: 0,
y: canvas.height / 2 - 40,
width: 10,
height: 80,
dy: 4,
color: "WHITE",
};
// สร้าง canvas ฝั่ง computer
const compPaddle = {
x: canvas.width - 10,
y: canvas.height / 2 - 40,
width: 10,
height: 80,
dy: 4,
color: "WHITE",
};
function drawRect(x, y, width, height, color) {
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
function drawCircle(x, y, radius, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
}
// ทำการวาดออกมา
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawRect(userPaddle.x, userPaddle.y, userPaddle.width, userPaddle.height, userPaddle.color);
drawRect(compPaddle.x, compPaddle.y, compPaddle.width, compPaddle.height, compPaddle.color);
drawCircle(ball.x, ball.y, ball.radius, ball.color);
}
function game() {
draw();
}
// run game
game();
</script>

สร้างให้ปิงปองและ cpu paddle เคลื่อนไหวได้ด้วย requestAnimationFrame()

<script>
function update() {
// ทำให้บอลเคลื่อนไหวไปเรื่อยๆ
ball.x += ball.dx;
ball.y += ball.dy;
// ออกนอกกรอบ canvas = เปลี่ยนเส้นทาง
if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
ball.dy = -ball.dy;
}
if (ball.x + ball.radius > canvas.width) {
// กระทบ paddle cpu
if (ball.y > compPaddle.y && ball.y < compPaddle.y + compPaddle.height) {
ball.dx = -ball.dx;
} else {
// ออกจอไป = reset ลูกใหม่
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;
// และเปลี่ยนทิศทาง
ball.dx = -ball.dx;
}
}
if (ball.x - ball.radius < 0) {
// กระทบ paddle ฝั่ง user
if (ball.y > userPaddle.y && ball.y < userPaddle.y + userPaddle.height) {
ball.dx = -ball.dx;
} else {
// ออกนอกจอไป = reset ใหม่
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;
}
}
// สุ่มการเคลื่อนไหวของ paddle
compPaddle.y += (ball.y - (compPaddle.y + compPaddle.height / 2)) * 0.09;
}
function game() {
// เพิ่มการเคลื่อนไหว
update();
draw();
// เพิ่มการเรียกในแต่ละ frame
requestAnimationFrame(game);
}
// run game
game();
</script>

ทำให้ paddle ตัวเองให้เคลื่อนไหวด้วย เมาส์

<script>
// เพิ่มการเคลื่อนไหว canvas ด้วยเมาส์
canvas.addEventListener("mousemove", (event) => {
const rect = canvas.getBoundingClientRect();
userPaddle.y = event.clientY - rect.top - userPaddle.height / 2;
});
</script>

ปกติ canvas ใช้ทำอะไรบ้าง

  • Drawing Applications ใช้ทำพวก image editor, stecth pad (คล้ายๆกับพวก Microsoft Paint) ** พวก web app อะไรก็ตามที่ต้องอาศัยการจัดการ UI แบบ Custom = จะใช้พวก canvas นี่แหละ ช่วยได้
  • Games อย่างที่เห็น เมื่อใช้ Canvas ผสมกับการ render animation = สามารถที่จะ render graphic ที่มี animation ได้ มันเลยกลายเป็น base ของการทำ game ได้
  • Animations ใช้ทำพวก animation ร่วมกับ user input ได้ (เช่นเคสการเล่นกับเมาส์, การคลิก)
  • Photo Manipulation ใช้ร่วมกับการจัดการภาพ ภาพมันสามารถนำมาแสดงผลบน canvas และ สามารถแทรก filter, ปรับสีและสามารถใช้ effect ร่วมกับภาพบน canvas ได้

อะไรก็ตามที่อาศัยการวาด, การทำ animation และการจัดการกับ Event ของ User = Canvas สามารถช่วยคุณได้

Related Post

Share on social media