Something went wrong. Try again.
triple triad implementation in godot + rust lib
Something went wrong. Try again.
5.8 kB · 205 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206extends Node3D
var _camera: Camera3Dvar _light: DirectionalLight3Dvar _table: MeshInstance3Dvar _cards: Array[Node3D] = []var _flipping := false
func _ready() -> void: _camera = Camera3D.new() _camera.position = Vector3(0, 9, 5.5) _camera.look_at(Vector3(0, 0, -0.5), Vector3.UP) _camera.current = true add_child(_camera)
_light = DirectionalLight3D.new() _light.position = Vector3(2, 8, 2) _light.look_at(Vector3.ZERO, Vector3.UP) _light.light_color = Color("ffe8cc") _light.shadow_enabled = true add_child(_light)
var ambient := WorldEnvironment.new() var env := Environment.new() env.ambient_light_color = Color("667799") env.ambient_light_energy = 0.3 env.background_mode = Environment.BG_COLOR env.background_color = Color("0e0e1a") ambient.environment = env add_child(ambient)
_table = _make_table() add_child(_table)
var card_data := [ {"pos": Vector3(-1.6, 0.05, 0), "ranks": [7, 6, 2, 7], "color": Color("4a90d9"), "name": "Ifrit"}, {"pos": Vector3(-0.5, 0.05, 0), "ranks": [5, 3, 8, 4], "color": Color("d94a4a"), "name": "Tonberry"}, {"pos": Vector3(0.5, 0.05, 0), "ranks": [9, 4, 7, 3], "color": Color("4a90d9"), "name": "Shiva"}, {"pos": Vector3(1.6, 0.05, 0), "ranks": [3, 8, 5, 6], "color": Color("d94a4a"), "name": "Odin"}, ]
for d in card_data: var card := _make_card(d.ranks, d.color, d.name) card.position = d.pos add_child(card) _cards.append(card)
var board_positions: Array[Vector3] = [] var bx := -1.1 var by := 0.05 for row in 3: for col in 3: board_positions.append(Vector3(bx + col * 1.1, by, -1.8 + row * 1.5))
for i in board_positions.size(): var slot := _make_slot() slot.position = board_positions[i] slot.set_meta("board_idx", i) add_child(slot)
_instructions_label()
func _make_table() -> MeshInstance3D: var mesh := BoxMesh.new() mesh.size = Vector3(12, 0.2, 8) var mat := StandardMaterial3D.new() mat.albedo_color = Color("2a5a2a") mat.roughness = 0.85 var mi := MeshInstance3D.new() mi.mesh = mesh mi.material_override = mat mi.position.y = -0.15 mi.create_trimesh_collision() return mi
func _make_slot() -> MeshInstance3D: var mesh := PlaneMesh.new() mesh.size = Vector2(0.95, 1.15) var mat := StandardMaterial3D.new() mat.albedo_color = Color("1a3a1a") mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA mat.albedo_color.a = 0.6 var mi := MeshInstance3D.new() mi.mesh = mesh mi.material_override = mat mi.rotation.x = -PI / 2 return mi
func _make_card(ranks: Array, card_color: Color, card_name: String) -> Node3D: var root := Node3D.new()
var mesh := BoxMesh.new() mesh.size = Vector3(0.85, 0.02, 1.1)
var front_mat := StandardMaterial3D.new() front_mat.albedo_color = card_color front_mat.roughness = 0.5
var mi := MeshInstance3D.new() mi.mesh = mesh mi.material_override = front_mat mi.rotation.x = -PI / 2 root.add_child(mi)
var col := CollisionShape3D.new() var shape := BoxShape3D.new() shape.size = Vector3(0.85, 0.1, 1.1) col.shape = shape col.rotation.x = -PI / 2
var body := StaticBody3D.new() body.collision_layer = 2 body.add_child(col) root.add_child(body)
var edge_mat := StandardMaterial3D.new() edge_mat.albedo_color = Color("222233") edge_mat.roughness = 0.8
var positions := [ Vector3(0, 0.005, -0.42), Vector3(0.35, 0.005, 0), Vector3(0, 0.005, 0.38), Vector3(-0.35, 0.005, 0), ]
for i in 4: var label := Label3D.new() var v: int = ranks[i] label.text = "A" if v >= 10 else str(v) label.font_size = 22 label.outline_size = 4 label.modulate = Color.WHITE label.billboard = BaseMaterial3D.BILLBOARD_ENABLED label.position = positions[i] root.add_child(label)
var name_label := Label3D.new() name_label.text = card_name name_label.font_size = 11 name_label.outline_size = 3 name_label.modulate = Color(1, 1, 1, 0.8) name_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED name_label.position = Vector3(0, 0.005, 0.15) name_label.pixel_size = 0.003 root.add_child(name_label)
root.set_meta("card_color", card_color) return root
func _instructions_label() -> void: var label := Label3D.new() label.text = "Click a card to flip it | R to reset" label.font_size = 18 label.outline_size = 4 label.modulate = Color("f0c040") label.billboard = BaseMaterial3D.BILLBOARD_ENABLED label.position = Vector3(0, 0.5, -4) add_child(label)
func _input(event: InputEvent) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _pick_card(event) if event is InputEventKey and event.pressed and event.keycode == KEY_R: for card in _cards: card.rotation = Vector3.ZERO card.scale = Vector3.ONE
func _pick_card(event: InputEventMouseButton) -> void: if _flipping: return var from := _camera.project_ray_origin(event.position) var dir := _camera.project_ray_normal(event.position) var space_state := get_world_3d().direct_space_state var query := PhysicsRayQueryParameters3D.create(from, from + dir * 20) query.collision_mask = 0xFFFFFFFF var result := space_state.intersect_ray(query) if result.is_empty(): return var hit: Object = result.collider for card in _cards: for child in card.get_children(): if child is StaticBody3D and child == hit: _flip_card(card) return
func _flip_card(card: Node3D) -> void: _flipping = true var tween := create_tween() tween.set_parallel(true) tween.tween_property(card, "rotation:y", PI, 0.3).set_ease(Tween.EASE_IN) tween.tween_property(card, "position:y", 0.4, 0.15).set_trans(Tween.TRANS_SINE) tween.chain() tween.tween_property(card, "rotation:y", PI * 2, 0.3).set_ease(Tween.EASE_OUT) tween.tween_property(card, "position:y", 0.05, 0.15).set_trans(Tween.TRANS_SINE) tween.chain() tween.tween_callback(func(): _flipping = false)