Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>CodeGalaxy Kids - Learn to Code!</title> | |
| <script src="https://cdn.jsdelivr.net/npm/blockly@10.0.0/blockly.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/blockly@10.0.0/msg/en.js"></script> | |
| <link href="https://cdn.jsdelivr.net/npm/blockly@10.0.0/media/blockly.css" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --primary: #6c5ce7; | |
| --secondary: #a29bfe; | |
| --accent: #ff7675; | |
| --success: #00b894; | |
| --warning: #fdcb6e; | |
| --dark: #2d3436; | |
| --light: #dfe6e9; | |
| --space-bg: #0f1b33; | |
| --robot-bg: #e8f4f8; | |
| --animal-bg: #e8f5e9; | |
| --galaxy-gradient: linear-gradient(135deg, #1a237e 0%, #4a148c 100%); | |
| --robot-gradient: linear-gradient(135deg, #00838f 0%, #006064 100%); | |
| --animal-gradient: linear-gradient(135deg, #2e7d32 0%, #1b5e20 100%); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Nunito', sans-serif; | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
| color: var(--dark); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| .app-container { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 100vh; | |
| } | |
| /* Header Styles */ | |
| .header { | |
| background: var(--galaxy-gradient); | |
| padding: 1rem 2rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
| position: relative; | |
| z-index: 100; | |
| } | |
| .logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .logo h1 { | |
| font-family: 'Fredoka', sans-serif; | |
| font-size: 2.2rem; | |
| color: white; | |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); | |
| } | |
| .logo-icon { | |
| width: 50px; | |
| height: 50px; | |
| background: white; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 24px; | |
| color: var(--primary); | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
| } | |
| .user-actions { | |
| display: flex; | |
| align-items: center; | |
| gap: 20px; | |
| } | |
| .avatar { | |
| width: 45px; | |
| height: 45px; | |
| border-radius: 50%; | |
| background: var(--accent); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| font-size: 18px; | |
| cursor: pointer; | |
| border: 3px solid var(--warning); | |
| } | |
| .points-badge { | |
| background: white; | |
| padding: 8px 15px; | |
| border-radius: 25px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| } | |
| .points-badge span { | |
| color: var(--primary); | |
| font-weight: bold; | |
| font-size: 1.1rem; | |
| } | |
| /* Main Content */ | |
| .main-content { | |
| display: flex; | |
| flex: 1; | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| width: 250px; | |
| background: white; | |
| padding: 1.5rem 1rem; | |
| box-shadow: 4px 0 12px rgba(0, 0, 0, 0.05); | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| z-index: 50; | |
| } | |
| .nav-item { | |
| padding: 14px 16px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| font-weight: 600; | |
| color: var(--dark); | |
| } | |
| .nav-item:hover, .nav-item.active { | |
| background: var(--secondary); | |
| color: white; | |
| } | |
| .nav-item i { | |
| font-size: 1.2rem; | |
| } | |
| .divider { | |
| height: 1px; | |
| background: var(--light); | |
| margin: 15px 0; | |
| } | |
| /* Content Area */ | |
| .content-area { | |
| flex: 1; | |
| padding: 2rem; | |
| overflow-y: auto; | |
| background: rgba(255, 255, 255, 0.8); | |
| } | |
| .section-title { | |
| font-family: 'Fredoka', sans-serif; | |
| font-size: 2rem; | |
| margin-bottom: 1.5rem; | |
| color: var(--primary); | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| /* Dashboard */ | |
| .welcome-banner { | |
| background: var(--galaxy-gradient); | |
| border-radius: 20px; | |
| padding: 2rem; | |
| color: white; | |
| margin-bottom: 2rem; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .banner-robot { | |
| position: absolute; | |
| right: 30px; | |
| bottom: -10px; | |
| width: 150px; | |
| height: 150px; | |
| background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="30" r="10" fill="white"/><rect x="30" y="40" width="40" height="40" rx="5" fill="white"/><rect x="20" y="45" width="10" height="20" rx="3" fill="white"/><rect x="70" y="45" width="10" height="20" rx="3" fill="white"/></svg>') no-repeat; | |
| } | |
| .learning-paths { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); | |
| gap: 1.5rem; | |
| margin-bottom: 2rem; | |
| } | |
| .path-card { | |
| background: white; | |
| border-radius: 16px; | |
| overflow: hidden; | |
| box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); | |
| transition: transform 0.3s ease; | |
| cursor: pointer; | |
| } | |
| .path-card:hover { | |
| transform: translateY(-5px); | |
| } | |
| .path-header { | |
| padding: 1.5rem; | |
| color: white; | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| .space-theme { | |
| background: var(--galaxy-gradient); | |
| } | |
| .robot-theme { | |
| background: var(--robot-gradient); | |
| } | |
| .animal-theme { | |
| background: var(--animal-gradient); | |
| } | |
| .path-content { | |
| padding: 1.5rem; | |
| } | |
| .path-title { | |
| font-size: 1.4rem; | |
| margin-bottom: 10px; | |
| } | |
| .progress-bar { | |
| height: 10px; | |
| background: var(--light); | |
| border-radius: 5px; | |
| margin: 15px 0; | |
| overflow: hidden; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background: var(--success); | |
| border-radius: 5px; | |
| } | |
| .badges-container { | |
| margin-top: 2rem; | |
| } | |
| .badges-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); | |
| gap: 1rem; | |
| } | |
| .badge { | |
| width: 80px; | |
| height: 80px; | |
| border-radius: 50%; | |
| background: linear-gradient(135deg, var(--warning) 0%, var(--accent) 100%); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 1.8rem; | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| position: relative; | |
| } | |
| .badge.locked { | |
| background: var(--light); | |
| color: #b0b0b0; | |
| } | |
| .badge-title { | |
| position: absolute; | |
| bottom: -25px; | |
| font-size: 0.7rem; | |
| text-align: center; | |
| width: 100%; | |
| color: var(--dark); | |
| } | |
| /* Blockly Workspace */ | |
| .workspace-container { | |
| display: flex; | |
| height: 70vh; | |
| gap: 20px; | |
| margin-top: 1.5rem; | |
| } | |
| .blockly-area { | |
| flex: 3; | |
| background: white; | |
| border-radius: 16px; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); | |
| overflow: hidden; | |
| } | |
| .code-area { | |
| flex: 2; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| } | |
| .code-panel { | |
| background: #1e1e1e; | |
| color: #dcdcdc; | |
| border-radius: 16px; | |
| padding: 1.5rem; | |
| flex: 1; | |
| font-family: monospace; | |
| overflow: auto; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); | |
| } | |
| .code-header { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 1rem; | |
| } | |
| .language-selector { | |
| background: #3c3c3c; | |
| color: white; | |
| border: none; | |
| padding: 5px 10px; | |
| border-radius: 5px; | |
| } | |
| .stage-container { | |
| background: white; | |
| border-radius: 16px; | |
| padding: 1.5rem; | |
| flex: 1; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); | |
| overflow: hidden; | |
| position: relative; | |
| background: linear-gradient(135deg, #e0f7fa 0%, #bbdefb 100%); | |
| } | |
| #stage { | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| overflow: hidden; | |
| border-radius: 8px; | |
| background: #f0f8ff; | |
| } | |
| .sprite { | |
| position: absolute; | |
| width: 60px; | |
| height: 60px; | |
| cursor: pointer; | |
| transition: transform 0.3s ease; | |
| } | |
| .sprite img { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: contain; | |
| } | |
| .stage-controls { | |
| position: absolute; | |
| bottom: 15px; | |
| left: 15px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .stage-btn { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| background: var(--primary); | |
| color: white; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); | |
| } | |
| .toolbar { | |
| display: flex; | |
| gap: 10px; | |
| margin-bottom: 1.5rem; | |
| } | |
| .btn { | |
| padding: 10px 20px; | |
| border-radius: 50px; | |
| border: none; | |
| font-weight: bold; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| transition: all 0.2s ease; | |
| } | |
| .btn-primary { | |
| background: var(--primary); | |
| color: white; | |
| } | |
| .btn-secondary { | |
| background: var(--secondary); | |
| color: white; | |
| } | |
| .btn-warning { | |
| background: var(--warning); | |
| color: var(--dark); | |
| } | |
| .btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| } | |
| /* Project Gallery */ | |
| .projects-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | |
| gap: 1.5rem; | |
| } | |
| .project-card { | |
| background: white; | |
| border-radius: 16px; | |
| overflow: hidden; | |
| box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); | |
| transition: transform 0.3s ease; | |
| cursor: pointer; | |
| } | |
| .project-card:hover { | |
| transform: translateY(-5px); | |
| } | |
| .project-image { | |
| height: 150px; | |
| background: linear-gradient(135deg, var(--secondary) 0%, var(--primary) 100%); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 3rem; | |
| } | |
| .project-info { | |
| padding: 1.2rem; | |
| } | |
| /* Age Groups */ | |
| .age-groups { | |
| display: flex; | |
| gap: 15px; | |
| margin: 2rem 0; | |
| flex-wrap: wrap; | |
| } | |
| .age-card { | |
| background: white; | |
| border-radius: 16px; | |
| padding: 1.5rem; | |
| flex: 1; | |
| min-width: 250px; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
| } | |
| .age-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| } | |
| .age-icon { | |
| width: 50px; | |
| height: 50px; | |
| border-radius: 50%; | |
| background: var(--secondary); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 1.5rem; | |
| } | |
| .concepts-list { | |
| padding-left: 20px; | |
| } | |
| .concepts-list li { | |
| margin-bottom: 8px; | |
| } | |
| /* Footer */ | |
| .footer { | |
| background: var(--dark); | |
| color: white; | |
| padding: 1.5rem 2rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .footer-links { | |
| display: flex; | |
| gap: 20px; | |
| } | |
| .footer-link { | |
| color: var(--light); | |
| text-decoration: none; | |
| } | |
| /* Animations */ | |
| @keyframes float { | |
| 0% { transform: translateY(0px); } | |
| 50% { transform: translateY(-10px); } | |
| 100% { transform: translateY(0px); } | |
| } | |
| .floating { | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| /* Responsive */ | |
| @media (max-width: 900px) { | |
| .workspace-container { | |
| flex-direction: column; | |
| height: auto; | |
| } | |
| .main-content { | |
| flex-direction: column; | |
| } | |
| .sidebar { | |
| width: 100%; | |
| flex-direction: row; | |
| overflow-x: auto; | |
| padding: 1rem; | |
| } | |
| .divider { | |
| display: none; | |
| } | |
| .age-groups { | |
| flex-direction: column; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- Header --> | |
| <header class="header"> | |
| <div class="logo"> | |
| <div class="logo-icon">π</div> | |
| <h1>CodeGalaxy Kids</h1> | |
| </div> | |
| <div class="user-actions"> | |
| <div class="points-badge"> | |
| <span>β 1,250</span> | |
| </div> | |
| <div class="avatar">MK</div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="main-content"> | |
| <!-- Sidebar Navigation --> | |
| <nav class="sidebar"> | |
| <div class="nav-item active"> | |
| <i class="fas fa-home"></i> Dashboard | |
| </div> | |
| <div class="nav-item"> | |
| <i class="fas fa-road"></i> Learning Path | |
| </div> | |
| <div class="nav-item"> | |
| <i class="fas fa-puzzle-piece"></i> Block Coding | |
| </div> | |
| <div class="nav-item"> | |
| <i class="fas fa-gamepad"></i> Projects | |
| </div> | |
| <div class="nav-item"> | |
| <i class="fas fa-trophy"></i> Rewards | |
| </div> | |
| <div class="divider"></div> | |
| <div class="nav-item"> | |
| <i class="fas fa-users"></i> Parent Zone | |
| </div> | |
| <div class="nav-item"> | |
| <i class="fas fa-cog"></i> Settings | |
| </div> | |
| </nav> | |
| <!-- Content Area --> | |
| <main class="content-area"> | |
| <h2 class="section-title"><i class="fas fa-rocket"></i> Welcome to CodeGalaxy, Maya!</h2> | |
| <!-- Dashboard Banner --> | |
| <div class="welcome-banner"> | |
| <h3><i class="fas fa-robot"></i> Continue Your Adventure!</h3> | |
| <p>Complete your current mission to earn 50 stars and unlock new coding powers!</p> | |
| <div class="banner-robot floating"></div> | |
| </div> | |
| <!-- Learning Paths --> | |
| <h3 class="section-title"><i class="fas fa-star"></i> Learning Paths</h3> | |
| <div class="learning-paths"> | |
| <!-- Space Explorer --> | |
| <div class="path-card"> | |
| <div class="path-header space-theme"> | |
| <i class="fas fa-rocket"></i> | |
| <h3>Space Explorer</h3> | |
| </div> | |
| <div class="path-content"> | |
| <h4 class="path-title">Mission: Navigate Asteroid Field</h4> | |
| <p>Use loops to navigate through space obstacles!</p> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" style="width: 65%"></div> | |
| </div> | |
| <p>65% Complete β’ 3/5 Missions</p> | |
| </div> | |
| </div> | |
| <!-- Robot Village --> | |
| <div class="path-card"> | |
| <div class="path-header robot-theme"> | |
| <i class="fas fa-robot"></i> | |
| <h3>Robot Village</h3> | |
| </div> | |
| <div class="path-content"> | |
| <h4 class="path-title">Mission: Help Robots Dance</h4> | |
| <p>Create sequences to choreograph robot dances!</p> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" style="width: 30%"></div> | |
| </div> | |
| <p>30% Complete β’ 1/5 Missions</p> | |
| </div> | |
| </div> | |
| <!-- Animal Adventures --> | |
| <div class="path-card"> | |
| <div class="path-header animal-theme"> | |
| <i class="fas fa-paw"></i> | |
| <h3>Animal Adventures</h3> | |
| </div> | |
| <div class="path-content"> | |
| <h4 class="path-title">Mission: Feed the Animals</h4> | |
| <p>Use conditionals to feed animals the right food!</p> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" style="width: 10%"></div> | |
| </div> | |
| <p>10% Complete β’ 0/5 Missions</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Age Groups --> | |
| <h3 class="section-title"><i class="fas fa-child"></i> Learning Path by Age</h3> | |
| <div class="age-groups"> | |
| <div class="age-card"> | |
| <div class="age-header"> | |
| <div class="age-icon">5-7</div> | |
| <h3>Beginner</h3> | |
| </div> | |
| <ul class="concepts-list"> | |
| <li>Shapes and colors</li> | |
| <li>Basic movement</li> | |
| <li>Simple sequences</li> | |
| <li>Pattern recognition</li> | |
| </ul> | |
| </div> | |
| <div class="age-card"> | |
| <div class="age-header"> | |
| <div class="age-icon">8-10</div> | |
| <h3>Intermediate</h3> | |
| </div> | |
| <ul class="concepts-list"> | |
| <li>Loops and repetition</li> | |
| <li>Conditional logic</li> | |
| <li>Variables</li> | |
| <li>Problem solving</li> | |
| </ul> | |
| </div> | |
| <div class="age-card"> | |
| <div class="age-header"> | |
| <div class="age-icon">11-13</div> | |
| <h3>Advanced</h3> | |
| </div> | |
| <ul class="concepts-list"> | |
| <li>Functions and events</li> | |
| <li>Debugging techniques</li> | |
| <li>Game mechanics</li> | |
| <li>Real-world problems</li> | |
| </ul> | |
| </div> | |
| <div class="age-card"> | |
| <div class="age-header"> | |
| <div class="age-icon">13+</div> | |
| <h3>Expert</h3> | |
| </div> | |
| <ul class="concepts-list"> | |
| <li>Text-based coding</li> | |
| <li>Python and JavaScript</li> | |
| <li>Web development</li> | |
| <li>AI concepts</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- Blockly Workspace --> | |
| <h3 class="section-title"><i class="fas fa-puzzle-piece"></i> Block Coding Playground</h3> | |
| <div class="toolbar"> | |
| <button class="btn btn-primary" id="runCode"> | |
| <i class="fas fa-play"></i> Run Code | |
| </button> | |
| <button class="btn btn-secondary" id="saveProject"> | |
| <i class="fas fa-save"></i> Save Project | |
| </button> | |
| <button class="btn btn-warning" id="getHelp"> | |
| <i class="fas fa-question-circle"></i> Get Help | |
| </button> | |
| <button class="btn" id="resetStage" style="background: #ff7675; color: white;"> | |
| <i class="fas fa-redo"></i> Reset | |
| </button> | |
| </div> | |
| <div class="workspace-container"> | |
| <div class="blockly-area" id="blocklyDiv"></div> | |
| <div class="code-area"> | |
| <div class="code-panel"> | |
| <div class="code-header"> | |
| <h4>Generated Code</h4> | |
| <select class="language-selector" id="languageSelector"> | |
| <option>JavaScript</option> | |
| <option>Python</option> | |
| </select> | |
| </div> | |
| <pre id="generatedCode"># Welcome to CodeGalaxy! | |
| # Your generated code will appear here | |
| # Drag blocks to the workspace to start coding! | |
| def main(): | |
| # Example: Move the robot forward | |
| robot.move_forward(3) | |
| # Example: Turn right | |
| robot.turn_right() | |
| # Example: Loop to collect stars | |
| for i in range(5): | |
| collect_star() | |
| if __name__ == "__main__": | |
| main()</pre> | |
| </div> | |
| <div class="stage-container"> | |
| <h4>Stage Preview</h4> | |
| <div id="stage"> | |
| <div class="sprite" id="robotSprite" style="top: 100px; left: 100px;"> | |
| <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='30' r='10' fill='%236c5ce7'/%3E%3Crect x='30' y='40' width='40' height='40' rx='5' fill='%236c5ce7'/%3E%3Crect x='20' y='45' width='10' height='20' rx='3' fill='%236c5ce7'/%3E%3Crect x='70' y='45' width='10' height='20' rx='3' fill='%236c5ce7'/%3E%3C/svg%3E" alt="Robot"> | |
| </div> | |
| <div class="sprite" id="star1" style="top: 50px; left: 200px;"> | |
| <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpolygon points='50,10 61,35 88,35 65,55 71,80 50,65 29,80 35,55 12,35 39,35' fill='%23fdcb6e'/%3E%3C/svg%3E" alt="Star"> | |
| </div> | |
| <div class="sprite" id="star2" style="top: 180px; left: 300px;"> | |
| <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpolygon points='50,10 61,35 88,35 65,55 71,80 50,65 29,80 35,55 12,35 39,35' fill='%23fdcb6e'/%3E%3C/svg%3E" alt="Star"> | |
| </div> | |
| <div class="sprite" id="rocket" style="top: 250px; left: 50px;"> | |
| <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M50,10 L70,40 L60,40 L65,90 L35,90 L40,40 L30,40 Z' fill='%23ff7675'/%3E%3Ccircle cx='50' cy='30' r='10' fill='%23a29bfe'/%3E%3C/svg%3E" alt="Rocket"> | |
| </div> | |
| </div> | |
| <div class="stage-controls"> | |
| <div class="stage-btn" id="greenFlag"> | |
| <i class="fas fa-flag" style="color: #00b894;"></i> | |
| </div> | |
| <div class="stage-btn" id="stopBtn"> | |
| <i class="fas fa-stop"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Badges Section --> | |
| <h3 class="section-title"><i class="fas fa-trophy"></i> Your Achievements</h3> | |
| <div class="badges-container"> | |
| <div class="badges-grid"> | |
| <div class="badge"> | |
| <i class="fas fa-star"></i> | |
| <div class="badge-title">Starter</div> | |
| </div> | |
| <div class="badge"> | |
| <i class="fas fa-redo"></i> | |
| <div class="badge-title">Loops Master</div> | |
| </div> | |
| <div class="badge"> | |
| <i class="fas fa-brain"></i> | |
| <div class="badge-title">Logic Wizard</div> | |
| </div> | |
| <div class="badge locked"> | |
| <i class="fas fa-lock"></i> | |
| <div class="badge-title">Variables Pro</div> | |
| </div> | |
| <div class="badge locked"> | |
| <i class="fas fa-lock"></i> | |
| <div class="badge-title">Game Designer</div> | |
| </div> | |
| <div class="badge locked"> | |
| <i class="fas fa-lock"></i> | |
| <div class="badge-title">Python Expert</div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Footer --> | |
| <footer class="footer"> | |
| <div class="copyright"> | |
| Β© 2023 CodeGalaxy Kids. All rights reserved. | |
| </div> | |
| <div class="footer-links"> | |
| <a href="#" class="footer-link">Privacy Policy</a> | |
| <a href="#" class="footer-link">Terms of Service</a> | |
| <a href="#" class="footer-link">Help Center</a> | |
| </div> | |
| </footer> | |
| </div> | |
| <script> | |
| // Initialize Blockly | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Custom Blockly blocks | |
| Blockly.Blocks['motion_move'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("move") | |
| .appendField(new Blockly.FieldDropdown([ | |
| ["forward", "FORWARD"], | |
| ["backward", "BACKWARD"] | |
| ]), "DIRECTION") | |
| .appendField(new Blockly.FieldNumber(10, 1), "STEPS") | |
| .appendField("steps"); | |
| this.setPreviousStatement(true); | |
| this.setNextStatement(true); | |
| this.setColour(160); | |
| this.setTooltip("Move the robot"); | |
| } | |
| }; | |
| Blockly.Blocks['motion_turn'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("turn") | |
| .appendField(new Blockly.FieldDropdown([ | |
| ["left", "LEFT"], | |
| ["right", "RIGHT"] | |
| ]), "DIRECTION") | |
| .appendField(new Blockly.FieldNumber(15, 1), "DEGREES") | |
| .appendField("degrees"); | |
| this.setPreviousStatement(true); | |
| this.setNextStatement(true); | |
| this.setColour(160); | |
| this.setTooltip("Turn the robot"); | |
| } | |
| }; | |
| Blockly.Blocks['event_whenflagclicked'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("when green flag clicked"); | |
| this.setNextStatement(true); | |
| this.setColour(120); | |
| this.setTooltip("Trigger when the green flag is clicked"); | |
| } | |
| }; | |
| Blockly.Blocks['controls_repeat'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("repeat") | |
| .appendField(new Blockly.FieldNumber(5, 1), "TIMES") | |
| .appendField("times"); | |
| this.appendStatementInput("DO") | |
| .setCheck(null); | |
| this.setPreviousStatement(true); | |
| this.setNextStatement(true); | |
| this.setColour(65); | |
| this.setTooltip("Repeat the enclosed blocks"); | |
| } | |
| }; | |
| Blockly.Blocks['controls_wait'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("wait") | |
| .appendField(new Blockly.FieldNumber(1, 0.1, 10, 0.1), "SECONDS") | |
| .appendField("seconds"); | |
| this.setPreviousStatement(true); | |
| this.setNextStatement(true); | |
| this.setColour(65); | |
| this.setTooltip("Wait for some seconds"); | |
| } | |
| }; | |
| Blockly.Blocks['looks_say'] = { | |
| init: function() { | |
| this.appendDummyInput() | |
| .appendField("say") | |
| .appendField(new Blockly.FieldTextInput("Hello!"), "MESSAGE") | |
| .appendField("for") | |
| .appendField(new Blockly.FieldNumber(2, 0.1), "SECONDS") | |
| .appendField("seconds"); | |
| this.setPreviousStatement(true); | |
| this.setNextStatement(true); | |
| this.setColour(210); | |
| this.setTooltip("Show a message bubble"); | |
| } | |
| }; | |
| // Blockly workspace | |
| const workspace = Blockly.inject('blocklyDiv', { | |
| toolbox: document.getElementById('toolbox'), | |
| grid: { | |
| spacing: 20, | |
| length: 3, | |
| colour: '#ccc', | |
| snap: true | |
| }, | |
| zoom: { | |
| controls: true, | |
| wheel: true, | |
| startScale: 1.0, | |
| maxScale: 3, | |
| minScale: 0.3, | |
| scaleSpeed: 1.2 | |
| }, | |
| move: { | |
| scrollbars: true, | |
| drag: true, | |
| wheel: true | |
| } | |
| }); | |
| // Initial blocks | |
| const initialXml = ` | |
| <xml xmlns="https://developers.google.com/blockly/xml"> | |
| <block type="event_whenflagclicked" id="start_block" x="20" y="20"> | |
| <next> | |
| <block type="looks_say"> | |
| <field name="MESSAGE">Let's code!</field> | |
| <field name="SECONDS">1</field> | |
| <next> | |
| <block type="motion_move"> | |
| <field name="DIRECTION">FORWARD</field> | |
| <field name="STEPS">50</field> | |
| <next> | |
| <block type="motion_turn"> | |
| <field name="DIRECTION">RIGHT</field> | |
| <field name="DEGREES">90</field> | |
| <next> | |
| <block type="controls_repeat"> | |
| <field name="TIMES">4</field> | |
| <statement name="DO"> | |
| <block type="motion_move"> | |
| <field name="DIRECTION">FORWARD</field> | |
| <field name="STEPS">30</field> | |
| <next> | |
| <block type="motion_turn"> | |
| <field name="DIRECTION">RIGHT</field> | |
| <field name="DEGREES">90</field> | |
| </block> | |
| </next> | |
| </block> | |
| </statement> | |
| </block> | |
| </next> | |
| </block> | |
| </next> | |
| </block> | |
| </next> | |
| </block> | |
| </next> | |
| </block> | |
| </xml> | |
| `; | |
| // Load initial blocks | |
| Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(initialXml), workspace); | |
| // Update code preview | |
| function updateCodePreview() { | |
| const codeElement = document.getElementById('generatedCode'); | |
| const language = document.getElementById('languageSelector').value; | |
| // In a real implementation, this would use Blockly generators | |
| if (language === 'JavaScript') { | |
| codeElement.textContent = `// JavaScript code\n\nfunction main() {\n // Say message\n say("Let's code!", 1);\n \n // Move forward\n move("forward", 50);\n \n // Turn right\n turn("right", 90);\n \n // Loop to draw a square\n for (let i = 0; i < 4; i++) {\n move("forward", 30);\n turn("right", 90);\n }\n}\n\n// Start the program\nmain();`; | |
| } else { | |
| codeElement.textContent = `# Python code\n\ndef main():\n # Say message\n say("Let's code!", 1)\n \n # Move forward\n move("forward", 50)\n \n # Turn right\n turn("right", 90)\n \n # Loop to draw a square\n for i in range(4):\n move("forward", 30)\n turn("right", 90)\n \nif __name__ == "__main__":\n main()`; | |
| } | |
| } | |
| // Sprite movement functions | |
| function moveSprite(direction, steps) { | |
| const robot = document.getElementById('robotSprite'); | |
| const currentLeft = parseInt(robot.style.left) || 100; | |
| const currentTop = parseInt(robot.style.top) || 100; | |
| if (direction === 'FORWARD') { | |
| robot.style.top = (currentTop - steps) + 'px'; | |
| } else { | |
| robot.style.top = (currentTop + steps) + 'px'; | |
| } | |
| // Check for star collection | |
| checkStarCollection(); | |
| } | |
| function turnSprite(direction, degrees) { | |
| const robot = document.getElementById('robotSprite'); | |
| const currentRotation = parseInt(robot.dataset.rotation) || 0; | |
| let newRotation; | |
| if (direction === 'RIGHT') { | |
| newRotation = currentRotation + degrees; | |
| } else { | |
| newRotation = currentRotation - degrees; | |
| } | |
| robot.dataset.rotation = newRotation; | |
| robot.style.transform = `rotate(${newRotation}deg)`; | |
| } | |
| function sayMessage(message, seconds) { | |
| const output = document.getElementById('output'); | |
| output.innerHTML = `<div class="speech-bubble">${message}</div>`; | |
| setTimeout(() => { | |
| output.innerHTML = ''; | |
| }, seconds * 1000); | |
| } | |
| function checkStarCollection() { | |
| const robot = document.getElementById('robotSprite'); | |
| const stars = document.querySelectorAll('.sprite:not(#robotSprite)'); | |
| const robotRect = robot.getBoundingClientRect(); | |
| stars.forEach(star => { | |
| const starRect = star.getBoundingClientRect(); | |
| // Check for collision | |
| if (!star.classList.contains('collected') && | |
| robotRect.left < starRect.right && | |
| robotRect.right > starRect.left && | |
| robotRect.top < starRect.bottom && | |
| robotRect.bottom > starRect.top) { | |
| // Collect the star | |
| star.classList.add('collected'); | |
| star.style.opacity = '0.3'; | |
| // Update points | |
| const pointsBadge = document.querySelector('.points-badge span'); | |
| const currentPoints = parseInt(pointsBadge.textContent.replace('β ', '')) || 0; | |
| pointsBadge.textContent = `β ${currentPoints + 50}`; | |
| // Show message | |
| const output = document.getElementById('output'); | |
| output.innerHTML = `<div class="speech-bubble">β Collected a star! +50 points</div>`; | |
| setTimeout(() => { | |
| output.innerHTML = ''; | |
| }, 2000); | |
| } | |
| }); | |
| } | |
| // Execute the block program | |
| function executeProgram() { | |
| // Reset collected stars | |
| document.querySelectorAll('.sprite').forEach(sprite => { | |
| if (sprite !== document.getElementById('robotSprite')) { | |
| sprite.classList.remove('collected'); | |
| sprite.style.opacity = '1'; | |
| } | |
| }); | |
| // Reset robot position | |
| const robot = document.getElementById('robotSprite'); | |
| robot.style.top = '100px'; | |
| robot.style.left = '100px'; | |
| robot.style.transform = 'rotate(0deg)'; | |
| robot.dataset.rotation = '0'; | |
| // Execute blocks in sequence | |
| const blocks = { | |
| 'looks_say': (block) => { | |
| const message = block.getFieldValue('MESSAGE'); | |
| const seconds = parseFloat(block.getFieldValue('SECONDS')); | |
| sayMessage(message, seconds); | |
| return new Promise(resolve => setTimeout(resolve, seconds * 1000)); | |
| }, | |
| 'motion_move': (block) => { | |
| const direction = block.getFieldValue('DIRECTION'); | |
| const steps = parseInt(block.getFieldValue('STEPS')); | |
| moveSprite(direction, steps); | |
| return new Promise(resolve => setTimeout(resolve, 800)); | |
| }, | |
| 'motion_turn': (block) => { | |
| const direction = block.getFieldValue('DIRECTION'); | |
| const degrees = parseInt(block.getFieldValue('DEGREES')); | |
| turnSprite(direction, degrees); | |
| return new Promise(resolve => setTimeout(resolve, 800)); | |
| }, | |
| 'controls_repeat': async (block) => { | |
| const times = parseInt(block.getFieldValue('TIMES')); | |
| const doBlock = block.getInputTargetBlock('DO'); | |
| for (let i = 0; i < times; i++) { | |
| let currentBlock = doBlock; | |
| while (currentBlock) { | |
| await executeBlock(currentBlock); | |
| currentBlock = currentBlock.nextConnection && currentBlock.nextConnection.targetBlock(); | |
| } | |
| } | |
| return Promise.resolve(); | |
| }, | |
| 'controls_wait': (block) => { | |
| const seconds = parseFloat(block.getFieldValue('SECONDS')); | |
| return new Promise(resolve => setTimeout(resolve, seconds * 1000)); | |
| } | |
| }; | |
| // Start from the green flag block | |
| const startBlock = workspace.getBlockById('start_block'); | |
| let currentBlock = startBlock.nextConnection && startBlock.nextConnection.targetBlock(); | |
| async function executeBlock(block) { | |
| const blockType = block.type; | |
| if (blocks[blockType]) { | |
| await blocks[blockType](block); | |
| } | |
| return Promise.resolve(); | |
| } | |
| async function runBlocks() { | |
| while (currentBlock) { | |
| await executeBlock(currentBlock); | |
| currentBlock = currentBlock.nextConnection && currentBlock.nextConnection.targetBlock(); | |
| } | |
| } | |
| runBlocks(); | |
| } | |
| // Event listeners | |
| document.getElementById('runCode').addEventListener('click', executeProgram); | |
| document.getElementById('greenFlag').addEventListener('click', executeProgram); | |
| document.getElementById('stopBtn').addEventListener('click', function() { | |
| // In a real implementation, this would stop all execution | |
| document.getElementById('output').innerHTML = '<p>βΉοΈ Program stopped</p>'; | |
| }); | |
| document.getElementById('resetStage').addEventListener('click', function() { | |
| const robot = document.getElementById('robotSprite'); | |
| robot.style.top = '100px'; | |
| robot.style.left = '100px'; | |
| robot.style.transform = 'rotate(0deg)'; | |
| robot.dataset.rotation = '0'; | |
| document.querySelectorAll('.sprite').forEach(sprite => { | |
| if (sprite !== robot) { | |
| sprite.classList.remove('collected'); | |
| sprite.style.opacity = '1'; | |
| } | |
| }); | |
| document.getElementById('output').innerHTML = '<p>π Stage has been reset</p>'; | |
| }); | |
| document.getElementById('getHelp').addEventListener('click', function() { | |
| const output = document.getElementById('output'); | |
| output.innerHTML = '<p>π€ Robo Helper: Try using a loop to repeat actions!</p>'; | |
| output.innerHTML += '<p>π Drag a "repeat" block to make the robot move multiple times</p>'; | |
| output.innerHTML += '<p>π‘ Remember: Each step in the loop will be repeated</p>'; | |
| }); | |
| document.getElementById('languageSelector').addEventListener('change', updateCodePreview); | |
| // Navigation functionality | |
| document.querySelectorAll('.nav-item').forEach(item => { | |
| item.addEventListener('click', function() { | |
| document.querySelectorAll('.nav-item').forEach(nav => { | |
| nav.classList.remove('active'); | |
| }); | |
| this.classList.add('active'); | |
| }); | |
| }); | |
| // Initialize code preview | |
| updateCodePreview(); | |
| }); | |
| </script> | |
| <!-- Blockly Toolbox --> | |
| <xml id="toolbox" style="display: none"> | |
| <category name="Motion" colour="#4A6CD4"> | |
| <block type="motion_move"></block> | |
| <block type="motion_turn"></block> | |
| </category> | |
| <category name="Events" colour="#FFAB19"> | |
| <block type="event_whenflagclicked"></block> | |
| </category> | |
| <category name="Control" colour="#5CB711"> | |
| <block type="controls_repeat"></block> | |
| <block type="controls_wait"></block> | |
| </category> | |
| <category name="Looks" colour="#FF6680"> | |
| <block type="looks_say"></block> | |
| </category> | |
| <category name="Operators" colour="#0FBD8C"> | |
| <block type="math_number"></block> | |
| <block type="math_arithmetic"></block> | |
| </category> | |
| </xml> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 𧬠<a href="https://enzostvs-deepsite.hf.space?remix=PrinceShadow003/codegalaxy" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |