Compare commits

..

3 Commits

Author SHA1 Message Date
f0f717e00e game: improve enemy-manager 2025-08-21 06:11:09 +02:00
83e2067fea game: change rat base hp 2025-08-21 06:10:24 +02:00
a0d121fadc game: add weapon active ability 2025-08-21 05:52:40 +02:00
10 changed files with 110 additions and 14 deletions

View File

@@ -67,6 +67,11 @@ click={
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(90, 11),"global_position":Vector2(99, 59),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(90, 11),"global_position":Vector2(99, 59),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
] ]
} }
active={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
]
}
[layer_names] [layer_names]

View File

@@ -6,7 +6,6 @@
[node name="EnemyRat" instance=ExtResource("1_o1awd")] [node name="EnemyRat" instance=ExtResource("1_o1awd")]
script = ExtResource("2_sari4") script = ExtResource("2_sari4")
max_health = 50.0
default_contact_damage = 5.0 default_contact_damage = 5.0
[node name="Sprite2D" parent="." index="0"] [node name="Sprite2D" parent="." index="0"]

View File

@@ -25,8 +25,10 @@ position = Vector2(1057, 798)
camera = NodePath("../MainCamera") camera = NodePath("../MainCamera")
main_ui = NodePath("../MainUI") main_ui = NodePath("../MainUI")
[node name="EnemyManager" parent="." node_paths=PackedStringArray("target") instance=ExtResource("5_tbgi4")] [node name="EnemyManager" parent="." node_paths=PackedStringArray("target", "camera") instance=ExtResource("5_tbgi4")]
spawn_rate = 1.5
target = NodePath("../Player") target = NodePath("../Player")
camera = NodePath("../MainCamera")
[node name="PickupMagnet" parent="." instance=ExtResource("6_tefeu")] [node name="PickupMagnet" parent="." instance=ExtResource("6_tefeu")]
position = Vector2(1697, 414) position = Vector2(1697, 414)

View File

@@ -4,6 +4,7 @@ extends Node2D
@export var max_enemies: int @export var max_enemies: int
@export var spawn_rate: float @export var spawn_rate: float
@export var target: CollisionObject2D @export var target: CollisionObject2D
@export var camera: Camera2D
@onready var timer: Timer = $Timer @onready var timer: Timer = $Timer
@@ -22,11 +23,61 @@ func _on_timer_timeout() -> void:
GlobalConst.sig_debug_stats_set.emit("enemy_count", "%s" % len(enemies)) GlobalConst.sig_debug_stats_set.emit("enemy_count", "%s" % len(enemies))
if len(enemies) < max_enemies: if len(enemies) < max_enemies:
var new_enemy = ENEMY_RAT.instantiate() var new_enemy = ENEMY_RAT.instantiate()
new_enemy.position = target.position + Vector2(50, 50) new_enemy.position = _get_spawn_pos()
new_enemy.target = target new_enemy.target = target
add_child(new_enemy) add_child(new_enemy)
func _get_spawn_pos() -> Vector2:
var rect = _get_camera_rect()
var side = randi() % 4
var margin = 50
var pos: Vector2
match side:
0: # Top
pos = Vector2(
randf_range(rect.position.x, rect.position.x + rect.size.x),
rect.position.y - margin
)
1: # Bottom
pos = Vector2(
randf_range(rect.position.x, rect.position.x + rect.size.x),
rect.position.y + rect.size.y + margin
)
2: # Left
pos = Vector2(
rect.position.x - margin,
randf_range(rect.position.y, rect.position.y + rect.size.y)
)
3: # Right
pos = Vector2(
rect.position.x + rect.size.x + margin,
randf_range(rect.position.y, rect.position.y + rect.size.y)
)
if !_is_pos_valid(pos):
pos = _get_spawn_pos()
return pos
func _is_pos_valid(pos: Vector2) -> bool:
var space = get_world_2d().direct_space_state
var parameters = PhysicsPointQueryParameters2D.new()
parameters.collide_with_areas = false
parameters.collide_with_bodies = true
parameters.collision_mask = 1
parameters.position = pos
var result = space.intersect_point(parameters, 1)
return result.size() == 0
func _get_camera_rect() -> Rect2:
var viewport_size = camera.get_viewport_rect().size
var half_size = viewport_size * 0.5
var top_left = camera.global_position - half_size
return Rect2(top_left, viewport_size)
func _on_stop_spawning(val: bool): func _on_stop_spawning(val: bool):
if val: if val:
timer.stop() timer.stop()

