mirror of
https://github.com/clarkjohn/wizard-chase.git
synced 2026-01-23 02:14:32 +00:00
Add initial code
This commit is contained in:
parent
a27c863d6b
commit
1135a36a9e
257 changed files with 12234 additions and 1 deletions
182
enemy/Enemy.gd
Normal file
182
enemy/Enemy.gd
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
class_name Enemy
|
||||
extends Area2D
|
||||
|
||||
onready var global := $"/root/Global" as Global
|
||||
onready var game := $"/root/Game" as Game
|
||||
onready var dungeon = game.find_node_by_name("Dungeon") as Dungeon
|
||||
onready var player = game.find_node_by_name("Player") as Player
|
||||
|
||||
export var is_debug_path_enable := false
|
||||
|
||||
const ENEMY_COLOR: Color = Color("#000000")
|
||||
|
||||
# init at EnemyAi.gd
|
||||
var wander_direction: Vector2
|
||||
|
||||
var old_pos: Vector2
|
||||
var direction: Vector2
|
||||
|
||||
var timer = null
|
||||
var speed = null
|
||||
|
||||
var wrapped_screen: bool
|
||||
var wrapped_tile := Vector2(0, 0)
|
||||
|
||||
var state
|
||||
|
||||
var last_map_pos_array := []
|
||||
const NUM_MAP_POSITIONS_TO_REMEBER = 2
|
||||
|
||||
var path := []
|
||||
var current_map_pos_in_path := 0
|
||||
|
||||
var is_stuck := false as bool
|
||||
|
||||
enum EnemyStateEnum { IDLE, SEEK, WANDER, OPPOSITE, CLYDE, SEEK_AHEAD, SEEK_BEHIND }
|
||||
var enemy_state_factory
|
||||
|
||||
|
||||
func _init():
|
||||
enemy_state_factory = {
|
||||
EnemyStateEnum.IDLE: IdleState,
|
||||
EnemyStateEnum.SEEK: SeekState,
|
||||
EnemyStateEnum.WANDER: WanderState,
|
||||
EnemyStateEnum.CLYDE: ClydeState,
|
||||
EnemyStateEnum.SEEK_AHEAD: SeekAheadState,
|
||||
EnemyStateEnum.SEEK_BEHIND: SeekBehindState
|
||||
}
|
||||
|
||||
|
||||
func get_state(get_state):
|
||||
return enemy_state_factory.get(get_state)
|
||||
|
||||
|
||||
func _ready():
|
||||
position = dungeon.snap_to_center(position)
|
||||
position.x += dungeon.HALF_CELL_SIZE.x
|
||||
position.y += dungeon.HALF_CELL_SIZE.y
|
||||
|
||||
var current_tile := dungeon.world_to_map(position) as Vector2
|
||||
last_map_pos_array.push_front(current_tile)
|
||||
|
||||
|
||||
func _process(delta: float):
|
||||
if global.state != global.states.ENTERED_MAZE:
|
||||
return
|
||||
|
||||
# pause all enemires if player is dead
|
||||
if !global.is_player_alive:
|
||||
return
|
||||
|
||||
# track position for enemy ai
|
||||
var current_tile := dungeon.world_to_map(position) as Vector2
|
||||
var last_map_pos = last_map_pos_array.front()
|
||||
if last_map_pos == null or last_map_pos != current_tile:
|
||||
last_map_pos_array.push_front(current_tile)
|
||||
last_map_pos_array.resize(NUM_MAP_POSITIONS_TO_REMEBER)
|
||||
|
||||
# prevent enemies from getting stuck in a wrap tile
|
||||
if not wrapped_screen:
|
||||
var post_wrap_pos := dungeon.handle_possible_screen_wrap(position, direction, true) as Vector2
|
||||
if post_wrap_pos != position:
|
||||
wrapped_screen = true
|
||||
wrapped_tile = dungeon.world_to_map(post_wrap_pos)
|
||||
position = post_wrap_pos
|
||||
else:
|
||||
wrapped_screen = false
|
||||
|
||||
# directions
|
||||
if old_pos.x > position.x:
|
||||
$AnimatedSprite.flip_h = true
|
||||
direction = Vector2.LEFT
|
||||
elif old_pos.x < position.x:
|
||||
$AnimatedSprite.flip_h = false
|
||||
direction = Vector2.RIGHT
|
||||
elif old_pos.y < position.y:
|
||||
direction = Vector2.UP
|
||||
elif old_pos.y > position.y:
|
||||
direction = Vector2.DOWN
|
||||
else:
|
||||
direction = Vector2.ZERO
|
||||
|
||||
old_pos = position
|
||||
|
||||
# move
|
||||
if global.state == global.states.ENTERED_MAZE:
|
||||
if state == null:
|
||||
change_state(self, EnemyStateEnum.IDLE, 2)
|
||||
elif is_able_to_move():
|
||||
var pos_to_move = path[0] as Vector2
|
||||
direction = (pos_to_move - position).normalized()
|
||||
var distance = position.distance_to(pos_to_move)
|
||||
if distance > 1:
|
||||
var target_pos = position + (speed * delta * direction)
|
||||
if is_stuck:
|
||||
position = target_pos
|
||||
elif dungeon.is_cell_tile_navigable(dungeon.world_to_map(target_pos)):
|
||||
position = target_pos
|
||||
else:
|
||||
# is stuck on blades, wall, spikes?
|
||||
# TODO fix this, getting stuck in the middle of spikes
|
||||
if dungeon.is_cell_tile_navigable(dungeon.world_to_map(position)):
|
||||
is_stuck = true
|
||||
path = dungeon.getAStarPath(position, dungeon.map_to_world(last_map_pos_array.back()))
|
||||
current_map_pos_in_path = 0
|
||||
pos_to_move = path[0] as Vector2
|
||||
direction = (pos_to_move - position).normalized()
|
||||
position = position + (speed * delta * direction)
|
||||
else:
|
||||
is_stuck = false
|
||||
var obstacle_pos := pos_to_move as Vector2
|
||||
dungeon.disable_astar(obstacle_pos)
|
||||
path = state.get_enemy_path(self, last_map_pos_array.back())
|
||||
current_map_pos_in_path = 0
|
||||
dungeon.enable_astar(obstacle_pos)
|
||||
else:
|
||||
path.remove(0)
|
||||
current_map_pos_in_path += 1
|
||||
else:
|
||||
# Enemy AI
|
||||
is_stuck = false
|
||||
path = state.get_enemy_path(self, last_map_pos_array.back())
|
||||
current_map_pos_in_path = 0
|
||||
|
||||
# only for debug drawing of path in _draw
|
||||
update()
|
||||
|
||||
|
||||
func is_able_to_move():
|
||||
return (
|
||||
path.size() > 0
|
||||
and current_map_pos_in_path < state.MAP_POS_TO_RECHECK_PATH
|
||||
and !wrapped_screen
|
||||
and state.is_able_to_move(self, player)
|
||||
)
|
||||
|
||||
|
||||
func change_state(caller, new_state, wait_time: float):
|
||||
# free old change_state timers
|
||||
for child_node in get_children():
|
||||
if child_node.name == "change_states":
|
||||
child_node.queue_free()
|
||||
|
||||
state = get_state(new_state).new(player, dungeon)
|
||||
timer = Timer.new()
|
||||
self.add_child(timer)
|
||||
timer.set_wait_time(wait_time)
|
||||
timer.name = "change_states"
|
||||
timer.connect("timeout", caller, "change_states")
|
||||
timer.set_one_shot(true)
|
||||
timer.start()
|
||||
|
||||
|
||||
func _draw():
|
||||
if is_debug_path_enable:
|
||||
if state != null and path.size() > 1:
|
||||
for p in path:
|
||||
draw_circle(p - get_global_position(), 4, _get_enemy_color())
|
||||
|
||||
|
||||
# to override
|
||||
func _get_enemy_color() -> Color:
|
||||
return Color.white
|
||||
55
enemy/ai/EnemyAI.gd
Normal file
55
enemy/ai/EnemyAI.gd
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
extends Node2D
|
||||
|
||||
onready var global := get_node("/root/Global")
|
||||
onready var game := $"/root/Game" as Game
|
||||
onready var player = game.find_node_by_name("Player") as Player
|
||||
onready var treasure = game.find_node_by_name("Treasure") as Treasure
|
||||
|
||||
onready var total_coins_in_level := treasure.get_used_cells_by_id(treasure.TILE_COIN).size() as int
|
||||
|
||||
const POSSIBLE_WANDER_DIRECTIONS = [Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT]
|
||||
|
||||
const PERCENTAGE_OF_COINS_LEFT_TO_INCREASE_FIEND_SPEED := .2
|
||||
|
||||
const MAX_ENEMY_SPEED_FACTOR_TO_PLAYER := 1.05
|
||||
const ENEMY_INITIAL_SPEED_FACTOR_TO_PLAYER := .8
|
||||
|
||||
var enemy_speed_increase_per_level
|
||||
var max_enemy_speed
|
||||
var inital_enemy_speed
|
||||
|
||||
|
||||
func _ready():
|
||||
# distribute wander directions; might be more than 4 enemies later on
|
||||
for i in self.get_child_count():
|
||||
self.get_child(i).wander_direction = POSSIBLE_WANDER_DIRECTIONS[i % POSSIBLE_WANDER_DIRECTIONS.size()]
|
||||
|
||||
inital_enemy_speed = self.get_child(0).speed
|
||||
enemy_speed_increase_per_level = (player.speed - inital_enemy_speed) / 10
|
||||
max_enemy_speed = player.speed * MAX_ENEMY_SPEED_FACTOR_TO_PLAYER as float
|
||||
|
||||
|
||||
func _process(_delta) -> void:
|
||||
if (
|
||||
not $EnemyFiend.is_chase_state_enabled
|
||||
and (treasure.get_total_coins_left() < total_coins_in_level * PERCENTAGE_OF_COINS_LEFT_TO_INCREASE_FIEND_SPEED)
|
||||
):
|
||||
$EnemyFiend.enable_chase_state()
|
||||
|
||||
if not $EnemyLizardMan.is_chase_state_enabled and global.current_chest_score_index > 1:
|
||||
$EnemyLizardMan.enable_chase_state()
|
||||
|
||||
if not $EnemySlime.is_chase_state_enabled and global.current_chest_score_index > 2:
|
||||
$EnemySlime.enable_chase_state()
|
||||
|
||||
if not global.is_enemies_speed_adjustment_per_level:
|
||||
global.is_enemies_speed_adjustment_per_level = true
|
||||
|
||||
for i in self.get_child_count():
|
||||
var current_speed = self.get_child(i).speed
|
||||
var speed_increase = (
|
||||
0
|
||||
if global.current_level == 1
|
||||
else enemy_speed_increase_per_level * (global.current_level - 1)
|
||||
)
|
||||
self.get_child(i).speed = clamp(current_speed + speed_increase, 0, max_enemy_speed)
|
||||
17
enemy/ai/EnemyState.gd
Normal file
17
enemy/ai/EnemyState.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class_name EnemyState
|
||||
extends Area2D
|
||||
|
||||
func _init():
|
||||
pass
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
func move(_delta: float, _enemy, _previous_tile: Vector2) -> Vector2:
|
||||
return Vector2(0, 0)
|
||||
|
||||
func is_able_to_move(enemy, player: Player) -> bool:
|
||||
return true
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
return []
|
||||
41
enemy/ai/states/ClydeState.gd
Normal file
41
enemy/ai/states/ClydeState.gd
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Similar to Clyde in pacman
|
||||
class_name ClydeState
|
||||
extends WanderState
|
||||
|
||||
const TILES_AWAY_FROM_PLAYER_TO_BACK_OFF := 5
|
||||
const WANDER_MAP_POS_TO_RECHECK_PATH := 4
|
||||
|
||||
var is_seeking_player: bool = true
|
||||
var distance_to_player_to_change_to_stop: float
|
||||
|
||||
|
||||
# weird child constructor, see https://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/gdscript_basics.html#class-constructor
|
||||
func _init(player, walls).(player, walls):
|
||||
distance_to_player_to_change_to_stop = _walls.get_cell_size().x * TILES_AWAY_FROM_PLAYER_TO_BACK_OFF
|
||||
|
||||
|
||||
func is_able_to_move(enemy, _player: Player) -> bool:
|
||||
var position := enemy.position as Vector2
|
||||
var current_map_pos_in_path := enemy.current_map_pos_in_path as int
|
||||
|
||||
if is_seeking_player and position.distance_to(_player.position) < distance_to_player_to_change_to_stop:
|
||||
return false
|
||||
elif not is_seeking_player and current_map_pos_in_path > WANDER_MAP_POS_TO_RECHECK_PATH:
|
||||
return false
|
||||
else:
|
||||
return true
|
||||
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
var position := enemy.position as Vector2
|
||||
|
||||
if not is_seeking_player:
|
||||
is_seeking_player = true
|
||||
_walls.disable_astar(_walls.map_to_world(previous_tile))
|
||||
var path = _walls.getAStarPath(position, _player.position)
|
||||
_walls.enable_astar(_walls.map_to_world(previous_tile))
|
||||
|
||||
return path
|
||||
else:
|
||||
is_seeking_player = false
|
||||
return get_wander_path(enemy, previous_tile)
|
||||
10
enemy/ai/states/IdleState.gd
Normal file
10
enemy/ai/states/IdleState.gd
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
class_name IdleState
|
||||
extends EnemyState
|
||||
|
||||
|
||||
func _init(player, walls: Dungeon):
|
||||
pass
|
||||
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
return []
|
||||
24
enemy/ai/states/SeekAheadState.gd
Normal file
24
enemy/ai/states/SeekAheadState.gd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
class_name SeekAheadState
|
||||
extends EnemyState
|
||||
|
||||
var _walls: Dungeon
|
||||
var _player: Area2D
|
||||
|
||||
const MAP_POS_TO_RECHECK_PATH := 8
|
||||
const TILES_TO_SEEK_AHEAD_OF_PLAYER = 5
|
||||
|
||||
|
||||
func _init(player, walls: Dungeon):
|
||||
_player = player
|
||||
_walls = walls as Dungeon
|
||||
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
var position := enemy.position as Vector2
|
||||
|
||||
var path := _walls.getAStarPath(position, get_player_future_position())
|
||||
return path
|
||||
|
||||
|
||||
func get_player_future_position() -> Vector2:
|
||||
return _walls.get_path_ahead(_player.position, _player.direction, TILES_TO_SEEK_AHEAD_OF_PLAYER)
|
||||
39
enemy/ai/states/SeekBehindState.gd
Normal file
39
enemy/ai/states/SeekBehindState.gd
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
class_name SeekBehindState
|
||||
extends EnemyState
|
||||
|
||||
var _walls: Dungeon
|
||||
var _player: Area2D
|
||||
|
||||
const MAP_POS_TO_RECHECK_PATH := 8
|
||||
const TILES_TO_SEEK_AHEAD_OF_PLAYER = 3
|
||||
|
||||
|
||||
func _init(player, walls: Dungeon):
|
||||
_player = player
|
||||
_walls = walls as Dungeon
|
||||
|
||||
|
||||
func get_enemy_path(enemy, _previous_tile: Vector2) -> Array:
|
||||
var position := enemy.position as Vector2
|
||||
|
||||
var path := _walls.getAStarPath(position, get_player_opposite_position())
|
||||
return path
|
||||
|
||||
|
||||
func get_player_opposite_position() -> Vector2:
|
||||
return _walls.get_path_ahead(
|
||||
_player.position, _get_opposite_direction(_player.direction), TILES_TO_SEEK_AHEAD_OF_PLAYER
|
||||
)
|
||||
|
||||
|
||||
func _get_opposite_direction(direction: Vector2) -> Vector2:
|
||||
if direction == Vector2.UP:
|
||||
return Vector2.DOWN
|
||||
elif direction == Vector2.RIGHT:
|
||||
return Vector2.LEFT
|
||||
elif direction == Vector2.DOWN:
|
||||
return Vector2.UP
|
||||
elif direction == Vector2.LEFT:
|
||||
return Vector2.RIGHT
|
||||
else:
|
||||
return direction
|
||||
23
enemy/ai/states/SeekState.gd
Normal file
23
enemy/ai/states/SeekState.gd
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
class_name SeekState
|
||||
extends EnemyState
|
||||
|
||||
var _walls: Dungeon
|
||||
var _player: Area2D
|
||||
|
||||
const MAP_POS_TO_RECHECK_PATH := 8
|
||||
|
||||
|
||||
func _init(player, walls: Dungeon):
|
||||
_player = player as Player
|
||||
_walls = walls as Dungeon
|
||||
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
var path := []
|
||||
var position := enemy.position as Vector2
|
||||
|
||||
_walls.disable_astar(_walls.map_to_world(previous_tile))
|
||||
path = _walls.getAStarPath(position, _player.position)
|
||||
_walls.enable_astar(_walls.map_to_world(previous_tile))
|
||||
|
||||
return path
|
||||
97
enemy/ai/states/WanderState.gd
Normal file
97
enemy/ai/states/WanderState.gd
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
class_name WanderState
|
||||
extends EnemyState
|
||||
|
||||
var _walls: TileMap
|
||||
var _player: Area2D
|
||||
|
||||
const MAP_POS_TO_RECHECK_PATH := 20
|
||||
const MAP_SIZE := 50
|
||||
|
||||
var tangent_toggle_x_array := [Vector2.LEFT, Vector2.RIGHT]
|
||||
var tangent_toggle_y_array := [Vector2.UP, Vector2.DOWN]
|
||||
|
||||
# half or a quarter, when finding shift post
|
||||
var shift_pos_array := [2, 4]
|
||||
|
||||
|
||||
func _init(player, walls):
|
||||
_player = player
|
||||
_walls = walls
|
||||
|
||||
|
||||
func get_enemy_path(enemy, previous_tile: Vector2) -> Array:
|
||||
return get_wander_path(enemy, previous_tile)
|
||||
|
||||
|
||||
func get_wander_path(enemy, previous_tile: Vector2) -> Array:
|
||||
var path := []
|
||||
var wander_direction = enemy.wander_direction
|
||||
var position := enemy.position as Vector2
|
||||
|
||||
var shift_direction = get_shift_direction(_player.position, position)
|
||||
var target_wander_direction = get_target_wander_direction(shift_direction, wander_direction)
|
||||
|
||||
_walls.disable_astar(_walls.map_to_world(previous_tile))
|
||||
path = _walls.getAStarPath(position, target_wander_direction)
|
||||
_walls.enable_astar(_walls.map_to_world(previous_tile))
|
||||
if path.size() == 0:
|
||||
path = _walls.getAStarPath(position, shift_direction)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
func get_shift_direction(player_pos: Vector2, enemy_pos: Vector2) -> Vector2:
|
||||
var shift_amount = swap_get(shift_pos_array) as int
|
||||
|
||||
var new_x = (int(player_pos.x) + (_walls.max_x_pos / shift_amount)) % _walls.max_x_pos
|
||||
var new_y = (int(player_pos.y) + (_walls.max_y_pos / shift_amount)) % _walls.max_y_pos
|
||||
|
||||
return Vector2(new_x, new_y)
|
||||
|
||||
|
||||
func is_player_around_corner_of_map(player_pos: Vector2) -> bool:
|
||||
return false
|
||||
|
||||
|
||||
func get_target_wander_direction(pos: Vector2, wander_direction: Vector2) -> Vector2:
|
||||
var far_pos := get_far_pos(pos, wander_direction)
|
||||
var far_with_tangent_pos := get_tangent_pos(far_pos, wander_direction)
|
||||
|
||||
return far_with_tangent_pos
|
||||
|
||||
|
||||
func get_far_pos(pos: Vector2, wander_direction: Vector2) -> Vector2:
|
||||
if wander_direction == Vector2.UP:
|
||||
pos.y -= MAP_SIZE * _walls.get_cell_size().y
|
||||
elif wander_direction == Vector2.RIGHT:
|
||||
pos.x += MAP_SIZE * _walls.get_cell_size().x
|
||||
elif wander_direction == Vector2.DOWN:
|
||||
pos.y += MAP_SIZE * _walls.get_cell_size().y
|
||||
elif wander_direction == Vector2.LEFT:
|
||||
pos.x -= MAP_SIZE * _walls.get_cell_size().x
|
||||
|
||||
return Vector2(clamp(pos.x, _walls.min_x_pos, _walls.max_x_pos), clamp(pos.y, _walls.min_y_pos, _walls.max_y_pos)) as Vector2
|
||||
|
||||
|
||||
func get_tangent_pos(pos: Vector2, wander_direction: Vector2) -> Vector2:
|
||||
if wander_direction == Vector2.UP or wander_direction == Vector2.DOWN:
|
||||
var new_dir = swap_get(tangent_toggle_y_array) as Vector2
|
||||
if new_dir == Vector2.LEFT:
|
||||
pos.x -= _walls.get_cell_size().x * 2
|
||||
else:
|
||||
pos.x += _walls.get_cell_size().x * 2
|
||||
else:
|
||||
var new_dir = swap_get(tangent_toggle_x_array) as Vector2
|
||||
if new_dir == Vector2.UP:
|
||||
pos.y -= _walls.get_cell_size().y * 2
|
||||
else:
|
||||
pos.y += _walls.get_cell_size().y * 2
|
||||
|
||||
return Vector2(clamp(pos.x, _walls.min_x_pos, _walls.max_x_pos), clamp(pos.y, _walls.min_y_pos, _walls.max_y_pos)) as Vector2
|
||||
|
||||
|
||||
func swap_get(swap_array: Array):
|
||||
var temp = swap_array[0]
|
||||
swap_array[0] = swap_array[1]
|
||||
swap_array[1] = temp
|
||||
return swap_array[0]
|
||||
38
enemy/enemyfiend/EnemyFiend.gd
Normal file
38
enemy/enemyfiend/EnemyFiend.gd
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
extends Enemy
|
||||
|
||||
const FIEND_COLOR: Color = Color("#da4e38")
|
||||
|
||||
export var is_enabled := true
|
||||
|
||||
var primary_AI_only := false
|
||||
var is_chase_state_enabled := false
|
||||
|
||||
|
||||
func _ready():
|
||||
set_process(is_enabled)
|
||||
disable_chase_state()
|
||||
|
||||
|
||||
func enable_chase_state() -> void:
|
||||
is_chase_state_enabled = true
|
||||
speed = player.speed * $"../".MAX_ENEMY_SPEED_FACTOR_TO_PLAYER
|
||||
primary_AI_only = true
|
||||
|
||||
|
||||
func disable_chase_state() -> void:
|
||||
is_chase_state_enabled = false
|
||||
speed = player.speed * 0.8
|
||||
primary_AI_only = false
|
||||
|
||||
|
||||
func change_states():
|
||||
if primary_AI_only:
|
||||
change_state(self, EnemyStateEnum.SEEK, 100)
|
||||
elif state is IdleState or state is SeekState:
|
||||
change_state(self, EnemyStateEnum.WANDER, 5)
|
||||
else:
|
||||
change_state(self, EnemyStateEnum.SEEK, 5)
|
||||
|
||||
|
||||
func _get_enemy_color() -> Color:
|
||||
return FIEND_COLOR
|
||||
BIN
enemy/enemyfiend/EnemyFiend.png
Normal file
BIN
enemy/enemyfiend/EnemyFiend.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 902 B |
34
enemy/enemyfiend/EnemyFiend.png.import
Normal file
34
enemy/enemyfiend/EnemyFiend.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/EnemyFiend.png-76817b915c6191e9e22bb98b20d04552.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://enemy/enemyfiend/EnemyFiend.png"
|
||||
dest_files=[ "res://.import/EnemyFiend.png-76817b915c6191e9e22bb98b20d04552.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
69
enemy/enemyfiend/EnemyFiend.tscn
Normal file
69
enemy/enemyfiend/EnemyFiend.tscn
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://enemy/enemyfiend/EnemyFiend.png" type="Texture" id=1]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=1]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 0, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=2]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 16, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=3]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 32, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=4]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 48, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=5]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 64, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=6]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 80, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=7]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 96, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=8]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 112, 0, 16, 25 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=9]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 6 ), SubResource( 7 ), SubResource( 8 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=10]
|
||||
extents = Vector2( 4, 6 )
|
||||
|
||||
[node name="EnemyFiend" type="Area2D"]
|
||||
z_index = 3
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
position = Vector2( 0, -13.7502 )
|
||||
frames = SubResource( 9 )
|
||||
frame = 2
|
||||
speed_scale = 2.0
|
||||
playing = true
|
||||
offset = Vector2( 0, 5 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( 0, -3 )
|
||||
shape = SubResource( 10 )
|
||||
37
enemy/enemylizardman/EnemyLizardMan.gd
Normal file
37
enemy/enemylizardman/EnemyLizardMan.gd
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
extends Enemy
|
||||
|
||||
const LIZARDMAN_COLOR: Color = Color("#49a790")
|
||||
|
||||
export var is_enabled := true
|
||||
|
||||
var primary_AI_only := false
|
||||
var is_chase_state_enabled := false
|
||||
|
||||
|
||||
func _ready():
|
||||
set_process(is_enabled)
|
||||
speed = player.speed * 0.8
|
||||
disable_chase_state()
|
||||
|
||||
|
||||
func enable_chase_state() -> void:
|
||||
is_chase_state_enabled = true
|
||||
primary_AI_only = true
|
||||
|
||||
|
||||
func disable_chase_state() -> void:
|
||||
is_chase_state_enabled = false
|
||||
primary_AI_only = false
|
||||
|
||||
|
||||
func change_states():
|
||||
if primary_AI_only:
|
||||
change_state(self, EnemyStateEnum.SEEK_AHEAD, 100)
|
||||
elif state is IdleState or state is SeekAheadState:
|
||||
change_state(self, EnemyStateEnum.WANDER, 5)
|
||||
else:
|
||||
change_state(self, EnemyStateEnum.SEEK_AHEAD, 5)
|
||||
|
||||
|
||||
func _get_enemy_color() -> Color:
|
||||
return LIZARDMAN_COLOR
|
||||
BIN
enemy/enemylizardman/EnemyLizardMan.png
Normal file
BIN
enemy/enemylizardman/EnemyLizardMan.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 960 B |
34
enemy/enemylizardman/EnemyLizardMan.png.import
Normal file
34
enemy/enemylizardman/EnemyLizardMan.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/EnemyLizardMan.png-beb5cc1a801a9397c54ee650f0ab3074.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://enemy/enemylizardman/EnemyLizardMan.png"
|
||||
dest_files=[ "res://.import/EnemyLizardMan.png-beb5cc1a801a9397c54ee650f0ab3074.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
69
enemy/enemylizardman/EnemyLizardMan.tscn
Normal file
69
enemy/enemylizardman/EnemyLizardMan.tscn
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://enemy/enemylizardman/EnemyLizardMan.png" type="Texture" id=1]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=1]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 0, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=2]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 16, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=3]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 32, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=4]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 48, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=5]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 64, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=6]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 80, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=7]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 96, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=8]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 112, 0, 16, 23 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=9]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 6 ), SubResource( 7 ), SubResource( 8 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=10]
|
||||
extents = Vector2( 4.14031, 5.17601 )
|
||||
|
||||
[node name="EnemyLizardMan" type="Area2D"]
|
||||
z_index = 3
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
position = Vector2( 0, -8 )
|
||||
rotation = 0.0174533
|
||||
frames = SubResource( 9 )
|
||||
playing = true
|
||||
offset = Vector2( 0, 2 )
|
||||
flip_h = true
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( -0.140312, -1.82399 )
|
||||
shape = SubResource( 10 )
|
||||
22
enemy/enemyogre/EnemyOgre.gd
Normal file
22
enemy/enemyogre/EnemyOgre.gd
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
extends Enemy
|
||||
|
||||
const OGRE_COLOR: Color = Color("#8f4029")
|
||||
|
||||
export var is_enabled := true
|
||||
|
||||
|
||||
func _ready():
|
||||
set_process(is_enabled)
|
||||
# slower than other enemies
|
||||
speed = player.speed * 0.7
|
||||
|
||||
|
||||
func change_states():
|
||||
if state is IdleState or state is ClydeState:
|
||||
change_state(self, EnemyStateEnum.CLYDE, 99)
|
||||
else:
|
||||
change_state(self, EnemyStateEnum.CLYDE, 99)
|
||||
|
||||
|
||||
func _get_enemy_color() -> Color:
|
||||
return OGRE_COLOR
|
||||
BIN
enemy/enemyogre/EnemyOgre.png
Normal file
BIN
enemy/enemyogre/EnemyOgre.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
34
enemy/enemyogre/EnemyOgre.png.import
Normal file
34
enemy/enemyogre/EnemyOgre.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/EnemyOgre.png-97455fedab595d09928b00cc6b68071a.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://enemy/enemyogre/EnemyOgre.png"
|
||||
dest_files=[ "res://.import/EnemyOgre.png-97455fedab595d09928b00cc6b68071a.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
69
enemy/enemyogre/EnemyOgre.tscn
Normal file
69
enemy/enemyogre/EnemyOgre.tscn
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://enemy/enemyogre/EnemyOgre.png" type="Texture" id=1]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=1]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 0, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=2]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 20, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=3]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 40, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=4]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 60, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=5]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 80, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=6]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 100, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=7]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 120, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=8]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 140, 0, 20, 28 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=9]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 6 ), SubResource( 7 ), SubResource( 8 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=10]
|
||||
extents = Vector2( 8, 11 )
|
||||
|
||||
[node name="EnemyOgre" type="Area2D"]
|
||||
z_index = 3
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
position = Vector2( 0, -13.75 )
|
||||
frames = SubResource( 9 )
|
||||
frame = 5
|
||||
speed_scale = 0.8
|
||||
playing = true
|
||||
offset = Vector2( 0, 4 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( 0, -8 )
|
||||
shape = SubResource( 10 )
|
||||
36
enemy/enemyslime/EnemySlime.gd
Normal file
36
enemy/enemyslime/EnemySlime.gd
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
extends Enemy
|
||||
|
||||
const SLIME_COLOR: Color = Color("#97da3f")
|
||||
|
||||
export var is_enabled := true
|
||||
var is_chase_state_enabled := false
|
||||
var primary_AI_only = false
|
||||
|
||||
|
||||
func _ready():
|
||||
set_process(is_enabled)
|
||||
speed = player.speed * 0.8
|
||||
disable_chase_state()
|
||||
|
||||
|
||||
func enable_chase_state() -> void:
|
||||
is_chase_state_enabled = true
|
||||
primary_AI_only = true
|
||||
|
||||
|
||||
func disable_chase_state() -> void:
|
||||
is_chase_state_enabled = false
|
||||
primary_AI_only = false
|
||||
|
||||
|
||||
func change_states():
|
||||
if primary_AI_only:
|
||||
change_state(self, EnemyStateEnum.SEEK_BEHIND, 20)
|
||||
elif state is IdleState or state is SeekBehindState:
|
||||
change_state(self, EnemyStateEnum.WANDER, 5)
|
||||
else:
|
||||
change_state(self, EnemyStateEnum.SEEK_BEHIND, 11)
|
||||
|
||||
|
||||
func _get_enemy_color() -> Color:
|
||||
return SLIME_COLOR
|
||||
BIN
enemy/enemyslime/EnemySlime.png
Normal file
BIN
enemy/enemyslime/EnemySlime.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 369 B |
34
enemy/enemyslime/EnemySlime.png.import
Normal file
34
enemy/enemyslime/EnemySlime.png.import
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/EnemySlime.png-f6127382170cd34ef61486c111b380c4.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://enemy/enemyslime/EnemySlime.png"
|
||||
dest_files=[ "res://.import/EnemySlime.png-f6127382170cd34ef61486c111b380c4.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
50
enemy/enemyslime/EnemySlime.tscn
Normal file
50
enemy/enemyslime/EnemySlime.tscn
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://enemy/enemyslime/EnemySlime.png" type="Texture" id=1]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=1]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 0, 0, 17, 18 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=2]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 17, 0, 17, 18 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=3]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 34, 0, 17, 18 )
|
||||
|
||||
[sub_resource type="AtlasTexture" id=4]
|
||||
flags = 4
|
||||
atlas = ExtResource( 1 )
|
||||
region = Rect2( 51, 0, 17, 18 )
|
||||
|
||||
[sub_resource type="SpriteFrames" id=5]
|
||||
animations = [ {
|
||||
"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ) ],
|
||||
"loop": true,
|
||||
"name": "moving",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=6]
|
||||
extents = Vector2( 3.99999, 5.33415 )
|
||||
|
||||
[node name="EnemySlime" type="Area2D"]
|
||||
z_index = 3
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
|
||||
position = Vector2( 0, -10 )
|
||||
frames = SubResource( 5 )
|
||||
animation = "moving"
|
||||
speed_scale = 0.6
|
||||
playing = true
|
||||
offset = Vector2( 0, 6 )
|
||||
flip_h = true
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( 1.15037e-05, -2.66585 )
|
||||
shape = SubResource( 6 )
|
||||
Loading…
Add table
Add a link
Reference in a new issue