ぬーぶのメモ帳

フリーゲームエンジン「Godot」でプログラム経験のない素人の備忘録 最近は色々な動作を考えて試すのが好き。

【Godot4】懲りずにマインスイーパーを作る2

盤面の準備
前回: 【Godot4】懲りずにマインスイーパーを作る1 - ぬーぶのメモ帳



前回素材やノードの紹介で終わりました。
今回はタイルマップの設定からステージのフロア部分を構築していきたいと思います。

今更ですがドクロに見えるでしょうか?
よろしければお付き合いください。


タイルマップの登録

まずは前回で紹介した黒白のタイルとナンバーの入った画像をタイルマップに登録します、タイルのサイズは64pxです。

・ TileSet の項目でタイルのサイズを設定


・ ファイルからタイルにドラッグ

タイルとして登録したい画像をタイル編集のウィンドウにドラッグするだけで登録の確認項目が出てきます。
特別な理由がない限り はい で全ての画像をタイルとして自動登録します。


・ タイル自動登録の確認

またアトラスの項目の下にIDがあります、これは登録した画像を1セットとしたタイルセットのIDになります、メソッドでタイルを指定する時などで必要になります。


・ タイルのIDは0から順に増えていく


黒白タイルの座標を取得

まず黒と白のタイルの座標を取得しようと思います。

と言っても方法はとても簡単
タイルマップのメソッド get_used_cells_by_id() を使用して座標を取得します。
メソッドについては ■ 以前の記事 でも説明していますので省略します。

ではそれらを格納するためコードを組み立てていきます。



コード

■ main.gd

extends Node2D

@onready var tile_map: TileMap = $TileMap
# 大量に生成される壁のコンテナ
@onready var wall_container: Node2D = $wall_container

# ステージの構成データ
@export var cell_size :int = 64
@export var stage_scale :Vector2i = Vector2i(10, 10)

# 盤面のデータを格納
var stage_array := []

# 白と黒のタイルを格納する配列
var floor_array := []
var wall_array := []


func _ready() -> void:
	get_stage()
	init_stage_array()
	set_stage()


func get_stage()-> void:
	# タイルマップの白黒タイルを取得
	floor_array = []
	wall_array = []
	wall_array = tile_map.get_used_cells_by_id(0,0,Vector2i.ZERO)
	floor_array = tile_map.get_used_cells_by_id(0,0,Vector2i(1, 0))

func init_stage_array()-> void:
	# 最初に全配列を初期化する
	for y in stage_scale.y:
		var y_array := []
		for x in stage_scale.x:
			y_array.append({"type": 0, "dig": false, "flag": false})
		stage_array.append(y_array)
	# 初期化した後、壁になる配列の値を変更
	for wall in wall_array:
		stage_array[wall.y][wall.x] = {"type": 99}
		
	print(stage_array) #後で消していい

func set_stage()-> void:
	for i in wall_array: # 壁の配列に壁のグラフィックを設置
		var wall = Sprite2D.new()
		wall.texture= load("自身のタイル画像")
		wall.global_position = i * cell_size
		wall.centered = false
		wall_container.add_child(wall)
		
	for i in floor_array:
		tile_map.set_cell(0, i, 1, Vector2i.ZERO)



 
■ 黒白タイルを取得

func get_stage()-> void:
	# タイルマップの白黒タイルを取得
	floor_array = []
	wall_array = []
	wall_array = tile_map.get_used_cells_by_id(0,0,Vector2i.ZERO)
	floor_array = tile_map.get_used_cells_by_id(0,0,Vector2i(1, 0))

まず定義したフロアと壁用の配列に
先ほどの get_used_cells_by_id() を使いそれぞれのタイルの座標を取得します。


■ 盤面を初期化

func init_stage_array()-> void:
	# 最初に全配列を初期化する
	for y in stage_scale.y:
		var y_array := []
		for x in stage_scale.x:
			y_array.append({"type": 0, "dig": false, "flag": false})
		stage_array.append(y_array)
	# 初期化した後、壁になる配列の値を変更
	for wall in wall_array:
		stage_array[wall.y][wall.x] = {"type": 99}
		
	print(stage_array) #後で消していい

次にマップ管理用の配列のデータを初期化します。
この時 {"type": 0, "dig": false, "flag": false} と辞書を使っています。
それぞれの床タイルに辞書で危険度、既に掘った所か、地雷マーカーを設置したか の判定を記録させます。



■ フロアと壁を配置

func set_stage()-> void:
	for i in wall_array: # 壁の配列に壁のグラフィックを設置
		var wall = Sprite2D.new()
		wall.texture= load("自身のタイル画像")
		wall.global_position = i * cell_size
		wall.centered = false
		wall_container.add_child(wall)
		
	for i in floor_array:
		tile_map.set_cell(0, i, 1, Vector2i.ZERO)

最後にフロアと壁の座標へグラフィックを実装していきます。
今回壁を Sprite2D で作成したのですが、大量にノードが追加されてしまうのでタイルマップで良かったかなあと後悔しました。


まとめ

今回はゲーム盤面の基礎を作成しました、タイルマップのメソッドを使うことで楽にステージ構築をできました。

もっと技術のある方ですとタイルマップを利用してタクティクスゲームでのキャラ配置や、アクションゲームで棘など障害物の指定をするのに見た事があります。

自分も何か面白い使い方を思いつきたいものです。
次回は爆弾の設置と、爆弾周りの数字設置まで行けたらいいなあと思っています。


今回はここまでになります、次回もお付き合いいただけると嬉しいです



■ 次 :【Godot4】懲りずにマインスイーパーを作る3 - ぬーぶのメモ帳