Merge branch 'dev' into dev-boss-continuation

This commit is contained in:
panorb
2020-04-20 21:49:48 +02:00
committed by GitHub
11 changed files with 271 additions and 379 deletions

View File

@@ -1,16 +1,25 @@
# WORKING TITLE # Bosskeeper - Keep the boss alive!
## Summary ## Story
Short summary of the game and gameplay. You start the game as a main character of any old video game and meet the slime boss - pretty much the first thing you encounter anywhere. But the boss is weak and easily defeated and therefore nobody even took the time to kill it properly. In this moment you decide that your days as a hero are over and that you would love nothing more than to help this boss to stay alive as long as possible.
In this game you have cards to help the angry slime boss to survive. Each time a marvelous hero comes by, you get the chance to place traps, walls, fields of slime and valuable barrels the hero just can't resist to look into. But watch out: if the slime boss dies, you are defeated too.
Have fun playing ~
## Context
This is a minigame developed by a team of 8 people for the Ludum Dare No. 46 in 04/2020 over the course of 3 days. The team members consisted of @panorb, @Sonaion, @Streamfire, @DerAnonymos, @Mienek, Leo (for all major assets), Markus (for sounds) and @creyD. It is written in the Godot framework and a playable version can be downloaded on the release page of this repo.
## Branching ## Branching
- `master` - Current state of the game - `master` - Current state of the game, latest major release
- `dev` - Next feature update state of the game - Merged to `master` - `dev` - Next feature update state of the game - Merged to `master`
- `dev-X` - Specific features for the game - Merged to `dev` - `dev-X` - Specific features for the game - Merged to `dev`
- `hotfix-X` - Bugfixes that need to be pushed to all branches - `hotfix-X` - Bugfixes that need to be pushed to all branches
## Context
Ludum Dare whatever ## Bugs
You may report bugs [here](https://github.com/creyD/ludum_dare_46/issues/new) but please don't expect us to fix them in a timely manner.

View File

@@ -31,6 +31,7 @@ height = 50.0
radius = 13.0 radius = 13.0
height = 30.0 height = 30.0
[sub_resource type="CapsuleShape2D" id=3] [sub_resource type="CapsuleShape2D" id=3]
radius = 20.0 radius = 20.0
height = 30.0 height = 30.0
@@ -1013,9 +1014,11 @@ position = Vector2( 0, -5 )
rotation = 1.5708 rotation = 1.5708
shape = SubResource( 2 ) shape = SubResource( 2 )
[node name="Hurtbox" parent="." instance=ExtResource( 1 )] [node name="Hurtbox" parent="." groups=[
"HittableByPlayer",
] instance=ExtResource( 1 )]
collision_layer = 4 collision_layer = 4
collision_mask = 0 collision_mask = 128
[node name="CollisionShape2D" parent="Hurtbox" index="0"] [node name="CollisionShape2D" parent="Hurtbox" index="0"]
rotation = 1.5708 rotation = 1.5708

View File

@@ -1,32 +1,104 @@
extends Node extends Node
const Kind = preload("res://Overlap/Kind.gd") # Relative path const Kind = preload("res://Overlap/Kind.gd") # Relative path
onready var aStar_node = AStar.new()
var path_start_position : Vector2= Vector2() setget _set_path_start_position
var path_end_position : Vector2 = Vector2() setget _set_path_end_position
var obstacles = []
var _point_path = []
var _half_cell_size = Vector2()
var object_grid : Array = [] var object_grid : Array = []
var prio_grid : Array = [] var prio_grid : Array = []
var used_grid : Array = []
var time_passed := 0.0 var time_passed := 0.0
var offset var offset
export(float, 0, 42.0) var refresh_rate = 0.0 export(float, 0, 42.0) var refresh_rate = 0.4
func _point_coors(point : Vector2):
return 14*point.y+point.x
func _ready():
var walls = get_tree().current_scene.get_node("FloorTileMap")
offset = walls.global_position
func _draw_object_grid(): for x in range(14):
object_grid.push_back([])
prio_grid.push_back([])
for y in range(7):
object_grid[x].push_back([Kind.FIELD])
prio_grid[x].push_back([Kind.TERMINAL_SYMBOL])
for tile in walls.get_used_cells():
if(is_in_coord(tile)):
object_grid[tile.x][tile.y][0] = Kind.WALL
obstacles.push_back(Vector2(tile.x, tile.y))
var walkableCells = []
for y in range(7): for y in range(7):
var stri = ""
for x in range(14): for x in range(14):
stri += str(object_grid[x][y]) + " " if object_grid[x][y][0] == Kind.FIELD:
print(stri) walkableCells.push_back(Vector2(x,y))
print() var Index = _point_coors(Vector2(x,y))
aStar_node.add_point(Index, Vector3(x,y,0.0))
func _draw_prio_grid(): #add points straight
for y in range(7): for point in walkableCells:
var stri = "" var point_index = _point_coors(point)
for x in range(14):
stri += str(prio_grid[x][y]) + " " var points_relative_str = PoolVector2Array([
print(stri) Vector2(point.x + 1, point.y),
print() Vector2(point.x - 1, point.y),
Vector2(point.x , point.y + 1),
Vector2(point.x , point.y - 1)
])
for point_rel in points_relative_str:
var point_relative_index = _point_coors(point_rel)
if point_rel == point or not is_in_coord(point_rel):
continue
if not aStar_node.has_point(point_relative_index):
continue
aStar_node.connect_points(point_index, point_relative_index, true)
#diagonal
for point in walkableCells:
var point_index = _point_coors(point)
var points_relative_dia = PoolVector2Array([
Vector2(point.x + 1, point.y + 1), Vector2(point.x, point.y + 1), Vector2(point.x + 1, point.y),
Vector2(point.x - 1, point.y + 1), Vector2(point.x, point.y + 1), Vector2(point.x - 1, point.y),
Vector2(point.x + 1, point.y - 1), Vector2(point.x, point.y - 1), Vector2(point.x + 1, point.y),
Vector2(point.x - 1, point.y - 1), Vector2(point.x, point.y - 1), Vector2(point.x - 1, point.y)
])
for i in range(points_relative_dia.size()/3):
var p_targ = points_relative_dia[i*3]
var p_ch1 = points_relative_dia[i*3+1]
var p_ch2 = points_relative_dia[i*3+2]
var p_targ_c = _point_coors(p_targ)
var p_ch1_c = _point_coors(p_targ)
var p_ch2_c = _point_coors(p_targ)
if p_targ == point or not is_in_coord(p_targ) and not aStar_node.has_point(p_targ_c):
continue
if p_ch1 == point or not is_in_coord(p_ch1) and not aStar_node.has_point(p_ch1_c):
continue
if p_ch2 == point or not is_in_coord(p_ch2) and not aStar_node.has_point(p_ch2_c):
continue
aStar_node.connect_points(point_index, p_targ_c, true)
func recalculate_path():
_point_path = []
var start_index = _point_coors(path_start_position)
var end_index = _point_coors(path_end_position)
_point_path = aStar_node.get_point_path(start_index, end_index)
func _reset_grids(): func _reset_grids():
for x in range(14): for x in range(14):
@@ -37,33 +109,6 @@ func _reset_grids():
prio_grid[x][y].pop_back() prio_grid[x][y].pop_back()
func _ready():
var walls = get_tree().current_scene.get_node("FloorTileMap")
offset = walls.global_position
#todo put in grid_lul
for x in range(14):
object_grid.push_back([])
prio_grid.push_back([])
used_grid.push_back([])
for y in range(7):
object_grid[x].push_back([Kind.FIELD])
prio_grid[x].push_back([Kind.TERMINAL_SYMBOL])
used_grid[x].push_back(false)
for tile in walls.get_used_cells():
if(_is_in_grid(tile)):
object_grid[tile.x][tile.y][0] = Kind.WALL
_update_grid()
func reset_history():
for x in range(14):
for y in range(7):
used_grid[x][y] = false
func countTargets(table): func countTargets(table):
for i in range(table.size()): for i in range(table.size()):
table[i]=0 table[i]=0
@@ -83,19 +128,6 @@ func _pixel_to_grid_coords(pixel : Vector2) -> Vector2:
new_coords.y = floor((pixel.y-offset.y) / 32.0) new_coords.y = floor((pixel.y-offset.y) / 32.0)
return new_coords return new_coords
func _is_in_grid(grid_coords : Vector2) -> bool:
if(grid_coords.x < 0):
return false
if(grid_coords.x > 13):
return false
if(grid_coords.y < 0):
return false
if(grid_coords.y > 6):
return false
return true
func get_nearest(position, kind): func get_nearest(position, kind):
var list = [] var list = []
for x in range(14): for x in range(14):
@@ -115,6 +147,23 @@ func get_nearest(position, kind):
mini = i mini = i
return list[mini] return list[mini]
func get_fields_around(point):
var points_relative_str = PoolVector2Array([
Vector2(point.x + 1, point.y + 1),
Vector2(point.x - 1, point.y + 1),
Vector2(point.x + 1, point.y - 1),
Vector2(point.x - 1, point.y - 1)
])
var point_list = []
for point_rel in points_relative_str:
var point_relative_index = _point_coors(point_rel)
if point_rel == point or not is_in_coord(point_rel):
continue
if not aStar_node.has_point(point_relative_index):
continue
point_list.push_back(point_rel)
return point_list
func _update_grid(): func _update_grid():
_reset_grids() _reset_grids()
@@ -122,14 +171,65 @@ func _update_grid():
for node in world.get_children(): for node in world.get_children():
var node_kind = node.get_node("Kind") var node_kind = node.get_node("Kind")
var grid_corrds = _pixel_to_grid_coords(node.global_position) var grid_corrds = _pixel_to_grid_coords(node.global_position)
if (_is_in_grid(grid_corrds)): if (is_in_coord(grid_corrds)):
if(node_kind.general != Kind.FIELD and node_kind.general != Kind.WALL): if(node_kind.general != Kind.FIELD and node_kind.general != Kind.WALL):
object_grid[grid_corrds.x][grid_corrds.y].push_back(node_kind.general) object_grid[grid_corrds.x][grid_corrds.y].push_back(node_kind.general)
prio_grid[grid_corrds.x][grid_corrds.y].push_back(node_kind.kind) prio_grid[grid_corrds.x][grid_corrds.y].push_back(node_kind.kind)
for y in range(7):
for x in range(14):
var index = _point_coors(Vector2(x,y))
var scale = 1.0
for val in object_grid[x][y]:
match val:
Kind.DAMAGE:
scale += 16
Kind.HEALING:
scale -= 8
Kind.SLOW:
scale += 8
var neighboor_list = get_fields_around(Vector2(x,y))
for neighboor in neighboor_list:
for val in object_grid[neighboor.x][neighboor.y]:
match val:
Kind.DAMAGE:
scale += 8
Kind.HEALING:
scale -= 4
Kind.SLOW:
scale += 4
if(scale<0):
scale = 0
aStar_node.set_point_weight_scale(index, scale)
func _physics_process(delta): func _physics_process(delta):
if(time_passed > refresh_rate): if(time_passed > refresh_rate):
time_passed -= refresh_rate time_passed -= refresh_rate
_update_grid() _update_grid()
time_passed += delta time_passed += delta
func is_in_coord(point):
if point[0]<0 || point[0]>13:
return false
if point[1]<0 || point[1]>6:
return false
return true
func _set_path_start_position(value : Vector2):
if value in obstacles:
return
if not is_in_coord(value):
return
path_start_position = value
func _set_path_end_position(value : Vector2):
if value in obstacles:
return
if not is_in_coord(value):
return
path_end_position = value

View File

@@ -45,7 +45,7 @@ shape = SubResource( 2 )
[node name="Hitbox" parent="." instance=ExtResource( 4 )] [node name="Hitbox" parent="." instance=ExtResource( 4 )]
collision_layer = 16 collision_layer = 16
damage = -0.5 damage = -1.5
[node name="CollisionShape2D" parent="Hitbox" index="0"] [node name="CollisionShape2D" parent="Hitbox" index="0"]
position = Vector2( 0, -2 ) position = Vector2( 0, -2 )

View File

@@ -2,10 +2,10 @@ extends KinematicBody2D
class_name Hero class_name Hero
const PrioQueue = preload("prio_queue.gd") # Relative path
const Grid = preload("res://Maps/Grid.gd") const Grid = preload("res://Maps/Grid.gd")
var grid var grid
var lock = Mutex.new()
enum{ enum{
STEP, STEP,
@@ -33,9 +33,15 @@ var actionFieldUsed = false
var areaRefList = [] var areaRefList = []
var threadTime = 0.6 var threadTime = 0.4
var threadDelta = 0.0 var threadDelta = 0.0
var hitDelta = 0.0
var hitTreshhold = 0.1
var aiDelta = 0.0
var aiTreshhold = 0.4
#calculates the sum of all present prios #calculates the sum of all present prios
func calcTotalPrio(): func calcTotalPrio():
var sum = 0 var sum = 0
@@ -67,10 +73,10 @@ func calcPrioTable():
i += 1 i += 1
return table return table
#14+7 0.999
#updates heart and bonfire prio #updates heart and bonfire prio
func adjustPrio(currentHealth, maxHealth): func adjustPrio(currentHealth, maxHealth):
var prioVal = 10.0 - (float(currentHealth)/float(maxHealth))*10.0 var prioVal = 20.0 - (float(currentHealth)/float(maxHealth))*20.0
var bonfire = prioVal + 1 var bonfire = prioVal + 1
var hearts = prioVal var hearts = prioVal
if(hearts < 0): if(hearts < 0):
@@ -88,151 +94,27 @@ func calcEnemyKind():
return i return i
#returns a move #returns a move
func getMoveDescription(myPosition : Vector2, targetPositions): func getMoveDescription(myPosition : Vector2, targetPositions : Vector2):
return AStar(myPosition, targetPositions) grid.path_start_position = myPosition
grid.path_end_position = targetPositions
grid.recalculate_path()
func getCost(field): if(grid._point_path.size()<=1):
var cost = 0 return [NOTHING, [0,0]]
for i in grid.object_grid[field.x][field.y]: var to = grid._point_path[1]
match i: var from = grid._point_path[0]
Grid.Kind.DAMAGE: var p1 = pow(to[0]-from[0],2)
cost += 100 var p2 = pow(to[1]-from[1],2)
Grid.Kind.SLOW:
cost += 1
return cost
#return an heurestic of distance var norm = sqrt(p1+p2)
# curr - current position var move = STEP
# targ - a target position if(norm > 1.0 && p1 != p2):
func h_fn(curr, target): move = ROLL
return 0 return [move, grid._point_path[1]]
# 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 = true):
var adj := []
#adj.append([STEP, Vector2(0,0)])
var p = currentPosition
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]-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()):
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._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 &&
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])
for i in range(pot_adj_roll.size()):
var next = pot_adj_roll[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._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):
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]),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]),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]),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])
var current_field = 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(): func movement_calulcaotr():
var currentPosition = grid._pixel_to_grid_coords(global_position) var currentPosition = grid._pixel_to_grid_coords(global_position)
var enemyKind var enemyKind
numbers = grid.countTargets(numbers) numbers = grid.countTargets(numbers)
@@ -240,21 +122,17 @@ func movement_calulcaotr():
enemyKind = calcEnemyKind() enemyKind = calcEnemyKind()
actionKind = enemyKind actionKind = enemyKind
actionFieldUsed = true actionFieldUsed = true
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
return
else: else:
enemyKind = actionKind enemyKind = actionKind
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
return
var targetField = grid.get_nearest(currentPosition, enemyKind) var targetField = grid.get_nearest(currentPosition, enemyKind)
if(targetField==[-1,-1]): if(targetField==[-1,-1]):
return return
return getMoveDescription(currentPosition, Vector2(targetField[0], targetField[1]))
var MoveAdvice = getMoveDescription(currentPosition, targetField)
grid.reset_history()
return MoveAdvice
func is_hittable(): func is_hittable():
var length = areaRefList.size() var length = areaRefList.size()
@@ -267,34 +145,29 @@ func hit_or_miss(target, current, delta):
func movement_decider_ai(target, kindOfStep, delta): func movement_decider_ai(target, kindOfStep, delta):
var currentPosition = grid._pixel_to_grid_coords(global_position) var currentPosition = grid._pixel_to_grid_coords(global_position)
hitDelta -= hitTreshhold
var currentPixel = global_position var currentPixel = global_position
var hitPixelTarget = is_hittable() var hitPixelTarget = is_hittable()
if hitPixelTarget!=null: if hitPixelTarget!=null && randf()<0.5:
hit_or_miss(hitPixelTarget, currentPixel, delta*4) hit_or_miss(hitPixelTarget, currentPixel, delta*4)
else: else:
if(kindOfStep==STEP): if(kindOfStep==STEP):
run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
targetFieldCur = target targetFieldCur = target
targetFieldUsed = true
ai_movement_state = STEP ai_movement_state = STEP
elif(kindOfStep==ROLL): elif(kindOfStep==ROLL):
roll(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4) roll(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
targetFieldCur = target
targetFieldUsed = true targetFieldCur = target
targetFieldUsed = true
ExecutionState = EXECUTING ExecutionState = EXECUTING
func movement_execution(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): if(targetFieldUsed):
var cur = grid._pixel_to_grid_coords(global_position) var cur = grid._pixel_to_grid_coords(global_position)
var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2))
@@ -320,7 +193,8 @@ func reset_exeution_state(delta):
func makeMove(delta): func makeMove(delta):
lock.lock()
if ExecutionState == AI_MOVE: if ExecutionState == AI_MOVE:
threadDelta = 0 threadDelta = 0
var MoveAdvice = movement_calulcaotr() var MoveAdvice = movement_calulcaotr()
@@ -329,10 +203,10 @@ func makeMove(delta):
var target = MoveAdvice[1] var target = MoveAdvice[1]
movement_decider_ai(target, MoveAdvice[0], delta) movement_decider_ai(target, MoveAdvice[0], delta)
elif ExecutionState == EXECUTING: if ExecutionState == EXECUTING:
movement_execution(delta) movement_execution(delta)
reset_exeution_state(delta) reset_exeution_state(delta)
lock.unlock()
# API Interface for ai_hero -> methods are handled in player.gd # API Interface for ai_hero -> methods are handled in player.gd
func attac(direction, delta): func attac(direction, delta):

