LoginSignup
2
4

PG0でゲームプログラミング

Last updated at Posted at 2024-02-05

はじめに

PG0は、プログラミング学習を目的としたプログラミング言語です。
PG0の詳細は『初心者用プログラミング言語「PG0」のススメ』を参照してください。

PG0はシンプルなプログラミング言語です。ゲームプログラミングで利用するのはPG0を拡張したPG0.5になります。

特徴

PG0は手続き型のプログラミング言語で、シングルスレッドで動作します。
ゲームプログラミングにおいても同様にシングルスレッドで動作し、イベント処理はありません。キー入力やタッチ入力はイベント処理ではなく入力状態を確認するAPIを利用します。
昔のBASICでゲームを作成していた感覚に近いかもしれません。

基本サンプル

描画の開始

PG0でゲームプログラミングをするにはPG0のWeb版で画面描画API(screen.js)をインポートします。
他に乱数を使う場合は数値処理API(math.js)をインポートします。
画面描画API、数値処理APIのリファレンスは以下になります。

以下のインポート文により利用することができます。

PG0
#import("lib/screen.js?v=1")
#import("lib/math.js?v=1")

描画を開始するにはstartScreen()を使います。

PG0
#import("lib/screen.js?v=1")
#import("lib/math.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

線の描画

線を描画するにはdrawLine()を使います。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

drawLine(100, 100, 500, 500, {"color": "#000", "width": 8})
sleep(3000)

image.png

四角の描画

四角を描画するにはdrawRect()を使います。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

drawRect(500, 300, 400, 300, {"color": "#00f", "fill": 1})
sleep(3000)

image.png

円の描画

円を描画するにはdrawCircle()を使います。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

drawCircle(500, 500, 400, {"color": "#00f", "fill": 1})
sleep(3000)

image.png

テキストの描画

テキストを描画するにはdrawText()を使います。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

drawText("Hello, world!", 640, 450, {"color": "#000", "fontstyle": "bold", "fontsize": 100})
sleep(3000)

image.png

色の判定

指定座標の色を判定するにはrgbToPoint()を使います。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

drawCircle(500, 500, 400, {"color": "#00f", "fill": 1})
var pt = rgbToPoint(500, 500)
drawText(pt, 0, 0, {"color": "#000", "fontsize": 50})
sleep(3000)

image.png

タッチ判定 (マウスクリック判定)

タッチされているかを判定するにはinTouch()を使います。
inTouch()の戻り値は連想配列で"touch"キーが1の場合はタッチされていることを示します。
"x"キーと"y"キーにはタッチ座標が入ります。

以下はタッチされた位置を丸で追いかけるサンプルです。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

while (1) {
	var t = inTouch()
	if (t["touch"]) {
		drawRect(0, 0, 1920, 1080, {"color": "#fff", "fill": 1})
		drawCircle(t["x"], t["y"], 100, {"color": "#000", "fill": 1})
	}
}

実際に動作するサンプルはこちら。
https://nakka.com/pg0/?cid=6a05e274-a1c3-4c52-9b18-fea72b9037d1

キー入力

入力されているキーを取得するにはinKey()を使います。
引数を指定するとキーの状態を返し、引数を指定しない場合は押されているキーを返します。

以下は入力されたキーを画面表示するサンプルです。

PG0
#import("lib/screen.js?v=1")

startScreen(1920, 1080, {"color": "#fff"})

while (1) {
	drawRect(0, 0, 1920, 1080, {"color": "#fff", "fill": 1})
	var k = inKey()
	if (length(k) > 0) {
		drawText(k, 100, 500, {"color": "#000", "fontsize": 50})
	}
	sleep(0)
}

実際に動作するサンプルはこちら。
https://nakka.com/pg0/?cid=871b5f39-ef8a-4e47-82c4-60967e4f8453

乱数(ランダム)の生成

乱数を生成するにはrandom()を使います。

以下は1から10までの乱数を30個生成するサンプルです。

PG0
#import("lib/math.js?v=1")

for (var i = 0; i < 30; i++) {
	print(int(random() * 10 + 1) + "\n")
}

実際に動作するサンプルはこちら。
https://nakka.com/pg0/?cid=7ee529f5-98df-4014-acc3-e29dcca94bd7

ゲームサンプル

上記の基本サンプルを組み合わせて作ったゲームとなります。
ランダムに円を描画し、自分は線で円に当たらないように右端に移動します。
自分は常に下がり続けますが、画面をタッチするかスペースキーを押している間は上がり続けます。

PG0
#import("lib/screen.js?v=1")
#import("lib/math.js?v=1")

// 初期化
var width = 1920, height = 1080
startScreen(width, height)

var level = 1
while (1) {
	// 画面のクリア
	drawRect(0, 0, width, height, {"color": "#fff", "fill": 1})
	// 障害物(青い丸)を配置
	for (var i = 0; i < 4; i++) {
		drawCircle(
			int(random() * (width - 500)) + 500,
			int(random() * height),
			int(random() * 100) + 100,
			{"color": "#00f", "fill": 1})
	}
	// レベルの描画
	drawText("Level." + level, 0, 0, {"fontsize": 40})
	// 初期化
	var x = 0, y = height / 2, move = 1

	// ゲームループ	
	while (1) {
		sleep(0)
		if (inTouch()["touch"] || inKey(" ")) {
			// タッチしている時は上昇
			move = -1
		} else {
			// 下降
			move = 1
		}
		// 前回座標の保存
		var px = x, py = y
		// 新しい座標
		x = x + level
		y = y + level * move
		// 移動先の色を取得
		var pt = rgbToPoint(x, y)
		// 自分を描画
		drawLine(px, py, x, y, {"color": "#000", "width": 8})
		if (x > width) {
			// 右端に到達するとクリアとなり、次のレベルに進む
			level++
			break
		}
		if (y < 0 || y > height || (pt["r"] == 0 && pt["g"] == 0 && pt["b"] != 0)) {
			// 上下の壁か障害物(青い丸)に当たるとゲームオーバー
			drawText("ゲームオーバー", 610, 492,
				{"fontstyle": "bold", "fontsize": 100, "color": "#aaa"})
			sleep(1000)
			// 次のゲームの開始のため、タッチするまで待機
			while (!inTouch()["touch"] && !inKey(" ")) {}
			level = 1
			break
		}
	}
}

image.png

実際に動作するサンプルはこちら。
https://nakka.com/pg0/?cid=7983e236-21b7-4c56-a533-1be229855c3f

その他のゲームサンプル

えだまめジャンプゲーム
https://nakka.com/pg0/?cid=fa0cdb93-dff4-4b63-aa3e-f0beefa2c90d

えだまめボールゲーム
https://nakka.com/pg0/?cid=37c2e44c-8e4a-4c5b-83dd-9e7f71a94884

テニスゲーム
https://nakka.com/pg0/?cid=6efa828f-ef80-440d-9acf-e41f066401a1

テトリス
https://nakka.com/pg0/?cid=f04397f0-b631-4354-b15f-e4e0c5d8fab1

シューティングゲーム
https://nakka.com/pg0/?cid=ee90d3f7-d603-48d0-be2b-c433f3ffbfe0

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4