LetsMakeGames2 / app.py
awacke1's picture
Update app.py
6cd5904 verified
raw
history blame
7.21 kB
import streamlit as st
import os
import random
import time
from PIL import Image
import json
from datetime import datetime
from pathlib import Path
import base64
from io import BytesIO
import numpy as np
GRID_WIDTH = 16
GRID_HEIGHT = 9
REFRESH_RATE = 10
INTERACTION_RADIUS = 2
POINTS_PER_INTERACTION = 1
@st.cache_resource
def get_game_images():
return {
'tile': Image.new('RGB', (50, 50), color='green'),
'player': Image.new('RGB', (50, 50), color='blue'),
'other_player': Image.new('RGB', (50, 50), color='red')
}
@st.cache_data
def get_name_components():
return {
'prefixes': ['Aer', 'Bal', 'Cal', 'Dor', 'El', 'Fae', 'Gor', 'Hel', 'Il', 'Jor',
'Kal', 'Lyr', 'Mel', 'Nym', 'Oro', 'Pyr', 'Qar', 'Ryn', 'Syl', 'Tyr'],
'suffixes': ['ian', 'or', 'ion', 'us', 'ix', 'ar', 'en', 'yr', 'el', 'an',
'is', 'ax', 'on', 'ir', 'ex', 'az', 'er', 'eth', 'ys', 'ix']
}
@st.cache_data(ttl=2)
def load_all_players(timestamp):
players = {}
if os.path.exists('players'):
for filename in os.listdir('players'):
if filename.endswith('.json'):
with open(f"players/{filename}", 'r') as f:
try:
player_data = json.load(f)
if time.time() - player_data['last_update'] < 60:
players[player_data['name']] = player_data
except json.JSONDecodeError:
continue
return {'players': players, 'last_update': time.time()}
def create_sync_mechanism():
sync_js = """
<script>
function updateGameState() {
const timestamp = Date.now();
window.parent.document.querySelector('.stApp').classList.add('refreshing');
setTimeout(() => window.location.reload(), 100);
}
function displayCharacterSheet(playerData) {
const sidebar = window.parent.document.querySelector('[data-testid="stSidebar"]');
if (sidebar && playerData) {
const statsDiv = document.createElement('div');
statsDiv.innerHTML = `
<div style="padding: 10px; margin: 5px; border: 1px solid #ccc; border-radius: 5px;">
<h3>${playerData.name}</h3>
<p>Score: ${playerData.stats.score}</p>
<p>HP: ${playerData.stats.HP}/${playerData.stats.MAX_HP}</p>
<p>STR: ${playerData.stats.STR}</p>
<p>DEX: ${playerData.stats.DEX}</p>
<p>CON: ${playerData.stats.CON}</p>
<p>INT: ${playerData.stats.INT}</p>
<p>WIS: ${playerData.stats.WIS}</p>
<p>CHA: ${playerData.stats.CHA}</p>
</div>
`;
}
}
function startSync() {
// Update game state every 10 seconds
setInterval(updateGameState, 10000);
// Handle visibility changes
document.addEventListener('visibilitychange', function() {
if (!document.hidden) {
updateGameState();
}
});
// Handle focus changes
window.addEventListener('focus', updateGameState);
}
if (document.readyState === 'complete') {
startSync();
} else {
window.addEventListener('load', startSync);
}
</script>
"""
st.components.v1.html(sync_js, height=0)
def show_character_sheet(player_data):
st.sidebar.markdown("### Character Sheet")
st.sidebar.markdown(f"""
**Name:** {player_data['name']}
**Stats:**
- HP: {player_data['stats']['HP']}/{player_data['stats']['MAX_HP']}
- STR: {player_data['stats']['STR']}
- DEX: {player_data['stats']['DEX']}
- CON: {player_data['stats']['CON']}
- INT: {player_data['stats']['INT']}
- WIS: {player_data['stats']['WIS']}
- CHA: {player_data['stats']['CHA']}
**Score:** {player_data['stats']['score']}
""")
[Previous functions remain the same: generate_fantasy_name, load_game_state, save_game_state, calculate_distance, update_position, etc.]
def main():
create_sync_mechanism()
update_nearby_players()
st.sidebar.title("Player Info")
current_time = time.time()
all_players = load_all_players(current_time)['players']
if st.session_state.player_name is None:
default_name = generate_fantasy_name()
player_name = st.sidebar.text_input("Enter your name or use generated name:", value=default_name)
if st.sidebar.button("Start Playing"):
st.session_state.player_name = player_name
if st.session_state.character_stats is None:
st.session_state.character_stats = {
'STR': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'DEX': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'CON': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'INT': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'WIS': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'CHA': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
'HP': random.randint(1, 20) * 2 + random.randint(1, 20),
'MAX_HP': 40,
'score': 0,
'created_at': time.time()
}
save_player_state()
st.rerun()
else:
show_character_sheet({'name': st.session_state.player_name, 'stats': st.session_state.character_stats})
st.sidebar.markdown("### Other Players")
for player_name, player_data in all_players.items():
if player_name != st.session_state.player_name:
show_character_sheet(player_data)
st.sidebar.markdown("### Movement Controls")
move_cols = st.sidebar.columns(3)
if move_cols[1].button("⬆️", key="up"):
update_position("up")
st.rerun()
cols = st.sidebar.columns(3)
if cols[0].button("⬅️", key="left"):
update_position("left")
st.rerun()
if cols[1].button("⬇️", key="down"):
update_position("down")
st.rerun()
if cols[2].button("➡️", key="right"):
update_position("right")
st.rerun()
if st.sidebar.button("Clear Game State"):
st.query_params.clear()
clear_caches()
st.rerun()
st.title("Multiplayer Tile Game")
create_game_board()
if (time.time() - st.session_state.last_move) > REFRESH_RATE:
st.session_state.last_move = time.time()
save_player_state()
st.rerun()
if __name__ == "__main__":
main()