ld39-dead_in_the_water/game/game.gd

287 lines
8.1 KiB
GDScript3
Raw Normal View History

2017-07-29 23:11:45 +00:00
extends Node2D
# Signals
signal game_energy_changed
signal game_deck_changed
signal game_discard_changed
signal game_hand_changed
signal game_state_changed
2017-07-31 00:17:24 +00:00
signal game_round_start
2017-07-29 23:11:45 +00:00
2017-07-31 00:17:24 +00:00
var DEBUG = false
2017-07-29 23:11:45 +00:00
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
2017-07-31 00:17:24 +00:00
export(int) var energy = 100
export(int) var base_energy_per_round = 10
2017-07-29 23:11:45 +00:00
const ENERGY_MAX = 100
const ENERGY_MIN = 0
const SHUFFLE_REPEATS = 3
const STARTING_DECK_SIZE = 10
# Card piles: hand, deck, discard
var max_hand_size = 5
var hand = []
# Index 0 = bottom for deck and discard
var deck = []
var discard = []
# Game state machine ish
var actions_per_round = 1
var actions_remaining = 1
var round_counter = 0
var game_state = -2
var game_win = false
var game_over_message = ''
var game_states = {
-2: "initializing",
-1: "round_start",
0: "waiting_player_action",
1: "playing_action",
2: "round_done",
3: "waiting", # Generic let something else finish
4: "event", # Some out of player control event
5: "over",
}
# Cards
var cards = {
"card_repair": preload("res://cards/card_repair.tscn"),
2017-07-31 00:17:24 +00:00
"card_repurpose": preload("res://cards/repurpose.tscn"),
"card_battery_small": preload("res://cards/battery_small.tscn"),
"card_battery_big": preload("res://cards/battery_big.tscn"),
"card_spare_parts": preload("res://cards/spare_parts.tscn"),
"card_injured": preload('res://cards/injured.tscn'),
"card_medkit": preload('res://cards/medkit.tscn'),
2017-07-29 23:11:45 +00:00
}
func _ready():
# Called every time the node is added to the scene.
# Initialization here
randomize()
var bar = get_node("ui/EnergyHolder/ProgressBar")
bar.set_min(ENERGY_MIN)
bar.set_max(ENERGY_MAX)
set_process(true)
2017-07-31 00:17:24 +00:00
get_node('ui/end_message/buttons/Replay').connect('pressed', self, 'on_game_replay')
get_node('ui/end_message/buttons/Quit').connect('pressed', self, 'on_game_quit')
2017-07-29 23:11:45 +00:00
if self.DEBUG:
get_node('ui/debug').show()
2017-07-31 00:17:24 +00:00
var areas = self.get_tree().get_nodes_in_group('areas')
for a in areas:
a.connect('game_area_activation_changed', self, 'on_area_activation_changed')
self.on_area_activation_changed(null, null)
2017-07-29 23:11:45 +00:00
init_game()
func init_game():
# Popuplate deck
2017-07-31 00:17:24 +00:00
self.energy = ENERGY_MAX
get_node('ui/EnergyHolder/ProgressBar').set_value(self.energy)
self.deck = []
# Choose starting deck:
self.add_card_to_deck('card_medkit')
self.add_card_to_deck('card_repurpose')
self.add_card_to_deck('card_spare_parts')
self.add_card_to_deck('card_spare_parts')
self.add_card_to_deck('card_spare_parts')
self.add_card_to_deck('card_injured')
self.add_card_to_deck('card_injured')
self.add_card_to_deck('card_injured')
self.add_card_to_deck('card_battery_small')
self.add_card_to_deck('card_battery_small')
self.discard = []
self.hand = []
2017-07-29 23:11:45 +00:00
while self.deck.size() < STARTING_DECK_SIZE:
2017-07-31 00:17:24 +00:00
self.add_card_to_deck(null)
2017-07-29 23:11:45 +00:00
self.shuffle()
emit_signal('game_deck_changed', self.deck.size())
2017-07-31 00:17:24 +00:00
emit_signal('game_hand_changed', self.hand.size())
emit_signal('game_discard_changed', self.discard.size())
get_node('areas/reactor').set_health(0)
2017-07-29 23:11:45 +00:00
self.update_game_state(-1)
2017-07-31 00:17:24 +00:00
func add_card_to_deck(key = null):
"""
If key is null, a card is randomly added
@returns bool
true is a card was added, false otherwise
"""
var node
if not key:
var card_keys = self.cards.keys()
node = self.cards[card_keys[rand_range(0, card_keys.size() - 1)]].instance()
elif self.cards.has(key):
node = self.cards[key].instance()
else:
return false
node.add_to_group('cards')
node.set_game(self)
get_node('cards').add_child(node)
node.hide()
self.deck.append(node)
return true
2017-07-29 23:11:45 +00:00
func update_game_state(new_state_idx):
2017-07-31 00:17:24 +00:00
if self.game_state == new_state_idx:
return
2017-07-29 23:11:45 +00:00
if ! self.game_states.has(new_state_idx):
print("Error: trying to change game_state to unknown index: %d" % new_state_idx)
return
var old_state = self.game_state
self.game_state = new_state_idx
print("Changed game state from %d to %d" % [old_state, new_state_idx])
emit_signal('game_state_changed', old_state, new_state_idx)
func _process():
pass
func update_energy(diff = 0):
2017-07-31 00:17:24 +00:00
if self.energy + diff > self.ENERGY_MAX:
diff = self.ENERGY_MAX - self.energy
print('Updating energy from %d by %d to %d' % [self.energy, diff, self.energy + diff])
2017-07-29 23:11:45 +00:00
self.energy += diff
emit_signal("game_energy_changed", self.energy)
if self.energy <= 0:
self.game_win = false
self.game_over_message = 'Ran out of energy.... your ship is floating useless and dead in space'
self.update_game_state(5)
return true
return false
func draw_hand(cmax = null):
if not cmax:
cmax = self.max_hand_size
var success = false
while self.hand.size() < cmax:
success = self.draw_card()
if not success:
break
func draw_card():
"""
returns bool: true if a card was drawn
"""
if self.hand.size() >= self.max_hand_size:
return false # Can't exceed max hand size
if self.deck.size() == 0:
self.shuffle_in_discard()
if self.deck.empty():
return false # Deck + Discard is milled out
var c = self.deck[-1]
self.deck.pop_back()
self.hand.push_back(c)
2017-07-31 00:17:24 +00:00
c.previous_location = Vector2(-200, -200)
2017-07-29 23:11:45 +00:00
emit_signal("game_deck_changed", self.deck.size())
emit_signal("game_hand_changed", self.hand.size())
return true
func shuffle_in_discard():
while not self.discard.empty():
self.deck.push_back(self.discard[-1])
self.discard.pop_back()
emit_signal("game_discard_changed", self.discard.size())
self.shuffle()
func shuffle():
if self.DEBUG:
print("--- start shuffle ---")
print(self.deck)
for i in range(1, SHUFFLE_REPEATS):
var new_deck = []
var x
while not self.deck.empty():
x = rand_range(0, self.deck.size()-1)
new_deck.append(self.deck[x])
self.deck.remove(x)
self.deck = new_deck
if self.DEBUG:
print(self.deck)
print("--- end shuffle ---")
func _on_game_game_state_changed(old_state, new_state):
if new_state == -1:
# New Round
self.round_counter += 1
self.actions_remaining = self.actions_per_round
self.draw_hand()
2017-07-31 00:17:24 +00:00
print("New round: %d" %self.round_counter)
2017-07-29 23:11:45 +00:00
emit_signal("game_round_start", self.round_counter)
self.update_game_state(0) # Waiting for player action
2017-07-31 00:17:24 +00:00
if new_state == 2: # Round done
2017-07-29 23:11:45 +00:00
var state_changed = self.update_energy(-get_round_energy_cost())
2017-07-31 00:17:24 +00:00
state_changed = state_changed || self.check_reactor_fixed()
2017-07-29 23:11:45 +00:00
if not state_changed:
self.update_game_state(-1)
if new_state == 5: # Game finish
2017-07-31 00:17:24 +00:00
var n = get_node('ui/end_message')
n.set_message(self.game_over_message)
n.show()
2017-07-29 23:11:45 +00:00
func play_card(card):
if self.game_state != 0:
return
2017-07-31 00:17:24 +00:00
card.start_card_play('on_card_play_done')
self.update_game_state(1) # playing action
func on_card_play_done(card, played):
if not played:
self.update_game_state(0) # Waiting for player input
return
self.discard_card(card)
self.actions_remaining -= 1
if self.actions_remaining <= 0:
self.update_game_state(2) # Round done
func discard_card(card):
2017-07-29 23:11:45 +00:00
card.hide()
card.set_global_pos(Vector2(-200,-200))
var p = self.hand.find(card)
print(p)
if p != -1:
self.hand.remove(p)
self.discard.append(card)
print(self.hand)
print(self.discard)
emit_signal('game_hand_changed', self.hand.size())
emit_signal('game_discard_changed', self.discard.size())
2017-07-31 00:17:24 +00:00
2017-07-29 23:11:45 +00:00
func get_round_energy_cost():
# @TODO base on enabled areas
2017-07-31 00:17:24 +00:00
var areas = get_tree().get_nodes_in_group('areas')
var cost = self.base_energy_per_round
for a in areas:
if a.activated:
cost += a.energy_cost
return cost
func check_reactor_fixed():
var n = get_node('areas/reactor')
if n.health == n.max_health:
self.game_win = true
self.game_over_message = 'Fixed the reactor - back on track and in it to win it :)'
self.update_game_state(5)
return true
return false
func on_game_quit():
get_tree().quit()
func on_game_replay():
get_tree().change_scene('res://game.tscn')
#get_node('ui/end_message').hide()
#self.init_game()
func on_area_activation_changed(area, activated):
var c = get_round_energy_cost()
get_node('ui/round_energy_label').set_text('Energy Consumption: %d' % c)
func destroy_card(card):
# Remove a card from the game
for ar in [self.hand, self.deck, self.discard]:
var i = ar.find(card)
if i != -1:
ar.remove(i)
self.remove_child(card)
emit_signal('game_hand_changed', self.hand.size())
emit_signal('game_discard_changed', self.discard.size())
emit_signal('game_deck_changed', self.deck.size())