今日のエッセイ
気まぐれゲーム作りです。
ゲームの王道ブロック崩しです。
パドルを左右に動かしてボールを弾き、上のブロックを消していきます。
とてもシンプルですが、プログラミングすると奥が深いです。
ゲームをスタートすると、パドルの上にボールが少し浮いた形で乗っています。
左右に動かして、好きな位置でスペースキーを押すと、ボールが発射されます。
後は、ボールが落ちないように、パドルで弾くだけです。
左上はスコア表示で、ブロックが一つ消えるごとに100点入ります。
右上はゲームレベルです。
ブロックを全て消すと、ブロックがリセットされて、戻ります。
その時にレベル表示が変わり、ボールのスピードがアップします。
ボールが落ちない限りゲームが続き、落ちるとゲームが止まってゲームオーバーです。
その時にハイスコアが表示されます。
タイトル:「Block-Breaker's」
プログラムはJavaScriptです。
HTMLの中に埋め込む形です。
<script>タグ内がJavaScriptとなります。
画像ファイルがなくても遊べます。
function resetGame() { //ゲームをリセットする
// ballをリセットする
ball.x = canvas.width / 2;
ball.y = 440;
ball.speedX = speed; //speedX:5
ball.speedY = speed; //speedY:-5
// paddleをリセットする
paddle.x = canvas.width / 2 - paddle.width / 2;
paddle.y = 460;
// blockをリセットする
blocks = [];
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 10; col++) {
blocks.push({
x: col * blockWidth + 10,
y: row * blockHeight + 50,
width: blockWidth,
height: blockHeight,
color: getRandomColor(),
visible: true
});
}
}
count = 30;
space = false;
}
ゲームをリセットするコードです。
スタート時にボールやパドルの位置をセットします。
function resetBlock() { //blockをリセットする
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 10; col++) {
blocks.push({
x: col * blockWidth + 10,
y: row * blockHeight + 50,
width: blockWidth,
height: blockHeight,
color: getRandomColor(),
visible: true
});
}
}
count = 30;
}
blockを全部消去した後に再度セットする関数です。
変数countは、blockの数を表しています。
function moveBall() { //ボールの動き
ball.x += ball.speedX;
ball.y += ball.speedY;
// ボールが左右の壁に当たった時の判定
if (ball.x - ball.radius < 0 || ball.x + ball.radius > canvas.width) {
ball.speedX = -ball.speedX;
}
// ボールが上の壁に当たった時の判定
if (ball.y - ball.radius < 0) {
ball.speedY = -ball.speedY;
}
// ボールが下の壁に当たった時の判定
if (ball.y + ball.radius > canvas.height) {
drawGameend(); //ゲームオーバー表示
clearinterval(); //ゲームを止める時
//ball.speedY = -ball.speedY; //落下無し無限ラリー
}
}
ボールの動きを設定する関数です。
clearinterval()はゲームを止める関数です。
ball.speedY=-ball.speedYを使うと落下しても跳ね返り、無限にラリーができます。
練習用です。
どんどん上がっていくスピードを体感してみてください。
これを使う時は、clearinterval()とdrawGameend()をコメントアウトします。
function movePaddle() { //paddleの動き
if (leftKeyDown) { //left key
paddle.x -= paddle.speed;
if(space==false){ball.x -= paddle.speed;}
if (paddle.x < 0) {
paddle.x = 0;
if(space==false){ball.x=paddle.width/2;}
}
}
if (rightKeyDown) { //right key
paddle.x += paddle.speed;
if(space==false){ball.x += paddle.speed;}
if (paddle.x + paddle.width > canvas.width) {
paddle.x = canvas.width - paddle.width;
if(space==false){ball.x=canvas.width-paddle.width/2;}
}
}
if (spaceKeyDown) { //space key
ball.speedX=speed+sp;
ball.speedY=-speed+sp;
}
}
パドルの動きを設定する関数です。
ボールを発射するまでは、パドルについていくようになっています。
function checkCollisions() { //衝突判定
// ボールがパドルに当たった時の判定
if (collision(ball, paddle)) {
ball.speedY = -ball.speedY;
}
// ボールがブロックに当たった時の判定
for (var i = 0; i < blocks.length; i++) {
if (collision(ball, blocks[i]) && blocks[i].visible) {
ball.speedY = -ball.speedY;
blocks[i].visible = false;
score+=100;
count-=1; //blockの個数判定
if(count == 0){ //blockを全部消した後の処理
setTimeout(resetBlock, 1500); //指定ミリ秒後にblockを表示する
lv += 1;
if(ball.speedX < 0){ //ballのスピード調整
ball.speedX -= 1;}
else{ball.speedX += 1;}
if(ball.speedY > 0){
ball.speedY +=1;}
else{ball.speedY -= 1;}
}
}
}
}
衝突判定についての関数です。
全体のソースコードです。
<!DOCTYPE html>
<html>
<head>
<title>Block-Breaker's</title>
<style>
#gameCanvas {
border: 2px solid #FFAA00;
background-color: #FFFF88;
}
</style>
</head>
<body onload="startGame()">
<canvas id="gameCanvas" width="520" height="480"></canvas>
<script>
var canvas;
var context;
var ball = {//speedX:5,speedY:5
x: 320,
y: 240,
radius: 10,
speedX: 5,
speedY: 5
};
var paddle = {
x: 250,
y: 460,
width: 100,
height: 20,
speed: 15//speed:10
};
var blocks = [];
var blockWidth = 50;
var blockHeight = 20;
var score = 0;
var count = 30;
var space = false;
var clear = false;
var speed = 0;
var sp = 5;
var lv = 1;
function startGame() {
canvas = document.getElementById("gameCanvas");
context = canvas.getContext("2d");
document.addEventListener("keydown", handleKeyDown);
document.addEventListener("keyup", handleKeyUp);
resetGame();
setInterval(updateGame, 20);
}
function resetGame() { //ゲームをリセットする
// ballをリセットする
ball.x = canvas.width / 2;
ball.y = 440;
ball.speedX = speed; //speedX:5
ball.speedY = speed; //speedY:-5
// paddleをリセットする
paddle.x = canvas.width / 2 - paddle.width / 2;
paddle.y = 460;
// blockをリセットする
blocks = [];
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 10; col++) {
blocks.push({
x: col * blockWidth + 10,
y: row * blockHeight + 50,
width: blockWidth,
height: blockHeight,
color: getRandomColor(),
visible: true
});
}
}
count = 30;
space = false;
}
function resetBlock() { //blockをリセットする
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 10; col++) {
blocks.push({
x: col * blockWidth + 10,
y: row * blockHeight + 50,
width: blockWidth,
height: blockHeight,
color: getRandomColor(),
visible: true
});
}
}
count = 30;
}
function updateGame() { //ゲームの更新
context.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
drawPaddle();
drawBlocks();
drawScore();
drawLv();
moveBall();
movePaddle();
checkCollisions();
}
function drawBall() { //ballを描画
context.beginPath();
context.arc(ball.x, ball.y, ball.radius, 0, 2 * Math.PI);
context.fillStyle = "#FFBB99";
context.fill();
context.closePath();
}
function drawPaddle() { //paddleを描画
context.fillStyle = "#00FF99";
context.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
function drawBlocks() { //blockを描画
for (var i = 0; i < blocks.length; i++) {
if (blocks[i].visible) {
context.fillStyle = blocks[i].color;
context.fillRect(blocks[i].x, blocks[i].y, blocks[i].width, blocks[i].height);
}
}
}
function drawScore() { //スコア表示
context.fillStyle = "#00AAFF";
context.font = "30px Arial";
context.fillText("1P:" + score, 10, 25);
}
function drawGameend() { //ゲームオーバーの表示
context.fillStyle = "#FFAAAA";
context.font = "30px Arial";
context.fillText("Game Over. Your Hi score is "+ score, 30, 220);
}
function drawLv() { //ゲームレベル表示
context.fillStyle = "#00FF88";
context.font = "30px Arial";
context.fillText("Lv: "+ lv, 430, 25);
}
function moveBall() { //ボールの動き
ball.x += ball.speedX;
ball.y += ball.speedY;
// ボールが左右の壁に当たった時の判定
if (ball.x - ball.radius < 0 || ball.x + ball.radius > canvas.width) {
ball.speedX = -ball.speedX;
}
// ボールが上の壁に当たった時の判定
if (ball.y - ball.radius < 0) {
ball.speedY = -ball.speedY;
}
// ボールが下の壁に当たった時の判定
if (ball.y + ball.radius > canvas.height) {
drawGameend(); //ゲームオーバー表示
clearinterval(); //ゲームを止める時
//ball.speedY = -ball.speedY; //落下無し無限ラリー
}
}
function movePaddle() { //paddleの動き
if (leftKeyDown) { //left key
paddle.x -= paddle.speed;
if(space==false){ball.x -= paddle.speed;}
if (paddle.x < 0) {
paddle.x = 0;
if(space==false){ball.x=paddle.width/2;}
}
}
if (rightKeyDown) { //right key
paddle.x += paddle.speed;
if(space==false){ball.x += paddle.speed;}
if (paddle.x + paddle.width > canvas.width) {
paddle.x = canvas.width - paddle.width;
if(space==false){ball.x=canvas.width-paddle.width/2;}
}
}
if (spaceKeyDown) { //space key
ball.speedX=speed+sp;
ball.speedY=-speed+sp;
}
}
function checkCollisions() { //衝突判定
// ボールがパドルに当たった時の判定
if (collision(ball, paddle)) {
ball.speedY = -ball.speedY;
}
// ボールがブロックに当たった時の判定
for (var i = 0; i < blocks.length; i++) {
if (collision(ball, blocks[i]) && blocks[i].visible) {
ball.speedY = -ball.speedY;
blocks[i].visible = false;
score+=100;
count-=1; //blockの個数判定
if(count == 0){ //blockを全部消した後の処理
setTimeout(resetBlock, 1500); //指定ミリ秒後にblockを表示する
lv += 1;
if(ball.speedX < 0){ //ballのスピード調整
ball.speedX -= 1;}
else{ball.speedX += 1;}
if(ball.speedY > 0){
ball.speedY +=1;}
else{ball.speedY -= 1;}
}
}
}
}
function collision(object1, object2) {
if (object1.x < object2.x + object2.width && object1.x + object1.radius * 2 > object2.x &&object1.y < object2.y + object2.height && object1.y + object1.radius * 2 > object2.y) {
return true;
} else {
return false;
}
}
function getRandomColor() { //ランダムでblockの色を決定する
var letters = "0123456789ABCDEF";
var color = "#";
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
var leftKeyDown = false;
var rightKeyDown = false;
var spaceKeyDown = false;
function handleKeyDown(event) { //Keyを押した時
//kyecode 37:Left 39:Right 38:Up 40:Down 32:Space
if (event.keyCode == 37) { // Key Left
leftKeyDown = true;
} else if (event.keyCode == 39) { // Key Right
rightKeyDown = true;
} else if (event.keyCode == 32) { // Key Space
spaceKeyDown = true;
space = true;
}
}
function handleKeyUp(event) { //Keyを離した時
if (event.keyCode == 37) { // Key Left
leftKeyDown = false;
} else if (event.keyCode == 39) { // Key Right
rightKeyDown = false;
} else if (event.keyCode == 32) { // Key Space
spaceKeyDown = false;
}
}
</script>