View File

@@ -2,10 +2,10 @@ extends KinematicBody2D
class_name Minion class_name Minion
const PrioQueue = preload("prio_queue.gd") # Relative path
const Grid = preload("res://Maps/Grid.gd") const Grid = preload("res://Maps/Grid.gd")
var grid var grid
var lock = Mutex.new()
enum{ enum{
STEP, STEP,
@@ -21,8 +21,7 @@ var ExecutionState = AI_MOVE
var ai_movement_state = NOTHING var ai_movement_state = NOTHING
var numbers = [0,0,0,0,0,0,0,0,0,0] 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 prios = [0,7,0,0,0,0,0,0,3,0]
var targetFieldCur = [0,0] var targetFieldCur = [0,0]
var targetFieldUsed = false var targetFieldUsed = false
@@ -30,9 +29,17 @@ var targetFieldUsed = false
var actionKind = Grid.Kind.TERMINAL_SYMBOL var actionKind = Grid.Kind.TERMINAL_SYMBOL
var actionFieldUsed = false var actionFieldUsed = false
var areaRefList = []
var threadTime = 0.4 var threadTime = 0.4
var threadDelta = 0.0 var threadDelta = 0.0
var hitDelta = 0.0
var hitTreshhold = 0.1
var aiDelta = 0.0
var aiTreshhold = 0.4
#calculates the sum of all present prios #calculates the sum of all present prios
func calcTotalPrio(): func calcTotalPrio():
var sum = 0 var sum = 0
@@ -64,11 +71,6 @@ func calcPrioTable():
i += 1 i += 1
return table return table
#14+7 0.999
#updates heart and bonfire prio
func adjustPrio(currentHealth, maxHealth):
return
#return the enemie which will be attacked #return the enemie which will be attacked
func calcEnemyKind(): func calcEnemyKind():
@@ -80,146 +82,53 @@ func calcEnemyKind():
return i return i
#returns a move #returns a move
func getMoveDescription(myPosition : Vector2, targetPositions): func getMoveDescription(myPosition : Vector2, targetPositions : Vector2):
return AStar(myPosition, targetPositions) grid.path_start_position = myPosition
grid.path_end_position = targetPositions
grid.recalculate_path()
func getCost(field): if(grid._point_path.size()<=1):
return 0 return [NOTHING, [0,0]]
#return an heurestic of distance var move = STEP
# curr - current position return [move, grid._point_path[1]]
# 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(): func movement_calulcaotr():
var currentPosition = grid._pixel_to_grid_coords(global_position) var currentPosition = grid._pixel_to_grid_coords(global_position)
var enemyKind var enemyKind
if(actionFieldUsed==false):
numbers = grid.countTargets(numbers)
if(actionKind == grid.Kind.TERMINAL_SYMBOL || numbers[actionKind]==0 || actionFieldUsed==false):
enemyKind = calcEnemyKind() enemyKind = calcEnemyKind()
actionKind = enemyKind actionKind = enemyKind
actionFieldUsed = true actionFieldUsed = true
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
return
else: else:
enemyKind = actionKind enemyKind = actionKind
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
return
var targetField = grid.get_nearest(currentPosition, enemyKind) var targetField = grid.get_nearest(currentPosition, enemyKind)
if(targetField==[-1,-1]): if(targetField==[-1,-1]):
return return
return getMoveDescription(currentPosition, Vector2(targetField[0], targetField[1]))
var MoveAdvice = getMoveDescription(currentPosition, targetField)
grid.reset_history()
return MoveAdvice
func movement_decider_ai(target, kindOfStep, delta): func movement_decider_ai(target, kindOfStep, delta):
var currentPosition = grid._pixel_to_grid_coords(global_position) var currentPosition = grid._pixel_to_grid_coords(global_position)
var field_of_movement = target
var currentPixel = global_position run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
targetFieldCur = target
if(kindOfStep==STEP): ai_movement_state = STEP
run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
targetFieldCur = target targetFieldCur = target
targetFieldUsed = true targetFieldUsed = true
ai_movement_state = STEP
ExecutionState = EXECUTING ExecutionState = EXECUTING
func movement_execution(delta): func movement_execution(delta):
if(targetFieldUsed): if(targetFieldUsed):
var cur = grid._pixel_to_grid_coords(global_position) var cur = grid._pixel_to_grid_coords(global_position)
var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2)) var distance = sqrt(pow(cur[0]-targetFieldCur[0],2)+ pow(cur[1]-targetFieldCur[1],2))
@@ -243,7 +152,8 @@ func reset_exeution_state(delta):
func makeMove(delta): func makeMove(delta):
lock.lock()
if ExecutionState == AI_MOVE: if ExecutionState == AI_MOVE:
threadDelta = 0 threadDelta = 0
var MoveAdvice = movement_calulcaotr() var MoveAdvice = movement_calulcaotr()
@@ -252,10 +162,10 @@ func makeMove(delta):
var target = MoveAdvice[1] var target = MoveAdvice[1]
movement_decider_ai(target, MoveAdvice[0], delta) movement_decider_ai(target, MoveAdvice[0], delta)
elif ExecutionState == EXECUTING: if ExecutionState == EXECUTING:
movement_execution(delta) movement_execution(delta)
reset_exeution_state(delta) reset_exeution_state(delta)
lock.unlock()
# API Interface for ai_hero -> methods are handled in player.gd # API Interface for ai_hero -> methods are handled in player.gd

