multiplayer_and_some_card_art #2

Merged
kensi.chandrawan merged 7 commits from multiplayer-and-card-art into main 2025-01-25 19:58:37 +07:00
9 changed files with 429 additions and 104 deletions
Showing only changes of commit 6c6e1b3289 - Show all commits

View file

@ -1,4 +1,10 @@
extends Control extends Control
class_name DemoGame
signal own_played_card(card: Card)
signal opponent_played_card(card: Card)
signal own_played_rts(move: String)
signal opponent_played_rts(move: String)
@export var player_1_deck: Array[Card] @export var player_1_deck: Array[Card]
@export var player_2_deck: Array[Card] @export var player_2_deck: Array[Card]
@ -7,6 +13,8 @@ extends Control
@onready var opponent_side = $Opponent @onready var opponent_side = $Opponent
@onready var start_game_btn = $StartGameButton @onready var start_game_btn = $StartGameButton
var id_to_card: Dictionary = {}
var player_action_queue: Dictionary var player_action_queue: Dictionary
var player_1_action: Action: var player_1_action: Action:
get: get:
@ -19,14 +27,30 @@ var player_2_action: Action:
set(value): set(value):
player_action_queue[MatchManager.PLAYER_2_ID] = value player_action_queue[MatchManager.PLAYER_2_ID] = value
func _ready() -> void: var id
var signal_connected := false
func init(player_id: int) -> void:
id = player_id
id_to_card.clear()
var cards = player_1_deck.duplicate()
cards.append_array(player_2_deck)
for card in cards:
if card.id not in id_to_card:
id_to_card[card.id] = card
match_manager.init({ match_manager.init({
MatchManager.PLAYER_1_ID: player_1_deck, MatchManager.PLAYER_1_ID: player_1_deck,
MatchManager.PLAYER_2_ID: player_2_deck MatchManager.PLAYER_2_ID: player_2_deck
}) })
own_side.attach(match_manager) own_side.attach(match_manager, player_id == MatchManager.PLAYER_1_ID)
opponent_side.attach(match_manager) opponent_side.attach(match_manager, player_id == MatchManager.PLAYER_2_ID)
match_manager.state_transitioned.connect(_on_match_manager_state_transitioned)
if !signal_connected:
match_manager.state_transitioned.connect(_on_match_manager_state_transitioned)
signal_connected = true
var transition_history: Array[PhaseTransition] = [] var transition_history: Array[PhaseTransition] = []
func _on_match_manager_state_transitioned(transition: PhaseTransition): func _on_match_manager_state_transitioned(transition: PhaseTransition):
@ -35,28 +59,100 @@ func _on_match_manager_state_transitioned(transition: PhaseTransition):
print("Phase: ", Match.phase_to_str(transition.from), " -> ", Match.phase_to_str(transition.to)) print("Phase: ", Match.phase_to_str(transition.from), " -> ", Match.phase_to_str(transition.to))
func _on_start_game_button_button_up() -> void: func _on_start_game_button_button_up() -> void:
#match_manager.resolve({})
pass
func rpc_start_game() -> void:
match_manager.resolve({}) match_manager.resolve({})
func _on_own_play_card(card: Card) -> void: func rpc_own_play_card(id: String) -> void:
player_1_action = ActionPlayCard.new(card) if !id.is_empty():
var card = id_to_card[id]
player_1_action = ActionPlayCard.new(card)
else:
player_1_action = ActionSkipCard.new()
print(self.id, " rpc_own_play_card", player_1_action, player_2_action)
if player_2_action: if player_2_action:
match_manager.resolve(player_action_queue) match_manager.resolve(player_action_queue)
player_action_queue.clear() player_action_queue.clear()
func _on_opponent_play_card(card: Card) -> void: func _on_own_play_card(card: Card) -> void:
player_2_action = ActionPlayCard.new(card) if card:
player_1_action = ActionPlayCard.new(card)
own_played_card.emit(card)
else:
player_1_action = ActionSkipCard.new()
own_played_card.emit(null)
print(id, " _on_own_play_card", player_1_action, player_2_action)
if player_2_action:
match_manager.resolve(player_action_queue)
player_action_queue.clear()
func rpc_opponent_play_card(id: String) -> void:
if !id.is_empty():
var card = id_to_card[id]
player_2_action = ActionPlayCard.new(card)
else:
player_2_action = ActionSkipCard.new()
print(self.id , " rpc_opponent_play_card", player_1_action, player_2_action)
if player_1_action: if player_1_action:
match_manager.resolve(player_action_queue) match_manager.resolve(player_action_queue)
player_action_queue.clear() player_action_queue.clear()
func _on_opponent_play_card(card: Card) -> void:
if card:
player_2_action = ActionPlayCard.new(card)
opponent_played_card.emit(card)
else:
player_2_action = ActionSkipCard.new()
opponent_played_card.emit(null)
print(id, " _on_opponent_play_card", player_1_action, player_2_action)
if player_1_action:
match_manager.resolve(player_action_queue)
player_action_queue.clear()
func rpc_own_rps_move(move: String) -> void:
player_1_action = ActionRPSMove.new(move)
print(id, " rpc_own_rps_move", player_1_action, player_2_action, move)
if player_2_action:
match_manager.resolve(player_action_queue)
player_action_queue.clear()
func _on_own_rps_move(move: String) -> void: func _on_own_rps_move(move: String) -> void:
player_1_action = ActionRPSMove.new(move) player_1_action = ActionRPSMove.new(move)
own_played_rts.emit(move)
print(id, " _on_own_rps_move", player_1_action, player_2_action, move)
if player_2_action: if player_2_action:
match_manager.resolve(player_action_queue) match_manager.resolve(player_action_queue)
player_action_queue.clear() player_action_queue.clear()
func rpc_opponent_rps_move(move: String) -> void:
player_2_action = ActionRPSMove.new(move)
print(id, " rpc_opponent_rps_move", player_1_action, player_2_action, move)
if player_1_action:
match_manager.resolve(player_action_queue)
player_action_queue.clear()
func _on_opponent_rps_move(move: String) -> void: func _on_opponent_rps_move(move: String) -> void:
player_2_action = ActionRPSMove.new(move) player_2_action = ActionRPSMove.new(move)
opponent_played_rts.emit(move)
print(id, " rpc_opponent_rps_move", player_1_action, player_2_action, move)
if player_1_action: if player_1_action:
match_manager.resolve(player_action_queue) match_manager.resolve(player_action_queue)
player_action_queue.clear() player_action_queue.clear()

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://bgc0u117jqyr1"] [gd_scene load_steps=8 format=3 uid="uid://l2ehohbd1xhk"]
[ext_resource type="Script" path="res://demo_game.gd" id="1_jn16u"] [ext_resource type="Script" path="res://demo_game.gd" id="1_jn16u"]
[ext_resource type="Script" path="res://player_side.gd" id="2_w4tnt"] [ext_resource type="Script" path="res://player_side.gd" id="2_w4tnt"]
@ -16,8 +16,8 @@ anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("1_jn16u") script = ExtResource("1_jn16u")
player_1_deck = Array[ExtResource("2_xuft0")]([ExtResource("3_we1tk"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk")]) player_1_deck = Array[ExtResource("2_xuft0")]([ExtResource("3_we1tk"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk"), ExtResource("5_3cm5x")])
player_2_deck = Array[ExtResource("2_xuft0")]([ExtResource("5_3cm5x"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk")]) player_2_deck = Array[ExtResource("2_xuft0")]([ExtResource("5_3cm5x"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk"), ExtResource("4_kkhfk"), ExtResource("3_we1tk")])
[node name="Own" type="VBoxContainer" parent="." node_paths=PackedStringArray("deck", "monster_name_label", "monster_health_label", "incoming_damage_label", "energy_label")] [node name="Own" type="VBoxContainer" parent="." node_paths=PackedStringArray("deck", "monster_name_label", "monster_health_label", "incoming_damage_label", "energy_label")]
layout_mode = 1 layout_mode = 1

