الجمعة، 11 أبريل 2025

import pygame import json import os import sys from pygame.locals import * import math class ScratchLikeApp: def __init__(self): pygame.init() pygame.mixer.init() # تهيئة نظام الصوت self.width, self.height = 1280, 720 self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption("Scratch Like - برمجة تفاعلية متطورة") # تحميل الخطوط try: self.font = pygame.font.Font(None, 24) self.title_font = pygame.font.Font(None, 28) self.header_font = pygame.font.Font(None, 32) except: self.font = pygame.font.SysFont('Arial', 16) self.title_font = pygame.font.SysFont('Arial', 20) self.header_font = pygame.font.SysFont('Arial', 24) # نظام الألوان المحسن self.colors = { 'primary': (74, 111, 165), # أزرق رئيسي 'secondary': (255, 159, 28), # برتقالي 'background': (248, 249, 250), # خلفية فاتحة 'panel': (233, 236, 239), 'text': (33, 37, 41), 'highlight': (255, 209, 102), # أصفر للتمييز 'success': (40, 167, 69), 'danger': (220, 53, 69), 'block_colors': { 'motion': (76, 201, 240), # أزرق فاتح 'looks': (247, 37, 133), # وردي 'sound': (114, 9, 183), # بنفسجي 'control': (58, 134, 255), # أزرق 'event': (46, 196, 182), # تركواز 'variables': (108, 117, 125) # رمادي } } # تحميل المؤثرات الصوتية self.sounds = { 'click': self.load_sound('click.wav'), 'success': self.load_sound('success.wav'), 'error': self.load_sound('error.wav'), 'connect': self.load_sound('connect.wav') } # الكتل المتاحة (مصنفة) self.blocks = { 'الأحداث': [ {'type': 'on_start', 'name': 'عند البدء', 'inputs': [], 'color': 'event'}, {'type': 'on_click', 'name': 'عند النقر', 'inputs': [], 'color': 'event'}, {'type': 'on_key', 'name': 'عند الضغط على مفتاح', 'inputs': [ {'type': 'dropdown', 'options': ['مسافة', 'أعلى', 'أسفل', 'يسار', 'يمين'], 'value': 'مسافة'} ], 'color': 'event'} ], 'الحركة': [ {'type': 'move', 'name': 'تحرك', 'inputs': [ {'type': 'number', 'default': 10, 'value': 10} ], 'color': 'motion'}, {'type': 'turn', 'name': 'استدر', 'inputs': [ {'type': 'number', 'default': 15, 'value': 15} ], 'color': 'motion'}, {'type': 'go_to', 'name': 'انتقل إلى', 'inputs': [ {'type': 'dropdown', 'options': ['الماوس', 'المركز', 'عشوائي'], 'value': 'الماوس'} ], 'color': 'motion'} ], 'المظهر': [ {'type': 'say', 'name': 'قل', 'inputs': [ {'type': 'text', 'default': 'مرحبا!', 'value': 'مرحبا!'} ], 'color': 'looks'}, {'type': 'change_size', 'name': 'غير الحجم إلى', 'inputs': [ {'type': 'number', 'default': 100, 'value': 100} ], 'color': 'looks'}, {'type': 'show', 'name': 'أظهر', 'inputs': [], 'color': 'looks'}, {'type': 'hide', 'name': 'أخف', 'inputs': [], 'color': 'looks'} ], 'الصوت': [ {'type': 'play_sound', 'name': 'شغل الصوت', 'inputs': [ {'type': 'dropdown', 'options': ['بونج', 'نقر', 'نجاح'], 'value': 'نقر'} ], 'color': 'sound'}, {'type': 'stop_sounds', 'name': 'أوقف كل الأصوات', 'inputs': [], 'color': 'sound'}, {'type': 'change_volume', 'name': 'غير مستوى الصوت', 'inputs': [ {'type': 'number', 'default': 50, 'value': 50} ], 'color': 'sound'} ], 'التحكم': [ {'type': 'repeat', 'name': 'كرر', 'inputs': [ {'type': 'number', 'default': 10, 'value': 10} ], 'color': 'control'}, {'type': 'wait', 'name': 'انتظر', 'inputs': [ {'type': 'number', 'default': 1, 'value': 1} ], 'color': 'control'}, {'type': 'if', 'name': 'إذا', 'inputs': [ {'type': 'condition', 'default': 'True', 'value': 'True'} ], 'color': 'control'} ], 'المتغيرات': [ {'type': 'set_var', 'name': 'اجعل', 'inputs': [ {'type': 'text', 'default': 'متغير', 'value': 'متغير'}, {'type': 'number', 'default': 0, 'value': 0} ], 'color': 'variables'} ] } # حالة التطبيق self.project = { 'name': 'مشروع جديد', 'sprites': [ { 'name': 'الكائن 1', 'x': 100, 'y': 100, 'size': 100, 'direction': 90, 'visible': True, 'costumes': [], 'current_costume': 0, 'sounds': [] } ], 'scripts': [[]], 'variables': {}, 'current_sprite': 0, 'volume': 70 } # تحميل الأصوات الافتراضية self.load_default_sounds() # واجهة المستخدم self.tabs = [ {'name': 'البرمجة', 'icon': '🧩', 'active': True}, {'name': 'الكائنات', 'icon': '👾', 'active': False}, {'name': 'الأصوات', 'icon': '🎵', 'active': False}, {'name': 'الإعدادات', 'icon': '⚙️', 'active': False} ] self.current_tab = 0 self.dragging = False self.current_block = None self.drag_offset = (0, 0) self.hover_button = None self.hover_tab = None self.hover_sprite = None self.editing_input = None self.output = "مرحباً! ابدأ بسحب الكتل إلى مساحة العمل" self.running = False self.show_tutorial = True # إنشاء مجلدات المشاريع إذا لم تكن موجودة if not os.path.exists('projects'): os.makedirs('projects') if not os.path.exists('projects/sounds'): os.makedirs('projects/sounds') # تحميل أي موارد إضافية self.load_resources() # تحميل الأصوات للكائنات for sprite in self.project['sprites']: self.load_sprite_sounds(sprite) def load_sound(self, filename): """تحميل صوت من ملف أو استخدام صوت افتراضي إذا لم يوجد""" try: if os.path.exists(f'projects/sounds/{filename}'): return pygame.mixer.Sound(f'projects/sounds/{filename}') else: # إنشاء صوت افتراضي (نغمة بسيطة) sound = pygame.mixer.Sound(buffer=bytearray([128 + int(127 * math.sin(i * 0.1)) for i in range(44100)])) return sound except: return None def load_default_sounds(self): """إنشاء أصوات افتراضية إذا لم تكن موجودة""" default_sounds = { 'click.wav': (440, 0.1), 'success.wav': (880, 0.3), 'error.wav': (220, 0.5), 'connect.wav': (660, 0.2) } for filename, (freq, duration) in default_sounds.items(): if not os.path.exists(f'projects/sounds/{filename}'): try: # إنشاء نغمة بسيطة وحفظها sample_rate = 44100 samples = int(sample_rate * duration) buf = bytearray(samples) for i in range(samples): buf[i] = 128 + int(127 * math.sin(2 * math.pi * freq * i / sample_rate)) sound = pygame.mixer.Sound(buffer=buf) sound.set_volume(0.5) pygame.mixer.Sound.save(sound, f'projects/sounds/{filename}') except: continue def load_sprite_sounds(self, sprite): """تحميل الأصوات المرتبطة بالكائن""" sprite['sounds'] = [] sprite_sounds_dir = f'projects/sounds/{sprite["name"]}' if os.path.exists(sprite_sounds_dir): for file in os.listdir(sprite_sounds_dir): if file.lower().endswith(('.wav', '.ogg', '.mp3')): try: sound = pygame.mixer.Sound(f'{sprite_sounds_dir}/{file}') sprite['sounds'].append({ 'name': os.path.splitext(file)[0], 'sound': sound, 'path': f'{sprite_sounds_dir}/{file}' }) except: continue # إضافة أصوات افتراضية إذا لم يكن هناك أصوات if not sprite['sounds']: for name in ['نغمة 1', 'نغمة 2']: sprite['sounds'].append({ 'name': name, 'sound': self.load_sound('click.wav'), 'path': None }) def load_resources(self): """تحميل الموارد الإضافية""" try: # تحميل أي صور موجودة للكائنات for sprite in self.project['sprites']: sprite['costumes'] = [] sprite_dir = f'projects/{sprite["name"]}' if os.path.exists(sprite_dir): for file in os.listdir(sprite_dir): if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): try: img = pygame.image.load(f'{sprite_dir}/{file}') img = pygame.transform.scale(img, (100, 100)) sprite['costumes'].append({ 'name': os.path.splitext(file)[0], 'image': img, 'path': f'{sprite_dir}/{file}' }) except: continue # إذا لم يكن هناك مظاهر، نضيف مظهر افتراضي if not sprite['costumes']: default_surface = pygame.Surface((100, 100), pygame.SRCALPHA) pygame.draw.circle(default_surface, (255, 100, 100), (50, 50), 45) sprite['costumes'].append({ 'name': 'مظهر افتراضي', 'image': default_surface, 'path': None }) except Exception as e: print(f"خطأ في تحميل الموارد: {e}") def draw_block(self, block, x, y, width=200, is_template=False, is_event=False): """رسم كتلة برمجية مع التصميم المحسن""" color = self.colors['block_colors'][block.get('color', 'control')] # إذا كانت كتلة حدث رئيسية if is_event: height = 60 pygame.draw.rect(self.screen, color, (x, y, width, height), border_radius=12) pygame.draw.rect(self.screen, self.darken_color(color), (x, y, width, height), 2, border_radius=12) else: height = 50 pygame.draw.rect(self.screen, color, (x, y, width, height), border_radius=10) pygame.draw.rect(self.screen, self.darken_color(color), (x, y, width, height), 2, border_radius=10) # تأثير ظل للكتل غير القوالب if not is_template: shadow = pygame.Surface((width, height), pygame.SRCALPHA) shadow.fill((0, 0, 0, 30)) self.screen.blit(shadow, (x+3, y+3)) # عرض اسم الكتلة text = self.title_font.render(block['name'], True, (255, 255, 255)) self.screen.blit(text, (x + 15, y + (20 if is_event else 15))) # عرض المدخلات إذا كانت موجودة if 'inputs' in block and not is_template: input_y = y + 40 if is_event else y + 30 for i, inp in enumerate(block['inputs']): if inp['type'] == 'number': input_rect = pygame.Rect(x + 120, input_y + i*25, 60, 25) pygame.draw.rect(self.screen, (255, 255, 255), input_rect, border_radius=5) pygame.draw.rect(self.screen, (0, 0, 0), input_rect, 1, border_radius=5) val = str(inp.get('value', inp.get('default', ''))) input_text = self.font.render(val, True, (0, 0, 0)) self.screen.blit(input_text, (x + 125, input_y + i*25 + 3)) elif inp['type'] == 'text': input_rect = pygame.Rect(x + 120, input_y + i*25, 120, 25) pygame.draw.rect(self.screen, (255, 255, 255), input_rect, border_radius=5) pygame.draw.rect(self.screen, (0, 0, 0), input_rect, 1, border_radius=5) val = str(inp.get('value', inp.get('default', ''))[:15] input_text = self.font.render(val, True, (0, 0, 0)) self.screen.blit(input_text, (x + 125, input_y + i*25 + 3)) elif inp['type'] == 'dropdown': input_rect = pygame.Rect(x + 120, input_y + i*25, 100, 25) pygame.draw.rect(self.screen, (255, 255, 255), input_rect, border_radius=5) pygame.draw.rect(self.screen, (0, 0, 0), input_rect, 1, border_radius=5) selected = inp.get('value', inp.get('options', [''])[0]) input_text = self.font.render(selected, True, (0, 0, 0)) self.screen.blit(input_text, (x + 125, input_y + i*25 + 3)) return pygame.Rect(x, y, width, height) def darken_color(self, color, factor=0.7): """تغميق اللون لعمل حدود أو تأثيرات""" return tuple(max(0, int(c * factor)) for c in color) def draw_palette(self): """رسم لوحة الكتل مع التصميم الجديد""" # خلفية اللوحة pygame.draw.rect(self.screen, self.colors['panel'], (10, 50, 250, self.height-160), border_radius=15) pygame.draw.rect(self.screen, self.darken_color(self.colors['panel']), (10, 50, 250, self.height-160), 2, border_radius=15) # شريط عنوان اللوحة pygame.draw.rect(self.screen, self.colors['primary'], (10, 50, 250, 40), border_top_left_radius=15, border_top_right_radius=15) title = self.header_font.render("الكتل البرمجية", True, (255, 255, 255)) self.screen.blit(title, (20, 60)) # عرض الكتل المصنفة y_offset = 100 for category, blocks in self.blocks.items(): # عنوان الفئة pygame.draw.rect(self.screen, self.lighten_color(self.colors['panel']), (15, y_offset-25, 240, 30), border_radius=5) cat_text = self.title_font.render(category, True, self.colors['text']) self.screen.blit(cat_text, (20, y_offset-20)) # كتل الفئة for block in blocks: block_rect = self.draw_block(block, 20, y_offset, 220, True) y_offset += 60 y_offset += 20 # مسافة بين الفئات def lighten_color(self, color, factor=0.1): """تفتيح اللون لعناوين الفئات""" return tuple(min(255, int(c + (255 - c) * factor)) for c in color) def draw_workspace(self): """رسم مساحة العمل مع التصميم المحسن""" # خلفية مساحة العمل pygame.draw.rect(self.screen, (255, 255, 255), (270, 50, self.width-280, self.height-120), border_radius=15) pygame.draw.rect(self.screen, self.colors['primary'], (270, 50, self.width-280, self.height-120), 2, border_radius=15) # المسرح المصغر stage_rect = pygame.Rect(self.width-300, 70, 260, 180) pygame.draw.rect(self.screen, (240, 240, 240), stage_rect, border_radius=10) pygame.draw.rect(self.screen, (200, 200, 200), stage_rect, 2, border_radius=10) # عرض الكائنات على المسرح for sprite in self.project['sprites']: if sprite['visible'] and sprite['costumes']: costume = sprite['costumes'][sprite['current_costume']] scale = min(50 / max(costume['image'].get_width(), 1), 50 / max(costume['image'].get_height(), 1)) scaled_width = int(costume['image'].get_width() * scale) scaled_height = int(costume['image'].get_height() * scale) scaled_img = pygame.transform.scale(costume['image'], (scaled_width, scaled_height)) # حساب الموقع على المسرح المصغر stage_x = self.width-300 + 130 + (sprite['x'] - 240) / 5 stage_y = 70 + 90 + (sprite['y'] - 180) / 5 # تدوير الصورة rotated_img = pygame.transform.rotate(scaled_img, -sprite['direction'] + 90) rect = rotated_img.get_rect(center=(stage_x, stage_y)) self.screen.blit(rotated_img, rect.topleft) # عرض الكتل في مساحة العمل y_offset = 70 for script in self.project['scripts'][self.current_tab]: if script['event']: event_rect = self.draw_block(script['event'], 290, y_offset, 250, False, True) y_offset += 70 for block in script['blocks']: block_rect = self.draw_block(block, 320, y_offset, 220) y_offset += 60 # تأثيرات السحب if self.dragging and self.current_block: self.draw_dragging_block() def draw_dragging_block(self): """رسم الكتلة أثناء سحبها بتأثيرات خاصة""" mouse_pos = pygame.mouse.get_pos() width = 250 if self.current_block['type'].startswith('on_') else 220 # تأثير شفافية block_surface = pygame.Surface((width, 60 if self.current_block['type'].startswith('on_') else 50), pygame.SRCALPHA) color = self.colors['block_colors'][self.current_block.get('color', 'control')] block_surface.fill((*color, 200)) # تأثير ظل shadow = pygame.Surface((width + 5, (60 if self.current_block['type'].startswith('on_') else 50) + 5), pygame.SRCALPHA) shadow.fill((0, 0, 0, 50)) self.screen.blit(shadow, (mouse_pos[0] - self.drag_offset[0] + 3, mouse_pos[1] - self.drag_offset[1] + 3)) # رسم الكتلة self.screen.blit(block_surface, (mouse_pos[0] - self.drag_offset[0], mouse_pos[1] - self.drag_offset[1])) # رسم النص text = self.title_font.render(self.current_block['name'], True, (255, 255, 255)) self.screen.blit(text, (mouse_pos[0] - self.drag_offset[0] + 15, mouse_pos[1] - self.drag_offset[1] + (20 if self.current_block['type'].startswith('on_') else 15))) def draw_tabs(self): """رسم تبويبات الواجهة بتصميم حديث""" for i, tab in enumerate(self.tabs): tab_rect = pygame.Rect(270 + i*150, 10, 140, 40) color = self.colors['primary'] if i == self.current_tab else self.lighten_color(self.colors['panel'], 0.3) hover_color = self.lighten_color(color, 0.2) current_color = hover_color if self.hover_tab == i else color pygame.draw.rect(self.screen, current_color, tab_rect, border_radius=20) pygame.draw.rect(self.screen, self.darken_color(current_color), tab_rect, 2, border_radius=20) # أيقونة التبويب icon = self.font.render(tab['icon'], True, (255, 255, 255)) self.screen.blit(icon, (270 + i*150 + 15, 20)) # اسم التبويب tab_text = self.title_font.render(tab['name'], True, (255, 255, 255)) self.screen.blit(tab_text, (270 + i*150 + 45, 20)) # زر إضافة تبويب جديد add_rect = pygame.Rect(270 + len(self.tabs)*150 + 10, 15, 30, 30) pygame.draw.rect(self.screen, self.colors['secondary'], add_rect, border_radius=15) add_text = self.title_font.render("+", True, (255, 255, 255)) self.screen.blit(add_text, (270 + len(self.tabs)*150 + 20, 20)) return add_rect def draw_toolbar(self): """رسم شريط الأدوات العائم""" toolbar_rect = pygame.Rect(self.width - 80, self.height - 80, 60, 60) pygame.draw.circle(self.screen, self.colors['primary'], (self.width - 50, self.height - 50), 30) pygame.draw.circle(self.screen, self.darken_color(self.colors['primary']), (self.width - 50, self.height - 50), 30, 2) # أيقونة القائمة menu_icon = [ (self.width - 60, self.height - 55, 20, 5), (self.width - 60, self.height - 50, 20, 5), (self.width - 60, self.height - 45, 20, 5) ] for x, y, w, h in menu_icon: pygame.draw.rect(self.screen, (255, 255, 255), (x, y, w, h), border_radius=2) # القائمة الموسعة عند النقر if self.hover_button == 'toolbar': tools = [ ('💾', 'حفظ', (self.width - 180, self.height - 120)), ('▶️', 'تشغيل', (self.width - 180, self.height - 70)), ('🔄', 'إعادة تعيين', (self.width - 120, self.height - 120)), ('🎨', 'المظاهر', (self.width - 120, self.height - 70)), ('🔊', 'الأصوات', (self.width - 60, self.height - 120)) ] for icon, text, pos in tools: pygame.draw.rect(self.screen, self.colors['secondary'], (*pos, 50, 40), border_radius=10) icon_surf = self.font.render(icon, True, (255, 255, 255)) self.screen.blit(icon_surf, (pos[0] + 15, pos[1] + 5)) text_surf = self.font.render(text, True, (255, 255, 255)) self.screen.blit(text_surf, (pos[0] + 5, pos[1] + 25)) return toolbar_rect def draw_output(self): """رسم منطقة الإخراج مع تصميم حديث""" output_rect = pygame.Rect(270, self.height-60, self.width-280, 50) pygame.draw.rect(self.screen, (255, 255, 255), output_rect, border_radius=10) pygame.draw.rect(self.screen, self.colors['primary'], output_rect, 2, border_radius=10) # نص الإخراج مع تقطيع إذا كان طويلاً output_text = self.output[:100] + "..." if len(self.output) > 100 else self.output text_surf = self.font.render(output_text, True, (0, 0, 0)) self.screen.blit(text_surf, (280, self.height-50)) # أيقونة حالة التشغيل status_color = self.colors['success'] if self.running else self.colors['danger'] pygame.draw.circle(self.screen, status_color, (self.width-40, self.height-35), 8) def draw_sprite_panel(self): """رسم لوحة الكائنات المحسنة""" panel_rect = pygame.Rect(10, self.height-100, 250, 90) pygame.draw.rect(self.screen, self.colors['panel'], panel_rect, border_radius=15) pygame.draw.rect(self.screen, self.darken_color(self.colors['panel']), panel_rect, 2, border_radius=15) # عنوان اللوحة title = self.title_font.render("الكائنات", True, self.colors['text']) self.screen.blit(title, (20, self.height-90)) # قائمة الكائنات x_offset = 20 for i, sprite in enumerate(self.project['sprites']): sprite_rect = pygame.Rect(x_offset, self.height-70, 60, 60) color = self.colors['primary'] if i == self.project['current_sprite'] else self.colors['panel'] hover_color = self.lighten_color(color, 0.2) current_color = hover_color if self.hover_sprite == i else color pygame.draw.rect(self.screen, current_color, sprite_rect, border_radius=10) pygame.draw.rect(self.screen, self.darken_color(current_color), sprite_rect, 2, border_radius=10) # عرض المظهر الحالي للكائن if sprite['costumes']: costume = sprite['costumes'][sprite['current_costume']] scaled_img = pygame.transform.scale(costume['image'], (40, 40)) self.screen.blit(scaled_img, (x_offset + 10, self.height-65)) x_offset += 70 # زر إضافة كائن جديد add_rect = pygame.Rect(x_offset, self.height-65, 30, 30) pygame.draw.rect(self.screen, self.colors['secondary'], add_rect, border_radius=15) add_text = self.title_font.render("+", True, (255, 255, 255)) self.screen.blit(add_text, (x_offset + 10, self.height-60)) return add_rect def draw_tutorial(self): """رسم فقاعة المساعدة التفاعلية""" if self.show_tutorial: help_rect = pygame.Rect(300, 100, 350, 180) pygame.draw.rect(self.screen, (255, 255, 255), help_rect, border_radius=20) pygame.draw.rect(self.screen, self.colors['primary'], help_rect, 2, border_radius=20) # رأس المساعدة pygame.draw.rect(self.screen, self.colors['primary'], (300, 100, 350, 40), border_top_left_radius=20, border_top_right_radius=20) title = self.title_font.render("كيف تبدأ؟", True, (255, 255, 255)) self.screen.blit(title, (320, 110)) # محتوى المساعدة help_text = [ "1. اسحب الكتل من اللوحة اليسرى", "2. أفلتها في مساحة العمل", "3. صل الكتل مع بعضها", "4. اضغط على تشغيل لتنفيذ البرنامج", "5. استخدم تبويب الكائنات لإدارة الشخصيات" ] for i, line in enumerate(help_text): text = self.font.render(line, True, self.colors['text']) self.screen.blit(text, (320, 150 + i*25)) # زر إغلاق close_rect = pygame.Rect(620, 110, 20, 20) pygame.draw.rect(self.screen, self.colors['danger'], close_rect, border_radius=10) close_text = self.font.render("✕", True, (255, 255, 255)) self.screen.blit(close_text, (625, 110)) return close_rect return None def play_sound(self, name): """تشغيل صوت مع ضبط مستوى الصوت""" if name in self.sounds and self.sounds[name]: self.sounds[name].set_volume(self.project['volume'] / 100) self.sounds[name].play() def execute_scripts(self): """تنفيذ السكربتات مع دعم الأصوات""" self.running = True self.output = "جاري التنفيذ..." self.play_sound('success') sprite = self.project['sprites'][self.project['current_sprite']] for script in self.project['scripts'][self.current_tab]: if script['event']['type'] == 'on_start': for block in script['blocks']: try: if block['type'] == 'move': steps = int(block['inputs'][0].get('value', 10)) sprite['x'] += steps self.output += f"\nتحرك {steps} خطوة" elif block['type'] == 'play_sound': sound_name = block['inputs'][0].get('value', 'نقر') self.play_sound(sound_name) self.output += f"\nتشغيل صوت: {sound_name}" # يمكن إضافة المزيد من الأوامر هنا except Exception as e: self.output += f"\nخطأ: {str(e)}" self.play_sound('error') self.output += "\nتم التنفيذ بنجاح" self.running = False def run(self): """الحلقة الرئيسية للتطبيق""" clock = pygame.time.Clock() running = True while running: mouse_pos = pygame.mouse.get_pos() self.hover_button = None self.hover_tab = None self.hover_sprite = None # معالجة الأحداث for event in pygame.event.get(): if event.type == QUIT: running = False elif event.type == MOUSEBUTTONDOWN: # التحقق من النقر على الكتل if 10 <= mouse_pos[0] <= 260 and 50 <= mouse_pos[1] <= self.height-110: y_offset = 100 block_clicked = None for category, blocks in self.blocks.items(): y_offset += 30 for block in blocks: block_rect = pygame.Rect(20, y_offset, 220, 50) if block_rect.collidepoint(mouse_pos): block_clicked = block.copy() self.drag_offset = (mouse_pos[0] - 20, mouse_pos[1] - y_offset) self.play_sound('click') break y_offset += 60 if block_clicked: break if block_clicked: self.dragging = True self.current_block = block_clicked # التحقق من النقر على الأزرار الأخرى elif self.hover_tab is not None: self.current_tab = self.hover_tab self.play_sound('click') elif self.hover_sprite is not None: self.project['current_sprite'] = self.hover_sprite self.play_sound('connect') elif self.hover_button == 'toolbar': self.play_sound('click') elif event.type == MOUSEBUTTONUP: if self.dragging and self.current_block: # إذا تم إسقاط الكتلة في مساحة العمل if 270 <= mouse_pos[0] <= self.width-10 and 50 <= mouse_pos[1] <= self.height-70: if self.current_block['type'].startswith('on_'): self.project['scripts'][self.current_tab].append({ 'event': self.current_block, 'blocks': [] }) else: if self.project['scripts'][self.current_tab]: self.project['scripts'][self.current_tab][-1]['blocks'].append(self.current_block) else: self.project['scripts'][self.current_tab].append({ 'event': {'type': 'on_start', 'name': 'عند البدء', 'inputs': []}, 'blocks': [self.current_block] }) self.play_sound('connect') self.dragging = False self.current_block = None elif event.type == MOUSEMOTION: if self.dragging and self.current_block: self.current_block['x'] = mouse_pos[0] - self.drag_offset[0] self.current_block['y'] = mouse_pos[1] - self.drag_offset[1] # الرسم self.screen.fill(self.colors['background']) self.draw_palette() self.draw_workspace() self.draw_tabs() self.draw_toolbar() self.draw_sprite_panel() self.draw_output() # تحديد العناصر التي يتم hover عليها close_rect = self.draw_tutorial() if close_rect and close_rect.collidepoint(mouse_pos): if pygame.mouse.get_pressed()[0]: self.show_tutorial = False pygame.display.flip() clock.tick(60) pygame.quit() if __name__ == "__main__": app = ScratchLikeApp() app.run()

