Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- project.godot ################################################################################################
- ; Engine configuration file.
- ; It's best edited using the editor UI and not directly,
- ; since the parameters that go here are not all obvious.
- ;
- ; Format:
- ; [section] ; section goes between []
- ; param=value ; assign values to parameters
- config_version=5
- [application]
- config/name="CollisionBugTest"
- run/main_scene="uid://chiiwry3l2pkm"
- config/features=PackedStringArray("4.7", "C#", "Mobile")
- config/icon="res://icon.svg"
- [autoload]
- EnemyObjectPool="*uid://dkifioyg6eets"
- [display]
- window/size/viewport_width=640
- window/size/viewport_height=360
- window/stretch/mode="viewport"
- window/stretch/scale_mode="integer"
- [dotnet]
- project/assembly_name="CollisionBugTest"
- [layer_names]
- 2d_physics/layer_1="Player"
- 2d_physics/layer_2="Enemy"
- [physics]
- 3d/physics_engine="Jolt Physics"
- [rendering]
- rendering_device/driver.windows="d3d12"
- renderer/rendering_method="mobile"
- PlayableArea.cs ################################################################################################
- using Godot;
- using System;
- public partial class PlayableArea : Area2D
- {
- public override void _Ready()
- {
- BodyEntered += OnBodyEntered;
- BodyExited += OnBodyExited;
- }
- private void OnBodyEntered(Node2D body)
- {
- if (body is Enemy)
- GD.Print($"[Playable area] Enemy entered");
- }
- private async void OnBodyExited(Node2D body)
- {
- try
- {
- if (body is Enemy enemy)
- {
- GD.Print("[Playable area] Enemy left.");
- await enemy.DefeatAsync(); //you would remove enemy here without full animated sequence but for minimal example it's okay
- }
- }
- catch (Exception e)
- {
- GD.PrintErr(e);
- }
- }
- }
- Game.cs ################################################################################################
- using Godot;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- public partial class Game : Node2D
- {
- [Export] private Button _btnStart;
- [Export] private Button _btnKill;
- private EnemyObjectPool _objectPool;
- private List<Enemy> _spawnedEnemies;
- private bool _started = false;
- private bool _killed = false;
- public override void _Ready()
- {
- base._Ready();
- _objectPool = EnemyObjectPool.Instance;
- _spawnedEnemies = [];
- _btnStart.Pressed += OnButtonStartPressed;
- _btnKill.Pressed += OnButtonKillPressed;
- _btnKill.Disabled = true;
- GD.Print($"[Game] Ready \n");
- }
- private async Task SpawnAsync()
- {
- GD.Print("[Game] Starting spawn sequence");
- var enemy = _objectPool.Dequeue();
- _spawnedEnemies.Add(enemy);
- enemy.Enable(new Vector2(512, 102));
- var position = new Vector2(64, 102);
- Tween tween = CreateTween();
- tween.SetEase(Tween.EaseType.Out);
- tween.SetTrans(Tween.TransitionType.Linear);
- tween.TweenProperty(enemy, "global_position", position, 2.0);
- await ToSignal(tween, Tween.SignalName.Finished);
- enemy.ReachedDesignatedLocation = true;
- GD.Print("\n");
- }
- private async Task DestroyEnemyAsync()
- {
- GD.Print($"[Game] Enemy defeated by player request.");
- var enemy = _spawnedEnemies.FirstOrDefault();
- if (enemy != null && enemy.ReachedDesignatedLocation)
- {
- await enemy.DefeatAsync();
- _spawnedEnemies.Remove(enemy);
- }
- GD.Print($"\n");
- }
- #region controls
- private async void OnButtonStartPressed()
- {
- try
- {
- _btnStart.Disabled = true;
- await SpawnAsync();
- _btnKill.Disabled = false;
- }
- catch (Exception e)
- {
- GD.PrintErr(e);
- }
- }
- private async void OnButtonKillPressed()
- {
- try
- {
- _btnKill.Disabled = true;
- await DestroyEnemyAsync();
- await SpawnAsync();
- }
- catch (Exception e)
- {
- GD.PrintErr(e);
- }
- }
- #endregion
- }
- EnemyObjectPool.cs ################################################################################################
- using Godot;
- using System;
- using System.Collections.Generic;
- public partial class EnemyObjectPool : Node
- {
- public static EnemyObjectPool Instance { get; private set; }
- [Export] private PackedScene _enemy;
- private int _maxMobs = 1;
- private Queue<Enemy> _objectPool;
- public override void _Ready()
- {
- Instance = this;
- var currentScene = GetTree()?.CurrentScene;
- var enemyContainer = currentScene.GetNode<Node2D>("EnemyContainer");
- InitializeEnemy(enemyContainer);
- GD.Print("[Object pool] Ready");
- }
- private void InitializeEnemy(Node2D container)
- {
- _objectPool = new();
- for (int i = 0; i < _maxMobs; i++)
- {
- var instance = _enemy.Instantiate() as Enemy;
- instance.Defeated += Enqueue;
- _objectPool.Enqueue(instance);
- container.AddChild(instance);
- }
- }
- private void Enqueue(Enemy enemy)
- {
- GD.Print("[Object pool] Enqueue");
- _objectPool.Enqueue(enemy);
- if (_objectPool.Count > _maxMobs) GD.PrintErr("Object pool size exceeded.");
- }
- public Enemy Dequeue()
- {
- GD.Print("[Object pool] Dequeue");
- return _objectPool.Dequeue();
- }
- }
- Enemy.cs ################################################################################################
- using Godot;
- using System;
- using System.Threading.Tasks;
- public partial class Enemy : CharacterBody2D
- {
- [Export] private CollisionShape2D _collision;
- public event Action<Enemy> Defeated;
- public bool ReachedDesignatedLocation { get; set; }
- private Vector2 _storagePoint = new(608, 90);
- private int _direction = 1;
- private bool _defeated = false;
- public void InvokeDefeated()
- {
- Defeated?.Invoke(this);
- }
- public override void _Ready()
- {
- base._Ready();
- Disable();
- GD.Print("[Enemy] Ready");
- }
- public override void _PhysicsProcess(double delta)
- {
- base._PhysicsProcess(delta);
- if(!ReachedDesignatedLocation) return;
- _direction *= -1;
- GlobalPosition += new Vector2(5 * _direction, 0);
- }
- public void Enable(Vector2 position)
- {
- GD.Print("[Enemy] Enable");
- _defeated = false;
- SetPhysicsProcess(true);
- GlobalPosition = position;
- _collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false);
- }
- public async Task DefeatAsync()
- {
- if(_defeated) return;
- _defeated = true;
- GD.Print("[Enemy] Defeat");
- StopProcessing();
- await SimulateDefeatAnimationAsync();
- MoveToStoragePoint();
- InvokeDefeated();
- //not hiding the sprite to see where the guy actually is
- }
- private async Task SimulateDefeatAnimationAsync()
- {
- Tween tween = CreateTween();
- tween.TweenProperty(this, "rotation_degrees", RotationDegrees + 360, 1.0f);
- await ToSignal(tween, Tween.SignalName.Finished);
- }
- private void StopProcessing()
- {
- _collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, true);
- SetPhysicsProcess(false);
- }
- private void Disable()
- {
- StopProcessing();
- MoveToStoragePoint();
- }
- private void MoveToStoragePoint()
- {
- GlobalPosition = _storagePoint;
- }
- }
- enemy_object_pool.tscn ################################################################################################
- [gd_scene format=3 uid="uid://dkifioyg6eets"]
- [ext_resource type="Script" uid="uid://b3k174bgmq0lm" path="res://EnemyObjectPool.cs" id="1_0mxj6"]
- [ext_resource type="PackedScene" uid="uid://bxjv371c24hv6" path="res://enemy.tscn" id="2_omt7x"]
- [node name="EnemyObjectPool" type="Node" unique_id=1887825628]
- script = ExtResource("1_0mxj6")
- _enemy = ExtResource("2_omt7x")
- enemy.tscn ################################################################################################
- [gd_scene format=3 uid="uid://bxjv371c24hv6"]
- [ext_resource type="Script" uid="uid://cqilqfy20e3fw" path="res://Enemy.cs" id="1_7k104"]
- [sub_resource type="Gradient" id="Gradient_7xaro"]
- [sub_resource type="GradientTexture2D" id="GradientTexture2D_plrnn"]
- gradient = SubResource("Gradient_7xaro")
- fill = 1
- fill_from = Vector2(0.51304346, 0.5)
- [sub_resource type="RectangleShape2D" id="RectangleShape2D_7xaro"]
- size = Vector2(64, 64)
- [node name="Enemy" type="CharacterBody2D" unique_id=1267955304 node_paths=PackedStringArray("_collision")]
- collision_layer = 2
- script = ExtResource("1_7k104")
- _collision = NodePath("CollisionShape2D")
- [node name="Sprite2D" type="Sprite2D" parent="." unique_id=1626383384]
- texture = SubResource("GradientTexture2D_plrnn")
- [node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1732114049]
- shape = SubResource("RectangleShape2D_7xaro")
- game.tscn ################################################################################################
- [gd_scene format=3 uid="uid://chiiwry3l2pkm"]
- [ext_resource type="Script" uid="uid://ce2yo6xexi7a6" path="res://Game.cs" id="1_80nbo"]
- [ext_resource type="Script" uid="uid://cov46dvwceotm" path="res://PlayableArea.cs" id="2_e2o6t"]
- [sub_resource type="RectangleShape2D" id="RectangleShape2D_plrnn"]
- size = Vector2(320, 360)
- [node name="Game" type="Node2D" unique_id=325719013 node_paths=PackedStringArray("_btnStart", "_btnKill")]
- script = ExtResource("1_80nbo")
- _btnStart = NodePath("Button")
- _btnKill = NodePath("Button2")
- [node name="Camera2D" type="Camera2D" parent="." unique_id=540720120]
- position = Vector2(320, 176)
- [node name="PlayableArea" type="Area2D" parent="." unique_id=467738821]
- collision_layer = 0
- collision_mask = 2
- script = ExtResource("2_e2o6t")
- [node name="CollisionShape2D" type="CollisionShape2D" parent="PlayableArea" unique_id=577274571]
- position = Vector2(160, 180)
- shape = SubResource("RectangleShape2D_plrnn")
- [node name="EnemyContainer" type="Node2D" parent="." unique_id=1525994715]
- [node name="Button" type="Button" parent="." unique_id=1855880708]
- offset_left = 328.0
- offset_top = 240.0
- offset_right = 384.0
- offset_bottom = 271.0
- text = "START"
- [node name="Button2" type="Button" parent="." unique_id=1367707068]
- offset_left = 328.0
- offset_top = 280.0
- offset_right = 369.0
- offset_bottom = 311.0
- text = "KILL & RESPAWN"
Advertisement
Add Comment
Please, Sign In to add comment