godot 调用class方法得用实例 不能用脚本引用

var enemyplay=preload("res://scripts/EnemyBall.gd")

不能用enemyplay.play调用

得用

func _handle_pocketed(body: RigidBody2D):

if "Enemy" in body.name or "enemy" in body.name:

body.play("xiao")

body.play调用

错误提示说明你在某个地方用 EnemyBall.play() 或 WhiteBall.play() 这种"类名.方法"的形式调用了实例方法。play() 是每个球的实例方法,必须通过实例(比如 self.play() 或某个敌人对象.play())调用。

检查一下你的代码,你是不是写成了这样:

go 复制代码
gdscript
# 错误写法
if something:
    EnemyBall.play()   # 错:EnemyBall 是类,不能直接用类名调用实例方法
要改成:
go 复制代码
gdscript
# 正确写法
self.play("xiao")  # 自己播放
# 或者
enemy_instance.play("xiao")  # 特定敌人实例播放
go 复制代码
extends Area2D

@onready var pocket_radius := _get_collision_radius()
@onready var table_rect: Rect2 = _get_table_rect()

var bodies_in_pocket := {}
var enemyplay=preload("res://scripts/EnemyBall.gd")
var whiteplay=preload("res://scripts/WhiteBall.gd")
func _get_collision_radius() -> float:
	var shapes = find_children("*", "CollisionShape2D", true, false)
	for shape in shapes:
		if shape.shape is CircleShape2D:
			return shape.shape.radius
	return 10.0

func _get_table_rect() -> Rect2:
	# 假设你的桌子 Sprite 路径是 "/root/Table/TableSprite"
	var table_sprite = get_node_or_null("/root/Table/TableSprite")
	if table_sprite and table_sprite is Sprite2D:
		var texture = table_sprite.texture

		if texture:
			var tex_size = texture.get_size() * table_sprite.scale
			# Sprite2D 的 global_position 是纹理中心,所以矩形左上角是中心减去一半尺寸
			var top_left = table_sprite.global_position - tex_size / 2
			var rect = Rect2(top_left, tex_size)
			# 缩一点边距,让球不贴墙
			return rect.grow(-70)
	
	# 回退默认值
	return Rect2(150, 250, 330, 610)



func _get_ball_radius(body: RigidBody2D) -> float:
	for child in body.get_children():
		if child is CollisionShape2D and child.shape is CircleShape2D:
			return child.shape.radius
	return 30.0

func _ready():
	body_entered.connect(_on_body_entered)
	body_exited.connect(_on_body_exited)

func _on_body_entered(body: Node2D):
	if body is RigidBody2D:
		bodies_in_pocket[body.get_instance_id()] = body

func _on_body_exited(body: Node2D):
	if body is RigidBody2D:
		bodies_in_pocket.erase(body.get_instance_id())

func _physics_process(_delta):
	for id in bodies_in_pocket.keys():
		var body = bodies_in_pocket[id]
		if not is_instance_valid(body):
			bodies_in_pocket.erase(id)
			continue
		# 获取CollisionShape2D的实际中心(Area2D位置 + Shape偏移)
		var collision_shape = find_child("CollisionShape2D", false, false)
		var pocket_center = global_position
		if collision_shape:
			pocket_center = global_position + collision_shape.position
		var dist = pocket_center.distance_to(body.global_position)
		var ball_radius = _get_ball_radius(body)
		# 球进洞条件:球心到球袋中心距离 < 球袋半径(这样球至少有部分在袋内)
		# 更严格可以减球半径: dist < pocket_radius - ball_radius
		var threshold = pocket_radius
		if dist < threshold:
			print(body.name, " 进洞!距离:", dist, " 阈值:", threshold, " 球半径:", ball_radius, " 袋半径:", pocket_radius)
			_handle_pocketed(body)
			bodies_in_pocket.erase(id)

