Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -9,6 +9,11 @@ from pathlib import Path
|
|
9 |
import base64
|
10 |
from io import BytesIO
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
# Fantasy name generator
|
13 |
def generate_fantasy_name():
|
14 |
prefixes = ['Aer', 'Bal', 'Cal', 'Dor', 'El', 'Fae', 'Gor', 'Hel', 'Il', 'Jor',
|
@@ -23,13 +28,16 @@ if 'initialized' not in st.session_state:
|
|
23 |
st.session_state.game_state = {
|
24 |
'players': {},
|
25 |
'chat_messages': [],
|
26 |
-
'tile_map': [],
|
27 |
'last_sync': time.time()
|
28 |
}
|
29 |
st.session_state.player_name = None
|
30 |
st.session_state.character_stats = None
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
-
# Character Stats Generation
|
33 |
def roll_stats():
|
34 |
return {
|
35 |
'STR': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
|
@@ -65,6 +73,9 @@ HP: {stats['HP']}/{stats['MAX_HP']}
|
|
65 |
## Score
|
66 |
Current Score: {stats['score']}
|
67 |
|
|
|
|
|
|
|
68 |
## Session Info
|
69 |
Created: {datetime.fromtimestamp(stats['created_at']).strftime('%Y-%m-%d %H:%M:%S')}
|
70 |
Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
@@ -81,87 +92,37 @@ def load_character_sheet(player_name):
|
|
81 |
return f.read()
|
82 |
return None
|
83 |
|
84 |
-
def
|
85 |
-
"""
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
gameState.velocity.x = speed;
|
116 |
-
break;
|
117 |
-
case 'x':
|
118 |
-
gameState.velocity = { x: 0, y: 0 };
|
119 |
-
break;
|
120 |
-
}
|
121 |
-
gameState.needsSync = true;
|
122 |
-
}
|
123 |
-
|
124 |
-
function updatePosition() {
|
125 |
-
const now = Date.now();
|
126 |
-
const delta = (now - gameState.lastUpdate) / 1000;
|
127 |
-
|
128 |
-
gameState.position.x += gameState.velocity.x * delta;
|
129 |
-
gameState.position.y += gameState.velocity.y * delta;
|
130 |
-
|
131 |
-
// Boundary checks
|
132 |
-
gameState.position.x = Math.max(0, Math.min(gameState.position.x, 19));
|
133 |
-
gameState.position.y = Math.max(0, Math.min(gameState.position.y, 14));
|
134 |
-
|
135 |
-
gameState.lastUpdate = now;
|
136 |
-
|
137 |
-
// Update player marker position
|
138 |
-
const marker = document.querySelector('.player-marker');
|
139 |
-
if (marker) {
|
140 |
-
marker.style.left = `${gameState.position.x * 60 + 25}px`;
|
141 |
-
marker.style.top = `${gameState.position.y * 60 + 25}px`;
|
142 |
-
}
|
143 |
-
}
|
144 |
-
|
145 |
-
function syncWithServer() {
|
146 |
-
if (gameState.needsSync) {
|
147 |
-
// Send position to Streamlit
|
148 |
-
window.parent.postMessage({
|
149 |
-
type: 'streamlit:sync',
|
150 |
-
position: gameState.position
|
151 |
-
}, '*');
|
152 |
-
gameState.needsSync = false;
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
// Initialize game loop
|
157 |
-
setInterval(updatePosition, 16); // ~60 FPS
|
158 |
-
setInterval(syncWithServer, 5000); // Sync every 5 seconds
|
159 |
-
setInterval(updateClock, 1000); // Update clock every second
|
160 |
-
|
161 |
-
// Set up event listeners
|
162 |
-
document.addEventListener('keydown', handleMovement);
|
163 |
-
</script>
|
164 |
-
"""
|
165 |
|
166 |
def main():
|
167 |
# Sidebar for player info and controls
|
@@ -185,7 +146,6 @@ def main():
|
|
185 |
if new_name != st.session_state.player_name:
|
186 |
old_name = st.session_state.player_name
|
187 |
st.session_state.player_name = new_name
|
188 |
-
# Rename character sheet
|
189 |
os.rename(f"characters/{old_name}.md",
|
190 |
f"characters/{new_name}.md")
|
191 |
st.rerun()
|
@@ -195,26 +155,33 @@ def main():
|
|
195 |
if character_sheet:
|
196 |
st.sidebar.markdown(character_sheet)
|
197 |
|
198 |
-
# Movement controls
|
199 |
st.sidebar.markdown("### Movement Controls")
|
200 |
move_cols = st.sidebar.columns(3)
|
201 |
-
move_cols[1].button("⬆️", key="up")
|
|
|
|
|
202 |
cols = st.sidebar.columns(3)
|
203 |
-
cols[0].button("⬅️", key="left")
|
204 |
-
|
205 |
-
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
207 |
|
208 |
# Main game area
|
209 |
st.title("Multiplayer Tile Game")
|
210 |
|
211 |
-
#
|
212 |
-
|
213 |
-
unsafe_allow_html=True)
|
214 |
|
215 |
-
#
|
216 |
-
if st.session_state.
|
217 |
-
st.
|
|
|
218 |
|
219 |
if __name__ == "__main__":
|
220 |
main()
|
|
|
9 |
import base64
|
10 |
from io import BytesIO
|
11 |
|
12 |
+
# Constants for game board
|
13 |
+
GRID_WIDTH = 16
|
14 |
+
GRID_HEIGHT = 9
|
15 |
+
REFRESH_RATE = 5 # seconds
|
16 |
+
|
17 |
# Fantasy name generator
|
18 |
def generate_fantasy_name():
|
19 |
prefixes = ['Aer', 'Bal', 'Cal', 'Dor', 'El', 'Fae', 'Gor', 'Hel', 'Il', 'Jor',
|
|
|
28 |
st.session_state.game_state = {
|
29 |
'players': {},
|
30 |
'chat_messages': [],
|
|
|
31 |
'last_sync': time.time()
|
32 |
}
|
33 |
st.session_state.player_name = None
|
34 |
st.session_state.character_stats = None
|
35 |
+
st.session_state.position = {
|
36 |
+
'x': random.randint(0, GRID_WIDTH - 1),
|
37 |
+
'y': random.randint(0, GRID_HEIGHT - 1)
|
38 |
+
}
|
39 |
+
st.session_state.last_move = time.time()
|
40 |
|
|
|
41 |
def roll_stats():
|
42 |
return {
|
43 |
'STR': sum(sorted([random.randint(1, 6) for _ in range(4)])[1:]),
|
|
|
73 |
## Score
|
74 |
Current Score: {stats['score']}
|
75 |
|
76 |
+
## Position
|
77 |
+
X: {st.session_state.position['x']}, Y: {st.session_state.position['y']}
|
78 |
+
|
79 |
## Session Info
|
80 |
Created: {datetime.fromtimestamp(stats['created_at']).strftime('%Y-%m-%d %H:%M:%S')}
|
81 |
Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
|
92 |
return f.read()
|
93 |
return None
|
94 |
|
95 |
+
def update_position(direction):
|
96 |
+
"""Update player position with wrapping"""
|
97 |
+
if direction == "up":
|
98 |
+
st.session_state.position['y'] = (st.session_state.position['y'] - 1) % GRID_HEIGHT
|
99 |
+
elif direction == "down":
|
100 |
+
st.session_state.position['y'] = (st.session_state.position['y'] + 1) % GRID_HEIGHT
|
101 |
+
elif direction == "left":
|
102 |
+
st.session_state.position['x'] = (st.session_state.position['x'] - 1) % GRID_WIDTH
|
103 |
+
elif direction == "right":
|
104 |
+
st.session_state.position['x'] = (st.session_state.position['x'] + 1) % GRID_WIDTH
|
105 |
+
|
106 |
+
st.session_state.last_move = time.time()
|
107 |
+
if st.session_state.character_stats:
|
108 |
+
save_character_sheet(st.session_state.player_name, st.session_state.character_stats)
|
109 |
+
|
110 |
+
def create_game_board():
|
111 |
+
"""Create and display the game board"""
|
112 |
+
# Create placeholder images for tiles
|
113 |
+
tile_image = Image.new('RGB', (50, 50), color='green')
|
114 |
+
player_image = Image.new('RGB', (50, 50), color='blue')
|
115 |
+
|
116 |
+
# Create columns for each row
|
117 |
+
for y in range(GRID_HEIGHT):
|
118 |
+
cols = st.columns(GRID_WIDTH)
|
119 |
+
for x in range(GRID_WIDTH):
|
120 |
+
# Display player or tile
|
121 |
+
if (x == st.session_state.position['x'] and
|
122 |
+
y == st.session_state.position['y']):
|
123 |
+
cols[x].image(player_image, use_column_width=True)
|
124 |
+
else:
|
125 |
+
cols[x].image(tile_image, use_column_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
def main():
|
128 |
# Sidebar for player info and controls
|
|
|
146 |
if new_name != st.session_state.player_name:
|
147 |
old_name = st.session_state.player_name
|
148 |
st.session_state.player_name = new_name
|
|
|
149 |
os.rename(f"characters/{old_name}.md",
|
150 |
f"characters/{new_name}.md")
|
151 |
st.rerun()
|
|
|
155 |
if character_sheet:
|
156 |
st.sidebar.markdown(character_sheet)
|
157 |
|
158 |
+
# Movement controls
|
159 |
st.sidebar.markdown("### Movement Controls")
|
160 |
move_cols = st.sidebar.columns(3)
|
161 |
+
if move_cols[1].button("⬆️", key="up"):
|
162 |
+
update_position("up")
|
163 |
+
st.rerun()
|
164 |
cols = st.sidebar.columns(3)
|
165 |
+
if cols[0].button("⬅️", key="left"):
|
166 |
+
update_position("left")
|
167 |
+
st.rerun()
|
168 |
+
if cols[1].button("⬇️", key="down"):
|
169 |
+
update_position("down")
|
170 |
+
st.rerun()
|
171 |
+
if cols[2].button("➡️", key="right"):
|
172 |
+
update_position("right")
|
173 |
+
st.rerun()
|
174 |
|
175 |
# Main game area
|
176 |
st.title("Multiplayer Tile Game")
|
177 |
|
178 |
+
# Display game board
|
179 |
+
create_game_board()
|
|
|
180 |
|
181 |
+
# Auto-refresh logic
|
182 |
+
if (time.time() - st.session_state.last_move) > REFRESH_RATE:
|
183 |
+
st.session_state.last_move = time.time()
|
184 |
+
st.rerun()
|
185 |
|
186 |
if __name__ == "__main__":
|
187 |
main()
|