View File

@@ -1,9 +1,13 @@
class_name Player class_name Player
extends CharacterBody2D extends CharacterBody2D
const WEAPON_SWORD = preload("res://scenes/weapons/weapon_sword.tscn")
@export var camera: Camera2D @export var camera: Camera2D
@export var main_ui: MainUI @export var main_ui: MainUI
var weapon: WeaponBase
@onready var sprite_2d: Sprite2D = $Sprite2D @onready var sprite_2d: Sprite2D = $Sprite2D
var player_stats: PlayerStats = PlayerStats.new() var player_stats: PlayerStats = PlayerStats.new()
@@ -13,10 +17,18 @@ var death_anim_done: bool = false
var god_mode: bool = false var god_mode: bool = false
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("active"):
weapon.do_active()
func _ready() -> void: func _ready() -> void:
camera.position = global_position camera.position = global_position
main_ui.player_ui.update_hp() main_ui.player_ui.update_hp()
GlobalConst.sig_debug_god_mode.connect(toggle_god_mode) GlobalConst.sig_debug_god_mode.connect(toggle_god_mode)
if not weapon:
weapon = WEAPON_SWORD.instantiate()
add_child(weapon)
func _physics_process(delta: float) -> void: func _physics_process(delta: float) -> void:

View File

@@ -1,8 +1,7 @@
[gd_scene load_steps=6 format=3 uid="uid://ca2so8fm3q8fe"] [gd_scene load_steps=5 format=3 uid="uid://ca2so8fm3q8fe"]
[ext_resource type="Texture2D" uid="uid://5x5wimok8uw2" path="res://assets/sprites/roguelikeChar_transparent.png" id="1_3vyb7"] [ext_resource type="Texture2D" uid="uid://5x5wimok8uw2" path="res://assets/sprites/roguelikeChar_transparent.png" id="1_3vyb7"]
[ext_resource type="Script" uid="uid://cvqaxckx4num3" path="res://scenes/player.gd" id="1_g2els"] [ext_resource type="Script" uid="uid://cvqaxckx4num3" path="res://scenes/player.gd" id="1_g2els"]
[ext_resource type="PackedScene" uid="uid://dfikvj27k01tu" path="res://scenes/weapons/weapon_sword.tscn" id="3_qhqgy"]
[sub_resource type="CircleShape2D" id="CircleShape2D_3vyb7"] [sub_resource type="CircleShape2D" id="CircleShape2D_3vyb7"]
radius = 8.0 radius = 8.0
@@ -30,6 +29,4 @@ monitorable = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="PickupArea"] [node name="CollisionShape2D" type="CollisionShape2D" parent="PickupArea"]
shape = SubResource("CircleShape2D_qhqgy") shape = SubResource("CircleShape2D_qhqgy")
[node name="WeaponSword" parent="." instance=ExtResource("3_qhqgy")]
[connection signal="area_entered" from="PickupArea" to="." method="_on_pickup_area_area_entered"] [connection signal="area_entered" from="PickupArea" to="." method="_on_pickup_area_area_entered"]

View File

