Add enemy respawns
This commit is contained in:
parent
911bceb750
commit
d22224a818
14
TODO.md
14
TODO.md
|
@ -1,22 +1,18 @@
|
|||
1. Enemy respawns
|
||||
* every now and again, the opponents has new units that spawn
|
||||
* indicator to show respawn is nearing
|
||||
* is it all the missing units, or a chance for each?
|
||||
2. Power ups
|
||||
1. Power ups
|
||||
* a chance of having power ups spawn on an random unoccupied square when a unit dies
|
||||
* +health, +attack, +speed, +jump, (pawn only) remove "attack_only", spawn a new (random?) piece, change movement type
|
||||
* then the enemy respawns units, their new units are stronger
|
||||
* support for pieces with multiple hit points
|
||||
* unit info panel
|
||||
3. Visual polish
|
||||
2. Visual polish
|
||||
* clean up tile borders
|
||||
* multiple square tiles to add variation
|
||||
* make the help text indicate (flash, etc.)
|
||||
4. Sound effects
|
||||
3. Sound effects
|
||||
* on hit
|
||||
* on piece lost
|
||||
* on piece kill
|
||||
* on opponent victory
|
||||
* if possible, a small bit of background music
|
||||
5. Further visual polish
|
||||
6. New units
|
||||
4. Further visual polish
|
||||
5. New units
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 892 B After Width: | Height: | Size: 891 B |
97
src/Game.gd
97
src/Game.gd
|
@ -32,6 +32,9 @@ var flash_help = null
|
|||
var rng = null
|
||||
var ai_target = null
|
||||
var ai_piece = null
|
||||
var reinforcements = null
|
||||
var reinforcements_size = 0
|
||||
var reinforcements_coords = []
|
||||
|
||||
const piece_types = {
|
||||
"pawn": "res://src/pieces/Pawn.tscn",
|
||||
|
@ -165,7 +168,7 @@ func _on_piece_click(piece, event):
|
|||
if piece == null:
|
||||
self.selected_piece = null
|
||||
return
|
||||
print("Selected piece: ", piece)
|
||||
#print("Selected piece: ", piece)
|
||||
if piece.is_in_group("player"):
|
||||
piece.get_node("Body").set_modulate(Color(0, 1, 0, 1))
|
||||
else:
|
||||
|
@ -278,7 +281,8 @@ func reset_game_state():
|
|||
self.board_squares[Vector2(x, y)] = {
|
||||
"x": x,
|
||||
"y": y,
|
||||
"piece": null
|
||||
"piece": null,
|
||||
"reinforcement": null,
|
||||
}
|
||||
y += 1
|
||||
x += 1
|
||||
|
@ -321,13 +325,97 @@ func _on_phase_end():
|
|||
self.current_state += 1;
|
||||
if not self.current_state in self.states.keys():
|
||||
self.current_state = 0
|
||||
self.turn += 1
|
||||
self._on_new_turn()
|
||||
get_node("TopBar/Bottom/Instruction").set_text(
|
||||
self.states[self.current_state]["description"] + " - " + self.states[self.current_state]["directive"]
|
||||
)
|
||||
|
||||
func choose_reinforcements(size, opponent: bool = true, at_spawn = true):
|
||||
var min_square = 0
|
||||
var max_square = (self.height * self.width) - 1
|
||||
if at_spawn:
|
||||
max_square = (self.width)*2 - 1
|
||||
var range_size = max_square - min_square
|
||||
var arrival_coords = []
|
||||
var n = 0
|
||||
while n < size:
|
||||
var try = 0
|
||||
var square_index = 0
|
||||
var square = null
|
||||
while try < 10:
|
||||
# Try to get an unoccupied square
|
||||
square_index = self.rng.randi() % range_size
|
||||
var square_coord = Vector2(
|
||||
floor(square_index % self.width), floor(square_index / self.width)
|
||||
)
|
||||
if at_spawn and not opponent:
|
||||
square_coord.y += self.height - 2
|
||||
square = self.board_squares[square_coord]
|
||||
if square['piece'] == null and square['reinforcement'] == null:
|
||||
# unoccupied, we'll take it
|
||||
arrival_coords.append(square_coord)
|
||||
var types = self.piece_types.keys()
|
||||
square['reinforcement'] = types[self.rng.randi()%types.size()]
|
||||
break
|
||||
# occupied, try again
|
||||
square = null
|
||||
try += 1
|
||||
if square == null:
|
||||
print("Failed to find a spot to spawn reinforcement")
|
||||
n += 1
|
||||
return arrival_coords
|
||||
|
||||
func _on_new_turn():
|
||||
self.turn += 1
|
||||
var just_spawned = false
|
||||
if self.reinforcements != null:
|
||||
var pf = get_node("/root/Game/MarginContainer/Playfield")
|
||||
self.reinforcements -= 1
|
||||
if self.reinforcements == 1:
|
||||
# decide on what will arrive
|
||||
self.reinforcements_coords = choose_reinforcements(self.reinforcements_size)
|
||||
# show the player where they will arrive
|
||||
for coord in self.reinforcements_coords:
|
||||
pf.squares[coord].get_ref().set_reinforcement(self.board_squares[coord]['reinforcement'])
|
||||
print("Reinforcement at coord ", coord, ": ", self.board_squares[coord]['reinforcement'])
|
||||
get_node("BottomBar/Help").set_text("Reinforcement arrival locations analyzed")
|
||||
self.flash_help = 3
|
||||
elif self.reinforcements == 0:
|
||||
# spawn them
|
||||
for coord in self.reinforcements_coords:
|
||||
pf.squares[coord].get_ref().set_reinforcement(null)
|
||||
var square = self.board_squares[coord]
|
||||
if square['piece'] == null:
|
||||
new_piece(square['reinforcement'], "opponent", coord)
|
||||
else:
|
||||
print("Reinforcement arrival at ", coord, " blocked by piece!")
|
||||
get_node("BottomBar/Help").set_text("Reinforcement at " + str(coord) + " telefragged.")
|
||||
self.flash_help = 2
|
||||
square['reinforcement'] = null
|
||||
just_spawned = true
|
||||
self.reinforcements = null
|
||||
self.reinforcements_size = 0
|
||||
self.reinforcements_coords = []
|
||||
|
||||
# Check for reinforcements
|
||||
var opponent_pieces = get_tree().get_nodes_in_group("opponent")
|
||||
# @TODO hardcoded value for number of pieces a side should have on the board
|
||||
# If they are less than 1/4 strength ensure that reinforcements are queued
|
||||
if opponent_pieces.size() <= 3 and self.reinforcements == null:
|
||||
self.reinforcements = 2 # 2 turns away
|
||||
self.reinforcements_size = 4
|
||||
get_node("BottomBar/Help").set_text("Multiple opponent reinforcements detected inbound")
|
||||
self.flash_help = 3
|
||||
if self.reinforcements == null and not just_spawned:
|
||||
var chance = lerp(0, 50, 1 - float(opponent_pieces.size())/16.0)
|
||||
var i = self.rng.randi() % 100
|
||||
print("Roll for reinforcements ", i, " < ", chance)
|
||||
if i < chance:
|
||||
self.reinforcements = 2
|
||||
self.reinforcements_size = 1
|
||||
get_node("BottomBar/Help").set_text("Inbound opponent reinforcements detected")
|
||||
self.flash_help = 3
|
||||
|
||||
get_node("TopBar/Top/HBoxContainer/Turn").set_text(str(self.turn))
|
||||
|
||||
func _reset_help():
|
||||
|
@ -341,7 +429,8 @@ func _process(delta):
|
|||
else:
|
||||
self._reset_help()
|
||||
self.flash_help = null
|
||||
if get_tree().get_nodes_in_group("opponent").empty() or get_tree().get_nodes_in_group("player").empty():
|
||||
var opponent_pieces = get_tree().get_nodes_in_group("opponent")
|
||||
if opponent_pieces.empty() or get_tree().get_nodes_in_group("player").empty():
|
||||
# The game is over
|
||||
self.current_state = 99
|
||||
var player_victory = false
|
||||
|
|
|
@ -40,7 +40,7 @@ func _input(event):
|
|||
get_tree().set_input_as_handled()
|
||||
else:
|
||||
if self.last_click != null and self.last_click <= CLICK_THRESHOLD:
|
||||
print("Click: ", self, event)
|
||||
#print("Click: ", self, event)
|
||||
emit_signal("click", self, event)
|
||||
# Work-around bug where only the last signal is connected
|
||||
# to the Game
|
||||
|
@ -52,7 +52,7 @@ func _input(event):
|
|||
get_tree().set_input_as_handled()
|
||||
if not event.pressed and self.hold_started:
|
||||
emit_signal("hold_stop", self, event)
|
||||
print("Hold stop", self, " ", event)
|
||||
#print("Hold stop", self, " ", event)
|
||||
self.cancel_hold()
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
|
@ -62,7 +62,7 @@ func _process(delta):
|
|||
self.last_click += delta
|
||||
if not self.hold_started and self.last_click >= self.CLICK_THRESHOLD:
|
||||
self.hold_started = true;
|
||||
print("Hold start", self, " ", null)
|
||||
#print("Hold start", self, " ", null)
|
||||
emit_signal("hold_start", self, null)
|
||||
if self.hold_started:
|
||||
self.set_global_position(get_viewport().get_mouse_position())
|
||||
|
|
|
@ -29,6 +29,7 @@ func initialize(width: int = 8, height: int = 8):
|
|||
# @TODO any tweaks to the node by calling custom function initialize()
|
||||
instance.translate(Vector2(128*i, 128*j))
|
||||
self.squares[Vector2(i, j)] = weakref(instance)
|
||||
instance.get_node("Control").set_tooltip(str(Vector2(i, j)))
|
||||
add_child(instance)
|
||||
j += 1
|
||||
i += 1
|
||||
|
|
|
@ -5,11 +5,41 @@ class_name Square
|
|||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
var reinforcement = null
|
||||
var timer = 0
|
||||
const FLASH_FREQUENCY = 2 # seconds
|
||||
const FLASH_MIN = Color(1, 0.75, 0.75, 1)
|
||||
const FLASH_MAX = Color(1, 0.5, 0.5, 1)
|
||||
const DEFAULT_BODY = Color(1, 1, 1, 1)
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
func set_reinforcement(reinforcement):
|
||||
self.reinforcement = reinforcement
|
||||
self.timer = 0
|
||||
print("Set reinforcement on ", self, " : ", reinforcement)
|
||||
if reinforcement == null:
|
||||
get_node("Body").set_modulate(DEFAULT_BODY)
|
||||
get_node("Control").set_tooltip("")
|
||||
else:
|
||||
get_node("Control").set_tooltip("Arriving unit: " + reinforcement)
|
||||
|
||||
func _process(delta):
|
||||
if self.reinforcement != null:
|
||||
self.timer += delta
|
||||
if self.timer >= FLASH_FREQUENCY*2:
|
||||
self.timer = 0
|
||||
if self.timer >= FLASH_FREQUENCY:
|
||||
# Going from dark to light
|
||||
get_node("Body").set_modulate(
|
||||
lerp(FLASH_MIN, FLASH_MAX, 1-((self.timer-FLASH_FREQUENCY)/FLASH_FREQUENCY))
|
||||
)
|
||||
else:
|
||||
# Going from light to dark
|
||||
get_node("Body").set_modulate(
|
||||
lerp(FLASH_MIN, FLASH_MAX, self.timer / FLASH_FREQUENCY)
|
||||
)
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
|
|
|
@ -19,6 +19,16 @@ modulate = Color( 0.12549, 0.0980392, 0.0980392, 1 )
|
|||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="Area2D" type="Area2D" parent="."]
|
||||
visible = false
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||
visible = false
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="Control" type="Control" parent="."]
|
||||
margin_right = 40.0
|
||||
margin_bottom = 40.0
|
||||
hint_tooltip = "Square"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue