تعبت من JavaScript - استخدم Python المستندة إلى المستعرض

تجربتي في تطوير لعبة "الأفعى" في بريثون



صورة



"انتظر ماذا؟" - أعتقد أن معظم القراء سيتفاعلون مع العنوان بهذه الطريقة.



هل تقصد "فقط استخدم Python في المتصفح"؟



يعلم الجميع أن JavaScript فقط يعمل في المتصفحات.



حسنًا ، توجد أعلاه لقطة شاشة لشفرة المصدر لموقعي الشخصي. ألقِ نظرة ، قد ترى شيئًا جديدًا لنفسك.



نعم ، إنها بايثون!



الآن ، دعنا نتحدث عن كيف وكيف يعمل بشكل جيد ، ونناقش أيضًا عددًا من بدائل JavaScript الأخرى.



إدخال بريثون



Brython هو تطبيق JavaScript لـ Python3 يتيح لك كتابة كود Python للويب.



في الأساس ، هي مكتبة JavaScript تقوم بتحويل كود Python الخاص بك إلى JS المكافئ وتشغيله في وقت التشغيل.



نظرًا لأن كتابة كود المتصفح بلغة Python تبدو رائعة ، فقد قررت أن أجربها.



تطوير "الأفعى" في بريثون



صورة



إليك رابط لموقعي حيث يمكنك تجربة إصدارات JavaScript و Brython من Snake. وهنا رابط لـ GitHub مع شفرة المصدر .



من أجل تجربة Brython ، قررت كتابة Snake الكلاسيكي.



نظرًا لأنني لست خبيرًا في HTML Canvas أو مطور ألعاب ، فقد قررت استخدام تطبيق JavaScript هذا كنقطة انطلاق. بمجرد أن أنشأت بالفعل "الأفعى" الخاصة بي على أساس Canvas ، لكن هذا التنفيذ أكثر إتقانًا وإحكامًا.



و كما كتب المؤلف في أقل من 5 دقائق . يجب أن أنسب الفضل لكريس ديلون ، إنه أمر مثير للإعجاب للغاية.



لذلك ، أضفت النقاط وحفظت أفضل نتيجة لتنفيذ كريس ، وقمت أيضًا بتحسين الواجهة قليلاً (أضفت زر إيقاف مؤقت وزرًا مع التعليمات) ثم نقلت اللعبة إلى بريثون.



لقد قمت أيضًا بتعديل الكود الخاص به بحيث يعمل في وضع معين strict، نظرًا لأن تطبيق كريس يستخدم أشياء مثل المتغيرات العامة الضمنية ، والتي ، في رأيي ، لا تعكس الشكل الذي يبدو عليه معظم الكود في JS (أنا لا أنتقد المؤلف - لقد تمت برمجته في ذلك الوقت ). كنت أرغب في الحصول على مقارنة جيدة بين كود Brython و JS. تبين أن



JavaScript مثل هذا ، ولن أنشر هذا الرمز هنا ، لذلك هدفنا هو التركيز على Brython.



على الرغم من أن معظم كود Brython تمت ترجمته حرفيًا من JS ، إلا أن بعض الأجزاء (مثل وظيفة التسجيل) تمت كتابتها مباشرةً في Brython ثم تم تنفيذها في JS لمعرفة الاختلافات.



تبدو النتيجة النهائية كما يلي:



<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Brython Snake</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">
    </script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <style> /* Removed to keep the snippet short. Find the full file here: */ </style>
</head>

<body onload="brython()">

    <h1 class="text-center">Snake built with <a href="https://brython.info">Python!</a></h1>
    <canvas id="game-board" width="400" height="400"></canvas>
    <br>
    <h3 id="score" class="text-center">Score: 0</h3>
    <br>
    <h6 id="high-score" class="text-center">High Score: 0</h6>
    <br>
    <div class="text-center">
        <button id="instructions-btn" class="btn btn-info">Instructions</button>
    </div>

    <script type="text/python">
        
        from browser import document, html, window
        from javascript import Math
        
        score = 0
        high_score = 0

        px = py = 10
        gs = tc = 20
        ax = ay = 15
        xv = yv = 0
        trail = []
        tail = 5

        pre_pause = [0,0]
        paused = False
   
        def game():
            global px, py, tc, gs, ax, ay, trail, tail, score
            px += xv
            py += yv
            if px < 0:
                px = tc-1
            if px > tc-1:
                px = 0
            if py < 0:
                py = tc-1
            if py > tc-1:
                py = 0
            ctx.fillStyle = "black"
            ctx.fillRect(0, 0, canvas.width, canvas.height)
            ctx.fillStyle = "lime"
            for i in range(len(trail)):
                ctx.fillRect(trail[i][0]*gs, trail[i][1]*gs, gs-2, gs-2)
                if trail[i][0] == px and trail[i][1] == py:
                    score = score if paused else 0 
                    tail = 5
            trail.insert(0, [px, py])
            while len(trail) > tail:
                trail.pop()
        
            if ax == px and ay == py:
                tail += 1
                ax = Math.floor(Math.random()*tc)
                ay = Math.floor(Math.random()*tc)
                score += 1
            update_score(score)
            ctx.fillStyle = "red"
            ctx.fillRect(ax*gs, ay*gs, gs-2, gs-2)
        
        def update_score(new_score):
            global high_score
            document["score"].innerHTML = "Score: " + str(new_score)
            if new_score > high_score:
                document["high-score"].innerHTML = "High Score: " + str(new_score)
                high_score = new_score

        def key_push(evt):
            global xv, yv, pre_pause, paused
            key = evt.keyCode
            if key == 37 and not paused:
                xv = -1
                yv = 0
            elif key == 38 and not paused:
                xv = 0
                yv = -1
            elif key == 39 and not paused:
                xv = 1
                yv = 0
            elif key == 40 and not paused:
                xv = 0
                yv = 1
            elif key == 32:
                temp = [xv, yv]
                xv = pre_pause[0]
                yv = pre_pause[1]
                pre_pause = [*temp]
                paused = not paused
            
        def show_instructions(evt):
            window.alert("Use the arrow keys to move and press spacebar to pause the game.")
        
        canvas = document["game-board"]
        ctx = canvas.getContext("2d")
        document.addEventListener("keydown", key_push)
        game_loop = window.setInterval(game, 1000/15)
        instructions_btn = document["instructions-btn"]
        instructions_btn.addEventListener("click", show_instructions)
    
</script>

</body>

</html>


لذلك ، بناءً على هذا المقتطف ، دعونا نفهم بعض مفاهيم بريثون الأساسية



اتصال Brython.js



لا يلزم التثبيت لاستخدام بريثون. فقط قم باستيراد البرنامج النصي بالداخل head :



<script type=”text/javascript” src=”https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">


تشغيل بريثون



لكي يقوم Brython بترجمة وتنفيذ كود Python كما لو كان رمز JS ، نحتاج إلى الاتصال Brythonفقط عندما يتم تحميل نص المستند. على سبيل المثال ، مثل هذا:



<body onload=”brython()”>


ستقوم هذه العلامة بالبحث عن علامات من scriptالنوع "text/python"وتشغيل التعليمات البرمجية الخاصة بهم.



API للعمل مع الويب



جافا سكريبت افتراضيا يتيح الوصول إلى كائنات مثل documentو windowالمطلوبة في أي مشروع JS. وفقًا لذلك ، يجب أن يكون Brython قادرًا على العمل معهم أيضًا.



لحل هذه المشكلة ، يمكن لمنشئي Brython ببساطة منح المطورين القدرة على الوصول إلى هذه الكائنات من كود Python ، لكن هذا سيؤدي إلى صرخات مصحح الأخطاء undefined variableوتدهور الأداء.



وبالتالي ، لاستخدام واجهات برمجة التطبيقات هذه ، يجب علينا استيرادها بنفس الطريقة التي نستورد بها أي وحدة Python أخرى:



from browser import document, html, window