@@ -7,6 +7,8 @@ extends Node2D
@export var attack_duration: float @export var attack_duration: float
@export var attack_range: float @export var attack_range: float
@onready var active_cd_timer: Timer = $ActiveCDTimer
func _on_attack_cd_timer_timeout() -> void: func _on_attack_cd_timer_timeout() -> void:
do_attack() do_attack()
@@ -16,6 +18,17 @@ func do_attack() -> void:
push_error("%s does not implement do_attack" % self) push_error("%s does not implement do_attack" % self)
func do_active() -> void:
if not active_cd_timer.is_stopped():
return
active_cd_timer.start()
_do_active()
func _do_active() -> void:
push_error("%s does not implement do_active" % self)
func find_target_in_radius() -> EnemyBase: func find_target_in_radius() -> EnemyBase:
var space_state: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state var space_state: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state
var shape := CircleShape2D.new() var shape := CircleShape2D.new()

View File

@@ -8,4 +8,7 @@ script = ExtResource("1_v4xn6")
[node name="AttackCDTimer" type="Timer" parent="."] [node name="AttackCDTimer" type="Timer" parent="."]
autostart = true autostart = true
[node name="ActiveCDTimer" type="Timer" parent="."]
one_shot = true
[connection signal="timeout" from="AttackCDTimer" to="." method="_on_attack_cd_timer_timeout"] [connection signal="timeout" from="AttackCDTimer" to="." method="_on_attack_cd_timer_timeout"]

View File

@@ -23,20 +23,34 @@ func do_attack() -> void:
return return
var projectile = WEAPON_SWORD_PROJECTILE.instantiate() var projectile = WEAPON_SWORD_PROJECTILE.instantiate()
projectile.damage = attack_damage
projectile.target = target projectile.target = target
projectile.on_hit_sig = projectile_hit projectile.on_hit_sig = projectile_hit
add_child(projectile) add_child(projectile)
func deal_damage(enemy: EnemyBase): func _do_active() -> void:
var radius = targeting_range_shape.shape.radius
var count = 15
for i in count:
var angle = TAU * float(i) / float(count)
var target_pos = Vector2(cos(angle), sin(angle)) * radius
var new_target := Marker2D.new()
new_target.global_position = global_position + target_pos
var projectile = WEAPON_SWORD_PROJECTILE.instantiate()
projectile.damage_mult = 3.0
projectile.target = new_target
projectile.on_hit_sig = projectile_hit
add_child(projectile)
func deal_damage(enemy: EnemyBase, damage_mult: float):
var crit_chance = _player.player_stats.get_final("crit_chance", _player.modifiers) var crit_chance = _player.player_stats.get_final("crit_chance", _player.modifiers)
var damage_dealt = attack_damage var damage_dealt = attack_damage * damage_mult
var is_crit = randf() >= 1 - crit_chance var is_crit = randf() >= 1 - crit_chance
if is_crit: if is_crit:
damage_dealt *= _player.player_stats.get_final("crit_multiplier", _player.modifiers) damage_dealt *= _player.player_stats.get_final("crit_multiplier", _player.modifiers)
enemy.take_damage(damage_dealt, is_crit) enemy.take_damage(damage_dealt, is_crit)
func _on_projectile_hit(projectile: WeaponSwordProjectile, enemy: EnemyBase): func _on_projectile_hit(projectile: WeaponSwordProjectile, enemy: EnemyBase, damage_mult: float):
deal_damage(enemy) deal_damage(enemy, damage_mult)

View File

@@ -4,7 +4,7 @@ extends Node2D
@export var speed: float = 500.0 @export var speed: float = 500.0
@export var range: float = 200.0 @export var range: float = 200.0
@export var target: Node2D @export var target: Node2D
@export var damage: float @export var damage_mult: float = 1.0
@export var on_hit_sig: Signal @export var on_hit_sig: Signal
var _direction: Vector2 var _direction: Vector2
@@ -36,5 +36,5 @@ func _physics_process(delta: float) -> void:
func _on_area_2d_body_entered(body: Node2D) -> void: func _on_area_2d_body_entered(body: Node2D) -> void:
if body in _already_hit: if body in _already_hit:
return return
on_hit_sig.emit(self, body) on_hit_sig.emit(self, body, damage_mult)
_already_hit.append(body) _already_hit.append(body)