From fc594529287c7b379a8e27355f1c46c3030190b6 Mon Sep 17 00:00:00 2001 From: Jonas Mucke Date: Mon, 20 Apr 2020 00:04:25 +0200 Subject: [PATCH 1/4] torch, minion, ai attack --- src/Boss/Boss_template.tscn | 1 + src/Boss/Minion.gd | 47 +++++++ src/Boss/Minion.tscn | 69 ++++++++++ src/Maps/Grid.gd | 2 + src/Objects/Barrel/Barrel.gd | 2 +- src/Objects/Bonfire/Bonfire.tscn | 2 +- src/Objects/Torch/Torch.gd | 21 +-- src/Objects/Torch/Torch.tscn | 7 +- src/Overlap/AI/AI_Hero.gd | 136 ++++++++++++++------ src/Player/Player.gd | 5 +- src/Player/Player.tscn | 5 +- src/World.tscn | 18 ++- src/project.godot | 1 + src/testSprites/white_minion_dog.png | Bin 0 -> 15098 bytes src/testSprites/white_minion_dog.png.import | 34 +++++ 15 files changed, 285 insertions(+), 65 deletions(-) create mode 100644 src/Boss/Minion.gd create mode 100644 src/Boss/Minion.tscn create mode 100644 src/testSprites/white_minion_dog.png create mode 100644 src/testSprites/white_minion_dog.png.import diff --git a/src/Boss/Boss_template.tscn b/src/Boss/Boss_template.tscn index 308ca14..f69f5b1 100644 --- a/src/Boss/Boss_template.tscn +++ b/src/Boss/Boss_template.tscn @@ -31,6 +31,7 @@ hframes = 60 [node name="Hitbox" parent="." instance=ExtResource( 2 )] collision_layer = 0 +collision_mask = 65 [node name="CollisionShape2D" parent="Hitbox" index="0"] position = Vector2( 0, -15 ) diff --git a/src/Boss/Minion.gd b/src/Boss/Minion.gd new file mode 100644 index 0000000..711ee35 --- /dev/null +++ b/src/Boss/Minion.gd @@ -0,0 +1,47 @@ +extends KinematicBody2D + +var velocity := Vector2.ZERO + +# This is how you export variables with ranges to the editor window +export(int, 0, 500) var ACCELERATION := 450 +# Reference for the current player + +onready var player_stats := $Stats +onready var debug_label := $DebugLabel + +var damage_per_second := 0.0 +var totaldamage := 0.0 + +func _debug_update(): + debug_label.text = str(player_stats.health) + "/" + str(player_stats.max_health) + " HP\n" + +# IMPORTANT: If you are using move_and_slide don't multiply by delta +# Godots physics system does that internally +# In move_and_collide(...) you have to multiply by delta. +func move(): + move_and_slide(velocity) + +func _physics_process(delta): + totaldamage += damage_per_second * delta + player_stats.speed += 10 * delta + while (totaldamage > 1): + totaldamage -= 1 + player_stats.health -= 1 + while (totaldamage <- 1): + totaldamage += 1 + player_stats.health += 1 + _debug_update() + move() + + +func _on_Stats_no_health(): + queue_free() + + +func _on_Hurtbox_area_entered(area): + player_stats.health -= area.damage + damage_per_second += area.damage + + +func _on_Hurtbox_area_exited(area): + damage_per_second -= area.damage diff --git a/src/Boss/Minion.tscn b/src/Boss/Minion.tscn new file mode 100644 index 0000000..d2fe865 --- /dev/null +++ b/src/Boss/Minion.tscn @@ -0,0 +1,69 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://Overlap/HurtHit_Box/Hurtbox.tscn" type="PackedScene" id=1] +[ext_resource path="res://Overlap/HurtHit_Box/Hitbox.tscn" type="PackedScene" id=2] +[ext_resource path="res://Overlap/Kind.tscn" type="PackedScene" id=3] +[ext_resource path="res://Overlap/Stats/Stats.tscn" type="PackedScene" id=4] +[ext_resource path="res://testSprites/white_minion_dog.png" type="Texture" id=5] +[ext_resource path="res://Boss/Minion.gd" type="Script" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 6.0 + +[sub_resource type="CapsuleShape2D" id=2] +radius = 11.0 +height = 11.0 + +[sub_resource type="CapsuleShape2D" id=3] +radius = 11.0 +height = 11.0 + +[node name="Minion" type="KinematicBody2D"] +script = ExtResource( 6 ) + +[node name="Kind" parent="." instance=ExtResource( 3 )] +kind = 3 + +[node name="Sprite" type="Sprite" parent="."] +position = Vector2( 0, -10.2123 ) +texture = ExtResource( 5 ) +hframes = 60 + +[node name="Body" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) + +[node name="Hitbox" parent="." instance=ExtResource( 2 )] +collision_layer = 0 +collision_mask = 65 + +[node name="CollisionShape2D" parent="Hitbox" index="0"] +position = Vector2( 0, -9 ) +shape = SubResource( 2 ) + +[node name="Hurtbox" parent="." instance=ExtResource( 1 )] +collision_layer = 8 +collision_mask = 0 + +[node name="CollisionShape2D" parent="Hurtbox" index="0"] +position = Vector2( 0, -9 ) +shape = SubResource( 3 ) + +[node name="DebugLabel" type="Label" parent="."] +margin_left = -50.8637 +margin_top = -41.3944 +margin_right = 51.1363 +margin_bottom = -27.3944 +text = "the white dog" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Stats" parent="." instance=ExtResource( 4 )] +max_health = 2 +[connection signal="area_entered" from="Hurtbox" to="." method="_on_Hurtbox_area_entered"] +[connection signal="area_exited" from="Hurtbox" to="." method="_on_Hurtbox_area_exited"] +[connection signal="no_health" from="Stats" to="." method="_on_Stats_no_health"] + +[editable path="Hitbox"] + +[editable path="Hurtbox"] diff --git a/src/Maps/Grid.gd b/src/Maps/Grid.gd index 396f8c9..19bea11 100644 --- a/src/Maps/Grid.gd +++ b/src/Maps/Grid.gd @@ -99,6 +99,8 @@ func get_nearest(position, kind): for i in prio_grid[x][y]: if(i == kind): list.append([x, y]) + if list.size() == 0: + return[-1,-1] var dist = [] for field in list: var tmp = sqrt(pow(position[0] - field[0], 2) + pow(position[1] - field[1], 2)) diff --git a/src/Objects/Barrel/Barrel.gd b/src/Objects/Barrel/Barrel.gd index 9dad71c..d45e1bf 100644 --- a/src/Objects/Barrel/Barrel.gd +++ b/src/Objects/Barrel/Barrel.gd @@ -6,7 +6,7 @@ var RedDrop = 0.2 var Heart = 0.2 func offset_vec(): - var offset = 20 + var offset = 16 return Vector2((randf()-0.5)*offset, (randf()-0.5)*offset) func _on_Hurtbox_area_entered(area): diff --git a/src/Objects/Bonfire/Bonfire.tscn b/src/Objects/Bonfire/Bonfire.tscn index 24a2e4d..e2291eb 100644 --- a/src/Objects/Bonfire/Bonfire.tscn +++ b/src/Objects/Bonfire/Bonfire.tscn @@ -30,7 +30,7 @@ texture = ExtResource( 3 ) [node name="Hurtbox" parent="." instance=ExtResource( 1 )] position = Vector2( 1.54256, -4.73786 ) -collision_layer = 8 +collision_layer = 64 collision_mask = 0 [node name="CollisionShape2D" parent="Hurtbox" index="0"] diff --git a/src/Objects/Torch/Torch.gd b/src/Objects/Torch/Torch.gd index 31df32b..860acde 100644 --- a/src/Objects/Torch/Torch.gd +++ b/src/Objects/Torch/Torch.gd @@ -1,20 +1,23 @@ extends Node2D export(int, 1, 5) var lifePoints = 3 -export(int, 1, 30) var spawnRate = 5 +export(int, 1, 30) var spawnRate = 5.0 +var Minion = load("res://Boss/Minion.tscn") var elapsedTime = 0.0 +func offset_vec(): + var offset = 16 + return Vector2((randf()-0.5)*offset, (randf()-0.5)*offset) + func _physics_process(delta): elapsedTime += delta - #if(elapsedTime>=spawnRate): - # elapsedTime-=spawnRate - # var Minion = load("") - # var world = get_tree().current_scene.get_child(2) - # #TODO minions - # var minion = Minion.instance() - # world.add_child(minion) - # minion.global_position = global_position + if(elapsedTime>=spawnRate): + elapsedTime-=spawnRate + var world = get_tree().current_scene.get_child(2) + var minion = Minion.instance() + world.add_child(minion) + minion.global_position = global_position+offset_vec() func _on_Hurtbox_area_entered(area): diff --git a/src/Objects/Torch/Torch.tscn b/src/Objects/Torch/Torch.tscn index 72dcad8..73caedf 100644 --- a/src/Objects/Torch/Torch.tscn +++ b/src/Objects/Torch/Torch.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://Overlap/HurtHit_Box/Hurtbox.tscn" type="PackedScene" id=1] [ext_resource path="res://testSprites/fackel.png" type="Texture" id=2] @@ -13,12 +13,13 @@ height = 12.0 [node name="Torch" type="Node2D"] script = ExtResource( 3 ) -[node name="FireEffect" parent="." instance=ExtResource( 4 )] -position = Vector2( 1.88936, -12.4698 ) [node name="Kind" parent="." instance=ExtResource( 5 )] general = 4 kind = 2 +[node name="FireEffect" parent="." instance=ExtResource( 4 )] +position = Vector2( 1.88936, -12.4698 ) + [node name="Sprite" type="Sprite" parent="."] position = Vector2( 0, -8 ) texture = ExtResource( 2 ) diff --git a/src/Overlap/AI/AI_Hero.gd b/src/Overlap/AI/AI_Hero.gd index 0f53e77..e855dd9 100644 --- a/src/Overlap/AI/AI_Hero.gd +++ b/src/Overlap/AI/AI_Hero.gd @@ -16,6 +16,7 @@ enum{ enum{ STEP, ROLL, + ATTAC, NOTHING } @@ -77,8 +78,8 @@ func calcPrioTable(): #updates heart and bonfire prio func adjustPrio(currentHealth, maxHealth): var prioVal = 40.0 - (float(currentHealth)/float(maxHealth))*40.0 - var bonfire = prioVal - var hearts = prioVal - 1 + var bonfire = prioVal + 1 + var hearts = prioVal if(hearts < 0): hearts = 0 prios[Grid.Kind.BONFIRE]=bonfire @@ -260,53 +261,81 @@ func AStar(source, target): return [NOTHING, [0,0]] +func movement_calulcaotr(): + var currentPosition = grid._pixel_to_grid_coords(global_position) + var calcNew = false + var MoveAdvice + + if(actionFieldUsed==false): + calcNew = true + + if(calcNew==true): + var enemyKind = calcEnemyKind() + if(enemyKind==Grid.Kind.TERMINAL_SYMBOL): + return + actionField = grid.get_nearest(currentPosition, enemyKind) + if(actionField==[-1,-1]): + return + actionFieldUsed = true + + MoveAdvice = getMoveDescription(currentPosition, actionField) + grid.reset_history() + + return MoveAdvice -func makeMove(delta): +func is_hittable(target): + for element in grid.prio_grid[target[0]][target[1]]: + if(element == grid.Kind.BOSS || element == grid.Kind.TORCH || element == grid.Kind.MINION): + return true + return false + +func hit_or_miss(target, current, hitable, delta): + run(Vector2(target[0]-current[0], target[1]-current[1]), delta*8) + attac(Vector2(target[0]-current[0], target[1]-current[1]), delta*4) + return hitable + +func movement_decider_ai(target, kindOfStep, delta): + var currentPosition = grid._pixel_to_grid_coords(global_position) + var field_of_movement = target - #if(actionFieldUsed==true): - # var random = randf() - # if(random < mindChangeProbability): - # ExecutionState = AI_MOVE + var top = [currentPosition[0]+0, currentPosition[1]-1] + var left = [currentPosition[0]-1, currentPosition[1]-0] + var right = [currentPosition[0]+1, currentPosition[1]-0] + var down = [currentPosition[0]+0, currentPosition[1]+1] + var field = [currentPosition[0]+0, currentPosition[1]+0] - if ExecutionState == AI_MOVE: - threadDelta = 0 - var currentPosition = grid._pixel_to_grid_coords(global_position) - var calcNew = false - var target - var MoveAdvice - if(actionFieldUsed==false): - calcNew = true - - if(calcNew==true): - var enemyKind = calcEnemyKind() - if(enemyKind==Grid.Kind.TERMINAL_SYMBOL): - return - target = grid.get_nearest(currentPosition, enemyKind) - actionField = target - actionFieldUsed = true - MoveAdvice = getMoveDescription(currentPosition, target) - else: - MoveAdvice = getMoveDescription(currentPosition, actionField) - grid.reset_history() - - target = MoveAdvice[1] - if(MoveAdvice[0]==STEP): + if(grid._is_in_grid(Vector2(field[0], field[1])) && hit_or_miss(field, currentPosition, is_hittable(field), delta)): + pass + elif(grid._is_in_grid(Vector2(target[0], target[1])) && hit_or_miss(target, currentPosition, is_hittable(target), delta)): + pass + elif(grid._is_in_grid(Vector2(left[0], left[1])) && hit_or_miss(left, currentPosition, is_hittable(left), delta)): + pass + elif(grid._is_in_grid(Vector2(down[0], down[1])) && hit_or_miss(down, currentPosition, is_hittable(down), delta)): + pass + elif(grid._is_in_grid(Vector2(top[0], top[1])) && hit_or_miss(top, currentPosition, is_hittable(top), delta)): + pass + elif(grid._is_in_grid(Vector2(down[0], down[1])) && hit_or_miss(down, currentPosition, is_hittable(down), delta)): + pass + else: + if(kindOfStep==STEP): run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) targetFieldCur = target targetFieldUsed = true ai_movement_state = STEP - elif(MoveAdvice[0]==ROLL): + elif(kindOfStep==ROLL): roll(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) targetFieldCur = target targetFieldUsed = true - ExecutionState = EXECUTING - - elif ExecutionState == EXECUTING: - if(targetFieldUsed): + ExecutionState = EXECUTING + + + +func movement_execution(delta): + if(targetFieldUsed): var cur = grid._pixel_to_grid_coords(global_position) var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) - if(distance<0.4): + if(distance<0.01): targetFieldUsed = false ExecutionState = AI_MOVE if(targetFieldCur[0]==actionField[0]&&targetFieldCur[1]==actionField[1]): @@ -317,10 +346,35 @@ func makeMove(delta): run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) elif(ai_movement_state==ROLL): run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) - threadDelta = threadDelta + delta - if(threadDelta>threadTime): - ExecutionState = AI_MOVE - actionFieldUsed = false + + +func reset_exeution_state(delta): + threadDelta = threadDelta + delta + if(threadDelta>threadTime): + ExecutionState = AI_MOVE + actionFieldUsed = false + + + +func makeMove(delta): + + #if(actionFieldUsed==true): + # var random = randf() + # if(random < mindChangeProbability): + # ExecutionState = AI_MOVE + + if ExecutionState == AI_MOVE: + threadDelta = 0 + var MoveAdvice = movement_calulcaotr() + if(MoveAdvice==null): + return + var target = MoveAdvice[1] + movement_decider_ai(target, MoveAdvice[0], delta) + + elif ExecutionState == EXECUTING: + movement_execution(delta) + reset_exeution_state(delta) + # API Interface for ai_hero -> methods are handled in player.gd func attac(direction, delta): @@ -333,3 +387,5 @@ func roll(direction, delta): func run(direction, delta): pass + +#todo diff --git a/src/Player/Player.gd b/src/Player/Player.gd index 33c4e3a..2dd08ff 100644 --- a/src/Player/Player.gd +++ b/src/Player/Player.gd @@ -149,7 +149,8 @@ func movement_hit(): func hit_finished(): movementState = moveState.IDLE - ExecutionState = AI_MOVE + ai_movement_state = STEP + ExecutionState = EXECUTING func movement_roll(): @@ -207,4 +208,4 @@ func movement_run(direction, delta): func movement_idle(): movementState = moveState.IDLE velocity = Vector2.ZERO - animation_state.change_scene("idle") + animation_state.change_state("idle") diff --git a/src/Player/Player.tscn b/src/Player/Player.tscn index 5247dda..662e5c5 100644 --- a/src/Player/Player.tscn +++ b/src/Player/Player.tscn @@ -624,6 +624,7 @@ size = 12 font_data = ExtResource( 6 ) [node name="Player" type="KinematicBody2D"] +scale = Vector2( 1.1, 1.1 ) script = ExtResource( 1 ) FRICTION = 270 @@ -637,7 +638,7 @@ scale = Vector2( 0.5, 0.5 ) texture = ExtResource( 2 ) offset = Vector2( 0, -18 ) hframes = 60 -frame = 9 +frame = 12 [node name="Body" type="CollisionShape2D" parent="."] position = Vector2( 0.0107212, 0.0456073 ) @@ -698,7 +699,7 @@ __meta__ = { [node name="SwordHitbox" parent="Pivot" instance=ExtResource( 4 )] collision_layer = 0 -collision_mask = 12 +collision_mask = 76 [node name="CollisionShape2D" parent="Pivot/SwordHitbox" index="0"] position = Vector2( 8.43416, 0.0698299 ) diff --git a/src/World.tscn b/src/World.tscn index b63f362..8906b4d 100644 --- a/src/World.tscn +++ b/src/World.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=11 format=2] [ext_resource path="res://Player/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://World.gd" type="Script" id=2] @@ -6,6 +6,7 @@ [ext_resource path="res://testSprites/dark.png" type="Texture" id=4] [ext_resource path="res://Menus/DragNDrop/DragNDropUI.tscn" type="PackedScene" id=5] [ext_resource path="res://Menus/DialogueBox/DialogueBox.tscn" type="PackedScene" id=6] +[ext_resource path="res://Objects/Torch/Torch.tscn" type="PackedScene" id=7] [ext_resource path="res://Objects/Bonfire/Bonfire.tscn" type="PackedScene" id=10] [ext_resource path="res://Boss/Boss_template.tscn" type="PackedScene" id=17] [ext_resource path="res://Maps/Grid.tscn" type="PackedScene" id=18] @@ -33,18 +34,21 @@ __meta__ = { [node name="YSort" type="YSort" parent="."] position = Vector2( 152, 120 ) -[node name="Bonfire" parent="YSort" instance=ExtResource( 10 )] -position = Vector2( 264, -24 ) - [node name="Player" parent="YSort" instance=ExtResource( 1 )] -position = Vector2( 240, 72 ) +position = Vector2( 200, 8 ) scale = Vector2( 2, 2 ) +debug = true ROLL_SPEED = 140 FRICTION = 200 [node name="Boss_template" parent="YSort" instance=ExtResource( 17 )] -position = Vector2( -67.0889, 2.27742 ) -debug = true +position = Vector2( -56, 8 ) + +[node name="Bonfire" parent="YSort" instance=ExtResource( 10 )] +position = Vector2( 288, 104 ) + +[node name="Torch" parent="YSort" instance=ExtResource( 7 )] +position = Vector2( 264, -40 ) [node name="Grid" parent="." instance=ExtResource( 18 )] diff --git a/src/project.godot b/src/project.godot index 2004c48..92abe87 100644 --- a/src/project.godot +++ b/src/project.godot @@ -147,6 +147,7 @@ attack={ 2d_physics/layer_4="monster" 2d_physics/layer_5="trap" 2d_physics/layer_6="collectable" +2d_physics/layer_7="Bonfire" [rendering] diff --git a/src/testSprites/white_minion_dog.png b/src/testSprites/white_minion_dog.png new file mode 100644 index 0000000000000000000000000000000000000000..5d01d9a99d82ee7a01e0c6459476fcc72f6e919e GIT binary patch literal 15098 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 qOQ7H Date: Mon, 20 Apr 2020 10:09:07 +0200 Subject: [PATCH 2/4] ai fixed --- src/Boss/Boss_template.tscn | 6 ++- src/Boss/Minion.tscn | 6 ++- src/Maps/Grid.gd | 3 ++ src/Objects/Barrel/Barrel.gd | 4 ++ src/Objects/Barrel/Barrel.tscn | 6 ++- src/Objects/Torch/Torch.gd | 2 +- src/Objects/Torch/Torch.tscn | 6 ++- src/Overlap/AI/AI_Hero.gd | 98 +++++++++++++++------------------- src/Player/Player.gd | 10 ++++ src/Player/Player.tscn | 35 +++++++++--- src/World.tscn | 12 +++-- src/project.godot | 1 + 12 files changed, 114 insertions(+), 75 deletions(-) diff --git a/src/Boss/Boss_template.tscn b/src/Boss/Boss_template.tscn index f69f5b1..3593d05 100644 --- a/src/Boss/Boss_template.tscn +++ b/src/Boss/Boss_template.tscn @@ -37,9 +37,11 @@ collision_mask = 65 position = Vector2( 0, -15 ) shape = SubResource( 1 ) -[node name="Hurtbox" parent="." instance=ExtResource( 1 )] +[node name="Hurtbox" parent="." groups=[ +"HittableByPlayer", +] instance=ExtResource( 1 )] collision_layer = 4 -collision_mask = 0 +collision_mask = 128 [node name="CollisionShape2D" parent="Hurtbox" index="0"] position = Vector2( 0, -15 ) diff --git a/src/Boss/Minion.tscn b/src/Boss/Minion.tscn index d2fe865..635e2a4 100644 --- a/src/Boss/Minion.tscn +++ b/src/Boss/Minion.tscn @@ -40,9 +40,11 @@ collision_mask = 65 position = Vector2( 0, -9 ) shape = SubResource( 2 ) -[node name="Hurtbox" parent="." instance=ExtResource( 1 )] +[node name="Hurtbox" parent="." groups=[ +"HittableByPlayer", +] instance=ExtResource( 1 )] collision_layer = 8 -collision_mask = 0 +collision_mask = 128 [node name="CollisionShape2D" parent="Hurtbox" index="0"] position = Vector2( 0, -9 ) diff --git a/src/Maps/Grid.gd b/src/Maps/Grid.gd index 19bea11..0a67aa9 100644 --- a/src/Maps/Grid.gd +++ b/src/Maps/Grid.gd @@ -64,6 +64,9 @@ func reset_history(): func countTargets(table): + for i in range(table.size()): + table[i]=0 + for x in range(14): for y in range(7): for i in prio_grid[x][y]: diff --git a/src/Objects/Barrel/Barrel.gd b/src/Objects/Barrel/Barrel.gd index d45e1bf..e355b25 100644 --- a/src/Objects/Barrel/Barrel.gd +++ b/src/Objects/Barrel/Barrel.gd @@ -1,5 +1,6 @@ extends StaticBody2D +export(int,1,10) var health = 1 var GreenDrop = 0.5 var BlueDrop = 0.4 var RedDrop = 0.2 @@ -10,6 +11,9 @@ func offset_vec(): return Vector2((randf()-0.5)*offset, (randf()-0.5)*offset) func _on_Hurtbox_area_entered(area): + health -= area.damage + if(health>0): + return queue_free() var GreenRubies = load("res://Objects/Rubies/Green.tscn") var BlueRubies = load("res://Objects/Rubies/Blue.tscn") diff --git a/src/Objects/Barrel/Barrel.tscn b/src/Objects/Barrel/Barrel.tscn index 942399f..b38e999 100644 --- a/src/Objects/Barrel/Barrel.tscn +++ b/src/Objects/Barrel/Barrel.tscn @@ -24,9 +24,11 @@ kind = 9 position = Vector2( 0.244171, -10.0111 ) texture = ExtResource( 3 ) -[node name="Hurtbox" parent="." instance=ExtResource( 1 )] +[node name="Hurtbox" parent="." groups=[ +"HittableByPlayer", +] instance=ExtResource( 1 )] collision_layer = 8 -collision_mask = 0 +collision_mask = 128 [node name="CollisionShape2D" parent="Hurtbox" index="0"] position = Vector2( 0.322258, -10.0297 ) diff --git a/src/Objects/Torch/Torch.gd b/src/Objects/Torch/Torch.gd index 860acde..774c993 100644 --- a/src/Objects/Torch/Torch.gd +++ b/src/Objects/Torch/Torch.gd @@ -22,6 +22,6 @@ func _physics_process(delta): func _on_Hurtbox_area_entered(area): lifePoints -= area.damage - if(lifePoints<0): + if(lifePoints<=0): queue_free() pass diff --git a/src/Objects/Torch/Torch.tscn b/src/Objects/Torch/Torch.tscn index 73caedf..f6d5e0f 100644 --- a/src/Objects/Torch/Torch.tscn +++ b/src/Objects/Torch/Torch.tscn @@ -24,9 +24,11 @@ position = Vector2( 1.88936, -12.4698 ) position = Vector2( 0, -8 ) texture = ExtResource( 2 ) -[node name="Hurtbox" parent="." instance=ExtResource( 1 )] +[node name="Hurtbox" parent="." groups=[ +"HittableByPlayer", +] instance=ExtResource( 1 )] collision_layer = 8 -collision_mask = 0 +collision_mask = 128 script = null [node name="CollisionShape2D" parent="Hurtbox" index="0"] diff --git a/src/Overlap/AI/AI_Hero.gd b/src/Overlap/AI/AI_Hero.gd index e855dd9..d96e897 100644 --- a/src/Overlap/AI/AI_Hero.gd +++ b/src/Overlap/AI/AI_Hero.gd @@ -38,9 +38,11 @@ var abortProb = 0.01 var targetFieldCur = [0,0] var targetFieldUsed = false -var actionField = [0,0] +var actionKind = Grid.Kind.TERMINAL_SYMBOL var actionFieldUsed = false +var areaRefList = [] + var threadTime = 0.4 var threadDelta = 0.0 #calculates the sum of all present prios @@ -263,61 +265,48 @@ func AStar(source, target): func movement_calulcaotr(): var currentPosition = grid._pixel_to_grid_coords(global_position) - var calcNew = false - var MoveAdvice + var enemyKind if(actionFieldUsed==false): - calcNew = true - - if(calcNew==true): - var enemyKind = calcEnemyKind() - if(enemyKind==Grid.Kind.TERMINAL_SYMBOL): - return - actionField = grid.get_nearest(currentPosition, enemyKind) - if(actionField==[-1,-1]): - return + enemyKind = calcEnemyKind() + actionKind = enemyKind actionFieldUsed = true + else: + enemyKind = actionKind - MoveAdvice = getMoveDescription(currentPosition, actionField) + if(enemyKind==Grid.Kind.TERMINAL_SYMBOL): + return + + var targetField = grid.get_nearest(currentPosition, enemyKind) + if(targetField==[-1,-1]): + return + + + var MoveAdvice = getMoveDescription(currentPosition, targetField) grid.reset_history() return MoveAdvice -func is_hittable(target): - for element in grid.prio_grid[target[0]][target[1]]: - if(element == grid.Kind.BOSS || element == grid.Kind.TORCH || element == grid.Kind.MINION): - return true - return false +func is_hittable(): + var length = areaRefList.size() + if length == 0: + return null + var randomNumber = randi()%length + return instance_from_id(areaRefList[randomNumber]).global_position -func hit_or_miss(target, current, hitable, delta): - run(Vector2(target[0]-current[0], target[1]-current[1]), delta*8) +func hit_or_miss(target, current, delta): attac(Vector2(target[0]-current[0], target[1]-current[1]), delta*4) - return hitable func movement_decider_ai(target, kindOfStep, delta): var currentPosition = grid._pixel_to_grid_coords(global_position) var field_of_movement = target + var currentPixel = global_position + var hitPixelTarget = is_hittable() - var top = [currentPosition[0]+0, currentPosition[1]-1] - var left = [currentPosition[0]-1, currentPosition[1]-0] - var right = [currentPosition[0]+1, currentPosition[1]-0] - var down = [currentPosition[0]+0, currentPosition[1]+1] - var field = [currentPosition[0]+0, currentPosition[1]+0] - - - if(grid._is_in_grid(Vector2(field[0], field[1])) && hit_or_miss(field, currentPosition, is_hittable(field), delta)): - pass - elif(grid._is_in_grid(Vector2(target[0], target[1])) && hit_or_miss(target, currentPosition, is_hittable(target), delta)): - pass - elif(grid._is_in_grid(Vector2(left[0], left[1])) && hit_or_miss(left, currentPosition, is_hittable(left), delta)): - pass - elif(grid._is_in_grid(Vector2(down[0], down[1])) && hit_or_miss(down, currentPosition, is_hittable(down), delta)): - pass - elif(grid._is_in_grid(Vector2(top[0], top[1])) && hit_or_miss(top, currentPosition, is_hittable(top), delta)): - pass - elif(grid._is_in_grid(Vector2(down[0], down[1])) && hit_or_miss(down, currentPosition, is_hittable(down), delta)): - pass - else: + if hitPixelTarget!=null: + hit_or_miss(hitPixelTarget, currentPixel, delta*4) + actionFieldUsed = false + else: if(kindOfStep==STEP): run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) targetFieldCur = target @@ -333,19 +322,20 @@ func movement_decider_ai(target, kindOfStep, delta): func movement_execution(delta): if(targetFieldUsed): - var cur = grid._pixel_to_grid_coords(global_position) - var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) - if(distance<0.01): - targetFieldUsed = false - ExecutionState = AI_MOVE - if(targetFieldCur[0]==actionField[0]&&targetFieldCur[1]==actionField[1]): - actionFieldUsed = false - else: - var currentPosition = grid._pixel_to_grid_coords(global_position) - if(ai_movement_state==STEP): - run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) - elif(ai_movement_state==ROLL): - run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) + var cur = grid._pixel_to_grid_coords(global_position) + var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) + if(distance<0.1): + targetFieldUsed = false + ExecutionState = AI_MOVE + var actionField = grid.get_nearest(cur, actionKind) + if(targetFieldCur[0]==actionField[0]&&targetFieldCur[1]==actionField[1]): + actionFieldUsed = false + else: + var currentPosition = grid._pixel_to_grid_coords(global_position) + if(ai_movement_state==STEP): + run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) + elif(ai_movement_state==ROLL): + run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) func reset_exeution_state(delta): diff --git a/src/Player/Player.gd b/src/Player/Player.gd index 2dd08ff..679913c 100644 --- a/src/Player/Player.gd +++ b/src/Player/Player.gd @@ -209,3 +209,13 @@ func movement_idle(): movementState = moveState.IDLE velocity = Vector2.ZERO animation_state.change_state("idle") + + +func _on_SwordRange_area_entered(area): + if(area.is_in_group("HittableByPlayer")): + areaRefList.push_back(area.get_instance_id()) + + +func _on_SwordRange_area_exited(area): + if(area.is_in_group("HittableByPlayer")): + areaRefList.erase(area.get_instance_id()) diff --git a/src/Player/Player.tscn b/src/Player/Player.tscn index 662e5c5..8654a0d 100644 --- a/src/Player/Player.tscn +++ b/src/Player/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=63 format=2] +[gd_scene load_steps=64 format=2] [ext_resource path="res://Player/Player.gd" type="Script" id=1] [ext_resource path="res://Player/player.png" type="Texture" id=2] @@ -619,7 +619,10 @@ height = 0.2 radius = 4.03497 height = 6.99104 -[sub_resource type="DynamicFont" id=49] +[sub_resource type="CircleShape2D" id=51] +radius = 14.7132 + +[sub_resource type="DynamicFont" id=50] size = 12 font_data = ExtResource( 6 ) @@ -691,7 +694,7 @@ position = Vector2( 1.90735e-06, 0.000833988 ) shape = SubResource( 47 ) [node name="Pivot" type="Position2D" parent="."] -position = Vector2( 0, -4.16248 ) +position = Vector2( 0, -4 ) rotation = 3.14159 __meta__ = { "_gizmo_extents_": 20.0 @@ -706,12 +709,24 @@ position = Vector2( 8.43416, 0.0698299 ) shape = SubResource( 48 ) disabled = true +[node name="SwordRange" parent="Pivot" instance=ExtResource( 4 )] +position = Vector2( 1.15451e-05, -4.16248 ) +rotation = -3.14159 +scale = Vector2( 0.909091, 0.909091 ) +collision_layer = 128 +collision_mask = 0 +damage = 0.0 + +[node name="CollisionShape2D" parent="Pivot/SwordRange" index="0"] +position = Vector2( 0, -4.56405 ) +shape = SubResource( 51 ) + [node name="DebugLabel" type="Label" parent="."] -margin_left = -8.01196 -margin_top = -21.2223 -margin_right = 8.98804 -margin_bottom = -9.22228 -custom_fonts/font = SubResource( 49 ) +margin_left = -8.12021 +margin_top = -21.9801 +margin_right = 12.8798 +margin_bottom = -9.98004 +custom_fonts/font = SubResource( 50 ) text = "Held" __meta__ = { "_edit_use_anchors_": false @@ -744,6 +759,8 @@ script = ExtResource( 16 ) [connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"] [connection signal="area_entered" from="Hurtbox" to="." method="_on_Hurtbox_area_entered"] [connection signal="area_exited" from="Hurtbox" to="." method="_on_Hurtbox_area_exited"] +[connection signal="area_entered" from="Pivot/SwordRange" to="." method="_on_SwordRange_area_entered"] +[connection signal="area_exited" from="Pivot/SwordRange" to="." method="_on_SwordRange_area_exited"] [connection signal="no_health" from="Stats" to="." method="_on_Stats_no_health"] [editable path="Hitbox"] @@ -751,3 +768,5 @@ script = ExtResource( 16 ) [editable path="Hurtbox"] [editable path="Pivot/SwordHitbox"] + +[editable path="Pivot/SwordRange"] diff --git a/src/World.tscn b/src/World.tscn index 8906b4d..294728b 100644 --- a/src/World.tscn +++ b/src/World.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=11 format=2] +[gd_scene load_steps=12 format=2] [ext_resource path="res://Player/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://World.gd" type="Script" id=2] @@ -7,6 +7,7 @@ [ext_resource path="res://Menus/DragNDrop/DragNDropUI.tscn" type="PackedScene" id=5] [ext_resource path="res://Menus/DialogueBox/DialogueBox.tscn" type="PackedScene" id=6] [ext_resource path="res://Objects/Torch/Torch.tscn" type="PackedScene" id=7] +[ext_resource path="res://Objects/Barrel/Barrel.tscn" type="PackedScene" id=8] [ext_resource path="res://Objects/Bonfire/Bonfire.tscn" type="PackedScene" id=10] [ext_resource path="res://Boss/Boss_template.tscn" type="PackedScene" id=17] [ext_resource path="res://Maps/Grid.tscn" type="PackedScene" id=18] @@ -15,7 +16,7 @@ script = ExtResource( 2 ) [node name="WallSprite" type="Sprite" parent="."] -position = Vector2( 355.382, 175.62 ) +position = Vector2( 360, 176 ) texture = ExtResource( 4 ) region_enabled = true region_rect = Rect2( 0, 0, 1280, 720 ) @@ -37,18 +38,21 @@ position = Vector2( 152, 120 ) [node name="Player" parent="YSort" instance=ExtResource( 1 )] position = Vector2( 200, 8 ) scale = Vector2( 2, 2 ) -debug = true ROLL_SPEED = 140 FRICTION = 200 [node name="Boss_template" parent="YSort" instance=ExtResource( 17 )] position = Vector2( -56, 8 ) +debug = true [node name="Bonfire" parent="YSort" instance=ExtResource( 10 )] position = Vector2( 288, 104 ) [node name="Torch" parent="YSort" instance=ExtResource( 7 )] -position = Vector2( 264, -40 ) +position = Vector2( 264, -24 ) + +[node name="Barrel" parent="YSort" instance=ExtResource( 8 )] +position = Vector2( 40, 8 ) [node name="Grid" parent="." instance=ExtResource( 18 )] diff --git a/src/project.godot b/src/project.godot index 92abe87..5485f84 100644 --- a/src/project.godot +++ b/src/project.godot @@ -148,6 +148,7 @@ attack={ 2d_physics/layer_5="trap" 2d_physics/layer_6="collectable" 2d_physics/layer_7="Bonfire" +2d_physics/layer_8="SwordRange" [rendering] From 3ec908f6c303610c7605618b118275086bf01e37 Mon Sep 17 00:00:00 2001 From: Jonas Mucke Date: Mon, 20 Apr 2020 13:15:24 +0200 Subject: [PATCH 3/4] ai adaptation --- src/Boss/Minion.gd | 21 ++- src/Boss/Minion.tscn | 10 +- src/Maps/Grid.gd | 2 +- src/Objects/Barrel/Barrel.gd | 6 +- src/Objects/Slime/Slime.tscn | 3 +- src/Objects/Torch/Torch.gd | 2 +- src/Overlap/AI/AI_Hero.gd | 108 +++++--------- src/Overlap/AI/AI_Minion.gd | 265 +++++++++++++++++++++++++++++++++++ src/Player/Player.gd | 10 +- src/Player/Player.tscn | 5 +- src/World.tscn | 54 +++++-- src/project.godot | 6 + 12 files changed, 399 insertions(+), 93 deletions(-) create mode 100644 src/Overlap/AI/AI_Minion.gd diff --git a/src/Boss/Minion.gd b/src/Boss/Minion.gd index 711ee35..25a6cb8 100644 --- a/src/Boss/Minion.gd +++ b/src/Boss/Minion.gd @@ -1,4 +1,4 @@ -extends KinematicBody2D +extends Minion var velocity := Vector2.ZERO @@ -12,9 +12,14 @@ onready var debug_label := $DebugLabel var damage_per_second := 0.0 var totaldamage := 0.0 +var rollvector = Vector2.ZERO + func _debug_update(): debug_label.text = str(player_stats.health) + "/" + str(player_stats.max_health) + " HP\n" +func _ready(): + grid = get_tree().current_scene.get_node("Grid") + # IMPORTANT: If you are using move_and_slide don't multiply by delta # Godots physics system does that internally # In move_and_collide(...) you have to multiply by delta. @@ -31,6 +36,9 @@ func _physics_process(delta): totaldamage += 1 player_stats.health += 1 _debug_update() + + run(Vector2.ZERO, delta) + makeMove(delta) move() @@ -45,3 +53,14 @@ func _on_Hurtbox_area_entered(area): func _on_Hurtbox_area_exited(area): damage_per_second -= area.damage + +# API Interface for ai_hero +func run(direction, delta): + direction = direction.normalized() + rollvector = direction + velocity = velocity.move_toward(player_stats.speed * rollvector, ACCELERATION * delta) + + if direction == Vector2.ZERO: + pass + else: + pass diff --git a/src/Boss/Minion.tscn b/src/Boss/Minion.tscn index 635e2a4..746afdc 100644 --- a/src/Boss/Minion.tscn +++ b/src/Boss/Minion.tscn @@ -12,14 +12,15 @@ radius = 6.0 [sub_resource type="CapsuleShape2D" id=2] radius = 11.0 -height = 11.0 +height = 1.0 [sub_resource type="CapsuleShape2D" id=3] radius = 11.0 -height = 11.0 +height = 1.0 [node name="Minion" type="KinematicBody2D"] script = ExtResource( 6 ) +ACCELERATION = 500 [node name="Kind" parent="." instance=ExtResource( 3 )] kind = 3 @@ -37,7 +38,7 @@ collision_layer = 0 collision_mask = 65 [node name="CollisionShape2D" parent="Hitbox" index="0"] -position = Vector2( 0, -9 ) +position = Vector2( 0.110184, -4.81305 ) shape = SubResource( 2 ) [node name="Hurtbox" parent="." groups=[ @@ -47,7 +48,7 @@ collision_layer = 8 collision_mask = 128 [node name="CollisionShape2D" parent="Hurtbox" index="0"] -position = Vector2( 0, -9 ) +position = Vector2( 0.110184, -4.81305 ) shape = SubResource( 3 ) [node name="DebugLabel" type="Label" parent="."] @@ -62,6 +63,7 @@ __meta__ = { [node name="Stats" parent="." instance=ExtResource( 4 )] max_health = 2 +max_speed = 80.0 [connection signal="area_entered" from="Hurtbox" to="." method="_on_Hurtbox_area_entered"] [connection signal="area_exited" from="Hurtbox" to="." method="_on_Hurtbox_area_exited"] [connection signal="no_health" from="Stats" to="." method="_on_Stats_no_health"] diff --git a/src/Maps/Grid.gd b/src/Maps/Grid.gd index 0a67aa9..1963a01 100644 --- a/src/Maps/Grid.gd +++ b/src/Maps/Grid.gd @@ -7,7 +7,7 @@ var prio_grid : Array = [] var used_grid : Array = [] var time_passed := 0.0 var offset -export(float, 0, 42.0) var refresh_rate = 1 +export(float, 0, 42.0) var refresh_rate = 0.0 func _draw_object_grid(): diff --git a/src/Objects/Barrel/Barrel.gd b/src/Objects/Barrel/Barrel.gd index e355b25..9aae4a5 100644 --- a/src/Objects/Barrel/Barrel.gd +++ b/src/Objects/Barrel/Barrel.gd @@ -1,9 +1,9 @@ extends StaticBody2D export(int,1,10) var health = 1 -var GreenDrop = 0.5 -var BlueDrop = 0.4 -var RedDrop = 0.2 +var GreenDrop = 0.4 +var BlueDrop = 0.5 +var RedDrop = 0.8 var Heart = 0.2 func offset_vec(): diff --git a/src/Objects/Slime/Slime.tscn b/src/Objects/Slime/Slime.tscn index d751da2..939f227 100644 --- a/src/Objects/Slime/Slime.tscn +++ b/src/Objects/Slime/Slime.tscn @@ -11,9 +11,10 @@ extents = Vector2( 16, 16 ) [node name="Kind" parent="." instance=ExtResource( 3 )] general = 2 -kind = 2 +kind = 10 [node name="Sprite" type="Sprite" parent="."] +position = Vector2( 0, 1.90735e-06 ) texture = ExtResource( 1 ) [node name="Hurtbox" parent="." instance=ExtResource( 2 )] diff --git a/src/Objects/Torch/Torch.gd b/src/Objects/Torch/Torch.gd index 774c993..94e13ec 100644 --- a/src/Objects/Torch/Torch.gd +++ b/src/Objects/Torch/Torch.gd @@ -1,7 +1,7 @@ extends Node2D export(int, 1, 5) var lifePoints = 3 -export(int, 1, 30) var spawnRate = 5.0 +export(float, 0, 30) var spawnRate = 5.0 var Minion = load("res://Boss/Minion.tscn") var elapsedTime = 0.0 diff --git a/src/Overlap/AI/AI_Hero.gd b/src/Overlap/AI/AI_Hero.gd index d96e897..e298d71 100644 --- a/src/Overlap/AI/AI_Hero.gd +++ b/src/Overlap/AI/AI_Hero.gd @@ -7,12 +7,6 @@ const Grid = preload("res://Maps/Grid.gd") var grid - -enum{ - LENGTH, - WAY -} - enum{ STEP, ROLL, @@ -31,10 +25,6 @@ var ai_movement_state = NOTHING var numbers = [0,0,0,0,0,0,0,0,0,0] var prios = [7,0,6,5,4,3,2,1,1,4] -var totalPrioTurn = 0 -var executesTurn = false -var abortProb = 0.01 - var targetFieldCur = [0,0] var targetFieldUsed = false @@ -43,8 +33,9 @@ var actionFieldUsed = false var areaRefList = [] -var threadTime = 0.4 +var threadTime = 0.6 var threadDelta = 0.0 + #calculates the sum of all present prios func calcTotalPrio(): var sum = 0 @@ -79,7 +70,7 @@ func calcPrioTable(): #14+7 0.999 #updates heart and bonfire prio func adjustPrio(currentHealth, maxHealth): - var prioVal = 40.0 - (float(currentHealth)/float(maxHealth))*40.0 + var prioVal = 10.0 - (float(currentHealth)/float(maxHealth))*10.0 var bonfire = prioVal + 1 var hearts = prioVal if(hearts < 0): @@ -106,16 +97,16 @@ func getCost(field): for i in grid.object_grid[field.x][field.y]: match i: Grid.Kind.DAMAGE: - cost += prios[Grid.Kind.BONFIRE] * 32 + cost += 100 Grid.Kind.SLOW: - cost += 1 + cost += 1 return cost #return an heurestic of distance # curr - current position # targ - a target position func h_fn(curr, target): - return sqrt(pow(target[0]-curr[0],2)+pow(target[0]-curr[0],2)) + return 0 # currCost - currentCost # target - position of the field to move to @@ -127,13 +118,13 @@ func adjacent(currentPosition, can_roll = true): var adj := [] #adj.append([STEP, Vector2(0,0)]) var p = currentPosition - var pot_adj_step = [[p[0]-1, p[1]-1], [p[0]-1, p[1]-0], [p[0]-1, p[1]+1], - [p[0]+0, p[1]-1], [p[0]+0, p[1]+1], - [p[0]+1, p[1]-1], [p[0]+1, p[1]+0], [p[0]+1, p[1]+1]] + var pot_adj_step = [[p[0]-1, p[1]-1], [p[0]-0, p[1]-1], [p[0]+1, p[1]-1], + [p[0]-1, p[1]-0], [p[0]+1, p[1]+0], + [p[0]-1, p[1]+1], [p[0]+0, p[1]+1], [p[0]+1, p[1]+1]] - var pot_adj_roll = [[p[0]-2, p[1]-2], [p[0]-2, p[1]-0], [p[0]-2, p[1]+2], - [p[0]+0, p[1]-2], [p[0]+0, p[1]+2], - [p[0]+2, p[1]-2], [p[0]+2, p[1]+0], [p[0]+2, p[1]+2]] + var pot_adj_roll = [[p[0]-0, p[1]-2], + [p[0]-2, p[1]-0],[p[0]+2, p[1]+0], + [p[0]+0, p[1]+2]] for i in range(pot_adj_step.size()): @@ -148,6 +139,8 @@ func adjacent(currentPosition, can_roll = true): continue if(grid.used_grid[next[0]][next[1]]): continue + if(grid._is_in_grid(Vector2(next[0], next[1])) ==false): + continue if(grid.object_grid[next[0]][next[1]][0]!=Grid.Kind.WALL): if(i==0): if(grid.object_grid[pot_adj_step[1][0]][pot_adj_step[1][1]][0]!=Grid.Kind.WALL && @@ -172,6 +165,7 @@ func adjacent(currentPosition, can_roll = true): adj.append([STEP, Vector2(next[0],next[1]),1.0]) + for i in range(pot_adj_roll.size()): var next = pot_adj_roll[i] if(next[0]<0): @@ -184,49 +178,21 @@ func adjacent(currentPosition, can_roll = true): continue if(grid.used_grid[next[0]][next[1]]): continue - if(grid.object_grid[next[0]][next[1]][0]!=Grid.Kind.WALL): - continue + if(grid._is_in_grid(Vector2(next[0], next[1])) == false): + continue if(grid.object_grid[next[0]][next[1]][0]!=Grid.Kind.WALL): if(i==0): - if(grid.object_grid[next[0]+0][next[1]+1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]+0][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]+1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]+2][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+2][next[1]+1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.1]) - if(i==1): if(grid.object_grid[next[0]+0][next[1]+1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.0]) - if(i==2): - if(grid.object_grid[next[0]-0][next[1]+1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]+0][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]+1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]+2][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-2][next[1]+1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.1]) - if(i==3): + adj.append([ROLL, Vector2(next[0],next[1]),1.0]) + if(i==1): if(grid.object_grid[next[0]+1][next[1]+0][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.0]) - if(i==4): + adj.append([ROLL, Vector2(next[0],next[1]),1.0]) + if(i==2): if(grid.object_grid[next[0]-1][next[1]+0][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.0]) - if(i==5): - if(grid.object_grid[next[0]+0][next[1]-1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]-0][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]-1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+1][next[1]-2][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]+2][next[1]-1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.1]) - if(i==6): + adj.append([ROLL, Vector2(next[0],next[1]),1.0]) + if(i==3): if(grid.object_grid[next[0]+0][next[1]-1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.0]) - if(i==7): - if(grid.object_grid[next[0]-0][next[1]-1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]-0][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]-1][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-1][next[1]-2][0]!=Grid.Kind.WALL && - grid.object_grid[next[0]-2][next[1]-1][0]!=Grid.Kind.WALL): - adj.append([ROLL, Vector2(next[0],next[1]),2.1]) + adj.append([ROLL, Vector2(next[0],next[1]),1.0]) return adj @@ -250,6 +216,7 @@ func AStar(source, target): # Set flag grid.used_grid[node[2][0]][node[2][1]] = true var adj_list = adjacent(node[2]) + var current_field = node[2] for i in adj_list: var move_cost = i[2] @@ -267,7 +234,9 @@ func movement_calulcaotr(): var currentPosition = grid._pixel_to_grid_coords(global_position) var enemyKind - if(actionFieldUsed==false): + + numbers = grid.countTargets(numbers) + if(actionKind == grid.Kind.TERMINAL_SYMBOL || numbers[actionKind]==0 || actionFieldUsed==false): enemyKind = calcEnemyKind() actionKind = enemyKind actionFieldUsed = true @@ -291,21 +260,19 @@ func is_hittable(): var length = areaRefList.size() if length == 0: return null - var randomNumber = randi()%length - return instance_from_id(areaRefList[randomNumber]).global_position + return instance_from_id(areaRefList[0]).global_position func hit_or_miss(target, current, delta): attac(Vector2(target[0]-current[0], target[1]-current[1]), delta*4) func movement_decider_ai(target, kindOfStep, delta): var currentPosition = grid._pixel_to_grid_coords(global_position) - var field_of_movement = target var currentPixel = global_position var hitPixelTarget = is_hittable() if hitPixelTarget!=null: hit_or_miss(hitPixelTarget, currentPixel, delta*4) - actionFieldUsed = false + else: if(kindOfStep==STEP): run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) @@ -321,6 +288,13 @@ func movement_decider_ai(target, kindOfStep, delta): func movement_execution(delta): + var currentPixel = global_position + var hitPixelTarget = is_hittable() + + if hitPixelTarget!=null: + hit_or_miss(hitPixelTarget, currentPixel, delta*4) + return + if(targetFieldUsed): var cur = grid._pixel_to_grid_coords(global_position) var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) @@ -346,13 +320,7 @@ func reset_exeution_state(delta): -func makeMove(delta): - - #if(actionFieldUsed==true): - # var random = randf() - # if(random < mindChangeProbability): - # ExecutionState = AI_MOVE - +func makeMove(delta): if ExecutionState == AI_MOVE: threadDelta = 0 var MoveAdvice = movement_calulcaotr() diff --git a/src/Overlap/AI/AI_Minion.gd b/src/Overlap/AI/AI_Minion.gd new file mode 100644 index 0000000..e2acc53 --- /dev/null +++ b/src/Overlap/AI/AI_Minion.gd @@ -0,0 +1,265 @@ +extends KinematicBody2D + +class_name Minion + +const PrioQueue = preload("prio_queue.gd") # Relative path +const Grid = preload("res://Maps/Grid.gd") + +var grid + +enum{ + STEP, + NOTHING +} + +enum{ + EXECUTING, + AI_MOVE +} + +var ExecutionState = AI_MOVE +var ai_movement_state = NOTHING + +var numbers = [0,0,0,0,0,0,0,0,0,0] +var prios = [0,6,0,0,0,0,0,0,4,0] + + +var targetFieldCur = [0,0] +var targetFieldUsed = false + +var actionKind = Grid.Kind.TERMINAL_SYMBOL +var actionFieldUsed = false + +var threadTime = 0.4 +var threadDelta = 0.0 + +#calculates the sum of all present prios +func calcTotalPrio(): + var sum = 0 + var i = Grid.Kind.BOSS + while i != Grid.Kind.TERMINAL_SYMBOL: + if(numbers[i]>0): + sum += prios[i] + i += 1 + return sum + +#calculates the relative porio +func calcRelPrio(index, sum) -> float: + if(sum==0): + return 0.0 + return float(prios[index])/float(sum) + +#calucaltes the prio table of all enemies[0,1) +func calcPrioTable(): + var table = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] + numbers = grid.countTargets(numbers) + var lower = 0.0 + var sum = calcTotalPrio() + + var i = 0; + while i != Grid.Kind.TERMINAL_SYMBOL: + if(numbers[i]!=0): + lower += calcRelPrio(i, sum) + table[i] = lower + i += 1 + + return table + +#14+7 0.999 +#updates heart and bonfire prio +func adjustPrio(currentHealth, maxHealth): + return + +#return the enemie which will be attacked +func calcEnemyKind(): + var table = calcPrioTable() + var number = randf() + var i = 0 + while i!=Grid.Kind.TERMINAL_SYMBOL and table[i] <= number: + i += 1 + return i + +#returns a move +func getMoveDescription(myPosition : Vector2, targetPositions): + return AStar(myPosition, targetPositions) + + +func getCost(field): + return 0 + +#return an heurestic of distance +# curr - current position +# targ - a target position +func h_fn(curr, target): + return sqrt(pow(target[0]-curr[0],2)+pow(target[0]-curr[0],2)) + +# currCost - currentCost +# target - position of the field to move to +func g_fn(currCost, target): + return currCost + getCost(target) + +# Returns the list of adjacent nodes +func adjacent(currentPosition, can_roll = false): + var adj := [] + #adj.append([STEP, Vector2(0,0)]) + var p = currentPosition + var pot_adj_step = [[p[0]-1, p[1]-1], [p[0]-1, p[1]-0], [p[0]-1, p[1]+1], + [p[0]+0, p[1]-1], [p[0]+0, p[1]+1], + [p[0]+1, p[1]-1], [p[0]+1, p[1]+0], [p[0]+1, p[1]+1]] + + + for i in range(pot_adj_step.size()): + var next = pot_adj_step[i] + if(next[0]<0): + continue + if(next[0]>13): + continue + if(next[1]<0): + continue + if(next[1]>6): + continue + if(grid.used_grid[next[0]][next[1]]): + continue + if(grid.object_grid[next[0]][next[1]][0]!=Grid.Kind.WALL): + if(i==0): + if(grid.object_grid[pot_adj_step[1][0]][pot_adj_step[1][1]][0]!=Grid.Kind.WALL && + grid.object_grid[pot_adj_step[3][0]][pot_adj_step[3][1]][0]!=Grid.Kind.WALL): + adj.append([STEP, Vector2(next[0],next[1]),1.1]) + continue + if(i==2): + if(grid.object_grid[pot_adj_step[1][0]][pot_adj_step[1][1]][0]!=Grid.Kind.WALL && + grid.object_grid[pot_adj_step[4][0]][pot_adj_step[4][1]][0]!=Grid.Kind.WALL): + adj.append([STEP, Vector2(next[0],next[1]),1.1]) + continue + if(i==5): + if(grid.object_grid[pot_adj_step[3][0]][pot_adj_step[3][1]][0]!=Grid.Kind.WALL && + grid.object_grid[pot_adj_step[6][0]][pot_adj_step[6][1]][0]!=Grid.Kind.WALL): + adj.append([STEP, Vector2(next[0],next[1]),1.1]) + continue + if(i==7): + if(grid.object_grid[pot_adj_step[4][0]][pot_adj_step[4][1]][0]!=Grid.Kind.WALL && + grid.object_grid[pot_adj_step[6][0]][pot_adj_step[6][1]][0]!=Grid.Kind.WALL): + adj.append([STEP, Vector2(next[0],next[1]),1.1]) + continue + + adj.append([STEP, Vector2(next[0],next[1]),1.0]) + + return adj + + +func AStar(source, target): + #swap rtarget and source, when target source istr reached, do inversxse step + # node layout [g+h(x), g(x), current, from, kind] + var tmp = source + source = target + target = tmp + + var Q = PrioQueue.new() + Q.insert([0,0, [source[0], source[1]], [source[0], source[1]], NOTHING] ) + while !Q.empty(): + var node = Q.delMin() + + # Check if reached + if(node[2][0] == target[0] and node[2][1] == target[1]): + return [node[4], node[3]] # 4 is kind | 3 is from + + # Set flag + grid.used_grid[node[2][0]][node[2][1]] = true + var adj_list = adjacent(node[2]) + for i in adj_list: + var move_cost = i[2] + + var g_val = g_fn(node[1]+move_cost, i[1]) + var h_val = h_fn(i[1], target) + + #[g+h(x), g(x), current, from, kind] + var new_node = [g_val+h_val, g_val,i[1], node[2], i[0]] + Q.insert(new_node) + + return [NOTHING, [0,0]] + + +func movement_calulcaotr(): + var currentPosition = grid._pixel_to_grid_coords(global_position) + + var enemyKind + if(actionFieldUsed==false): + enemyKind = calcEnemyKind() + actionKind = enemyKind + actionFieldUsed = true + else: + enemyKind = actionKind + + if(enemyKind==Grid.Kind.TERMINAL_SYMBOL): + return + + var targetField = grid.get_nearest(currentPosition, enemyKind) + if(targetField==[-1,-1]): + return + + + var MoveAdvice = getMoveDescription(currentPosition, targetField) + grid.reset_history() + + return MoveAdvice + + +func movement_decider_ai(target, kindOfStep, delta): + var currentPosition = grid._pixel_to_grid_coords(global_position) + var field_of_movement = target + var currentPixel = global_position + + if(kindOfStep==STEP): + run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) + targetFieldCur = target + targetFieldUsed = true + ai_movement_state = STEP + + ExecutionState = EXECUTING + + + +func movement_execution(delta): + if(targetFieldUsed): + var cur = grid._pixel_to_grid_coords(global_position) + var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) + if(distance<0.1): + targetFieldUsed = false + ExecutionState = AI_MOVE + var actionField = grid.get_nearest(cur, actionKind) + if(targetFieldCur[0]==actionField[0]&&targetFieldCur[1]==actionField[1]): + actionFieldUsed = false + else: + var currentPosition = grid._pixel_to_grid_coords(global_position) + if(ai_movement_state==STEP): + run(Vector2(targetFieldCur[0]-currentPosition[0], targetFieldCur[1]-currentPosition[1]), delta*4) + + +func reset_exeution_state(delta): + threadDelta = threadDelta + delta + if(threadDelta>threadTime): + ExecutionState = AI_MOVE + actionFieldUsed = false + + + +func makeMove(delta): + if ExecutionState == AI_MOVE: + threadDelta = 0 + var MoveAdvice = movement_calulcaotr() + if(MoveAdvice==null): + return + var target = MoveAdvice[1] + movement_decider_ai(target, MoveAdvice[0], delta) + + elif ExecutionState == EXECUTING: + movement_execution(delta) + reset_exeution_state(delta) + + +# API Interface for ai_hero -> methods are handled in player.gd + +func run(direction, delta): + pass + +#todo diff --git a/src/Player/Player.gd b/src/Player/Player.gd index 679913c..2abd01c 100644 --- a/src/Player/Player.gd +++ b/src/Player/Player.gd @@ -4,7 +4,7 @@ class_name Player This is an example player controller script created by Paul """ var velocity := Vector2.ZERO -var rollvector := Vector2.ZERO +var rollvector := Vector2(-1,0) # This is how you export variables with ranges to the editor window export(bool) var debug := false @@ -77,7 +77,7 @@ func _physics_process(delta): elif movementState == moveState.IDLE: movement_idle() else: - movement_run(Vector2(0,0), delta) + movement_run(Vector2.ZERO, delta) makeMove(delta) move() $"Effects/HealEffect".emitting = heal_per_second > 0 @@ -148,9 +148,11 @@ func movement_hit(): func hit_finished(): + grid._update_grid() movementState = moveState.IDLE ai_movement_state = STEP ExecutionState = EXECUTING + actionFieldUsed = false func movement_roll(): @@ -179,15 +181,19 @@ func _on_Hurtbox_area_entered(area): if area.damage > 0: damage_per_second += area.damage + pass else: heal_per_second += abs(area.damage) + pass func _on_Hurtbox_area_exited(area): if area.damage > 0: damage_per_second -= area.damage + pass else: heal_per_second -= abs(area.damage) + pass func _on_Stats_no_health(): diff --git a/src/Player/Player.tscn b/src/Player/Player.tscn index 8654a0d..97f2555 100644 --- a/src/Player/Player.tscn +++ b/src/Player/Player.tscn @@ -617,10 +617,10 @@ height = 0.2 [sub_resource type="CapsuleShape2D" id=48] radius = 4.03497 -height = 6.99104 +height = 9.42006 [sub_resource type="CircleShape2D" id=51] -radius = 14.7132 +radius = 13.3924 [sub_resource type="DynamicFont" id=50] size = 12 @@ -629,6 +629,7 @@ font_data = ExtResource( 6 ) [node name="Player" type="KinematicBody2D"] scale = Vector2( 1.1, 1.1 ) script = ExtResource( 1 ) +ROLL_SPEED = 120 FRICTION = 270 [node name="Kind" parent="." instance=ExtResource( 7 )] diff --git a/src/World.tscn b/src/World.tscn index 294728b..069a7d8 100644 --- a/src/World.tscn +++ b/src/World.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=2] +[gd_scene load_steps=16 format=2] [ext_resource path="res://Player/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://World.gd" type="Script" id=2] @@ -8,10 +8,15 @@ [ext_resource path="res://Menus/DialogueBox/DialogueBox.tscn" type="PackedScene" id=6] [ext_resource path="res://Objects/Torch/Torch.tscn" type="PackedScene" id=7] [ext_resource path="res://Objects/Barrel/Barrel.tscn" type="PackedScene" id=8] +[ext_resource path="res://Boss/Minion.tscn" type="PackedScene" id=9] [ext_resource path="res://Objects/Bonfire/Bonfire.tscn" type="PackedScene" id=10] +[ext_resource path="res://Objects/Slime/Slime.tscn" type="PackedScene" id=11] +[ext_resource path="res://Objects/Traps/Sting.tscn" type="PackedScene" id=12] [ext_resource path="res://Boss/Boss_template.tscn" type="PackedScene" id=17] [ext_resource path="res://Maps/Grid.tscn" type="PackedScene" id=18] +[sub_resource type="AnimationNodeStateMachinePlayback" id=1] + [node name="World" type="Node2D"] script = ExtResource( 2 ) @@ -26,7 +31,7 @@ position = Vector2( 16, 16 ) tile_set = ExtResource( 3 ) cell_size = Vector2( 32, 32 ) format = 1 -tile_data = PoolIntArray( -131059, 47, 0, -131058, 47, 2, -1, 47, 4, -65536, 47, 196609, -65535, 47, 196609, -65534, 47, 196609, -65533, 47, 196609, -65532, 47, 196609, -65531, 47, 196609, -65530, 47, 8, -65529, 47, 196609, -65528, 47, 8, -65527, 47, 196609, -65526, 47, 196609, -65525, 47, 196609, -65524, 47, 196609, -65523, 47, 196614, -65522, 47, 196618, -65521, 47, 196610, 65535, 47, 65539, 6, 47, 131075, 8, 47, 131075, 14, 47, 65539, 131071, 47, 65539, 65541, 47, 196611, 65550, 47, 65539, 196607, 47, 65539, 131075, 47, 196608, 131076, 47, 196610, 131086, 47, 65539, 262143, 47, 65539, 196614, 47, 196611, 196622, 47, 65539, 327679, 47, 65539, 262147, 47, 196611, 262149, 47, 196611, 262158, 47, 65539, 393215, 47, 65539, 327684, 47, 196611, 327688, 47, 196611, 327694, 47, 65539, 458751, 47, 65539, 393221, 47, 3, 393225, 47, 3, 393230, 47, 65539, 524287, 47, 196612, 458752, 47, 196609, 458753, 47, 196609, 458754, 47, 196609, 458755, 47, 196609, 458756, 47, 196609, 458757, 47, 196616, 458758, 47, 196609, 458759, 47, 196609, 458760, 47, 196609, 458761, 47, 196616, 458762, 47, 196609, 458763, 47, 196609, 458764, 47, 196609, 458765, 47, 196609, 458766, 47, 196615 ) +tile_data = PoolIntArray( -131059, 47, 0, -131058, 47, 2, -1, 47, 4, -65536, 47, 196609, -65535, 47, 196609, -65534, 47, 196609, -65533, 47, 196609, -65532, 47, 196609, -65531, 47, 196609, -65530, 47, 8, -65529, 47, 196609, -65528, 47, 8, -65527, 47, 196609, -65526, 47, 196609, -65525, 47, 196609, -65524, 47, 196609, -65523, 47, 196614, -65522, 47, 196618, -65521, 47, 196610, 65535, 47, 65539, 6, 47, 131075, 8, 47, 131075, 14, 47, 65539, 131071, 47, 65539, 65541, 47, 196611, 65550, 47, 65539, 196607, 47, 65539, 131075, 47, 196608, 131076, 47, 196610, 131086, 47, 65539, 262143, 47, 65539, 196614, 47, 196611, 196622, 47, 65539, 327679, 47, 65539, 262147, 47, 196611, 262149, 47, 196611, 262158, 47, 65539, 393215, 47, 65539, 327684, 47, 196611, 327694, 47, 65539, 458751, 47, 65539, 393221, 47, 3, 393230, 47, 65539, 524287, 47, 196612, 458752, 47, 196609, 458753, 47, 196609, 458754, 47, 196609, 458755, 47, 196609, 458756, 47, 196609, 458757, 47, 196616, 458758, 47, 196609, 458759, 47, 196609, 458760, 47, 196609, 458761, 47, 196609, 458762, 47, 196609, 458763, 47, 196609, 458764, 47, 196609, 458765, 47, 196609, 458766, 47, 196615 ) __meta__ = { "_edit_group_": true, "_edit_lock_": true @@ -36,24 +41,53 @@ __meta__ = { position = Vector2( 152, 120 ) [node name="Player" parent="YSort" instance=ExtResource( 1 )] -position = Vector2( 200, 8 ) +position = Vector2( 136, 112 ) scale = Vector2( 2, 2 ) -ROLL_SPEED = 140 FRICTION = 200 +[node name="AnimationTree" parent="YSort/Player" index="4"] +parameters/playback = SubResource( 1 ) + +[node name="Stats" parent="YSort/Player" index="9"] +max_health = 20 + [node name="Boss_template" parent="YSort" instance=ExtResource( 17 )] position = Vector2( -56, 8 ) -debug = true [node name="Bonfire" parent="YSort" instance=ExtResource( 10 )] position = Vector2( 288, 104 ) -[node name="Torch" parent="YSort" instance=ExtResource( 7 )] -position = Vector2( 264, -24 ) - [node name="Barrel" parent="YSort" instance=ExtResource( 8 )] position = Vector2( 40, 8 ) +[node name="Torch" parent="YSort" instance=ExtResource( 7 )] +position = Vector2( -112, -72 ) +spawnRate = 2.039 + +[node name="Minion" parent="YSort" instance=ExtResource( 9 )] +position = Vector2( 240, -40 ) + +[node name="Minion2" parent="YSort" instance=ExtResource( 9 )] +position = Vector2( 96, -80 ) + +[node name="Slime" parent="YSort" instance=ExtResource( 11 )] +position = Vector2( 104, 104 ) + +[node name="Slime2" parent="YSort" instance=ExtResource( 11 )] +position = Vector2( 168, 104 ) + +[node name="Slime3" parent="YSort" instance=ExtResource( 11 )] +position = Vector2( 136, 72 ) + +[node name="Slime4" parent="YSort" instance=ExtResource( 11 )] +position = Vector2( 168, 72 ) + +[node name="Slime5" parent="YSort" instance=ExtResource( 11 )] +position = Vector2( 104, 72 ) + +[node name="Sting" parent="YSort" instance=ExtResource( 12 )] +position = Vector2( 136, 48 ) + [node name="Grid" parent="." instance=ExtResource( 18 )] [node name="CanvasLayer" type="CanvasLayer" parent="."] @@ -62,6 +96,10 @@ position = Vector2( 40, 8 ) visible = false [node name="DragNDropUI" parent="CanvasLayer" instance=ExtResource( 5 )] +margin_left = 0.0 +margin_right = 0.0 ObjectParent = NodePath("../..") +[editable path="YSort/Player"] + [editable path="YSort/Bonfire"] diff --git a/src/project.godot b/src/project.godot index 5485f84..2438715 100644 --- a/src/project.godot +++ b/src/project.godot @@ -24,6 +24,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://Overlap/AI/AI_Hero.gd" }, { +"base": "KinematicBody2D", +"class": "Minion", +"language": "GDScript", +"path": "res://Overlap/AI/AI_Minion.gd" +}, { "base": "Hero", "class": "Player", "language": "GDScript", @@ -48,6 +53,7 @@ _global_script_class_icons={ "Boss": "", "DialougeBox": "", "Hero": "", +"Minion": "", "Player": "", "SlimeBoss": "", "TitleSceenButton": "", From 69e9e8eba2e8a93b5d4ca9bd4cf17a590bb93d07 Mon Sep 17 00:00:00 2001 From: Jonas Mucke Date: Mon, 20 Apr 2020 13:28:08 +0200 Subject: [PATCH 4/4] changed dependencies --- src/Maps/Grid.gd | 6 +++--- src/Objects/Barrel/Barrel.gd | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Maps/Grid.gd b/src/Maps/Grid.gd index 1963a01..91b19a9 100644 --- a/src/Maps/Grid.gd +++ b/src/Maps/Grid.gd @@ -38,7 +38,7 @@ func _reset_grids(): func _ready(): - var walls = get_tree().current_scene.get_child(1) + var walls = get_tree().current_scene.get_node("../FloorTileMap") offset = walls.global_position #todo put in grid_lul for x in range(14): @@ -117,9 +117,9 @@ func get_nearest(position, kind): func _update_grid(): _reset_grids() - var world = get_tree().current_scene.get_child(2) + var world = get_tree().current_scene.get_node("../YSort") for node in world.get_children(): - var node_kind = node.get_child(0) + var node_kind = node.get_node("Kind") var grid_corrds = _pixel_to_grid_coords(node.global_position) if (_is_in_grid(grid_corrds)): if(node_kind.general != Kind.FIELD and node_kind.general != Kind.WALL): diff --git a/src/Objects/Barrel/Barrel.gd b/src/Objects/Barrel/Barrel.gd index 9aae4a5..0bd2e38 100644 --- a/src/Objects/Barrel/Barrel.gd +++ b/src/Objects/Barrel/Barrel.gd @@ -21,7 +21,7 @@ func _on_Hurtbox_area_entered(area): var Hearts = load("res://Objects/Heart/Heart.tscn") #index of ysort - var world = get_tree().current_scene.get_child(2) + var world = get_tree().current_scene.get_node("YSort") if(randf()