JavaScript»ゲーム制作»clickイベント トランプをめくる(全カード)
ファイル名: js-game/quest_00729.html
下のプログラムをうつして、
ソースコード
class Card {
constructor(image, num, mark) {
this.image = image;
this.num = num;
this.mark = mark;
this.x = 0;
this.y = 0;
this.opened = false; // 最初は裏向き
}
// このカードの表示位置(左上頂点)を指定したx, yに設定する
setLocation(x, y) {
this.x = x;
this.y = y;
}
// x, yで指定された点がこのカードの表示領域内であれば、カードを開いた状態にする
openIfContains(x, y) {
if (x > this.x && x < this.x + 32 && y > this.y && y < this.y + 64) {
this.opened = true;
}
}
update() {
// 特に自動的に変化するデータはない
}
render(context) {
const trimX = this.opened ? this.num * 32 : 448;
const trimY = this.opened ? this.mark * 64 : 128;
context.drawImage(this.image, trimX, trimY, 32, 64, this.x, this.y, 32, 64);
}
}
// 52枚のCardオブジェクトがはいったデッキを表すクラス
class CardDeck {
constructor(image) {
this.cards = [];
for (let num = 0; num < 13; num++) {
for (let mark = 0; mark < 4; mark++) {
this.cards.push(new Card(image, num, mark));
}
}
}
// デッキ内のCardをシャッフルする
shuffle() {
for (let i = this.cards.length - 1; i > 0; i--) {
const r = Math.floor(Math.random() * (i + 1));
const tmp = this.cards[i];
this.cards[i] = this.cards[r];
this.cards[r] = tmp;
}
}
// カードデッキから、nで指定した枚数のCardオブジェクトを配列で取り出す
pop(n) {
const cards = [];
for (let i = 0; i < n; i++) {
cards.push(this.cards.pop());
}
return cards;
}
}
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
const image = new Image();
image.src = "cards.png";
image.addEventListener("load", () => {
const deck = new CardDeck(image);
deck.shuffle();
const cards = deck.pop(52);
cards.forEach((card, i) => {
const x = (i % 13) * 32 + 32;
const y = Math.floor(i / 13) * 64 + 32;
card.setLocation(x, y);
});
canvas.addEventListener("click", (e) => {
const rect = e.target.getBoundingClientRect();
const x = e.clientX - rect.left - 1;
const y = e.clientY - rect.top - 1;
cards.forEach(card => card.openIfContains(x, y));
});
const FPS = 20;
const frameTime = 1 / FPS;
let prevTimestamp = 0;
const update = (timestamp) => {
const elapsed = (timestamp - prevTimestamp) / 1000;
if (elapsed <= frameTime) {
requestAnimationFrame(update);
return;
}
prevTimestamp = timestamp;
cards.forEach(card => card.update());
context.clearRect(0, 0, 320, 320);
cards.forEach(card => card.render(context));
requestAnimationFrame(update);
};
update();
});
解説
各クラスは「トランプをめくる((横一列))」と同じですね。ちがうところは77~81行目です。
popメソッドで52枚すべてを取り出して配列にしています。そして、横に13枚並ぶようにx,yを設定しています。