JavaScript»体験講座 体験講座 ゲームをつくろう もぐらたたき編(ゲームエンジン使用)
ファイル名: js-trial/quest_01109.html
タイトル画面の作成
タイトル画面を表示します。
// スタートボタン
class StartButton extends Actor {
constructor() {
super(110, 150, new Rect(0, 0, 100, 25));
this.w = 100;
this.h = 25;
}
render(context) {
context.fillStyle = "#fff";
context.font = "25px monospace";
context.textAlign = "center"
context.fillText("START", 160, this.y + this.h);
}
}
// タイトル画面
class MoguTitleScene extends Scene {
constructor() {
super();
this.startButton = new StartButton();
this.add(this.startButton);
}
renderBackground(context) {
super.renderBackground(context);
context.fillStyle = "#000";
context.fillRect(0, 0, this.game.width, this.game.height);
}
}
// ゲームスタート
window.onload = () => {
const game = new Game("もぐらたたき", 320, 345, 60);
game.loadAssets().then(() => {
game.changeScene(new MoguTitleScene());
game.start();
});
};
STARTボタンを押したらゲーム画面に変わる
ゲーム画面と、背景画像を用意して、
// ゲームスタートの手前にこれを追加
class MoguMainScene extends Scene {
constructor(backgroundImage) {
super();
this.backgroundImage = backgroundImage;
}
renderBackground(context) {
super.renderBackground(context);
context.drawImage(this.backgroundImage, 0, 25, 320, 320);
}
}
// ゲームスタート
window.onload = () => {
const game = new Game("もぐらたたき", 320, 345, 60);
// 画像読込
game.addImage("bg", "bg.png");
game.loadAssets().then(() => {
...
STARTボタンがクリックされたときにゲーム画面に切り替えます。
class StartButton extends Actor {
constructor() {
super(110, 150, new Rect(0, 0, 100, 25));
this.w = 100;
this.h = 25;
}
// スタートボタンにこれを追加
onClick(game, x, y) {
if (!this.startedAt) {
this.startedAt = this.tick;
}
}
// これも追加
update(game, input) {
if (this.startedAt) {
game.changeScene(new MoguMainScene(game.image.bg));
}
}
...
モグラをランダムに出現させる
12匹のモグラを用意し、並べます。
render(context) {
context.fillStyle = "#fff";
context.font = "25px monospace";
context.textAlign = "center"
context.fillText("START", 160, this.y + this.h);
}
}
// スタートボタンの下にこれを追加
class Mogu extends Actor {
constructor(image, x, y) {
super(x, y, new Rect(0, 0, 80, 85));
this.image = image;
this.visible = false;
}
update(game, input) {
if (game.tick % game.fps === 0) {
this.visible = Math.random() >= 0.7;
}
}
render(context) {
if (!this.visible) {
return;
}
const x = 0;
const y = 0;
context.drawImage(this.image, x, y, 80, 85, this.x, this.y, 80, 85);
}
}
class MoguMainScene extends Scene {
constructor(backgroundImage) {
super();
this.backgroundImage = backgroundImage;
}
// MoguMainSceneの中にこれを追加
onStart(game) {
for (let i = 0; i < 12; i++) {
const x = (i % 4) * 80;
const y = Math.floor(i / 4) * 85 + 85;
const mogu = new Mogu(game.image.mogu, x, y);
this.add(mogu);
}
}
...
window.onload = () => {
const game = new Game("もぐらたたき", 320, 345, 60);
game.addImage("bg", "bg.png");
// モグラ画像読込
game.addImage("mogu", "mogu.png");
game.loadAssets().then(() => {
game.changeScene(new MoguTitleScene());
game.start();
});
};
たたかれたモグラを泣かす
class Mogu extends Actor {
constructor(image, x, y) {
super(x, y, new Rect(0, 0, 80, 85));
this.image = image;
// これを追加
this.hit = false;
this.visible = false;
}
// これを追加
onClick(game, x, y) {
if (this.visible && !this.hit) {
this.hit = true;
this.dispatchEvent("hit", new GameEvent(this));
}
}
update(game, input) {
if (game.tick % 60 === 0) {
// これを追加
this.hit = false;
this.visible = Math.random() >= 0.7;
}
}
render(context) {
if (!this.visible) {
return;
}
// ここを変更
const x = this.hit ? 80 : 0;
const y = 0;
context.drawImage(this.image, x, y, 80, 85, this.x, this.y, 80, 85);
}
}
スコアをつける
render(context) {
if (!this.visible) {
return;
}
const x = this.hit ? 80 : 0;
const y = 0;
context.drawImage(this.image, x, y, 80, 85, this.x, this.y, 80, 85);
}
}
// Moguの下にこれを追加
class ScoreLabel extends Actor {
constructor(x, y) {
super(x, y);
this.score = 0;
}
addScore(mogu) {
this.score += 10;
}
render(context) {
context.fillStyle = "rgb(0, 0, 0)";
context.font = "23px monospace";
context.fillText("SCORE: " + this.score, this.x, this.y);
}
}
onStart(game) {
// MoguMainSceneのonStartの中にこれを追加
this.scoreLabel = new ScoreLabel(0, 20);
this.add(this.scoreLabel);
for (let i = 0; i < 12; i++) {
const x = (i % 4) * 80;
const y = Math.floor(i / 4) * 85 + 85;
const mogu = new Mogu(game.image.mogu, x, y);
// これも追加
mogu.addEventListener("hit", e => this.scoreLabel.addScore(e.target));
this.add(mogu);
}
}
モグラをたたいたときの効果音をならす
window.onload = () => {
const game = new Game("もぐらたたき", 320, 345, 60);
game.addImage("bg", "bg.png");
game.addImage("mogu", "mogu.png");
// 効果音の読込. hit01.mp3 ~ hit09.mp3 まで、好きなのを使ってね
game.addAudio("hit", "hit09.mp3", 5);
game.loadAssets().then(() => {
...
onClick(game, x, y) {
if (this.visible && !this.hit) {
// MoguのonClickの中にこれを追加
game.audio.hit.play(0.2);
this.hit = true;
this.dispatchEvent("hit", new GameEvent(this));
}
}
BGMをならす
window.onload = () => {
const game = new Game("もぐらたたき", 320, 345, 60);
game.addImage("bg", "bg.png");
game.addImage("mogu", "mogu.png");
game.addAudio("hit", "hit09.mp3", 5);
// BGMの読込. bgm01.mp3 ~ bgm04.mp3 まで、好きなのを使ってね
game.addAudio("bgm", "bgm01.mp3");
game.loadAssets().then(() => {
...
onClick(game, x, y) {
if (!this.startedAt) {
this.startedAt = this.tick;
// StartButtonのonClickの中にこれを追加
game.loadAudios();
}
}
onStart(game) {
// MoguMainSceneのonStartの中にこれを追加
game.audio.bgm.playEndless(0.2);
this.scoreLabel = new ScoreLabel(0, 20);
this.add(this.scoreLabel);
ときどきレアモグラを出現させる
class Mogu extends Actor {
constructor(image, x, y) {
super(x, y, new Rect(0, 0, 80, 85));
this.image = image;
this.hit = false;
this.visible = false;
// これを追加
this.rare = false;
}
// 中略
update(game, input) {
if (game.tick % game.fps === 0) {
this.hit = false;
this.visible = Math.random() >= 0.7;
// これを追加. 0.99以上になる確率は1%. 0.99を別の値に変えたらレア出現率が変わる
this.rare = Math.random() >= 0.99;
}
}
render(context) {
if (!this.visible) {
return;
}
const x = this.hit ? 80 : 0;
// ここを変更. 85を170や255にするとレアモグラの色が変わる
const y = this.rare ? 85 : 0;
context.drawImage(this.image, x, y, 80, 85, this.x, this.y, 80, 85);
}
}
class ScoreLabel extends Actor {
constructor(x, y) {
super(x, y);
this.score = 0;
}
addScore(mogu) {
// ここを変更. 500はレアモグラをたたいたときの点数
this.score += mogu.rare ? 500 : 10;
}
...
※ このサンプルで使用したオーディオファイルは下記サイトからお借りしました。