ولست بحاجة إلى تنفيذ الأمر pip install. بعد كل شيء ، تقوم بتضمين كل ذلك في HTML! ما عليك سوى إضافة الواردات المطلوبة وسيتولى بريثون الباقي.



لنرى كيف أنها تعمل بشكل جيد، لقد حاولت استخدام عدة أساليب مختلفة من API على الويب: alert، setInterval، addEventListenerالخ لقد عملوا جميعًا كما ينبغي.



كائنات وطرق جافا سكريبت المضمنة



في "الأفعى" ، بمجرد أن يأكل الثعبان التفاحة ، نحتاج إلى إنتاج تفاحة جديدة في مكان عشوائي.



ومع ذلك ، لا يمكنني استخدام الوحدة العشوائية من مكتبة Python *. فكيف يمكنني إنشاء رقم عشوائي (بدون كتابة مكتبتي الخاصة)؟



اتضح أن Brython لديه دعم JavaScript أوسع مما كنت أعتقد. نرى:



from javascript import Math
random_num = Math.floor(Math.random()*10)


بفضل الوحدة javascript، إذا كان هناك كائن يمكنني الوصول إليه باستخدام JS ، فيمكنني الوصول إليه باستخدام Brython.



إذا قمت باستيراد مكتبة JavaScript (jQuery ، Bootstrap) وأردت استخدام أساليبها ، فيمكنني القيام بذلك باستخدام from javascript import <>. وبطبيعة الحال ، يمكنني أيضًا استخدام كائنات JS المضمنة مثل Dateأو String.

* يبدو أن Brython يأتي مع عدد من مكتبات Python القياسية المنفذة مباشرة في JavaScript ، وإذا لم يكن لدى الوحدة إصدار JS ، فلا يزال بإمكانك استيرادها. سيحصل Brython على إصدار Python خالص وسيعمل رمز الوحدة النمطية المستوردة جنبًا إلى جنب مع كود Brython. ومع ذلك ، لم تعمل الوحدة العشوائية بالنسبة لي - لكن يمكنني فهم السبب.

إنشاءات محددة



في Python ، إذا أردت فك قائمة ، يمكنني الكتابة list2 = [*list1]. أيضًا ، إذا كنت أرغب في تعيين قيم لمتغير بناءً على بعض الشروط ، فيمكنني الكتابة foo = 10 if condition else 20.



هذه التركيبات لها مكافئات JavaScript: [...arr]عامل الانتشار ( ) والعامل الثلاثي ( let foo = condition ? 10 : 20).



لكن هل يدعمهم بريثون؟



لقد جربتهم وعملوا بشكل رائع. يمكنك أن ترى أن تفريغ القائمة من Python ويتم استخدام التعيين الشرطي في التعليمات البرمجية الخاصة بي.



تصحيح



لأكون صادقًا ، اعتقدت أن التصحيح في Brython سيكون فظيعًا.



في الحقيقة ، هذا ليس بهذا السوء.



بالطبع ، كتبت مشروعًا صغيرًا جدًا وغير معقد للغاية ، لكن الأخطاء التي ألقى بها بريثون كانت في الغالب دقيقة ومفهومة تمامًا.



هذا صحيح على الأقل بالنسبة لأخطاء بناء الجملة. يعد استيراد الوحدات من مكتبة Python قصة مختلفة تمامًا.



أداء



صورة



JavaScript Snake



صورة



Brython Snake



كما هو متوقع ، كود Brython أبطأ من JavaScript. في حالتي ، كان أبطأ بنحو 1.7 مرة.



أظن أنه في المشاريع الأكثر تعقيدًا ، سيكون Brython أبطأ عدة مرات من JS الخالص.



ومع ذلك ، يمكنك تحويل شفرة Brython الخاصة بك مسبقًا واستخدام JavaScript فقط على الصفحة ، والتي يجب أن تؤدي بشكل أفضل.



لقد حاولت بالفعل استخدام محرر Brython لتحويل كود Brython الخاص بي إلى JS وتشغيل الكود الناتج على صفحة ويب ، ولكن نظرًا لوجود عدد كبير من الأخطاء ، فقد تخليت عن هذا في الوقت الحالي. ومع ذلك ، لم أبذل الكثير من الجهد في هذا الأمر.



الأفكار النهائية حول بريثون



لأكون صادقًا ، لقد تأثرت تمامًا ببريثون. إليك بعض الإيجابيات والسلبيات من تجربتي الخاصة مع اللغة:



الإيجابيات



  • تمكنت من كتابة أغنية "Snake" بدون أي متاعب غير ضرورية ، وكانت تجربة التصحيح إيجابية بشكل مدهش.
  • في مشروعي البسيط ، تفاعل Brython بسلاسة مع كائنات JavaScript الأصلية المتوفرة على الصفحة
  • أقدر حقيقة أن الكود الخاص بي يبدو أنظف في Python ، وأحب أيضًا أنه يمكنني استخدام تركيبات Python المفيدة لكتابة كود المتصفح.
  • في حالة لعبتي ، على الرغم من أن تحميل Brython أبطأ من JavaScript ، فإن المستخدم لا يلاحظ هذا الاختلاف.
  • يسعدني أن أرى Python في الكود المصدري لموقعي.


سلبيات



  • إن برايتون أبطأ بكثير من JS الخالصة.
  • Brython JavaScript.
  • Brython
  • Brython .


بشكل عام ، بعد أن أنهيت مشروعي الأول في بريثون ، أستطيع أن أقول بكل ثقة أنني سأحاول مرة أخرى يومًا ما.



ومع ذلك ، أعتقد أن Brython الآن أكثر ملاءمة لمطوري JavaScript المألوفين بـ Python وتعبوا من JS ، بدلاً من مطوري Python الذين يريدون تطوير الويب دون تعلم JavaScript.



أعتقد أن فهم JavaScript ضروري للعمل بشكل جيد مع Brython. وإذا قررت قضاء بعض الوقت في تعلم JavaScript لتسهيل الكتابة بلغة Brython ، فيمكنك فقط استخدام JavaScript.



بدائل متصفح JS الأخرى



صورة



السبب في أنني اخترت Brython كان بسبب معظم خيارات الانتقال من Python إلى JS التي تعلمتها لأول مرة ، كان الوحيد الذي يتم تطويره بنشاط على GitHub. معظم محولات Python إلى JavaScript التي نظرت إليها لم تلتزم بها منذ عدة سنوات.



ومع ذلك ، هناك بدائل أخرى.



Pyodide ، على سبيل المثال ، يبدو خيارًا مثيرًا للاهتمام. يقوم بتجميع Python (جنبًا إلى جنب مع مكتباتها العلمية) إلى WebAssembly ، مما يسمح لها بالعمل في متصفح.



WebAssembly ، كما يوحي الاسم ، مجمع للويب. مثلما يمكن للمُجمِّع على أجهزة الكمبيوتر لدينا أن يعمل كوسيط بين اللغات عالية المستوى ورمز الجهاز ، فإن WebAssembly يفعل الشيء نفسه على الويب.



وبالتالي ، من الممكن كتابة مترجم يقوم بترجمة Python (أو أي لغة أخرى) إلى WebAssembly ، مما يسمح له بالعمل في المتصفح.



هذا مشروع طموح وواعد ومن المرجح أن يؤدي إلى حقيقة أننا سنرى المزيد والمزيد من تطوير الويب بدون JavaScript.



ومع ذلك ، فهي لا تزال في مهدها (~ 3 سنوات) ، لذا من المحتمل أن يستغرق الأمر بعض الوقت قبل أن نرى استبدال JavaScript بانتظام بلغات أخرى.



وبينما ننتظر ، سيتعين عليك استخدام أدوات مثل Brython إذا كنت لا تستطيع حقًا التعامل مع JavaScript.



لكن بصراحة ، هذه بداية جيدة!



صورة


تعرف على المزيد حول كيفية الحصول على مهنة رفيعة المستوى من الصفر أو Level Up في المهارات والراتب من خلال أخذ دورات SkillFactory المدفوعة عبر الإنترنت:











All Articles