godot

L012 ゲーム構成 (エネミー)


Godot4.2についての覚書です。

エネミーをスポーンさせます。

エネミー(敵)キャラクターに限らず、オブジェクトを画面内に発生させる場合の参考です。

ベース

作成物

マウスでクリックすると消えます。
3つ消すと再度スポーンします。

mainのシーンにenemyを追加していきます。

main.gdのスクリプトは以下です。
enemyシーンを呼び出して追加します。
mainシーン内のノード名enemyがなくなると、再度enemyを追加します。
(形式がPythonに似ているので表示スタイルにしています)

extends Node2D

var xPos = 250
var yPos = 100
var Enemy = preload("res://enemy.tscn")

func _process(delta):

	var cnt = 0 #enemyのカウント
	
	#-----ツリーのノード名を検索
	for child in get_children():
		print(child.name)
		if "Enemy" in child.name:
			cnt += 1
			#print("Enemy" )
	print("個数:" + str(cnt))
	if cnt == 0:
		#print("NoEnemy" )
		pass
	#----------------------
	
	#----エネミーが0になった場合にスポーンする
	if cnt == 0:
	#if Common.countEne == 0:
		for i in range(3):
			var Enemy = Enemy.instantiate()
			Enemy.setPos(position.x + i*xPos+100, position.y + yPos)
			Enemy.name = "Enemy" + str(i)
			self.add_child(Enemy)

enemy.gdのスクリプトは以下です。

extends Area2D

func setPos(x, y):
	position = Vector2(x, y)

func _on_input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		# マウスの入力があった
		if event.is_pressed():
			# オブジェクトを消す
			queue_free()

共通ファイル(r1)

定数や共有したい変数を別のファイルに設定します。

 ベースでは、シーン内のノード名を調べて、enemyノードが無くなった場合に追加します。
ここでは、追加したカウントを保持して追加します。
 モデルのシーンはmainとenemyからなります。
 両シーンで使われる変数(emCount:int)とそれを記述するスクリプトファイル(Common.gd)を追加します。

Common.gdは メニュー>プロジェクト設定>自動読み込み でインポートします。

作業は1:30ごろから(前半はgithubの登録)

Common.gd

var emCount:int

main.gd(使用しない部分はコメントアウト)

extends Node2D

var xPos = 250
var yPos = 100
var Enemy = preload("res://enemy.tscn")

func _process(delta):

	#var cnt = 0 #enemyのカウント
	#
	##-----ツリーのノード名を検索
	#for child in get_children():
		##print(child.name)
		#if "Enemy" in child.name:
			#cnt += 1
			##print("Enemy" + str(cnt))
	#print("個数:" + str(cnt))
	#if cnt == 0:
		##print("NoEnemy" )
		#pass
	##----------------------
	
	#----エネミーが0になった場合にスポーンする
	#if cnt == 0:
	if Common.emCount == 0:
		for i in range(3):
			var Enemy = Enemy.instantiate()
			Enemy.setPos(position.x + i*xPos+100, position.y + yPos)
			Enemy.name = "Enemy" + str(i)
			self.add_child(Enemy)
			
			Common.emCount += 1

enemy.gd(emCount追加)

extends Area2D

func setPos(x, y):
	position = Vector2(x, y)

func _on_input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		# マウスの入力があった
		if event.is_pressed():
			# オブジェクトを消す
			queue_free()
			Common.emCount -=1

弾を追加(r2)

enemy形状から弾が出力されるようにします。
シーンとしてBulletを追加します。
弾が残り続けると処理が重くなっていくので、画面外で削除します。
弾の挙動は出力角度と速さを指定します。

enemy.gd

extends Area2D

func setPos(x, y):
	position = Vector2(x, y)
	em_X = x
	em_Y = y
func _on_input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		# マウスの入力があった
		if event.is_pressed():
			# オブジェクトを消す
			queue_free()
			Common.emCount -=1

#弾の設定
var Bullet   = preload("res://bullet.tscn")
var count2:int
var degcount:float
var em_X:float
var em_Y:float

func _physics_process(delta):
	

	count2 += 1
	if count2 == 1:
		var bullet = Bullet.instantiate()
		bullet.start(-90,  100)
		# ルートノードを取得
		add_child(bullet)
		await get_tree().create_timer(1).timeout
		count2 = 0
		

bullet.gd

extends Area2D

# 移動方向
var velocity = Vector2()

# 開始
func start(deg, speed):
	velocity.x = speed * cos(deg_to_rad(deg))
	velocity.y = speed * -sin(deg_to_rad(deg))


func _physics_process(delta):
	position += velocity * delta


func _on_visible_on_screen_notifier_2d_screen_exited():
	queue_free()
	pass # Replace with function body.

アイテムの出現(r4)

3つあるエネミーを削除すると、ランダムな位置にアイテムが発生して落下します。

