Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -236,31 +236,80 @@ class ScottPilgrimGame:
|
|
236 |
# Create a single game instance to be managed by gr.State
|
237 |
game_instance = ScottPilgrimGame()
|
238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
def update_ui(game_state):
|
240 |
"""
|
241 |
Updates all Gradio UI components based on the current game state.
|
242 |
-
|
243 |
-
It now returns the game_state as well, to match the number of output components.
|
244 |
"""
|
245 |
phase = game_state.current_game_phase
|
246 |
-
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
# Configure visibility for each game phase
|
250 |
char_buttons_visible = (phase == "start")
|
251 |
action_buttons_visible = (phase == "combat")
|
252 |
play_again_visible = (phase in ["game_over", "win"])
|
253 |
|
254 |
-
if phase == "start":
|
255 |
-
log = "Welcome to Scott Pilgrim vs. The World: The RPG!\nChoose your hero!"
|
256 |
-
elif phase == "game_over":
|
257 |
-
log += "\n\nGAME OVER! Better luck next time!"
|
258 |
-
elif phase == "win":
|
259 |
-
log += "\n\nYOU WON! Thanks for playing!"
|
260 |
-
|
261 |
return (
|
262 |
-
|
263 |
-
|
264 |
gr.update(visible=char_buttons_visible),
|
265 |
gr.update(visible=action_buttons_visible),
|
266 |
gr.update(visible=play_again_visible),
|
@@ -297,8 +346,8 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
297 |
game_state = gr.State(game_instance)
|
298 |
|
299 |
# UI Components
|
300 |
-
game_output = gr.
|
301 |
-
status_output = gr.
|
302 |
|
303 |
with gr.Row(visible=True) as character_selection_buttons:
|
304 |
scott_btn = gr.Button("Play as Scott Pilgrim")
|
|
|
236 |
# Create a single game instance to be managed by gr.State
|
237 |
game_instance = ScottPilgrimGame()
|
238 |
|
239 |
+
# New helper to format the message log into color-coded HTML
|
240 |
+
def _format_log_html(game_state):
|
241 |
+
"""Returns the message log as HTML with basic color-coding."""
|
242 |
+
# Early return for fresh page load
|
243 |
+
if not game_state.message_log:
|
244 |
+
return ""
|
245 |
+
|
246 |
+
player_name = game_state.player.name if game_state.player else ""
|
247 |
+
enemy_name = game_state.current_enemy.name if game_state.current_enemy else ""
|
248 |
+
|
249 |
+
html_lines = []
|
250 |
+
for msg in game_state.message_log:
|
251 |
+
color = "#000000" # default black
|
252 |
+
if player_name and (msg.startswith(player_name) or msg.startswith("You")):
|
253 |
+
color = "#2ECC71" # green for player actions
|
254 |
+
elif enemy_name and msg.startswith(enemy_name):
|
255 |
+
color = "#E74C3C" # red for enemy actions
|
256 |
+
elif msg.startswith("---") or "Congratulations" in msg or "GAME OVER" in msg:
|
257 |
+
color = "#F1C40F" # yellow/gold for system or banner messages
|
258 |
+
html_lines.append(f"<div style='margin-bottom:4px; color:{color}; white-space:pre-wrap;'>{msg}</div>")
|
259 |
+
|
260 |
+
return "".join(html_lines)
|
261 |
+
|
262 |
+
# New helper to build a richer status block with progress bars for HP/XP
|
263 |
+
def _format_status_html(game_state):
|
264 |
+
if not game_state.player:
|
265 |
+
return ""
|
266 |
+
|
267 |
+
player = game_state.player
|
268 |
+
status_html = [
|
269 |
+
f"<h4 style='margin:4px 0'>{player.name} (Lvl {player.level})</h4>",
|
270 |
+
f"HP: <progress value='{player.current_hp}' max='{player.max_hp}' style='width:160px;height:14px;'></progress> {player.current_hp}/{player.max_hp}<br>",
|
271 |
+
f"XP: <progress value='{player.xp}' max='{player.level * 50}' style='width:160px;height:14px;'></progress> {player.xp}/{player.level * 50}<br><br>"
|
272 |
+
]
|
273 |
+
|
274 |
+
if game_state.current_enemy:
|
275 |
+
enemy = game_state.current_enemy
|
276 |
+
status_html.extend([
|
277 |
+
f"<h4 style='margin:4px 0'>{enemy.name}</h4>",
|
278 |
+
f"HP: <progress value='{enemy.current_hp}' max='{enemy.max_hp}' style='width:160px;height:14px;'></progress> {enemy.current_hp}/{enemy.max_hp}"
|
279 |
+
])
|
280 |
+
|
281 |
+
return "".join(status_html)
|
282 |
+
|
283 |
+
# Updated update_ui to output HTML instead of plain text
|
284 |
def update_ui(game_state):
|
285 |
"""
|
286 |
Updates all Gradio UI components based on the current game state.
|
287 |
+
Returns log_html, status_html, and component visibility updates.
|
|
|
288 |
"""
|
289 |
phase = game_state.current_game_phase
|
290 |
+
|
291 |
+
# Special welcome / end-screen messages
|
292 |
+
if phase == "start" and not game_state.message_log:
|
293 |
+
game_state.message_log = [
|
294 |
+
"Welcome to Scott Pilgrim vs. The World: The RPG!",
|
295 |
+
"Choose your hero!"
|
296 |
+
]
|
297 |
+
elif phase == "game_over":
|
298 |
+
game_state.message_log.append("\nGAME OVER! Better luck next time!")
|
299 |
+
elif phase == "win":
|
300 |
+
game_state.message_log.append("\nYOU WON! Thanks for playing!")
|
301 |
+
|
302 |
+
log_html = _format_log_html(game_state)
|
303 |
+
status_html = _format_status_html(game_state)
|
304 |
+
|
305 |
# Configure visibility for each game phase
|
306 |
char_buttons_visible = (phase == "start")
|
307 |
action_buttons_visible = (phase == "combat")
|
308 |
play_again_visible = (phase in ["game_over", "win"])
|
309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
return (
|
311 |
+
log_html,
|
312 |
+
status_html,
|
313 |
gr.update(visible=char_buttons_visible),
|
314 |
gr.update(visible=action_buttons_visible),
|
315 |
gr.update(visible=play_again_visible),
|
|
|
346 |
game_state = gr.State(game_instance)
|
347 |
|
348 |
# UI Components
|
349 |
+
game_output = gr.HTML(label="Game Log")
|
350 |
+
status_output = gr.HTML(label="Current Status")
|
351 |
|
352 |
with gr.Row(visible=True) as character_selection_buttons:
|
353 |
scott_btn = gr.Button("Play as Scott Pilgrim")
|