import streamlit as st import os import random import time from PIL import Image import json from datetime import datetime from pathlib import Path # Initialize session state variables if 'game_state' not in st.session_state: st.session_state.game_state = { 'players': {}, 'chat_messages': [], 'tile_map': [], 'current_player': None } if 'player_name' not in st.session_state: st.session_state.player_name = None if 'last_refresh' not in st.session_state: st.session_state.last_refresh = time.time() if 'start_time' not in st.session_state: st.session_state.start_time = None if 'play_duration' not in st.session_state: st.session_state.play_duration = 0 # Utility functions def load_tiles(tiles_path="tiles"): """Load tile images from the specified directory""" tiles = {} if not os.path.exists(tiles_path): os.makedirs(tiles_path) return tiles for file in os.listdir(tiles_path): if file.endswith(('.png', '.jpg', '.jpeg')): tile_name = os.path.splitext(file)[0] tile_path = os.path.join(tiles_path, file) tiles[tile_name] = Image.open(tile_path) return tiles def generate_map(width=20, height=15): """Generate a random tile map""" tile_types = ['grass', 'water', 'rock'] return [[random.choice(tile_types) for _ in range(width)] for _ in range(height)] def save_game_state(): """Save the current game state to a file""" state_file = Path("game_state.json") state_to_save = { 'players': st.session_state.game_state['players'], 'chat_messages': st.session_state.game_state['chat_messages'], 'tile_map': st.session_state.game_state['tile_map'] } with open(state_file, 'w') as f: json.dump(state_to_save, f) def load_game_state(): """Load the game state from file""" state_file = Path("game_state.json") if state_file.exists(): with open(state_file, 'r') as f: loaded_state = json.load(f) st.session_state.game_state.update(loaded_state) def add_chat_message(player_name, message): """Add a message to the chat history""" timestamp = datetime.now().strftime("%H:%M:%S") st.session_state.game_state['chat_messages'].append({ 'player': player_name, 'message': message, 'timestamp': timestamp }) save_game_state() def format_duration(seconds): """Format duration in seconds to HH:MM:SS""" hours = seconds // 3600 minutes = (seconds % 3600) // 60 seconds = seconds % 60 return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}" def check_auto_refresh(): """Check if it's time to refresh the page""" current_time = time.time() if current_time - st.session_state.last_refresh >= 5: # 5-second refresh interval st.session_state.last_refresh = current_time st.rerun() def update_play_duration(): """Update the player's total play duration""" if st.session_state.start_time is not None: current_time = time.time() st.session_state.play_duration = int(current_time - st.session_state.start_time) # Main game UI def main(): st.title("Multiplayer Tile Game") # Player login/join game section if st.session_state.player_name is None: with st.form("join_game"): player_name = st.text_input("Enter your name:") submitted = st.form_submit_button("Join Game") if submitted and player_name: st.session_state.player_name = player_name st.session_state.start_time = time.time() st.session_state.play_duration = 0 st.session_state.game_state['players'][player_name] = { 'position': {'x': 0, 'y': 0}, 'last_active': time.time(), 'score': 0 } st.rerun() else: # Update play duration update_play_duration() # Display play duration st.sidebar.metric("Play Time", format_duration(st.session_state.play_duration)) # Game layout with columns col1, col2 = st.columns([2, 1]) with col1: st.subheader("Game Map") # Load or generate tile map if not st.session_state.game_state['tile_map']: st.session_state.game_state['tile_map'] = generate_map() # Display tile map tiles = load_tiles() if tiles: # Create a placeholder for the game map map_placeholder = st.empty() # Update player position with arrow keys if st.session_state.player_name: player = st.session_state.game_state['players'][st.session_state.player_name] # Movement controls cols = st.columns(4) if cols[0].button("←"): player['position']['x'] = max(0, player['position']['x'] - 1) if cols[1].button("↑"): player['position']['y'] = max(0, player['position']['y'] - 1) if cols[2].button("↓"): player['position']['y'] = min(14, player['position']['y'] + 1) if cols[3].button("→"): player['position']['x'] = min(19, player['position']['x'] + 1) # Display current position st.write(f"Position: ({player['position']['x']}, {player['position']['y']})") else: st.warning("No tile images found. Please add images to the 'tiles' directory.") with col2: st.subheader("Chat Room") # Chat message display chat_container = st.container() with chat_container: for message in st.session_state.game_state['chat_messages'][-50:]: st.text(f"[{message['timestamp']}] {message['player']}: {message['message']}") # Chat input with st.form("chat_form", clear_on_submit=True): message = st.text_input("Message:") if st.form_submit_button("Send") and message: add_chat_message(st.session_state.player_name, message) st.rerun() # Logout button if st.button("Leave Game"): if st.session_state.player_name in st.session_state.game_state['players']: del st.session_state.game_state['players'][st.session_state.player_name] st.session_state.player_name = None st.session_state.start_time = None st.session_state.play_duration = 0 save_game_state() st.rerun() # Auto-refresh check check_auto_refresh() if __name__ == "__main__": load_game_state() main()