あっぷりノート

Fix the Bits | あっぷり工房

旅、ギア、サプリ、マインド、トレーニング ── “走る”は創れる

#2 JavaScriptでアクションゲームを作る │ 敵、ダメージ判定、スコア得点

f:id:you_key69:20220212163452j:plain


走れない代わりに、走るゲームを創るプロジェクト、第2回。


→記念すべき第1回をまだご覧になっていない方はコチラからどうぞ

今回は敵キャラを登場させて、ダメージ判定スコアの積算を実装してみた。


ということで、さっそく本日の成果物をお届けしよう。

本日の成果物















  • 敵キャラが攻めてくる
  • 避けると100ポイント加算
  • 当たると停止・キャラ消滅
  • RESTARTボタンでリスタート

ぶつかったら「GAME OVER」って出せば?と子どもに指摘されました。

いいお客さんですw

本日のドット絵

メットール

f:id:you_key69:20220212163227j:plain

敵キャラのために採用したのは「メットール」。

ロックマン界のクリボー的存在である。



こやつをまずExcelでドット打ちし、png化したものを投入したというわけだ。

本日のソースコード(JavaScript)

<input type="button" onclick="restart()" value="RESTART" id="btn_Restart">
<canvas id="gamecanvas" width="420" height="360"></canvas>

<script>
var canvas, g;
var characterPosX, characterPosY, characterImage, characterR;
var enemyPosX, enemyPosY, enemyImage, enemySpeed, enemyR;
var speed,acceleration;
var score;

onload = function () {
  // 描画コンテキストの取得
  canvas = document.getElementById("gamecanvas");
  g = canvas.getContext("2d");
  // 初期化
  init();
  // 入力処理の指定
  document.onkeydown = keydown;
  document.onmousedown = mousedown;
  // ゲームループの設定 60FPS
  setInterval("gameloop()", 16);
};

function restart() {
	init();
}

function init() {
	characterPosX = 0;
	characterPosY = 300;
	characterR = 26;
	characterImage = new Image();
	characterImage.src = "https://cdn-ak.f.st-hatena.com/images/fotolife/y/you_key69/20220211/20220211130115.png";
	speed = 0;
	acceleration = 0;

	// 敵の表示位置・スピード
	enemyPosX = 630;
	enemyPosY = 310;
	enemyR = 18;
	enemyImage = new Image();
	enemyImage.src = "https://cdn-ak.f.st-hatena.com/images/fotolife/y/you_key69/20220211/20220211222731.png";
	enemySpeed = 5;
	
	// スコア初期化
	score = 0;
}

function keydown(e) {
	if (e.keyCode == 74) { // [J]押下時
		characterJump();
	}
}
function mousedown() {
	characterJump();
}
function characterJump() {
	speed = -20; // Y軸の移動スピード
	acceleration = 1.2; // 加速度(重力)
}

function gameloop() {
	update(); // キャラクターの移動
	draw(); // キャラクターの描画
}

function update() {
	speed = speed + acceleration;
	characterPosY = characterPosY + speed;
	
	// 初期移動 
	if (characterPosX < 70) {
		characterPosX = characterPosX + 5; // 1フレーム毎に2ドット移動
	}
	if (characterPosY > 300) {
		characterPosY = 300; // 着地
		speed = 0;
		acceleration = 0;
	}
	/*
	if (characterPosX > 540) {
		init(); // 右端まで行ったら戻る
	}
	*/
	
	// 敵が左端まで行ったら戻る
	enemyPosX -= enemySpeed;
	if (enemyPosX < -100) {
		enemyPosX = 630;
		score += 100; // 避けたら100pt加算
		//alert(score);
	}
	
	// 当たり判定
	var diffX = characterPosX - enemyPosX;
	var diffY = characterPosY - enemyPosY;
	var distance = Math.sqrt(diffX * diffX + diffY * diffY);
	if (distance < characterR + enemyR) {
		enemySpeed = 0;
		characterImage.src = "";
	}
}

function draw() {
	// 背景描画
	g.fillStyle = "rgb(153,204,51)";
	g.fillRect(0, 0, 420, 360);
	
	// キャラクタ描画
	g.drawImage(
		characterImage,
		characterPosX - characterImage.width / 2,
		characterPosY - characterImage.height / 2
	);
	
	// 敵描画
	g.drawImage(
		enemyImage,
		enemyPosX - enemyImage.width / 2,
		enemyPosY - enemyImage.height / 2
	);

	// スコア描画
	g.fillStyle = "rgb(255,255,255)";
	g.font = "16pt Arial";
	var scoreLabel = "SCORE : " + score;
	var scoreLabelWidth = g.measureText(scoreLabel).width;
	g.fillText(scoreLabel, 390 - scoreLabelWidth, 40); // 表示文言,位置指定(x,y)

}
</script>

本日の教材

教材はこれ↑

本日の学び

ダメージ判定に「三平方の定理」を使った。

f:id:you_key69:20220212164738j:plain
覚えてますか?

直角三角形の3辺が、a^2 + b^2 = c^2」という、ピタゴラスの定理とも呼ばれるやつである。


キャラの中心と敵の中心からお互いの半径が重なった場合に“当たり”と見なすために使うのだ。

人生で初めて三平方の定理を生活に活かすことができたので、「こんなの人生で使わないし!」と文系に進むことを決めた中3の頃の自分に云ってやりたい。

今後の展望

だいぶゲームらしさが出てきた。

ただ、相変わらず「走る」動作になっていないので、ちゃんと「走る」アクションを描画したい。


そしてせっかく走らせるならジャンプ動作もしっかり作りこみたいと思ってしまうのである。

完璧主義は大成しない良い例だ。


いや、大器晩成型だと主張しつづけてはいるんだけれども。

走る、を創ろう。