View file

@ -130,3 +130,211 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'" Remove-Item -Recurse -Force '{temp_dir}'"
[preset.2]
name="Android"
platform="Android"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path=""
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.2.options]
custom_template/debug=""
custom_template/release=""
gradle_build/use_gradle_build=false
gradle_build/gradle_build_directory=""
gradle_build/android_source_template=""
gradle_build/compress_native_libraries=false
gradle_build/export_format=0
gradle_build/min_sdk=""
gradle_build/target_sdk=""
architectures/armeabi-v7a=false
architectures/arm64-v8a=true
architectures/x86=false
architectures/x86_64=false
version/code=1
version/name=""
package/unique_name="com.example.$genname"
package/name=""
package/signed=true
package/app_category=2
package/retain_data_on_uninstall=false
package/exclude_from_recents=false
package/show_in_android_tv=false
package/show_in_app_library=true
package/show_as_launcher_app=false
launcher_icons/main_192x192=""
launcher_icons/adaptive_foreground_432x432=""
launcher_icons/adaptive_background_432x432=""
graphics/opengl_debug=false
xr_features/xr_mode=0
screen/immersive_mode=true
screen/support_small=true
screen/support_normal=true
screen/support_large=true
screen/support_xlarge=true
user_data_backup/allow=false
command_line/extra_args=""
apk_expansion/enable=false
apk_expansion/SALT=""
apk_expansion/public_key=""
permissions/custom_permissions=PackedStringArray()
permissions/access_checkin_properties=false
permissions/access_coarse_location=false
permissions/access_fine_location=false
permissions/access_location_extra_commands=false
permissions/access_mock_location=false
permissions/access_network_state=false
permissions/access_surface_flinger=false
permissions/access_wifi_state=false
permissions/account_manager=false
permissions/add_voicemail=false
permissions/authenticate_accounts=false
permissions/battery_stats=false
permissions/bind_accessibility_service=false
permissions/bind_appwidget=false
permissions/bind_device_admin=false
permissions/bind_input_method=false
permissions/bind_nfc_service=false
permissions/bind_notification_listener_service=false
permissions/bind_print_service=false
permissions/bind_remoteviews=false
permissions/bind_text_service=false
permissions/bind_vpn_service=false
permissions/bind_wallpaper=false
permissions/bluetooth=false
permissions/bluetooth_admin=false
permissions/bluetooth_privileged=false
permissions/brick=false
permissions/broadcast_package_removed=false
permissions/broadcast_sms=false
permissions/broadcast_sticky=false
permissions/broadcast_wap_push=false
permissions/call_phone=false
permissions/call_privileged=false
permissions/camera=false
permissions/capture_audio_output=false
permissions/capture_secure_video_output=false
permissions/capture_video_output=false
permissions/change_component_enabled_state=false
permissions/change_configuration=false
permissions/change_network_state=false
permissions/change_wifi_multicast_state=false
permissions/change_wifi_state=false
permissions/clear_app_cache=false
permissions/clear_app_user_data=false
permissions/control_location_updates=false
permissions/delete_cache_files=false
permissions/delete_packages=false
permissions/device_power=false
permissions/diagnostic=false
permissions/disable_keyguard=false
permissions/dump=false
permissions/expand_status_bar=false
permissions/factory_test=false
permissions/flashlight=false
permissions/force_back=false
permissions/get_accounts=false
permissions/get_package_size=false
permissions/get_tasks=false
permissions/get_top_activity_info=false
permissions/global_search=false
permissions/hardware_test=false
permissions/inject_events=false
permissions/install_location_provider=false
permissions/install_packages=false
permissions/install_shortcut=false
permissions/internal_system_window=false
permissions/internet=false
permissions/kill_background_processes=false
permissions/location_hardware=false
permissions/manage_accounts=false
permissions/manage_app_tokens=false
permissions/manage_documents=false
permissions/manage_external_storage=false
permissions/master_clear=false
permissions/media_content_control=false
permissions/modify_audio_settings=false
permissions/modify_phone_state=false
permissions/mount_format_filesystems=false
permissions/mount_unmount_filesystems=false
permissions/nfc=false
permissions/persistent_activity=false
permissions/post_notifications=false
permissions/process_outgoing_calls=false
permissions/read_calendar=false
permissions/read_call_log=false
permissions/read_contacts=false
permissions/read_external_storage=false
permissions/read_frame_buffer=false
permissions/read_history_bookmarks=false
permissions/read_input_state=false
permissions/read_logs=false
permissions/read_phone_state=false
permissions/read_profile=false
permissions/read_sms=false
permissions/read_social_stream=false
permissions/read_sync_settings=false
permissions/read_sync_stats=false
permissions/read_user_dictionary=false
permissions/reboot=false
permissions/receive_boot_completed=false
permissions/receive_mms=false
permissions/receive_sms=false
permissions/receive_wap_push=false
permissions/record_audio=false
permissions/reorder_tasks=false
permissions/restart_packages=false
permissions/send_respond_via_message=false
permissions/send_sms=false
permissions/set_activity_watcher=false
permissions/set_alarm=false
permissions/set_always_finish=false
permissions/set_animation_scale=false
permissions/set_debug_app=false
permissions/set_orientation=false
permissions/set_pointer_speed=false
permissions/set_preferred_applications=false
permissions/set_process_limit=false
permissions/set_time=false
permissions/set_time_zone=false
permissions/set_wallpaper=false
permissions/set_wallpaper_hints=false
permissions/signal_persistent_processes=false
permissions/status_bar=false
permissions/subscribed_feeds_read=false
permissions/subscribed_feeds_write=false
permissions/system_alert_window=false
permissions/transmit_ir=false
permissions/uninstall_shortcut=false
permissions/update_device_stats=false
permissions/use_credentials=false
permissions/use_sip=false
permissions/vibrate=false
permissions/wake_lock=false
permissions/write_apn_settings=false
permissions/write_calendar=false
permissions/write_call_log=false
permissions/write_contacts=false
permissions/write_external_storage=false
permissions/write_gservices=false
permissions/write_history_bookmarks=false
permissions/write_profile=false
permissions/write_secure_settings=false
permissions/write_settings=false
permissions/write_sms=false
permissions/write_social_stream=false
permissions/write_sync_settings=false
permissions/write_user_dictionary=false

87
main.gd
View file

@ -1,41 +1,41 @@
extends Node extends Node
class_name MainNode
const PORT = 25565 const PORT = 25565
const PORT_RANGE := 10 const PORT_RANGE := 10
const MAX_CONNECTIONS = 20 const MAX_CONNECTIONS = 20
var counter = 0
@onready var before_connect_container = get_node("BeforeConnect") as Container @onready var before_connect_container = get_node("BeforeConnect") as Container
@onready var host_text_edit = get_node("%HostTextEdit") as TextEdit
@onready var connect_button = get_node("%ConnectButton") as Button @onready var connect_button = get_node("%ConnectButton") as Button
@onready var host_button = get_node("%HostButton") as Button @onready var host_button = get_node("%HostButton") as Button
@onready var server_discovery = get_node("%ServerDiscovery") as ServerDiscovery @onready var server_discovery = get_node("%ServerDiscovery") as ServerDiscovery
@onready var after_connect_container = get_node("%AfterConnect") as Container @onready var after_connect_container = get_node("%AfterConnect") as Node
@onready var counter_label = get_node("%CounterLabel") as Label
@onready var decrement_button = get_node("%DecrementButton") as Button
@onready var increment_button = get_node("%IncrementButton") as Button
@onready var disconnect_button = get_node("%DisconnectButton") as Button @onready var disconnect_button = get_node("%DisconnectButton") as Button
@onready var start_game_button = get_node("%StartGameButton") as Button
@onready var demo_game = get_node("AfterConnect/DemoGame") as DemoGame
@onready var start_game_button = (get_node("AfterConnect/DemoGame") as DemoGame).start_game_btn
var active_port: int var active_port: int
var server_buttons: Dictionary = Dictionary() var server_buttons: Dictionary = Dictionary()
var base_seed: int
func _clean_room(): func _clean_room():
# this is if someone left the room and we will just clean the game room again # this is if someone left the room and we will just clean the game room again
# should only called on host # should only called on host
_set_counter(0) # need to clean for server
pass pass
func _on_start_game_clicked(): func _on_start_game_clicked():
if !multiplayer.multiplayer_peer: if !multiplayer.multiplayer_peer:
return return
if !multiplayer.get_unique_id() != 1: if !multiplayer.is_server():
return return
if (multiplayer.get_peers().size() == 0): if (multiplayer.get_peers().size() == 0):
return return
# do start game here, should only run on host # do start game here, should only run on host
_start_game.rpc()
pass pass
func _ready() -> void: func _ready() -> void:
@ -51,13 +51,45 @@ func _ready() -> void:
#multiplayer.connection_failed.connect(_on_connected_fail) #multiplayer.connection_failed.connect(_on_connected_fail)
multiplayer.server_disconnected.connect(_on_server_disconnected) multiplayer.server_disconnected.connect(_on_server_disconnected)
increment_button.button_up.connect(func(): _increment.rpc())
decrement_button.button_up.connect(func(): _decrement.rpc())
disconnect_button.button_up.connect(_on_disconnect_clicked) disconnect_button.button_up.connect(_on_disconnect_clicked)
connect_button.get_parent().remove_child(connect_button) connect_button.get_parent().remove_child(connect_button)
server_discovery.server_added.connect(_on_server_added) server_discovery.server_added.connect(_on_server_added)
server_discovery.server_removed.connect(_on_server_removed) server_discovery.server_removed.connect(_on_server_removed)
demo_game.own_played_card.connect(func (card): _on_own_played_card.rpc(card.id if card else ""))
demo_game.opponent_played_card.connect(func (card): _on_opponent_played_card.rpc(card.id if card else ""))
demo_game.own_played_rts.connect(func (move): _on_own_played_rts.rpc(move))
demo_game.opponent_played_rts.connect(func (move): _on_opponent_played_rts.rpc(move))
@rpc("any_peer", "call_remote", "reliable")
func _on_own_played_card(card_id: String):
demo_game.rpc_own_play_card(card_id)
@rpc("any_peer", "call_remote", "reliable")
func _on_opponent_played_card(card_id: String):
demo_game.rpc_opponent_play_card(card_id)
@rpc("any_peer", "call_remote", "reliable")
func _on_own_played_rts(move: String):
demo_game.rpc_own_rps_move(move)
@rpc("any_peer", "call_remote", "reliable")
func _on_opponent_played_rts(move: String):
demo_game.rpc_opponent_rps_move(move)
@rpc("authority", "call_local", "reliable")
func _sync_seed(seed: int):
seed(seed)
@rpc("authority", "call_local", "reliable")
func _start_game():
if multiplayer.is_server():
demo_game.init(MatchManager.PLAYER_1_ID)
else:
demo_game.init(MatchManager.PLAYER_2_ID)
demo_game.rpc_start_game()
func _on_disconnect_clicked(): func _on_disconnect_clicked():
if (multiplayer.is_server()): if (multiplayer.is_server()):
@ -118,8 +150,12 @@ func _on_host_pressed():
_on_connected_ok() _on_connected_ok()
start_game_button.disabled = true
start_game_button.text = "Start Game (Not enough player)" start_game_button.text = "Start Game (Not enough player)"
base_seed = randi()
_sync_seed.rpc(base_seed)
server_discovery.enable_server(active_port) server_discovery.enable_server(active_port)
func is_port_available(port: int) -> bool: func is_port_available(port: int) -> bool:
@ -133,26 +169,13 @@ func is_port_available(port: int) -> bool:
else: else:
return false return false
@rpc("any_peer", "call_local")
func _increment():
counter += 1
counter_label.text = str(counter)
@rpc("any_peer", "call_local")
func _decrement():
counter -= 1
counter_label.text = str(counter)
@rpc("authority", "call_remote")
func _set_counter(value: int):
counter = value
counter_label.text = str(counter)
func _on_player_connected(id: int): func _on_player_connected(id: int):
if multiplayer.get_unique_id() == 1: if multiplayer.get_unique_id() == 1:
_set_counter.rpc_id(id, counter)
_sync_seed.rpc(base_seed)
if (multiplayer.get_peers().size() > 0): if (multiplayer.get_peers().size() > 0):
start_game_button.disabled = false
start_game_button.text = "Start Game" start_game_button.text = "Start Game"
server_discovery.disable_server() server_discovery.disable_server()
@ -165,22 +188,20 @@ func _on_player_disconnected(id):
if (id != 1 and multiplayer.get_unique_id() == 1): if (id != 1 and multiplayer.get_unique_id() == 1):
_clean_room() _clean_room()
start_game_button.disabled = true
start_game_button.text = "Start Game (Not enough player)" start_game_button.text = "Start Game (Not enough player)"
server_discovery.enable_server(active_port) server_discovery.enable_server(active_port)
func _on_connected_ok(): func _on_connected_ok():
$AfterConnect.visible = true $AfterConnect.visible = true
$BeforeConnect.visible = false $BeforeConnect.visible = false
counter_label.text = str(counter)
if (multiplayer.is_server()): if (multiplayer.is_server()):
disconnect_button.text = "Disconnect (Host)" disconnect_button.text = "Disconnect (Host)"
if start_game_button.get_parent() != after_connect_container: start_game_button.visible = true
after_connect_container.add_child(start_game_button)
else: else:
disconnect_button.text = "Disconnect" disconnect_button.text = "Disconnect"
if start_game_button.get_parent() == after_connect_container: start_game_button.visible = false
after_connect_container.remove_child(start_game_button)
func _on_connected_fail(): func _on_connected_fail():
pass pass

