mirror of
https://github.com/creyD/ludum_dare_46.git
synced 2026-06-11 21:22:22 +02:00
Merge branch 'dev' into dev-gameplay
This commit is contained in:
21
README.md
21
README.md
@@ -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
|
||||
|
||||
- `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-X` - Specific features for the game - Merged to `dev`
|
||||
- `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.
|
||||
|
||||
@@ -20,7 +20,7 @@ radius = 18.0
|
||||
height = 18.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=2]
|
||||
radius = 18.0
|
||||
radius = 20.0
|
||||
height = 18.0
|
||||
|
||||
[sub_resource type="CircleShape2D" id=3]
|
||||
@@ -448,7 +448,7 @@ states/move/position = Vector2( 143, 70 )
|
||||
|
||||
[node name="SlimeBoss" type="KinematicBody2D"]
|
||||
collision_layer = 4
|
||||
collision_mask = 3
|
||||
collision_mask = 131
|
||||
script = ExtResource( 4 )
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
@@ -491,9 +491,11 @@ collision_layer = 4
|
||||
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 )
|
||||
|
||||
217
src/Maps/Grid.gd
217
src/Maps/Grid.gd
@@ -1,32 +1,104 @@
|
||||
extends Node
|
||||
|
||||
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 prio_grid : Array = []
|
||||
var used_grid : Array = []
|
||||
var time_passed := 0.0
|
||||
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):
|
||||
var stri = ""
|
||||
for x in range(14):
|
||||
stri += str(object_grid[x][y]) + " "
|
||||
print(stri)
|
||||
print()
|
||||
|
||||
|
||||
func _draw_prio_grid():
|
||||
for y in range(7):
|
||||
var stri = ""
|
||||
for x in range(14):
|
||||
stri += str(prio_grid[x][y]) + " "
|
||||
print(stri)
|
||||
print()
|
||||
|
||||
if object_grid[x][y][0] == Kind.FIELD:
|
||||
walkableCells.push_back(Vector2(x,y))
|
||||
var Index = _point_coors(Vector2(x,y))
|
||||
aStar_node.add_point(Index, Vector3(x,y,0.0))
|
||||
|
||||
#add points straight
|
||||
for point in walkableCells:
|
||||
var point_index = _point_coors(point)
|
||||
|
||||
var points_relative_str = PoolVector2Array([
|
||||
Vector2(point.x + 1, point.y),
|
||||
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():
|
||||
for x in range(14):
|
||||
@@ -37,32 +109,6 @@ func _reset_grids():
|
||||
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):
|
||||
for i in range(table.size()):
|
||||
table[i]=0
|
||||
@@ -82,19 +128,6 @@ func _pixel_to_grid_coords(pixel : Vector2) -> Vector2:
|
||||
new_coords.y = floor((pixel.y-offset.y) / 32.0)
|
||||
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):
|
||||
var list = []
|
||||
for x in range(14):
|
||||
@@ -114,6 +147,23 @@ func get_nearest(position, kind):
|
||||
mini = i
|
||||
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():
|
||||
_reset_grids()
|
||||
@@ -121,14 +171,65 @@ func _update_grid():
|
||||
for node in world.get_children():
|
||||
var node_kind = node.get_node("Kind")
|
||||
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):
|
||||
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)
|
||||
|
||||
|
||||
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):
|
||||
if(time_passed > refresh_rate):
|
||||
time_passed -= refresh_rate
|
||||
_update_grid()
|
||||
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
|
||||
|
||||
@@ -45,7 +45,7 @@ shape = SubResource( 2 )
|
||||
|
||||
[node name="Hitbox" parent="." instance=ExtResource( 4 )]
|
||||
collision_layer = 16
|
||||
damage = -0.5
|
||||
damage = -1.5
|
||||
|
||||
[node name="CollisionShape2D" parent="Hitbox" index="0"]
|
||||
position = Vector2( 0, -2 )
|
||||
|
||||
@@ -2,10 +2,10 @@ extends KinematicBody2D
|
||||
|
||||
class_name Hero
|
||||
|
||||
const PrioQueue = preload("prio_queue.gd") # Relative path
|
||||
const Grid = preload("res://Maps/Grid.gd")
|
||||
|
||||
var grid
|
||||
var lock = Mutex.new()
|
||||
|
||||
enum{
|
||||
STEP,
|
||||
@@ -33,9 +33,15 @@ var actionFieldUsed = false
|
||||
|
||||
var areaRefList = []
|
||||
|
||||
var threadTime = 0.6
|
||||
var threadTime = 0.4
|
||||
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
|
||||
func calcTotalPrio():
|
||||
var sum = 0
|
||||
@@ -67,10 +73,10 @@ func calcPrioTable():
|
||||
i += 1
|
||||
|
||||
return table
|
||||
#14+7 0.999
|
||||
|
||||
#updates heart and bonfire prio
|
||||
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 hearts = prioVal
|
||||
if(hearts < 0):
|
||||
@@ -88,151 +94,27 @@ func calcEnemyKind():
|
||||
return i
|
||||
|
||||
#returns a move
|
||||
func getMoveDescription(myPosition : Vector2, targetPositions):
|
||||
return AStar(myPosition, targetPositions)
|
||||
|
||||
|
||||
func getCost(field):
|
||||
var cost = 0
|
||||
for i in grid.object_grid[field.x][field.y]:
|
||||
match i:
|
||||
Grid.Kind.DAMAGE:
|
||||
cost += 100
|
||||
Grid.Kind.SLOW:
|
||||
cost += 1
|
||||
return cost
|
||||
func getMoveDescription(myPosition : Vector2, targetPositions : Vector2):
|
||||
grid.path_start_position = myPosition
|
||||
grid.path_end_position = targetPositions
|
||||
grid.recalculate_path()
|
||||
if(grid._point_path.size()<=1):
|
||||
return [NOTHING, [0,0]]
|
||||
var to = grid._point_path[1]
|
||||
var from = grid._point_path[0]
|
||||
var p1 = pow(to[0]-from[0],2)
|
||||
var p2 = pow(to[1]-from[1],2)
|
||||
|
||||
#return an heurestic of distance
|
||||
# curr - current position
|
||||
# targ - a target position
|
||||
func h_fn(curr, target):
|
||||
return 0
|
||||
|
||||
# currCost - currentCost
|
||||
# target - position of the field to move to
|
||||
func g_fn(currCost, target):
|
||||
return currCost + getCost(target)
|
||||
var norm = sqrt(p1+p2)
|
||||
var move = STEP
|
||||
if(norm > 1.0 && p1 != p2):
|
||||
move = ROLL
|
||||
return [move, grid._point_path[1]]
|
||||
|
||||
# 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():
|
||||
var currentPosition = grid._pixel_to_grid_coords(global_position)
|
||||
|
||||
var enemyKind
|
||||
|
||||
numbers = grid.countTargets(numbers)
|
||||
@@ -240,21 +122,17 @@ func movement_calulcaotr():
|
||||
enemyKind = calcEnemyKind()
|
||||
actionKind = enemyKind
|
||||
actionFieldUsed = true
|
||||
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
|
||||
return
|
||||
else:
|
||||
enemyKind = actionKind
|
||||
|
||||
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
|
||||
return
|
||||
|
||||
var targetField = grid.get_nearest(currentPosition, enemyKind)
|
||||
if(targetField==[-1,-1]):
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
var MoveAdvice = getMoveDescription(currentPosition, targetField)
|
||||
grid.reset_history()
|
||||
return getMoveDescription(currentPosition, Vector2(targetField[0], targetField[1]))
|
||||
|
||||
return MoveAdvice
|
||||
|
||||
func is_hittable():
|
||||
var length = areaRefList.size()
|
||||
@@ -267,34 +145,29 @@ func hit_or_miss(target, current, delta):
|
||||
|
||||
func movement_decider_ai(target, kindOfStep, delta):
|
||||
var currentPosition = grid._pixel_to_grid_coords(global_position)
|
||||
|
||||
hitDelta -= hitTreshhold
|
||||
var currentPixel = global_position
|
||||
var hitPixelTarget = is_hittable()
|
||||
|
||||
if hitPixelTarget!=null:
|
||||
if hitPixelTarget!=null && randf()<0.5:
|
||||
hit_or_miss(hitPixelTarget, currentPixel, delta*4)
|
||||
|
||||
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(kindOfStep==ROLL):
|
||||
roll(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
|
||||
targetFieldCur = target
|
||||
targetFieldUsed = true
|
||||
|
||||
targetFieldCur = target
|
||||
targetFieldUsed = true
|
||||
|
||||
ExecutionState = EXECUTING
|
||||
|
||||
|
||||
|
||||
func movement_execution(delta):
|
||||
var currentPixel = global_position
|
||||
var hitPixelTarget = is_hittable()
|
||||
|
||||
if hitPixelTarget!=null:
|
||||
hit_or_miss(hitPixelTarget, currentPixel, delta*4)
|
||||
return
|
||||
|
||||
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))
|
||||
@@ -321,7 +194,8 @@ func reset_exeution_state(delta):
|
||||
|
||||
|
||||
|
||||
func makeMove(delta):
|
||||
func makeMove(delta):
|
||||
lock.lock()
|
||||
if ExecutionState == AI_MOVE:
|
||||
threadDelta = 0
|
||||
var MoveAdvice = movement_calulcaotr()
|
||||
@@ -330,10 +204,10 @@ func makeMove(delta):
|
||||
var target = MoveAdvice[1]
|
||||
movement_decider_ai(target, MoveAdvice[0], delta)
|
||||
|
||||
elif ExecutionState == EXECUTING:
|
||||
if ExecutionState == EXECUTING:
|
||||
movement_execution(delta)
|
||||
reset_exeution_state(delta)
|
||||
|
||||
lock.unlock()
|
||||
|
||||
# API Interface for ai_hero -> methods are handled in player.gd
|
||||
func attac(direction, delta):
|
||||
|
||||
@@ -2,10 +2,10 @@ extends KinematicBody2D
|
||||
|
||||
class_name Minion
|
||||
|
||||
const PrioQueue = preload("prio_queue.gd") # Relative path
|
||||
const Grid = preload("res://Maps/Grid.gd")
|
||||
|
||||
var grid
|
||||
var lock = Mutex.new()
|
||||
|
||||
enum{
|
||||
STEP,
|
||||
@@ -21,8 +21,7 @@ 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 prios = [0,7,0,0,0,0,0,0,3,0]
|
||||
|
||||
var targetFieldCur = [0,0]
|
||||
var targetFieldUsed = false
|
||||
@@ -30,9 +29,17 @@ var targetFieldUsed = false
|
||||
var actionKind = Grid.Kind.TERMINAL_SYMBOL
|
||||
var actionFieldUsed = false
|
||||
|
||||
var areaRefList = []
|
||||
|
||||
var threadTime = 0.4
|
||||
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
|
||||
func calcTotalPrio():
|
||||
var sum = 0
|
||||
@@ -64,11 +71,6 @@ func calcPrioTable():
|
||||
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():
|
||||
@@ -80,146 +82,53 @@ func calcEnemyKind():
|
||||
return i
|
||||
|
||||
#returns a move
|
||||
func getMoveDescription(myPosition : Vector2, targetPositions):
|
||||
return AStar(myPosition, targetPositions)
|
||||
|
||||
|
||||
func getCost(field):
|
||||
return 0
|
||||
func getMoveDescription(myPosition : Vector2, targetPositions : Vector2):
|
||||
grid.path_start_position = myPosition
|
||||
grid.path_end_position = targetPositions
|
||||
grid.recalculate_path()
|
||||
if(grid._point_path.size()<=1):
|
||||
return [NOTHING, [0,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)
|
||||
var move = STEP
|
||||
return [move, grid._point_path[1]]
|
||||
|
||||
# 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):
|
||||
|
||||
numbers = grid.countTargets(numbers)
|
||||
if(actionKind == grid.Kind.TERMINAL_SYMBOL || numbers[actionKind]==0 || actionFieldUsed==false):
|
||||
enemyKind = calcEnemyKind()
|
||||
actionKind = enemyKind
|
||||
actionFieldUsed = true
|
||||
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
|
||||
return
|
||||
else:
|
||||
enemyKind = actionKind
|
||||
|
||||
if(enemyKind==Grid.Kind.TERMINAL_SYMBOL):
|
||||
return
|
||||
|
||||
var targetField = grid.get_nearest(currentPosition, enemyKind)
|
||||
if(targetField==[-1,-1]):
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
var MoveAdvice = getMoveDescription(currentPosition, targetField)
|
||||
grid.reset_history()
|
||||
|
||||
return MoveAdvice
|
||||
|
||||
return getMoveDescription(currentPosition, Vector2(targetField[0], targetField[1]))
|
||||
|
||||
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
|
||||
|
||||
|
||||
run(Vector2(target[0]-currentPosition[0], target[1]-currentPosition[1]), delta*4)
|
||||
targetFieldCur = target
|
||||
ai_movement_state = STEP
|
||||
|
||||
targetFieldCur = target
|
||||
targetFieldUsed = true
|
||||
|
||||
ExecutionState = EXECUTING
|
||||
|
||||
|
||||
|
||||
func movement_execution(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))
|
||||
@@ -243,7 +152,8 @@ func reset_exeution_state(delta):
|
||||
|
||||
|
||||
|
||||
func makeMove(delta):
|
||||
func makeMove(delta):
|
||||
lock.lock()
|
||||
if ExecutionState == AI_MOVE:
|
||||
threadDelta = 0
|
||||
var MoveAdvice = movement_calulcaotr()
|
||||
@@ -252,10 +162,10 @@ func makeMove(delta):
|
||||
var target = MoveAdvice[1]
|
||||
movement_decider_ai(target, MoveAdvice[0], delta)
|
||||
|
||||
elif ExecutionState == EXECUTING:
|
||||
if ExecutionState == EXECUTING:
|
||||
movement_execution(delta)
|
||||
reset_exeution_state(delta)
|
||||
|
||||
lock.unlock()
|
||||
|
||||
# API Interface for ai_hero -> methods are handled in player.gd
|
||||
|
||||
|
||||
@@ -150,24 +150,13 @@ func movement_hit():
|
||||
func hit_finished():
|
||||
grid._update_grid()
|
||||
movementState = moveState.IDLE
|
||||
ai_movement_state = STEP
|
||||
ExecutionState = EXECUTING
|
||||
ExecutionState = AI_MOVE
|
||||
actionFieldUsed = false
|
||||
|
||||
|
||||
func movement_roll():
|
||||
velocity = rollvector * ROLL_SPEED
|
||||
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():
|
||||
|
||||
@@ -632,8 +632,11 @@ font_data = ExtResource( 6 )
|
||||
scale = Vector2( 2, 2 )
|
||||
collision_mask = 14
|
||||
script = ExtResource( 1 )
|
||||
debug = null
|
||||
ROLL_SPEED = 120
|
||||
FRICTION = 270
|
||||
ACCELERATION = null
|
||||
title_scene = null
|
||||
|
||||
[node name="Kind" parent="." instance=ExtResource( 7 )]
|
||||
general = 4
|
||||
|
||||
@@ -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]
|
||||
@@ -23,7 +23,8 @@ HeroTemplate = ExtResource( 1 )
|
||||
|
||||
[node name="Background" parent="." instance=ExtResource( 7 )]
|
||||
pause_mode = 1
|
||||
frame = 36
|
||||
frame = 20
|
||||
playing = false
|
||||
|
||||
[node name="FloorTileMap" type="TileMap" parent="."]
|
||||
pause_mode = 1
|
||||
@@ -44,6 +45,9 @@ position = Vector2( 379.618, 131.478 )
|
||||
[node name="SlimeBoss" parent="YSort" instance=ExtResource( 8 )]
|
||||
position = Vector2( 104, 80 )
|
||||
|
||||
[node name="Minion" parent="YSort" instance=ExtResource( 9 )]
|
||||
position = Vector2( 24, 184 )
|
||||
|
||||
[node name="Grid" parent="." instance=ExtResource( 18 )]
|
||||
pause_mode = 1
|
||||
|
||||
|
||||
BIN
src/icon.ico
Normal file
BIN
src/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
src/icon.png
BIN
src/icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 551 B |
Reference in New Issue
Block a user