はじめに
Raspberry Piは、教育目的で設計された小型コンピュータです。
低電力であること、手のひらサイズでコンパクトであることが、最大の特徴です。そのため、連続稼働させる使い方がとても適しています。例えば、
- Webサーバー(ウェブサーバー):この記事を読めばできます!
- 簡易ゲームの公開:この記事を読めばできます!
- ファイルサーバー:この記事を読めばインストールだけでできます!
- 録画サーバー
などがあります💡
今回、Vesonn JPの「Raspberry Pi5 16gb セット技適済み」を用いて、ローカルWebサーバー(ウェブサーバー)を立ち上げ、簡単なゲーム(ブロック崩し)を作ってみました!
ローカルではありますが、家族や友人とスコアアタックなど楽しめそうです!
作りこめば、対戦できるゲームを作ることもできるので遊びの可能性は無限大です!✨
開封の儀
外箱を開けると、下記のようなセットが入っています。内容物は簡単に、「Raspberry Pi5 16gb本体」、「電源アダプタ―」、「HDMIケーブル」、「SDカード&リーダー」、「ケース&クーラー」等になります。そのため、すぐにインストールと電源につないでディスプレイ出力できます。さらに、ケースによる保護と冷却が行えます。
ケースとクーラーはこれが入っています。

最初に、SDカードへRaspberry Pi OSをインストールしよう
まず、下記の付属のSDカードリーダーを用いて、お持ちのPCでOSをインストールします。OSは、Raspberry Piを動作させるために必要なシステムです。

PCから、Raspberry Pi OS – Raspberry Piにアクセスして、Raspberry Pi Imagerをダウンロードしてください(Download for Windows)。ダウンロードしたら、指示に従ってインストールしてください。
重要:「Would you like to apply OS customization settings?」のポップアップ時は、「設定を編集する」をクリックして、下記を設定されることをオススメします。
- 一般 タブ
- ホスト名(例:raspberrypi)
- ユーザー名とパスワードを設定する
- ユーザー名(例:risupuresso)
- パスワード(解説:root権限に入る際に必要になりますので設定してください)
- ユーザー名とパスワードを設定する
- Wi-Fiを設定する
- SSID(解説:通常はWi-Fiのルーターに記載があります)
- パスワード(解説:通常はWi-Fiのルーターに記載があります)
- Wi-Fiを使う国(例:JP)
- ロケール設定をする
- タイムゾーン(例:Asia/Tokyo)
- キーボードレイアウト(例:jp)
- ホスト名(例:raspberrypi)
- オプション タブ
- SSHを有効化する
- パスワード認証を使う
- SSHを有効化する
上記の設定を行うことで、Raspberry Pi 5初回起動時の手間がなくなり、最初からWi-Fiに接続され、さらには、外部からSSH接続できるようになります。SSH接続できるということは、SFTPクライアントを使用すればファイルサーバーとして機能するということです。
最後に、microSDカードをRaspberry Pi 5本体に差し込みます。向きを間違えないよう注意ください。

接続してRaspberry Piを起動しよう
下記のように接続していきます。電源アダプタをコンセントにまだ刺さないでください。
具体的には、本体左下部に電源アダプタ、その右隣にmicroHDMIケーブル(反対側のHDMIはディスプレイに接続)、本体右上部にキーボード&マウスをUSB接続します。

あと一息です!電源アダプタをコンセントに繋ぐと、Raspberry Pi 5は自動で起動します!

