godot-genre-card-game by thedivergentai/gd-agentic-skills
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-genre-card-game采用数据驱动设计和生动 UI 的数字卡牌游戏专家蓝图。
Callable 对象 或 Command 资源 中。_process() 中进行棋盘状态计算(力量/生命值);必须使用 信号驱动触发器 或集中式的 EffectStack 解析器。Array.push_back() 和 Array.pop_back() 来从上到下解析反应。广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
global_position 来定位手牌;必须使用 Curve2D(贝塞尔曲线)布局和 sample_baked() 方法来定位,以实现平滑的非圆形弧线排列。create_tween() 和 tween_property 链式调用(0.2秒+)来实现生动的卡牌手感。int,以避免精度漂移。_draw() 自定义绘制 来绕过 SceneTree 的开销。queue_redraw() 更新视觉效果。for 循环中删除数组元素;必须反向迭代或使用 filter() 来避免索引错误。_init() 中提供无参数构造函数;否则,资源将无法在检查器中加载。_get_drag_data()。filter() 模式。| 阶段 | 技能 | 目的 |
|---|---|---|
| 1. 数据 | resources, custom-resources | 定义卡牌属性(费用、类型、效果) |
| 2. UI | control-nodes, layout-containers | 手牌布局、卡牌定位、工具提示 |
| 3. 输入 | drag-and-drop, state-machines | 将卡牌拖拽到目标、悬停 |
| 4. 逻辑 | command-pattern, signals | 执行卡牌效果、回合阶段 |
| 5. 润色 | godot-tweening, shaders | 抽牌动画、全息闪卡效果 |
Godot 资源非常适合存储卡牌数据。
# card_data.gd
extends Resource
class_name CardData
enum Type { ATTACK, SKILL, POWER }
enum Target { ENEMY, SELF, ALL_ENEMIES }
@export var id: String
@export var name: String
@export_multiline var description: String
@export var cost: int
@export var type: Type
@export var target_type: Target
@export var icon: Texture2D
@export var effect_script: Script # 每张卡牌的自定义逻辑
处理各个牌堆:抽牌堆、手牌、弃牌堆、消耗堆。
# deck_manager.gd
var draw_pile: Array[CardData] = []
var hand: Array[CardData] = []
var discard_pile: Array[CardData] = []
func draw_cards(amount: int) -> void:
for i in amount:
if draw_pile.is_empty():
reshuffle_discard()
if draw_pile.is_empty():
break # 没有剩余卡牌
var card = draw_pile.pop_back()
hand.append(card)
card_drawn.emit(card)
func reshuffle_discard() -> void:
draw_pile.append_array(discard_pile)
discard_pile.clear()
draw_pile.shuffle()
代表手牌中卡牌的交互式节点。
# card_ui.gd
extends Control
var card_data: CardData
var start_pos: Vector2
var is_dragging: bool = false
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if event.pressed:
start_drag()
else:
end_drag()
func _process(delta: float) -> void:
if is_dragging:
global_position = get_global_mouse_position() - size / 2
else:
# 悬停效果或返回手牌位置
pass
将卡牌的"打出"与其"效果"解耦。
func play_card(card: CardData, target: Node) -> void:
if current_energy < card.cost:
show_error("能量不足")
return
current_energy -= card.cost
# 执行效果
var effect = card.effect_script.new()
effect.execute(target)
move_to_discard(card)
手牌通常排列成弧形。使用数学公式(贝塞尔曲线或圆形)根据 index 和 total_cards 来定位它们。
func update_hand_visuals() -> void:
var center_x = screen_width / 2
var radius = 1000.0
var angle_step = 5.0
for i in hand_visuals.size():
var card = hand_visuals[i]
var angle = deg_to_rad((i - hand_visuals.size() / 2.0) * angle_step)
var target_pos = Vector2(
center_x + sin(angle) * radius,
screen_height + cos(angle) * radius
)
card.target_rotation = angle
card.target_position = target_pos
mouse_filter(Pass 与 Stop)。z_index 或 CanvasLayer 来确保被拖动的卡牌始终位于其他所有内容之上。每周安装量
79
仓库
GitHub 星标数
59
首次出现
2026年2月10日
安全审计
安装于
gemini-cli74
opencode74
cursor72
codex72
kimi-cli69
github-copilot69
Expert blueprint for digital card games with data-driven design and juicy UI.
Callable objects or Command resources pushed to a LIFO stack._process(); strictly use Signal-driven triggers or a centralized EffectStack resolver.Array.push_back() and Array.pop_back() to resolve reactions from top-to-bottom.global_position for cards in hand; strictly position them using a Curve2D (Bezier) layout with sample_baked() for smooth, non-circular arcs.create_tween() and tween_property chainings (0.2s+) for juicy card-feel.int for Costs, Attack, and Health to avoid precision drift._draw() custom drawing to bypass SceneTree overhead when rendering 100+ cards or map icons.queue_redraw().for loop; strictly iterate in reverse or use filter() to avoid indexing errors._init(); otherwise, Resources will fail to load in the Inspector._get_drag_data() for Control nodes.filter() patterns for querying board metadata.| Phase | Skills | Purpose |
|---|---|---|
| 1. Data | resources, custom-resources | Defining Card properties (Cost, Type, Effect) |
| 2. UI | control-nodes, layout-containers | Hand layout, card positioning, tooltips |
| 3. Input | drag-and-drop, state-machines | Dragging cards to targets, hovering |
| 4. Logic | , |
Godot Resources are perfect for card data.
# card_data.gd
extends Resource
class_name CardData
enum Type { ATTACK, SKILL, POWER }
enum Target { ENEMY, SELF, ALL_ENEMIES }
@export var id: String
@export var name: String
@export_multiline var description: String
@export var cost: int
@export var type: Type
@export var target_type: Target
@export var icon: Texture2D
@export var effect_script: Script # Custom logic per card
Handles the piles: Draw Pile, Hand, Discard Pile, Exhaust Pile.
# deck_manager.gd
var draw_pile: Array[CardData] = []
var hand: Array[CardData] = []
var discard_pile: Array[CardData] = []
func draw_cards(amount: int) -> void:
for i in amount:
if draw_pile.is_empty():
reshuffle_discard()
if draw_pile.is_empty():
break # No cards left
var card = draw_pile.pop_back()
hand.append(card)
card_drawn.emit(card)
func reshuffle_discard() -> void:
draw_pile.append_array(discard_pile)
discard_pile.clear()
draw_pile.shuffle()
The interactive node representing a card in hand.
# card_ui.gd
extends Control
var card_data: CardData
var start_pos: Vector2
var is_dragging: bool = false
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if event.pressed:
start_drag()
else:
end_drag()
func _process(delta: float) -> void:
if is_dragging:
global_position = get_global_mouse_position() - size / 2
else:
# Hover effect or return to hand position
pass
Decouple the "playing" of a card from its "effect".
func play_card(card: CardData, target: Node) -> void:
if current_energy < card.cost:
show_error("Not enough energy")
return
current_energy -= card.cost
# Execute effect
var effect = card.effect_script.new()
effect.execute(target)
move_to_discard(card)
Cards in hand usually form an arc. Use a math formula (Bezier or Circle) to position them based on index and total_cards.
func update_hand_visuals() -> void:
var center_x = screen_width / 2
var radius = 1000.0
var angle_step = 5.0
for i in hand_visuals.size():
var card = hand_visuals[i]
var angle = deg_to_rad((i - hand_visuals.size() / 2.0) * angle_step)
var target_pos = Vector2(
center_x + sin(angle) * radius,
screen_height + cos(angle) * radius
)
card.target_rotation = angle
card.target_position = target_pos
mouse_filter (Pass vs Stop).z_index or CanvasLayer to ensure the dragged card is always on top of everything else.Weekly Installs
79
Repository
GitHub Stars
59
First Seen
Feb 10, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli74
opencode74
cursor72
codex72
kimi-cli69
github-copilot69
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
120,000 周安装
Google Docs API 技能:自动化文档创建、编辑与管理 | 集成指南
138 周安装
Java 21+ 专家技能:现代 Java 开发、Spring Boot 3.x、JVM 性能优化与云原生架构
138 周安装
React 前端开发专家技能:最佳实践、性能优化与 TypeScript 集成指南
141 周安装
Boss直聘职位搜索技能 - AI自动化爬取招聘信息,支持薪资、公司规模筛选
146 周安装
Tailwind CSS UI重构指南:基于《重构UI》的52条最佳实践与代码规范
140 周安装
Conductor 状态监控工具 - 实时查看项目进度、轨道任务与阻塞项
144 周安装
command-patternsignals| Executing card effects, turn phases |
| 5. Polish | godot-tweening, shaders | Draw animations, holographic foils |