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は メニュー>プロジェクト設定>自動読み込み でインポートします。
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にする必要があります。
メニュー>デバッグ>コリジョン形状を表示 にしてください。

弾の追加シーン(r5-2)
編集する必要がある箇所は以下です。
1.enemyの位置情報を弾に渡す。

bullet.start(0, 0, deg, speed)
bullet.start(position.x, position.y, deg, speed)
#bullet.start(0, 0, deg, speed)
2.弾のシーンをmain直下にする。

add_child(bullet)
$"..".add_child(bullet)
サンプルデータ上だとEnemy1.gdの部分になります。
コメント