Settlers of EMF

Allow menu screens to avoid redrawing the logo, for quicker
response times when navigating menus.
master
Mat Booth 2018-10-30 19:23:34 +00:00
parent 846bab0ab1
commit fcd537cdfd
1 changed files with 123 additions and 50 deletions

View File

@ -80,19 +80,28 @@ class State:
class Menu(State):
def __init__(self, question, choices):
MENU_ITEM_OFFSET = 120
def __init__(self, question, choices, clear_title=True):
self.question = question
self.choices = choices
self.clear_title = clear_title
def is_choice_enabled(self, num):
c = self.choices[num]
return 'disabled' not in c or not c['disabled']
def get_selected_choice(self):
return self.choices[self.selection].copy()
def draw(self):
# Draw the menu on screen
ugfx.clear(ugfx.BLACK)
ugfx.display_image(0, 0, 'settlers_of_emf/title.png')
ugfx.text(5, 100, self.question, ugfx.WHITE)
if self.clear_title:
ugfx.clear(ugfx.BLACK)
ugfx.display_image(0, 0, 'settlers_of_emf/title.png')
else:
ugfx.area(0, 95, 240, 225, ugfx.BLACK)
ugfx.text(5, 95, self.question, ugfx.WHITE)
offset = 0
for i in range(len(self.choices)):
c = self.choices[i]
@ -105,13 +114,13 @@ class Menu(State):
text = "{} ".format(c['name'])
else:
text = "{} - {} ".format(i + 1, c['name'])
ugfx.text(18, offset + 125, text, col)
ugfx.text(18, offset + Menu.MENU_ITEM_OFFSET, text, col)
offset = offset + 20
if 'cost' in c:
for j in range(len(c['cost'])):
cost = c['cost'][j]
ugfx.area((42 * j) + 46, offset + 125, 18, 18, cost['resource']['col'])
ugfx.text((42 * j) + 64, offset + 125, "x{} ".format(cost['amount']), col)
ugfx.area((42 * j) + 46, offset + Menu.MENU_ITEM_OFFSET, 18, 18, cost['resource']['col'])
ugfx.text((42 * j) + 64, offset + Menu.MENU_ITEM_OFFSET, "x{} ".format(cost['amount']), col)
offset = offset + 20
# Set the initial selection
@ -185,10 +194,10 @@ class Menu(State):
def _set_selection(self, new_selection):
# Redraws the selection box
size = 2 if 'cost' in self.choices[self.selection] else 1
ugfx.box(0, self._get_offset_for_selection(self.selection) + 125, 240, 20 * size, ugfx.BLACK)
ugfx.box(0, self._get_offset_for_selection(self.selection) + Menu.MENU_ITEM_OFFSET, 240, 20 * size, ugfx.BLACK)
self.selection = new_selection
size = 2 if 'cost' in self.choices[self.selection] else 1
ugfx.box(0, self._get_offset_for_selection(self.selection) + 125, 240, 20 * size, ugfx.WHITE)
ugfx.box(0, self._get_offset_for_selection(self.selection) + Menu.MENU_ITEM_OFFSET, 240, 20 * size, ugfx.WHITE)
def _get_offset_for_selection(self, sel):
# Menu items are double height if they need to show a cost, so iterate
@ -203,9 +212,6 @@ class Menu(State):
class MainMenu(Menu):
NEW_GAME = 0
CONTINUE_GAME = 1
EXIT = 2
options = [
{'name': "Start New Game"},
@ -213,9 +219,13 @@ class MainMenu(Menu):
{'name': "Exit"},
]
def __init__(self, disable_continue_option=True):
NEW_GAME = 0
CONTINUE_GAME = 1
EXIT = 2
def __init__(self, disable_continue_option=True, clear_title=True):
MainMenu.options[MainMenu.CONTINUE_GAME]['disabled'] = disable_continue_option
super().__init__('Welcome!', MainMenu.options)
super().__init__('Welcome!', MainMenu.options, clear_title)
class TeamMenu(Menu):
@ -248,14 +258,31 @@ class TeamMenu(Menu):
continue
option['disabled'] = option['name'] in [team['name'] for team in teams]
TeamMenu.options[TeamMenu.START_GAME]['disabled'] = len(teams) == 0
super().__init__('Player {}, choose a team:'.format(len(teams) + 1), TeamMenu.options)
def get_selected_team(self):
return TeamMenu.options[self.selection].copy()
super().__init__('Player {}, choose a team:'.format(len(teams) + 1), TeamMenu.options, False)
class ActionMenu(Menu):
options = [
{'name': "Build"},
{'name': "Trade"},
{'name': "End Turn"},
{'name': "Back"},
]
BUILD = 0
TRADE = 1
END_TURN = 2
BACK = 3
def __init__(self, dice_roll, clear_title=True):
# Rolling the dice is mandatory, so don't let the turn end unless it happened
ActionMenu.options[ActionMenu.END_TURN]['disabled'] = dice_roll == 0
super().__init__('Do a thing:', ActionMenu.options, clear_title)
class BuildMenu(Menu):
options = [
{'name': "Build Road (0 points)",
'cost': [{'resource': BRICK, 'amount': 1},
@ -268,19 +295,14 @@ class ActionMenu(Menu):
{'name': "Upgrade to City (2 points)",
'cost': [{'resource': WHEAT, 'amount': 2},
{'resource': ORE, 'amount': 3}]},
# TODO Implement trading
{'name': "Trade", 'disabled': True},
{'name': "End Turn"},
{'name': "Back"},
]
TRADE = len(options) - 3
END_TURN = len(options) - 2
BACK = len(options) - 1
def __init__(self, resources, dice_roll):
def __init__(self, resources):
# Disable build options based on whether the player can afford them
for option in ActionMenu.options:
for option in BuildMenu.options:
if 'cost' not in option:
continue
option['disabled'] = False
@ -289,12 +311,39 @@ class ActionMenu(Menu):
if resource.resource == cost['resource']:
if resource.quantity < cost['amount']:
option['disabled'] = True
# Rolling the dice is mandatory, so don't let the turn end unless it happened
ActionMenu.options[ActionMenu.END_TURN]['disabled'] = dice_roll == 0
super().__init__('Do a thing:', ActionMenu.options)
super().__init__('Build:', BuildMenu.options, False)
def get_selected_build(self):
return ActionMenu.options[self.selection].copy()
class TradeMenu(Menu):
options = [
{'name': "Buy a Resource",
'cost': [{'resource': BRICK, 'amount': 4}]},
{'name': "Buy a Resource",
'cost': [{'resource': WOOD, 'amount': 4}]},
{'name': "Buy a Resource",
'cost': [{'resource': SHEEP, 'amount': 4}]},
{'name': "Buy a Resource",
'cost': [{'resource': WHEAT, 'amount': 4}]},
{'name': "Buy a Resource",
'cost': [{'resource': ORE, 'amount': 4}]},
{'name': "Back"},
]
BACK = len(options) - 1
def __init__(self, resources):
# Disable trade options based on whether the player can afford them
for option in TradeMenu.options:
if 'cost' not in option:
continue
option['disabled'] = False
for cost in option['cost']:
for resource in resources:
if resource.resource == cost['resource']:
if resource.quantity < cost['amount']:
option['disabled'] = True
super().__init__('Trade:', TradeMenu.options, False)
class NextPlayer(Menu):
@ -302,7 +351,7 @@ class NextPlayer(Menu):
START_TURN = 0
def __init__(self, team):
super().__init__('Pass the badge to next team:', [team])
super().__init__('Pass the badge to next team:', [team], False)
class Hex:
@ -937,62 +986,86 @@ class Settlers:
TEAM_MENU = 2
GAME = 3
ACTION_MENU = 4
END_TURN = 5
ACTION_TRADE_MENU = 5
ACTION_BUILD_MENU = 6
ACTION_END_TURN = 7
def __init__(self):
self.old_state = None
self.state = Settlers.MAIN_MENU
self.game = None
self.teams = []
def enter_state(self, state):
self.old_state = self.state
self.state = state
def run(self):
while self.state != Settlers.EXIT:
if self.state == Settlers.MAIN_MENU:
menu = MainMenu(self.game is None)
menu = MainMenu(self.game is None, self.old_state != Settlers.TEAM_MENU)
x = menu.run()
if x == MainMenu.NEW_GAME:
self.teams = []
self.state = Settlers.TEAM_MENU
self.enter_state(Settlers.TEAM_MENU)
if x == MainMenu.CONTINUE_GAME:
self.state = Settlers.GAME
self.enter_state(Settlers.GAME)
if x == MainMenu.EXIT:
self.state = Settlers.EXIT
self.enter_state(Settlers.EXIT)
if self.state == Settlers.TEAM_MENU:
elif self.state == Settlers.TEAM_MENU:
menu = TeamMenu(self.teams)
x = menu.run()
if x <= TeamMenu.TEAM_MAX:
self.teams.append(menu.get_selected_team())
self.teams.append(menu.get_selected_choice())
if len(self.teams) >= 4:
x = TeamMenu.START_GAME
if x == TeamMenu.BACK:
self.state = Settlers.MAIN_MENU
self.enter_state(Settlers.MAIN_MENU)
if x == TeamMenu.START_GAME:
self.game = GameBoard(self.teams)
self.game.next_player()
self.state = Settlers.GAME
self.enter_state(Settlers.GAME)
if self.state == Settlers.GAME:
elif self.state == Settlers.GAME:
x = self.game.run()
if x == GameBoard.MAIN_MENU:
self.state = Settlers.MAIN_MENU
self.enter_state(Settlers.MAIN_MENU)
if x == GameBoard.ACTION_MENU:
self.state = Settlers.ACTION_MENU
self.enter_state(Settlers.ACTION_MENU)
if self.state == Settlers.ACTION_MENU:
menu = ActionMenu(self.game.player.resources, self.game.dice.total())
elif self.state == Settlers.ACTION_MENU:
menu = ActionMenu(self.game.dice.total(), self.old_state != Settlers.ACTION_BUILD_MENU and self.old_state != Settlers.ACTION_TRADE_MENU)
x = menu.run()
if x == ActionMenu.BACK:
self.state = Settlers.GAME
if x == ActionMenu.BUILD:
self.enter_state(Settlers.ACTION_BUILD_MENU)
if x == ActionMenu.TRADE:
self.enter_state(Settlers.ACTION_TRADE_MENU)
if x == ActionMenu.END_TURN:
self.state = Settlers.END_TURN
self.enter_state(Settlers.ACTION_END_TURN)
if x == ActionMenu.BACK:
self.enter_state(Settlers.GAME)
elif self.state == Settlers.ACTION_BUILD_MENU:
menu = BuildMenu(self.game.player.resources)
x = menu.run()
if x == BuildMenu.BACK:
self.enter_state(Settlers.ACTION_MENU)
# TODO initiate building a thing
if self.state == Settlers.END_TURN:
elif self.state == Settlers.ACTION_TRADE_MENU:
menu = TradeMenu(self.game.player.resources)
x = menu.run()
if x == TradeMenu.BACK:
self.enter_state(Settlers.ACTION_MENU)
# TODO initiate trading a thing
elif self.state == Settlers.ACTION_END_TURN:
self.game.next_player()
menu = NextPlayer(self.game.player.team)
x = menu.run()
self.state = Settlers.GAME
self.enter_state(Settlers.GAME)
# User chose exit, a machine reset is the easiest way :-)
restart_to_default()