func _handle_pocketed(body: RigidBody2D):
	if "Enemy" in body.name or "enemy" in body.name:
		body.play("xiao")
		print(body.name, " 进洞!")
		# 通知Game敌人进洞,奖励耍赖币
		var game = get_node_or_null("/root/Main/Game")
		if game and game.has_signal("enemy_pocketed"):
			game.emit_signal("enemy_pocketed")
		body.queue_free()
	else:
		print(body.name, " 玩家进洞!")
		# 1. 球立即消失
		body.visible = false
		body.set_physics_process(false)
		# 扣一半血
		var health_bar = body.find_child("HealthBar")
		if health_bar:
			health_bar.current_health *= 0.5
			health_bar.health_bar.value = health_bar.current_health
			health_bar.label.text = "%d/%d" % [health_bar.current_health, health_bar.max_health]
		# 2. 显示提示
		_show_pocket_message()
		
		
		
		
		
		
		# 3. 3秒后重置球
		await get_tree().create_timer(3.0).timeout
		_reset_ball_to_table(body)

var _pocket_label: Label

func _show_pocket_message():
	# 获取或创建提示Label
	if not _pocket_label:
		_pocket_label = Label.new()
		_pocket_label.name = "PocketMessage"
		_pocket_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
		_pocket_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
		_pocket_label.add_theme_font_size_override("font_size", 48)
		_pocket_label.add_theme_color_override("font_color", Color.RED)
		_pocket_label.add_theme_color_override("font_outline_color", Color.WHITE)
		_pocket_label.add_theme_constant_override("outline_size", 8)
		# 放在屏幕中央
		var vp = get_viewport()
		_pocket_label.set_anchors_preset(Control.PRESET_CENTER)
		add_child(_pocket_label)

	_pocket_label.text = "玩家进洞!"
	_pocket_label.visible = true

	# 等待后隐藏
	await get_tree().create_timer(2.5).timeout
	_pocket_label.visible = false

func _reset_ball_to_table(ball: RigidBody2D):
	print("===== 重置球到桌面 =====")
	# 直接用一个"硬"的安全中心点,或者动态取视图中心
	#var screen_center = get_viewport().get_visible_rect().size / 2
	# 随机偏移一个合理范围,例如 x:±200, y:±100
	#var offset = Vector2(randf_range(-70, 70), randf_range(-70, 70))
	var center = table_rect.get_center()
	var offset = Vector2(randf_range(-60, 60), randf_range(-60, 60))
	ball.global_position = center + offset

	# 保险 clamp 防止出界
	ball.global_position.x = clamp(ball.global_position.x, table_rect.position.x + 30, table_rect.end.x - 30)
	ball.global_position.y = clamp(ball.global_position.y, table_rect.position.y + 30, table_rect.end.y - 30)

	ball.linear_velocity = Vector2.ZERO
	ball.angular_velocity = 0.0
	ball.visible = true
	ball.set_physics_process(true)
	ball.contact_monitor = true
	ball.max_contacts_reported = 10
相关推荐
风酥糖2 小时前
Godot游戏练习01-第32节-国际化
游戏·游戏引擎·godot
魔士于安3 小时前
Unity类似博物馆场景
前端·unity·游戏引擎·贴图·模型
RReality3 小时前
【Unity Shader URP】模板遮罩 / 传送门 实战教程
ui·unity·游戏引擎·图形渲染·材质
郑寿昌11 小时前
虚幻引擎6:Lumen光源技术前瞻
游戏引擎·虚幻
RPGMZ1 天前
RPGMakerMZ 获取敌人攻击时属性 用于画UI或属性克制
javascript·游戏引擎·rpgmz·rpgmakermz
zdr尽职尽责1 天前
Untiy 处理Aseprite 资产 解决偏移问题
学习·unity·c#·游戏引擎
LcGero1 天前
游戏引擎Luanti的前世今生与技术解析
游戏引擎·lua·游戏开发·我的世界·luanti
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 06:相机视图矩阵的由来
c++·线性代数·unity·矩阵·godot·图形渲染·unreal engine
MFXWW22 天前
从 Python 到 3D 开发:Ursina 引擎零基础入门学习路径与核心开发思路
python·游戏引擎·游戏程序·ursina