-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 删除众多在新逻辑中不会使用到的信号激活函数和变量; 删除 put 和 back_to_origin_global_position 信号,base_level 所需的 原 card_put 信号交给 Block 处理。 暂不提供替代方案,新函数、变量的使用可参见其说明。 - 将 _on_mouse_release(), _on_mouse_pressed() 分别重命名为 put_down 和 pick_up,以避免与其他信号激活函数混淆,并重写逻辑。 - 修复行为:当 Card 放下时,会选择距离最近的一个可放入的 Block 放入。 - 修改行为:若 Card 的碰撞箱未和任一可放入的 Block 相交,会销毁回到 Card Base。 - 修复碰撞箱边界。
- Loading branch information
Showing
2 changed files
with
121 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,161 @@ | ||
extends Area2D | ||
extends Area2D | ||
|
||
class_name Card | ||
class_name Card | ||
|
||
signal put | ||
signal back_to_origin_global_position | ||
|
||
var is_dragging = false | ||
var have_deal_on_mouse_release = true | ||
var origin_global_position: Vector2 | ||
var last_global_position: Vector2 | ||
var is_card_entered = 0 | ||
var entered_area: Block | ||
var last_occupied_area: Block | ||
var is_dragging := false ## 是否正在被拖拽。 | ||
|
||
var is_card_base_entered = 0 | ||
var entered_card_base_global_position: Vector2 | ||
var current_block: Block = null ## 当前所占用的 Block 对象。 | ||
|
||
var is_victory := false | ||
var is_victory := false ## 是否已通关。 | ||
|
||
var shake_amount : float | ||
var is_shaking := false | ||
var shake_amount : float ## 震动幅度(单位为像素)。 | ||
var is_shaking := false ## 是否正在震动。 | ||
|
||
|
||
func _ready(): | ||
origin_global_position = global_position | ||
last_global_position = global_position | ||
$HighlightSprite.visible = false | ||
|
||
func _on_mouse_release(): | ||
#prints(entered_area.name, is_card_entered, entered_area.occupied) | ||
have_deal_on_mouse_release = true | ||
if is_card_entered > 0 and entered_area and not entered_area.occupied: | ||
global_position = entered_area.global_position | ||
last_global_position = global_position | ||
if last_occupied_area: | ||
last_occupied_area.occupied = false | ||
entered_area.occupied = true | ||
last_occupied_area = entered_area | ||
entered_area.set_card(self) | ||
emit_signal("put") | ||
Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) | ||
$SFXPutDown.play() | ||
# prints("card", $Word.get_word(), "put at", entered_area.name, "at global_position", global_position, "when origin global_position at", origin_global_position) | ||
else: | ||
global_position = last_global_position | ||
|
||
if global_position == origin_global_position: | ||
emit_signal("back_to_origin_global_position") | ||
|
||
if is_card_base_entered > 0: | ||
reset_position() | ||
|
||
is_dragging = false | ||
is_card_entered = 0 | ||
is_card_base_entered = 0 | ||
|
||
func reset_position(): | ||
global_position = origin_global_position | ||
var err := emit_signal("back_to_origin_global_position") | ||
if err != 0: | ||
printerr(err) | ||
last_global_position = origin_global_position | ||
#print(last_occupied_area) | ||
if last_occupied_area: | ||
last_occupied_area.occupied = false | ||
last_occupied_area = null | ||
## 获取当前最近的,Area 相交的,且未被占用的 Block。 | ||
## | ||
## 距离按两个中心点间的距离计算。 | ||
func get_top_prior_entered_block() -> Block: | ||
var top_block: Block = null | ||
for area: Area2D in get_overlapping_areas(): | ||
if area is Block and area.is_empty(): | ||
if top_block == null or (self.position - top_block.position).length() > (self.position - area.position).length(): | ||
top_block = area | ||
return top_block | ||
|
||
|
||
## 进行被拾取时的处理。 | ||
## | ||
## 一般在生成 Card 时,以及鼠标移到 Card 上点击鼠标左键时调用。 | ||
func pick_up(): | ||
self.z_index += 1 | ||
self.is_dragging = true | ||
if self.current_block != null: | ||
self.current_block.set_card(null) | ||
self.current_block = null | ||
|
||
|
||
## 进行被放下时的处理。 | ||
## | ||
## 一般在 Card 被拖动的过程中,点击鼠标右键时调用。 | ||
func put_down(): | ||
self.z_index -= 1 | ||
var entered_block := get_top_prior_entered_block() | ||
if entered_block != null: | ||
self.current_block = entered_block | ||
self.position = entered_block.position | ||
self.is_dragging = false | ||
|
||
$SFXPutDown.play() | ||
|
||
entered_block.set_card(self) | ||
|
||
Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) # 设置鼠标指针形状为手形 | ||
|
||
func _on_mouse_pressed(): | ||
have_deal_on_mouse_release = false | ||
last_global_position = global_position | ||
is_dragging = true | ||
is_card_entered = 0 | ||
is_card_base_entered = 0 | ||
|
||
else: | ||
queue_free() | ||
|
||
func _input_event(_viewport: Object, event: InputEvent, _shape_idx: int) -> void: | ||
#prints(self, event) | ||
if not is_victory and event is InputEventMouseButton: | ||
if event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: | ||
_on_mouse_pressed() | ||
elif not event.is_pressed() and is_dragging: | ||
_on_mouse_release() | ||
|
||
if event.is_pressed() and event.button_index == MOUSE_BUTTON_RIGHT: | ||
reset_position() | ||
|
||
func _process(_delta: float) -> void: | ||
if not have_deal_on_mouse_release and not Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): | ||
_on_mouse_release() | ||
if is_dragging: | ||
have_deal_on_mouse_release = false | ||
global_position = get_global_mouse_position().round() | ||
Input.set_default_cursor_shape(Input.CURSOR_DRAG) | ||
## 使 Card 开始震动。 | ||
## | ||
## * is_letter_red:是否要将字符颜色改为红色 | ||
## * amount:震动幅度 | ||
## * duration:震动持续时长 | ||
func shake(is_letter_red: bool, amount: float, duration: float) -> void: | ||
$ShakeTimer.wait_time = duration | ||
self.shake_amount = amount | ||
|
||
# 开启震动 | ||
$ShakeTimer.start() | ||
self.is_shaking = true | ||
|
||
if is_letter_red: | ||
$Word.set_color(ImageLib.PALETTE["red"]) | ||
else: | ||
$HighlightSprite.visible = false | ||
|
||
var offset := 0 | ||
if is_shaking: | ||
var progress = $ShakeTimer.time_left / $ShakeTimer.wait_time * 2 * PI | ||
offset = int(sin(progress) * shake_amount) | ||
$CardBackSprite.position.x = offset | ||
$HighlightSprite.position.x = offset | ||
$Word.position.x = offset | ||
|
||
func on_card_entered(area: Block) -> void: | ||
is_card_entered += 1 | ||
#print(is_card_entered) | ||
entered_area = area | ||
## 设置字符颜色。 | ||
func set_color(value: Color) -> void: # 设置颜色函数 | ||
$Word.set_color(value) # 设置文字颜色 | ||
|
||
func on_card_exited() -> void: | ||
is_card_entered -= 1 | ||
|
||
func on_card_base_entered(pos: Vector2) -> void: | ||
is_card_base_entered += 1 | ||
#print(is_card_entered) | ||
entered_card_base_global_position = pos | ||
## 设置是否为胜利状态。 | ||
func set_victory(v: bool): # 设置胜利状态函数 | ||
if v: | ||
$CollisionShape2D.set_deferred("disabled", true) # 如果胜利,禁用碰撞形状 | ||
|
||
func on_card_base_exited() -> void: | ||
is_card_base_entered -= 1 | ||
#print(is_card_entered) | ||
|
||
## 设置字符为 value,同时更新卡背颜色。 | ||
func set_word(value: String) -> void: | ||
$Word.set_word(value) | ||
var card_type := "card-%s" % ExprValidator.get_char_type_as_str(get_word()).to_lower() | ||
if ImageLib.PALETTE.has(card_type): | ||
$Word.set_word(value) | ||
var card_type := "card-%s" % ExprValidator.get_char_type_as_str(get_word()).to_lower() # 根据单词类型获取卡牌类型 | ||
if ImageLib.PALETTE.has(card_type): # 如果配色盘中包含该卡牌类型对应颜色,则更新卡背颜色 | ||
ImageLib.update_animation( | ||
$CardBackSprite, 1, 3, 1, "res://objects/card/card%d.png", | ||
ImageLib.PALETTE["lightblue"], ImageLib.PALETTE[card_type] | ||
ImageLib.PALETTE["lightblue"], ImageLib.PALETTE[card_type] | ||
) | ||
|
||
|
||
|
||
## 获取字符。 | ||
func get_word() -> String: | ||
return $Word.get_word() | ||
|
||
|
||
func shake(is_letter_red: bool, amount: float, duration: float) -> void: | ||
$ShakeTimer.wait_time = duration | ||
shake_amount = amount | ||
|
||
# 开启震动 | ||
$ShakeTimer.start() | ||
is_shaking = true | ||
|
||
|
||
if is_letter_red: | ||
$Word.set_color(ImageLib.PALETTE["red"]) | ||
else: | ||
$HighlightSprite.visible = false | ||
func _ready(): | ||
$HighlightSprite.visible = false | ||
|
||
|
||
func _process(_delta: float) -> void: | ||
if self.is_dragging: # 如果正在拖拽 | ||
self.global_position = get_global_mouse_position().round() # 将卡牌位置设置为鼠标位置的全局位置,四舍五入取整 | ||
Input.set_default_cursor_shape(Input.CURSOR_DRAG) # 设置鼠标指针形状为拖拽形状 | ||
|
||
var offset := 0 | ||
if self.is_shaking: | ||
# 如果正在震动,则设置震动偏移量为 sin(progress) * self.shake_amount | ||
# 其中 progress in [0, 2 * PI] 是震动进度,随着时间的推移逐渐增加 | ||
# self.shake_amount 是震动幅度 | ||
var progress = (1 - $ShakeTimer.time_left / $ShakeTimer.wait_time) * 2 * PI | ||
offset = int(sin(progress) * self.shake_amount) | ||
|
||
# 设置 Sprite 的震动偏移量 | ||
$CardBackSprite.position.x = offset | ||
$HighlightSprite.position.x = offset | ||
$Word.position.x = offset | ||
|
||
|
||
func _input_event(_viewport: Object, event: InputEvent, _shape_idx: int) -> void: | ||
if event is InputEventMouseButton: | ||
if event.button_index == MOUSE_BUTTON_LEFT: | ||
if event.is_pressed(): # 如果按下左键,则拾取 Card | ||
pick_up() | ||
elif self.is_dragging: # 否则则是放开左键,此时若 Card 正在拖拽,则放下 | ||
put_down() | ||
|
||
elif event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): # 按下右键时 | ||
queue_free() | ||
|
||
|
||
|
||
func _on_mouse_entered(): | ||
$HighlightSprite.visible = true | ||
Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) | ||
Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) # 设置鼠标指针形状为手形 | ||
|
||
|
||
func _on_mouse_exited(): | ||
$HighlightSprite.visible = false | ||
Input.set_default_cursor_shape(Input.CURSOR_ARROW) | ||
Input.set_default_cursor_shape(Input.CURSOR_ARROW) # 设置鼠标指针形状为箭头 | ||
|
||
func set_color(value: Color) -> void: | ||
$Word.set_color(value) | ||
|
||
func set_victory(v: bool): | ||
if v: | ||
$CollisionShape2D.set_deferred("disabled", true) | ||
func _on_tree_exiting(): | ||
if self.current_block != null: | ||
self.current_block.set_card(null) | ||
|
||
|
||
func _on_shake_timer_timeout(): | ||
is_shaking = false | ||
self.is_shaking = false | ||
$Word.set_color(ImageLib.PALETTE["default"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters