feature updates
This commit is contained in:
@@ -7,7 +7,13 @@ enum State {
|
||||
DECK_BUILDER,
|
||||
GAME_SETUP,
|
||||
PLAYING,
|
||||
PAUSED
|
||||
PAUSED,
|
||||
LOGIN,
|
||||
REGISTER,
|
||||
ONLINE_LOBBY,
|
||||
ONLINE_GAME,
|
||||
PROFILE,
|
||||
LEADERBOARD
|
||||
}
|
||||
|
||||
var current_state: State = State.MENU
|
||||
@@ -20,6 +26,16 @@ const DECK_BUILDER_SIZE := Vector2i(1600, 900)
|
||||
const GAME_SETUP_SIZE := Vector2i(800, 600)
|
||||
# Game window size
|
||||
const GAME_SIZE := Vector2i(2160, 980)
|
||||
# Login screen size
|
||||
const LOGIN_SIZE := Vector2i(400, 500)
|
||||
# Register screen size
|
||||
const REGISTER_SIZE := Vector2i(400, 600)
|
||||
# Online lobby size
|
||||
const ONLINE_LOBBY_SIZE := Vector2i(600, 700)
|
||||
# Profile screen size
|
||||
const PROFILE_SIZE := Vector2i(600, 700)
|
||||
# Leaderboard screen size
|
||||
const LEADERBOARD_SIZE := Vector2i(600, 700)
|
||||
|
||||
# Scene references
|
||||
var main_menu: MainMenu = null
|
||||
@@ -27,12 +43,26 @@ var deck_builder: DeckBuilder = null
|
||||
var game_setup_menu: GameSetupMenu = null
|
||||
var game_scene: Node3D = null
|
||||
var pause_menu: PauseMenu = null
|
||||
var login_screen: LoginScreen = null
|
||||
var register_screen: RegisterScreen = null
|
||||
var online_lobby: OnlineLobby = null
|
||||
var profile_screen: ProfileScreen = null
|
||||
var leaderboard_screen: LeaderboardScreen = null
|
||||
|
||||
# Selected decks for gameplay
|
||||
var selected_deck: Deck = null
|
||||
var player1_deck: Array = [] # Card IDs for player 1
|
||||
var player2_deck: Array = [] # Card IDs for player 2
|
||||
|
||||
# AI settings
|
||||
var is_vs_ai: bool = false
|
||||
var ai_difficulty: int = AIStrategy.Difficulty.NORMAL
|
||||
|
||||
# Online game settings
|
||||
var is_online_game: bool = false
|
||||
var online_game_data: Dictionary = {}
|
||||
var online_pause_menu: Control = null
|
||||
|
||||
# Preload the main game scene script
|
||||
const MainScript = preload("res://scripts/Main.gd")
|
||||
|
||||
@@ -52,6 +82,18 @@ func _input(event: InputEvent) -> void:
|
||||
_show_pause_menu()
|
||||
State.PAUSED:
|
||||
_hide_pause_menu()
|
||||
State.LOGIN:
|
||||
_on_login_back()
|
||||
State.REGISTER:
|
||||
_on_register_back()
|
||||
State.ONLINE_LOBBY:
|
||||
_on_online_lobby_back()
|
||||
State.ONLINE_GAME:
|
||||
_show_online_pause_menu()
|
||||
State.PROFILE:
|
||||
_on_profile_back()
|
||||
State.LEADERBOARD:
|
||||
_on_leaderboard_back()
|
||||
|
||||
func _show_main_menu() -> void:
|
||||
# Clean up any existing game
|
||||
@@ -86,12 +128,37 @@ func _show_main_menu() -> void:
|
||||
game_setup_menu.queue_free()
|
||||
game_setup_menu = null
|
||||
|
||||
# Create main menu
|
||||
# Clean up login screen if exists
|
||||
if login_screen:
|
||||
login_screen.queue_free()
|
||||
login_screen = null
|
||||
|
||||
# Clean up register screen if exists
|
||||
if register_screen:
|
||||
register_screen.queue_free()
|
||||
register_screen = null
|
||||
|
||||
# Clean up online lobby if exists
|
||||
if online_lobby:
|
||||
online_lobby.queue_free()
|
||||
online_lobby = null
|
||||
|
||||
# Clean up profile screen if exists
|
||||
if profile_screen:
|
||||
profile_screen.queue_free()
|
||||
profile_screen = null
|
||||
|
||||
# Clean up leaderboard screen if exists
|
||||
if leaderboard_screen:
|
||||
leaderboard_screen.queue_free()
|
||||
leaderboard_screen = null
|
||||
|
||||
if not main_menu:
|
||||
main_menu = MainMenu.new()
|
||||
add_child(main_menu)
|
||||
main_menu.play_game.connect(_on_start_game)
|
||||
main_menu.deck_builder.connect(_on_deck_builder)
|
||||
main_menu.online_game.connect(_on_online_game)
|
||||
|
||||
main_menu.visible = true
|
||||
current_state = State.MENU
|
||||
@@ -169,9 +236,11 @@ func _on_game_setup_back() -> void:
|
||||
_show_main_menu()
|
||||
|
||||
|
||||
func _on_game_setup_start(p1_deck: Array, p2_deck: Array) -> void:
|
||||
func _on_game_setup_start(p1_deck: Array, p2_deck: Array, p_is_vs_ai: bool = false, p_ai_difficulty: int = AIStrategy.Difficulty.NORMAL) -> void:
|
||||
player1_deck = p1_deck
|
||||
player2_deck = p2_deck
|
||||
is_vs_ai = p_is_vs_ai
|
||||
ai_difficulty = p_ai_difficulty
|
||||
|
||||
if game_setup_menu:
|
||||
game_setup_menu.visible = false
|
||||
@@ -234,6 +303,10 @@ func _start_new_game() -> void:
|
||||
if player2_deck.size() > 0:
|
||||
game_scene.player2_deck = player2_deck
|
||||
|
||||
# Pass AI configuration
|
||||
game_scene.is_vs_ai = is_vs_ai
|
||||
game_scene.ai_difficulty = ai_difficulty
|
||||
|
||||
add_child(game_scene)
|
||||
|
||||
# Create pause menu
|
||||
@@ -264,3 +337,405 @@ func _on_restart_game() -> void:
|
||||
|
||||
func _on_return_to_menu() -> void:
|
||||
_show_main_menu()
|
||||
|
||||
|
||||
# ======= ONLINE PLAY =======
|
||||
|
||||
func _on_online_game() -> void:
|
||||
# Hide menu
|
||||
if main_menu:
|
||||
main_menu.visible = false
|
||||
|
||||
# Check if already authenticated
|
||||
if NetworkManager and NetworkManager.is_authenticated:
|
||||
_show_online_lobby()
|
||||
else:
|
||||
_show_login_screen()
|
||||
|
||||
|
||||
func _show_login_screen() -> void:
|
||||
# Switch to login screen window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_size(LOGIN_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - LOGIN_SIZE.x) / 2,
|
||||
(screen.y - LOGIN_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to login size
|
||||
get_tree().root.content_scale_size = LOGIN_SIZE
|
||||
|
||||
# Create login screen
|
||||
if not login_screen:
|
||||
login_screen = LoginScreen.new()
|
||||
add_child(login_screen)
|
||||
login_screen.login_successful.connect(_on_login_successful)
|
||||
login_screen.register_requested.connect(_on_register_requested)
|
||||
login_screen.back_pressed.connect(_on_login_back)
|
||||
|
||||
login_screen.visible = true
|
||||
login_screen.focus_email()
|
||||
current_state = State.LOGIN
|
||||
|
||||
|
||||
func _on_login_back() -> void:
|
||||
if login_screen:
|
||||
login_screen.visible = false
|
||||
login_screen.clear_form()
|
||||
_show_main_menu()
|
||||
|
||||
|
||||
func _on_login_successful(_user_data: Dictionary) -> void:
|
||||
if login_screen:
|
||||
login_screen.visible = false
|
||||
login_screen.clear_form()
|
||||
_show_online_lobby()
|
||||
|
||||
|
||||
func _on_register_requested() -> void:
|
||||
if login_screen:
|
||||
login_screen.visible = false
|
||||
login_screen.clear_form()
|
||||
_show_register_screen()
|
||||
|
||||
|
||||
func _show_register_screen() -> void:
|
||||
# Switch to register screen window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_size(REGISTER_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - REGISTER_SIZE.x) / 2,
|
||||
(screen.y - REGISTER_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to register size
|
||||
get_tree().root.content_scale_size = REGISTER_SIZE
|
||||
|
||||
# Create register screen
|
||||
if not register_screen:
|
||||
register_screen = RegisterScreen.new()
|
||||
add_child(register_screen)
|
||||
register_screen.registration_successful.connect(_on_registration_successful)
|
||||
register_screen.login_requested.connect(_on_login_from_register)
|
||||
register_screen.back_pressed.connect(_on_register_back)
|
||||
|
||||
register_screen.visible = true
|
||||
register_screen.focus_email()
|
||||
current_state = State.REGISTER
|
||||
|
||||
|
||||
func _on_register_back() -> void:
|
||||
if register_screen:
|
||||
register_screen.visible = false
|
||||
register_screen.clear_form()
|
||||
_show_main_menu()
|
||||
|
||||
|
||||
func _on_registration_successful(_message: String) -> void:
|
||||
# After successful registration, show login screen
|
||||
if register_screen:
|
||||
register_screen.visible = false
|
||||
register_screen.clear_form()
|
||||
_show_login_screen()
|
||||
|
||||
|
||||
func _on_login_from_register() -> void:
|
||||
if register_screen:
|
||||
register_screen.visible = false
|
||||
register_screen.clear_form()
|
||||
_show_login_screen()
|
||||
|
||||
|
||||
func _show_online_lobby() -> void:
|
||||
# Switch to online lobby window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_size(ONLINE_LOBBY_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - ONLINE_LOBBY_SIZE.x) / 2,
|
||||
(screen.y - ONLINE_LOBBY_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to online lobby size
|
||||
get_tree().root.content_scale_size = ONLINE_LOBBY_SIZE
|
||||
|
||||
# Create online lobby
|
||||
if not online_lobby:
|
||||
online_lobby = OnlineLobby.new()
|
||||
add_child(online_lobby)
|
||||
online_lobby.back_pressed.connect(_on_online_lobby_back)
|
||||
online_lobby.game_starting.connect(_on_online_game_starting)
|
||||
online_lobby.profile_requested.connect(_show_profile_screen)
|
||||
online_lobby.leaderboard_requested.connect(_show_leaderboard_screen)
|
||||
|
||||
# Connect to game_ended signal for handling online game completion
|
||||
if NetworkManager and not NetworkManager.game_ended.is_connected(_on_online_game_ended):
|
||||
NetworkManager.game_ended.connect(_on_online_game_ended)
|
||||
|
||||
online_lobby.visible = true
|
||||
current_state = State.ONLINE_LOBBY
|
||||
|
||||
|
||||
func _on_online_lobby_back() -> void:
|
||||
if online_lobby:
|
||||
online_lobby.visible = false
|
||||
_show_main_menu()
|
||||
|
||||
|
||||
func _on_online_game_starting(game_data: Dictionary) -> void:
|
||||
if online_lobby:
|
||||
online_lobby.visible = false
|
||||
|
||||
# Store game data
|
||||
online_game_data = game_data
|
||||
is_online_game = true
|
||||
|
||||
var opponent = game_data.get("opponent", {})
|
||||
print("Starting online game against: ", opponent.get("username", "Unknown"))
|
||||
print("Game ID: ", game_data.get("game_id", ""))
|
||||
print("Local player index: ", game_data.get("your_player_index", 0))
|
||||
print("First player: ", game_data.get("first_player", 0))
|
||||
|
||||
# Switch to game window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, false)
|
||||
DisplayServer.window_set_size(GAME_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - GAME_SIZE.x) / 2,
|
||||
(screen.y - GAME_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to game size
|
||||
get_tree().root.content_scale_size = GAME_SIZE
|
||||
|
||||
_start_online_game(game_data)
|
||||
|
||||
|
||||
func _start_online_game(game_data: Dictionary) -> void:
|
||||
# Make sure game isn't paused
|
||||
get_tree().paused = false
|
||||
|
||||
# Clean up existing game
|
||||
if game_scene:
|
||||
game_scene.queue_free()
|
||||
game_scene = null
|
||||
|
||||
# Reset GameManager state
|
||||
if GameManager:
|
||||
GameManager.is_game_active = false
|
||||
GameManager.game_state = null
|
||||
|
||||
# Create new game scene
|
||||
game_scene = Node3D.new()
|
||||
game_scene.set_script(MainScript)
|
||||
|
||||
# Mark as online game
|
||||
game_scene.is_online_game = true
|
||||
|
||||
# Get the deck ID from NetworkManager (set when joining queue/room)
|
||||
var deck_id = game_data.get("deck_id", "")
|
||||
var local_player_index = game_data.get("your_player_index", 0)
|
||||
|
||||
# Load the selected deck for the local player
|
||||
var local_deck = _load_deck_by_id(deck_id)
|
||||
|
||||
# For online games, player positions are swapped based on index
|
||||
# The local player is always displayed on the bottom (player 1 position visually)
|
||||
# But the game logic uses the server-assigned indices
|
||||
if local_player_index == 0:
|
||||
game_scene.player1_deck = local_deck
|
||||
game_scene.player2_deck = [] # Opponent's deck is hidden
|
||||
else:
|
||||
game_scene.player1_deck = [] # Opponent's deck is hidden
|
||||
game_scene.player2_deck = local_deck
|
||||
|
||||
# Pass game configuration
|
||||
game_scene.is_vs_ai = false
|
||||
game_scene.online_game_data = game_data
|
||||
|
||||
add_child(game_scene)
|
||||
|
||||
# Setup online game specifics after scene is added
|
||||
game_scene.setup_online_game(game_data)
|
||||
|
||||
# Create online pause menu (no restart option, has forfeit)
|
||||
_create_online_pause_menu()
|
||||
|
||||
current_state = State.ONLINE_GAME
|
||||
|
||||
|
||||
func _load_deck_by_id(deck_id: String) -> Array:
|
||||
# Load deck from CardDatabase saved decks or starter decks
|
||||
if deck_id.is_empty():
|
||||
# Use default starter deck
|
||||
return CardDatabase.get_starter_deck_ids("Fire Starter")
|
||||
|
||||
# Check saved decks
|
||||
var saved_decks = CardDatabase.get_saved_decks()
|
||||
for deck in saved_decks:
|
||||
if deck.get("id", "") == deck_id:
|
||||
return deck.get("card_ids", [])
|
||||
|
||||
# Check starter decks
|
||||
var starter_decks = CardDatabase.get_starter_decks()
|
||||
for deck in starter_decks:
|
||||
if deck.get("id", "") == deck_id:
|
||||
return deck.get("card_ids", [])
|
||||
|
||||
# Fallback to first starter deck
|
||||
return CardDatabase.get_starter_deck_ids("Fire Starter")
|
||||
|
||||
|
||||
func _create_online_pause_menu() -> void:
|
||||
if online_pause_menu:
|
||||
online_pause_menu.queue_free()
|
||||
|
||||
online_pause_menu = Control.new()
|
||||
online_pause_menu.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
online_pause_menu.visible = false
|
||||
|
||||
# Semi-transparent background
|
||||
var bg = ColorRect.new()
|
||||
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
bg.color = Color(0, 0, 0, 0.7)
|
||||
online_pause_menu.add_child(bg)
|
||||
|
||||
# Menu container
|
||||
var container = VBoxContainer.new()
|
||||
container.set_anchors_preset(Control.PRESET_CENTER)
|
||||
container.custom_minimum_size = Vector2(300, 200)
|
||||
container.add_theme_constant_override("separation", 20)
|
||||
online_pause_menu.add_child(container)
|
||||
|
||||
# Title
|
||||
var title = Label.new()
|
||||
title.text = "PAUSED"
|
||||
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
title.add_theme_font_size_override("font_size", 32)
|
||||
container.add_child(title)
|
||||
|
||||
# Resume button
|
||||
var resume_btn = Button.new()
|
||||
resume_btn.text = "Resume"
|
||||
resume_btn.custom_minimum_size = Vector2(200, 50)
|
||||
resume_btn.pressed.connect(_hide_online_pause_menu)
|
||||
container.add_child(resume_btn)
|
||||
|
||||
# Forfeit button
|
||||
var forfeit_btn = Button.new()
|
||||
forfeit_btn.text = "Forfeit Game"
|
||||
forfeit_btn.custom_minimum_size = Vector2(200, 50)
|
||||
forfeit_btn.pressed.connect(_on_forfeit_game)
|
||||
container.add_child(forfeit_btn)
|
||||
|
||||
add_child(online_pause_menu)
|
||||
|
||||
|
||||
func _show_online_pause_menu() -> void:
|
||||
if online_pause_menu:
|
||||
online_pause_menu.visible = true
|
||||
get_tree().paused = true
|
||||
|
||||
|
||||
func _hide_online_pause_menu() -> void:
|
||||
if online_pause_menu:
|
||||
online_pause_menu.visible = false
|
||||
get_tree().paused = false
|
||||
|
||||
|
||||
func _on_forfeit_game() -> void:
|
||||
# Send concede to server
|
||||
if NetworkManager:
|
||||
NetworkManager.send_concede()
|
||||
|
||||
_hide_online_pause_menu()
|
||||
# Game end will be handled by the game_ended signal
|
||||
|
||||
|
||||
func _on_online_game_ended(_result: Dictionary) -> void:
|
||||
is_online_game = false
|
||||
online_game_data = {}
|
||||
|
||||
if online_pause_menu:
|
||||
online_pause_menu.queue_free()
|
||||
online_pause_menu = null
|
||||
|
||||
# Return to online lobby after a delay
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
_show_online_lobby()
|
||||
|
||||
|
||||
# ======= PROFILE SCREEN =======
|
||||
|
||||
func _show_profile_screen() -> void:
|
||||
# Hide online lobby
|
||||
if online_lobby:
|
||||
online_lobby.visible = false
|
||||
|
||||
# Switch to profile screen window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_size(PROFILE_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - PROFILE_SIZE.x) / 2,
|
||||
(screen.y - PROFILE_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to profile size
|
||||
get_tree().root.content_scale_size = PROFILE_SIZE
|
||||
|
||||
# Create profile screen
|
||||
if not profile_screen:
|
||||
profile_screen = ProfileScreen.new()
|
||||
add_child(profile_screen)
|
||||
profile_screen.back_pressed.connect(_on_profile_back)
|
||||
else:
|
||||
profile_screen.refresh()
|
||||
|
||||
profile_screen.visible = true
|
||||
current_state = State.PROFILE
|
||||
|
||||
|
||||
func _on_profile_back() -> void:
|
||||
if profile_screen:
|
||||
profile_screen.visible = false
|
||||
_show_online_lobby()
|
||||
|
||||
|
||||
# ======= LEADERBOARD SCREEN =======
|
||||
|
||||
func _show_leaderboard_screen() -> void:
|
||||
# Hide online lobby
|
||||
if online_lobby:
|
||||
online_lobby.visible = false
|
||||
|
||||
# Switch to leaderboard screen window size
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_size(LEADERBOARD_SIZE)
|
||||
var screen := DisplayServer.screen_get_size()
|
||||
DisplayServer.window_set_position(Vector2i(
|
||||
(screen.x - LEADERBOARD_SIZE.x) / 2,
|
||||
(screen.y - LEADERBOARD_SIZE.y) / 2
|
||||
))
|
||||
|
||||
# Set viewport to leaderboard size
|
||||
get_tree().root.content_scale_size = LEADERBOARD_SIZE
|
||||
|
||||
# Create leaderboard screen
|
||||
if not leaderboard_screen:
|
||||
leaderboard_screen = LeaderboardScreen.new()
|
||||
add_child(leaderboard_screen)
|
||||
leaderboard_screen.back_pressed.connect(_on_leaderboard_back)
|
||||
else:
|
||||
leaderboard_screen.refresh()
|
||||
|
||||
leaderboard_screen.visible = true
|
||||
current_state = State.LEADERBOARD
|
||||
|
||||
|
||||
func _on_leaderboard_back() -> void:
|
||||
if leaderboard_screen:
|
||||
leaderboard_screen.visible = false
|
||||
_show_online_lobby()
|
||||
|
||||
Reference in New Issue
Block a user