Ivan Shakhov 4 роки тому
батько
коміт
dd11042d95

+ 11 - 0
.editorconfig

@@ -0,0 +1,11 @@
+# Top-most EditorConfig file.
+root = true
+
+# Unix-style newlines with a newline ending every file.
+[*.cs]
+insert_final_newline = true
+csharp_space_after_cast = false
+indent_size = 4
+
+[*.csproj]
+indent_size = 2

+ 21 - 10
2d/dodge_the_creeps/Main.gd

@@ -1,6 +1,6 @@
 extends Node
 
-export(PackedScene) var Mob
+export(PackedScene) var _mob_scene
 var score
 
 func _ready():
@@ -16,6 +16,7 @@ func game_over():
 
 
 func new_game():
+	get_tree().call_group("mobs", "queue_free")
 	score = 0
 	$Player.start($StartPosition.position)
 	$StartTimer.start()
@@ -25,16 +26,26 @@ func new_game():
 
 
 func _on_MobTimer_timeout():
-	$MobPath/MobSpawnLocation.offset = randi()
-	var mob = Mob.instance()
-	add_child(mob)
-	var direction = $MobPath/MobSpawnLocation.rotation + TAU / 4
-	mob.position = $MobPath/MobSpawnLocation.position
+	# Choose a random location on Path2D.
+	var mob_spawn_location = get_node("MobPath/MobSpawnLocation");
+	mob_spawn_location.offset = randi()
+
+	# Create a Mob instance and add it to the scene.
+	var mob_instance = _mob_scene.instance()
+	add_child(mob_instance)
+
+	# Set the mob's direction perpendicular to the path direction.
+	var direction = mob_spawn_location.rotation + TAU / 4
+
+	# Set the mob's position to a random location.
+	mob_instance.position = mob_spawn_location.position
+
+	# Add some randomness to the direction.
 	direction += rand_range(-TAU / 8, TAU / 8)
-	mob.rotation = direction
-	mob.linear_velocity = Vector2(rand_range(mob.min_speed, mob.max_speed), 0).rotated(direction)
-	# warning-ignore:return_value_discarded
-	$HUD.connect("start_game", mob, "_on_start_game")
+	mob_instance.rotation = direction
+
+	# Choose the velocity.
+	mob_instance.linear_velocity = Vector2(rand_range(mob_instance.min_speed, mob_instance.max_speed), 0).rotated(direction)
 
 
 func _on_ScoreTimer_timeout():

+ 1 - 1
2d/dodge_the_creeps/Main.tscn

