943 أسطر
33 KiB
HTML
943 أسطر
33 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ar" dir="rtl">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>creative kid · copy the painting</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
user-select: none;
|
||
}
|
||
|
||
body {
|
||
background: #b8d8d0;
|
||
background-image: radial-gradient(circle at 30% 40%, #d4eae2 0%, #b0cfc5 100%);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-family: 'Segoe UI', 'Comic Sans MS', 'Cairo', sans-serif;
|
||
padding: 16px;
|
||
}
|
||
|
||
.game-box {
|
||
max-width: 1200px;
|
||
width: 100%;
|
||
background: #fcf3e0;
|
||
border-radius: 80px 80px 50px 50px;
|
||
border: 6px solid #ffb882;
|
||
box-shadow: 0 20px 0 #9f7c5f, 0 30px 30px rgba(0,0,0,0.25);
|
||
padding: 30px 25px 25px;
|
||
}
|
||
|
||
.level-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: #fad6b3;
|
||
border-radius: 120px;
|
||
padding: 12px 25px;
|
||
margin-bottom: 30px;
|
||
border: 4px solid #c1804b;
|
||
box-shadow: 0 7px 0 #825e3c;
|
||
}
|
||
|
||
.level-badge {
|
||
background: #2b5e5e;
|
||
color: #f5ffd3;
|
||
font-size: 1.8rem;
|
||
font-weight: 700;
|
||
padding: 8px 35px;
|
||
border-radius: 70px;
|
||
border: 3px solid #fbd26a;
|
||
box-shadow: 0 5px 0 #143535;
|
||
transform: rotate(-1deg);
|
||
}
|
||
|
||
.stars-box {
|
||
display: flex;
|
||
gap: 8px;
|
||
background: #fcedb3;
|
||
padding: 10px 30px;
|
||
border-radius: 50px;
|
||
border: 3px solid #ab6f3f;
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.message-panel {
|
||
background: #feebc0;
|
||
padding: 15px 25px;
|
||
border-radius: 40px;
|
||
font-size: 1.4rem;
|
||
font-weight: 600;
|
||
color: #2a4f4f;
|
||
border: 3px solid #d68b4c;
|
||
text-align: center;
|
||
margin-bottom: 20px;
|
||
box-shadow: 0 5px 0 #ad7b55;
|
||
transition: all 0.3s;
|
||
min-height: 90px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
}
|
||
|
||
.color-status-bar {
|
||
background: #ffe5ca;
|
||
border-radius: 60px;
|
||
padding: 15px 20px;
|
||
margin-bottom: 20px;
|
||
border: 4px solid #c47748;
|
||
box-shadow: 0 5px 0 #9e5b31;
|
||
}
|
||
|
||
.color-status-title {
|
||
font-size: 1.3rem;
|
||
color: #2b5e5e;
|
||
font-weight: 700;
|
||
margin-bottom: 10px;
|
||
text-align: center;
|
||
}
|
||
|
||
.required-colors-grid {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 15px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.color-requirement {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
background: white;
|
||
padding: 8px 18px;
|
||
border-radius: 50px;
|
||
border: 3px solid #c1804b;
|
||
box-shadow: 0 3px 0 #8b5e3c;
|
||
transition: all 0.2s;
|
||
min-width: 120px;
|
||
}
|
||
|
||
.color-requirement.completed {
|
||
background: #c8e6c9;
|
||
border-color: #2e7d32;
|
||
box-shadow: 0 3px 0 #1b5e20;
|
||
}
|
||
|
||
.color-requirement.missing {
|
||
background: #ffecb3;
|
||
border-color: #ff6f00;
|
||
animation: pulse 1.5s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { transform: scale(1); }
|
||
50% { transform: scale(1.05); background: #ffe082; }
|
||
100% { transform: scale(1); }
|
||
}
|
||
|
||
.req-color-dot {
|
||
width: 35px;
|
||
height: 35px;
|
||
border-radius: 50%;
|
||
border: 3px solid #3a281b;
|
||
}
|
||
|
||
.req-color-name {
|
||
font-size: 1.2rem;
|
||
font-weight: 700;
|
||
color: #2a4f4f;
|
||
flex: 1;
|
||
}
|
||
|
||
.req-status {
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.painting-area {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20px;
|
||
justify-content: center;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.master-piece {
|
||
flex: 1 1 280px;
|
||
min-width: 280px;
|
||
background: #eadac0;
|
||
padding: 25px 20px;
|
||
border-radius: 60px;
|
||
border: 6px solid #a1683a;
|
||
box-shadow: 0 12px 0 #603f24, inset 0 -5px 0 #ffefd1;
|
||
}
|
||
|
||
.master-piece h3 {
|
||
text-align: center;
|
||
background: #a1582b;
|
||
color: white;
|
||
padding: 15px 10px;
|
||
border-radius: 50px;
|
||
margin-top: -50px;
|
||
margin-bottom: 25px;
|
||
font-size: 1.8rem;
|
||
border: 3px solid #ffbe7a;
|
||
}
|
||
|
||
.canvas-master {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
background: white;
|
||
border-radius: 40px;
|
||
box-shadow: 0 8px 0 #6f4f33;
|
||
border: 3px solid #402e1b;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.kid-canvas-wrap {
|
||
flex: 1 1 280px;
|
||
min-width: 280px;
|
||
background: #cfb595;
|
||
padding: 25px 20px;
|
||
border-radius: 60px;
|
||
border: 6px solid #4f7b6e;
|
||
box-shadow: 0 12px 0 #295b4e, inset 0 -5px 0 #dcf2e3;
|
||
}
|
||
|
||
.kid-canvas-wrap h3 {
|
||
text-align: center;
|
||
background: #1e6d5e;
|
||
color: white;
|
||
padding: 15px 10px;
|
||
border-radius: 50px;
|
||
margin-top: -50px;
|
||
margin-bottom: 25px;
|
||
font-size: 1.8rem;
|
||
border: 3px solid #9ef0d6;
|
||
}
|
||
|
||
.canvas-kid {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
background: white;
|
||
border-radius: 40px;
|
||
box-shadow: 0 8px 0 #2e5a4b;
|
||
border: 3px solid #1c463a;
|
||
cursor: crosshair;
|
||
touch-action: none;
|
||
}
|
||
|
||
.draw-tools {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 20px;
|
||
background: #ffe5ca;
|
||
padding: 15px 25px;
|
||
border-radius: 70px;
|
||
border: 4px solid #c47748;
|
||
box-shadow: 0 8px 0 #9e5b31;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.color-row {
|
||
display: flex;
|
||
gap: 8px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
}
|
||
|
||
.color-dot {
|
||
width: 45px;
|
||
height: 45px;
|
||
border-radius: 50%;
|
||
border: 4px solid #3a281b;
|
||
cursor: pointer;
|
||
box-shadow: 0 5px 0 #5d4d3a;
|
||
transition: all 0.1s;
|
||
position: relative;
|
||
}
|
||
|
||
.color-dot.active {
|
||
transform: scale(1.15);
|
||
border: 5px solid white;
|
||
box-shadow: 0 0 0 3px #2d6e6e, 0 5px 0 #5d4d3a;
|
||
}
|
||
|
||
.color-dot.used {
|
||
position: relative;
|
||
}
|
||
|
||
.color-dot.used::after {
|
||
content: "✓";
|
||
position: absolute;
|
||
top: -8px;
|
||
right: -8px;
|
||
background: #27ae60;
|
||
color: white;
|
||
width: 22px;
|
||
height: 22px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1rem;
|
||
font-weight: bold;
|
||
border: 2px solid white;
|
||
}
|
||
|
||
.size-pick {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
background: #b5aa95;
|
||
padding: 5px 15px;
|
||
border-radius: 40px;
|
||
border: 3px solid #564b38;
|
||
}
|
||
|
||
.size-btn {
|
||
background: #fcf3e6;
|
||
border: 3px solid #5d4f3b;
|
||
font-size: 2rem;
|
||
font-weight: 700;
|
||
width: 45px;
|
||
height: 45px;
|
||
border-radius: 30px;
|
||
box-shadow: 0 5px 0 #5e4b32;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.size-btn:active {
|
||
transform: translateY(4px);
|
||
box-shadow: none;
|
||
}
|
||
|
||
#sizeDisplay {
|
||
font-size: 1.6rem;
|
||
min-width: 45px;
|
||
text-align: center;
|
||
font-weight: 700;
|
||
background: #f0dbbc;
|
||
padding: 5px 0;
|
||
border-radius: 20px;
|
||
}
|
||
|
||
.action-group {
|
||
display: flex;
|
||
gap: 12px;
|
||
}
|
||
|
||
.action-btn {
|
||
background: #fae6cd;
|
||
border: 4px solid #946b42;
|
||
font-size: 1.3rem;
|
||
padding: 10px 22px;
|
||
border-radius: 50px;
|
||
cursor: pointer;
|
||
box-shadow: 0 7px 0 #75583a;
|
||
transition: 0.07s;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.action-btn:active {
|
||
transform: translateY(7px);
|
||
box-shadow: none;
|
||
}
|
||
|
||
.action-btn:disabled {
|
||
opacity: 0.5;
|
||
pointer-events: none;
|
||
transform: none;
|
||
box-shadow: 0 7px 0 #75583a;
|
||
}
|
||
|
||
.action-btn.success {
|
||
background: #b3e4b3;
|
||
border-color: #12874a;
|
||
box-shadow: 0 7px 0 #0a5f33;
|
||
}
|
||
|
||
.level-complete {
|
||
text-align: center;
|
||
background: #b3e4b3;
|
||
border: 4px solid #12874a;
|
||
border-radius: 50px;
|
||
padding: 20px;
|
||
font-size: 2rem;
|
||
font-weight: bold;
|
||
color: #054d2b;
|
||
margin-top: 20px;
|
||
animation: bounce 1s infinite;
|
||
}
|
||
|
||
@keyframes bounce {
|
||
0%, 100% { transform: translateY(0); }
|
||
50% { transform: translateY(-10px); }
|
||
}
|
||
|
||
.hidden {
|
||
display: none;
|
||
}
|
||
|
||
.celebrate {
|
||
animation: celebrate 0.5s ease;
|
||
}
|
||
|
||
@keyframes celebrate {
|
||
0% { transform: scale(1); }
|
||
50% { transform: scale(1.05); background: #ffd966; }
|
||
100% { transform: scale(1); }
|
||
}
|
||
|
||
.color-guide {
|
||
font-size: 1rem;
|
||
color: #2b5e5e;
|
||
background: #fcf3e0;
|
||
padding: 5px 15px;
|
||
border-radius: 30px;
|
||
display: inline-block;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="game-box" id="gameBox">
|
||
<div class="level-header">
|
||
<div class="level-badge"><span>🎨</span> مرحلة <span id="levelNumber">1</span>/5</div>
|
||
<div class="stars-box" id="starDisplay">⭐⭐⭐</div>
|
||
</div>
|
||
|
||
<!-- شريط حالة الألوان المطلوبة -->
|
||
<div class="color-status-bar" id="colorStatusBar">
|
||
<div class="color-status-title">🎯 الألوان المطلوبة في هذه المرحلة:</div>
|
||
<div id="requiredColorsGrid" class="required-colors-grid"></div>
|
||
</div>
|
||
|
||
<div class="message-panel" id="gameMessage">
|
||
👆 ابدأ الرسم!
|
||
</div>
|
||
|
||
<div class="painting-area">
|
||
<div class="master-piece">
|
||
<h3>🖼️ اللوحة الأصل</h3>
|
||
<canvas id="masterCanvas" class="canvas-master" width="300" height="300"></canvas>
|
||
</div>
|
||
|
||
<div class="kid-canvas-wrap">
|
||
<h3>🧑🎤 نسختك</h3>
|
||
<canvas id="kidCanvas" class="canvas-kid" width="300" height="300"></canvas>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="draw-tools">
|
||
<div class="color-row" id="colorPalette"></div>
|
||
<div class="size-pick">
|
||
<button class="size-btn" id="sizeDown">−</button>
|
||
<span id="sizeDisplay">8</span>
|
||
<button class="size-btn" id="sizeUp">+</button>
|
||
</div>
|
||
<div class="action-group">
|
||
<button class="action-btn" id="clearKidBtn">🧽 امسح</button>
|
||
<button class="action-btn" id="nextLevelBtn" disabled>➡️ التالي</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="levelCompleteMsg" class="level-complete hidden">✨ أحسنت! فتحت المرحلة التالية ✨</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
// ---------- تعريف دقيق للألوان مع نطاقات موسعة للبني ----------
|
||
const colorMap = [
|
||
// الألوان الأساسية
|
||
{ hex: '#1e5fb4', name: 'أزرق', ranges: [[0,50], [80,150], [150,220]] }, // أزرق
|
||
{ hex: '#c93838', name: 'أحمر', ranges: [[150,255], [0,80], [0,80]] }, // أحمر
|
||
{ hex: '#e6b422', name: 'أصفر', ranges: [[200,255], [150,220], [0,80]] }, // أصفر
|
||
{ hex: '#2b7d4d', name: 'أخضر', ranges: [[0,80], [100,180], [0,80]] }, // أخضر
|
||
|
||
// بني - نطاقات موسعة جداً للبني
|
||
{ hex: '#8B4513', name: 'بني', ranges: [[80,160], [40,100], [0,60]] }, // بني غامق
|
||
{ hex: '#b07d5e', name: 'بني فاتح', ranges: [[150,200], [100,150], [70,120]] }, // بني فاتح
|
||
{ hex: '#7d5335', name: 'بني', ranges: [[100,150], [60,100], [30,70]] }, // بني متوسط
|
||
{ hex: '#a0522d', name: 'بني', ranges: [[130,180], [70,120], [30,80]] }, // بني آخر
|
||
{ hex: '#7a4c29', name: 'بني', ranges: [[100,140], [60,90], [30,60]] }, // بني غامق
|
||
{ hex: '#b87333', name: 'بني برتقالي', ranges: [[160,200], [100,140], [40,80]] }, // بني مائل للبرتقالي
|
||
|
||
// ألوان أخرى
|
||
{ hex: '#000000', name: 'أسود', ranges: [[0,50], [0,50], [0,50]] },
|
||
{ hex: '#f57eb6', name: 'وردي', ranges: [[220,255], [100,180], [160,220]] },
|
||
{ hex: '#aa80ff', name: 'بنفسجي', ranges: [[150,220], [100,180], [220,255]] },
|
||
{ hex: '#cc6612', name: 'برتقالي', ranges: [[180,240], [80,140], [0,60]] },
|
||
{ hex: '#4fb86b', name: 'أخضر فاتح', ranges: [[50,120], [160,220], [50,120]] }
|
||
];
|
||
|
||
// المستويات مع أسماء ألوان واضحة
|
||
const levels = [
|
||
{
|
||
name: "الدائرة الزرقاء",
|
||
bg: '#ffffff',
|
||
shapes: [
|
||
{ type: 'circle', x: 150, y: 150, radius: 60, color: '#1e5fb4', colorName: 'أزرق' }
|
||
]
|
||
},
|
||
{
|
||
name: "المربع والدائرة",
|
||
bg: '#ffffff',
|
||
shapes: [
|
||
{ type: 'rect', x: 100, y: 100, w: 80, h: 80, color: '#c93838', colorName: 'أحمر' },
|
||
{ type: 'circle', x: 220, y: 220, radius: 35, color: '#e6b422', colorName: 'أصفر' }
|
||
]
|
||
},
|
||
{
|
||
name: "المثلث والخطوط",
|
||
bg: '#ffffff',
|
||
shapes: [
|
||
{ type: 'triangle', x1: 150, y1: 70, x2: 80, y2: 200, x3: 220, y3: 200, color: '#2b7d4d', colorName: 'أخضر' },
|
||
{ type: 'line', x1: 40, y1: 260, x2: 260, y2: 260, color: '#7a4c29', width: 6, colorName: 'بني' },
|
||
{ type: 'line', x1: 50, y1: 270, x2: 250, y2: 270, color: '#b87333', width: 4, colorName: 'بني برتقالي' }
|
||
]
|
||
},
|
||
{
|
||
name: "المنزل الجميل",
|
||
bg: '#f0f8ff',
|
||
shapes: [
|
||
{ type: 'rect', x: 110, y: 160, w: 120, h: 100, color: '#b07d5e', colorName: 'بني فاتح' },
|
||
{ type: 'triangle', x1: 80, y1: 160, x2: 260, y2: 160, x3: 170, y3: 70, color: '#b34e4e', colorName: 'أحمر' },
|
||
{ type: 'rect', x: 155, y: 210, w: 30, h: 50, color: '#dbb44b', colorName: 'أصفر' }
|
||
]
|
||
},
|
||
{
|
||
name: "الشجرة الخضراء",
|
||
bg: '#ecffe7',
|
||
shapes: [
|
||
{ type: 'rect', x: 135, y: 200, w: 30, h: 80, color: '#8B4513', colorName: 'بني' },
|
||
{ type: 'circle', x: 150, y: 150, radius: 45, color: '#2b7d4d', colorName: 'أخضر' },
|
||
{ type: 'circle', x: 115, y: 130, radius: 20, color: '#4fb86b', colorName: 'أخضر فاتح' },
|
||
{ type: 'circle', x: 185, y: 130, radius: 20, color: '#4fb86b', colorName: 'أخضر فاتح' }
|
||
]
|
||
}
|
||
];
|
||
|
||
// عناصر الصفحة
|
||
const masterCanvas = document.getElementById('masterCanvas');
|
||
const kidCanvas = document.getElementById('kidCanvas');
|
||
const ctxMaster = masterCanvas.getContext('2d');
|
||
const ctxKid = kidCanvas.getContext('2d');
|
||
|
||
const levelSpan = document.getElementById('levelNumber');
|
||
const starDisplay = document.getElementById('starDisplay');
|
||
const gameMessage = document.getElementById('gameMessage');
|
||
const requiredColorsGrid = document.getElementById('requiredColorsGrid');
|
||
const nextBtn = document.getElementById('nextLevelBtn');
|
||
const levelCompleteMsg = document.getElementById('levelCompleteMsg');
|
||
const clearKidBtn = document.getElementById('clearKidBtn');
|
||
const colorPalette = document.getElementById('colorPalette');
|
||
const sizeDown = document.getElementById('sizeDown');
|
||
const sizeUp = document.getElementById('sizeUp');
|
||
const sizeDisplay = document.getElementById('sizeDisplay');
|
||
|
||
let currentColor = colorMap[0].hex;
|
||
let brushSize = 8;
|
||
let currentLevel = 0;
|
||
let drawing = false;
|
||
let usedColors = new Set();
|
||
|
||
// تهيئة منتقي الألوان
|
||
function buildPalette() {
|
||
colorPalette.innerHTML = '';
|
||
colorMap.forEach((color, index) => {
|
||
const dot = document.createElement('div');
|
||
dot.className = 'color-dot';
|
||
dot.style.backgroundColor = color.hex;
|
||
dot.setAttribute('data-color', color.hex);
|
||
dot.setAttribute('data-name', color.name);
|
||
dot.addEventListener('click', (e) => {
|
||
document.querySelectorAll('.color-dot').forEach(d => d.classList.remove('active'));
|
||
dot.classList.add('active');
|
||
currentColor = color.hex;
|
||
});
|
||
colorPalette.appendChild(dot);
|
||
});
|
||
document.querySelectorAll('.color-dot')[0]?.classList.add('active');
|
||
}
|
||
buildPalette();
|
||
|
||
// تحديث حجم الفرشاة
|
||
function updateSizeDisplay() {
|
||
sizeDisplay.innerText = brushSize;
|
||
}
|
||
sizeDown.addEventListener('click', () => {
|
||
if (brushSize > 2) { brushSize -= 2; updateSizeDisplay(); }
|
||
});
|
||
sizeUp.addEventListener('click', () => {
|
||
if (brushSize < 30) { brushSize += 2; updateSizeDisplay(); }
|
||
});
|
||
updateSizeDisplay();
|
||
|
||
// رسم اللوحة الأصل
|
||
function drawMaster(levelIndex) {
|
||
const level = levels[levelIndex];
|
||
ctxMaster.clearRect(0, 0, 300, 300);
|
||
ctxMaster.fillStyle = level.bg || '#ffffff';
|
||
ctxMaster.fillRect(0, 0, 300, 300);
|
||
|
||
level.shapes.forEach(shape => {
|
||
ctxMaster.beginPath();
|
||
ctxMaster.fillStyle = shape.color;
|
||
ctxMaster.strokeStyle = shape.color;
|
||
ctxMaster.lineWidth = shape.width || 4;
|
||
|
||
switch (shape.type) {
|
||
case 'circle':
|
||
ctxMaster.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
|
||
shape.fill ? ctxMaster.fill() : ctxMaster.stroke();
|
||
break;
|
||
case 'rect':
|
||
shape.fill ? ctxMaster.fillRect(shape.x, shape.y, shape.w, shape.h) : ctxMaster.strokeRect(shape.x, shape.y, shape.w, shape.h);
|
||
break;
|
||
case 'triangle':
|
||
ctxMaster.moveTo(shape.x1, shape.y1);
|
||
ctxMaster.lineTo(shape.x2, shape.y2);
|
||
ctxMaster.lineTo(shape.x3, shape.y3);
|
||
ctxMaster.closePath();
|
||
shape.fill ? ctxMaster.fill() : ctxMaster.stroke();
|
||
break;
|
||
case 'line':
|
||
ctxMaster.moveTo(shape.x1, shape.y1);
|
||
ctxMaster.lineTo(shape.x2, shape.y2);
|
||
ctxMaster.stroke();
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
|
||
// مسح لوحة الطفل
|
||
function clearKid() {
|
||
ctxKid.clearRect(0, 0, 300, 300);
|
||
ctxKid.fillStyle = '#ffffff';
|
||
ctxKid.fillRect(0, 0, 300, 300);
|
||
usedColors.clear();
|
||
updateUI();
|
||
}
|
||
|
||
// دقيقة للتعرف على اللون بناءً على قيم RGB
|
||
function identifyColor(r, g, b) {
|
||
let bestMatch = null;
|
||
let bestScore = Infinity;
|
||
|
||
colorMap.forEach(color => {
|
||
// حساب المسافة اللونية
|
||
const rgb = hexToRgb(color.hex);
|
||
if (!rgb) return;
|
||
|
||
const distance = Math.sqrt(
|
||
Math.pow(r - rgb.r, 2) * 0.3 + // وزن أقل للأحمر
|
||
Math.pow(g - rgb.g, 2) * 0.4 + // وزن أكثر للأخضر (العين البشرية حساسة له)
|
||
Math.pow(b - rgb.b, 2) * 0.3 // وزن أقل للأزرق
|
||
);
|
||
|
||
// تحقق إضافي للبني - نطاقات خاصة
|
||
const isBrown = color.name.includes('بني');
|
||
if (isBrown) {
|
||
// البني يتميز بانخفاض اللون الأزرق
|
||
if (b > 120) return; // إذا كان الأزرق عالي، ليس بني
|
||
|
||
// البني نسبة الأحمر للأخضر محددة
|
||
if (r < 80 || g < 40) return;
|
||
|
||
// تعديل المسافة للبني
|
||
const brownScore = distance * 0.7; // وزن أقل للبني (نسامحه أكثر)
|
||
if (brownScore < bestScore) {
|
||
bestScore = brownScore;
|
||
bestMatch = color;
|
||
}
|
||
} else {
|
||
if (distance < bestScore) {
|
||
bestScore = distance;
|
||
bestMatch = color;
|
||
}
|
||
}
|
||
});
|
||
|
||
// تسامح أكبر للألوان
|
||
return bestScore < 70 ? bestMatch : null;
|
||
}
|
||
|
||
// تحليل الألوان المستخدمة في الرسم
|
||
function analyzeColors() {
|
||
const imageData = ctxKid.getImageData(0, 0, 300, 300);
|
||
const data = imageData.data;
|
||
const colorsFound = new Set();
|
||
|
||
// أخذ عينات من البكسل (كل 5 بكسل لتسريع التحليل)
|
||
for (let i = 0; i < data.length; i += 20) {
|
||
const r = data[i];
|
||
const g = data[i+1];
|
||
const b = data[i+2];
|
||
const a = data[i+3];
|
||
|
||
// تجاهل الخلفية البيضاء والشفافة
|
||
if (a < 10) continue;
|
||
if (r > 250 && g > 250 && b > 250) continue;
|
||
|
||
const color = identifyColor(r, g, b);
|
||
if (color) {
|
||
colorsFound.add(color.hex);
|
||
}
|
||
}
|
||
|
||
return colorsFound;
|
||
}
|
||
|
||
// تحديث واجهة المستخدم
|
||
function updateUI() {
|
||
// تحليل الألوان المستخدمة
|
||
const foundColors = analyzeColors();
|
||
usedColors = foundColors;
|
||
|
||
// تحديث علامات الاستخدام على ألوان الأداة
|
||
document.querySelectorAll('.color-dot').forEach(dot => {
|
||
const colorHex = dot.dataset.color;
|
||
if (usedColors.has(colorHex)) {
|
||
dot.classList.add('used');
|
||
} else {
|
||
dot.classList.remove('used');
|
||
}
|
||
});
|
||
|
||
// تحديث شبكة الألوان المطلوبة
|
||
updateRequiredColorsGrid();
|
||
|
||
// التحقق من الاكتمال
|
||
checkLevelCompletion();
|
||
}
|
||
|
||
// تحديث شبكة الألوان المطلوبة
|
||
function updateRequiredColorsGrid() {
|
||
const level = levels[currentLevel];
|
||
const requiredColors = [];
|
||
|
||
// جمع الألوان المطلوبة (بدون تكرار)
|
||
level.shapes.forEach(shape => {
|
||
if (shape.color && shape.colorName) {
|
||
requiredColors.push({
|
||
hex: shape.color,
|
||
name: shape.colorName
|
||
});
|
||
}
|
||
});
|
||
|
||
// إزالة التكرار
|
||
const uniqueColors = [];
|
||
const seen = new Set();
|
||
requiredColors.forEach(color => {
|
||
if (!seen.has(color.hex)) {
|
||
seen.add(color.hex);
|
||
uniqueColors.push(color);
|
||
}
|
||
});
|
||
|
||
requiredColorsGrid.innerHTML = '';
|
||
uniqueColors.forEach(color => {
|
||
const isUsed = usedColors.has(color.hex);
|
||
const div = document.createElement('div');
|
||
div.className = `color-requirement ${isUsed ? 'completed' : 'missing'}`;
|
||
div.innerHTML = `
|
||
<div class="req-color-dot" style="background-color: ${color.hex}"></div>
|
||
<span class="req-color-name">${color.name}</span>
|
||
<span class="req-status">${isUsed ? '✓' : '○'}</span>
|
||
`;
|
||
requiredColorsGrid.appendChild(div);
|
||
});
|
||
}
|
||
|
||
// التحقق من اكتمال المستوى
|
||
function checkLevelCompletion() {
|
||
const level = levels[currentLevel];
|
||
|
||
// جمع الألوان المطلوبة
|
||
const requiredColors = new Set();
|
||
level.shapes.forEach(shape => {
|
||
if (shape.color) {
|
||
requiredColors.add(shape.color);
|
||
}
|
||
});
|
||
|
||
// التحقق من وجود كل لون مطلوب
|
||
let allColorsUsed = true;
|
||
const missingColors = [];
|
||
|
||
requiredColors.forEach(reqColor => {
|
||
let found = false;
|
||
usedColors.forEach(usedColor => {
|
||
// مقارنة مرنة للألوان (خاصة للبني)
|
||
if (colorDistance(reqColor, usedColor) < 60) {
|
||
found = true;
|
||
}
|
||
});
|
||
if (!found) {
|
||
allColorsUsed = false;
|
||
const shape = level.shapes.find(s => s.color === reqColor);
|
||
if (shape && shape.colorName) {
|
||
missingColors.push(shape.colorName);
|
||
}
|
||
}
|
||
});
|
||
|
||
// تحديث رسالة اللعبة وزر التالي
|
||
if (allColorsUsed && usedColors.size > 0) {
|
||
nextBtn.disabled = false;
|
||
nextBtn.classList.add('success');
|
||
gameMessage.innerHTML = '🎉 ممتاز! استخدمت كل الألوان المطلوبة ✓';
|
||
gameMessage.style.background = '#b3e4b3';
|
||
gameMessage.style.border = '4px solid #12874a';
|
||
} else {
|
||
nextBtn.disabled = true;
|
||
nextBtn.classList.remove('success');
|
||
|
||
if (missingColors.length > 0) {
|
||
gameMessage.innerHTML = `🎨 الألوان الناقصة: ${missingColors.join('، ')}`;
|
||
} else {
|
||
gameMessage.innerHTML = '👆 استخدم الألوان من اللوحة الأصل';
|
||
}
|
||
gameMessage.style.background = '#feebc0';
|
||
gameMessage.style.border = '3px solid #d68b4c';
|
||
}
|
||
}
|
||
|
||
// دوال مساعدة للألوان
|
||
function hexToRgb(hex) {
|
||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||
return result ? {
|
||
r: parseInt(result[1], 16),
|
||
g: parseInt(result[2], 16),
|
||
b: parseInt(result[3], 16)
|
||
} : null;
|
||
}
|
||
|
||
function colorDistance(hex1, hex2) {
|
||
const rgb1 = hexToRgb(hex1);
|
||
const rgb2 = hexToRgb(hex2);
|
||
if (!rgb1 || !rgb2) return 999;
|
||
|
||
return Math.sqrt(
|
||
Math.pow(rgb1.r - rgb2.r, 2) * 0.3 +
|
||
Math.pow(rgb1.g - rgb2.g, 2) * 0.4 +
|
||
Math.pow(rgb1.b - rgb2.b, 2) * 0.3
|
||
);
|
||
}
|
||
|
||
// أحداث الرسم
|
||
function startDrawing(e) {
|
||
e.preventDefault();
|
||
drawing = true;
|
||
ctxKid.beginPath();
|
||
draw(e);
|
||
}
|
||
|
||
function stopDrawing() {
|
||
drawing = false;
|
||
ctxKid.beginPath();
|
||
updateUI();
|
||
}
|
||
|
||
function draw(e) {
|
||
if (!drawing) return;
|
||
e.preventDefault();
|
||
|
||
let clientX, clientY;
|
||
if (e.touches) {
|
||
clientX = e.touches[0].clientX;
|
||
clientY = e.touches[0].clientY;
|
||
} else {
|
||
clientX = e.clientX;
|
||
clientY = e.clientY;
|
||
}
|
||
|
||
const rect = kidCanvas.getBoundingClientRect();
|
||
const scaleX = kidCanvas.width / rect.width;
|
||
const scaleY = kidCanvas.height / rect.height;
|
||
|
||
const canvasX = (clientX - rect.left) * scaleX;
|
||
const canvasY = (clientY - rect.top) * scaleY;
|
||
|
||
if (canvasX < 0 || canvasX > 300 || canvasY < 0 || canvasY > 300) return;
|
||
|
||
ctxKid.lineCap = 'round';
|
||
ctxKid.lineJoin = 'round';
|
||
ctxKid.strokeStyle = currentColor;
|
||
ctxKid.lineWidth = brushSize;
|
||
|
||
ctxKid.lineTo(canvasX, canvasY);
|
||
ctxKid.stroke();
|
||
ctxKid.beginPath();
|
||
ctxKid.moveTo(canvasX, canvasY);
|
||
}
|
||
|
||
// إضافة مستمعي الأحداث
|
||
kidCanvas.addEventListener('mousedown', startDrawing);
|
||
kidCanvas.addEventListener('mousemove', draw);
|
||
kidCanvas.addEventListener('mouseup', stopDrawing);
|
||
kidCanvas.addEventListener('mouseleave', stopDrawing);
|
||
kidCanvas.addEventListener('touchstart', startDrawing, { passive: false });
|
||
kidCanvas.addEventListener('touchmove', draw, { passive: false });
|
||
kidCanvas.addEventListener('touchend', stopDrawing);
|
||
kidCanvas.addEventListener('touchcancel', stopDrawing);
|
||
kidCanvas.addEventListener('contextmenu', e => e.preventDefault());
|
||
|
||
clearKidBtn.addEventListener('click', clearKid);
|
||
|
||
// تحميل المستوى
|
||
function loadLevel(index) {
|
||
currentLevel = index;
|
||
drawMaster(currentLevel);
|
||
clearKid();
|
||
levelSpan.innerText = (currentLevel + 1) + '/' + levels.length;
|
||
|
||
// تحديث النجوم
|
||
let stars = '';
|
||
for (let i = 0; i < levels.length; i++) {
|
||
stars += i <= currentLevel ? '⭐' : '☆';
|
||
}
|
||
starDisplay.innerText = stars;
|
||
|
||
nextBtn.disabled = true;
|
||
nextBtn.classList.remove('success');
|
||
levelCompleteMsg.classList.add('hidden');
|
||
|
||
gameMessage.innerHTML = levels[currentLevel].name + ' - ابدأ الرسم!';
|
||
gameMessage.style.background = '#feebc0';
|
||
|
||
// تحديث الألوان المطلوبة
|
||
updateRequiredColorsGrid();
|
||
}
|
||
|
||
// المستوى التالي
|
||
nextBtn.addEventListener('click', () => {
|
||
if (currentLevel < levels.length - 1) {
|
||
currentLevel++;
|
||
loadLevel(currentLevel);
|
||
} else {
|
||
levelCompleteMsg.classList.remove('hidden');
|
||
levelCompleteMsg.innerText = '🎉 🏆 أنت فنان عظيم! أكملت كل المراحل 🏆 🎉';
|
||
nextBtn.disabled = true;
|
||
gameMessage.innerHTML = '✨ ألف مبروك! ✨';
|
||
}
|
||
});
|
||
|
||
// بداية اللعبة
|
||
loadLevel(0);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html> |