sunbal7 commited on
Commit
4541cc1
ยท
verified ยท
1 Parent(s): 9f919e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +621 -138
app.py CHANGED
@@ -9,6 +9,10 @@ import numpy as np
9
  from transformers import pipeline
10
  import base64
11
  import re
 
 
 
 
12
 
13
  # Set up the page
14
  st.set_page_config(
@@ -178,10 +182,37 @@ st.markdown("""
178
  margin: 0 auto 10px;
179
  }
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  /* Progress bar styling */
182
  .stProgress > div > div > div {
183
  background-color: #ff5722 !important;
184
  }
 
 
 
 
 
 
 
 
 
 
 
185
  </style>
186
  """, unsafe_allow_html=True)
187
 
@@ -234,10 +265,10 @@ def create_storyboard_image(text, width=400, height=300):
234
 
235
  return img
236
 
237
- def generate_sprite_animation(story, character="spaceship", theme="space", num_frames=4):
238
  """Generate a sprite-based animation from story"""
239
  frames = []
240
- width, height = 300, 200
241
 
242
  for i in range(num_frames):
243
  # Create base image with theme
@@ -245,14 +276,20 @@ def generate_sprite_animation(story, character="spaceship", theme="space", num_f
245
  bg_color = (0, 0, 30)
246
  star_color = (255, 255, 255)
247
  elif theme == "jungle":
248
- bg_color = (0, 100, 0)
249
- star_color = None # No stars in jungle
250
  elif theme == "medieval":
251
  bg_color = (139, 69, 19)
252
  star_color = None
253
  elif theme == "underwater":
254
  bg_color = (0, 105, 148)
255
  star_color = None
 
 
 
 
 
 
256
  else:
257
  bg_color = (0, 0, 30)
258
  star_color = (255, 255, 255)
@@ -260,109 +297,391 @@ def generate_sprite_animation(story, character="spaceship", theme="space", num_f
260
  img = Image.new('RGB', (width, height), color=bg_color)
261
  draw = ImageDraw.Draw(img)
262
 
263
- # Draw stars for space theme
264
- if star_color:
265
- for _ in range(30):
 
266
  x = random.randint(0, width)
267
  y = random.randint(0, height)
268
  draw.ellipse([x, y, x+2, y+2], fill=star_color)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  # Draw moving elements based on frame
271
  if character == "spaceship":
272
- ship_x = 50 + i * 60
273
- ship_y = 80
274
- draw.polygon([(ship_x, ship_y), (ship_x+30, ship_y),
275
- (ship_x+15, ship_y-20)], fill=(169, 169, 169))
 
 
 
276
 
277
  if "shoot" in story.lower() and i > 1:
278
  for j in range(3):
279
- laser_x = ship_x + 15
280
- laser_y = ship_y - 20 + j*5
281
- draw.line([(laser_x, laser_y), (width, laser_y)], fill=(255, 0, 0), width=2)
282
 
283
  elif character == "dragon":
284
- dragon_x = 50 + i * 40
285
- dragon_y = 100
286
- # Draw dragon body
287
- draw.ellipse([dragon_x, dragon_y, dragon_x+40, dragon_y+20], fill=(178, 34, 34))
288
- # Draw dragon head
289
- draw.ellipse([dragon_x+30, dragon_y-5, dragon_x+50, dragon_y+15], fill=(178, 34, 34))
290
- # Draw wings
291
- draw.ellipse([dragon_x+10, dragon_y-15, dragon_x+30, dragon_y], fill=(138, 43, 226))
292
 
293
  if "fire" in story.lower() and i > 0:
294
  for j in range(5):
295
- flame_x = dragon_x + 50
296
- flame_y = dragon_y + 5 - j*5
297
- flame_size = random.randint(5, 15)
298
  draw.ellipse([flame_x, flame_y, flame_x+flame_size, flame_y+flame_size],
299
  fill=(255, random.randint(100, 200), 0))
300
 
301
  elif character == "knight":
302
- knight_x = 50 + i * 40
303
- knight_y = 120
304
- # Draw knight body
305
- draw.rectangle([knight_x, knight_y, knight_x+20, knight_y+40], fill=(70, 70, 70))
306
- # Draw knight head
307
- draw.ellipse([knight_x+5, knight_y-15, knight_x+15, knight_y-5], fill=(210, 180, 140))
308
- # Draw sword
309
- draw.rectangle([knight_x+15, knight_y+10, knight_x+25, knight_y+15], fill=(192, 192, 192))
310
- draw.polygon([(knight_x+25, knight_y+12), (knight_x+35, knight_y+10), (knight_x+35, knight_y+15)], fill=(192, 192, 192))
 
 
311
 
312
  if "attack" in story.lower() and i % 2 == 1:
313
  # Draw sword swing
314
- draw.line([(knight_x+25, knight_y+12), (knight_x+45, knight_y-10)], fill=(255, 255, 0), width=2)
315
 
316
  elif character == "mermaid":
317
- mermaid_x = 50 + i * 40
318
- mermaid_y = 120
319
- # Draw mermaid tail
320
- draw.ellipse([mermaid_x, mermaid_y, mermaid_x+30, mermaid_y+20], fill=(255, 105, 180))
321
- # Draw mermaid body
322
- draw.ellipse([mermaid_x+5, mermaid_y-20, mermaid_x+25, mermaid_y], fill=(255, 218, 185))
323
- # Draw hair
324
- draw.ellipse([mermaid_x-5, mermaid_y-25, mermaid_x+30, mermaid_y-15], fill=(255, 215, 0))
325
 
326
  if "swim" in story.lower() and i > 0:
327
  # Draw bubbles
328
  for j in range(3):
329
- bubble_x = mermaid_x + random.randint(0, 30)
330
- bubble_y = mermaid_y - random.randint(10, 30)
331
- draw.ellipse([bubble_x, bubble_y, bubble_x+5, bubble_y+5], fill=(173, 216, 230))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
  # Draw enemies based on theme
334
  if theme == "space" and "alien" in story.lower():
335
- alien_x = 200
336
- alien_y = 100 - i*10
337
- draw.ellipse([alien_x, alien_y, alien_x+20, alien_y+20], fill=(50, 205, 50))
338
- draw.ellipse([alien_x+5, alien_y+5, alien_x+7, alien_y+7], fill=(0, 0, 0))
339
- draw.ellipse([alien_x+13, alien_y+5, alien_x+15, alien_y+7], fill=(0, 0, 0))
 
340
 
341
  elif theme == "jungle" and "snake" in story.lower():
342
- snake_x = 200
343
- snake_y = 150 - i*5
344
- for segment in range(5):
345
- offset = segment * 5
346
- draw.ellipse([snake_x+offset, snake_y+offset, snake_x+offset+15, snake_y+offset+15], fill=(0, 128, 0))
347
 
348
  elif theme == "medieval" and "dragon" in story.lower() and character != "dragon":
349
- dragon_x = 220
350
- dragon_y = 80
351
- draw.ellipse([dragon_x, dragon_y, dragon_x+40, dragon_y+20], fill=(178, 34, 34))
352
- draw.line([(dragon_x+40, dragon_y+10), (dragon_x+60, dragon_y)], fill=(178, 34, 34), width=3)
353
 
354
  elif theme == "underwater" and "shark" in story.lower():
355
- shark_x = 220
356
- shark_y = 80 + i*10
357
- # Draw shark body
358
- draw.ellipse([shark_x, shark_y, shark_x+60, shark_y+30], fill=(169, 169, 169))
359
- # Draw shark fin
360
- draw.polygon([(shark_x+40, shark_y), (shark_x+50, shark_y-20), (shark_x+60, shark_y)], fill=(169, 169, 169))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
 
362
  frames.append(img)
363
 
364
  return frames
365
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  def generate_code_explanation(story, explanation_generator):
367
  """Generate code explanation using open-source model"""
368
  try:
@@ -391,14 +710,16 @@ def extract_story_elements(story, ner_model, classifier):
391
 
392
  # Find hero based on keywords and entities
393
  hero_keywords = {
394
- "spaceship": ["spaceship", "rocket", "ship", "alien", "planet", "star"],
395
  "dragon": ["dragon", "monster", "creature", "beast", "wyvern"],
396
- "knight": ["knight", "warrior", "prince", "princess", "king", "queen", "sword"],
397
- "mermaid": ["mermaid", "merman", "sea", "ocean", "underwater", "fish"]
 
 
398
  }
399
 
400
  # Find world based on keywords and classification
401
- world_labels = ["space", "jungle", "medieval", "underwater"]
402
 
403
  # Find hero by keywords
404
  story_lower = story.lower()
@@ -419,6 +740,10 @@ def extract_story_elements(story, ner_model, classifier):
419
  hero = "knight"
420
  elif "mermaid" in story_lower or "sea" in story_lower:
421
  hero = "mermaid"
 
 
 
 
422
 
423
  # Classify world
424
  result = classifier(story, world_labels)
@@ -429,10 +754,14 @@ def extract_story_elements(story, ner_model, classifier):
429
  world = "underwater"
430
  if "forest" in story_lower or "jungle" in story_lower:
431
  world = "jungle"
432
- if "castle" in story_lower or "kingdom" in story_lower or "dragon" in story_lower:
433
  world = "medieval"
434
  if "space" in story_lower or "alien" in story_lower or "planet" in story_lower:
435
  world = "space"
 
 
 
 
436
 
437
  return hero, world
438
 
@@ -440,6 +769,16 @@ def extract_story_elements(story, ner_model, classifier):
440
  st.error(f"Error analyzing story: {str(e)}")
441
  return "spaceship", "space"
442
 
 
 
 
 
 
 
 
 
 
 
443
  # Header section
444
  st.markdown('<div class="header">CodeTales โœจ</div>', unsafe_allow_html=True)
445
  st.markdown('<div class="subheader">Storytime + Coding Magic</div>', unsafe_allow_html=True)
@@ -483,20 +822,28 @@ if 'xp' not in st.session_state:
483
  st.session_state.xp = 0
484
  if 'analyzed' not in st.session_state:
485
  st.session_state.analyzed = False
 
 
 
 
486
 
487
  # Character and theme mapping
488
  characters = {
489
  "spaceship": "๐Ÿš€ Spaceship",
490
  "dragon": "๐Ÿ‰ Dragon",
491
  "knight": "๐Ÿ›ก๏ธ Knight",
492
- "mermaid": "๐Ÿงœโ€โ™€๏ธ Mermaid"
 
 
493
  }
494
 
495
  themes = {
496
  "space": "๐ŸŒŒ Space",
497
  "jungle": "๐ŸŒฟ Jungle",
498
  "medieval": "๐Ÿฐ Medieval",
499
- "underwater": "๐ŸŒŠ Underwater"
 
 
500
  }
501
 
502
  # Main content
@@ -540,25 +887,41 @@ with col1:
540
  st.markdown(f'<div class="world-suggestion">Your World: {themes[st.session_state.selected_theme]}</div>',
541
  unsafe_allow_html=True)
542
 
543
- st.info("๐Ÿ’ก The AI chose these based on your story! Click Generate Animation when ready.")
 
 
 
 
 
 
 
 
544
 
545
  # Generate animation button
546
- if st.button("๐ŸŽฌ Generate Animation!", use_container_width=True, key="generate", type="primary"):
547
  st.session_state.animation_generated = True
548
- with st.spinner("๐Ÿง™โ€โ™‚๏ธ Creating your animation..."):
549
  # Generate animation frames
550
  st.session_state.animation_frames = generate_sprite_animation(
551
  story_text,
552
  character=st.session_state.selected_character,
553
- theme=st.session_state.selected_theme
 
554
  )
555
 
556
  # Generate code explanation
557
  st.session_state.code_explanation = generate_code_explanation(story_text, explanation_generator)
558
 
 
 
 
 
 
 
 
559
  # Update user progress
560
  st.session_state.story_count += 1
561
- st.session_state.xp += 20
562
 
563
  # Check for level up
564
  if st.session_state.xp >= 100:
@@ -575,12 +938,8 @@ with col2:
575
  st.markdown("### ๐ŸŽฎ Step 3: Your Animation")
576
  # Display animation frames
577
  st.markdown("**Your Story Comes to Life!**")
578
- cols = st.columns(len(st.session_state.animation_frames))
579
- for i, frame in enumerate(st.session_state.animation_frames):
580
- with cols[i]:
581
- st.image(frame, caption=f"Frame {i+1}", use_container_width=True)
582
 
583
- # Create an animated GIF
584
  gif_buffer = BytesIO()
585
  st.session_state.animation_frames[0].save(
586
  gif_buffer,
@@ -590,10 +949,13 @@ with col2:
590
  duration=500,
591
  loop=0
592
  )
593
- gif_data = gif_buffer.getvalue()
 
 
 
594
  st.download_button(
595
  label="โฌ‡๏ธ Download Animation",
596
- data=gif_data,
597
  file_name="your_story.gif",
598
  mime="image/gif",
599
  use_container_width=True
@@ -606,7 +968,7 @@ with col2:
606
  st.markdown("### ๐ŸŽฎ Step 3: Your Animation")
607
  st.image("https://img.freepik.com/free-vector/hand-drawn-colorful-space-background_23-2148821798.jpg",
608
  use_container_width=True)
609
- st.info("๐Ÿ‘† Click 'Generate Animation' to bring your story to life!")
610
  elif story_text:
611
  st.markdown("### ๐ŸŽฎ Your Animation Will Appear Here")
612
  preview_img = create_storyboard_image(story_text)
@@ -619,65 +981,161 @@ with col2:
619
 
620
  st.markdown('</div>', unsafe_allow_html=True)
621
 
622
- # Tavus explanation section
623
  if st.session_state.animation_generated and st.session_state.story_text:
624
  st.markdown('<div class="robot-speech">', unsafe_allow_html=True)
625
  st.markdown("### ๐Ÿค– Step 4: Tavus the Robot Teacher Explains Coding")
626
 
627
- # Extract action words from story
628
- action_words = ["zoom", "shoot", "fly", "move", "jump", "run", "attack",
629
- "laser", "alien", "spaceship", "dragon", "fire", "hero",
630
- "sword", "castle", "escape", "fight", "win", "swim", "dive"]
631
- found_actions = [word for word in action_words if re.search(r'\b' + word + r'\b', st.session_state.story_text.lower())]
632
-
633
- if found_actions:
634
- # Create explanation based on found words
635
- st.markdown("#### ๐Ÿงฉ Story Actions to Code Concepts")
636
- cols = st.columns(3)
637
- action_colors = ["#ff6b6b", "#4ecdc4", "#ffd166", "#06d6a0", "#118ab2"]
638
-
639
- for i, action in enumerate(found_actions[:6]):
640
- with cols[i % 3]:
641
- color = action_colors[i % len(action_colors)]
642
- st.markdown(f'<div style="background:{color}; color:white; border-radius:10px; padding:10px; text-align:center;">', unsafe_allow_html=True)
643
- st.markdown(f"**{action.capitalize()}**")
644
-
645
- # Add code snippets based on action
646
- if action == "zoom":
647
- st.code("hero.move_fast(10)", language="python")
648
- elif action == "shoot":
649
- st.code("laser = hero.create_weapon()", language="python")
650
- elif action == "fly":
651
- st.code("hero.fly(height=100)", language="python")
652
- elif action == "move":
653
- st.code("hero.move(direction='right')", language="python")
654
- elif action == "jump":
655
- st.code("hero.jump(power=20)", language="python")
656
- elif action == "run":
657
- st.code("hero.speed = hero.speed * 2", language="python")
658
- elif action == "attack":
659
- st.code("hero.attack(enemy)", language="python")
660
- elif action == "swim":
661
- st.code("hero.swim(speed=5)", language="python")
662
- elif action == "dive":
663
- st.code("hero.dive(depth=30)", language="python")
664
- else:
665
- st.code(f"hero.{action}()", language="python")
666
-
667
- st.markdown("</div>", unsafe_allow_html=True)
668
-
669
- st.markdown("---")
670
-
671
- # Show AI-generated explanation
672
  st.markdown("### ๐Ÿง  AI-Powered Explanation:")
673
  st.write(st.session_state.code_explanation)
674
 
675
- st.markdown("#### ๐Ÿ’ก Remember:")
676
- st.markdown("""
677
- - Every action in your story becomes code
678
- - Code is just instructions for computers
679
- - You're already thinking like a coder!
680
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
 
682
  st.markdown("</div>", unsafe_allow_html=True)
683
 
@@ -687,6 +1145,30 @@ if 'new_level' in st.session_state and st.session_state.new_level:
687
  st.success(f"๐ŸŒŸ Level Up! You're now Level {st.session_state.level}!")
688
  st.session_state.new_level = False
689
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
690
  # Benefits section
691
  st.markdown("""
692
  ## โค Why Kids & Parents Love CodeTales
@@ -698,6 +1180,7 @@ st.markdown("""
698
  | ๐ŸŽฎ Interactive game creation | โž— Reinforces STEM fundamentals |
699
  | ๐Ÿ˜„ Fun characters and worlds | ๐Ÿงฉ Encourages logical reasoning |
700
  | ๐ŸŒŸ Unlock new levels | ๐Ÿ“ˆ Tracks learning progress |
 
701
  """)
702
 
703
  # Footer
 
9
  from transformers import pipeline
10
  import base64
11
  import re
12
+ import pygame
13
+ import sys
14
+ import os
15
+ import tempfile
16
 
17
  # Set up the page
18
  st.set_page_config(
 
182
  margin: 0 auto 10px;
183
  }
184
 
185
+ .coding-tutorial {
186
+ background: rgba(41, 128, 185, 0.9);
187
+ border-radius: 20px;
188
+ padding: 1.5rem;
189
+ margin-top: 2rem;
190
+ color: white;
191
+ border: 3px solid #2980b9;
192
+ }
193
+
194
+ .code-playground {
195
+ background: rgba(44, 62, 80, 0.9);
196
+ border-radius: 15px;
197
+ padding: 1.5rem;
198
+ margin-top: 1.5rem;
199
+ }
200
+
201
  /* Progress bar styling */
202
  .stProgress > div > div > div {
203
  background-color: #ff5722 !important;
204
  }
205
+
206
+ .level-indicator {
207
+ background: rgba(52, 152, 219, 0.9);
208
+ color: white;
209
+ border-radius: 50px;
210
+ padding: 0.5rem 1rem;
211
+ display: inline-block;
212
+ margin-bottom: 1rem;
213
+ font-weight: bold;
214
+ border: 2px solid #2c3e50;
215
+ }
216
  </style>
217
  """, unsafe_allow_html=True)
218
 
 
265
 
266
  return img
267
 
268
+ def generate_sprite_animation(story, character="spaceship", theme="space", num_frames=8):
269
  """Generate a sprite-based animation from story"""
270
  frames = []
271
+ width, height = 400, 300
272
 
273
  for i in range(num_frames):
274
  # Create base image with theme
 
276
  bg_color = (0, 0, 30)
277
  star_color = (255, 255, 255)
278
  elif theme == "jungle":
279
+ bg_color = (34, 139, 34)
280
+ star_color = None
281
  elif theme == "medieval":
282
  bg_color = (139, 69, 19)
283
  star_color = None
284
  elif theme == "underwater":
285
  bg_color = (0, 105, 148)
286
  star_color = None
287
+ elif theme == "desert":
288
+ bg_color = (210, 180, 140)
289
+ star_color = None
290
+ elif theme == "arctic":
291
+ bg_color = (240, 248, 255)
292
+ star_color = None
293
  else:
294
  bg_color = (0, 0, 30)
295
  star_color = (255, 255, 255)
 
297
  img = Image.new('RGB', (width, height), color=bg_color)
298
  draw = ImageDraw.Draw(img)
299
 
300
+ # Draw background elements
301
+ if theme == "space":
302
+ # Stars
303
+ for _ in range(50):
304
  x = random.randint(0, width)
305
  y = random.randint(0, height)
306
  draw.ellipse([x, y, x+2, y+2], fill=star_color)
307
+
308
+ # Planets
309
+ draw.ellipse([300, 30, 380, 110], fill=(255, 165, 0), outline=(255, 215, 0), width=2)
310
+
311
+ elif theme == "jungle":
312
+ # Trees
313
+ for x in [50, 150, 250, 350]:
314
+ draw.rectangle([x, 150, x+20, 250], fill=(101, 67, 33))
315
+ draw.ellipse([x-20, 120, x+40, 180], fill=(34, 139, 34))
316
+
317
+ # Sun
318
+ draw.ellipse([320, 30, 380, 90], fill=(255, 215, 0))
319
+
320
+ elif theme == "medieval":
321
+ # Castle
322
+ draw.rectangle([250, 100, 350, 250], fill=(169, 169, 169))
323
+ draw.rectangle([280, 150, 320, 250], fill=(105, 105, 105))
324
+ for x in [260, 300, 340]:
325
+ draw.polygon([(x, 80), (x-20, 100), (x+20, 100)], fill=(220, 20, 60))
326
+
327
+ # Mountains
328
+ draw.polygon([(0, 250), (100, 100), (200, 250)], fill=(120, 120, 120))
329
+
330
+ elif theme == "underwater":
331
+ # Seaweed
332
+ for x in [50, 150, 250, 350]:
333
+ draw.line([(x, 250), (x, 180)], fill=(0, 128, 0), width=5)
334
+ draw.ellipse([x-20, 170, x+20, 190], fill=(0, 128, 0))
335
+
336
+ # Bubbles
337
+ for _ in range(20):
338
+ x = random.randint(0, width)
339
+ y = random.randint(0, 200)
340
+ size = random.randint(5, 15)
341
+ draw.ellipse([x, y, x+size, y+size], fill=(173, 216, 230), outline=(70, 130, 180))
342
+
343
+ elif theme == "desert":
344
+ # Sand dunes
345
+ for x in [0, 100, 200, 300]:
346
+ draw.arc([x, 150, x+200, 300], 180, 360, fill=(210, 180, 140), width=50)
347
+
348
+ # Sun
349
+ draw.ellipse([300, 30, 370, 100], fill=(255, 140, 0))
350
+
351
+ elif theme == "arctic":
352
+ # Snowy ground
353
+ draw.rectangle([0, 200, width, height], fill=(255, 255, 255))
354
+
355
+ # Snowflakes
356
+ for _ in range(50):
357
+ x = random.randint(0, width)
358
+ y = random.randint(0, 180)
359
+ draw.ellipse([x, y, x+3, y+3], fill=(255, 255, 255))
360
+
361
+ # Mountains
362
+ draw.polygon([(0, 250), (100, 100), (200, 250)], fill=(200, 200, 200))
363
 
364
  # Draw moving elements based on frame
365
  if character == "spaceship":
366
+ ship_x = 50 + i * 40
367
+ ship_y = 120
368
+ # Spaceship body
369
+ draw.polygon([(ship_x, ship_y), (ship_x+50, ship_y),
370
+ (ship_x+25, ship_y-30)], fill=(169, 169, 169))
371
+ # Spaceship details
372
+ draw.rectangle([ship_x+20, ship_y-10, ship_x+30, ship_y], fill=(0, 191, 255))
373
 
374
  if "shoot" in story.lower() and i > 1:
375
  for j in range(3):
376
+ laser_x = ship_x + 25
377
+ laser_y = ship_y - 30 + j*5
378
+ draw.line([(laser_x, laser_y), (width, laser_y)], fill=(255, 0, 0), width=3)
379
 
380
  elif character == "dragon":
381
+ dragon_x = 50 + i * 30
382
+ dragon_y = 140
383
+ # Dragon body
384
+ draw.ellipse([dragon_x, dragon_y, dragon_x+60, dragon_y+30], fill=(178, 34, 34))
385
+ # Dragon head
386
+ draw.ellipse([dragon_x+50, dragon_y+5, dragon_x+70, dragon_y+25], fill=(178, 34, 34))
387
+ # Dragon wings
388
+ draw.ellipse([dragon_x+10, dragon_y-20, dragon_x+40, dragon_y+10], fill=(138, 43, 226))
389
 
390
  if "fire" in story.lower() and i > 0:
391
  for j in range(5):
392
+ flame_x = dragon_x + 70
393
+ flame_y = dragon_y + 15 - j*5
394
+ flame_size = random.randint(8, 18)
395
  draw.ellipse([flame_x, flame_y, flame_x+flame_size, flame_y+flame_size],
396
  fill=(255, random.randint(100, 200), 0))
397
 
398
  elif character == "knight":
399
+ knight_x = 50 + i * 30
400
+ knight_y = 150
401
+ # Knight body
402
+ draw.rectangle([knight_x, knight_y, knight_x+25, knight_y+50], fill=(70, 70, 70))
403
+ # Knight head
404
+ draw.ellipse([knight_x+5, knight_y-15, knight_x+20, knight_y], fill=(210, 180, 140))
405
+ # Knight helmet
406
+ draw.arc([knight_x, knight_y-20, knight_x+25, knight_y], 0, 180, fill=(50, 50, 50), width=3)
407
+ # Sword
408
+ draw.rectangle([knight_x+20, knight_y+10, knight_x+30, knight_y+15], fill=(192, 192, 192))
409
+ draw.polygon([(knight_x+30, knight_y+12), (knight_x+40, knight_y+10), (knight_x+40, knight_y+15)], fill=(192, 192, 192))
410
 
411
  if "attack" in story.lower() and i % 2 == 1:
412
  # Draw sword swing
413
+ draw.line([(knight_x+30, knight_y+12), (knight_x+60, knight_y-20)], fill=(255, 255, 0), width=3)
414
 
415
  elif character == "mermaid":
416
+ mermaid_x = 50 + i * 30
417
+ mermaid_y = 150
418
+ # Mermaid tail
419
+ draw.ellipse([mermaid_x, mermaid_y, mermaid_x+40, mermaid_y+30], fill=(255, 105, 180))
420
+ # Mermaid body
421
+ draw.ellipse([mermaid_x+10, mermaid_y-30, mermaid_x+30, mermaid_y], fill=(255, 218, 185))
422
+ # Mermaid hair
423
+ draw.ellipse([mermaid_x-10, mermaid_y-35, mermaid_x+40, mermaid_y-20], fill=(255, 215, 0))
424
 
425
  if "swim" in story.lower() and i > 0:
426
  # Draw bubbles
427
  for j in range(3):
428
+ bubble_x = mermaid_x + random.randint(0, 40)
429
+ bubble_y = mermaid_y - random.randint(20, 40)
430
+ draw.ellipse([bubble_x, bubble_y, bubble_x+8, bubble_y+8], fill=(173, 216, 230))
431
+
432
+ elif character == "robot":
433
+ robot_x = 50 + i * 35
434
+ robot_y = 150
435
+ # Robot body
436
+ draw.rectangle([robot_x, robot_y, robot_x+30, robot_y+50], fill=(100, 100, 100))
437
+ # Robot head
438
+ draw.rectangle([robot_x-5, robot_y-20, robot_x+35, robot_y], fill=(150, 150, 150))
439
+ # Robot eyes
440
+ draw.ellipse([robot_x+5, robot_y-15, robot_x+10, robot_y-10], fill=(0, 255, 0))
441
+ draw.ellipse([robot_x+20, robot_y-15, robot_x+25, robot_y-10], fill=(0, 255, 0))
442
+ # Robot arms
443
+ draw.rectangle([robot_x-10, robot_y+10, robot_x, robot_y+20], fill=(100, 100, 100))
444
+ draw.rectangle([robot_x+30, robot_y+10, robot_x+40, robot_y+20], fill=(100, 100, 100))
445
+
446
+ if "laser" in story.lower() and i > 1:
447
+ draw.line([(robot_x+40, robot_y+15), (width, robot_y+15)], fill=(0, 255, 0), width=3)
448
+
449
+ elif character == "unicorn":
450
+ unicorn_x = 50 + i * 30
451
+ unicorn_y = 150
452
+ # Unicorn body
453
+ draw.ellipse([unicorn_x, unicorn_y, unicorn_x+40, unicorn_y+20], fill=(255, 240, 245))
454
+ # Unicorn head
455
+ draw.ellipse([unicorn_x+30, unicorn_y-5, unicorn_x+50, unicorn_y+15], fill=(255, 240, 245))
456
+ # Unicorn horn
457
+ draw.polygon([(unicorn_x+40, unicorn_y-10), (unicorn_x+45, unicorn_y-30), (unicorn_x+50, unicorn_y-10)], fill=(255, 215, 0))
458
+ # Unicorn mane
459
+ for j in range(5):
460
+ color = random.choice(['#FF69B4', '#9370DB', '#87CEFA'])
461
+ draw.ellipse([unicorn_x+25+j*3, unicorn_y-10-j*2, unicorn_x+35+j*3, unicorn_y+j*2], fill=color)
462
 
463
  # Draw enemies based on theme
464
  if theme == "space" and "alien" in story.lower():
465
+ alien_x = 300
466
+ alien_y = 120 - i*5
467
+ draw.ellipse([alien_x, alien_y, alien_x+30, alien_y+30], fill=(50, 205, 50))
468
+ draw.ellipse([alien_x+7, alien_y+8, alien_x+12, alien_y+13], fill=(0, 0, 0))
469
+ draw.ellipse([alien_x+18, alien_y+8, alien_x+23, alien_y+13], fill=(0, 0, 0))
470
+ draw.arc([alien_x+7, alien_y+15, alien_x+23, alien_y+25], 0, 180, fill=(0, 0, 0), width=2)
471
 
472
  elif theme == "jungle" and "snake" in story.lower():
473
+ snake_x = 300
474
+ snake_y = 180 - i*5
475
+ for segment in range(8):
476
+ offset = segment * 8
477
+ draw.ellipse([snake_x+offset, snake_y+offset, snake_x+offset+20, snake_y+offset+20], fill=(0, 128, 0))
478
 
479
  elif theme == "medieval" and "dragon" in story.lower() and character != "dragon":
480
+ dragon_x = 250
481
+ dragon_y = 100
482
+ draw.ellipse([dragon_x, dragon_y, dragon_x+50, dragon_y+25], fill=(178, 34, 34))
483
+ draw.line([(dragon_x+50, dragon_y+12), (dragon_x+80, dragon_y)], fill=(178, 34, 34), width=4)
484
 
485
  elif theme == "underwater" and "shark" in story.lower():
486
+ shark_x = 250
487
+ shark_y = 100 + i*8
488
+ # Shark body
489
+ draw.ellipse([shark_x, shark_y, shark_x+80, shark_y+40], fill=(169, 169, 169))
490
+ # Shark fin
491
+ draw.polygon([(shark_x+60, shark_y), (shark_x+70, shark_y-30), (shark_x+80, shark_y)], fill=(169, 169, 169))
492
+
493
+ elif theme == "desert" and "scorpion" in story.lower():
494
+ scorpion_x = 300
495
+ scorpion_y = 200
496
+ # Scorpion body
497
+ draw.ellipse([scorpion_x, scorpion_y, scorpion_x+40, scorpion_y+20], fill=(165, 42, 42))
498
+ # Scorpion tail
499
+ draw.line([(scorpion_x+40, scorpion_y+10), (scorpion_x+60, scorpion_y-10)], fill=(165, 42, 42), width=3)
500
+ # Scorpion claws
501
+ draw.line([(scorpion_x, scorpion_y+5), (scorpion_x-15, scorpion_y)], fill=(165, 42, 42), width=3)
502
+ draw.line([(scorpion_x, scorpion_y+15), (scorpion_x-15, scorpion_y+20)], fill=(165, 42, 42), width=3)
503
+
504
+ elif theme == "arctic" and "yeti" in story.lower():
505
+ yeti_x = 280
506
+ yeti_y = 180
507
+ # Yeti body
508
+ draw.ellipse([yeti_x, yeti_y, yeti_x+50, yeti_y+50], fill=(240, 240, 240))
509
+ # Yeti eyes
510
+ draw.ellipse([yeti_x+15, yeti_y+15, yeti_x+20, yeti_y+20], fill=(0, 0, 0))
511
+ draw.ellipse([yeti_x+30, yeti_y+15, yeti_x+35, yeti_y+20], fill=(0, 0, 0))
512
+ # Yeti mouth
513
+ draw.arc([yeti_x+15, yeti_y+25, yeti_x+35, yeti_y+35], 0, 180, fill=(0, 0, 0), width=2)
514
+
515
+ # Add frame number
516
+ draw.text((10, 10), f"Frame {i+1}", fill=(255, 255, 255))
517
 
518
  frames.append(img)
519
 
520
  return frames
521
 
522
+ def generate_pygame_code(story, character, theme):
523
+ """Generate PyGame code based on the story"""
524
+ # Basic PyGame template
525
+ code = f"""import pygame
526
+ import sys
527
+
528
+ # Initialize Pygame
529
+ pygame.init()
530
+
531
+ # Screen dimensions
532
+ WIDTH, HEIGHT = 800, 600
533
+ screen = pygame.display.set_mode((WIDTH, HEIGHT))
534
+ pygame.display.set_caption("Your Story: {character.capitalize()} in {theme.capitalize()}")
535
+
536
+ # Colors
537
+ BACKGROUND = {get_theme_color(theme)}
538
+ HERO_COLOR = {get_character_color(character)}
539
+
540
+ # Hero position
541
+ hero_x = 100
542
+ hero_y = HEIGHT // 2
543
+ hero_speed = 5
544
+
545
+ # Main game loop
546
+ clock = pygame.time.Clock()
547
+ running = True
548
+
549
+ while running:
550
+ for event in pygame.event.get():
551
+ if event.type == pygame.QUIT:
552
+ running = False
553
+
554
+ # Handle keyboard input
555
+ keys = pygame.key.get_pressed()
556
+ if keys[pygame.K_LEFT]:
557
+ hero_x -= hero_speed
558
+ if keys[pygame.K_RIGHT]:
559
+ hero_x += hero_speed
560
+ if keys[pygame.K_UP]:
561
+ hero_y -= hero_speed
562
+ if keys[pygame.K_DOWN]:
563
+ hero_y += hero_speed
564
+
565
+ # Fill the background
566
+ screen.fill(BACKGROUND)
567
+
568
+ # Draw the hero
569
+ {get_character_drawing_code(character)}
570
+
571
+ # Draw story elements
572
+ {get_story_elements_code(story, theme)}
573
+
574
+ pygame.display.flip()
575
+ clock.tick(60)
576
+
577
+ pygame.quit()
578
+ sys.exit()
579
+ """
580
+ return code
581
+
582
+ def get_theme_color(theme):
583
+ """Get theme color for PyGame code"""
584
+ colors = {
585
+ "space": "(0, 0, 30)",
586
+ "jungle": "(34, 139, 34)",
587
+ "medieval": "(139, 69, 19)",
588
+ "underwater": "(0, 105, 148)",
589
+ "desert": "(210, 180, 140)",
590
+ "arctic": "(240, 248, 255)"
591
+ }
592
+ return colors.get(theme, "(0, 0, 30)")
593
+
594
+ def get_character_color(character):
595
+ """Get character color for PyGame code"""
596
+ colors = {
597
+ "spaceship": "(169, 169, 169)",
598
+ "dragon": "(178, 34, 34)",
599
+ "knight": "(70, 70, 70)",
600
+ "mermaid": "(255, 105, 180)",
601
+ "robot": "(100, 100, 100)",
602
+ "unicorn": "(255, 240, 245)"
603
+ }
604
+ return colors.get(character, "(169, 169, 169)")
605
+
606
+ def get_character_drawing_code(character):
607
+ """Get PyGame drawing code for character"""
608
+ if character == "spaceship":
609
+ return """ # Draw spaceship
610
+ pygame.draw.polygon(screen, HERO_COLOR, [(hero_x, hero_y),
611
+ (hero_x+50, hero_y),
612
+ (hero_x+25, hero_y-30)])
613
+ pygame.draw.rect(screen, (0, 191, 255), (hero_x+20, hero_y-10, 10, 10))"""
614
+ elif character == "dragon":
615
+ return """ # Draw dragon
616
+ pygame.draw.ellipse(screen, HERO_COLOR, (hero_x, hero_y, 60, 30))
617
+ pygame.draw.ellipse(screen, HERO_COLOR, (hero_x+50, hero_y+5, 20, 20))
618
+ pygame.draw.ellipse(screen, (138, 43, 226), (hero_x+10, hero_y-20, 30, 30))"""
619
+ elif character == "knight":
620
+ return """ # Draw knight
621
+ pygame.draw.rect(screen, HERO_COLOR, (hero_x, hero_y, 25, 50))
622
+ pygame.draw.ellipse(screen, (210, 180, 140), (hero_x+5, hero_y-15, 15, 15))
623
+ pygame.draw.arc(screen, (50, 50, 50), (hero_x, hero_y-20, 25, 20), 0, 3.14, 3)
624
+ pygame.draw.rect(screen, (192, 192, 192), (hero_x+20, hero_y+10, 10, 5))
625
+ pygame.draw.polygon(screen, (192, 192, 192), [(hero_x+30, hero_y+12),
626
+ (hero_x+40, hero_y+10),
627
+ (hero_x+40, hero_y+15)])"""
628
+ elif character == "mermaid":
629
+ return """ # Draw mermaid
630
+ pygame.draw.ellipse(screen, HERO_COLOR, (hero_x, hero_y, 40, 30))
631
+ pygame.draw.ellipse(screen, (255, 218, 185), (hero_x+10, hero_y-30, 20, 30))
632
+ pygame.draw.ellipse(screen, (255, 215, 0), (hero_x-10, hero_y-35, 50, 15))"""
633
+ elif character == "robot":
634
+ return """ # Draw robot
635
+ pygame.draw.rect(screen, HERO_COLOR, (hero_x, hero_y, 30, 50))
636
+ pygame.draw.rect(screen, (150, 150, 150), (hero_x-5, hero_y-20, 40, 20))
637
+ pygame.draw.ellipse(screen, (0, 255, 0), (hero_x+5, hero_y-15, 5, 5))
638
+ pygame.draw.ellipse(screen, (0, 255, 0), (hero_x+20, hero_y-15, 5, 5))
639
+ pygame.draw.rect(screen, HERO_COLOR, (hero_x-10, hero_y+10, 10, 10))
640
+ pygame.draw.rect(screen, HERO_COLOR, (hero_x+30, hero_y+10, 10, 10))"""
641
+ elif character == "unicorn":
642
+ return """ # Draw unicorn
643
+ pygame.draw.ellipse(screen, HERO_COLOR, (hero_x, hero_y, 40, 20))
644
+ pygame.draw.ellipse(screen, HERO_COLOR, (hero_x+30, hero_y-5, 20, 20))
645
+ pygame.draw.polygon(screen, (255, 215, 0), [(hero_x+40, hero_y-10),
646
+ (hero_x+45, hero_y-30),
647
+ (hero_x+50, hero_y-10)])"""
648
+ else:
649
+ return """ # Draw hero
650
+ pygame.draw.rect(screen, HERO_COLOR, (hero_x, hero_y, 40, 60))"""
651
+
652
+ def get_story_elements_code(story, theme):
653
+ """Get PyGame code for story elements"""
654
+ code = ""
655
+ if "alien" in story.lower() and theme == "space":
656
+ code += """ # Draw alien
657
+ pygame.draw.ellipse(screen, (50, 205, 50), (600, 200, 30, 30))
658
+ pygame.draw.ellipse(screen, (0, 0, 0), (610, 210, 5, 5))
659
+ pygame.draw.ellipse(screen, (0, 0, 0), (620, 210, 5, 5))
660
+ pygame.draw.arc(screen, (0, 0, 0), (610, 220, 15, 10), 0, 3.14, 2)
661
+ """
662
+
663
+ if "dragon" in story.lower() and theme == "medieval":
664
+ code += """ # Draw dragon
665
+ pygame.draw.ellipse(screen, (178, 34, 34), (650, 150, 50, 25))
666
+ pygame.draw.line(screen, (178, 34, 34), (700, 162), (730, 150), 4)
667
+ """
668
+
669
+ if "treasure" in story.lower():
670
+ code += """ # Draw treasure
671
+ pygame.draw.rect(screen, (255, 215, 0), (700, 400, 30, 20))
672
+ pygame.draw.rect(screen, (255, 215, 0), (705, 395, 20, 10))
673
+ """
674
+
675
+ if "castle" in story.lower() and theme == "medieval":
676
+ code += """ # Draw castle
677
+ pygame.draw.rect(screen, (169, 169, 169), (600, 300, 150, 150))
678
+ pygame.draw.rect(screen, (105, 105, 105), (650, 350, 50, 100))
679
+ for x in range(610, 740, 40):
680
+ pygame.draw.polygon(screen, (220, 20, 60), [(x, 300), (x-20, 320), (x+20, 320)])
681
+ """
682
+
683
+ return code
684
+
685
  def generate_code_explanation(story, explanation_generator):
686
  """Generate code explanation using open-source model"""
687
  try:
 
710
 
711
  # Find hero based on keywords and entities
712
  hero_keywords = {
713
+ "spaceship": ["spaceship", "rocket", "ship", "alien", "planet", "star", "space"],
714
  "dragon": ["dragon", "monster", "creature", "beast", "wyvern"],
715
+ "knight": ["knight", "warrior", "prince", "princess", "king", "queen", "sword", "castle"],
716
+ "mermaid": ["mermaid", "merman", "sea", "ocean", "underwater", "fish"],
717
+ "robot": ["robot", "cyborg", "machine", "android"],
718
+ "unicorn": ["unicorn", "horse", "pony", "magic"]
719
  }
720
 
721
  # Find world based on keywords and classification
722
+ world_labels = ["space", "jungle", "medieval", "underwater", "desert", "arctic"]
723
 
724
  # Find hero by keywords
725
  story_lower = story.lower()
 
740
  hero = "knight"
741
  elif "mermaid" in story_lower or "sea" in story_lower:
742
  hero = "mermaid"
743
+ elif "robot" in story_lower:
744
+ hero = "robot"
745
+ elif "unicorn" in story_lower:
746
+ hero = "unicorn"
747
 
748
  # Classify world
749
  result = classifier(story, world_labels)
 
754
  world = "underwater"
755
  if "forest" in story_lower or "jungle" in story_lower:
756
  world = "jungle"
757
+ if "castle" in story_lower or "kingdom" in story_lower or "dragon" in story_lower or "knight" in story_lower:
758
  world = "medieval"
759
  if "space" in story_lower or "alien" in story_lower or "planet" in story_lower:
760
  world = "space"
761
+ if "desert" in story_lower or "sand" in story_lower:
762
+ world = "desert"
763
+ if "arctic" in story_lower or "snow" in story_lower or "ice" in story_lower:
764
+ world = "arctic"
765
 
766
  return hero, world
767
 
 
769
  st.error(f"Error analyzing story: {str(e)}")
770
  return "spaceship", "space"
771
 
772
+ def run_pygame_code(code):
773
+ """Run PyGame code and capture the output"""
774
+ with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f:
775
+ f.write(code)
776
+ temp_file_name = f.name
777
+
778
+ # Create a video capture of the PyGame window
779
+ os.system(f"python {temp_file_name} &")
780
+ return temp_file_name
781
+
782
  # Header section
783
  st.markdown('<div class="header">CodeTales โœจ</div>', unsafe_allow_html=True)
784
  st.markdown('<div class="subheader">Storytime + Coding Magic</div>', unsafe_allow_html=True)
 
822
  st.session_state.xp = 0
823
  if 'analyzed' not in st.session_state:
824
  st.session_state.analyzed = False
825
+ if 'pygame_code' not in st.session_state:
826
+ st.session_state.pygame_code = ""
827
+ if 'show_code' not in st.session_state:
828
+ st.session_state.show_code = False
829
 
830
  # Character and theme mapping
831
  characters = {
832
  "spaceship": "๐Ÿš€ Spaceship",
833
  "dragon": "๐Ÿ‰ Dragon",
834
  "knight": "๐Ÿ›ก๏ธ Knight",
835
+ "mermaid": "๐Ÿงœโ€โ™€๏ธ Mermaid",
836
+ "robot": "๐Ÿค– Robot",
837
+ "unicorn": "๐Ÿฆ„ Unicorn"
838
  }
839
 
840
  themes = {
841
  "space": "๐ŸŒŒ Space",
842
  "jungle": "๐ŸŒฟ Jungle",
843
  "medieval": "๐Ÿฐ Medieval",
844
+ "underwater": "๐ŸŒŠ Underwater",
845
+ "desert": "๐Ÿœ๏ธ Desert",
846
+ "arctic": "โ„๏ธ Arctic"
847
  }
848
 
849
  # Main content
 
887
  st.markdown(f'<div class="world-suggestion">Your World: {themes[st.session_state.selected_theme]}</div>',
888
  unsafe_allow_html=True)
889
 
890
+ # Customization options
891
+ st.markdown("### ๐ŸŽจ Customize Your Hero")
892
+ custom_char = st.selectbox(
893
+ "Choose a different hero:",
894
+ options=list(characters.keys()),
895
+ format_func=lambda x: characters[x],
896
+ index=list(characters.keys()).index(st.session_state.selected_character)
897
+
898
+ st.session_state.selected_character = custom_char
899
 
900
  # Generate animation button
901
+ if st.button("๐ŸŽฌ Generate Animation & Code!", use_container_width=True, key="generate", type="primary"):
902
  st.session_state.animation_generated = True
903
+ with st.spinner("๐Ÿง™โ€โ™‚๏ธ Creating your animation and code..."):
904
  # Generate animation frames
905
  st.session_state.animation_frames = generate_sprite_animation(
906
  story_text,
907
  character=st.session_state.selected_character,
908
+ theme=st.session_state.selected_theme,
909
+ num_frames=8
910
  )
911
 
912
  # Generate code explanation
913
  st.session_state.code_explanation = generate_code_explanation(story_text, explanation_generator)
914
 
915
+ # Generate PyGame code
916
+ st.session_state.pygame_code = generate_pygame_code(
917
+ story_text,
918
+ st.session_state.selected_character,
919
+ st.session_state.selected_theme
920
+ )
921
+
922
  # Update user progress
923
  st.session_state.story_count += 1
924
+ st.session_state.xp += 25
925
 
926
  # Check for level up
927
  if st.session_state.xp >= 100:
 
938
  st.markdown("### ๐ŸŽฎ Step 3: Your Animation")
939
  # Display animation frames
940
  st.markdown("**Your Story Comes to Life!**")
 
 
 
 
941
 
942
+ # Show animation as GIF
943
  gif_buffer = BytesIO()
944
  st.session_state.animation_frames[0].save(
945
  gif_buffer,
 
949
  duration=500,
950
  loop=0
951
  )
952
+
953
+ st.image(gif_buffer, caption="Your Animated Story", use_container_width=True)
954
+
955
+ # Download button
956
  st.download_button(
957
  label="โฌ‡๏ธ Download Animation",
958
+ data=gif_buffer.getvalue(),
959
  file_name="your_story.gif",
960
  mime="image/gif",
961
  use_container_width=True
 
968
  st.markdown("### ๐ŸŽฎ Step 3: Your Animation")
969
  st.image("https://img.freepik.com/free-vector/hand-drawn-colorful-space-background_23-2148821798.jpg",
970
  use_container_width=True)
971
+ st.info("๐Ÿ‘† Click 'Generate Animation & Code!' to bring your story to life!")
972
  elif story_text:
973
  st.markdown("### ๐ŸŽฎ Your Animation Will Appear Here")
974
  preview_img = create_storyboard_image(story_text)
 
981
 
982
  st.markdown('</div>', unsafe_allow_html=True)
983
 
984
+ # Coding tutorial section
985
  if st.session_state.animation_generated and st.session_state.story_text:
986
  st.markdown('<div class="robot-speech">', unsafe_allow_html=True)
987
  st.markdown("### ๐Ÿค– Step 4: Tavus the Robot Teacher Explains Coding")
988
 
989
+ # Show code explanation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
990
  st.markdown("### ๐Ÿง  AI-Powered Explanation:")
991
  st.write(st.session_state.code_explanation)
992
 
993
+ # Toggle for showing full code
994
+ if st.button("๐Ÿ‘จโ€๐Ÿ’ป Show Me the Full Code!", key="show_code"):
995
+ st.session_state.show_code = not st.session_state.show_code
996
+
997
+ if st.session_state.show_code:
998
+ st.markdown("### ๐Ÿ Your Story as Python Code")
999
+ st.code(st.session_state.pygame_code, language='python')
1000
+
1001
+ if st.button("โ–ถ๏ธ Run This Code in PyGame", key="run_pygame"):
1002
+ with st.spinner("๐Ÿš€ Launching your game..."):
1003
+ temp_file = run_pygame_code(st.session_state.pygame_code)
1004
+ st.success(f"Game launched! Check your desktop for the PyGame window")
1005
+ st.info("Use arrow keys to move your character!")
1006
+
1007
+ # Step-by-step coding tutorial
1008
+ st.markdown("### ๐Ÿ‘ฃ Step-by-Step Coding Tutorial")
1009
+ with st.expander("1. Setting Up Your Game"):
1010
+ st.markdown("""
1011
+ Every PyGame program starts with these basic steps:
1012
+ ```python
1013
+ import pygame # Import the game library
1014
+ import sys # Import system library for exit
1015
+
1016
+ # Initialize Pygame
1017
+ pygame.init()
1018
+
1019
+ # Create a game window
1020
+ WIDTH, HEIGHT = 800, 600
1021
+ screen = pygame.display.set_mode((WIDTH, HEIGHT))
1022
+ pygame.display.set_caption("Your Awesome Game")
1023
+ ```
1024
+ """)
1025
+
1026
+ with st.expander("2. Creating Your Hero"):
1027
+ st.markdown(f"""
1028
+ Let's create your {st.session_state.selected_character} hero:
1029
+ ```python
1030
+ # Hero position
1031
+ hero_x = 100
1032
+ hero_y = 300
1033
+
1034
+ # How to draw your hero
1035
+ def draw_hero():
1036
+ {get_character_drawing_code(st.session_state.selected_character).replace('\n', '\n ')}
1037
+ ```
1038
+ """)
1039
+
1040
+ with st.expander("3. Making Your Hero Move"):
1041
+ st.markdown("""
1042
+ We'll use keyboard input to move the hero:
1043
+ ```python
1044
+ hero_speed = 5
1045
+
1046
+ # Inside the game loop
1047
+ keys = pygame.key.get_pressed()
1048
+ if keys[pygame.K_LEFT]:
1049
+ hero_x -= hero_speed
1050
+ if keys[pygame.K_RIGHT]:
1051
+ hero_x += hero_speed
1052
+ if keys[pygame.K_UP]:
1053
+ hero_y -= hero_speed
1054
+ if keys[pygame.K_DOWN]:
1055
+ hero_y += hero_speed
1056
+ ```
1057
+ """)
1058
+
1059
+ with st.expander("4. Adding Your Story Elements"):
1060
+ story_elements = []
1061
+ if "alien" in st.session_state.story_text.lower():
1062
+ story_elements.append("Aliens")
1063
+ if "dragon" in st.session_state.story_text.lower():
1064
+ story_elements.append("Dragons")
1065
+ if "treasure" in st.session_state.story_text.lower():
1066
+ story_elements.append("Treasure")
1067
+
1068
+ if story_elements:
1069
+ elements = ", ".join(story_elements)
1070
+ st.markdown(f"""
1071
+ Let's add {elements} from your story:
1072
+ ```python
1073
+ def draw_story_elements():
1074
+ {get_story_elements_code(st.session_state.story_text, st.session_state.selected_theme).replace('\n', '\n ')}
1075
+ ```
1076
+ """)
1077
+ else:
1078
+ st.markdown("""
1079
+ Add your own story elements with drawing commands:
1080
+ ```python
1081
+ # Example: Draw a treasure chest
1082
+ pygame.draw.rect(screen, (255, 215, 0), (700, 400, 30, 20))
1083
+ pygame.draw.rect(screen, (255, 215, 0), (705, 395, 20, 10))
1084
+ ```
1085
+ """)
1086
+
1087
+ with st.expander("5. Running Your Game"):
1088
+ st.markdown("""
1089
+ Finally, we put everything together in a game loop:
1090
+ ```python
1091
+ # Main game loop
1092
+ clock = pygame.time.Clock()
1093
+ running = True
1094
+
1095
+ while running:
1096
+ # Handle events
1097
+ for event in pygame.event.get():
1098
+ if event.type == pygame.QUIT:
1099
+ running = False
1100
+
1101
+ # Handle movement
1102
+ # ... (movement code from step 3)
1103
+
1104
+ # Draw everything
1105
+ screen.fill(BACKGROUND)
1106
+ draw_hero()
1107
+ draw_story_elements()
1108
+
1109
+ # Update the display
1110
+ pygame.display.flip()
1111
+ clock.tick(60)
1112
+
1113
+ pygame.quit()
1114
+ sys.exit()
1115
+ ```
1116
+ """)
1117
+
1118
+ st.markdown("</div>", unsafe_allow_html=True)
1119
+
1120
+ # Code Playground
1121
+ if st.session_state.animation_generated:
1122
+ st.markdown('<div class="code-playground">', unsafe_allow_html=True)
1123
+ st.markdown("### ๐Ÿงช Step 5: Code Playground")
1124
+ st.markdown("Try modifying your code and see the changes!")
1125
+
1126
+ # Editable code area
1127
+ modified_code = st.text_area(
1128
+ "Edit your Python code:",
1129
+ value=st.session_state.pygame_code,
1130
+ height=300,
1131
+ key="code_editor"
1132
+ )
1133
+
1134
+ # Run the modified code
1135
+ if st.button("๐Ÿš€ Run My Modified Code", key="run_modified_code"):
1136
+ with st.spinner("Running your code..."):
1137
+ temp_file = run_pygame_code(modified_code)
1138
+ st.success("Game launched with your modifications!")
1139
 
1140
  st.markdown("</div>", unsafe_allow_html=True)
1141
 
 
1145
  st.success(f"๐ŸŒŸ Level Up! You're now Level {st.session_state.level}!")
1146
  st.session_state.new_level = False
1147
 
1148
+ # Achievements
1149
+ st.markdown("### ๐Ÿ† Your Achievements")
1150
+ achievement_cols = st.columns(4)
1151
+ with achievement_cols[0]:
1152
+ st.markdown('<div class="achievement-badge">๐Ÿ“</div>', unsafe_allow_html=True)
1153
+ st.markdown("**Storyteller**", help="Created your first story")
1154
+ st.markdown(f"{st.session_state.story_count} story created")
1155
+
1156
+ with achievement_cols[1]:
1157
+ st.markdown('<div class="achievement-badge">๐Ÿ‘พ</div>', unsafe_allow_html=True)
1158
+ st.markdown("**Animator**", help="Generated 5 animations")
1159
+ st.markdown(f"{min(st.session_state.story_count, 5)}/5 animations")
1160
+
1161
+ with achievement_cols[2]:
1162
+ st.markdown('<div class="achievement-badge">๐Ÿ’ป</div>', unsafe_allow_html=True)
1163
+ st.markdown("**Coder**", help="Modified and ran code")
1164
+ st.markdown("Unlocked!" if st.session_state.animation_generated else "Locked")
1165
+
1166
+ with achievement_cols[3]:
1167
+ st.markdown('<div class="achievement-badge">๐Ÿš€</div>', unsafe_allow_html=True)
1168
+ st.markdown("**Explorer**", help="Used 3 different heroes")
1169
+ heroes_used = len(set([st.session_state.selected_character]))
1170
+ st.markdown(f"{heroes_used}/3 heroes used")
1171
+
1172
  # Benefits section
1173
  st.markdown("""
1174
  ## โค Why Kids & Parents Love CodeTales
 
1180
  | ๐ŸŽฎ Interactive game creation | โž— Reinforces STEM fundamentals |
1181
  | ๐Ÿ˜„ Fun characters and worlds | ๐Ÿงฉ Encourages logical reasoning |
1182
  | ๐ŸŒŸ Unlock new levels | ๐Ÿ“ˆ Tracks learning progress |
1183
+ | ๐Ÿ’ป Real Python coding experience | ๐ŸŽฏ Aligned with coding curriculum |
1184
  """)
1185
 
1186
  # Footer