Skip to content

Commit

Permalink
refactor(card)!: 对 Card 重大重构
Browse files Browse the repository at this point in the history
- 删除众多在新逻辑中不会使用到的信号激活函数和变量;
  删除 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
cutekibry committed Feb 13, 2024
1 parent 30adff0 commit b0ace12
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 130 deletions.
245 changes: 118 additions & 127 deletions objects/card/card.gd
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"])
6 changes: 3 additions & 3 deletions objects/card/card.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ animations = [{
}]

[sub_resource type="RectangleShape2D" id="RectangleShape2D_gu6l6"]
size = Vector2(24, 24)

[node name="Card" type="Area2D"]
z_index = 50
script = ExtResource("1_0bviv")

[node name="Word" parent="." instance=ExtResource("1_ns36n")]
z_index = 1

[node name="CardBackSprite" type="AnimatedSprite2D" parent="."]
sprite_frames = SubResource("SpriteFrames_fo0r0")

[node name="HighlightSprite" type="Sprite2D" parent="."]
texture = ExtResource("7_kix4t")

[node name="Word" parent="." instance=ExtResource("1_ns36n")]

[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
z_index = 15
shape = SubResource("RectangleShape2D_gu6l6")
Expand Down

0 comments on commit b0ace12

Please sign in to comment.