From fc594529287c7b379a8e27355f1c46c3030190b6 Mon Sep 17 00:00:00 2001 From: Jonas Mucke Date: Mon, 20 Apr 2020 00:04:25 +0200 Subject: [PATCH] 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