codegalaxy / index.html
PrinceShadow003's picture
make this as working model - Initial Deployment
44d96ab verified
<!DOCTYPE html>
<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>