View file

@ -1,7 +1,8 @@
[gd_scene load_steps=3 format=3 uid="uid://c7gn46af6whf8"] [gd_scene load_steps=4 format=3 uid="uid://c7gn46af6whf8"]
[ext_resource type="Script" path="res://main.gd" id="1_e0ud3"] [ext_resource type="Script" path="res://main.gd" id="1_e0ud3"]
[ext_resource type="Script" path="res://server_discovery.gd" id="2_hed18"] [ext_resource type="Script" path="res://server_discovery.gd" id="2_hed18"]
[ext_resource type="PackedScene" uid="uid://l2ehohbd1xhk" path="res://demo_game.tscn" id="3_2ln6b"]
[node name="Main" type="Control"] [node name="Main" type="Control"]
layout_mode = 3 layout_mode = 3
@ -28,18 +29,6 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
alignment = 1 alignment = 1
[node name="HostTextEdit" type="TextEdit" parent="BeforeConnect"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
placeholder_text = "192.168.*.*"
[node name="RefreshButton" type="Button" parent="BeforeConnect"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 64)
layout_mode = 2
text = "Refresh"
[node name="HostButton" type="Button" parent="BeforeConnect"] [node name="HostButton" type="Button" parent="BeforeConnect"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 64) custom_minimum_size = Vector2(0, 64)
@ -59,54 +48,24 @@ unique_name_in_owner = true
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("2_hed18") script = ExtResource("2_hed18")
[node name="AfterConnect" type="VBoxContainer" parent="."] [node name="AfterConnect" type="Control" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 8 anchors_preset = 15
anchor_left = 0.5 anchor_right = 1.0
anchor_top = 0.5 anchor_bottom = 1.0
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -187.5
offset_top = -88.5
offset_right = 187.5
offset_bottom = 88.5
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
[node name="CounterLabel" type="Label" parent="AfterConnect"] [node name="DemoGame" parent="AfterConnect" instance=ExtResource("3_2ln6b")]
unique_name_in_owner = true layout_mode = 1
layout_mode = 2
size_flags_vertical = 3
theme_override_font_sizes/font_size = 64
text = "1"
horizontal_alignment = 1
vertical_alignment = 1
[node name="DisconnectButton" type="Button" parent="AfterConnect"] [node name="DisconnectButton" type="Button" parent="AfterConnect"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 offset_left = 966.0
offset_right = 1152.0
offset_bottom = 31.0
size_flags_horizontal = 8
text = "Disconnect" text = "Disconnect"
[node name="Actions" type="HBoxContainer" parent="AfterConnect"]
layout_mode = 2
[node name="DecrementButton" type="Button" parent="AfterConnect/Actions"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "-"
[node name="IncrementButton" type="Button" parent="AfterConnect/Actions"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "+"
[node name="StartGameButton" type="Button" parent="AfterConnect"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Start Game"

View file

@ -10,10 +10,15 @@ signal rps_move(move: String)
@export var energy_label: Label @export var energy_label: Label
var match_manager: MatchManager var match_manager: MatchManager
var show_buttons: bool
var signal_connected: bool
func attach(match_manager: MatchManager): func attach(match_manager: MatchManager, show_buttons: bool = true):
self.show_buttons = show_buttons
self.match_manager = match_manager self.match_manager = match_manager
match_manager.state_transitioned.connect(_on_update) if !signal_connected:
match_manager.state_transitioned.connect(_on_update)
signal_connected = true
func _on_update(transition): func _on_update(transition):
for child in deck.get_children(): for child in deck.get_children():
@ -28,13 +33,28 @@ func _on_update(transition):
monster_health_label.text = "Health: " + str(monster.health) monster_health_label.text = "Health: " + str(monster.health)
incoming_damage_label.text = "Incoming Damage: " + str(monster.health_delta) incoming_damage_label.text = "Incoming Damage: " + str(monster.health_delta)
if match_manager.phase in [Match.Phase.SUMMON, Match.Phase.SUPPORT_1, Match.Phase.SUPPORT_2]: if match_manager.phase in [Match.Phase.SUMMON, Match.Phase.SUPPORT_1, Match.Phase.SUPPORT_2]:
if (
match_manager.phase != Match.Phase.SUMMON && show_buttons
) or (
match_manager.phase == Match.Phase.SUMMON and player.monster and player.monster.health > 0 && show_buttons
):
var skip_btn = Button.new()
skip_btn.text = "Skip"
skip_btn.button_up.connect(func (): play_card.emit(null))
deck.add_child(skip_btn)
for card: Card in player.hand: for card: Card in player.hand:
if match_manager.phase == Match.Phase.SUMMON and card is not MonsterCard: #if match_manager.phase == Match.Phase.SUMMON and card is not MonsterCard:
continue #continue
if (match_manager.phase == Match.Phase.SUPPORT_1 or match_manager.phase == Match.Phase.SUPPORT_2) and card is not SupportCard: #if (match_manager.phase == Match.Phase.SUPPORT_1 or match_manager.phase == Match.Phase.SUPPORT_2) and card is not SupportCard:
continue #continue
if match_manager.phase == Match.Phase.SUPPORT_1 and card.type == "red": #if match_manager.phase == Match.Phase.SUPPORT_1 and card.type == "red":
#continue
if !show_buttons :
continue continue
var btn = Button.new() var btn = Button.new()
btn.text = card.id btn.text = card.id
btn.button_up.connect(func (): play_card.emit(card)) btn.button_up.connect(func (): play_card.emit(card))
@ -44,10 +64,16 @@ func _on_update(transition):
card is SupportCard and match_manager.phase != Match.Phase.SUPPORT_1 and match_manager.phase != Match.Phase.SUPPORT_2 card is SupportCard and match_manager.phase != Match.Phase.SUPPORT_1 and match_manager.phase != Match.Phase.SUPPORT_2
) or ( ) or (
card is SupportCard and card.type == "red" and match_manager.phase != Match.Phase.SUPPORT_2 card is SupportCard and card.type == "red" and match_manager.phase != Match.Phase.SUPPORT_2
) or (
card is MonsterCard and match_manager.phase == Match.Phase.SUMMON and player.monster and player.monster.health > 0
) )
deck.add_child(btn) deck.add_child(btn)
if match_manager.phase == Match.Phase.RPS: if match_manager.phase == Match.Phase.RPS:
for move in ["rock", "paper", "scissors"]: for move in ["rock", "paper", "scissors"]:
if !show_buttons:
continue
var btn = Button.new() var btn = Button.new()
btn.text = move btn.text = move
btn.button_up.connect(func (): rps_move.emit(move)) btn.button_up.connect(func (): rps_move.emit(move))

View file

@ -22,3 +22,4 @@ Match="*res://tcg/match/match.gd"
[rendering] [rendering]
renderer/rendering_method="mobile" renderer/rendering_method="mobile"
textures/vram_compression/import_etc2_astc=true

View file

@ -0,0 +1,2 @@
extends Action
class_name ActionSkipCard

View file

@ -29,6 +29,14 @@ func init(decks: Dictionary):
cleanup() cleanup()
for player_id in [PLAYER_1_ID, PLAYER_2_ID]: for player_id in [PLAYER_1_ID, PLAYER_2_ID]:
var deck_shuffled = decks[player_id].duplicate() as Array[Card] var deck_shuffled = decks[player_id].duplicate() as Array[Card]
var first_monster = deck_shuffled.filter(func (card): return card is MonsterCard)[0]
var first_monster_idx = deck_shuffled.find(first_monster)
deck_shuffled.pop_at(first_monster_idx)
var zero_idx_card = deck_shuffled.pop_at(0)
deck_shuffled.insert(0, first_monster)
deck_shuffled.insert(first_monster_idx, zero_idx_card)
deck_shuffled.shuffle() deck_shuffled.shuffle()
players[player_id] = MatchPlayer.new(player_id, deck_shuffled) players[player_id] = MatchPlayer.new(player_id, deck_shuffled)
@ -75,11 +83,13 @@ func resolve(action_by_player_id: Dictionary) -> PhaseTransition:
"player": player_1, "player": player_1,
"card": player_1_action.card "card": player_1_action.card
}) })
player_1.hand.erase(player_1_action.card)
if player_2_action is ActionPlayCard: if player_2_action is ActionPlayCard:
support_cards.append({ support_cards.append({
"player": player_2, "player": player_2,
"card": player_2_action.card "card": player_2_action.card
}) })
player_2.hand.erase(player_2_action.card)
support_cards.sort_custom(func(a, b): return a.card.priority < b.card.priority) support_cards.sort_custom(func(a, b): return a.card.priority < b.card.priority)
for played_card in support_cards: for played_card in support_cards:
var player: MatchPlayer = played_card.player var player: MatchPlayer = played_card.player
@ -102,11 +112,13 @@ func resolve(action_by_player_id: Dictionary) -> PhaseTransition:
"player": player_1, "player": player_1,
"card": player_1_action.card "card": player_1_action.card
}) })
player_1.hand.erase(player_1_action.card)
if player_2_action is ActionPlayCard: if player_2_action is ActionPlayCard:
support_cards.append({ support_cards.append({
"player": player_2, "player": player_2,
"card": player_2_action.card "card": player_2_action.card
}) })
player_2.hand.erase(player_2_action.card)
support_cards.sort_custom(func(a, b): return a.card.priority < b.card.priority) support_cards.sort_custom(func(a, b): return a.card.priority < b.card.priority)
for played_card in support_cards: for played_card in support_cards:
var player: MatchPlayer = played_card.player var player: MatchPlayer = played_card.player