@@ -14,7 +14,7 @@ _data = {
 
 [node name="Main" type="Node"]
 script = ExtResource( 1 )
-Mob = ExtResource( 2 )
+_mob_scene = ExtResource( 2 )
 
 [node name="ColorRect" type="ColorRect" parent="."]
 anchor_right = 1.0

+ 2 - 1
2d/dodge_the_creeps/Mob.gd

@@ -3,9 +3,10 @@ extends RigidBody2D
 #warning-ignore-all:unused_class_variable
 export var min_speed = 150
 export var max_speed = 250
-var mob_types = ["walk", "swim", "fly"]
 
 func _ready():
+	$AnimatedSprite.playing = true
+	var mob_types = $AnimatedSprite.frames.get_animation_names()
 	$AnimatedSprite.animation = mob_types[randi() % mob_types.size()]
 
 

+ 8 - 8
2d/dodge_the_creeps/Mob.tscn

@@ -10,11 +10,6 @@
 
 [sub_resource type="SpriteFrames" id=1]
 animations = [ {
-"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
-"loop": true,
-"name": "fly",
-"speed": 3.0
-}, {
 "frames": [ ExtResource( 4 ), ExtResource( 5 ) ],
 "loop": true,
 "name": "walk",
@@ -24,13 +19,20 @@ animations = [ {
 "loop": true,
 "name": "swim",
 "speed": 4.0
+}, {
+"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
+"loop": true,
+"name": "fly",
+"speed": 3.0
 } ]
 
 [sub_resource type="CapsuleShape2D" id=2]
 radius = 35.2706
 height = 23.3281
 
-[node name="Mob" type="RigidBody2D"]
+[node name="Mob" type="RigidBody2D" groups=[
+"mobs",
+]]
 collision_mask = 0
 gravity_scale = 0.0
 script = ExtResource( 1 )
@@ -42,8 +44,6 @@ __meta__ = {
 scale = Vector2( 0.75, 0.75 )
 frames = SubResource( 1 )
 animation = "walk"
-frame = 1
-playing = true
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
 rotation = 1.5708

+ 14 - 9
2d/dodge_the_creeps/Player.gd

@@ -2,27 +2,30 @@ extends Area2D
 
 signal hit
 
-export var speed = 400
-var screen_size
+# These only need to be accessed in this script, so we can make them private.
+# Private variables in GDScript have their name starting with an underscore.
+export var _speed = 400 # How fast the player will move (pixels/sec).
+var _screen_size # Size of the game window.
 
 func _ready():
-	screen_size = get_viewport_rect().size
+	_screen_size = get_viewport_rect().size
 	hide()
 
 
 func _process(delta):
-	var velocity = Vector2()
+	var velocity = Vector2() # The player's movement vector.
 	velocity.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
 	velocity.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
 
 	if velocity.length() > 0:
-		velocity = velocity.normalized() * speed
+		velocity = velocity.normalized() * _speed
 		$AnimatedSprite.play()
 	else:
 		$AnimatedSprite.stop()
+
 	position += velocity * delta
-	position.x = clamp(position.x, 0, screen_size.x)
-	position.y = clamp(position.y, 0, screen_size.y)
+	position.x = clamp(position.x, 0, _screen_size.x)
+	position.y = clamp(position.y, 0, _screen_size.y)
 
 	if velocity.x != 0:
 		$AnimatedSprite.animation = "right"
@@ -36,10 +39,12 @@ func _process(delta):
 func start(pos):
 	position = pos
 	show()
-	$CollisionShape2D.disabled = false
+	# Must be deferred as we can't change physics properties on a physics callback.
+	$CollisionShape2D.set_deferred("disabled", false)
 
 
 func _on_Player_body_entered(_body):
-	hide()
+	hide() # Player disappears after being hit.
 	emit_signal("hit")
+	# Must be deferred as we can't change physics properties on a physics callback.
 	$CollisionShape2D.set_deferred("disabled", true)

+ 2 - 23
mono/dodge_the_creeps/Dodge the Creeps with C#.csproj

@@ -1,26 +1,5 @@
-<Project Sdk="Godot.NET.Sdk/3.2.3">
+<Project Sdk="Godot.NET.Sdk/3.2.3">
   <PropertyGroup>
-    <ProjectGuid>{75CB0382-CCCC-4A4D-ABF0-C6CD04D9F832}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <RootNamespace>DodgetheCreepswithC</RootNamespace>
-    <AssemblyName>Dodge the Creeps with C#</AssemblyName>
-    <GodotProjectGeneratorVersion>1.0.7374.16792</GodotProjectGeneratorVersion>
-    <TargetFramework>net472</TargetFramework>
-    <!--The following properties were overriden during migration to prevent errors.
-    Enabling them may require other manual changes to the project and its files.-->
-    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-    <Deterministic>false</Deterministic>
+    <TargetFramework>netstandard2.1</TargetFramework>
   </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="HUD.cs" />
-    <Compile Include="Main.cs" />
-    <Compile Include="Mob.cs" />
-    <Compile Include="Player.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <ItemGroup />
 </Project>

+ 2 - 3
mono/dodge_the_creeps/HUD.cs

@@ -1,5 +1,4 @@
 using Godot;
-using System;
 
 public class HUD : CanvasLayer
 {
@@ -15,7 +14,7 @@ public class HUD : CanvasLayer
         GetNode<Timer>("MessageTimer").Start();
     }
 
-    async public void ShowGameOver()
+    public async void ShowGameOver()
     {
         ShowMessage("Game Over");
 
@@ -37,7 +36,7 @@ public class HUD : CanvasLayer
     public void OnStartButtonPressed()
     {
         GetNode<Button>("StartButton").Hide();
-        EmitSignal("StartGame");
+        EmitSignal(nameof(StartGame));
     }
 
     public void OnMessageTimerTimeout()

+ 16 - 17
mono/dodge_the_creeps/Main.cs

@@ -1,20 +1,18 @@
 using Godot;
-using System;
 
 public class Main : Node
 {
+#pragma warning disable 649
+    // We assign this in the editor, so we don't need the warning about not being assigned.
     [Export]
-    public PackedScene mob;
+    private PackedScene _mobScene;
+#pragma warning restore 649
 
     private int _score;
 
-    // We use 'System.Random' as an alternative to GDScript's random methods.
-    private Random _random = new Random();
-
-    // We'll use this later because C# doesn't support GDScript's randi().
-    private float RandRange(float min, float max)
+    public override void _Ready()
     {
-        return (float)_random.NextDouble() * (max - min) + min;
+        GD.Randomize();
     }
 
     public void GameOver()
@@ -30,6 +28,9 @@ public class Main : Node
 
     public void NewGame()
     {
+        // Note that for calling Godot-provided methods with strings,
+        // we have to use the original Godot snake_case name.
+        GetTree().CallGroup("mobs", "queue_free");
         _score = 0;
 
         var player = GetNode<Player>("Player");
@@ -60,16 +61,16 @@ public class Main : Node
 
     public void OnMobTimerTimeout()
     {
-        // Note: Normally it is best to use explicit types rather than the var keyword.
-        // However, var is acceptable to use here because the types are obviously
-        // PathFollow2D and RigidBody2D, since they appear later on the line.
+        // Note: Normally it is best to use explicit types rather than the `var`
+        // keyword. However, var is acceptable to use here because the types are
+        // obviously PathFollow2D and Mob, since they appear later on the line.
 
         // Choose a random location on Path2D.
         var mobSpawnLocation = GetNode<PathFollow2D>("MobPath/MobSpawnLocation");
-        mobSpawnLocation.SetOffset(_random.Next());
+        mobSpawnLocation.Offset = GD.Randi();
 
         // Create a Mob instance and add it to the scene.
-        var mobInstance = (RigidBody2D)mob.Instance();
+        var mobInstance = (Mob)_mobScene.Instance();
         AddChild(mobInstance);
 
         // Set the mob's direction perpendicular to the path direction.
@@ -79,12 +80,10 @@ public class Main : Node
         mobInstance.Position = mobSpawnLocation.Position;
 
         // Add some randomness to the direction.
-        direction += RandRange(-Mathf.Tau / 8, Mathf.Tau / 8);
+        direction += (float)GD.RandRange(-Mathf.Tau / 8, Mathf.Tau / 8);
         mobInstance.Rotation = direction;
 
         // Choose the velocity.
-        mobInstance.SetLinearVelocity(new Vector2(RandRange(150f, 250f), 0).Rotated(direction));
-
-        GetNode("HUD").Connect("StartGame", mobInstance, "OnStartGame");
+        mobInstance.LinearVelocity = new Vector2((float)GD.RandRange(mobInstance.minSpeed, mobInstance.maxSpeed), 0).Rotated(direction);
     }
 }

+ 1 - 1
mono/dodge_the_creeps/Main.tscn

@@ -14,7 +14,7 @@ _data = {
 
 [node name="Main" type="Node"]
 script = ExtResource( 1 )
-mob = ExtResource( 2 )
+_mobScene = ExtResource( 2 )
 
 [node name="ColorRect" type="ColorRect" parent="."]
 anchor_right = 1.0

+ 6 - 8
mono/dodge_the_creeps/Mob.cs

@@ -4,19 +4,17 @@ using System;
 public class Mob : RigidBody2D
 {
     [Export]
-    public int minSpeed; // Minimum speed range.
+    public int minSpeed;
 
     [Export]
-    public int maxSpeed; // Maximum speed range.
-
-    private String[] _mobTypes = { "walk", "swim", "fly" };
-
-    // C# doesn't have GDScript's random methods, so we use System.Random insetad.
-    private static Random _random = new Random();
+    public int maxSpeed;
 
     public override void _Ready()
     {
-        GetNode<AnimatedSprite>("AnimatedSprite").Animation = _mobTypes[_random.Next(0, _mobTypes.Length)];
+        var animSprite = GetNode<AnimatedSprite>("AnimatedSprite");
+        animSprite.Playing = true;
+        string[] mobTypes = animSprite.Frames.GetAnimationNames();
+        animSprite.Animation = mobTypes[GD.Randi() % mobTypes.Length];
     }
 
     public void OnVisibilityScreenExited()

+ 3 - 3
mono/dodge_the_creeps/Mob.tscn

@@ -30,7 +30,9 @@ animations = [ {
 radius = 35.8898
 height = 29.3103
 
-[node name="Mob" type="RigidBody2D"]
+[node name="Mob" type="RigidBody2D" groups=[
+"mobs",
+]]
 collision_mask = 0
 gravity_scale = 0.0
 script = ExtResource( 1 )
@@ -44,8 +46,6 @@ maxSpeed = 250
 scale = Vector2( 0.75, 0.75 )
 frames = SubResource( 1 )
 animation = "walk"
-frame = 1
-playing = true
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
 rotation = 1.5708

+ 9 - 6
mono/dodge_the_creeps/Player.cs

@@ -5,14 +5,17 @@ public class Player : Area2D
     [Signal]
     public delegate void Hit();
 
+    // These only need to be accessed in this script, so we can make them private.
+    // Private variables in C# in Godot have their name starting with an
+    // underscore and also have the "private" keyword instead of "public".
     [Export]
-    public int speed; // How fast the player will move (pixels/sec).
+    private int _speed = 400; // How fast the player will move (pixels/sec).
 
     private Vector2 _screenSize; // Size of the game window.
 
     public override void _Ready()
     {
-        _screenSize = GetViewport().GetSize();
+        _screenSize = GetViewportRect().Size;
         Hide();
     }
 
@@ -26,7 +29,7 @@ public class Player : Area2D
 
         if (velocity.Length() > 0)
         {
-            velocity = velocity.Normalized() * speed;
+            velocity = velocity.Normalized() * _speed;
             animatedSprite.Play();
         }
         else
@@ -59,14 +62,14 @@ public class Player : Area2D
         Position = pos;
         Show();
         // Must be deferred as we can't change physics properties on a physics callback.
-        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("Disabled", false);
+        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("disabled", false);
     }
 
     public void OnPlayerBodyEntered(PhysicsBody2D body)
     {
         Hide(); // Player disappears after being hit.
-        EmitSignal("Hit");
+        EmitSignal(nameof(Hit));
         // Must be deferred as we can't change physics properties on a physics callback.
-        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("Disabled", true);
+        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("disabled", true);
     }
 }

+ 1 - 1
mono/dodge_the_creeps/Player.tscn

@@ -51,7 +51,7 @@ script = ExtResource( 1 )
 __meta__ = {
 "_edit_group_": true
 }
-speed = 400
+_speed = 400
 
 [node name="AnimatedSprite" type="AnimatedSprite" parent="."]
 scale = Vector2( 0.5, 0.5 )

+ 0 - 25
mono/dodge_the_creeps/Properties/AssemblyInfo.cs

@@ -1,25 +0,0 @@
-using System.Reflection;
-
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-
-[assembly: AssemblyTitle("Dodge the Creeps with C#")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-
-[assembly: AssemblyVersion("1.0.*")]
-
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]