我们在上一节的基础上,为炮塔添加两个Area2D,分别表示注意范围和攻击范围。并且设置其碰撞形状为两个半径不同的圆形。
当玩家进入炮塔的注意范围时,炮塔会将自己旋转到玩家的方向,但不开火。
而当玩家进入炮塔 的攻击范围时,则炮塔开始自动攻击。
我们创建一个玩家场景:
将其添加到player组。
添加代码如下:
extends KinematicBody2D
var speed = 80.0
var velocity = Vector2.ZERO
func _physics_process(delta):
var dir = Input.get_vector("ui_left","ui_right","ui_up","ui_down")
velocity = move_and_slide(dir * speed)
在主场景中我们实例化一个Player场景,并为其添加一个Camera2D节点,并勾选其Current属性,作为当前相机。
此时玩家已经可以自由移动,并且视图始终以玩家为中心。
我们修改炮塔的代码如下:
extends StaticBody2D
const bullet = preload("res://bullet.tscn")
onready var body = $base/body
onready var bullet_start_pos = $base/body/body/Position2D
var is_noticed = false
var player
func _process(delta):
if is_noticed:
body.look_at(player.global_position)
else:
body.rotation_degrees += 1
func shoot():
var b= bullet.instance()
add_child(b)
b.dir = global_position.direction_to(get_global_mouse_position())
b.global_position = bullet_start_pos.global_position
b.global_rotation = b.dir.angle()
func _on_notice_area_body_entered(mbody):
if mbody.is_in_group("player"):
player = mbody
is_noticed = true
pass
func _on_notice_area_body_exited(mbody):
if mbody.is_in_group("player"):
is_noticed = false
pass
其中为notice_area连接信号,body_entered和body_exited,用于当玩家进入注意范围后,将炮塔指向玩家的位置。
运行效果:
我们继续修改:
extends StaticBody2D
const bullet = preload("res://bullet.tscn")
onready var body = $base/body
onready var bullet_start_pos = $base/body/body/Position2D
var is_noticed = false
var can_attack = false
var player
func _process(delta):
if is_noticed:
body.look_at(player.global_position)
if can_attack:
shoot(player.global_position)
else:
body.rotation_degrees += 1
func shoot(pos:Vector2):
var b= bullet.instance()
add_child(b)
b.dir = global_position.direction_to(pos)
b.global_position = bullet_start_pos.global_position
b.global_rotation = b.dir.angle()
func _on_notice_area_body_entered(mbody):
if mbody.is_in_group("player"):
player = mbody
is_noticed = true
pass
func _on_notice_area_body_exited(mbody):
if mbody.is_in_group("player"):
is_noticed = false
pass
func _on_attack_area_body_entered(mbody):
if mbody.is_in_group("player"):
can_attack = true
pass
func _on_attack_area_body_exited(mbody):
if mbody.is_in_group("player"):
can_attack = false
pass
运行效果:
可以看到,由于我们的炮塔没有攻击的时间间隔,所以每物理帧都会发射一枚炮弹,也就是一分钟之内发射60发。
为了控制炮塔发射炮弹的时间间隔,我们添加一个Timer节点。
我们继续修改代码如下:
extends StaticBody2D
const bullet = preload("res://bullet.tscn")
var is_noticed = false
var can_attack = false
var cool_down = 0.5 # 发射间隔时间,单位:秒
var player
onready var body = $base/body
onready var bullet_start_pos = $base/body/body/Position2D
onready var CD_timer =$CD_timer # 发射的时间间隔
func _process(delta):
if is_noticed:
body.look_at(player.global_position)
if can_attack:
if CD_timer.is_stopped():
CD_timer.start(cool_down)
else:
CD_timer.stop()
else:
body.rotation_degrees += 1
func shoot(pos:Vector2):
var b= bullet.instance()
add_child(b)
b.dir = global_position.direction_to(pos)
b.global_position = bullet_start_pos.global_position
b.global_rotation = b.dir.angle()
func _on_notice_area_body_entered(mbody):
if mbody.is_in_group("player"):
player = mbody
is_noticed = true
pass
func _on_notice_area_body_exited(mbody):
if mbody.is_in_group("player"):
is_noticed = false
pass
func _on_attack_area_body_entered(mbody):
if mbody.is_in_group("player"):
can_attack = true
pass
func _on_attack_area_body_exited(mbody):
if mbody.is_in_group("player"):
can_attack = false
pass
func _on_CD_timer_timeout():
shoot(player.global_position)
pass
运行效果: