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> |