الخميس، 3 أبريل 2025

import tkinter as tk from tkinter import ttk, filedialog from PIL import Image, ImageDraw, ImageTk import os class SimplePaintWithSave: def __init__(self, root): self.root = root self.root.title("برنامج الرسم مع الحفظ") # إعدادات الرسم self.canvas_width = 800 self.canvas_height = 600 self.current_color = "black" self.line_width = 3 # إنشاء عناصر الواجهة self.create_widgets() # متغيرات تتبع الرسم self.last_x = None self.last_y = None self.drawing = False # صورة الخلفية للتتبع self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white") self.draw = ImageDraw.Draw(self.image) def create_widgets(self): # شريط الأدوات العلوي toolbar = ttk.Frame(self.root) toolbar.pack(fill=tk.X, padx=5, pady=5) # أزرار الألوان colors = ["black", "red", "green", "blue", "yellow", "purple"] for color in colors: btn = tk.Button(toolbar, bg=color, width=3, command=lambda c=color: self.set_color(c)) btn.pack(side=tk.LEFT, padx=2) # زر المسح clear_btn = ttk.Button(toolbar, text="مسح الكل", command=self.clear_canvas) clear_btn.pack(side=tk.LEFT, padx=5) # زر الحفظ save_btn = ttk.Button(toolbar, text="حفظ كصورة", command=self.save_image) save_btn.pack(side=tk.RIGHT) # لوحة الرسم self.canvas = tk.Canvas(self.root, width=self.canvas_width, height=self.canvas_height, bg="white") self.canvas.pack(fill=tk.BOTH, expand=True) # ربط أحداث الماوس self.canvas.bind("", self.start_drawing) self.canvas.bind("", self.draw) self.canvas.bind("", self.stop_drawing) def set_color(self, new_color): self.current_color = new_color def start_drawing(self, event): self.drawing = True self.last_x = event.x self.last_y = event.y def draw(self, event): if self.drawing: # الرسم على Canvas self.canvas.create_line( self.last_x, self.last_y, event.x, event.y, width=self.line_width, fill=self.current_color, capstyle=tk.ROUND, smooth=True ) # الرسم على صورة PIL self.draw.line( [(self.last_x, self.last_y), (event.x, event.y)], fill=self.current_color, width=self.line_width ) self.last_x = event.x self.last_y = event.y def stop_drawing(self, event): self.drawing = False def clear_canvas(self): self.canvas.delete("all") self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white") self.draw = ImageDraw.Draw(self.image) def save_image(self): try: # اختيار مكان الحفظ file_path = filedialog.asksaveasfilename( defaultextension=".png", filetypes=[("PNG Image", "*.png"), ("JPEG Image", "*.jpg"), ("All Files", "*.*")], title="حفظ الصورة" ) if file_path: # حفظ الصورة بنفس نوع الملف المحدد if file_path.lower().endswith('.jpg') or file_path.lower().endswith('.jpeg'): self.image.save(file_path, "JPEG", quality=95) else: self.image.save(file_path, "PNG") print(f"تم الحفظ بنجاح: {os.path.basename(file_path)}") tk.messagebox.showinfo("تم الحفظ", f"تم حفظ الصورة في:\n{file_path}") except Exception as e: tk.messagebox.showerror("خطأ", f"حدث خطأ أثناء الحفظ:\n{str(e)}") if __name__ == "__main__": root = tk.Tk() root.geometry("900x700") root.minsize(400, 300) # تحسين المظهر style = ttk.Style() style.configure("TButton", padding=5) app = SimplePaintWithSave(root) root.mainloop()
import tkinter as tk from tkinter import ttk class SimplePaint: def __init__(self, root): self.root = root self.root.title("برنامج الرسم - Python 3.13.2") # إعدادات أساسية self.canvas_width = 800 self.canvas_height = 600 self.current_color = "black" self.line_width = 3 # إنشاء عناصر الواجهة self.create_widgets() # متغيرات تتبع الرسم self.last_x = None self.last_y = None def create_widgets(self): # شريط الأدوات toolbar = ttk.Frame(self.root) toolbar.pack(fill=tk.X, padx=5, pady=5) # أزرار الألوان colors = ["black", "red", "green", "blue", "yellow", "purple"] for color in colors: btn = tk.Button(toolbar, bg=color, width=3, command=lambda c=color: self.set_color(c)) btn.pack(side=tk.LEFT, padx=2) # زر المسح clear_btn = ttk.Button(toolbar, text="مسح الكل", command=self.clear_canvas) clear_btn.pack(side=tk.RIGHT) # لوحة الرسم self.canvas = tk.Canvas(self.root, width=self.canvas_width, height=self.canvas_height, bg="white") self.canvas.pack(fill=tk.BOTH, expand=True) # ربط أحداث الماوس self.canvas.bind("", self.start_drawing) self.canvas.bind("", self.draw) self.canvas.bind("", self.stop_drawing) def set_color(self, new_color): self.current_color = new_color def start_drawing(self, event): self.last_x = event.x self.last_y = event.y def draw(self, event): if self.last_x and self.last_y: self.canvas.create_line( self.last_x, self.last_y, event.x, event.y, width=self.line_width, fill=self.current_color, capstyle=tk.ROUND, smooth=True ) self.last_x = event.x self.last_y = event.y def stop_drawing(self, event): self.last_x = None self.last_y = None def clear_canvas(self): self.canvas.delete("all") if __name__ == "__main__": # إعداد النافذة الرئيسية root = tk.Tk() # تحسينات للتشغيل على 3.13.2 root.tk.call('tk', 'scaling', 1.5) # تحسين الدقة للشاشات الحديثة # ضبط حجم النافذة root.geometry("900x700") root.minsize(400, 300) # تشغيل التطبيق app = SimplePaint(root) # التحقق من الإصدار print(f"يعمل على Python {tk.TkVersion}") root.mainloop()

الثلاثاء، 1 أبريل 2025

لعبة معركة الطائرات الفضائية
0
❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
0 🪙