itemのシーンを追加して、発生する条件をエネミーのスクリプトに追記します。

enemyA1.gd

extends Node2D

var xPos = 250
var yPos = 100
var Enemy = preload("res://enemy1/enemy1.tscn")
#アイテム発生用に追加
var Item = preload("res://Item/item.tscn")
var ItemFlag:bool = false
var iniFlag:bool = true
func _ready():
	iniFlag = true
	
func _process(delta):

	var cnt = 0 #enemyのカウント
	
	#-----ツリーのノード名を検索
	for child in get_children():
		#print(child.name)
		if "Enemy" in child.name:
			cnt += 1
			#print("Enemy" + str(cnt))
	#print("個数:" + str(cnt))
	if cnt == 0:
		#print("NoEnemy" )
		pass
	#----------------------
	
	#----エネミーが0になった場合にスポーンする
	if cnt == 0:
	#if Common.emCount == 0:
		for i in range(3):
			var Enemy = Enemy.instantiate()
			Enemy.setPos(position.x + i*xPos+100, position.y + yPos)
			Enemy.name = "Enemy" + str(i)
			self.add_child(Enemy)

			#Common.emCount += 1
			
		#初回にアイテムを作成しない。
		if iniFlag == true:
			ItemFlag = false
			iniFlag = false
		else:
			ItemFlag = true

	#----エネミーが0になった場合アイテムをスポーンする
	if ItemFlag == true:
	#if Common.emCount == 0:
		for i in range(1):
			var Item = Item.instantiate()
			var item_x = randi_range(0, 10)
			print(item_x*100)
			Item.setPos( item_x*100, position.y + yPos+200)
			Item.name = "Item" + str(i)
			self.add_child(Item)
	
		ItemFlag = false
	
	

アイテムのランダム化(r5)

3種類のアイテムを定義して、ランダムに発生させるようにします。

var Items = ["ItemA","ItemB","ItemC"]
で3種類の名称を設定します。
Item作成時にランダムに名称を割り当てます。

enemyA1.gd

extends Node2D

var xPos = 250
var yPos = 100
var Enemy = preload("res://enemy1/enemy1.tscn")
#アイテム発生用に追加
var Item = preload("res://Item/item.tscn")
var ItemFlag:bool = false
var iniFlag:bool = true
func _ready():
	iniFlag = true

var Items = ["ItemA","ItemB","ItemC"]

func _process(delta):

	var cnt = 0 #enemyのカウント
	
	#-----ツリーのノード名を検索
	for child in get_children():
		#print(child.name)
		if "Enemy" in child.name:
			cnt += 1
			#print("Enemy" + str(cnt))
	#print("個数:" + str(cnt))
	if cnt == 0:
		#print("NoEnemy" )
		pass
	#----------------------
	
	#----エネミーが0になった場合にスポーンする
	if cnt == 0:
	#if Common.emCount == 0:
		for i in range(3):
			var Enemy = Enemy.instantiate()
			Enemy.setPos(position.x + i*xPos+100, position.y + yPos)
			Enemy.name = "Enemy" + str(i)
			self.add_child(Enemy)

			#Common.emCount += 1
			
		#初回にアイテムを作成しない。
		if iniFlag == true:
			ItemFlag = false
			iniFlag = false
		else:
			ItemFlag = true

	#----エネミーが0になった場合アイテムをスポーンする
	if ItemFlag == true:
	#if Common.emCount == 0:
		for i in range(1):
			var Item = Item.instantiate()
			var item_x = randi_range(0, 10)
			#print(item_x*100)
			Item.name = Items[randi_range(0, 2)]			
			Item.setPos( item_x*100, position.y + yPos+200,Item.name)
			#Item.name = "Item" + str(i)			
			self.add_child(Item)
	
		ItemFlag = false
	
	#-----ツリーのノード名を検索
	for child in get_children():
		#print(child.name)
		if "Item" in child.name:
			cnt += 1
			print("Item:" + child.name)
	#print("個数:" + str(cnt))
	if cnt == 0:
		#print("NoEnemy" )
		pass
	#----------------------

item.gdの変更箇所

var Im_Y:float

#アイテムのセット
func setPos(x, y):
func setPos(x, y,ItemName):
	position = Vector2(x, y)
	Im_X = x
	Im_Y = y
	var label = Label.new()
	label.text = ItemName
	label.add_theme_color_override("font_color", Color(1, 0, 0, 1))
	label.add_theme_font_size_override("font_size", 50)
	
	add_child(label)

var velocity = Vector2()
func _process(delta):

サンプルデータ

githubに置いています。リビジョンのrは上記に対応。
コリジョンの形状表示をonにする必要があります。
メニュー>デバッグ>コリジョン形状を表示 にしてください。

GitHub - WOCae/L012
Contribute to WOCae/L012 development by creating an account on GitHub.

コメント