View File

@@ -150,24 +150,13 @@ func movement_hit():
func hit_finished(): func hit_finished():
grid._update_grid() grid._update_grid()
movementState = moveState.IDLE movementState = moveState.IDLE
ai_movement_state = STEP ExecutionState = AI_MOVE
ExecutionState = EXECUTING
actionFieldUsed = false actionFieldUsed = false
func movement_roll(): func movement_roll():
velocity = rollvector * ROLL_SPEED velocity = rollvector * ROLL_SPEED
animation_state.change_state("roll") animation_state.change_state("roll")
"""
# Roll.gd
func enter():
owner.animation_state.travel("roll")
func update():
owner.velocity = rollvector * ROLL_SPEED
"""
ExecutionState = EXECUTING
func roll_finished(): func roll_finished():

View File

@@ -631,8 +631,11 @@ font_data = ExtResource( 6 )
]] ]]
collision_mask = 14 collision_mask = 14
script = ExtResource( 1 ) script = ExtResource( 1 )
debug = null
ROLL_SPEED = 120 ROLL_SPEED = 120
FRICTION = 270 FRICTION = 270
ACCELERATION = null
title_scene = null
[node name="Kind" parent="." instance=ExtResource( 7 )] [node name="Kind" parent="." instance=ExtResource( 7 )]
general = 4 general = 4
@@ -736,7 +739,7 @@ __meta__ = {
} }
[node name="Stats" parent="." instance=ExtResource( 5 )] [node name="Stats" parent="." instance=ExtResource( 5 )]
max_health = 999999 max_health = 20
[node name="AnimationStates" type="Node" parent="."] [node name="AnimationStates" type="Node" parent="."]
script = ExtResource( 15 ) script = ExtResource( 15 )