補足:ファイルサーバーを使うには? (SFTP) / SSH接続するには?
右上のWi-Fiマークにマウスカーソルを合わせると、IPアドレスが表示されます。SFTPクライアント(例えば、WindowsであればWinSCP、iPhoneであればDocuments by Readdleなど)から、Raspberry Pi 5のファイルにアクセス出来ます。
例えばDocuments by Readdleであれば、インストール時に設定した、ホスト:IPアドレス、ログイン:ユーザー名、パスワードを入力すれば、Raspberry Pi 5のファイルにアクセスできます。
ターミナル(WindowsであればPowerShell、iPhoneであればiSHなど)からSSH接続する時は、下記のようなコマンドを使用してください(ユーザー名:risupresso、IPアドレス:192.168.0.5の場合)。
ssh risupresso@192.168.0.5
接続先のサーバーが正しいか確認される(fingerprint)ので問題なければyes、その後、パスワードを入力すると接続できます。
ローカルWebサーバーを立てて、簡単なゲーム(ブロック崩し)を公開しよう
まず、左上のターミナルのマーク[>_]をクリックし、ターミナルを起動してください。
/var/www/htmlディレクトリを作成します。
sudo mkdir -p /var/www/html
そのまま、作成したディレクトリに移動します。
cd /var/www/html
次に、index.htmlファイルを作成します。
sudo touch index.html
index.htmlファイルをテキストエディタで編集します。
sudo nano index.html
下記のコードをコピーして、右クリックでpaste(貼り付け)します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ブロック崩しデモ</title>
<style>
body { margin:0; background:#222; color:#fff; text-align:center; }
#gameCanvas {
background: #000;
display: block; margin: 0 auto;
max-width: 100%; height: auto;
touch-action: none;
}
#info { margin: 8px; font-size: 1rem; }
</style>
</head>
<body>
<h1>ブロック崩しデモ</h1>
<div id="info">
Level: <span id="level">1</span>
Score: <span id="score">0</span>
Lives: <span id="lives">3</span>
</div>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script>
(() => {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const levelEl = document.getElementById('level');
const scoreEl = document.getElementById('score');
const livesEl = document.getElementById('lives');
// ゲームステート
let level = 1, score = 0, lives = 3;
let bricksLeft = 0; // ← 追加
let ballX = canvas.width/2, ballY = canvas.height-30;
let ballDX = 4, ballDY = -4, ballRadius = 8;
const paddleHeight = 12, paddleWidth = 100;
let paddleX = (canvas.width - paddleWidth) / 2;
let rightPressed = false, leftPressed = false;
const brickRowCountBase = 3;
const brickColumnCount = 7;
const brickWidth = 75, brickHeight = 20;
const brickPadding = 10, brickOffsetTop = 50, brickOffsetLeft = 35;
let bricks = [];
// ブロック初期化
function initBricks() {
const rows = brickRowCountBase + level - 1;
bricksLeft = rows * brickColumnCount; // ← ここでセット
bricks = [];
for (let r = 0; r < rows; r++) {
bricks[r] = [];
for (let c = 0; c < brickColumnCount; c++) {
const hue = Math.floor(360 * c / brickColumnCount);
bricks[r][c] = {
x:0, y:0, status:1,
color: `hsl(${hue}, 70%, 60%)`
};
}
}
}
function drawBricks() {
for (let r = 0; r < bricks.length; r++) {
for (let c = 0; c < brickColumnCount; c++) {
const b = bricks[r][c];
if (!b.status) continue;
const x = c*(brickWidth+brickPadding) + brickOffsetLeft;
const y = r*(brickHeight+brickPadding) + brickOffsetTop;
b.x = x; b.y = y;
ctx.fillStyle = b.color;
ctx.fillRect(x, y, brickWidth, brickHeight);
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI*2);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.fillStyle = '#0f0';
ctx.fillRect(paddleX, canvas.height - paddleHeight - 10, paddleWidth, paddleHeight);
}
function drawInfo() {
levelEl.textContent = level;
scoreEl.textContent = score;
livesEl.textContent = lives;
}
// ブロック衝突判定
function collisionDetection() {
for (let r = 0; r < bricks.length; r++) {
for (let c = 0; c < brickColumnCount; c++) {
const b = bricks[r][c];
if (!b.status) continue;
if (
ballX > b.x && ballX < b.x + brickWidth &&
ballY > b.y && ballY < b.y + brickHeight
) {
ballDY = -ballDY;
b.status = 0;
bricksLeft--; // ← カウントダウン
score += 10;
// 全破壊で次レベル
if (bricksLeft === 0) {
level++;
ballDX *= 1.1; ballDY *= 1.1;
initBricks();
}
}
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks(); drawBall(); drawPaddle(); drawInfo();
collisionDetection();
// 壁バウンス
if (ballX + ballDX > canvas.width - ballRadius || ballX + ballDX < ballRadius) {
ballDX = -ballDX;
}
if (ballY + ballDY < ballRadius) {
ballDY = -ballDY;
}
// パドル判定
else if (ballY + ballDY > canvas.height - ballRadius - paddleHeight - 10) {
if (ballX > paddleX && ballX < paddleX + paddleWidth) {
const paddleCenter = paddleX + paddleWidth/2;
const relX = (ballX - paddleCenter) / (paddleWidth/2);
const maxA = 75 * Math.PI/180;
const speed = Math.hypot(ballDX, ballDY);
const ang = relX * maxA;
ballDX = speed * Math.sin(ang);
ballDY = -speed * Math.cos(ang);
} else {
lives--;
if (!lives) {
alert('Game Over');
document.location.reload();
return;
} else {
ballX = canvas.width/2; ballY = canvas.height-30;
ballDX = 4; ballDY = -4;
paddleX = (canvas.width - paddleWidth)/2;
}
}
}
// 位置更新
ballX += ballDX;
ballY += ballDY;
// パドル移動
if (rightPressed && paddleX < canvas.width - paddleWidth) paddleX += 7;
if (leftPressed && paddleX > 0) paddleX -= 7;
requestAnimationFrame(draw);
}
// イベント登録(キーボード/タッチ/マウス)
document.addEventListener('keydown', e => {
if (e.key==='Right'||e.key==='ArrowRight') rightPressed = true;
if (e.key==='Left' ||e.key==='ArrowLeft') leftPressed = true;
});
document.addEventListener('keyup', e => {
if (e.key==='Right'||e.key==='ArrowRight') rightPressed = false;
if (e.key==='Left' ||e.key==='ArrowLeft') leftPressed = false;
});
canvas.addEventListener('touchmove', e => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const tx = (e.touches[0].clientX - rect.left) * scaleX;
paddleX = Math.max(0, Math.min(tx - paddleWidth/2, canvas.width - paddleWidth));
}, { passive: false });
document.addEventListener('mousemove', e => {
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const mx = (e.clientX - rect.left) * scaleX;
if (mx > 0 && mx < canvas.width) paddleX = mx - paddleWidth/2;
});
// 初期化&開始
initBricks();
draw();
})();
</script>
</body>
</html>
Ctrl+OのあとEnterキーで保存してください。その後Ctrl+Xで、nanoを終了します。
最後に、Webサーバーを立ち上げます。例としてポート番号8000としています。
python3 -m http.server 8000
あとはブラウザで、http://IPアドレス:8000とすれば、同一ネットワーク内であればアクセスでき、簡単なゲーム(ブロック崩し)で遊ぶことができます!✨

まとめ
Vesonn JPの「Raspberry Pi5 16gb セット技適済み」は、簡単にセットアップでき、実用性も高いので一台持っていると便利でしょう。
Webサーバー、ファイルサーバー、プログラミングなどが、省電力&コンパクトで行えます!✨
コメント