diff --git a/Scenes/Player.tscn b/Scenes/Player.tscn index 7350165..65b31c4 100644 --- a/Scenes/Player.tscn +++ b/Scenes/Player.tscn @@ -5,7 +5,7 @@ [ext_resource type="Script" path="res://Scripts/Logic/PlayerInput.cs" id="3_tvoua"] [sub_resource type="CircleShape2D" id="CircleShape2D_68yf8"] -radius = 26.0768 +radius = 20.48 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_bekoo"] properties/0/path = NodePath(".:position") @@ -23,15 +23,14 @@ properties/1/path = NodePath("InputSynchronizer:MovementDirection") properties/1/spawn = true properties/1/replication_mode = 1 -[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("PlayerCamera", "PlayerInput", "PlayerDashCountdown")] +[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("PlayerCamera", "PlayerInput")] script = ExtResource("1_0btyt") PlayerCamera = NodePath("Camera2D") PlayerInput = NodePath("InputSynchronizer") -PlayerDashCountdown = NodePath("DashCountdown") [node name="Sprite2D" type="Sprite2D" parent="."] position = Vector2(2.08165e-12, 2.08165e-12) -scale = Vector2(0.05, 0.05) +scale = Vector2(0.04, 0.04) texture = ExtResource("1_cqpqa") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] diff --git a/Scenes/Root.tscn b/Scenes/Root.tscn index 078d053..f776242 100644 --- a/Scenes/Root.tscn +++ b/Scenes/Root.tscn @@ -1,23 +1,31 @@ -[gd_scene load_steps=5 format=3 uid="uid://bjhmjrldq4lkt"] +[gd_scene load_steps=6 format=3 uid="uid://bjhmjrldq4lkt"] -[ext_resource type="Script" path="res://Scripts/Multiplayer.cs" id="1_fym13"] [ext_resource type="PackedScene" uid="uid://b3gx0bl43lku3" path="res://Scenes/Player.tscn" id="1_vby0g"] -[ext_resource type="PackedScene" uid="uid://bvll23f5ibd4v" path="res://Scenes/UI/MultiplayerUI.tscn" id="2_7o53i"] +[ext_resource type="PackedScene" uid="uid://bvll23f5ibd4v" path="res://Scenes/UI/StartScreen.tscn" id="2_7o53i"] +[ext_resource type="Script" path="res://Scripts/Launcher.cs" id="2_u5cms"] [ext_resource type="Script" path="res://Scripts/Logic/World.cs" id="3_xwguj"] +[ext_resource type="Script" path="res://Scripts/TilesManager.cs" id="5_5wdx5"] [node name="Node" type="Node"] -[node name="MultiplayerNode" type="Node" parent="." node_paths=PackedStringArray("World")] -script = ExtResource("1_fym13") -World = NodePath("../World") +[node name="StartScreen" parent="." node_paths=PackedStringArray("Launcher") instance=ExtResource("2_7o53i")] +Launcher = NodePath("../LauncherNode") -[node name="MultiplayerUi" parent="." node_paths=PackedStringArray("MultiplayerController") instance=ExtResource("2_7o53i")] -MultiplayerController = NodePath("../MultiplayerNode") +[node name="LauncherNode" type="Node" parent="." node_paths=PackedStringArray("World")] +script = ExtResource("2_u5cms") +World = NodePath("../World") [node name="World" type="Node2D" parent="."] script = ExtResource("3_xwguj") PlayerScene = ExtResource("1_vby0g") -[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] +[node name="TilesSpawner" type="MultiplayerSpawner" parent="World"] +_spawnable_scenes = PackedStringArray("res://Scenes/Tiles/Brick.tscn") +spawn_path = NodePath("../Tiles") + +[node name="Tiles" type="Node2D" parent="World"] +script = ExtResource("5_5wdx5") + +[node name="PlayerSpawner" type="MultiplayerSpawner" parent="."] _spawnable_scenes = PackedStringArray("res://Scenes/Player.tscn") spawn_path = NodePath("../World") diff --git a/Scenes/Tiles/Brick.tscn b/Scenes/Tiles/Brick.tscn new file mode 100644 index 0000000..e3ec998 --- /dev/null +++ b/Scenes/Tiles/Brick.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://nj0k4l4mgq6"] + +[ext_resource type="Texture2D" uid="uid://c2qpm7mcrvq57" path="res://Sprites/Brick.png" id="1_fms8g"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_saayk"] +size = Vector2(51.2, 51.2) + +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_fbc2m"] +properties/0/path = NodePath(".:position") +properties/0/spawn = true +properties/0/replication_mode = 1 + +[node name="Brick" type="StaticBody2D"] + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(2.08165e-12, 2.08165e-12) +scale = Vector2(0.05, 0.05) +texture = ExtResource("1_fms8g") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_saayk") + +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +replication_config = SubResource("SceneReplicationConfig_fbc2m") diff --git a/Scenes/UI/MultiplayerUI.tscn b/Scenes/UI/StartScreen.tscn similarity index 50% rename from Scenes/UI/MultiplayerUI.tscn rename to Scenes/UI/StartScreen.tscn index 39a5d45..768ee58 100644 --- a/Scenes/UI/MultiplayerUI.tscn +++ b/Scenes/UI/StartScreen.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=2 format=3 uid="uid://bvll23f5ibd4v"] -[ext_resource type="Script" path="res://Scripts/UI/MultiplayerUi.cs" id="1_fm6j5"] +[ext_resource type="Script" path="res://Scripts/UI/StartScreen.cs" id="1_f8by8"] -[node name="MultiplayerUi" type="Control" node_paths=PackedStringArray("ServerPortInput", "ServerAddrInput", "StartAsServerButton", "StartAsClientButton")] +[node name="StartScreen" type="Control" node_paths=PackedStringArray("ServerPortInput", "ServerAddrInput", "StartAsSingleButton", "StartAsServerButton", "StartAsClientButton")] process_mode = 3 layout_mode = 3 anchors_preset = 15 @@ -10,11 +10,12 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_fm6j5") +script = ExtResource("1_f8by8") ServerPortInput = NodePath("CenterContainer/VBoxContainer/PortEdit") ServerAddrInput = NodePath("CenterContainer/VBoxContainer/AddrEdit") -StartAsServerButton = NodePath("CenterContainer/VBoxContainer/HBoxContainer/HostButton") -StartAsClientButton = NodePath("CenterContainer/VBoxContainer/HBoxContainer/ConnectButton") +StartAsSingleButton = NodePath("CenterContainer/VBoxContainer/PlayAloneButton") +StartAsServerButton = NodePath("CenterContainer/VBoxContainer/MultiplayerActions/HostButton") +StartAsClientButton = NodePath("CenterContainer/VBoxContainer/MultiplayerActions/ConnectButton") [node name="CenterContainer" type="CenterContainer" parent="."] layout_mode = 0 @@ -24,7 +25,16 @@ offset_bottom = 648.0 [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] layout_mode = 2 -[node name="Label" type="Label" parent="CenterContainer/VBoxContainer"] +[node name="SinglePlayerTitle" type="Label" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +text = "Singleplayer" +horizontal_alignment = 1 + +[node name="PlayAloneButton" type="Button" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +text = "Play Alone" + +[node name="MultiplayerTitle" type="Label" parent="CenterContainer/VBoxContainer"] layout_mode = 2 text = "Mutiplayer" horizontal_alignment = 1 @@ -37,13 +47,13 @@ placeholder_text = "Server port" layout_mode = 2 placeholder_text = "Server address" -[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/VBoxContainer"] +[node name="MultiplayerActions" type="HBoxContainer" parent="CenterContainer/VBoxContainer"] layout_mode = 2 -[node name="HostButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"] +[node name="HostButton" type="Button" parent="CenterContainer/VBoxContainer/MultiplayerActions"] layout_mode = 2 text = "Host a Game" -[node name="ConnectButton" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"] +[node name="ConnectButton" type="Button" parent="CenterContainer/VBoxContainer/MultiplayerActions"] layout_mode = 2 text = "Connect a Game" diff --git a/Scripts/Multiplayer.cs b/Scripts/Launcher.cs similarity index 92% rename from Scripts/Multiplayer.cs rename to Scripts/Launcher.cs index b3a9bd8..29c2fa0 100644 --- a/Scripts/Multiplayer.cs +++ b/Scripts/Launcher.cs @@ -3,7 +3,7 @@ using Godot; namespace CodingLand.Scripts; -public partial class Multiplayer : Node +public partial class Launcher : Node { [Export] public World World; @@ -30,6 +30,12 @@ public partial class Multiplayer : Node } } + public void StartAsSingle() + { + GameUnfreeze(); + World.StartGame(); + } + public bool StartAsServer(int port) { var peer = new ENetMultiplayerPeer(); diff --git a/Scripts/Logic/PlayerInput.cs b/Scripts/Logic/PlayerInput.cs index 60a30a3..b82f7c3 100644 --- a/Scripts/Logic/PlayerInput.cs +++ b/Scripts/Logic/PlayerInput.cs @@ -6,22 +6,26 @@ public partial class PlayerInput : MultiplayerSynchronizer { [Export] public bool IsDashing; + [Export] public Vector2 BuildingAt; + [Export] public Vector2 MovementDirection; + private bool IsCurrentPlayer => GetMultiplayerAuthority() == Multiplayer.GetUniqueId(); + public override void _Ready() { - if (GetMultiplayerAuthority() != Multiplayer.GetUniqueId()) - { - SetProcess(false); - SetPhysicsProcess(false); - } + if (IsCurrentPlayer) return; + SetProcess(false); + SetPhysicsProcess(false); } [Rpc(CallLocal = true)] private void Dash() - { - IsDashing = true; - } + => IsDashing = true; + + [Rpc(CallLocal = true)] + private void Build(Vector2 pos) + => BuildingAt = pos; public override void _Process(double delta) { @@ -30,4 +34,11 @@ public partial class PlayerInput : MultiplayerSynchronizer if (Input.IsActionJustPressed("move_dash")) Rpc(nameof(Dash)); } + + public override void _Input(InputEvent evt) + { + if (!IsCurrentPlayer) return; + if (evt is InputEventMouseButton { Pressed: true }) + Rpc(nameof(Build), GetViewport().GetMousePosition()); + } } \ No newline at end of file diff --git a/Scripts/Logic/World.cs b/Scripts/Logic/World.cs index 7fd4127..0390700 100644 --- a/Scripts/Logic/World.cs +++ b/Scripts/Logic/World.cs @@ -1,4 +1,3 @@ -using System.Numerics; using Godot; using Vector2 = Godot.Vector2; diff --git a/Scripts/Player.cs b/Scripts/Player.cs index 484b903..848584e 100644 --- a/Scripts/Player.cs +++ b/Scripts/Player.cs @@ -6,20 +6,22 @@ namespace CodingLand.Scripts; public partial class Player : CharacterBody2D { private int _currentPlayerId = 1; - + [Export] public float MaxSpeed = 400f; [Export] public float Acceleration = 500f; [Export] public float Deceleration = 500f; [Export] public float RotationSpeed = 5f; + [Export] public int Reach = 5; + [Export] public Camera2D PlayerCamera; [Export] public PlayerInput PlayerInput; - [Export] public Timer PlayerDashCountdown; [Export] public float PlayerDashAcceleration = 2f; - [Export] public int PlayerId + [Export] + public int PlayerId { get => _currentPlayerId; set @@ -34,18 +36,34 @@ public partial class Player : CharacterBody2D PlayerId = id; PlayerInput.SetMultiplayerAuthority(id); } + + private TilesManager _tilesMgr; public override void _Ready() { if (PlayerId == Multiplayer.GetUniqueId()) PlayerCamera.Enabled = true; + _tilesMgr = GetNode("../Tiles"); + } + + public override void _Process(double delta) + { + var vec = GetGlobalMousePosition(); + if (PlayerInput.BuildingAt == Vector2.Zero) return; + var distance = Position.DistanceTo(vec); + if (distance <= Reach * _tilesMgr.TileSize) + { + // Able to build + Rpc(nameof(AddTile), vec); + } + + PlayerInput.BuildingAt = Vector2.Zero; } public override void _PhysicsProcess(double delta) { var input = PlayerInput.MovementDirection; - if (input != Vector2.Zero) { input = input.Normalized(); @@ -59,14 +77,27 @@ public partial class Player : CharacterBody2D Velocity = Velocity.MoveToward(Vector2.Zero, Deceleration * (float)delta); } - if (PlayerInput.IsDashing && PlayerDashCountdown.IsStopped()) + var dashCountdown = GetNode("DashCountdown"); + if (PlayerInput.IsDashing && dashCountdown.IsStopped()) { PlayerInput.IsDashing = false; Velocity *= PlayerDashAcceleration; - PlayerDashCountdown.Start(); + dashCountdown.Start(); } Position += Velocity * (float)delta; MoveAndSlide(); } + + [Rpc(mode: MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)] + public void AddTile(Vector2 pos) + { + if (_tilesMgr.GetTileByPosition(pos) != null) return; + + var tileVec = new Vector2(_tilesMgr.TileSize, _tilesMgr.TileSize); + var blueprint = GD.Load("res://Scenes/Tiles/Brick.tscn"); + var instance = blueprint.Instantiate(); + instance.Position = pos.Snapped(tileVec); + _tilesMgr.AddChild(instance); + } } diff --git a/Scripts/TilesManager.cs b/Scripts/TilesManager.cs new file mode 100644 index 0000000..477ac00 --- /dev/null +++ b/Scripts/TilesManager.cs @@ -0,0 +1,35 @@ +using Godot; + +namespace CodingLand.Scripts; + +public partial class TilesManager : Node2D +{ + [Export] public float TileSize = 51.2f; + + [Rpc(CallLocal = true)] + public void AddTile(Vector2 pos) + { + if (GetTileByPosition(pos) == null) + { + var tileVec = new Vector2(TileSize, TileSize); + // TODO Replace the brick to player selection + var blueprint = GD.Load("res://Scenes/Tiles/Brick.tscn"); + var instance = blueprint.Instantiate(); + instance.Position = pos.Snapped(tileVec); + AddChild(instance); + } + } + + public T GetTileByPosition(Vector2 position) where T : Node2D + { + foreach (var item in GetChildren()) + { + if (item is T tile && tile.Position == position) + { + return tile; + } + } + + return null; + } +} \ No newline at end of file diff --git a/Scripts/UI/MultiplayerUi.cs b/Scripts/UI/StartScreen.cs similarity index 80% rename from Scripts/UI/MultiplayerUi.cs rename to Scripts/UI/StartScreen.cs index 7b2cbad..defa4ab 100644 --- a/Scripts/UI/MultiplayerUi.cs +++ b/Scripts/UI/StartScreen.cs @@ -2,15 +2,16 @@ using Godot; namespace CodingLand.Scripts.UI; -public partial class MultiplayerUi : Control +public partial class StartScreen : Control { [Export] public int DefaultServerPort = 4343; [Export] public string DefaultServerAddr = "127.0.0.1"; - [Export] public Multiplayer MultiplayerController; + [Export] public Launcher Launcher; [Export] public LineEdit ServerPortInput; [Export] public LineEdit ServerAddrInput; + [Export] public Button StartAsSingleButton; [Export] public Button StartAsServerButton; [Export] public Button StartAsClientButton; @@ -41,6 +42,11 @@ public partial class MultiplayerUi : Control ServerPortInput.Text = DefaultServerPort.ToString(); ServerAddrInput.Text = DefaultServerAddr; + StartAsSingleButton.Pressed += () => + { + Launcher.StartAsSingle(); + Hide(); + }; StartAsServerButton.Pressed += () => { if (!DoValidation()) @@ -50,7 +56,7 @@ public partial class MultiplayerUi : Control } var port = ServerPortInput.Text; - var result = MultiplayerController.StartAsServer(int.Parse(port)); + var result = Launcher.StartAsServer(int.Parse(port)); if (result) Hide(); @@ -65,7 +71,7 @@ public partial class MultiplayerUi : Control var addr = ServerAddrInput.Text; var port = ServerPortInput.Text; - var result = MultiplayerController.StartAsClient(addr, int.Parse(port)); + var result = Launcher.StartAsClient(addr, int.Parse(port)); if (result) Hide(); diff --git a/Sprites/Brick.png b/Sprites/Brick.png new file mode 100644 index 0000000..c6b4f02 Binary files /dev/null and b/Sprites/Brick.png differ diff --git a/Sprites/Brick.png.import b/Sprites/Brick.png.import new file mode 100644 index 0000000..fbe6f82 --- /dev/null +++ b/Sprites/Brick.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c2qpm7mcrvq57" +path="res://.godot/imported/Brick.png-618f5af6fe8b4d7875a5284d9ba4a8f0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Brick.png" +dest_files=["res://.godot/imported/Brick.png-618f5af6fe8b4d7875a5284d9ba4a8f0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..819f2a3 --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,76 @@ +[preset.0] + +name="iOS" +platform="iOS" +runnable=true +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 + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +architectures/arm64=true +application/app_store_team_id="" +application/code_sign_identity_debug="" +application/export_method_debug=1 +application/code_sign_identity_release="" +application/export_method_release=0 +application/targeted_device_family=2 +application/bundle_identifier="" +application/signature="" +application/short_version="" +application/version="" +application/icon_interpolation=4 +application/launch_screens_interpolation=4 +application/export_project_only=false +capabilities/access_wifi=false +capabilities/push_notifications=false +user_data/accessible_from_files_app=false +user_data/accessible_from_itunes_sharing=false +privacy/camera_usage_description="" +privacy/camera_usage_description_localized={} +privacy/microphone_usage_description="" +privacy/microphone_usage_description_localized={} +privacy/photolibrary_usage_description="" +privacy/photolibrary_usage_description_localized={} +icons/iphone_120x120="" +icons/iphone_180x180="" +icons/ipad_76x76="" +icons/ipad_152x152="" +icons/ipad_167x167="" +icons/app_store_1024x1024="" +icons/spotlight_40x40="" +icons/spotlight_80x80="" +icons/settings_58x58="" +icons/settings_87x87="" +icons/notification_40x40="" +icons/notification_60x60="" +storyboard/use_launch_screen_storyboard=true +storyboard/image_scale_mode=0 +storyboard/custom_image@2x="" +storyboard/custom_image@3x="" +storyboard/use_custom_bg_color=false +storyboard/custom_bg_color=Color(0, 0, 0, 1) +landscape_launch_screens/iphone_2436x1125="" +landscape_launch_screens/iphone_2208x1242="" +landscape_launch_screens/ipad_1024x768="" +landscape_launch_screens/ipad_2048x1536="" +portrait_launch_screens/iphone_640x960="" +portrait_launch_screens/iphone_640x1136="" +portrait_launch_screens/iphone_750x1334="" +portrait_launch_screens/iphone_1125x2436="" +portrait_launch_screens/ipad_768x1024="" +portrait_launch_screens/ipad_1536x2048="" +portrait_launch_screens/iphone_1242x2208="" +dotnet/include_scripts_content=false +dotnet/include_debug_symbols=true +dotnet/embed_build_outputs=false diff --git a/project.godot b/project.godot index 9980d8d..012762b 100644 --- a/project.godot +++ b/project.godot @@ -50,3 +50,4 @@ move_dash={ [rendering] renderer/rendering_method="mobile" +textures/vram_compression/import_etc2_astc=true