View File

@@ -9,6 +9,7 @@
[ext_resource path="res://Maps/Background/Background.tscn" type="PackedScene" id=7] [ext_resource path="res://Maps/Background/Background.tscn" type="PackedScene" id=7]
[ext_resource path="res://Boss/SlimeBoss/SlimeBoss.tscn" type="PackedScene" id=8] [ext_resource path="res://Boss/SlimeBoss/SlimeBoss.tscn" type="PackedScene" id=8]
[ext_resource path="res://Fonts/Harmonic/Harmonic12.tres" type="DynamicFont" id=9] [ext_resource path="res://Fonts/Harmonic/Harmonic12.tres" type="DynamicFont" id=9]
[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/Bonfire/Bonfire.tscn" type="PackedScene" id=10]
[ext_resource path="res://Debug/BossStateDisplay.gd" type="Script" id=11] [ext_resource path="res://Debug/BossStateDisplay.gd" type="Script" id=11]
[ext_resource path="res://Maps/Tilesets/Edge/tileset_edge.png" type="Texture" id=12] [ext_resource path="res://Maps/Tilesets/Edge/tileset_edge.png" type="Texture" id=12]
@@ -241,7 +242,7 @@ region_enabled = true
region_rect = Rect2( 0, 0, 1280, 720 ) region_rect = Rect2( 0, 0, 1280, 720 )
[node name="Background" parent="." instance=ExtResource( 7 )] [node name="Background" parent="." instance=ExtResource( 7 )]
frame = 32 frame = 0
[node name="FloorTileMap" type="TileMap" parent="."] [node name="FloorTileMap" type="TileMap" parent="."]
visible = false visible = false
@@ -267,18 +268,21 @@ tile_data = PoolIntArray( -1, 5, 0, -65536, 3, 0, -65535, 3, 0, -65534, 3, 0, -6
[node name="YSort" type="YSort" parent="."] [node name="YSort" type="YSort" parent="."]
[node name="Bonfire" parent="YSort" instance=ExtResource( 10 )] [node name="Bonfire" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( 265.543, -16 ) position = Vector2( 448, 32 )
[node name="Player" parent="YSort" instance=ExtResource( 1 )] [node name="Player" parent="YSort" instance=ExtResource( 1 )]
position = Vector2( 432, 168 ) position = Vector2( 432, 168 )
scale = Vector2( 2, 2 ) scale = Vector2( 2, 2 )
debug = true debug = true
ROLL_SPEED = 140 ROLL_SPEED = 140
FRICTION = 200 FRICTION = null
[node name="SlimeBoss" parent="YSort" instance=ExtResource( 8 )] [node name="SlimeBoss" parent="YSort" instance=ExtResource( 8 )]
position = Vector2( 240, 120 ) position = Vector2( 240, 120 )
[node name="Minion" parent="YSort" instance=ExtResource( 9 )]
position = Vector2( 24, 184 )
[node name="Grid" parent="." instance=ExtResource( 18 )] [node name="Grid" parent="." instance=ExtResource( 18 )]
[node name="CanvasLayer" type="CanvasLayer" parent="."] [node name="CanvasLayer" type="CanvasLayer" parent="."]

BIN
src/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 551 B