<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/page/5/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</description><language>ar</language><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x648;&#x62D;&#x62F;&#x629; SQLite3 &#x641;&#x64A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-sqlite3-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1837/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/1013109505_---SQLite3----3.png.48de86df22febdb257a98541a9aa2b91.png" /></p>
<p>
	تُعد <a href="https://academy.hsoub.com/devops/servers/databases/%D9%83%D9%8A%D9%81-%D9%88%D9%85%D8%AA%D9%89-%D9%86%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-sqlite-r111/" rel="">SQLite</a> قاعدة بيانات SQL قائمة بحد ذاتها self-contained، ومعتمدة على الملفات file-based، وهي مُضمّنة في <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون</a> افتراضيًا، إذ من الممكن استخدامها في أي من تطبيقات بايثون دون الحاجة لتثبيت أي برمجيات إضافية.
</p>

<p>
	سنتعرف في هذا المقال على الوحدة <a href="https://docs.python.org/3.8/library/sqlite3.html" rel="external nofollow"><code>sqlite3</code></a> في بايثون 3، إذ سننشئ اتصالاً مع قاعدة بيانات SQLite، كما سنضيف جدولاً إليها، وسندخل بعض البيانات إلى هذا الجدول ونقرأها ونعدّلها.
</p>

<p>
	سنتعامل في هذا المقال مع مثال لتطبيق جرد مخزون أسماك في حوض مُفترض، وبالتالي لا بُدّ من التعديل في حال إضافة أو إزالة سمكة من الحوض.
</p>

<h2>
	مستلزمات العمل
</h2>

<p>
	لتحقيق أقصى فائدة ممكنة من هذا المقال، يُفضّل أن تكون مُطّلعًا على البرمجة <a href="https://wiki.hsoub.com/Python" rel="external">بلغة بايثون</a> وعلى <a href="https://academy.hsoub.com/programming/sql/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-sql-r585/" rel="">أساسيات لغة SQL</a>، وفي هذا الصدد ننصحك بقراءة المقالات التالية قبل إكمال هذا المقال:
</p>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">مدخل إلى لغة بايثون البرمجية</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D8%AA%D8%B9%D9%84%D9%85-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-mysql-r297/" rel="">تعلم أساسيات MySQL</a>.
	</li>
</ul>

<h2>
	الخطوة الأولى – إنشاء اتصال مع قاعدة بيانات SQLite
</h2>

<p>
	عند إنشاء اتصال مع قاعدة بيانات SQLite، فإنّنا نصل بالنتيجة إلى بيانات موجودة في ملف ما على جهاز الحاسوب، حيث تُعد محركات <a href="https://academy.hsoub.com/programming/sql/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%B9%D9%86-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r584/" rel="">قواعد بيانات SQL</a> كاملة الميزات ويمكن استخدامها لأغراض متعددة، وسنتعامل في مقالنا الحالي مع قاعدة بيانات تُعنى بتعقّب مخزون الأسماك في حوض أسماك مُفترض.
</p>

<p>
	يمكن الاتصال بقاعدة البيانات SQLite باستخدام الوحدة <code>sqlite3</code> في بايثون على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_9" style=""><span class="kwd">import</span><span class="pln"> sqlite3

connection </span><span class="pun">=</span><span class="pln"> sqlite3</span><span class="pun">.</span><span class="pln">connect</span><span class="pun">(</span><span class="str">"aquarium.db"</span><span class="pun">)</span></pre>

<p>
	حيث تستورد التعليمة <code>import sqlite3</code> الوحدة <code>sqlite3</code>، مما يمنح برنامج بايثون وصولًا إلى هذه الوحدة، بينمّا تعيد الدالة <code>()sqlite3.connect</code> كائن اتصال <a href="https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection" rel="external nofollow"><code>Connection</code></a> والذي سنستخدمه في التخاطب مع قاعدة البيانات SQLite الموجودة في الملف <code>aquarium.db</code> الذي يُنشأ تلقائيًا من قبل الدالة <code>()sqlite3.connect</code> في حال عدم وجود ملف بنفس الاسم أصلًا في الحاسوب.
</p>

<p>
	يمكن التأكد من أنّ الكائن <code>connection</code> قد أُنشئ بنجاح عبر تشغيل الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8532_17" style=""><span class="kwd">print</span><span class="pun">(</span><span class="pln">connection</span><span class="pun">.</span><span class="pln">total_changes</span><span class="pun">)</span></pre>

<p>
	وبتشغيل شيفرة بايثون السابقة، سيظهر لنا الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8532_13" style=""><span class="lit">0</span></pre>

<p>
	إذ تمثّل سمة الكائن <code>connection.total_changes</code> إجمالي عدد السجلات (الأسطر) التي جرى تغييرها من قبل الكائن <code>connection</code>، ولكننا لم ننفّذ أي تعليمات SQL حتى الآن، ما يعني أنّ العدد 0 صحيح لعدد التغييرات الإجمالي <code>total_changes</code> حاليًا.
</p>

<p>
	وفي حال رغبتك بإعادة خطوات هذا المقال من البداية في أي وقت، يمكنك حذف الملف "aquarium.db" من حاسوبك.
</p>

<p>
	<strong>ملاحظة:</strong> من الممكن أيضًا الاتصال بقاعدة بيانات SQLite مُتصلة بالذاكرة مُباشرةً (وليس بملف) عبر تمرير السلسة النصية الخاصّة <code>":memory:"</code> إلى الدالة <code>()sqlite3.connect</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_19" style=""><span class="pln"> sqlite3</span><span class="pun">.</span><span class="pln">connect</span><span class="pun">(</span><span class="str">":memory:"</span><span class="pun">)</span></pre>

<p>
	من الجدير بالملاحظة أنّ هذا النوع من <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قواعد البيانات</a> سيختفي بمجرّد إنهاء برنامج بايثون، ما يجعلها مناسبة للحالات التي نحتاج فيها إلى استخدام وضع الحماية مؤقتًا (البيئة التي يمكن للمطور من خلالها العمل على مشروع قاعدة بيانات دون تعريض البيانات للخطر في حالة حدوث خطأ ما) بغية اختبار أمر ما في SQLite دون الحاجة إلى البيانات بعد إنهاء البرنامج.
</p>

<h2>
	الخطوة الثانية – إضافة بيانات إلى قاعدة البيانات SQLite
</h2>

<p>
	الآن وبعد أن أنشأنا الاتصال مع قاعدة بيانات SQLite المُتمثلّة بالملف "aquarium.db"، أصبح من الممكن البدء بإدخال البيانات إلى قاعدة البيانات وقراءتها منها؛ إذ تُخزّن البيانات في قواعد بيانات SQLite ضمن جداول، التي تعرّف مجموعةً من الأعمدة قد تكون خالية تمامًا، أو محتوية على سجل واحد أو أكثر، بحيث يتضمّن كل سجل بيانات موافقة للأعمدة المُعرفّة في الجدول.
</p>

<p>
	سننشئ جدولًا باسم "fish" يتتبع البيانات التالية:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_21" style=""><span class="pun">------------------------------------------------------</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  tank_number  </span><span class="pun">|</span><span class="pln">   species    </span><span class="pun">|</span><span class="pln">  name  </span><span class="pun">|</span><span class="pln">
</span><span class="pun">------------------------------------------------------</span><span class="pln">
</span><span class="pun">|</span><span class="pln">            </span><span class="lit">1</span><span class="pln">             </span><span class="pun">|</span><span class="pln">     shark     </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Sammy</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">------------------------------------------------------</span><span class="pln">
</span><span class="pun">|</span><span class="pln">            </span><span class="lit">7</span><span class="pln">             </span><span class="pun">|</span><span class="pln"> cuttlefish </span><span class="pun">|</span><span class="pln">   </span><span class="typ">Jamie</span><span class="pln">   </span><span class="pun">|</span><span class="pln">
</span><span class="pun">------------------------------------------------------</span></pre>

<p>
	سيتتبع الجدول "fish" قيم الاسم <code>name</code> والنوع <code>species</code> ورقم الخزّان <code>tank_number</code> لكل سمكة في الحوض، وقد ضمّنا مثالين لسجلات الأسماك، الأول لسمكة من نوع قرش <code>shark</code> باسم <code>Sammy</code>، والآخر لسمكة من النوع حبّار <code>cuttlefish</code> باسم <code>Jamie</code>.
</p>

<p>
	ومن الممكن إنشاء الجدول <code>fish</code> في SQLite اعتمادًا على الكائن <code>connection</code> المُنشأ في الخطوة الأولى من هذا المقال، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_23" style=""><span class="pln">cursor </span><span class="pun">=</span><span class="pln"> connection</span><span class="pun">.</span><span class="pln">cursor</span><span class="pun">()</span><span class="pln">
cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"CREATE TABLE fish (name TEXT, species TEXT, tank_number INTEGER)"</span><span class="pun">)</span></pre>

<p>
	إذ تعيد الدالة <code>()connection.cursor</code> في الشيفرة السابقة <a href="https://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor" rel="external nofollow">كائن مؤشّر <code>Cursor</code></a>، والذي يمكنّنا من تنفيذ تعليمات SQL على قاعدة البيانات SQLite باستخدام الدالة <code>()cursor.execute</code>، أمّا السلسة النصية <code>"... CREATE TABLE fish"</code> فهي تعليمة SQL تُنشئ جدولًا باسم <code>fish</code> مُتضمنًا الأعمدة الثلاث التي أشرنا إليها سابقًا وهي الاسم <code>name</code>، الذي يحتوي بيانات من النوع النصي <code>TEXT</code>، والنوع <code>species</code> الذي يحتوي أيضًا بيانات من النوع النصي <code>TEXT</code>، ورقم الخزان <code>tank_number</code>، الذي يحتوي بيانات من نوع عدد صحيح <code>INTEGER</code>.
</p>

<p>
	الآن وبعدما أنشأنا الجدول، أصبح من الممكن إدخال سجلات البيانات إليه:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_25" style=""><span class="pln">cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"INSERT INTO fish VALUES ('Sammy', 'shark', 1)"</span><span class="pun">)</span><span class="pln">
cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"INSERT INTO fish VALUES ('Jamie', 'cuttlefish', 7)"</span><span class="pun">)</span></pre>

<p>
	استدعينا في الشيفرة السابقة الدالة <code>()cursor.execute</code> مرتين، المرة الأولى بغية إدخال السجل الخاص بالسمكة القرش المسماة <code>Sammy</code> إلى الخزان رقم "1"، والثانية لإدخال سمكة الحبار المسمّاة <code>Jamie</code> إلى الخزان رقم "7"، أمّا السلسة النصية <code>"... INSERT INTO fish VALUES"</code> فهي تعليمة SQL مسؤولة عن إدخال السجلات إلى الجدول.
</p>

<p>
	أمّا في الخطوة التالية فسنستخدم تعليمة <code>SELECT</code> من تعليمات SQL بغية التحقّق من السجلات المُدخلة إلى جدول الأسماك "fish".
</p>

<h2>
	الخطوة الثالثة – قراءة بيانات من قاعدة البيانات SQLite
</h2>

<p>
	أضفنا في الخطوة السابقة سجلين إلى جدول الأسماك "fish" في قاعدة البيانات SQLite، ومن الممكن جلب هذه السجلات باستخدام التعليمة <code>SELECT</code> من تعليمات SQL على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_27" style=""><span class="pln">rows </span><span class="pun">=</span><span class="pln"> cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"SELECT name, species, tank_number FROM fish"</span><span class="pun">).</span><span class="pln">fetchall</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">rows</span><span class="pun">)</span></pre>

<p>
	وحال تشغيل هذه الشيفرة، سيظهر الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_29" style=""><span class="pun">[(</span><span class="str">'Sammy'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Jamie'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cuttlefish'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">)]</span></pre>

<p>
	شغّلت الدالة <code>()cursor.execute</code> -في الشيفرة السابقة- تعليمة <code>SELECT</code> بغية جلب قيم كل من أعمدة الاسم والنوع ورقم الخزان من جدول الأسماك "fish"، لتجلب الدالة <code>()fetchall</code> كافّة نتائج التعليمة <code>SELECT</code>، ولدى تنفيذ التعليمة <code>(print(rows</code> ستظهر قائمةٌ مكونةٌ من سجلين، ولكل سجل ثلاثة مُدخلات يمثّل كل منها عمود من الأعمدة التي اخترناها من جدول الأسماك، إذ يتضمّن هذان السجلان البيانات التي أدخلناها في الخطوة الثانية، بمعنى أنّنا سنحصل على سجل لسمكة القرش "Sammy"، وسجل لسمكة الحبّار "Jamie"، وفي حال كان المطلوب جلب السجلات من جدول الأسماك التي تحقّق مجموعة من المعايير المُحدّدة، فمن الممكن استخدام العبارة <code>WHERE</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_31" style=""><span class="pln">target_fish_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Jamie"</span><span class="pln">
rows </span><span class="pun">=</span><span class="pln"> cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"SELECT name, species, tank_number FROM fish WHERE name = ?"</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">target_fish_name</span><span class="pun">,),</span><span class="pln">
</span><span class="pun">).</span><span class="pln">fetchall</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">rows</span><span class="pun">)</span></pre>

<p>
	وعند تشغيل الشيفرة، سنحصل على الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_33" style=""><span class="pun">[(</span><span class="str">'Jamie'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cuttlefish'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">)]</span></pre>

<p>
	تعمل التعليمة <code>()cursor.execute(&lt;SQL statement&gt;).fetchall</code> في المثال السابق على جلب كافّة النتائج من التعليمة <code>SELECT</code>، بينما تعمل العبارة <code>WHERE</code> في التعليمة <code>SELECT</code> على ترشيح السجلات لتكون فقط تلك التي تكون فيها قيمة العمود <code>name</code> هي <code>target_fish_name</code>، ومن الجدير بالملاحظة أنّه من الممكن استخدام الموضع المؤقت <code>?</code> بديلًا عن المتغير <code>target_fish_name</code> ضمن التعليمة <code>SELECT</code>، ومن المتوقّع في حالتنا أن يوافق سجلًا واحدًا هذا المعيار، إذ ستكون القيمة المعادة بعد الترشيح هي سجل سمكة الحبّار "Jamie".
</p>

<p>
	<strong>تنبيه:</strong> لا تستخدم عمليات بايثون على السلاسل النصية أبدًا في إنشاء تعليمات SQL ديناميكيًا، إذ يعرّضك استخدام هذه العمليات في تجميع السلاسل النصية لتعليمات SQL إلى خطر هجمات <a href="https://academy.hsoub.com/tags/sql%20injection/" rel="">حقن استعلامات SQL</a> المُستخدمة بغية سرقة أو تحريف أو تعديل البيانات المُخزّنة في قاعدة البيانات، وعوضًا عن ذلك استخدم الموضع المؤقت <code>?</code> في تعليمات SQL عند رغبتك بتعويض القيم تلقائيًا من قبل برنامج بايثون، إذ نمرر مجموعةً من القيم المُجمّعة مثل وسيط ثاني في الدالة <code>()Cursor.execute</code> لربط هذه القيم بتعليمات SQL، وهذا النمط من التعويض مشروح في مقالنا.
</p>

<h2>
	الخطوة 4 – تعديل البيانات في قاعدة بيانات SQLite
</h2>

<p>
	من الممكن تعديل السجلات في قاعدة البيانات SQLite باستخدام تعليمتي <code>UPDATE</code> و <code>DELETE</code> من تعليمات SQL.
</p>

<p>
	لنفترض على سبيل المثال أنّه قد نُقل القرش "Sammy" إلى الخزان رقم 2، فعندها من الممكن تعديل سجل هذه السمكة في الجدول "fish" للتعبير عن هذا التغيير على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_35" style=""><span class="pln">new_tank_number </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
moved_fish_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Sammy"</span><span class="pln">
cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"UPDATE fish SET tank_number = ? WHERE name = ?"</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">new_tank_number</span><span class="pun">,</span><span class="pln"> moved_fish_name</span><span class="pun">)</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	استخدمنا في الشيفرة السابقة تعليمة <code>UPDATE</code> من تعليمات SQL لتغيير رقم الخزان <code>tank_number</code> للسمكة <code>Sammy</code> إلى القيمة الجديدة "2"، إذ تضمن الجملة <code>WHERE</code> في التعليمة <code>UPDATE</code> أنّه لن تتغير قيمة رقم الخزان إلا عند تحقق شرط وهو أن يكون اسم السمكة هو Sammy أي <code>"name = "Sammy</code>، ومن الممكن التأكّد من تنفيذ التعديل بالشكل الصحيح من خلال تشغيل تعليمة <code>SELECT</code> التالية:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_37" style=""><span class="pln">rows </span><span class="pun">=</span><span class="pln"> cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"SELECT name, species, tank_number FROM fish"</span><span class="pun">).</span><span class="pln">fetchall</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">rows</span><span class="pun">)</span></pre>

<p>
	وبتشغيل الشيفرة السابقة سنحصل على الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_39" style=""><span class="pun">[(</span><span class="str">'Sammy'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Jamie'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cuttlefish'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">)]</span></pre>

<p>
	فنلاحظ أنّ السجل الخاص بالسمكة "Sammy" يملك القيمة "2" مثل رقم للخزان ضمن العمود <code>tank_number</code>.
</p>

<p>
	الآن لنفترض أنّنا حرّرنا القرش Sammy إلى الطبيعة، وبالتالي لم يعد موجودًا في الحوض، عندها يتوجّب حذف السجل الخاص به من الجدول "fish"، لذا سنستخدم التعليمة <code>DELETE</code> من تعليمات SQL لحذف السجل المطلوب كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_55" style=""><span class="pln">released_fish_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Sammy"</span><span class="pln">
cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"DELETE FROM fish WHERE name = ?"</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">released_fish_name</span><span class="pun">,)</span><span class="pln">
</span><span class="pun">)</span></pre>

<p>
	استخدمنا في الشيفرة السابقة التعليمة <code>DELETE</code> من تعليمات SQL لحذف سجل السمكة <code>Sammy</code> من النوع <code>shark</code>، إذ ضمنت الجملة <code>WHERE</code> في التعليمة <code>DELETE</code> أنّه لن يُحذف السجل إلّا عند تحقق شرط كون اسم السمكة هو Sammy أي <code>"name = "Sammy</code>، ومن الممكن التأكّد من تنفيذ الحذف بالشكل الصحيح من خلال تشغيل تعليمة <code>SELECT</code> التالية:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_43" style=""><span class="pln">rows </span><span class="pun">=</span><span class="pln"> cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"SELECT name, species, tank_number FROM fish"</span><span class="pun">).</span><span class="pln">fetchall</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">rows</span><span class="pun">)</span></pre>

<p>
	وبتشغيل الشيفرة السابقة سنحصل على الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_45" style=""><span class="pun">[(</span><span class="str">'Jamie'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cuttlefish'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">)]</span></pre>

<p>
	فنلاحظ أنّه قد حُذف فعلًا السجل الخاص بالسمكة <code>Sammy</code> من النوع <code>shark</code>، ولم يتبقَ سوى سجل سمكة <code>Jamie</code> من نوع الحبّار <code>cuttlefish</code>.
</p>

<h2>
	الخطوة 5 – استخدام تعليمة with للإغلاق الآلي
</h2>

<p>
	استخدمنا في هذا المقال كائنين رئيسين للتعامل مع قاعدة البيانات "aquarium.db" من النوع SQLite وهما: كائن اتصال باسم <code>connection</code> وكائن مؤشّر باسم <code>cursor</code>.
</p>

<p>
	يتوجّب إغلاق ملفات بايثون بعد الانتهاء من العمل عليها، وكذلك الأمر بالنسبة للكائنات مثل <code>Connection</code> و <code>Cursor</code>، إذ يجب إغلاقها عند الانتهاء من استخدامها، ومن الممكن استخدام العبارة <code>with</code> لمساعدتنا على إغلاق الكائنات <code>Connection</code> و <code>Cursor</code> تلقائيًا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8532_51" style=""><span class="kwd">from</span><span class="pln"> contextlib </span><span class="kwd">import</span><span class="pln"> closing

</span><span class="kwd">with</span><span class="pln"> closing</span><span class="pun">(</span><span class="pln">sqlite3</span><span class="pun">.</span><span class="pln">connect</span><span class="pun">(</span><span class="str">"aquarium.db"</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> connection</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">with</span><span class="pln"> closing</span><span class="pun">(</span><span class="pln">connection</span><span class="pun">.</span><span class="pln">cursor</span><span class="pun">())</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> cursor</span><span class="pun">:</span><span class="pln">
        rows </span><span class="pun">=</span><span class="pln"> cursor</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">"SELECT 1"</span><span class="pun">).</span><span class="pln">fetchall</span><span class="pun">()</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">rows</span><span class="pun">)</span></pre>

<p>
	تُعد الدالة <code>closing</code> من الدوال سهلة الاستخدام التي توفّرها الوحدة <a href="https://docs.python.org/3/library/contextlib.html" rel="external nofollow"><code>contextlib</code></a>، فعند إنهاء التعليمة <code>with</code>، تضمن <code>closing</code> استدعاء الدالة <code>()close</code> بغض النظر عن الكائن المُمرّر إليها، وفي مثالنا استخدمنا الدالة <code>closing</code> مرتين، الأولى لضمان الإغلاق التلقائي للكائن <code>Connection</code> المُعاد من الدالة <code>()sqlite3.connect</code>، والثانية لضمان الإغلاق التلقائي للكائن <code>Cursor</code> المُعاد من الدالة <code>()connection.cursor</code>، وبتشغيل الشيفرة السابقة سنحصل على الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_8532_49" style=""><span class="pun">[(</span><span class="lit">1</span><span class="pun">,)]</span></pre>

<p>
	وبما أنّ التعليمة <code>"SELECT 1"</code> هي تعليمة SQL تعيد دومًا سجلًا وحيدًا بعمود وحيد قيمتة "1"، فمن المنطقي في هذه الحالة الحصول على سجل يحتوي فقط القيمة "1" بمثابة قيمة معادة من الشيفرة.
</p>

<h2>
	الخاتمة
</h2>

<p>
	تمثّل الوحدة <code>sqlite3</code> جزءًا فعّالًا من مكتبة بايثون المعيارية، إذ تمكنّنا من العمل مع قاعدة بيانات SQL محلية كاملة الميزات دون الحاجة لتثبيت أي برمجيات إضافية.
</p>

<p>
	استعرضنا في هذا المقال كيفية استخدام الوحدة <code>sqlite3</code> للاتصال مع قاعدة بيانات SQLite، وكيفية إضافة البيانات إليها وقراءتها منها وتعديلها، كما نوهّنا لأخطار هجمات حقن استعلامات SQL، وبيّنا كيفية استخدام <code>contextlib.closing</code> لاستدعاء الدالة <code>()close</code> تلقائيًا وتطبيقها على كائنات بايثون الموجودة ضمن عبارات <code>with</code>.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-the-sqlite3-module-in-python-3" rel="external nofollow">How To Use the sqlite3 Module in Python 3</a> لصاحبه DavidMuller.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-php-mysqli-%D9%88%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sqlite3-r1131/" rel="">إضافة PHP MySQLi ونظام إدارة قواعد البيانات SQLite3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/flask/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-sqlite-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-flask-r346/" rel="">التعامل مع قواعد البيانات SQLite في تطبيقات Flask</a>
	</li>
	<li>
		النسخةالعربية الكاملة لكتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1837</guid><pubDate>Wed, 04 Jan 2023 18:08:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x628;&#x639;&#x62F; &#x645;&#x643;&#x62A;&#x628;&#x629; NumPy &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D8%A7-%D8%A8%D8%B9%D8%AF-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1829/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/639d86db78848_---NumPy--.png.8f6abb6999f8b3a112b45aae4bdfe1e6.png" /></p>

<p>
	وصلنا الآن إلى نهاية سلسلة مقالات <a href="https://academy.hsoub.com/tags/numpy/" rel="">NumPy</a>، ونأمل أن تكون أدركت أهمية مكتبة NumPy وأنها مكتبة قوية ومتعددة الاستخدامات. وبنفس الوقت تذكر أن <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">لغة بايثون</a> هي لغة قوية جدًا، وقد تكون في بعض الحالات المحددة أقوى من NumPy.
</p>

<p>
	لنفكر على سبيل المثال، في تمرين مثير للاهتمام على النحو التالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		اكتب الشيفرة المختصرة لحساب جميع التخصيصات "القانونية" لأربعة أرصدة stocks بحيث تكون التخصيصات في كتلة واحدة 1.0، ومجموع التخصيصات هو 10.0.
	</p>
</blockquote>

<p>
	جُمعت إجابات مختلفة من المجتمع، وأسفرت الحلول المقترحة عن نتائج مفاجئة. لكن لنبدأ بكتابة التعليمات البرمجية <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بلغة بايثون</a> لحل هذا التمرين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_10" style="">
<span class="kwd">def</span><span class="pln"> solution_1</span><span class="pun">():</span><span class="pln">
    </span><span class="com"># Brute force</span><span class="pln">
    </span><span class="com"># 14641 (=11*11*11*11) iterations &amp; tests</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">):</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> k </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">):</span><span class="pln">
                    </span><span class="kwd">if</span><span class="pln"> i</span><span class="pun">+</span><span class="pln">j</span><span class="pun">+</span><span class="pln">k</span><span class="pun">+</span><span class="pln">l </span><span class="pun">==</span><span class="pln"> </span><span class="lit">10</span><span class="pun">:</span><span class="pln">
                        Z</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="pln">i</span><span class="pun">,</span><span class="pln">j</span><span class="pun">,</span><span class="pln">k</span><span class="pun">,</span><span class="pln">l</span><span class="pun">))</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z</span></pre>

<p>
	هذا الحل هو الأبطأ لأنه يتطلب 4 حلقات، كما أنه يختبر جميع المجموعات المختلفة والبالغ عددها 11641 والمكونة من 4 أعداد صحيحة بين 0 و 10 للاحتفاظ فقط بالمجموعات التي يكون مجموعها مساوٍ إلى 10. يمكننا طبعًا التخلص من الحلقات باستخدام أداة itertools، لكن التعليمات تظل بطيئة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_12" style="">
<span class="kwd">import</span><span class="pln"> itertools </span><span class="kwd">as</span><span class="pln"> it

</span><span class="kwd">def</span><span class="pln"> solution_2</span><span class="pun">():</span><span class="pln">
    </span><span class="com"># Itertools</span><span class="pln">
    </span><span class="com"># 14641 (=11*11*11*11) iterations &amp; tests</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[(</span><span class="pln">i</span><span class="pun">,</span><span class="pln">j</span><span class="pun">,</span><span class="pln">k</span><span class="pun">,</span><span class="pln">l</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> i</span><span class="pun">,</span><span class="pln">j</span><span class="pun">,</span><span class="pln">k</span><span class="pun">,</span><span class="pln">l </span><span class="kwd">in</span><span class="pln"> it</span><span class="pun">.</span><span class="pln">product</span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">),</span><span class="pln">repeat</span><span class="pun">=</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> i</span><span class="pun">+</span><span class="pln">j</span><span class="pun">+</span><span class="pln">k</span><span class="pun">+</span><span class="pln">l </span><span class="pun">==</span><span class="pln"> </span><span class="lit">10</span><span class="pun">]</span></pre>

<p>
	كان أحد أفضل الحلول المقترحة يستفيد من إمكانية الحصول على حلقات مخبأة ذكية تتيح لنا بناء كل صف tuple مباشرةً، دون أي اختبار كما هو موضح أدناه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_14" style="">
<span class="kwd">def</span><span class="pln"> solution_3</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b </span><span class="pun">-</span><span class="pln"> c</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> a </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> b </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> c </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">)]</span></pre>

<p>
	يستخدم كاتب هذا التمرين أفضل حل بالاعتماد على NumPy استراتيجية مختلفة مع مجموعة مقيدة من الاختبارات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_16" style="">
<span class="kwd">def</span><span class="pln"> solution_4</span><span class="pun">():</span><span class="pln">
    X123 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">indices</span><span class="pun">((</span><span class="lit">11</span><span class="pun">,</span><span class="lit">11</span><span class="pun">,</span><span class="lit">11</span><span class="pun">)).</span><span class="pln">reshape</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="lit">11</span><span class="pun">*</span><span class="lit">11</span><span class="pun">*</span><span class="lit">11</span><span class="pun">)</span><span class="pln">
    X4 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> X123</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">vstack</span><span class="pun">((</span><span class="pln">X123</span><span class="pun">,</span><span class="pln"> X4</span><span class="pun">)).</span><span class="pln">T</span><span class="pun">[</span><span class="pln">X4 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">]</span></pre>

<p>
	إذا قيّمنا مدة تنفيذ هذه التوابع نحصل على:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_18" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"solution_1()"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.9</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"solution_2()"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.67</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"solution_3()"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">60.4</span><span class="pln"> usec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"solution_4()"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">54.4</span><span class="pln"> usec per loop</span></pre>

<p>
	كما تلاحظ حل Numpy هو الأسرع ولكن الحل باستخدام بايثون قابل للمقارنة. سنحاول الآن إضافة تعديل صغير على حل بايثون:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_20" style="">
<span class="kwd">def</span><span class="pln"> solution_3_bis</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">((</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b </span><span class="pun">-</span><span class="pln"> c</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> a </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pun">)</span><span class="pln">
           </span><span class="kwd">for</span><span class="pln"> b </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> c </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">11</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">))</span></pre>

<p>
	وسنحصل على النتيجة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_22" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"solution_3_bis()"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">10000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.643</span><span class="pln"> usec per loop</span></pre>

<p>
	اكتسبنا هنا عاملًا قدره 100 فقط عن طريق استبدال قوسين مربعين بأقواس عادية. كيف يعقل ذلك؟ يمكن العثور على التفسير من خلال النظر في نوع الكائن المُعاد:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_24" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">type</span><span class="pun">(</span><span class="pln">solution_3</span><span class="pun">()))</span><span class="pln">
</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'list'</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">type</span><span class="pun">(</span><span class="pln">solution_3_bis</span><span class="pun">()))</span><span class="pln">
</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'generator'</span><span class="pun">&gt;</span></pre>

<p>
	يعيد التابع <code>()solution_3_bis</code> مولدًا generator يمكن استخدامه لإنشاء القائمة الكاملة أو للتكرار على جميع العناصر المختلفة. على أي حال، تأتي عملية التسريع الضخمة من عدم الاستقرار في القائمة الكاملة، وبالتالي من المهم أن نتساءل عما إذا كنت بحاجة إلى مثيل فعلي لنتيجتك أو إذا كان المولد البسيط ينفذ المهمة.
</p>

<h2>
	مكتبة Numpy وأخواتها
</h2>

<p>
	هناك العديد من حزم بايثون الأخرى إلى جانب Numpy، والتي تستحق النظر لأنها تتناول أصناف مشابهة ولكن مختلفة من المشكلات باستخدام التقنيات المختلفة (التجميع، الجهاز الافتراضي، وحدة معالجة الرسوميات GPU، الضغط، إلخ). قد تكون حزمة واحدة أفضل من الأخرى اعتمادًا على مشكلتك المحددة وأجهزتك الخاصة. دعونا نوضح استخدامهم من خلال مثال بسيط جدًا، إذ نريد حساب تعبير بناءً على متجهين عددين float:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_26" style="">
<span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">b</span></pre>

<h3>
	حزمة NumExpr
</h3>

<p>
	توفر <a href="https://github.com/pydata/numexpr/wiki/Numexpr-Users-Guide" rel="external nofollow">حزمة numexpr</a> إجراءات للتقييم السريع لتعبيرات المصفوفة من ناحية العناصر باستخدام جهاز افتراضي يعتمد على المتجهات vector-based، وهي مشابهة لحزمة SciPy، لكنها لا تتطلب خطوة ترجمة منفصلة لشيفرات C أو <a href="https://academy.hsoub.com/programming/cpp/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-c-r802/" rel="">++C</a>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2069_29" style="">
<span class="kwd">import</span><span class="pln"> numpy as np
</span><span class="kwd">import</span><span class="pln"> numexpr as ne

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="typ">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="typ">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> ne</span><span class="pun">.</span><span class="pln">evaluate</span><span class="pun">(</span><span class="str">"2*a + 3*b"</span><span class="pun">)</span></pre>

<h3>
	مصرف Cython
</h3>

<p>
	<a href="http://cython.org/" rel="external nofollow">Cython</a> هو مصرّف ثابت محسن لكل من لغة برمجة بايثون ولغة كايثون Cython الموسعة (استنادًا إلى Pyrex). يجعل مصرّف كايثون كتابة امتدادات C لبايثون سهلة مثل <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> نفسها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_32" style="">
<span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np

</span><span class="kwd">def</span><span class="pln"> evaluate</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">ndarray a</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ndarray b</span><span class="pun">):</span><span class="pln">
    cdef int i
    cdef np</span><span class="pun">.</span><span class="pln">ndarray c </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros_like</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">size</span><span class="pun">):</span><span class="pln">
        c</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">a</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">b</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> c

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> evaluate</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span></pre>

<h3>
	مصرف Numba
</h3>

<p>
	يمنحك مصرّف <a href="http://numba.pydata.org/" rel="external nofollow">Numba</a> القدرة على تسريع تطبيقاتك من خلال وظائف عالية الأداء مكتوبة مباشرةً بلغة بايثون. مع بعض التعليقات التوضيحية يمكن تجميع تعليمات بايثون array-oriented و math-heavy في الوقت المناسب لتعليمات الآلة الأصلية، على غرار C و ++C وفورتران Fortran، دون الحاجة إلى تبديل <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">اللغات</a> أو مترجم بايثون.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_34" style="">
<span class="kwd">from</span><span class="pln"> numba </span><span class="kwd">import</span><span class="pln"> jit
</span><span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np

</span><span class="lit">@jit</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> evaluate</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">ndarray a</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ndarray b</span><span class="pun">):</span><span class="pln">
    c </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros_like</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">size</span><span class="pun">):</span><span class="pln">
        c</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">a</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">b</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> c

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> evaluate</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span></pre>

<h3>
	مكتبة Theano
</h3>

<p>
	<a href="http://www.deeplearning.net/software/theano/" rel="external nofollow">مكتبة Theano</a> هي مكتبة بايثون تتيح لك تحديد التعبيرات الرياضية التي تتضمن مصفوفات متعددة الأبعاد وتحسينها وتقييمها بكفاءة. تتميز Theano بالتكامل الوثيق مع الاستخدام غير المستقر والشفاف لوحدة معالجة الرسوميات GPU ، والتمايز الرمزي symbolic differentiation الفعال، وتحسينات السرعة والثبات، وإنشاء شيفرة C الديناميكية، واختبار الوحدة الشامل والتحقق الذاتي.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_37" style="">
<span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
</span><span class="kwd">import</span><span class="pln"> theano</span><span class="pun">.</span><span class="pln">tensor </span><span class="kwd">as</span><span class="pln"> T

x </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">.</span><span class="pln">fvector</span><span class="pun">(</span><span class="str">'x'</span><span class="pun">)</span><span class="pln">
y </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">.</span><span class="pln">fvector</span><span class="pun">(</span><span class="str">'y'</span><span class="pun">)</span><span class="pln">
z </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">y
f </span><span class="pun">=</span><span class="pln"> function</span><span class="pun">([</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">],</span><span class="pln"> z</span><span class="pun">)</span><span class="pln">

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span></pre>

<h3>
	PyCUDA
</h3>

<p>
	يتيح لك <a href="http://mathema.tician.de/software/pycuda" rel="external nofollow">PyCUDA</a> الوصول إلى واجهة برمجة تطبيقات الحساب المتوازي CUDA الخاصة بشركة Nvidia من بايثون.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_39" style="">
<span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
</span><span class="kwd">import</span><span class="pln"> pycuda</span><span class="pun">.</span><span class="pln">autoinit
</span><span class="kwd">import</span><span class="pln"> pycuda</span><span class="pun">.</span><span class="pln">driver </span><span class="kwd">as</span><span class="pln"> drv
</span><span class="kwd">from</span><span class="pln"> pycuda</span><span class="pun">.</span><span class="pln">compiler </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">SourceModule</span><span class="pln">

mod </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SourceModule</span><span class="pun">(</span><span class="str">"""
    __global__ void evaluate(float *c, float *a, float *b)
    {
      const int i = threadIdx.x;
      c[i] = 2*a[i] + 3*b[i];
    }
"""</span><span class="pun">)</span><span class="pln">

evaluate </span><span class="pun">=</span><span class="pln"> mod</span><span class="pun">.</span><span class="pln">get_function</span><span class="pun">(</span><span class="str">"evaluate"</span><span class="pun">)</span><span class="pln">

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros_like</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln">

evaluate</span><span class="pun">(</span><span class="pln">drv</span><span class="pun">.</span><span class="typ">Out</span><span class="pun">(</span><span class="pln">c</span><span class="pun">),</span><span class="pln"> drv</span><span class="pun">.</span><span class="typ">In</span><span class="pun">(</span><span class="pln">a</span><span class="pun">),</span><span class="pln"> drv</span><span class="pun">.</span><span class="typ">In</span><span class="pun">(</span><span class="pln">b</span><span class="pun">),</span><span class="pln"> block</span><span class="pun">=(</span><span class="lit">400</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> grid</span><span class="pun">=(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">))</span></pre>

<h3>
	مكتبة PyOpenCL
</h3>

<p>
	تتيح لك <a href="http://mathema.tician.de/software/pyopencl" rel="external nofollow">PyOpenCL</a> الوصول إلى وحدات معالجة الرسومات وأجهزة الحوسبة المتوازية الأخرى من بايثون.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2069_41" style="">
<span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
</span><span class="kwd">import</span><span class="pln"> pyopencl </span><span class="kwd">as</span><span class="pln"> cl

a </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">empty_like</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln">

ctx </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="pln">create_some_context</span><span class="pun">()</span><span class="pln">
queue </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="typ">CommandQueue</span><span class="pun">(</span><span class="pln">ctx</span><span class="pun">)</span><span class="pln">

mf </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="pln">mem_flags
gpu_a </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="typ">Buffer</span><span class="pun">(</span><span class="pln">ctx</span><span class="pun">,</span><span class="pln"> mf</span><span class="pun">.</span><span class="pln">READ_ONLY </span><span class="pun">|</span><span class="pln"> mf</span><span class="pun">.</span><span class="pln">COPY_HOST_PTR</span><span class="pun">,</span><span class="pln"> hostbuf</span><span class="pun">=</span><span class="pln">a</span><span class="pun">)</span><span class="pln">
gpu_b </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="typ">Buffer</span><span class="pun">(</span><span class="pln">ctx</span><span class="pun">,</span><span class="pln"> mf</span><span class="pun">.</span><span class="pln">READ_ONLY </span><span class="pun">|</span><span class="pln"> mf</span><span class="pun">.</span><span class="pln">COPY_HOST_PTR</span><span class="pun">,</span><span class="pln"> hostbuf</span><span class="pun">=</span><span class="pln">b</span><span class="pun">)</span><span class="pln">

evaluate </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="typ">Program</span><span class="pun">(</span><span class="pln">ctx</span><span class="pun">,</span><span class="pln"> </span><span class="str">"""
    __kernel void evaluate(__global const float *gpu_a;
                           __global const float *gpu_b;
                           __global       float *gpu_c)
    {
        int gid = get_global_id(0);
        gpu_c[gid] = 2*gpu_a[gid] + 3*gpu_b[gid];
    }
"""</span><span class="pun">).</span><span class="pln">build</span><span class="pun">()</span><span class="pln">

gpu_c </span><span class="pun">=</span><span class="pln"> cl</span><span class="pun">.</span><span class="typ">Buffer</span><span class="pun">(</span><span class="pln">ctx</span><span class="pun">,</span><span class="pln"> mf</span><span class="pun">.</span><span class="pln">WRITE_ONLY</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">nbytes</span><span class="pun">)</span><span class="pln">
evaluate</span><span class="pun">.</span><span class="pln">evaluate</span><span class="pun">(</span><span class="pln">queue</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> gpu_a</span><span class="pun">,</span><span class="pln"> gpu_b</span><span class="pun">,</span><span class="pln"> gpu_c</span><span class="pun">)</span><span class="pln">
cl</span><span class="pun">.</span><span class="pln">enqueue_copy</span><span class="pun">(</span><span class="pln">queue</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> gpu_c</span><span class="pun">)</span></pre>

<h2>
	Scipy وأخواتها
</h2>

<p>
	إذا كان هناك عدة حزم إضافية لمكتبة Numpy، فهناك الملايين من الحزم الإضافية لـ scipy؛ إذ ربما يكون لكل مجال من مجالات العلوم مجموعته الخاصة، ومعظم الأمثلة التي كنا ندرسها حتى الآن كان من الممكن حلها في استدعائين أو ثلاثة استدعاءات باستخدام الحزمة ذات الصلة. لكن طبعًا لم يكن هذا هو الهدف. تعد برمجة الوظائف بنفسك عمومًا تمرينًا جيدًا إذا كان لديك بعض وقت الفراغ، وتتمثل أكبر صعوبة في هذه المرحلة في العثور على هذه الحزم ذات الصلة. فيما يلي قائمة قصيرة جدًا من الحزم التي جرى صيانتها واختبارها جيدًا والتي قد تبسط حياتك العلمية (اعتمادًا على مجالك). هناك طبعًا الكثير من الخيارات وذلك حسب احتياجاتك الخاصة، ومن المحتمل ألا تكون مضطرًا إلى برمجة كل شيء بنفسك.
</p>

<h3>
	مكتبة scikit-learn
</h3>

<p>
	<a href="http://scikit-learn.org/stable/" rel="external nofollow">scikit-learn</a> هي مكتبة تعلم آلي مجانية للغة برمجة بايثون، وتتميز بخوارزميات تصنيف وانحدار وتجميع مختلفة بما في ذلك دعم خوارزمية أجهزة المتجهات vector machines، والغابات العشوائية random forests وتعزيز التدرج gradient boosting و k-means و DBSCAN، وهذه الحزمة مصممة للتفاعل مع مكتبات بايثون الرقمية والعلمية numpy و SciPy.
</p>

<h3>
	مكتبة scikit-image
</h3>

<p>
	<a href="http://scikit-image.org/" rel="external nofollow">scikit-image</a> عبارة عن حزمة بايثون مخصصة لمعالجة الصور، واستخدام المصفوفات المتداخلة مثل كائنات صور. يصف هذا المقال كيفية استخدام scikit-image في مهام معالجة الصور المختلفة، ويركز على الارتباط بوحدات بايثون النمطية العلمية الأخرى مثل numpy و SciPy.
</p>

<h3>
	مكتبة SymPy
</h3>

<p>
	<a href="http://www.sympy.org/en/index.html" rel="external nofollow">SymPy</a> هي مكتبة بايثون للرياضيات الرمزية، وتهدف إلى أن تصبح كل ميزات النظام الحاسوبي جبرية -أو اختصارًا CAS- مع الحفاظ على الشيفرة بسيطة قدر الإمكان حتى تكون مفهومة وقابلةً للتوسّع بسهولة. كُتبت كامل مكتبة SymPy بلغة بايثون.
</p>

<h3>
	حزمة Astropy
</h3>

<p>
	مشروع <a href="http://www.astropy.org/" rel="external nofollow">Astropy</a> هو جهد مجتمعي لتطوير حزمة أساسية واحدة لعلم الفلك astronomy في بايثون وتعزيز إمكانية التشغيل البيني بين حزم علم الفلك في بايثون.
</p>

<h3>
	حزمة Cartopy
</h3>

<p>
	<a href="http://scitools.org.uk/cartopy/" rel="external nofollow">Cartopy</a> هي حزمة بايثون مصممة لتسهيل رسم الخرائط لتحليل البيانات والتصوير. تستفيد Cartopy من المكتبات القوية PROJ.4 والمكتوبة والمحددة الشكل ولها واجهة رسم بسيطة وبديهية لحزمة matplotlib لإنشاء خرائط جاهزة النشر.
</p>

<h3>
	محاكي Brian
</h3>

<p>
	<a href="http://www.briansimulator.org/" rel="external nofollow">Brian</a> هو محاكي مجاني ومفتوح المصدر للشبكات العصبية، مكتوب بلغة البرمجة بايثون وهو متاح على جميع الأنظمة الأساسية تقريبًا. يساعد المحاكي في توفير وقت المعالجات إضافةً إلى توفير وقت الباحثين. صُمم محاكي Brian ليكون سهل التعلم والاستخدام ومرن جدًا وقابلًا للتوسيع بسهولة.
</p>

<h3>
	مكتبة Glumpy
</h3>

<p>
	<a href="http://glumpy.github.io/" rel="external nofollow">Glumpy</a> هي مكتبة تصور تفاعلي مبنية على OpenGL في بايثون، وهدفها هو تسهيل إنشاء تمثيلات مرئية سريعة وقابلة للتطوير وجميلة وتفاعلية وديناميكية.
</p>

<h2>
	الخلاصة
</h2>

<p>
	تُعد Numpy مكتبةً متعددة الاستخدامات، ولكن هذا لا يعني أنه ينبغي عليك استخدامها في كل الحالات. عرضنا في هذا الدليل بعض البدائل (بما في ذلك تعليمات بايثون العادية) وهي تستحق البحث والتعب، ولكن الاختيار عائدٌ لك، إذ عليك أن تفكر بالحل الأفضل بالنسبة لك من حيث وقت التطوير ووقت الحساب والجهد الذي ستحتاجه للتعديل. في حال قررت تصميم حلك الخاص فيجب عليك اختباره والمحافظة عليه، ولكن في المقابل ستكون حرًا في تصميمه بالطريقة التي تريدها. من ناحية أخرى: إذا قررت الاعتماد على حزمة طرف ثالث، فستوفر الكثير من وقت التطوير ولكن ستضطر إلى تكييف الحزمة مع احتياجاتك الخاصة.
</p>

<p>
	ترجمة -وبتصرّف- للفصل <a href="https://www.labri.fr/perso/nrougier/from-python-to-numpy/#beyond-numpy" rel="external nofollow">Beyond NumPy</a> من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AE%D8%B5%D9%8A%D8%B5-%D8%A3%D8%B3%D9%84%D9%88%D8%A8-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-custom-vectorization-%D8%B9%D8%A8%D8%B1-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1821/" rel="">تخصيص أسلوب المتجهات Custom vectorization عبر استعمال مكتبة NumPy</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/" rel="">مفاهيم متقدمة حول مكتبة NumPy في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1829</guid><pubDate>Sat, 17 Dec 2022 09:22:08 +0000</pubDate></item><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629; &#x628;&#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1815/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/63945145cad15_---.png.bcc0b73a678c4866b5647e9dfe28f276.png" /></p>
<p>
	سنبدأ في هذا المقال من سلسلة <span ipsnoautolink="true">برمجة الذكاء الاصطناعي</span> في تعلم أساسيات <span ipsnoautolink="true">لغة بايثون</span>، وهي من أهم <span ipsnoautolink="true">لغات البرمجة </span>على الإطلاق المستخدمة في مجال <span ipsnoautolink="true">الذكاء الاصطناعي</span>، ولكنها ليست لذلك فقط؛ إذ تُستعمَل لغة بايثون في كثير من المجالات الأخرى مثل برمجة المواقع وبرامج سطح المكتب و<span ipsnoautolink="true">أنظمة التشغيل</span> وغيرها.
</p>

<h2>
	قبل البدء في أساسيات لغة بايثون: ما هي لغة البرمجة بايثون؟
</h2>

<p>
	تعني <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> في اللغة الإنجليزية نوعًا من الثعابين الكبيرة، لكنها لم تُسمى لذلك بل سُمِّيَت بهذا الاسم تيمنًا ببرنامج ترفيهي قدَّمته قناة BBC يحمل اسم Monty Python’s Flying Circus، وذلك بعد ما شاهده مخترع اللغة.
</p>

<p style="text-align: center;">
	<img alt="code-coding-programming-technology-technical-concept.png" class="ipsImage ipsImage_thumbnailed" data-fileid="117732" data-ratio="66.75" data-unique="5qyxaslmt" width="800" src="https://academy.hsoub.com/uploads/monthly_2023_01/code-coding-programming-technology-technical-concept.png.d6e60f2ed8fa9e9148fcc0ad6f5165f7.png">
</p>

<p>
	وتُعَدّ بايثون لغةً برمجيةً عامةً، أي تستطيع استخدامها في مجالات عدة على عكس بعض اللغات الأخرى التي تتخصص في مجال ما دونًا عن الآخر، كما تُعَدّ لغةً بسيطةً ومتطورةً للغاية، بالإضافة إلى أنها تدعم البرمجة كائنية التوجه Object Oriented Programming أو <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr> اختصارًا.
</p>

<p>
	صُنِعت بايثون بواسطة الهولندي جايدو فان روسم Guido van Rossum، وأُصدِرت في شهر 11 من عام 1994م بعدما عُمِل عليها في معهد الأبحاث القومي للرياضيات <a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">وعلوم الحاسوب</a> في هولندا، في حين نُشر الإصدار الثاني من بايثون في عام 2000م؛ أما الإصدار الثالث، فقد نُشِر في عام 2008م وهو الإصدار المستخدم حاليًا من بايثون لأن الإصدار الثاني السابق قد توقف دعمه وتطويره.
</p>

<h2>
	خصائص لغة بايثون
</h2>

<p>
	تُعَدّ <a href="https://wiki.hsoub.com/Python" rel="external">لغة بايثون</a> لغةً <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D8%A7%D9%84%D9%85%D9%82%D8%B5%D9%88%D8%AF-%D8%A8%D9%85%D8%B5%D8%B7%D9%84%D8%AD-%D9%85%D9%81%D8%AA%D9%88%D8%AD-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-open-source%D8%9F-r885/" rel="">مفتوحة المصدر</a> تجد شيفرتها المصدرية على موقع <a href="https://github.com/python/cpython" rel="external nofollow">GitHub</a>، وبالتالي يستطيع أيّ مبرمج المشاركة في تطوير اللغة. وبحسب موقع جيت هاب GitHub، فقد شارك أكثر من 1200 شخص حول العالم في تطويرها، كما تُعرَف بايثون بسهولة تراكيب الجمل فيها Syntax التي تشبه تركيب اللغة الإنجليزية بنسبة كبيرة، وهي لغة مهمة جدًا للطلبة والباحثين والمهنيين على حد سواء في الكثير من النطاقات العلمية والعملية.
</p>

<p>
	وتتميز بايثون بالميزات التالية:
</p>

<ul>
	<li>
		لغة برمجة مفسرة Interpreted
	</li>
	<li>
		تدعم البرمجة الكائنية
	</li>
	<li>
		مناسبة للمبتدئين
	</li>
	<li>
		مدعومة بالكثير من المكتبات
	</li>
	<li>
		لغة مجانية ومفتوحة المصدر
	</li>
	<li>
		تستخدم في العديد من التخصصات
	</li>
</ul>

<h3>
	لغة برمجة مفسرة Interpreted
</h3>

<p>
	أي أنها تُنفَّذ مباشرةً مثل <a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">لغة PHP</a> ولغة Perl، ولا تحتاج إلى تصريف كامل الشيفرة أولًا ثم تنفيذها مثل لغة C، فلا يتطلب الأمر تحويل الشيفرة الخاصة بك إلى شيفرة ثنائية تفهمها الآلة أولًا لتبدأ عملية التنفيذ، وهذا قد يميز شيفرات بايثون في سرعة تنفيذها أثناء البرمجة.
</p>

<p>
	وفي تلك النقطة بالتحديد قد يختلف بعض المبرمجين، فالبرغم من تصنيف بايثون أنها لغة مفسَّرة، إلا أنّ الشيفرة تُصرَّف compiled أولًا ليستطيع المُفسِّر فهمها قبل تنفيذها، لذلك قد تجد بعض النقاشات المتباينة حول بايثون لمحاولة تصنيفها تصنيفًا دقيقًا. يذهب بعض المبرمجين إلى القول بأنّ لغة بايثون لها طريقتها الخاصة في تلك النقطة، فالأمر معقَّد ولا نريد الخوض فيه.
</p>

<h3>
	تدعم البرمجة الكائنية
</h3>

<p>
	تدعم بايثون نمطًا يُدعى الكائنية في البرمجة Object-oriented programming (أو تدعى الشيئية أحيانًا)، وهو نمط شهير ومهم، إذ تُكتَب الشيفرة ويُتعامَل مع أجزاء التطبيق على أساس الكائنات Objects، وهو نمط غير مدعوم في بعض اللغات القديمة مثل لغة C، كما أنها تدعم البرمجة الوظيفية Functional والهيكلية Structured وغيرها.
</p>

<h3>
	أساسيات لغة بايثون مناسبة للمبتدئين
</h3>

<p>
	تُعَد بايثون مناسبةً جدًا للمبتدئين، حيث أنَّ صياغة الجمل فيها بسيطة للغاية، ولا يتطلب الأمر الدخول في تفاصيل كثيرة عند كتابتها؛ لذلك فهي سهلة التعلم والقراءة.
</p>

<h3>
	مدعومة بالكثير من المكتبات
</h3>

<p>
	يمكنك في بايثون إيجاد مكتبات بسيطة الاستخدام تستطيع بها برمجة تطبيقات معقدة جدًا، فهي لغة لديها أرشيف واسع من المكتبات في كافة المجالات تقريبًا.
</p>

<h3>
	لغة مجانية ومفتوحة المصدر
</h3>

<p>
	توجد بعض لغات البرمجة غير المجانية، أي أنك مُطالَب بدفع الأموال لشركة ما، كي تستطيع استخدام تلك اللغة، كما أنَه لا يمكنك ولا يمكن لأيّ شخص آخر إصلاح مشكلة ما في اللغة أو أن يطوِّر ميزةً أو خاصيةً جديدةً في اللغة، فالشيفرة المصدرية في تلك الحالة تقع تحت أيدي الشركة المصنعة فقط، وهي الوحيدة التي يحق لها تطوير اللغة أو إصلاح مشاكلها أو إصدار نسخ جديدة منها.
</p>

<p>
	أما في بايثون والعديد من اللغات المجانية المفتوحة المصدر، فالأمر مختلف إذ عمِل على على لغة بايثون أكثر من 1200 شخص حول العالم، فالشيفرة المصدرية للغة موجودة ومتاحة على موقع GitHub، ويمكن لأيّ شخص له الخبرة والمعرفة الكافية أن يطوِّر أو يعدِّل ميزةً ما، كما يستطيع مجتمع مبرمِجي بايثون على الإنترنت من المشاركة بآرائهم في تطوير اللغة، فالأمر بالجميع وللجميع، وهي لغة مجانية بالكامل تستطيع استخدامها في أيّ مشروع خيري أو تجاري، بدون أية مشاكل قانونية على الإطلاق.
</p>

<h3>
	تستخدم في العديد من التخصصات
</h3>

<p>
	لا يقتصر الأمر أبدًا على <a href="https://academy.hsoub.com/tags/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9%20%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1%20%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A/" rel="">برمجة الذكاء الاصطناعي</a> و<a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-r1009/" rel="">تعلّم الآلة</a>، ولا يقتصر على برمجة مواقع الويب أيضًا، إذ تُعَدّ بايثون من أكثر لغات البرمجة انتشارًا وتوغلًا في العديد من المجالات في حياتنا اليومية، وفي التخصصات العلمية والأبحاث ومعامل ومختبرات الجامعات حول العالم، لذلك بتعلُُّمك للغة بايثون فإنّ الأمر لا يقتصر على فرصة عمل في مجال <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A/" rel="">الذكاء الاصطناعي</a> فحسب، وإنما تستطيع استخدام معرفتك وخبرتك في بايثون في مجالات أخرى تفتح عليك أبواب دخل إضافية.
</p>

<p>
	تُشتهر بايثون أيضًا في استخدامها في برمجة المواقع و<a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8/" rel="">تطبيقات سطح المكتب</a> وبرمجة برامج تجارية عبر بايثون مثل <a href="https://academy.hsoub.com/apps/erp/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A3%D9%88%D8%AF%D9%88-odoo/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D9%85%D9%88%D9%82%D8%B9-%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%AF%D9%88-odoo-r686/" rel="">أودوو Odoo</a> الذي يُعَدّ أشهرها وله متخصصين وشركات تجارية تعتمد كليةً على استخدامه.
</p>

<p>
	كما أنَّ لغة بايثون كما أوردنا تدخل في الكثير من مجالات البحث العلمي، فهي من أكثر اللغات التي تحتوي على مكتبات تهدف إلى خدمة مجالات البحث العلمي والرياضيات من الذكاء الاصطناعي حتى التغير المناخي وتُعَد دراسة لغة بايثون أمرًا أساسيًا بالنسبة لمبرمجي الذكاء الاصطناعي، لذلك سنبدأ الآن في دراسة أساسيات اللغة حتى نكون على قدر من المعرفة المطلوبة لنبدأ في دراسة وتطبيق <a href="https://wiki.hsoub.com/Algorithms" rel="external">الخوارزميات</a> الأساسية في تعلُّم الآلة. لذلك فإن السهل البدء بتعلم أساسيات بايثون والبدء في عالم البرمجة بسهولة.
</p>

<h2>
	تثبيت لغة بايثون
</h2>

<p>
	أول ما نبدأ به في تعلم أساسيات لغة Python ولكي تستطيع العمل بلغة بايثون، يجب عليك أولًا تثبيت البرنامج الذي يفهم اللغة ثم ينفذها، وذلك لكي يستطيع حاسوبك التعرف على الأوامر التي تكتبها لتعمل عليه بصورة صحيحة، لذلك من الضروري أن تكون أول خطوة نقوم بها هي تثبيت لغة بايثون على حاسوبك.
</p>

<p>
	يختلف أمر تثبيت اللغة باختلاف <a href="https://academy.hsoub.com/apps/operating-systems/%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84/" rel="">نظام التشغيل</a>، فإذا كان حاسوبك مثلًا يعمل على نظام <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس Linux</a>، فعلى الأرجح أنّ حاسوبك مثبَّت عليه بالفعل لغة بايثون، وللتأكد من ذلك يمكنك فتح الطرفية Terminal ثم كتابة الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_21" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python </span><span class="pun">--</span><span class="pln">version</span></pre>

<p>
	أول الأمر التالي بالنسبة للإصدار الثالث:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_23" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python3 </span><span class="pun">--</span><span class="pln">version</span></pre>

<p>
	إذا كانت بايثون مثبتةً بالفعل على حاسوبك، فسيظهر لك رقم الإصدار المثبَّت، والجدير بالذكر أنه يجب أن يكون الإصدار المثبت لديك هو الإصدار الثالث، وبالتالي يجب بدء رقم الإصدار بالرقم 3؛ أما إذا لم تكن اللغة مثبتةً على حاسوبك، فيمكنك ذلك عبر تنفيذ الأمر الآتي في الطرفية Terminal على لينكس.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_25" style=""><span class="pun">&gt;&gt;</span><span class="pln"> sudo apt</span><span class="pun">-</span><span class="pln">get install python3</span><span class="pun">.</span><span class="lit">6</span></pre>

<p>
	أما إذا كنت مستخدِمًا لنظام التشغيل ماك macOS بمختلف إصداراته، فعلى الأغلب أيضًا أنّ لغة بايثون مثبتة بالفعل على حاسوبك، وتستطيع اختبار ذلك عبر الأمر السابق ذكره بخصوص نظام لينكس، فإذا لم تكن اللغة مثبتةً، فيمكنك ببساطة تثبيتها مثل أيّ برنامج أخر عن طريق الموقع الرسمي للغة <a href="python.org/downloads" rel="">/Python</a>.
</p>

<p>
	بعد تثبيت اللغة بالطرق الموضحة أعلاه في نظامي لينكس وماكينتوش، فمن المحتمل ألا يعمل أمر التحقق من الإصدار وألا يكون جاهزًا للعمل بعد، إذ أنه قد لا يُتعرَّف على برنامج بايثون عندما تُنفِّذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_27" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python </span><span class="pun">--</span><span class="pln">version</span></pre>

<p>
	ولحل ذلك يجب تنفيذ الأمر التالي في الطرفية Terminal:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_29" style=""><span class="pun">&gt;&gt;</span><span class="pln"> export PYTHONPATH</span><span class="pun">=/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">python3</span><span class="pun">.</span><span class="lit">6</span></pre>

<p>
	مع تغيير كلمة <code>python3.6</code> لأنها قد تختلف حسب الإصدار الذي ثبَّته؛ لذلك يجب التحقق من ذلك المسار على حاسوبك أولًا لترى أيّ الإصدارات يجب استدعاؤها في الأمر السابق.
</p>

<p>
	أما في حالة مستخدمي نظام الويندوز، فالأمر بسيط للغاية، إذ تستطيع تنزيل برنامج اللغة من الموقع الرسمي السالف ذكره، ثم تثبيته مثل أيّ برنامج آخر على حاسوبك دون تعقيدات قد لا يعمل كذلك أمر التحقق من إصدار اللغة بصورة تلقائية بعد التثبيت، ولحل ذلك ببساطة يمكنك فتح موجِّه الأوامر Command Prompt في ويندوز ثم تنفيذ الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_31" style=""><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">%</span><span class="pln">path</span><span class="pun">%;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Python</span></pre>

<p>
	مع الأخذ في الحسبان إمكانية تغيير النص C:\Python إذا كنت قد تثبَّت اللغة في مسار آخر على حاسوبك أثناء عملية التثبيت.
</p>

<h3>
	استعمال بايثون مع خدمة Google Colab
</h3>

<p>
	ضمن أساسيات لغة بايثون وبالرغم من سهولة عملية تثبيت بايثون على حاسوبك، فإنه ليس من الضروري فعلًا فعل تلك الخطوات السالف ذكرها، فقد أصدرت شركة جوجل مؤخرًا ما يُدعى Google Colaboratory عبر موقع الأبحاث الخاص بها <a href="colab.research.google.com" rel="">\colab.research</a>، وبالتالي تستطيع ببساطة استخدام تلك الخاصية بإنشاء ذلك النوع من الملفات على خدمة <a href="https://academy.hsoub.com/apps/productivity/google-drive/" rel="">Google Drive</a> الموجودة مجانيًا لأي عنوان بريد إلكتروني مُسجَّل على Gmail، بعدها يمكنك البدء في كتابة وتنفيذ شيفرة البايثون الخاصة بك عبر الإنترنت دون الحاجة إلى الدخول في الكثير من التعقيدات والمشاكل التقنية أثناء تعلمك، أو حتى أثناء عملك في برمجة الذكاء الاصطناعي.
</p>

<p>
	كما تحتوى تلك الخدمة تلقائيًا على معظم وأهم مكتبات بايثون المستخدَمة في مجال الذكاء الاصطناعي عامةً ومجال تعلّم الآلة خاصةً، فنجد مثلًا تلقائيًا في تلك الخدمة أنّ مكتبات متخصصة في الرياضيات مثل Numpy، ومكتبات متخصصة في رسم البيانات مثل Matplotlib ومكتبات متخصصة في خوارزميات تعلّم الآلة مثل Keras، ومكتبات متخصصة في التعلّم العميق والشبكات العصبية مثل Tensorflow …إلخ مثبتة ومتاحة للاستخدام مباشرةً.
</p>

<p>
	أُصدِرت الخدمة أساسًا للتسهيل على العاملين في مجال برمجة الذكاء الاصطناعي، وبالأخص تعلُّم الآلة ليستطيع المبرمج مشاركة الشيفرة المصدرية الخاصة به مع نتائج هذه الشيفرة والملاحظات مع شركائه في العمل أو أي شخص آخر، وهي خدمة سحابية بالكامل، أي أنها تعمل عبر الإنترنت ولا تحتاج إلى أي متطلبات أو إمكانيات في حاسوبك، فكل ما تحتاجه لاستخدام الخدمة هي وصلة الإنترنت وعنوان بريد إلكتروني من Gmail.
</p>

<p>
	أفضِّل شخصيًا استخدام تلك الخدمة أثناء التعلم لأنها بسيطة وسهلة، وتحتوي تلقائيًا على الكثير من مكتبات بايثون الخاصة بالذكاء الاصطناعي التي قد يكون تثبيت بعضها عملًا شاقًا إذا حدث خطأ ما أثناء التثبيت والسبب الآخر الذي يدفعني إلى التوصية باستخدام تلك الخدمة بشدة، هو عدم امتلاك بعض أجهزة الحاسوب للإمكانيات اللازمة لتشغيل نماذج تعلّم الآلة، إذ تحتاج بعض الخوارزميات إلى ذاكرة عشوائية RAM كبيرة ليُدرَّب النموذج تدريبًا صحيحًا، وذلك اعتمادًا على حجم البيانات المتدفقة إلى النموذج.
</p>

<p>
	ولمزيد من التفاصيل، ارجع إلى مقال <a href="https://academy.hsoub.com/apps/productivity/%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-google-colab-r742" rel="">دليل استخدام Google Colab</a>.
</p>

<h2>
	برنامجك الأول في لغة بايثون
</h2>

<p>
	من أساسيات لغة بايثون أنك تستطيع البدء في كتابة برنامجك الأول بعدة من الطرق، أولها عبر كتابة الشيفرة مباشرةً في الطرفية Terminal في لينكس وماك وموجِّه الأوامر Command Prompt في ويندوز؛ وثانيها، كتابة البرنامج في ملف أو عدة ملفات منفصلة، ثم تشغيلها عبر البرامج السابق ذكرها؛ أما ثالثها فتكون عن طريق خدمة Google Colab التي ذكرناها سابقًا.
</p>

<p>
	أما كتابة الشيفرة مباشرة في الطرفية وموجه الأوامر، فالخطوات لذلك بسيطة، وكل ما عليك فعله بعد فتح أحد تلك البرامج حسب نظام التشغيل الخاص بحاسوبك هو تنفيذ الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_34" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python</span></pre>

<p>
	أو الأمر التالي بالنسبة للإصدار 3 من بايثون:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_36" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python3</span></pre>

<p>
	تستطيع بعد ذلك كتابة أوامر بايثون مباشرةً وتنفيذها، كما يمكنك الخروج من هذه الشاشة بعد ذلك عبر كتابة الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_38" style=""><span class="pun">&gt;&gt;</span><span class="pln"> quit</span><span class="pun">()</span></pre>

<p>
	وأما كتابة الشيفرة في ملف منفصل، فتستطيع إنشاء ملف جديد في أيّ مكان في حاسوبك وتسميته بأيّ اسم تريده، كما يفضَّل أن يكون الاسم معبِّرًا، فالتسمية البسيطة والمعبِّرة من الأمور المهمة. احفظ بعد ذلك الملف بصيغة py -وهي صيغة اختصارية لكلمة Python-، فإذا كان مثلًا اسم الملف Program، فستكون التسمية الكاملة للملف Program.py، ثم اذهب إلى المكان المخزن فيه الملف غبر الطرفية أو موجِّه الأوامر، وبعدها نفِّذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_40" style=""><span class="pun">&gt;&gt;</span><span class="pln"> python </span><span class="typ">Program</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	والطريقة الثالثة، تستطيع ببساطة استخدام Google Colab من خدمة Google Drive ومن ثم إنشاء ملف جديد من نوع Google Colaboratory، ثم البدء في إضافة الفقرات، فيمكنك إضافة شيفرات بايثون في ذلك الملف بجانب نصوص عادية وبذلك تستطيع كتابة ملاحظات وتعليقات بين أسطر الشيفرات ويمكنك في الوقت نفسه تنفيذ الشيفرات ككل أو أجزاء محددة.
</p>

<p>
	سنبدأ بأمر الطباعة لكتابة أول برنامج بايثون خاص بك، فوظيفة أمر الطباعة في بايثون وفي كثير من اللغات الأخرى، هي طباعة نص على شاشة المستخدِم عند تشغيل البرنامج، وقد ذكرنا ذلك الأمر سابقًا عند الحديث عن الخوارزميات في البرمجة، فعند كتابة الأمر <code>print</code> والذي يعني اطبع بالإنجليزية، فيجب إلحاقه بقوسين، ومن ثم فتح علامات تنصيص بداخل القوسين تحتوى على الجملة التي نريد طباعتها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_42" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">)</span></pre>

<p>
	قد يُستخدَم الأمر <code>print</code> لطباعة النصوص على الشاشة أو لطباعة الأرقام، فالأمر سيان في حالة الطباعة، ولكن لا يجب إضافة علامات تنصيص في حالة طباعة الأعداد.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_44" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3</span></pre>

<p>
	كما أنه من الممكن طباعة نتيجة عملية رياضية بسيطة مثل عمليات الجمع والطرح كما في الأمثلة الآتية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_47" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pun">+</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">6</span><span class="pun">-</span><span class="lit">4</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2</span></pre>

<p>
	يمكن أيضًا طباعة عمليات الضرب والقسمة وباقي القسمة، إذ يمكنك عبر كتابة الشيفرة التالية طباعة حاصل ضرب عددين مثلًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_49" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">6</span><span class="pun">*</span><span class="lit">6</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">36</span></pre>

<p>
	والأمر بسيط كذلك لطباعة حاصل قسمة عددين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_51" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">49</span><span class="pun">/</span><span class="lit">7</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">7.0</span></pre>

<p>
	أما حالة طباعة باقي القسمة، فسنستخدِم رمز النسبة المئوية <code>%</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_53" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="lit">50</span><span class="pun">%</span><span class="lit">7</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	كما يمكنك طباعة أيّ عدد من النصوص باستخدام علامة الزائد <code>+</code> كما في المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_55" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"World!"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="typ">World</span><span class="pun">!</span></pre>

<p>
	إذا أردنا تضمين قيمة عددية داخل نص، فيجب فيجب تحويل العدد إلى نص لأنّ الأعداد في بايثون وفي عدد من اللغات الأخرى عمومًا هي نوع من أنواع البيانات، لذلك يجب استخدام دالة <code>str</code> في هذه الحالة لتحويل العدد إلى نص لتستطيع لغة بايثون التعامل معها على أساس نص.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_57" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello "</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)+</span><span class="str">"nd "</span><span class="pun">+</span><span class="str">"World!"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="lit">2nd</span><span class="pln"> </span><span class="typ">World</span><span class="pun">!</span></pre>

<p>
	نستطيع الاستغناء عن دالة <code>str</code> إذا أدرجنا الأعداد داخل علامات التنصيص، إذ ستَعُدّ بايثون الأعداد داخل علامات التنصيص نصًا عاديًا، كما سنتعرف على الدوال بصورة أكبر في الصفحات القادمة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_59" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"2nd "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"World!"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="lit">2nd</span><span class="pln"> </span><span class="typ">World</span><span class="pun">!</span></pre>

<h2>
	المعرفات في بايثون
</h2>

<p>
	تعد المعرِّفات Identifiers من أساسيات البايثون وهي الكلمات التي تستطيع من خلالها تعريف اسم متغير Variable أو ثابت Constant أو دالة Function أو صنف Class أو وحدة Module، ونختصر ذلك كله الآن بكلمة المعرِّفات فقط للدلالة على أيّ منهم، فتلك المتغيرات والثوابت والدوال والأصناف والوحدات، كلها مواضيع وسنتعرف عليها بالتفصيل في هذا الكتاب.
</p>

<p>
	تخضع تسمية المعرفات إلى قواعد محدَّدة لا يُمكن الخروج عنها في بايثون؛ لأنه عند الخروج عن إحدى القواعد سيطبع مفسر بايثون رسالة خطأ عند محاولتك تشغيل البرنامج، وتلك القواعد كما يلي:
</p>

<ol>
	<li>
		يجب أن تبدأ بحرف إنجليزي أو شَرطة سفلية Underscore <code>_</code> ولا يُمكنها البدء برقم أبدًا.
	</li>
	<li>
		لا يمكنها احتواء رموز مثل <code>%</code> أو <code>$</code> أو <code>&amp;</code> …إلخ، ولكن يمكنها احتواء الأرقام.
	</li>
	<li>
		ألا تكون مطابقةً لأيّ كلمة من الكلمات المفتاحية في بايثون.
	</li>
</ol>

<p>
	الكلمات المفتاحية في بايثون هي كلمات تُستخدَم في أصل اللغة، بمعنى أنّ تلك الكلمات يقرؤها مفسر لغة بايثون لإجراء مهمة ما، فكلمة مثل <code>print</code> كما علمنا من قبل تؤدي مهمة طباعة نص أو عدد على الشاشة، لذلك لا نستطيع تعريف متغير أو ثابت أو دالة بهذا الاسم، وتكون جميع الكلمات المفتاحية في لغة بايثون كما يلي:
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
	<tbody>
		<tr>
			<td>
				and
			</td>
			<td>
				exec
			</td>
			<td>
				not
			</td>
		</tr>
		<tr>
			<td>
				as
			</td>
			<td>
				finally
			</td>
			<td>
				or
			</td>
		</tr>
		<tr>
			<td>
				assert
			</td>
			<td>
				for
			</td>
			<td>
				Pass
			</td>
		</tr>
		<tr>
			<td>
				break
			</td>
			<td>
				from
			</td>
			<td>
				print
			</td>
		</tr>
		<tr>
			<td>
				class
			</td>
			<td>
				global
			</td>
			<td>
				raise
			</td>
		</tr>
		<tr>
			<td>
				continue
			</td>
			<td>
				if
			</td>
			<td>
				return
			</td>
		</tr>
		<tr>
			<td>
				def
			</td>
			<td>
				import
			</td>
			<td>
				try
			</td>
		</tr>
		<tr>
			<td>
				del
			</td>
			<td>
				in
			</td>
			<td>
				while
			</td>
		</tr>
		<tr>
			<td>
				elif
			</td>
			<td>
				is
			</td>
			<td>
				with
			</td>
		</tr>
		<tr>
			<td>
				else
			</td>
			<td>
				lambda
			</td>
			<td>
				yield
			</td>
		</tr>
		<tr>
			<td>
				except
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
	</tbody>
</table>

<p>
	والجدير بالذكر أنّ جميع تلك الكلمات المفتاحية لا تحتوي على أي حرف كبير، وبما أنّ لغة بايثون لغة حساسة لحالة الأحرف، فمن تسمية أيّ معرِّف بتلك الكلمات في حالة تغيير حالة الأحرف، بمعنى أنه لا يُمكنك تسمية متغير باسم print، لكن يمكنك تسمية متغير باسم Print أو PRINT لأنه بالنسبة لبايثون، تكون الكلمات الثلاثة السابقة مختلفةً تمامًا عن بعضها، وبناءً على ذلك، فإذا أردت تسمية متغير أو دالة أو صنف في بايثون، فيجب عليك اتباع القواعد السابقة.
</p>

<p>
	كما أنّ هناك أيضًا في بايثون بعض التوصيات أثناء التسمية، وهي ليست قواعدًا يجب اتباعها بل هي أقرب إلى العُرف، ولكن من الأفضل اتباعها حتى تكون الشيفرة المصدرية في أفضل صورة ممكنة، وتلك التوصيات هي كما يلي:
</p>

<ol>
	<li>
		اسم الصنف من المفضل أن يبدأ بحرف كبير مثل Mouse وليس mouse.
	</li>
	<li>
		جميع المعرِّفات الأخرى مثل المتغيرات والدوال من الأفضل أن تبدأ بحرف صغير.
	</li>
	<li>
		إذا عرَّفت متغيرًا ما خاصًا، ولا تريد أن يُستخدَم في أيّ مكان آخر في البرنامج، فمن المفضل بدء اسم المتغير بشرطة سفلية واحدة أو شرطتين إذا كان المتغير خاصًا جدًا.
	</li>
</ol>

<h2>
	السطور والمسافات
</h2>

<p>
	لدى بايثون نوعًا فريدًا من القواعد عندما يتعلق الأمر بالأسطر والمسافات وتنظيم الشيفرة، إذ تستخدِم معظم <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> الأخرى الأقواس المعقوصة <code>{ }</code> لكتابة كتلة من الشيفرات، لكن الأمر في بايثون مختلف قليلًا، إذ تُنظَّم كتل الشيفرات باستخدام المسافات، وهي عادةً مسافة جدولة Tab، أو فراغين أو أربعة فراغات spaces، فنكتب كتلةً من الشيفرات لتُنفَّذ عند تحقق شرط معين بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_61" style=""><span class="kwd">if</span><span class="pln"> something_happens</span><span class="pun">:</span><span class="pln">
    do_this</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
    do_that</span><span class="pun">()</span></pre>

<p>
	نقول للمفسر في المثال السابق الوهمي إذا حدث هذا الأمر، افعل هذا؛ وإذ لم يحدث، افعل ذاك، فالأمر بسيط للغاية، المهم دقق بالمسافات وكيف أن <code>do_this</code> تدخل ضمن الشرط <code>if</code> أما <code>do_that</code> فتدخل ضمن <code>else</code>.
</p>

<p>
	وبالمثل، عند كتابة كتلة من الشيفرة داخل أيّ قاعدة شرطية أو غيرها من القواعد، يجب عليك البدء في كتابة أسطر الشيفرة الخاصة بالكتلة بعد مسافة تفصل بينها وبين أول السطر، أو بمعنى أدق تفصل بينها وبين كتلة الشيفرة التي تسبقها، انظر مثلًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_63" style=""><span class="pln">count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> count </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> count </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Count is between 10 and 20"</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Count is larger than 20"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Count is less than 10"</span><span class="pun">)</span></pre>

<p>
	وإليك المثال التالي لموازنة طريقة بايثون تلك مع اللغات الأخرى مثل <a href="https://wiki.hsoub.com/JavaScript" rel="external">لغة جافاسكربت</a>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_65" style=""><span class="pln">let count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is between 10 and 20"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is larger than 20"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is less than 10"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تضمَّن كتل الشيفرة في هذا المثال بداخل القواعد الشرطية داخل أقواس معقوصة بغض النظر عن المسافة بين كل سطر وبدايته، المثال السابق يكافئ:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_68" style=""><span class="pln">let count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is between 10 and 20"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is larger than 20"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Count is less than 10"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المثالان السابقان متطابقان تمامًا ويعملان بلا مشكلة؛ أما في بايثون، فتخضع الشيفرة إلى قاعدة مسافات الأسطر تلك، ولا يُمكن كسر تلك القاعدة، كما أنّ كافة مبرمجي بايثون يحبون قاعدة المسافات لأنها تُجبِر المبرمجين على كتابة شيفرة بسيطة ومنظمة وسهلة القراءة.
</p>

<p>
	ومن أساسيات البايثون وأهم القواعد الخاصة بالأسطر في بايثون، نجد قاعدة استكمال الأسطر، فإذا كنت تكتب سطرًا ما وكان هذا السطر طويلًا للغاية وتريد تقسيمه إلى سطرين، فستستطيع في بايثون تحقيق ذلك عبر استخدام الرمز <code>\</code>، فإذا كتبت سطرًا يجمع رقمَين مثلًا ثم يقسم أحدهما على الآخر، وكنت تريد تجزئة هذا السطر إلى سطرين مختلفين، فيمكنك فعل ذلك كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_70" style=""><span class="lit">30</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">31.0</span><span class="pln">
</span><span class="lit">30</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> \
</span><span class="pun">/</span><span class="pln"> </span><span class="lit">6</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">31.0</span></pre>

<p>
	كتبنا في السطر الأول عملية الجمع مع عملية القسمة في سطر واحد مباشرةً وأنتج ذلك العدد <code>31</code>، أما في المثال الثاني كتبنا عملية الجمع في السطر الأول فقط، ثم ألحقنا عملية الجمع بالرمز <code>\</code>، واستكملنا السطر التالي العمليات بكتابة عملية القسمة مباشرةً، وأنتج ذلك في النهاية العدد نفسه، لكن توجد مع ذلك حالة خاصة لأيّ سطر في بايثون يحتوي على إحدى الأقواس بمختلف أنواعها، مثل <code>[]</code> أو <code>{}</code> أو <code>()</code>، إذ يمكن كتابة تلك الأسطر على سطرين أو أكثر دون استخدام الرمز السابق ذكره، فالسطر التالي مثلًا يعمل بدون مشكلة حتى مع عدم استخدامنا للرمز.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_72" style=""><span class="pln">items </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'item_1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'item_2'</span><span class="pun">,</span><span class="pln">
         </span><span class="str">'item_3'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'item_4'</span><span class="pun">,</span><span class="pln">
         </span><span class="str">'item_5'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'item_6'</span><span class="pun">]</span></pre>

<h2>
	علامات التنصيص
</h2>

<p>
	توجد اختلافات بسيطة بين علامات التنصيص في <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">لغة بايثون</a> مثل أي لغة برمجة أخرى، إذ يمكنك في بايثون تضمين أيّ نص بين علامتَي تنصيص مُفرَدة ' أو علامتي تنصيص مزدوجة " أو علامتي تنصيص ثلاثية """ أو ''' لكن من أهم قواعد استخدام علامات التنصيص في بايثون هي إنهاء النص بعلامة التنصيص نفسها المُستخدَمة في البداية، فلا يُمكن استخدام علامة تنصيص مُفرَدة في بداية النص ثم استخدام علامة تنصيص مزدوجة في نهايته، وإنما يجب تطابق العلامة في البداية والنهاية للنص الواحد، وإليك أمثلةً على ذلك في أوامر الطباعة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_74" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello World!"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Hello World!'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"""Hello World!"""</span><span class="pun">)</span></pre>

<p>
	أما بالنسبة لعلامات التنصيص الثلاثية، فتُستخدَم في الغالب لامتلاكها ميزةً غير موجودة في العلامات المفرَدة والمزدوجة، إذ تُعَدّ قادرةً على معالجة النصوص التي تتكون من أكثر من سطر، في حين أنّ علامات التنصيص المُفردة والمزدوجة يجب احتوائها على نص مكوَّن من سطر واحد لا أكثر، فلا يمكنك مثلًا طباعة سطرين متتالين عبر علامات التنصيص المزدوجة، أي لا يمكنك تنفيذ المثال التالي في بايثون بصورة صحيحة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_76" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello
World!"</span><span class="pun">)</span></pre>

<p>
	لكن يمكنك تنفيذ ذلك الأمر عند استخدام علامات التنصيص الثلاثية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_78" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"""Hello
World!"""</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln">
</span><span class="typ">World</span><span class="pun">!</span></pre>

<h2>
	التعليقات في أساسيات لغة بايثون
</h2>

<p>
	ستحتاج في كثير من الأوقات أثناء كتابتك أو عملك على برنامج ما، إلى كتابة بعض الملاحظات على بعض الأسطر، فقد تكون تلك الملاحظات موجهةً لتذكيرك بكيفية عمل هذه الكتلة من الشيفرة، أو لتذكيرك بأمر ما تريد استكماله في هذه الأسطر في وقت لاحق، وتوفر بايثون مثلها مثل بقية لغات البرمجة إمكانية كتابة التعليقات عبر استعمال الرمز # والذي سيؤدي إلى تجاهل ما يليه حتى آخر السطر، انظر مثلًا الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_80" style=""><span class="com"># هذا تعليق</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello, Python!"</span><span class="pun">)</span><span class="pln"> </span><span class="com"># تعليق آخر</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Python</span><span class="pun">!</span></pre>

<p>
	كما ترى، فإنّ المثال السابق يعمل عملًا عاديًا وكأنه مكتوب بالشكل التالي دون تعليقات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_82" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello, Python!"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Python</span><span class="pun">!</span></pre>

<p>
	فإذا كتبت أيّ سطر برمجي بعد رمز # فسيتجاهله مفسر بايثون تمامًا كما لو أنه غير موجود؛ وذلك لأن التعليقات هي في الأساس جمل من اللغة الطبيعية البشرية التي يستخدمها المبرمج للتعليق وكتابة الملاحظات بين تعليمات البرنامج.
</p>

<p>
	كما أنه في بايثون توجد طريقة أخرى لكتابة التعليقات في أسطر عدة، وذلك باستخدام علامات التنصيص الثلاثية، ومن مميزات هذه الطريقة أنها قد تُستخدم في توثيق الدوال وغير ذلك، كما أن هنالك أدوات تستخلص تلك التعليقات لتوليد توثيق لشيفرة البرنامج ووظائفه.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_84" style=""><span class="str">"""This is a multi line comment.
It's wonderful how easy is Python language!"""</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello World!"</span><span class="pun">)</span></pre>

<p>
	تُستخدَم التعليقات استخدامًا كبيرًا أثناء برمجة التطبيقات المعقَّدة، فغير أنها تُستخدَم للتعليق على الشيفرة، فإنها قد تكون مفيدةً بصورة كبيرة في تعطيل وتفعيل بعض الأسطر في الشيفرة أثناء عملك على حل مشكلة ما، مثل نسخ سطر ما ووضعه بداخل التعليق حتى يتجاهله البرنامج، ولكي أحتفظ بذلك السطر لاستخدامه لاحقًا.
</p>

<h2>
	تعليمات متعددة في سطر واحد
</h2>

<p>
	تنتهي التعليمة البرمجية في السطر في معظم لغات البرمجة مثل <a href="https://wiki.hsoub.com/PHP" rel="external">لغة PHP</a> أو جافاسكربت JavaScript عن طريق كتابة رمز الفاصلة المنقوطة <code>;</code> مما يسمح بكتابة أكثر من تعليمة برمجية في سطر واحد؛ أما في بايثون، فينتهي السطر عن طريق بداية سطر جديد، ولكن مع ذلك تدعم بايثون تلك الميزة أيضًا، إذ يمكنك إنهاء التعليمة البرمجية عبر الرمز <code>;</code> وهو بالإنجليزية Semicolon، وهو أمر اختياري وليس إجباريًا كما في اللغات الأخرى، وبذلك تستطيع كتابة أكثر من تعليمة برمجية في سطر واحد مثل اللغات الأخرى.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5455_87" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Hello"</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"World"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">World</span></pre>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A-r1814/" rel="">البرمجة والخوارزميات والذكاء الاصطناعي</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1815</guid><pubDate>Sat, 31 Dec 2022 18:07:00 +0000</pubDate></item><item><title>&#x62A;&#x62E;&#x635;&#x64A;&#x635; &#x623;&#x633;&#x644;&#x648;&#x628; &#x627;&#x644;&#x645;&#x62A;&#x62C;&#x647;&#x627;&#x62A; Custom vectorization &#x639;&#x628;&#x631; &#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x645;&#x643;&#x62A;&#x628;&#x629; NumPy</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%AE%D8%B5%D9%8A%D8%B5-%D8%A3%D8%B3%D9%84%D9%88%D8%A8-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-custom-vectorization-%D8%B9%D8%A8%D8%B1-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1821/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/639859a3dce9a_----.png.f06aa7c3372b7c14e3f52e9b4022b478.png" /></p>

<p>
	تتمثل إحدى نقاط قوة مكتبة NumPy في إمكانية استخدامها لبناء كائنات جديدة أو لتصنيف كائن <code>ndarray</code> إلى صنف فرعي. هذه العملية السابقة مملة بعض الشيء ولكنها تستحق الجهد لأنها تسمح لك بتحسين كائن <code>ndarray</code> ليناسب مشكلتك.
</p>

<p>
	سندرس في هذا المقال حالتين من العالم الحقيقي (قائمة مقيدة بنوع typed list ومصفوفة مراعية للذاكرة memory-aware array) اللتان تُستخدمان على نطاق واسع في مشروع glumpy، بينما تُعد الحالة الثانية -وهي مصفوفة مضاعفة الدقة double precision array- شائعة في الدراسة الأكاديمية.
</p>

<h3>
	القائمة المقيدة بنوع Typed list
</h3>

<p>
	تسمى أيضًا المصفوفة غير المنتظمة، وهي قائمة بالعناصر التي تحتوي جميعها على نفس نوع البيانات (بمعنى NumPy). وتوفر كلًا من القائمة وواجهة برمجة تطبيقات ndarray. ولكن نظرًا لأن <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-r1314/" rel="">واجهات برمجة التطبيقات APIs</a> المخصصة قد لا تكون متوافقة في بعض الحالات، علينا تحديد الخيارات. على سبيل المثال فيما يتعلق بالعامل "+" سنختار استخدام NumPy <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>، إذ تُضاف القيمة إلى كل عنصر على حدة بدلًا من توسيع القائمة عن طريق إلحاق عنصر جديد بها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_8" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> l </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">([[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">]])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">l</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">l</span><span class="pun">+</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span></pre>

<p>
	نريد أن نوفر للكائن الجديد إمكانية إدراج العناصر وإنشائها وإزالتها بسلاسة من قائمة <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>، وهذا ما سنوضحه في الفقرات التالية.
</p>

<h3>
	الإنشاء Creation
</h3>

<p>
	نظرًا لأن الكائن ديناميكي بحكم التعريف، فمن المهم تقديم تابع إنشاء للأغراض العامة general-purpose قوي بما يكفي لتجنب الاضطرار إلى معالجات لاحقة، إذ تكلف معالجات مثل الإدراج، أو الحذف كثيرًا من العمليات ونحن نسعى إلى تجنبها. إليك اقتراح لإنشاء كائن <code>TypedList</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_10" style="">
<span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> sizes</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">float</span><span class="pun">)</span><span class="pln">
    </span><span class="str">"""
    Parameters
    ----------

    data : array_like
        An array, any object exposing the array interface, an object
        whose __array__ method returns an array, or any (nested) sequence.

    sizes:  int or 1-D array
        If `itemsize is an integer, N, the array will be divided
        into elements of size N. If such partition is not possible,
        an error is raised.

        If `itemsize` is 1-D array, the array will be divided into
        elements whose successive sizes will be picked from itemsize.
        If the sum of itemsize values is different from array size,
        an error is raised.

    dtype: np.dtype
        Any object that can be interpreted as a NumPy data type.
    """</span></pre>

<p>
	تسمح واجهة برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> هذه بإنشاء قائمة فارغة أو إنشاء قائمة من بعض البيانات الخارجية. لاحظ أنه في الحالة الأخيرة نحتاج إلى تحديد كيفية تقسيم البيانات إلى عدة عناصر أو تقسيمها إلى عناصر بحجم 1، ويمكن أن يكون قسمًا عاديًا (أي أن كل عنصر بطول بيانات 2)، أو قسمًا مخصصًا (أي يجب تقسيم البيانات إلى عناصر بحجم 1 و2 و3 و4 عنصر).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_12" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> L </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">([[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">6</span><span class="pun">,</span><span class="lit">7</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">9</span><span class="pun">]])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">L</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pln"> </span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">6</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="lit">8</span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span><span class="pln">

</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> L </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">10</span><span class="pun">),</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">])</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pln"> </span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="lit">6</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="lit">8</span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span></pre>

<p>
	في هذه المرحلة السؤال هو ما إذا كان يجب إنشاء صنف فرعي مشتق من الصنف <code>ndarray</code>، أو استخدام مصفوفة <code>ndarray</code> داخلية لتخزين بياناتنا. في هذه الحالة، ليس من المنطقي استخدام صنف فرعي <code>ndarray</code> لأننا لا نريد تقديم واجهة <code>ndarray</code>. بدلًا من ذلك، سنستخدم مصفوفة <code>ndarray</code> لتخزين بيانات القائمة وسيوفر لنا اختيار هذا التصميم مزيدًا من المرونة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113756" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398599c4adfe_01.png.260de6274d88613c4d91843e949a0218.png" rel=""><img alt="استخدام مصفوفة عناصر items" class="ipsImage ipsImage_thumbnailed" data-fileid="113756" data-unique="29rhqe9mr" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398599cbb47e_01.thumb.png.97f650a81df51eef04b3d9730ab35da9.png" style="width: 600px; height: auto;"></a>
</p>

<p>
	سنستخدم لتخزين حد limit لكل عنصر مصفوفة عناصر items، ستهتم بتخزين الموضع (البداية والنهاية) لكل عنصر. توجد حالتان منفصلتان لإنشاء قائمة، هما: لم تُقدم أية بيانات، أو قُدمت بعض البيانات. الحالة الأولى سهلة وتتطلب فقط إنشاء مصفوفتي <code>data_</code> و <code>items_</code>. لاحظ أن حجم المصفوفتين غير فارغ لأن تغيير حجم المصفوفة سيكون مكلفًا جدًا في كل مرة ندخل عنصر جديد فيها. لذلك من الأفضل حجز بعض المساحة.
</p>

<p>
	<strong>الحالة الأولى</strong>: لم تُقدّم أية بيانات، فقط <code>dtype</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_15" style="">
<span class="pln">self</span><span class="pun">.</span><span class="pln">_data </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="lit">512</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">dtype</span><span class="pun">)</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_items </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="lit">64</span><span class="pun">,</span><span class="lit">2</span><span class="pun">),</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_size </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	<strong>الحالة الثانية</strong>: قُدمت بعض البيانات بالإضافة إلى قائمة بأحجام العناصر.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_17" style="">
<span class="pln">self</span><span class="pun">.</span><span class="pln">_data </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span><span class="pln"> copy</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_size </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">.</span><span class="pln">size
self</span><span class="pun">.</span><span class="pln">_count </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">sizes</span><span class="pun">)</span><span class="pln">
indices </span><span class="pun">=</span><span class="pln"> sizes</span><span class="pun">.</span><span class="pln">cumsum</span><span class="pun">()</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_items </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="pln">len</span><span class="pun">(</span><span class="pln">sizes</span><span class="pun">),</span><span class="lit">2</span><span class="pun">),</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:,</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> indices</span><span class="pun">[:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:,</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> indices</span></pre>

<h3>
	الوصول Access
</h3>

<p>
	بمجرد الانتهاء من عملية الإنشاء، لا بد من إجراء قليل من الحسابات في كل التوابع وتغيير مفتاح key مختلف عند الحصول على عنصر أو إدراجه أو ضبطه. إليك تعليمات تابع <code>__getitem__</code>، وهو تابع سهل ولكن هناك خطوة سلبية محتملة فيه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_19" style="">
<span class="kwd">def</span><span class="pln"> __getitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">key</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> int</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> key </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            key </span><span class="pun">+=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> key </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> key </span><span class="pun">&gt;=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">IndexError</span><span class="pun">(</span><span class="str">"Tuple index out of range"</span><span class="pun">)</span><span class="pln">
        dstart </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="pln">key</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
        dstop  </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="pln">key</span><span class="pun">][</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_data</span><span class="pun">[</span><span class="pln">dstart</span><span class="pun">:</span><span class="pln">dstop</span><span class="pun">]</span><span class="pln">

    </span><span class="kwd">elif</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">key</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> slice</span><span class="pun">:</span><span class="pln">
        istart</span><span class="pun">,</span><span class="pln"> istop</span><span class="pun">,</span><span class="pln"> step </span><span class="pun">=</span><span class="pln"> key</span><span class="pun">.</span><span class="pln">indices</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">self</span><span class="pun">))</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> istart </span><span class="pun">&gt;</span><span class="pln"> istop</span><span class="pun">:</span><span class="pln">
            istart</span><span class="pun">,</span><span class="pln">istop </span><span class="pun">=</span><span class="pln"> istop</span><span class="pun">,</span><span class="pln">istart
        dstart </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="pln">istart</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> istart </span><span class="pun">==</span><span class="pln"> istop</span><span class="pun">:</span><span class="pln">
            dstop </span><span class="pun">=</span><span class="pln"> dstart
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            dstop  </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_items</span><span class="pun">[</span><span class="pln">istop</span><span class="pun">-</span><span class="lit">1</span><span class="pun">][</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_data</span><span class="pun">[</span><span class="pln">dstart</span><span class="pun">:</span><span class="pln">dstop</span><span class="pun">]</span><span class="pln">

    </span><span class="kwd">elif</span><span class="pln"> isinstance</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln">str</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_data</span><span class="pun">[</span><span class="pln">key</span><span class="pun">][:</span><span class="pln">self</span><span class="pun">.</span><span class="pln">_size</span><span class="pun">]</span><span class="pln">

    </span><span class="kwd">elif</span><span class="pln"> key </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Ellipsis</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">data

    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">TypeError</span><span class="pun">(</span><span class="str">"List indices must be integers"</span><span class="pun">)</span></pre>

<h4>
	تمرين
</h4>

<p>
	يُعد تعديل القائمة أكثر تعقيدًا، لأنه يتطلب إدارة الذاكرة بطريقة صحيحة، وبما أن ذلك لا يمثل صعوبة حقيقة، فقد تركنا هذا تمرينًا لك. في حال احتجت إلى مساعدة، يمكنك إلقاء نظرة على التعليمات البرمجية أدناه. كن حذرًا مع الخطوات السلبية ونطاق المفتاح وتوسع المصفوفة. عندما تحتاج المصفوفة الأساسية إلى التوسيع، فمن الأفضل توسيعها أكثر من اللازم لتجنب الحاجة إلى التوسع المستقبلي.
</p>

<h3>
	ضبط عنصر Setitem
</h3>

<p>
	يمكننا ضبط عنصر كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_21" style="">
<span class="pln">L </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">([[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]])</span><span class="pln">
L</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113757" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398599d6a800_02_.png.7027c85c06d99860d9286371c6181022.png" rel=""><img alt="ضبط عنصر Setitem" class="ipsImage ipsImage_thumbnailed" data-fileid="113757" data-unique="hq41r2kre" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398599ecf427_02_.thumb.png.62b11717c6bd43608f5bd567441d576c.png" style="width: 500px; height: auto;"></a>
</p>

<h3>
	حذف عنصر Delitem
</h3>

<p>
	يجري حذف عنصر على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_25" style="">
<span class="pln">L </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">([[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]])</span><span class="pln">
</span><span class="kwd">del</span><span class="pln"> L</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113758" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398599fa66ca_03_.png.39da81a02ba821b64f126f433b278eeb.png" rel=""><img alt="حذف عنصر Delitem" class="ipsImage ipsImage_thumbnailed" data-fileid="113758" data-unique="vmlmfpls8" src="https://academy.hsoub.com/uploads/monthly_2022_12/639859a14dbdd_03_.thumb.png.126a63950f36618668c59f55f7cfeda4.png" style="width: 500px; height: auto;"></a>
</p>

<h3>
	إدراج عنصر insert
</h3>

<p>
	يمكننا إضافة عنصر كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_30" style="">
<span class="pln">L </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TypedList</span><span class="pun">([[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]])</span><span class="pln">
L</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">])</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113759" href="https://academy.hsoub.com/uploads/monthly_2022_12/639859a260842_04.png.fbec955f6cc80839886a18bc32a30440.png" rel=""><img alt="إدراج عنصر insert" class="ipsImage ipsImage_thumbnailed" data-fileid="113759" data-unique="m6uf4h836" src="https://academy.hsoub.com/uploads/monthly_2022_12/639859a39becd_04.thumb.png.b66ad32bb5f6c9695aa8efcb0a1fc271.png" style="width: 500px; height: auto;"></a>
</p>

<h2>
	مصفوفة مراعية للذاكرة Memory aware array
</h2>

<h3>
	مكتبة Glumpy
</h3>

<p>
	<a href="http://glumpy.github.io/" rel="external nofollow">Glumpy</a> هي مكتبة تمثيل مرئي تفاعلي مبنية على OpenGL في بايثون هدفها تسهيل إنشاء عروض مرئية سريعة وقابلة للتطوير وجميلة وتفاعلية وديناميكية. يوضح الشكل التالي محاكاة مجرة حلزونية باستخدام نظرية موجة الكثافة density wave theory:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113760" href="https://academy.hsoub.com/uploads/monthly_2022_12/639859a72502b_05_.png.1e3cb86f328b19f7f846ccf3ce1dc613.png" rel=""><img alt="مكتبة Glumpy" class="ipsImage ipsImage_thumbnailed" data-fileid="113760" data-unique="dscf3c3ru" src="https://academy.hsoub.com/uploads/monthly_2022_12/639859a72502b_05_.png.1e3cb86f328b19f7f846ccf3ce1dc613.png" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	محاكاة مجرة حلزونية باستخدام نظرية موجة الكثافة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113762" href="https://academy.hsoub.com/uploads/monthly_2022_12/Tiger.png.a25b64e457e2360f304ae6a3f66ead33.png" rel=""><img alt="عرض لنمر باستخدام التجميعات واستدعائين GL." class="ipsImage ipsImage_thumbnailed" data-fileid="113762" data-unique="dufcs96gv" src="https://academy.hsoub.com/uploads/monthly_2022_12/Tiger.png.a25b64e457e2360f304ae6a3f66ead33.png" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	عرض لنمر باستخدام التجميعات واستدعائين GL.
</p>

<p>
	تعتمد Glumpy على تكامل محكم وسلس مع المصفوفات المعقدة، وهذا يعني أنه يمكنك معالجة بيانات وحدة معالجة الرسومات GPU كما تفعل مع مصفوفات numpy العادية، وستتولى مكتبة Glumpy بقية المهام، وأسرع طريقة لفهم ذلك هي بالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_38" style="">
<span class="kwd">from</span><span class="pln"> glumpy </span><span class="kwd">import</span><span class="pln"> gloo

dtype </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[(</span><span class="str">"position"</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln">  </span><span class="com"># x,y</span><span class="pln">
         </span><span class="pun">(</span><span class="str">"color"</span><span class="pun">,</span><span class="pln">    np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)]</span><span class="pln">  </span><span class="com"># r,g,b</span><span class="pln">
V </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">),</span><span class="pln">dtype</span><span class="pun">).</span><span class="pln">view</span><span class="pun">(</span><span class="pln">gloo</span><span class="pun">.</span><span class="typ">VertexBuffer</span><span class="pun">)</span><span class="pln">
V</span><span class="pun">[</span><span class="str">"position"</span><span class="pun">][</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.0</span><span class="pln">
V</span><span class="pun">[</span><span class="str">"position"</span><span class="pun">][</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.0</span></pre>

<p>
	<code>V</code> هو <code>VertexBuffer</code> وهو يمثّل GPUData ومصفوفة numpy. عندما يُعدل <code>V</code>، تعتني Glumpy بحساب أصغر كتلة متجاورة من ذاكرة dirty حتى تحميلها على ذاكرة GPU. عندما يُستخدم هذا المخزن المؤقت على وحدة معالجة الرسومات GPU، تتولى Glumpy تحميل منطقة dirty في اللحظات الأخيرة، وهذا يعني أنه في حال عدم استخدامك <code>V</code> فلن يُحمّل أي شيء على وحدة معالجة الرسومات. في الحالة المذكورة أعلاه، تتكون آخر منطقة ذاكرة dirty محسوبة من 88 بايت بدءًا من الإزاحة 0 كما هو موضح أدناه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113761" href="https://academy.hsoub.com/uploads/monthly_2022_12/06dirty.png.779305e10f426d2b7b78bf33b65684a7.png" rel=""><img alt="عمل Glumpy" class="ipsImage ipsImage_thumbnailed" data-fileid="113761" data-unique="3nzw64s1n" src="https://academy.hsoub.com/uploads/monthly_2022_12/06dirty.thumb.png.c92ff377be9041601cdff79ac2022857.png" style="width: 600px; height: auto;"></a>
</p>

<p>
	وبالتالي سينتهي الأمر بتحميل Glumpy 88 بايت بينما عُدّل 16 بايت فقط فعليًا. قد تتساءل عما إذا كان هذا هو الأمثل. في الواقع يكون الأمر كذلك في معظم الأوقات، لأن تحميل بعض البيانات إلى مخزن مؤقت يتطلب الكثير من العمليات على جانب GL ولكل استدعاء تكلفة ثابتة.
</p>

<h2>
	صنف فرعي من Array
</h2>

<p>
	كما هو موضح في <a href="https://docs.scipy.org/doc/numpy/user/basics.subclassing.html" rel="external nofollow">توثيق Subclassing ndarray</a>، فإن التصنيف الفرعي ndarray معقد بسبب حقيقة أن الحالات الجديدة لأصناف ndarray يمكن أن تظهر بثلاث طرق مختلفة:
</p>

<ul>
<li>
		استدعاء صريح للباني.
	</li>
	<li>
		تحويل العرض view casting.
	</li>
	<li>
		قالب جديد.
	</li>
</ul>
<p>
	ومع ذلك فإن حالتنا أبسط لأننا مهتمون فقط بتحويل العرض، لذلك نحتاج فقط إلى تعريف التابع <code>__new__</code> الذي سيُستدعى عند إنشاء كل نسخة. لذلك ستجهز صنف <code>GPUData</code> بخاصيتين:
</p>

<ul>
<li>
		النطاقات <code>extents</code>: يمثل هذا النطاق الكامل للعرض نسبيًا بالنسبة للمصفوفة الأساسية، ويُخزّن مثل إزاحة بايت وحجم بايت.
	</li>
	<li>
		البيانات المنتظرة <code>pending_data</code>: يمثل هذا تجاور لمنطقة dirty ويُخزّن مثل (إزاحة البايت، حجم البايت) نسبيًا بالنسبة إلى خاصية <code>extents</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_42" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">GPUData</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">ndarray</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __new__</span><span class="pun">(</span><span class="pln">cls</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">args</span><span class="pun">,</span><span class="pln"> </span><span class="pun">**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ndarray</span><span class="pun">.</span><span class="pln">__new__</span><span class="pun">(</span><span class="pln">cls</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">args</span><span class="pun">,</span><span class="pln"> </span><span class="pun">**</span><span class="pln">kwargs</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">args</span><span class="pun">,</span><span class="pln"> </span><span class="pun">**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">pass</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __array_finalize__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> obj</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> isinstance</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">,</span><span class="pln"> </span><span class="typ">GPUData</span><span class="pun">):</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">_extents </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">size</span><span class="pun">*</span><span class="pln">self</span><span class="pun">.</span><span class="pln">itemsize
            self</span><span class="pun">.</span><span class="pln">__class__</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">_pending_data </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_extents
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">_extents </span><span class="pun">=</span><span class="pln"> obj</span><span class="pun">.</span><span class="pln">_extents</span></pre>

<h3>
	نطاقات الحوسبة
</h3>

<p>
	نحتاج في كل مرة يُطلب فيها عرض جزئي للمصفوفة إلى حساب نطاقات هذا العرض الجزئي حتى نتمكن من الوصول إلى المصفوفة الأساسية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_44" style="">
<span class="kwd">def</span><span class="pln"> __getitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">):</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ndarray</span><span class="pun">.</span><span class="pln">__getitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> hasattr</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">,</span><span class="str">'shape'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">shape </span><span class="pun">==</span><span class="pln"> </span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> Z
    Z</span><span class="pun">.</span><span class="pln">_extents </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_compute_extents</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z

</span><span class="kwd">def</span><span class="pln"> _compute_extents</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> Z</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">:</span><span class="pln">
        base </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">base</span><span class="pun">.</span><span class="pln">__array_interface__</span><span class="pun">[</span><span class="str">'data'</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
        view </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">__array_interface__</span><span class="pun">[</span><span class="str">'data'</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
        offset </span><span class="pun">=</span><span class="pln"> view </span><span class="pun">-</span><span class="pln"> base
        shape </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
        strides </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">)</span><span class="pln">
        size </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">shape</span><span class="pun">*</span><span class="pln">strides</span><span class="pun">).</span><span class="pln">sum</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">itemsize
        </span><span class="kwd">return</span><span class="pln"> offset</span><span class="pun">,</span><span class="pln"> offset</span><span class="pun">+</span><span class="pln">size
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">size</span><span class="pun">*</span><span class="pln">self</span><span class="pun">.</span><span class="pln">itemsize</span></pre>

<h3>
	تعقب البيانات المنتظرة pending data باستمرار
</h3>

<p>
	تتمثل إحدى الصعوبات الإضافية في أننا لا نريد أن تتعقب جميع طرق العرض منطقة dirty المُستخدمة ولكن نريد تعقب فقط المصفوفة الأساسية. هذا هو سبب عدم إنشاء نسخة من<code>self._pending_data</code> في الحالة الثانية من تابع <code>__array_finalize__</code>. سنتعامل مع هذا عندما نحتاج إلى تحديث بعض البيانات أثناء استدعاء <code>__setitem__</code> على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9451_46" style="">
<span class="kwd">def</span><span class="pln"> __setitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">):</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ndarray</span><span class="pun">.</span><span class="pln">__getitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">shape </span><span class="pun">==</span><span class="pln"> </span><span class="pun">():</span><span class="pln">
        key </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">mod</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="pln">key</span><span class="pun">)+</span><span class="pln">self</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">)</span><span class="pln">
        offset </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_extents</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]+(</span><span class="pln">key </span><span class="pun">*</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">).</span><span class="pln">sum</span><span class="pun">()</span><span class="pln">
        size </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">itemsize
        self</span><span class="pun">.</span><span class="pln">_add_pending_data</span><span class="pun">(</span><span class="pln">offset</span><span class="pun">,</span><span class="pln"> offset</span><span class="pun">+</span><span class="pln">size</span><span class="pun">)</span><span class="pln">
        key </span><span class="pun">=</span><span class="pln"> tuple</span><span class="pun">(</span><span class="pln">key</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        Z</span><span class="pun">.</span><span class="pln">_extents </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_compute_extents</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">_add_pending_data</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">_extents</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">_extents</span><span class="pun">[</span><span class="lit">1</span><span class="pun">])</span><span class="pln">
    np</span><span class="pun">.</span><span class="pln">ndarray</span><span class="pun">.</span><span class="pln">__setitem__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> _add_pending_data</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> stop</span><span class="pun">):</span><span class="pln">
    base </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">base
    </span><span class="kwd">if</span><span class="pln"> isinstance</span><span class="pun">(</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> </span><span class="typ">GPUData</span><span class="pun">):</span><span class="pln">
        base</span><span class="pun">.</span><span class="pln">_add_pending_data</span><span class="pun">(</span><span class="pln">start</span><span class="pun">,</span><span class="pln"> stop</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_pending_data </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">_pending_data </span><span class="pun">=</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> stop
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            start </span><span class="pun">=</span><span class="pln"> min</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">_pending_data</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> start</span><span class="pun">)</span><span class="pln">
            stop </span><span class="pun">=</span><span class="pln"> max</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">_pending_data</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> stop</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">_pending_data </span><span class="pun">=</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> stop</span></pre>

<h2>
	الخلاصة
</h2>

<p>
	كما هو موضح على موقع ويب NumPy، فإن مكتبة NumPy هي الحزمة الأساسية للحوسبة العلمية باستخدام بايثون، ولكن وكما هو موضح في هذا المقال يتجاوز استخدام نقاط قوة NumPy مجرد حاوية متعددة الأبعاد multi-dimensional container للبيانات العامة.
</p>

<p>
	يمكن استخدام ndarray مثل خاصية خاصة في حالة واحدة (أسلوب TypedList)، أو تصنيفًا فرعيًا مباشرًا لصنف <code>ndarray</code> (أسلوب GPUData) لتتبع الذاكرة في حالات أخرى، وقد وضحنا كيف يمكن أن تتوسع قدرات NumPy لتناسب احتياجات محددة للغاية.
</p>

<p>
	ترجمة -وبتصرّف- للفصل <a href="https://www.labri.fr/perso/nrougier/from-python-to-numpy/#custom-vectorization" rel="external nofollow">Custom vectorization</a> من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AD%D9%84-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D9%83%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1820/" rel="">الاعتماد على المتجهات في حل المشاكل باستعمال مكتبة NumPy في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-vectorization-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1819/" rel="">استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1821</guid><pubDate>Tue, 13 Dec 2022 11:21:57 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x639;&#x62A;&#x645;&#x627;&#x62F; &#x639;&#x644;&#x649; &#x627;&#x644;&#x645;&#x62A;&#x62C;&#x647;&#x627;&#x62A; &#x641;&#x64A; &#x62D;&#x644; &#x627;&#x644;&#x645;&#x634;&#x627;&#x643;&#x644; &#x628;&#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x645;&#x643;&#x62A;&#x628;&#x629; NumPy &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AD%D9%84-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D9%83%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1820/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/639852622fc74_-----Python--NumPy2.png.82e9742d8d5c613c71d9c14689db0648.png" /></p>

<p>
	يعد الاعتماد على المتجهات في المشاكل أصعب بكثير من متجهات الشيفرات لأنه يعني أنه يتعين عليك إعادة التفكير في مشكلتك من أجل جعلها معتمدة على المتجهات vectorizable، وهذا يعني غالبًا أن عليك استخدام خوارزمية مختلفة لحل مشكلتك، أو حتى الأسوأ من ذلك، فقد تحتاج إلى ابتكار خوارزمية جديدة. وبالتالي تكمن الصعوبة في التفكير خارج الصندوق.
</p>

<p>
	لتوضيح ذلك دعنا نفكر في مشكلة بسيطة، ولنفرض لدينا متجهين <code>X</code> و <code>Y</code>، ونريد حساب مجموع <code>[X * Y [j</code> لجميع أزواج المؤشرات <code>i</code> و <code>j</code>. أحد الحلول البسيطة والواضحة هو كتابة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_6" style="">
<span class="kwd">def</span><span class="pln"> compute_python</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">):</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">X</span><span class="pun">)):</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">)):</span><span class="pln">
            result </span><span class="pun">+=</span><span class="pln"> X</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> Y</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span></pre>

<p>
	ولكن تتضمن الشيفرات السابقة حلقتين وبالتالي فإن التنفيذ سيكون بطيئًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_8" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"compute_python(X,X)"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.274481</span><span class="pln"> sec per loop</span></pre>

<p>
	كيف يمكن جعل المشكلة معتمدة على المتجهات إذًا؟ إذا كنت تتذكر مقرر الجبر الخطي، فربما تكون قد حددت التعبير <code>[X * Y [j</code> ليكون مشابهًا جدًا لتعبير المصفوفة، لذلك ربما يمكننا الاستفادة من سرعة NumPy. أحد الحلول الخاطئة هو بكتابة:
</p>

<pre class="ipsCode">
def compute_numpy_wrong(X, Y):
    return (X*Y).sum()
</pre>

<p>
	هذا الحل خاطئ لأن التعبير <code>X * Y</code> يحسب في الواقع متجهًا جديدًا <code>Z</code> وفقًا لما يلي: <code>[Z = X * Y [i</code>، وليس هذا ما نريده، لذلك سنجرب استغلال ميزة البث broadcasting لمكتبة NumPy وإعادة تشكيل المتجهين أولًا ثم ضربهما:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_10" style="">
<span class="kwd">def</span><span class="pln"> compute_numpy</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">):</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> X</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">X</span><span class="pun">),</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> Y</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln">len</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">))</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">()</span></pre>

<p>
	أصبح لدينا <code>[Z[i,j] == X[i,0]*Y[0,j</code>، وإذا حسبنا مجموع كل عناصر <code>Z</code>، سنحصل على النتيجة المتوقعة. سنتأكد الآن من مقدار التحسن في السرعة الذي اكتسبناه في هذه الطريقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_12" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"compute_numpy(X,X)"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">10</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.00157926</span><span class="pln"> sec per loop</span></pre>

<p>
	هذا أفضل، فقد حصلنا على عامل سرعة أكبر بحوالي 150 مرة، ولكن لا يزال بإمكاننا تحسين هذا العامل.
</p>

<p>
	بالعودة إلى الطريقة الأولى، يمكنك أن تلاحظ أن الحلقة الداخلية تستخدم <code>[X [i</code> الذي لا يعتمد على المؤشر <code>j</code>، مما يعني أنه يمكن إزالته من الحلقة الداخلية. يمكن إعادة كتابة الشيفرة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_14" style="">
<span class="kwd">def</span><span class="pln"> compute_numpy_better_1</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">):</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">X</span><span class="pun">)):</span><span class="pln">
        </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">)):</span><span class="pln">
            </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> Y</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln">
        result </span><span class="pun">+=</span><span class="pln"> X</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]*</span><span class="typ">Ysum</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span></pre>

<p>
	ونظرًا لأن الحلقة الداخلية لا تعتمد على المؤشر <code>i</code>، فيمكننا أن نحسبها مرةً واحدةً فقط:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_16" style="">
<span class="kwd">def</span><span class="pln"> compute_numpy_better_2</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">):</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">)):</span><span class="pln">
        </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> Y</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">X</span><span class="pun">)):</span><span class="pln">
        result </span><span class="pun">+=</span><span class="pln"> X</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]*</span><span class="typ">Ysum</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span></pre>

<p>
	خفضنا التعقيد بفضل إزالة الحلقة الداخلية من "(O(n<sup>2</sup>" إلى "(O(n". وبنفس الطريقة يمكننا كتابة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_18" style="">
<span class="kwd">def</span><span class="pln"> compute_numpy_better_3</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">)):</span><span class="pln">
        </span><span class="typ">Ysum</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> Y</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln">
    </span><span class="typ">Xsum</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">X</span><span class="pun">)):</span><span class="pln">
        </span><span class="typ">Xsum</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> X</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Xsum</span><span class="pun">*</span><span class="typ">Ysum</span></pre>

<p>
	أخيرًا، بعد أن أدركنا أننا نحتاج فقط إلى حاصل ضرب المجموع لكلٍ من <code>X</code> و <code>Y</code> على التوالي، يمكننا الاستفادة من دالة <code>np.sum</code> وكتابة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_20" style="">
<span class="kwd">def</span><span class="pln"> compute_numpy_better</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span></pre>

<p>
	وبالتالي حصلنا على شيفرات برمجية أقصر وأرتب وأسرع:
</p>

<pre class="ipsCode">
&gt;&gt;&gt; X = np.arange(1000)
&gt;&gt;&gt; timeit("compute_numpy_better(X,X)")
1000 loops, best of 3: 3.97208e-06 sec per loop
</pre>

<p>
	بهذه الطريقة نكون قد أعدنا صياغة المشكلة، مستغلين حقيقة أن: "‎∑<sub>ij</sub> X<sub>i</sub>Y<sub>j</sub> = ∑<sub>i</sub>X<sub>i</sub>∑<sub>j</sub>Y<sub>j</sub>".
</p>

<p>
	وتعلمنا الآن أن هناك نوعين من التحويل المعتمد على المتجهات، وهما: متجهات الشيفرات ومتجهات المشكلة. يُعد النوع الثاني من المتجهات هو الأصعب والأكثر أهمية لأنك من خلاله يمكنك توقع مكاسب هائلة في تحسين السرعة. اكتسبنا في هذا المثال البسيط عامل سرعة أكبر بمقدار 150 مرة عند استخدام متجهات الشيفرة، واكتسبنا عامل قدره 70000 باستخدام متجهات المشكلة، أي من خلال كتابة مشكلتنا بطريقة مختلفة فقط.
</p>

<p>
	إذا أعدنا كتابة الحل الأخير بطريقة <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> فإن التحسين سيكون جيدًا ولكن ليس مثل استخدام numpy:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_22" style="">
<span class="kwd">def</span><span class="pln"> compute_python_better</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)*</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">y</span><span class="pun">)</span></pre>

<p>
	هذا الإصدار الجديد من بايثون أسرع بكثير من إصدار بايثون السابق، لكنه لا يزال أبطأ 50 مرةً من الإصدار numpy:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_25" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"compute_python_better(X,X)"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.000155677</span><span class="pln"> sec per loop</span></pre>

<h2>
	إيجاد المسار
</h2>

<p>
	يتعلق اكتشاف المسار بإيجاد أقصر مسار في الرسم البياني. يمكن تقسيم هذا إلى مشكلتين مختلفتين: العثور على مسار بين كل عقدتين في الرسم البياني والعثور على أقصر مسار، وسنوضح ذلك من خلال اكتشاف المسار في متاهة، لذلك ستكون المهمة الأولى هي بناء المتاهة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113748" href="https://academy.hsoub.com/uploads/monthly_2022_12/Longleat-maze-cropped.jpg.577058e9df3a5620443ac70ecfd8ce71.jpg" rel=""><img alt="متاهة سياج أخضر تحيط بمنزل Longleat الفخم في إنجلترا" class="ipsImage ipsImage_thumbnailed" data-fileid="113748" data-unique="236h02fcg" src="https://academy.hsoub.com/uploads/monthly_2022_12/Longleat-maze-cropped.thumb.jpg.8273b418df05fbcad9e71408b4ddfc1f.jpg" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	متاهة سياج أخضر تحيط بمنزل Longleat الفخم في إنجلترا. صورة <a href="https://commons.wikimedia.org/wiki/File:Longleat_maze.jpg" rel="external nofollow">Prince Rurik</a>، 2005.
</p>

<h3>
	بناء متاهة
</h3>

<p>
	توجد عدة <a href="https://wiki.hsoub.com/Algorithms" rel="external">خوارزميات</a> لإنشاء متاهة، لكننا سنستخدم هنا خوارزمية معينة تعمل عن طريق إنشاء "n" (الكثافة) جزيرة بطول "p" (التعقيد). تنشأ الجزيرة من خلال اختيار نقطة بداية عشوائية بإحداثيات فردية، ثم نختار اتجاهًا عشوائيًا.
</p>

<p>
	إذا كانت الخلية التي تملك خطوتين في اتجاه معين حرة سيُضاف جدار في أول وثاني خطوة في هذا الاتجاه، وتُكرر العملية n خطوة لهذه الجزيرة، وبالتالي ننشيء p جزيرة. يكون كل من <code>n</code> و <code>p</code> أعداد عشرية float لتتكيف مع حجم المتاهة. تكون الجزر صغيرة جدًا مع هذا التعقيد المنخفض ويكون حل المتاهة سهلًا، وتحتوي المتاهة على مزيدٍ من "الغرف الفارغة الكبيرة" مع الكثافة المنخفضة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_29" style="">
<span class="kwd">def</span><span class="pln"> build_maze</span><span class="pun">(</span><span class="pln">shape</span><span class="pun">=(</span><span class="lit">65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">65</span><span class="pun">),</span><span class="pln"> complexity</span><span class="pun">=</span><span class="lit">0.75</span><span class="pun">,</span><span class="pln"> density</span><span class="pun">=</span><span class="lit">0.50</span><span class="pun">):</span><span class="pln">
    </span><span class="com"># Only odd shapes</span><span class="pln">
    shape </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]//</span><span class="lit">2</span><span class="pun">)*</span><span class="lit">2</span><span class="pun">+</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]//</span><span class="lit">2</span><span class="pun">)*</span><span class="lit">2</span><span class="pun">+</span><span class="lit">1</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># ضبط التعقيد والكثافة نسبةً إلى حجم المتاهة</span><span class="pln">
    n_complexity </span><span class="pun">=</span><span class="pln"> int</span><span class="pun">(</span><span class="pln">complexity</span><span class="pun">*(</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]+</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]))</span><span class="pln">
    n_density </span><span class="pun">=</span><span class="pln"> int</span><span class="pun">(</span><span class="pln">density</span><span class="pun">*(</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]*</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]))</span><span class="pln">

    </span><span class="com"># بناء المتاهة الفعلية</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">bool</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># ملء الحدود</span><span class="pln">
    Z</span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="pun">:]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">:]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

    </span><span class="com"># تبدأ الجزر بنقطة مع انحياز من طرف الحدود</span><span class="pln">
    P </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">normal</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n_density</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">))</span><span class="pln">
    P </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.5</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(-</span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">minimum</span><span class="pun">(</span><span class="pln">P</span><span class="pun">,</span><span class="pln"> </span><span class="pun">+</span><span class="lit">0.5</span><span class="pun">))</span><span class="pln">
    P </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">P</span><span class="pun">*[</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]]).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
    P </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*(</span><span class="pln">P</span><span class="pun">//</span><span class="lit">2</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># إنشاء الجزر</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">n_density</span><span class="pun">):</span><span class="pln">
        </span><span class="com"># Test for early stop: if all starting point are busy, this means we</span><span class="pln">
        </span><span class="com"># won't be able to connect any island, so we stop.</span><span class="pln">
        T </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:-</span><span class="lit">2</span><span class="pun">:</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:-</span><span class="lit">2</span><span class="pun">:</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> T</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> T</span><span class="pun">.</span><span class="pln">size</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">break</span><span class="pln">
        x</span><span class="pun">,</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> P</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
        Z</span><span class="pun">[</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">n_complexity</span><span class="pun">):</span><span class="pln">
            neighbours </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> x </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">          neighbours</span><span class="pun">.</span><span class="pln">append</span><span class="pun">([(</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">-</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">-</span><span class="lit">2</span><span class="pun">)])</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> neighbours</span><span class="pun">.</span><span class="pln">append</span><span class="pun">([(</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">+</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">+</span><span class="lit">2</span><span class="pun">)])</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> y </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">          neighbours</span><span class="pun">.</span><span class="pln">append</span><span class="pun">([(</span><span class="pln">y</span><span class="pun">-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y</span><span class="pun">-</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">)])</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> y </span><span class="pun">&lt;</span><span class="pln"> shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> neighbours</span><span class="pun">.</span><span class="pln">append</span><span class="pun">([(</span><span class="pln">y</span><span class="pun">+</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y</span><span class="pun">+</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">)])</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">neighbours</span><span class="pun">):</span><span class="pln">
                choice </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">neighbours</span><span class="pun">))</span><span class="pln">
                next_1</span><span class="pun">,</span><span class="pln"> next_2 </span><span class="pun">=</span><span class="pln"> neighbours</span><span class="pun">[</span><span class="pln">choice</span><span class="pun">]</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">next_2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
                    Z</span><span class="pun">[</span><span class="pln">next_1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                    Z</span><span class="pun">[</span><span class="pln">next_2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                    y</span><span class="pun">,</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> next_2
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">break</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z</span></pre>

<p>
	هنا رسم متحرك يوضح عملية التوليد.
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409728?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	بناء متاهة متدرجة مع التحكم في التعقيد والكثافة.
</p>

<h3>
	خوارزمية الاتساع أولا Breadth-first
</h3>

<p>
	تعالج خوارزمية البحث ذات الاتساع أولًا Breadth-first (وكذلك خوارزمية العمق أولًا depth-first) مشكلة إيجاد مسار بين عقدتين من خلال فحص جميع الاحتمالات بدءًا من عقدة الجذر والتوقف بمجرد العثور على حل (الوصول إلى العقدة الوجهة). تعمل هذه الخوارزمية في الوقت الخطي بالتعقيد <code>(|O(|V| + |E</code>، إذ يمثل <code>V</code> عدد الرؤوس vertices و <code>E</code> هو عدد الحواف. كتابة مثل هذه الخوارزمية ليس صعبًا بشرط أن يكون لديك بنية البيانات الصحيحة. في حالتنا فإن تمثيل المتاهة على شكل مصفوفة ليس هو الحل الأنسب، ونحتاج إلى تحويله إلى رسم بياني حقيقي وفق اقتراح <a href="http://bryukh.com/" rel="external nofollow">فالنتين بريوخانوف Valentin Bryukhanov</a>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_33" style="">
<span class="kwd">def</span><span class="pln"> build_graph</span><span class="pun">(</span><span class="pln">maze</span><span class="pun">):</span><span class="pln">
    height</span><span class="pun">,</span><span class="pln"> width </span><span class="pun">=</span><span class="pln"> maze</span><span class="pun">.</span><span class="pln">shape
    graph </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">):</span><span class="pln"> </span><span class="pun">[]</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">width</span><span class="pun">)</span><span class="pln">
                        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">height</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> maze</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="pln">j</span><span class="pun">]}</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> row</span><span class="pun">,</span><span class="pln"> col </span><span class="kwd">in</span><span class="pln"> graph</span><span class="pun">.</span><span class="pln">keys</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> row </span><span class="pun">&lt;</span><span class="pln"> height </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> maze</span><span class="pun">[</span><span class="pln">row </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">][</span><span class="pln">col</span><span class="pun">]:</span><span class="pln">
            graph</span><span class="pun">[(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)].</span><span class="pln">append</span><span class="pun">((</span><span class="str">"S"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">row </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)))</span><span class="pln">
            graph</span><span class="pun">[(</span><span class="pln">row </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)].</span><span class="pln">append</span><span class="pun">((</span><span class="str">"N"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)))</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> col </span><span class="pun">&lt;</span><span class="pln"> width </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> maze</span><span class="pun">[</span><span class="pln">row</span><span class="pun">][</span><span class="pln">col </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]:</span><span class="pln">
            graph</span><span class="pun">[(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)].</span><span class="pln">append</span><span class="pun">((</span><span class="str">"E"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)))</span><span class="pln">
            graph</span><span class="pun">[(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)].</span><span class="pln">append</span><span class="pun">((</span><span class="str">"W"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> col</span><span class="pun">)))</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> graph</span></pre>

<p>
	<strong>ملاحظة:</strong> إذا استخدمنا خوارزمية العمق أولاً فلا يوجد ضمان للعثور على أقصر مسار، ويمكننا فقط للعثور على مسار إذا كان موجودًا.
</p>

<p>
	بعد الانتهاء من ذلك، تكون كتابة خوارزمية الاتساع أولًا أمرًا سهلًا. نبدأ من عقدة البداية ونزور العقد في العمق الحالي ونكرر العملية حتى الوصول إلى العقدة النهائية إن أمكن. والسؤال هنا: هل نحصل بهذه الطريقة على أقصر طريق لاستكشاف الرسم البياني؟ في هذه الحالة المحددة "نعم"، لأننا لا نملك رسمًا بيانيًا مرجحًا للحافة، أي أن جميع الحواف لها نفس الوزن (أو التكلفة).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_36" style="">
<span class="kwd">def</span><span class="pln"> breadth_first</span><span class="pun">(</span><span class="pln">maze</span><span class="pun">,</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> goal</span><span class="pun">):</span><span class="pln">
    queue </span><span class="pun">=</span><span class="pln"> deque</span><span class="pun">([([</span><span class="pln">start</span><span class="pun">],</span><span class="pln"> start</span><span class="pun">)])</span><span class="pln">
    visited </span><span class="pun">=</span><span class="pln"> set</span><span class="pun">()</span><span class="pln">
    graph </span><span class="pun">=</span><span class="pln"> build_graph</span><span class="pun">(</span><span class="pln">maze</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">while</span><span class="pln"> queue</span><span class="pun">:</span><span class="pln">
        path</span><span class="pun">,</span><span class="pln"> current </span><span class="pun">=</span><span class="pln"> queue</span><span class="pun">.</span><span class="pln">popleft</span><span class="pun">()</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> current </span><span class="pun">==</span><span class="pln"> goal</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="pln">path</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> current </span><span class="kwd">in</span><span class="pln"> visited</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">continue</span><span class="pln">
        visited</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">current</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> direction</span><span class="pun">,</span><span class="pln"> neighbour </span><span class="kwd">in</span><span class="pln"> graph</span><span class="pun">[</span><span class="pln">current</span><span class="pun">]:</span><span class="pln">
            p </span><span class="pun">=</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">path</span><span class="pun">)</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">neighbour</span><span class="pun">)</span><span class="pln">
            queue</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="pln">p</span><span class="pun">,</span><span class="pln"> neighbour</span><span class="pun">))</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">None</span></pre>

<h3>
	طريقة بيلمان فورد Bellman-Ford
</h3>

<p>
	خوارزمية بيلمان فورد Bellman-Ford قادرة على إيجاد المسار الأمثل في الرسم البياني باستخدام عملية الانتشار، إذ تعثر على المسار الأفضل عن طريق تصاعد التدرج الناتج. تعمل هذه الخوارزمية في الوقت التربيعي <code>(|O(|V||E</code>، إذ يمثّل <code>V</code> عدد الرؤوس و <code>E</code> عدد الحواف. في حالتنا البسيطة لن نواجه الكثير من المشاكل. الخوارزمية موضحة أدناه في الشكل (القراءة من اليسار إلى اليمين ومن أعلى إلى أسفل). بعد فهم الخوارزمية يمكننا صعود التدرج اللوني من عقدة البداية، ويمكنك التحقق من الشكل الذي يؤدي إلى أقصر طريق.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113745" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398525dbdad2_02Bellman-Ford.png.7d65e77202c79c3ba98ac1f57a6ed2a0.png" rel=""><img alt="طريقة بيلمان فورد Bellman-Ford" class="ipsImage ipsImage_thumbnailed" data-fileid="113745" data-unique="guaw2azkl" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398525e76866_02Bellman-Ford.thumb.png.2681c002f571a56e36f3c947956486fc.png" style="width: 780px; height: auto;"></a>
</p>

<p>
	قيم خوارزمية التكرار في متاهة بسيطة. بمجرد الوصول إلى المدخل، يكون من السهل العثور على أقصر طريق عن طريق صعود تدرج القيمة.
</p>

<p>
	نبدأ بتعيين عقدة الخروج على القيمة 1، بينما تُعيّن كل عقدة أخرى بالقيمة 0 باستثناء الجدران، ثم نكرر العملية بحيث تحسب القيمة الجديدة لكل خلية على أنها القيمة القصوى بين قيمة الخلية الحالية وقيم الخلايا الأربعة المُخفّضة المتجاورة (gamma=0.9 في الحالة أدناه). تبدأ العملية بمجرد أن تصبح قيمة عقدة البداية موجبة تمامًا.
</p>

<p>
	يُعد التنفيذ باستخدام NumPy أبسط إذا استفدنا من ميزات عامل الترشيح العام generic_filter (من scipy.ndimage) لعملية الانتشار:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_39" style="">
<span class="kwd">def</span><span class="pln"> diffuse</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">):</span><span class="pln">
    </span><span class="com"># North, West, Center, East, South</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> max</span><span class="pun">(</span><span class="pln">gamma</span><span class="pun">*</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> gamma</span><span class="pun">*</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> gamma</span><span class="pun">*</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">3</span><span class="pun">],</span><span class="pln"> gamma</span><span class="pun">*</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">4</span><span class="pun">])</span><span class="pln">

</span><span class="com"># Build gradient array</span><span class="pln">
G </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">)</span><span class="pln">

</span><span class="com"># Initialize gradient at the entrance with value 1</span><span class="pln">
G</span><span class="pun">[</span><span class="pln">start</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># Discount factor</span><span class="pln">
gamma </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.99</span><span class="pln">

</span><span class="com"># We iterate until value at exit is &gt; 0. This requires the maze</span><span class="pln">
</span><span class="com"># to have a solution or it will be stuck in the loop.</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> G</span><span class="pun">[</span><span class="pln">goal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">:</span><span class="pln">
    G </span><span class="pun">=</span><span class="pln"> Z </span><span class="pun">*</span><span class="pln"> generic_filter</span><span class="pun">(</span><span class="pln">G</span><span class="pun">,</span><span class="pln"> diffuse</span><span class="pun">,</span><span class="pln"> footprint</span><span class="pun">=[[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">],</span><span class="pln">
                                                  </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">],</span><span class="pln">
                                                  </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]])</span><span class="pln"> </span></pre>

<p>
	لكن في هذه الحالة بالتحديد يكون الأمر بطيئًا إلى حد ما، ومن الأفضل إعداد حلنا الخاص، وإعادة استخدام جزء من تشفير لعبة الحياة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_41" style="">
<span class="com"># Build gradient array</span><span class="pln">
G </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">)</span><span class="pln">

</span><span class="com"># Initialize gradient at the entrance with value 1</span><span class="pln">
G</span><span class="pun">[</span><span class="pln">start</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># Discount factor</span><span class="pln">
gamma </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.99</span><span class="pln">

</span><span class="com"># We iterate until value at exit is &gt; 0. This requires the maze</span><span class="pln">
</span><span class="com"># to have a solution or it will be stuck in the loop.</span><span class="pln">
G_gamma </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">empty_like</span><span class="pun">(</span><span class="pln">G</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> G</span><span class="pun">[</span><span class="pln">goal</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">:</span><span class="pln">
    np</span><span class="pun">.</span><span class="pln">multiply</span><span class="pun">(</span><span class="pln">G</span><span class="pun">,</span><span class="pln"> gamma</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">G_gamma</span><span class="pun">)</span><span class="pln">
    N </span><span class="pun">=</span><span class="pln"> G_gamma</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:-</span><span class="lit">2</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
    W </span><span class="pun">=</span><span class="pln"> G_gamma</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">:-</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
    C </span><span class="pun">=</span><span class="pln"> G</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
    E </span><span class="pun">=</span><span class="pln"> G_gamma</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">:]</span><span class="pln">
    S </span><span class="pun">=</span><span class="pln"> G_gamma</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
    G</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]*</span><span class="pln">np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">N</span><span class="pun">,</span><span class="pln">np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">W</span><span class="pun">,</span><span class="pln">
                                np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">C</span><span class="pun">,</span><span class="pln">np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">E</span><span class="pun">,</span><span class="pln">S</span><span class="pun">))))</span></pre>

<p>
	بمجرد الانتهاء من ذلك، يمكننا صعود التدرج للعثور على أقصر طريق كما هو موضح في الشكل أدناه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113746" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398525f68638_03.png.01bda38c4c28afb7976998d70ed49373.png" rel=""><img alt="صعود التدرج للعثور على أقصر طريق في اللعبة" class="ipsImage ipsImage_thumbnailed" data-fileid="113746" data-unique="qjlxpo2yh" src="https://academy.hsoub.com/uploads/monthly_2022_12/639852604d403_03.thumb.png.372c4d84999ef3562bc1bb50153c7ab0.png" style="width: 650px; height: auto;"></a>
</p>

<p>
	إيجاد المسار باستخدام خوارزمية بيلمان-فورد. تشير الألوان المتدرجة إلى القيم المنتشرة من نقطة نهاية المتاهة (أسفل اليمين). عُثر على المسار من خلال التدرج التصاعدي من الهدف.
</p>

<h2>
	خوارزمية تدفقات السوائل Fluid Dynamics
</h2>

<p>
	فيما يلي سنوضح طريقة عمل خوارزمية تدفقات السوائل، وكيفية تنفيذها برمجيًا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113749" href="https://academy.hsoub.com/uploads/monthly_2022_12/Self-similar-turbulence.png.437fd57833c7d411be417910daff979a.png" rel=""><img alt="التدفق الهيدروديناميكي بمستويين مختلفين من التقريب" class="ipsImage ipsImage_thumbnailed" data-fileid="113749" data-unique="3iswzg0d3" src="https://academy.hsoub.com/uploads/monthly_2022_12/Self-similar-turbulence.thumb.png.d05797197c364f14e604674b93c3b5d0.png" style="width: 700px; height: auto;"></a>
</p>

<p>
	التدفق الهيدروديناميكي بمستويين مختلفين من التقريب، نهر نيكار، هايدلبرغ، ألمانيا. صورة <a href="https://commons.wikimedia.org/wiki/File:Self_Similar_Turbulence.png" rel="external nofollow">Steven Mathey</a>، 2012.
</p>

<h3>
	طريقة لاغرانج Lagrangian مقابل أويلريان Eulerian
</h3>

<p>
	في نظرية الحقل الكلاسيكية، فإن مواصفات لاغرانج للحقل هي طريقة للنظر إلى حركة السوائل، إذ يتبّع المراقب حركة السائل عبر المكان والزمان، ويعطينا رسم موقع كل جزء عبر الزمن مسار ذلك الجزء، ويمكن تخيل هذا على أنه الجلوس في قارب والانجراف في النهر.
</p>

<p>
	تعد مواصفات أويلريان لحقل التدفق طريقةً للنظر إلى حركة السوائل التي تركز على مواقع محددة في الفضاء الذي يتدفق من خلاله السائل مع مرور الوقت. يمكن تصور ذلك من خلال الجلوس على ضفة النهر ومشاهدة الماء يمر من الموقع الثابت. أي بعبارة أخرى، في حالة أويلريان يُقسم جزءٌ من الفضاء إلى خلايا وتحتوي كل خلية على متجه السرعة ومعلومات أخرى، مثل الكثافة ودرجة الحرارة. نحتاج في حالة لاغرانج إلى فيزياء تعتمد على الجسيمات مع تفاعلات ديناميكية وعمومًا نحتاج إلى عدد كبير من الجسيمات.
</p>

<p>
	لكلتا الطريقتين مزايا وعيوب ويعتمد الاختيار بين الطريقتين على طبيعة مشكلتك، ويمكنك أيضًا مزج الطريقتين في طريقة هجينة. مع ذلك، فإن أكبر مشكلة في المحاكاة القائمة على الجسيمات هي أن تفاعل الجسيمات يتطلب إيجاد الجسيمات المجاورة وهذا له تكلفة كما رأينا في حالة أسراب الطيور Boids في <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-vectorization-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1819/" rel="">المقال السابق</a>. إذا استهدفنا <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>و NumPy فقط، فمن الأفضل اختيار طريقة أويلريان لأن الاعتماد على المتجهات سيكون عديم الأهمية تقريبًا مقارنةً بطريقة لاغرانج.
</p>

<h3>
	كتابة الشيفرة باستخدام مكتبة NumPy
</h3>

<p>
	لن نشرح كل النظرية الكامنة وراء ديناميك السوائل الحسابية لوجود العديد من الموارد عبر الإنترنت التي تشرح هذا بطريقة جيدة. لماذا نختار حسابات السائل إذًا؟ لأن النتائج تكون غالبًا جيدة ورائعة. سنعمل على تبسيط المشكلة أكثر من خلال تنفيذ طريقة من رسوميات الحاسوب بحيث يكون الهدف هو السلوك المقنع.
</p>

<p>
	سنعمل على تبسيط المشكلة أكثر من خلال تنفيذ طريقة من رسوميات الحاسوب، إذ لا يكون الهدف هو التصحيح ولكن السلوك المقنع. كتب جو ستام Jos Stam مقالًا لطيفًا جدًا لصالح SIGGRAPH عام 1999 يصف تقنية الحصول على سوائل مستقرة بمرور الوقت (أي لا يتباعد حلها على المدى الطويل). وكتب <a href="https://github.com/albertosantini/python-fluid" rel="external nofollow">ألبيرتو سانتينيAlberto Santini</a> تعليمات باستخدام <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">لغة البرمجة بايثون</a> (استخدم حينها numarray). الآن، علينا فقط تكييفها مع مكتبة NumPy الحديثة وتسريعها قليلًا باستخدام الحيل المعقدة. لن نشرح الشيفرات لأنها طويلة جدًا.
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409708?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	 
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409675?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	 
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="350" src="https://player.vimeo.com/video/778409686?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	محاكاة الدخان باستخدام خوارزمية السوائل المستقرة بواسطة جو ستام. تأتي معظم مقاطع الفيديو الصحيحة من <a href="http://glumpy.github.io/" rel="external nofollow">حزمة Glumpy</a> وتستخدم GPU (عمليات الإطارات الاحتياطية، أي عدم وجود OpenCL أو CUDA) لإجراء عمليات حسابية أسرع.
</p>

<h2>
	أخذ عينات الضجيج الأزرق
</h2>

<p>
	يشير الضجيج الأزرق blue noise إلى مجموعات العينات التي لها توزيعات عشوائية وموحدة مع عدم وجود أي انحياز طيفي. هذا الضجيج مفيد جدًا في مجموعة متنوعة من تطبيقات الرسوم، مثل التصيير rendering والتردد dithering وما إلى ذلك، وقد اقترحت عدة طرق لتحقيق مثل هذا الضجيج، ولكن الطريقة الأكثر بساطة هي بالتأكيد طريقة دارت DART.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113747" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398526472cb1_07_.png.26105706aa61ef7d58460c4f3e8d94f1.png" rel=""><img alt="أخذ عينات الضجيج الأزرق" class="ipsImage ipsImage_thumbnailed" data-fileid="113747" data-unique="8q46jkyq2" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398526612b65_07_.thumb.png.e6a3fcdbb737f511ebb58b2f97713afd.png" style="width: 600px; height: auto;"></a>
</p>

<h3>
	طريقة دارت DART
</h3>

<p>
	تُعد طريقة دارت DART واحدةً من أقدم وأبسط الطرق، وهي تعمل عن طريق الرسم المتسلسل لنقاط عشوائية موحدة وقبول فقط تلك التي تقع على مسافة لا تقل عن كل عينة مقبولة سابقة، ولذلك فهي طريقة بطيئة جدًا لأن كل مرشح جديد يحتاج إلى اختباره مقابل المرشحين المقبولين السابقين؛ وكلما زادت النقاط التي تقبلها كانت الطريقة أبطأ. لنفكر في وحدة السطح والحد الأدنى لنصف القطر r لفرضه في كل نقطة.
</p>

<p>
	التعبئة الأكثر كثافة للدوائر في المستوى هي الشبكة السداسية لشكل خلية النحل، وتحسب الكثافة بالصيغة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113750" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398526e6f78d_1.png.1fb06a7a08bb8b1d2b29539f5f784682.png" rel=""><img alt="حساب كثافة الدوائر" class="ipsImage ipsImage_thumbnailed" data-fileid="113750" data-unique="kdhxvpt2f" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398526e6f78d_1.png.1fb06a7a08bb8b1d2b29539f5f784682.png" style="width: 120px; height: auto;"></a>
</p>

<p>
	بالنظر إلى الدوائر ذات نصف القطر r، يمكننا أن نكتب:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113751" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398526fc98fa_2.png.82031500b9f01be6c1c89fec271a7fb7.png" rel=""><img alt="حساب كثافة الدوائر ذات نصف القطر r" class="ipsImage ipsImage_thumbnailed" data-fileid="113751" data-unique="mxzllrvev" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398526fc98fa_2.png.82031500b9f01be6c1c89fec271a7fb7.png" style="width: 200px; height: auto;"></a>
</p>

<p>
	نحن نعلم الحد الأعلى النظري لعدد الأقراص الممكن وضعها على السطح ولكن من المحتمل ألا نصل إلى هذا الحد الأقصى بسبب المواضع العشوائية. علاوةً على ذلك، نظرًا لرفض الكثير من النقاط بعد قبول القليل منها، سنحتاج إلى وضع حد لعدد المحاكمات الفاشلة المتتالية قبل أن نوقف العملية كاملةً.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4204_55" style="">
<span class="kwd">import</span><span class="pln"> math
</span><span class="kwd">import</span><span class="pln"> random

</span><span class="kwd">def</span><span class="pln"> DART_sampling</span><span class="pun">(</span><span class="pln">width</span><span class="pun">=</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> height</span><span class="pun">=</span><span class="lit">1.0</span><span class="pun">,</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.025</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">=</span><span class="lit">100</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> distance</span><span class="pun">(</span><span class="pln">p0</span><span class="pun">,</span><span class="pln"> p1</span><span class="pun">):</span><span class="pln">
        dx</span><span class="pun">,</span><span class="pln"> dy </span><span class="pun">=</span><span class="pln"> p0</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-</span><span class="pln">p1</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> p0</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]-</span><span class="pln">p1</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">hypot</span><span class="pun">(</span><span class="pln">dx</span><span class="pun">,</span><span class="pln"> dy</span><span class="pun">)</span><span class="pln">

    points </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    last_success </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">:</span><span class="pln">
        x </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> width</span><span class="pun">)</span><span class="pln">
        y </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> height</span><span class="pun">)</span><span class="pln">
        accept </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> points</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> distance</span><span class="pun">(</span><span class="pln">p</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">))</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> r</span><span class="pun">:</span><span class="pln">
                accept </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
                </span><span class="kwd">break</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> accept </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">:</span><span class="pln">
            points</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> i</span><span class="pun">-</span><span class="pln">last_success </span><span class="pun">&gt;</span><span class="pln"> k</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">break</span><span class="pln">
            last_success </span><span class="pun">=</span><span class="pln"> i
        i </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> points</span></pre>

<p>
	تركنا لك تمرين إيجاد اتجاه توجيه لطريقة دارت DART. إذ تكمن الفكرة في إجراء حساب مسبق لعدد منتظم كافٍ من العينات العشوائية، إضافةً إلى المسافات المقترنة واختبار تضمينها التسلسلي.
</p>

<h3>
	طريقة بريدسون Bridson
</h3>

<p>
	إذا لم تسبب متجهات الطريقة السابقة أي صعوبة حقيقية، فإن تحسين السرعة ليس جيدًا وتظل الجودة منخفضة وتعتمد على المعامل <code>k</code>؛ فكلما كان هذا المعامل أعلى، كان ذلك أفضل لأنه يتحكم بصورةٍ أساسية في مدى صعوبة محاولة إدخال عينة جديدة، ولكن عندما يكون هناك عدد كبير فعلًا من العينات المقبولة، فإن فرصة واحد فقط ستسمح لنا بالعثور على موقع لإدخال عينة جديدة. يمكننا زيادة قيمة <code>k</code> ولكن هذا سيجعل الطريقة أبطأ دون أي ضمان في الجودة. حان الوقت للتفكير خارج الصندوق ولحسن الحظ، فعل روبرت بريدسون ذلك لنا واقترح طريقة بسيطة لكنها فعالة:
</p>

<ul>
<li>
		الخطوة 0: تهيئة شبكة خلفية ذات <code>n</code> بُعد لتخزين العينات وتسريع البحث المكاني. نختار حجم الخلية المراد تقييدها من خلال
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113752" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398527030acb_3.png.4fd823acdac32176122ac87257a443dc.png" rel=""><img alt="تهيئة شبكة خلفية ذات n بُعد لتخزين العينات وتسريع البحث المكاني" class="ipsImage ipsImage_thumbnailed" data-fileid="113752" data-unique="zyr4c4xlu" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398527030acb_3.png.4fd823acdac32176122ac87257a443dc.png" style="width: 50px; height: auto;"></a>
</p>

<p style="margin-right: 40px;">
	بحيث تحتوي كل خلية شبكية على عينة واحدة على الأكثر، وبالتالي يمكن تنفيذ الشبكة مثل مصفوفة بسيطة من الأعداد الصحيحة ذات البعد <code>n</code>: يشير الرقم الافتراضي "1-" إلى عدم وجود عينة، بينما يعطي العدد الصحيح غير السالب مؤشر العينة الموجود في الخلية.
</p>

<ul>
<li>
		<p>
			الخطوة 1. حدد العينة الأولية x<sub>0</sub>، التي تُختار عشوائيًا من المجال، وأدخلها في شبكة الخلفية وهيّئ "القائمة النشطة" (مجموعة من مؤشرات العينة) باستخدام هذا المؤشر (صفر).
		</p>
	</li>
	<li>
		<p>
			الخطوة 2: عندما لا تكون القائمة النشطة فارغة، اختر منها مؤشرًا عشوائيًا وليكن <code>i</code>. عليك توليد ما يصل إلى "k" من النقاط المختارة بطريقة موحدة من الحلقة الكروية بين نصف القطر "r" و "2r" وحول x<sub>i</sub>. تحقق من أجل كل نقطة مما إذا كانت على مسافة "r" من العينات الموجودة (باستخدام شبكة الخلفية لاختبار العينات القريبة فقط). إذا كانت نقطة ما بعيدة بحد كافٍ عن العينات الموجودة فأرسلها على أنها عينة تالية وأضفها إلى القائمة النشطة. إذا لم يعثر على مثل هذه النقط بعد "k" محاولة، عليك إزالة <code>i</code> من القائمة النشطة.
		</p>
	</li>
</ul>
<p>
	لا يطرح التنفيذ مشكلة حقيقية ويُترك بمثابة تمرين للقارئ. لاحظ أن هذه الطريقة ليست سريعة فحسب ولكنها تقدم أيضًا جودة أفضل (المزيد من العينات) من طريقة دارت DART ومع وجود عدد كبير من المحاولات.
</p>

<h2>
	الخلاصة
</h2>

<p>
	يعد المثال الأخير الذي كنا ندرسه هو مثال جيد، لأن متجهات المشكلة أكثر أهمية من متجهات الشيفرات، وقد كنا محظوظين في هذه الحالة المحددة بما يكفي لإنجاز العمل ولكن لن يكون الأمر كذلك دائمًا. نأمل أن تكون الآن مقتنعًا أنه من الجيد البحث عن حلول بديلة بمجرد العثور على حل. ستعمل دائمًا على تحسين السرعة من خلال متجهات الشيفرات والتعليمات البرمجية ولكن في هذه العملية فقد تفوتك تحسينات كبيرة.
</p>

<p>
	ترجمة -وبتصرّف- للفصل <a href="https://www.labri.fr/perso/nrougier/from-python-to-numpy/#problem-vectorization" rel="external nofollow">Problem vectorization</a> من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-vectorization-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1819/" rel="">استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/" rel="">مفاهيم متقدمة حول مكتبة NumPy في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a><em><em><em><em> </em></em></em></em>
	</li>
</ul>
]]></description><guid isPermaLink="false">1820</guid><pubDate>Tue, 13 Dec 2022 10:43:19 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x645;&#x62A;&#x62C;&#x647;&#x627;&#x62A; vectorization &#x641;&#x64A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x645;&#x639; &#x645;&#x643;&#x62A;&#x628;&#x629; NumPy</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A7%D8%AA-vectorization-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D8%B9-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-r1819/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/6398474eed7c2_-------NumPy.png.20c67c11fa652a270a89f614fc8ff72b.png" /></p>

<p>
	يُقصد باستخدام المتجهات vectorization في الشيفرة أن المشكلة التي تحاول حلها قابلةٌ للتحليل بطبيعتها ولا تتطلب سوى استخدام بعض الحيل لجعلها أسرع، وهذا لا يعني أن الأمر سهل أو مباشر، ولكنه على الأقل لا يستلزم إعادة التفكير في كامل مشكلتك. يتطلب الأمر بعض الخبرة لمعرفة أين يمكن استخدام المتجهات في الشيفرة. سنوضح ذلك من خلال مثال بسيط، إذ نريد تلخيص قائمتين من الأعداد الصحيحة.
</p>

<p>
	سنستخدم الدالة البسيطة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_7" style="">
<span class="kwd">def</span><span class="pln"> add_python</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln">Z2</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">z1</span><span class="pun">+</span><span class="pln">z2 </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">z1</span><span class="pun">,</span><span class="pln">z2</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> zip</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln">Z2</span><span class="pun">)]</span></pre>

<p>
	إعادة كتابة الشيفرة السابقة عبر المتجهات من مكتبة NumPy بسهولة كبيرة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_9" style="">
<span class="kwd">def</span><span class="pln"> add_numpy</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln">Z2</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln">Z2</span><span class="pun">)</span></pre>

<p>
	وكما هو متوقع تظهر المقارنة أن الطريقة الثانية هي الأسرع:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_12" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z1 </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">sample</span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">),</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z2 </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">sample</span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">),</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"add_python(Z1, Z2)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">68</span><span class="pln"> usec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"add_numpy(Z1, Z2)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">10000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.14</span><span class="pln"> usec per loop</span></pre>

<p>
	كما أنها تتكيف أيضًا مع شكل <code>Z1</code> و <code>Z2</code>، وهذا هو سبب عدم كتابة <code>Z1 + Z2</code> لأن هذه الطريقة لن تعمل إذا كان كل من <code>Z1</code> و <code>Z2</code> قائمتين. تُفسّر عملية الجمع الداخلية في الطريقة الأولى المعتمدة على تابع <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">لغة بايثون</a> بطريقة مختلفة اعتمادًا على طبيعة الكائنين؛ وإذا أخذنا في الحسبان قائمتين متداخلتين، نحصل على المخرجات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_15" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z1 </span><span class="pun">+</span><span class="pln"> Z2
</span><span class="pun">[[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> add_python</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln"> Z2</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> add_numpy</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln"> Z2</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[[</span><span class="pln"> </span><span class="lit">6</span><span class="pln">  </span><span class="lit">8</span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="lit">10</span><span class="pln"> </span><span class="lit">12</span><span class="pun">]]</span></pre>

<p>
	تربط الطريقة الأولى القائمتين معًا، بينما تربط الطريقة الثانية القوائم الداخلية معًا، وتحسب الطريقة الأخيرة ما هو متوقع. يمكنك إعادة كتابة تعليمات <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> بحيث تضم قوائم متداخلة مختلفة الحجم.
</p>

<h2>
	المتجه الموحد Uniform vectorization
</h2>

<p>
	يُعد المتجه الموحد أبسط شكل من أشكال المتجهات، إذ تشترك جميع العناصر في نفس العملية الحسابية في كل خطوة زمنية مع عدم وجود معالجة محددة لأي عنصر. لعبة الحياة هي إحدى الحالات النمطية التي اخترعها جون كونواي John Conway وهي إحدى أقدم الأمثلة على المشغلات الآلية الخلوية cellular automata، التي تمثّل مجموعةً من الخلايا التي ترتبط معًا بمفهوم الجيران وتكون متجّهاتها بسيطة.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		تُعرف المشغلات الآلية الخلوية بالإنكليزية باسم "cellular automata"، تدل على مصفوفة من الخلايا يمكن أن تأخذ عددًا منته من الحالات حيث كل حالة مستقبلية للخلية تتعلق بحالتها الحاضرة وبحالة الخلايا المجاورة لها. إن التحول من حالة إلى أخرى يحكم بقواعد معرفة مسبقًا.
	</p>
</blockquote>

<p>
	سنحدّد بدايةً قواعد اللعبة ثم سندرس كيفية جعلها معتمدة على المتجهات:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113735" href="https://academy.hsoub.com/uploads/monthly_2022_12/00-Textile-Cone-cropped.jpg.7678b8874455ab80b3ef0bb795250c2b.jpg" rel=""><img alt="شكل نسيج صدفة الحلزون ذو نمط المشغل الآلي الخلوي" class="ipsImage ipsImage_thumbnailed" data-fileid="113735" data-unique="doydawalq" src="https://academy.hsoub.com/uploads/monthly_2022_12/00-Textile-Cone-cropped.thumb.jpg.59e042d9d2ae3bd0166fe19bcddd696f.jpg" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	يظهر نسيج صدفة الحلزون نمط مشغل آلي خلوي على غلافها الخارجي. الصورة <a href="https://commons.wikimedia.org/wiki/File:Textile_cone.JPG" rel="external nofollow">لريتشارد لينج 2005</a>.
</p>

<h3>
	لعبة الحياة
</h3>

<p>
	يمكنك الحصول على فكرة حول لعبة الحياة في <a href="https://ar.wikipedia.org/wiki/%D9%84%D8%B9%D8%A8%D8%A9_%D8%A7%D9%84%D8%AD%D9%8A%D8%A7%D8%A9_(%D8%AD%D9%88%D8%B3%D8%A8%D8%A9" rel="external nofollow">موقع ويكيبيديا</a>؛ وهي لعبة معتمدة على المشغلات الآلية الخلوية، وابتكرها عالم الرياضيات البريطاني جون هورتون كونواي John Horton Conway في عام 1970. اللعبة هي لعبة بدون لاعب، مما يعني أن تطورها يُحدّد من خلال حالتها الأولية، ولا تحتاج اللعبة إلى مدخلات من اللاعبين، ويتفاعل المراقب مع لعبة الحياة من خلال إنشاء تكوين أولي ومراقبة كيفية تطور اللعبة.
</p>

<p>
	عالم لعبة الحياة هي شبكة متعامدة ثنائية الأبعاد لا نهائية من الخلايا المربعة، لكل منها حالتين محتملتين (حياة أو موت)، وترتبط حالة كل خلية بجاراتها الثمانية، وهي الخلايا المتجاورة أفقيًا، أو رأسيًا، أو قطريًا، وتحدث في كل خطوة في الوقت المناسب التحولات التالية:
</p>

<ul>
<li>
		تموت أي خلية حية لها أقل من اثنين من الجيران الأحياء (كما لو كانت بسبب الاحتياجات الناجمة عن نقص السكان).
	</li>
	<li>
		تموت أي خلية لها أكثر من ثلاثة جيران أحياء (كما لو كان السبب هو الاكتظاظ).
	</li>
	<li>
		تعيش أي خلية حية لها اثنان أو ثلاثة من الجيران الأحياء للجيل القادم.
	</li>
	<li>
		تصبح أي خلية ميتة مع ثلاثة جيران أحياء بالضبط خليةً حية.
	</li>
</ul>
<p>
	يشكل النمط الأولي "أصل seed" النظام. يُنشأ الجيل الأول من خلال القواعد السابقة في وقت واحد على كل خلية (تحدث الولادات والوفيات في وقت واحد)، أي كل جيل هو نتيجة خالصة للجيل السابق، ويستمر تطبيق القواعد بطريقة مستمرة لخلق أجيال أخرى.
</p>

<h3>
	كتابة شيفرة بلغة بايثون
</h3>

<p>
	يمكننا كتابة شيفرة لعبة Game of Life في لغة <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون</a> باستخدام قائمة list تمثّل اللوحة، إذ من المفترض أن تتطور الخلايا. تُجهز هذه اللوحة بحدود صفرية "0" مما يسمح بتسريع الأمور قليلًا عن طريق تجنب إجراء اختبارات محددة للحدود عند حساب الجيران.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_19" style="">
<span class="pln">Z </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
     </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
     </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
     </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
     </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
     </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]]</span></pre>

<p>
	يكون عدد الجيران واضحًا عند أخذ الحدود بالحسبان:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_22" style="">
<span class="kwd">def</span><span class="pln"> compute_neighbours</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">):</span><span class="pln">
    shape </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">),</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])</span><span class="pln">
    N  </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[[</span><span class="lit">0</span><span class="pun">,]*(</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">])]</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> y </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]-</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
            N</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">-</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">-</span><span class="lit">1</span><span class="pun">]+</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">-</span><span class="lit">1</span><span class="pun">]+</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">+</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> \
                    </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">-</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln">            </span><span class="pun">+</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">+</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln">   \
                    </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">-</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]+</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]+</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">+</span><span class="lit">1</span><span class="pun">][</span><span class="pln">y</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> N</span></pre>

<p>
	نكرر الخطوة في الوقت المناسب، ولذلك نحسب عدد الجيران لكل خلية داخلية ثم نحدث كامل اللوحة وفقًا للقواعد الأربعة المذكورة أعلاه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_24" style="">
<span class="kwd">def</span><span class="pln"> iterate</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">):</span><span class="pln">
    N </span><span class="pun">=</span><span class="pln"> compute_neighbours</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> y </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]-</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
             </span><span class="kwd">if</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> N</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">):</span><span class="pln">
                 Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
             </span><span class="kwd">elif</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> N</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
                 Z</span><span class="pun">[</span><span class="pln">x</span><span class="pun">][</span><span class="pln">y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z</span></pre>

<p>
	يوضح الشكل أدناه أربعة تكرارات على منطقة 4×4، إذ أن الحالة الأولية هي <a href="https://en.wikipedia.org/wiki/Glider_(Conway%27s_Life)" rel="external nofollow">طائرة شراعية glider</a>، وهي بنية اكتُشفت عام 1970.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113736" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398474bed16f_01_.PNG.8d2dccae546a580472a128a88e001838.PNG" rel=""><img alt="نمط الطائرة الشراعية" class="ipsImage ipsImage_thumbnailed" data-fileid="113736" data-unique="mnzckll78" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398474bed16f_01_.PNG.8d2dccae546a580472a128a88e001838.PNG" style="width: 650px; height: auto;"></a>
</p>

<p>
	من المعروف أن نمط الطائرة الشراعية يكرر نفسه خطوةً واحدةً قطريًا خلال أربعة تكرارات.
</p>

<h3>
	كتابة شيفرة Numpy
</h3>

<p>
	بناءً على التعليمات السابقة المكتوبة بلغة بايثون، نلاحظ أن شيفرة لعبة الحياة ينقسم إلى قسمين، أحدهما مسؤول عن حساب عدد الجيران والآخر مسؤول عن تطبيق القواعد. يُعد حساب عدد الجيران أمرًا سهلًا نسبيًا، لأننا حرصنا على إضافة حد فارغ حول النطاق arena. ومن خلال النظر في العروض الجزئية للنطاق يمكننا الوصول إلى الجيران بطريقة حدسية كما توضح هذه الحالة أحادية البعد:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113737" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398474d3caec_02.png.d7bae5a6fae3eb9a80e62d07202b4ee4.png" rel=""><img alt="كتابة شيفرة Numpy أحادية البعد" class="ipsImage ipsImage_thumbnailed" data-fileid="113737" data-unique="m7hunivv5" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398474e9b072_02.thumb.png.f1179983390d535c095d950d7c9a30b7.png" style="width: 500px; height: auto;"></a>
</p>

<p>
	يتطلب الانتقال إلى الحالة ثنائية البعد حسابات إضافية للتأكد من مراعاة جميع الجيران الثمانية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_29" style="">
<span class="pln">N </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
N</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z</span><span class="pun">[</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">,</span><span class="lit">2</span><span class="pun">:]</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
                 Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">]</span><span class="pln">                </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">:]</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
                 Z</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:</span><span class="pln">  </span><span class="pun">,</span><span class="pln"> </span><span class="pun">:-</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:</span><span class="pln">  </span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:</span><span class="pln">  </span><span class="pun">,</span><span class="lit">2</span><span class="pun">:])</span></pre>

<p>
	يمكننا لتطبيق القاعدة كتابة التعليمات البرمجية باستخدام تابع <code>argwhere</code> الذي سينتج عنه رقم المؤشر عندما يكون الشرط المحدد صحيحًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_32" style="">
<span class="com"># المصفوفات المسطحة</span><span class="pln">
N_ </span><span class="pun">=</span><span class="pln"> N</span><span class="pun">.</span><span class="pln">ravel</span><span class="pun">()</span><span class="pln">
Z_ </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">ravel</span><span class="pun">()</span><span class="pln">

</span><span class="com"># تطبيق القواعد</span><span class="pln">
R1 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">argwhere</span><span class="pun">(</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z_</span><span class="pun">==</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N_ </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
R2 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">argwhere</span><span class="pun">(</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z_</span><span class="pun">==</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N_ </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
R3 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">argwhere</span><span class="pun">(</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z_</span><span class="pun">==</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">((</span><span class="pln">N_</span><span class="pun">==</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N_</span><span class="pun">==</span><span class="lit">3</span><span class="pun">))</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
R4 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">argwhere</span><span class="pun">(</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z_</span><span class="pun">==</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N_</span><span class="pun">==</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

</span><span class="com"># ضبط قيم جديدة</span><span class="pln">
Z_</span><span class="pun">[</span><span class="pln">R1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
Z_</span><span class="pun">[</span><span class="pln">R2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
Z_</span><span class="pun">[</span><span class="pln">R3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z_</span><span class="pun">[</span><span class="pln">R3</span><span class="pun">]</span><span class="pln">
Z_</span><span class="pun">[</span><span class="pln">R4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># كن متأكدًا من بقاء الحدود فارغة</span><span class="pln">
Z</span><span class="pun">[</span><span class="lit">0</span><span class="pun">,:]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[-</span><span class="lit">1</span><span class="pun">,:]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:,</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:,-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	رغم عدم استخدام الإصدار الأول للحلقات المتداخلة لكنه يبقى بعيدًا على أن يكون أمثليًا بسبب استخدام استدعاءات <code>argwhere</code> التي قد تكون بطيئة جدًا، ويمكننا بدلًا من ذلك تحليل القواعد إلى الخلايا التي ستبقى على قيد الحياة (أي التي ستبقى عند قيمة 1) والخلايا التي ستلد وذلك بالاستفادة من القدرة المنطقية لمكتبة Numpy:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		لم نكتب <code>Z = 0</code> لأن هذا سيعين ببساطة القيمة "0" إلى <code>Z</code> التي ستصبح بعد ذلك قيمةً مفردة.
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_34" style="">
<span class="pln">birth </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N</span><span class="pun">==</span><span class="lit">3</span><span class="pun">)[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]==</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
survive </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">N</span><span class="pun">==</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">N</span><span class="pun">==</span><span class="lit">3</span><span class="pun">))[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">]==</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
Z</span><span class="pun">[...]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
Z</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">][</span><span class="pln">birth </span><span class="pun">|</span><span class="pln"> survive</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	إذا دققت في أول سطرين ستلاحظ أن المتغيرين <code>birth</code> و <code>survive</code> مصفوفتان يمكن استخدامهما لتعيين قسم المصفوفة <code>Z</code> إلى القيمة "1" بعد محوها.
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe __idm_id__="57345" height="506" weight="600" src="https://player.vimeo.com/video/778409806?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<h3>
	تمرين
</h3>

<p>
	يمكن أن ينتج عن تفاعل الأصناف الكيميائية وانتشارها مجموعةً متنوعةً من الأنماط، تذكرنا غالبًا بتلك التي نراها في الطبيعة، ومن أمثلة هذا التفاعل نموذج معادلات جراي سكوت Gray-Scott، ولمزيد من المعلومات حول هذا النظام الكيميائي راجع مقالة الأنماط المعقدة في نظام بسيط.
</p>

<p>
	لنفكر في نوعين كيميائيين U و V، ولكل منهما تركيز u و v ومعدل انتشاء Du و Dv. يُحوّل V إلى P بمعدل تحويل k. يمثل f معدل العملية التي تشبع U وتجعل كل من U و V و P يتلاشى. ويمكن كتابة ذلك على النحو التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113743" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398475ddf26b_.png.221047778f6289d9890339553cb1b161.png" rel=""><img alt="المعادلات والتفاعل الكيميائي للأصناف" class="ipsImage ipsImage_thumbnailed" data-fileid="113743" data-unique="4k7x7h6sy" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398475ea7747_.thumb.png.275a5917c137ef0d149b65e894839680.png" style="width: 600px; height: auto;"></a>
</p>

<p>
	استنادًا إلى مثال لعبة الحياة سنجرب تنفيذ نظام نشر التفاعل. فيما يلي مجموعة من المعاملات التي سنحتاج إلى اختبارها:
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
<thead><tr>
<th>
				الاسم
			</th>
			<th>
				Du
			</th>
			<th>
				Dv
			</th>
			<th>
				f
			</th>
			<th>
				k
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				Bacteria 1
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.035
			</td>
			<td>
				0.065
			</td>
		</tr>
<tr>
<td>
				Bacteria 2
			</td>
			<td>
				0.14
			</td>
			<td>
				0.06
			</td>
			<td>
				0.035
			</td>
			<td>
				0.065
			</td>
		</tr>
<tr>
<td>
				Coral
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.060
			</td>
			<td>
				0.062
			</td>
		</tr>
<tr>
<td>
				Fingerprint
			</td>
			<td>
				0.19
			</td>
			<td>
				0.05
			</td>
			<td>
				0.060
			</td>
			<td>
				0.062
			</td>
		</tr>
<tr>
<td>
				Spirals
			</td>
			<td>
				0.10
			</td>
			<td>
				0.10
			</td>
			<td>
				0.018
			</td>
			<td>
				0.050
			</td>
		</tr>
<tr>
<td>
				Spirals Dense
			</td>
			<td>
				0.12
			</td>
			<td>
				0.08
			</td>
			<td>
				0.020
			</td>
			<td>
				0.050
			</td>
		</tr>
<tr>
<td>
				Spirals Fast
			</td>
			<td>
				0.10
			</td>
			<td>
				0.16
			</td>
			<td>
				0.020
			</td>
			<td>
				0.050
			</td>
		</tr>
<tr>
<td>
				Unstable
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.020
			</td>
			<td>
				0.055
			</td>
		</tr>
<tr>
<td>
				Worms 1
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.050
			</td>
			<td>
				0.065
			</td>
		</tr>
<tr>
<td>
				Worms 2
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.054
			</td>
			<td>
				0.063
			</td>
		</tr>
<tr>
<td>
				Zebrafish
			</td>
			<td>
				0.16
			</td>
			<td>
				0.08
			</td>
			<td>
				0.035
			</td>
			<td>
				0.060
			</td>
		</tr>
</tbody>
</table>
<p>
	والنتائج هي كالآتي:
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe __idm_id__="57346" allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409789?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	والآتي:
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe __idm_id__="57347" allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409768?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	إضافةً إلى ما يلي:
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409747?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<h2>
	المتجهات الزمنية Temporal vectorization
</h2>

<p>
	مجموعة Mandelbrot هي مجموعةٌ من الأعداد العقدية <code>c</code> التي لا تتباعد diverge فيها الدالة "f<sub>c</sub>(z) = z<sup>2</sup> + c" عند تكرارها بدءًا من z = 0، أي من أجل التسلسل "… ,((f<sub>c</sub>(0), f<sub>c</sub>(f<sub>c</sub>(0" وتظل محدودة بالقيمة المطلقة. من السهل حسابها ولكنها قد تستغرق وقتًا طويلَا جدًا لأنك تحتاج إلى التأكد من أن رقمًا معينًا لا يتباعد، ويُنفّذ ذلك من خلال تكرار الحساب حتى أقصى عدد من التكرارات، وبعد ذلك إذا كان الرقم لا يزال ضمن الحدود يكون غير متباعد، وبالتأكيد كلما زاد عدد مرات التكرار زادت الدقة التي تحصل عليها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113742" href="https://academy.hsoub.com/uploads/monthly_2022_12/Fractal-Broccoli-cropped.jpg.53250cf34b2c1837050556e003eb6312.jpg" rel=""><img alt="روكلي رومانسكو الذي يُظهر شكلًا قريبًا من كسورية fractal طبيعية" class="ipsImage ipsImage_thumbnailed" data-fileid="113742" data-unique="zpvml67kr" src="https://academy.hsoub.com/uploads/monthly_2022_12/Fractal-Broccoli-cropped.thumb.jpg.f6b7d707a663b3cf0c643b6a1526024b.jpg" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	بروكلي رومانسكو، يُظهر شكلًا قريبًا من كسورية fractal طبيعية. صورة <a href="https://commons.wikimedia.org/wiki/File:Fractal_Broccoli.jpg" rel="external nofollow">جون سوليفان</a>، 2004.
</p>

<h3>
	كتابة شيفرة بايثون
</h3>

<p>
	تكتب التعليمات البرمجية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_43" style="">
<span class="pln"> </span><span class="kwd">def</span><span class="pln"> mandelbrot_python</span><span class="pun">(</span><span class="pln">xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> xn</span><span class="pun">,</span><span class="pln"> yn</span><span class="pun">,</span><span class="pln"> maxiter</span><span class="pun">,</span><span class="pln"> horizon</span><span class="pun">=</span><span class="lit">2.0</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> mandelbrot</span><span class="pun">(</span><span class="pln">z</span><span class="pun">,</span><span class="pln"> maxiter</span><span class="pun">):</span><span class="pln">
        c </span><span class="pun">=</span><span class="pln"> z
        </span><span class="kwd">for</span><span class="pln"> n </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">maxiter</span><span class="pun">):</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> abs</span><span class="pun">(</span><span class="pln">z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> horizon</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> n
            z </span><span class="pun">=</span><span class="pln"> z</span><span class="pun">*</span><span class="pln">z </span><span class="pun">+</span><span class="pln"> c
        </span><span class="kwd">return</span><span class="pln"> maxiter
    r1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">xmin</span><span class="pun">+</span><span class="pln">i</span><span class="pun">*(</span><span class="pln">xmax</span><span class="pun">-</span><span class="pln">xmin</span><span class="pun">)/</span><span class="pln">xn </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">xn</span><span class="pun">)]</span><span class="pln">
    r2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">ymin</span><span class="pun">+</span><span class="pln">i</span><span class="pun">*(</span><span class="pln">ymax</span><span class="pun">-</span><span class="pln">ymin</span><span class="pun">)/</span><span class="pln">yn </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">yn</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">mandelbrot</span><span class="pun">(</span><span class="pln">complex</span><span class="pun">(</span><span class="pln">r</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">),</span><span class="pln">maxiter</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> r </span><span class="kwd">in</span><span class="pln"> r1 </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> r2</span><span class="pun">]</span></pre>

<p>
	الجزء المثير للاهتمام والبطيء في الشيفرات السابقة هو دالة <code>mandelbrot</code> التي تحسب التسلسل "(((…f<sub>c</sub>(f<sub>c</sub>(f<sub>c</sub>". جعل هذه الشيفرات معتمدة على المتجهات ليس أمرًا واضحًا تمامًا بسبب تعليمة <code>return</code> الداخلية التي توحي بعملية فاضلية للعنصر. بمجرد أن يتباعد لا نحتاج إلى التكرار مرةً أخرى ويمكننا إرجاع عدد التكرارات في حال عدم التباعد، ولكن كيف يمكن أن تفعل Numpy الشيء نفسه؟
</p>

<h3>
	كتابة الشيفرة باستخدام مكتبة Numpy
</h3>

<p>
	الحيلة هي البحث في كل قيم التكرار التي لم تتباعد بعد وتحديث المعلومات المتعلقة بهذه القيم فقط. نظرًا لأننا نبدأ من "Z = 0"، فإننا نعلم أن كل قيمة ستُحدث مرةً واحدةً على الأقل (عندما تكون مساويةً للصفر فإنها لم تتباعد بعد)، وستتوقف عن التحديث بمجرد تباعدها. ولفعل ذلك سنستخدم فهرسة fancy indexing مع الدالة <code>(less(x1,x2</code> التي ترجع القيمة الحقيقية للعنصر المحقق (x1&lt;x2).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_45" style="">
<span class="kwd">def</span><span class="pln"> mandelbrot_numpy</span><span class="pun">(</span><span class="pln">xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> xn</span><span class="pun">,</span><span class="pln"> yn</span><span class="pun">,</span><span class="pln"> maxiter</span><span class="pun">,</span><span class="pln"> horizon</span><span class="pun">=</span><span class="lit">2.0</span><span class="pun">):</span><span class="pln">
    X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">linspace</span><span class="pun">(</span><span class="pln">xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> xn</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
    Y </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">linspace</span><span class="pun">(</span><span class="pln">ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> yn</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
    C </span><span class="pun">=</span><span class="pln"> X </span><span class="pun">+</span><span class="pln"> Y</span><span class="pun">[:,</span><span class="kwd">None</span><span class="pun">]*</span><span class="lit">1j</span><span class="pln">
    N </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
    Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">complex64</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> n </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">maxiter</span><span class="pun">):</span><span class="pln">
        I </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">less</span><span class="pun">(</span><span class="pln">abs</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">),</span><span class="pln"> horizon</span><span class="pun">)</span><span class="pln">
        N</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> n
        Z</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]**</span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> C</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln">
    N</span><span class="pun">[</span><span class="pln">N </span><span class="pun">==</span><span class="pln"> maxiter</span><span class="pun">-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z</span><span class="pun">,</span><span class="pln"> N</span></pre>

<p>
	وإليك النتيجة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_47" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> xn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2.25</span><span class="pun">,</span><span class="pln"> </span><span class="pun">+</span><span class="lit">0.75</span><span class="pun">,</span><span class="pln"> int</span><span class="pun">(</span><span class="lit">3000</span><span class="pun">/</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> yn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.25</span><span class="pun">,</span><span class="pln"> </span><span class="pun">+</span><span class="lit">1.25</span><span class="pun">,</span><span class="pln"> int</span><span class="pun">(</span><span class="lit">2500</span><span class="pun">/</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> maxiter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">200</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"mandelbrot_python(xmin, xmax, ymin, ymax, xn, yn, maxiter)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6.1</span><span class="pln"> sec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"mandelbrot_numpy(xmin, xmax, ymin, ymax, xn, yn, maxiter)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.15</span><span class="pln"> sec per loop</span></pre>

<h3>
	كتابة الشيفرة الأسرع باستخدام Numpy
</h3>

<p>
	سيكون الربح بزيادة السرعة خمسة أضعاف تقريبًا وليس بالقدر الذي نتوقعه، ومن أسباب هذه المشكلة هو أن الدالة <code>np.less</code> تشير إلى اختبارات <code>xn × yn</code> في كل تكرار، بينما نعلم أن بعض القيم قد تباعدت فعلًا، وحتى إذا أجريت هذه الاختبارات على المستوى C (من خلال numpy)، ستبقى التكلفة كبيرة. توجد طريقةٌ أخرى اقترحها دان جودمان Dan Goodman وذلك بالعمل على مصفوفة ديناميكية في كل تكرار بحيث تخزن فقط النقاط التي لم تتباعد بعد، وهذا يتطلب إضافة أسطر برمجية إضافية ولكن ستكون النتيجة أسرع وتؤدي إلى تحسين عامل السرعة عشر مرات مقارنةً بالطريقة الأولى.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_49" style="">
<span class="kwd">def</span><span class="pln"> mandelbrot_numpy_2</span><span class="pun">(</span><span class="pln">xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> xn</span><span class="pun">,</span><span class="pln"> yn</span><span class="pun">,</span><span class="pln"> itermax</span><span class="pun">,</span><span class="pln"> horizon</span><span class="pun">=</span><span class="lit">2.0</span><span class="pun">):</span><span class="pln">
    </span><span class="typ">Xi</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Yi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">mgrid</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:</span><span class="pln">xn</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">yn</span><span class="pun">]</span><span class="pln">
    </span><span class="typ">Xi</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Yi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Xi</span><span class="pun">.</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">uint32</span><span class="pun">),</span><span class="pln"> </span><span class="typ">Yi</span><span class="pun">.</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">uint32</span><span class="pun">)</span><span class="pln">
    X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">linspace</span><span class="pun">(</span><span class="pln">xmin</span><span class="pun">,</span><span class="pln"> xmax</span><span class="pun">,</span><span class="pln"> xn</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)[</span><span class="typ">Xi</span><span class="pun">]</span><span class="pln">
    Y </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">linspace</span><span class="pun">(</span><span class="pln">ymin</span><span class="pun">,</span><span class="pln"> ymax</span><span class="pun">,</span><span class="pln"> yn</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)[</span><span class="typ">Yi</span><span class="pun">]</span><span class="pln">
    C </span><span class="pun">=</span><span class="pln"> X </span><span class="pun">+</span><span class="pln"> Y</span><span class="pun">*</span><span class="lit">1j</span><span class="pln">
    N_ </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">uint32</span><span class="pun">)</span><span class="pln">
    Z_ </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">complex64</span><span class="pun">)</span><span class="pln">
    </span><span class="typ">Xi</span><span class="pun">.</span><span class="pln">shape </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Yi</span><span class="pun">.</span><span class="pln">shape </span><span class="pun">=</span><span class="pln"> C</span><span class="pun">.</span><span class="pln">shape </span><span class="pun">=</span><span class="pln"> xn</span><span class="pun">*</span><span class="pln">yn

    Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">complex64</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">itermax</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">break</span><span class="pln">

        </span><span class="com"># Compute for relevant points only</span><span class="pln">
        np</span><span class="pun">.</span><span class="pln">multiply</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">,</span><span class="pln"> Z</span><span class="pun">,</span><span class="pln"> Z</span><span class="pun">)</span><span class="pln">
        np</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">,</span><span class="pln"> C</span><span class="pun">,</span><span class="pln"> Z</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># Failed convergence</span><span class="pln">
        I </span><span class="pun">=</span><span class="pln"> abs</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> horizon
        N_</span><span class="pun">[</span><span class="typ">Xi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">],</span><span class="pln"> </span><span class="typ">Yi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">+</span><span class="lit">1</span><span class="pln">
        Z_</span><span class="pun">[</span><span class="typ">Xi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">],</span><span class="pln"> </span><span class="typ">Yi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># Keep going with those who have not diverged yet</span><span class="pln">
        np</span><span class="pun">.</span><span class="pln">negative</span><span class="pun">(</span><span class="pln">I</span><span class="pun">,</span><span class="pln">I</span><span class="pun">)</span><span class="pln">
        Z </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln">
        </span><span class="typ">Xi</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Yi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Xi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">],</span><span class="pln"> </span><span class="typ">Yi</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln">
        C </span><span class="pun">=</span><span class="pln"> C</span><span class="pun">[</span><span class="pln">I</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> Z_</span><span class="pun">.</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> N_</span><span class="pun">.</span><span class="pln">T</span></pre>

<p>
	وتصبح النتيجة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_51" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"mandelbrot_numpy_2(xmin, xmax, ymin, ymax, xn, yn, maxiter)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">510</span><span class="pln"> msec per loop</span></pre>

<h3>
	إظهار النتائج
</h3>

<p>
	من أجل تصور نتائجنا يمكننا عرض المصفوفة N مباشرةً باستخدام الأمر <code>imshow</code> من مكتبة matplotlib ولكن هذا سينتج صورة مخططة banded وهي نتيجة معروفة لخوارزمية عد الهروب escape count المستخدمة. يمكن التخلص من هذا الربط من خلال حساب الهروب الجزئي وذلك عن طريق قياس مدى هبوط النقطة المتكررة خارج حدود قطع الهروب. فيما يلي صورة للنتيجة، إذ استخدمنا التسوية الطبيعية recount normalization، وأضفنا خريطة ألوان طبيعية (gamma=0.3) إضافةً إلى تظليل فاتح.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113738" href="https://academy.hsoub.com/uploads/monthly_2022_12/639847524642a_03_.PNG.4f5bf98fd3b674ce38b1696012b509c5.PNG" rel=""><img alt="إظهار نتائج المصفوفة N" class="ipsImage ipsImage_thumbnailed" data-fileid="113738" data-unique="3dj1vezli" src="https://academy.hsoub.com/uploads/monthly_2022_12/63984755cc9a1_03_.thumb.PNG.d0d48b8c35c659bf49d1aa767ad68e44.PNG" style="width: 500px; height: auto;"></a>
</p>

<h3>
	تمرين
</h3>

<p>
	نريد الآن قياس البعد الكسري لمجموعة ماندلبورت Mandelbrot باستخدام بُعد <a href="https://en.wikipedia.org/wiki/Minkowski%E2%80%93Bouligand_dimension" rel="external nofollow">Minkowski–Bouligand dimension</a>، ولفعل ذلك نحتاج إلى حسابات لمربع بأبعاد متناقص، كما هو موضح في لقطة الشاشة التالية، وكما تتوقع لا يمكننا استخدام تعليمات بايثون العادية لأنها ستكون بطيئة جدًا. الهدف من التمرين هو كتابة دالة باستخدام NumPy تأخذ مصفوفة عشرية ثنائية الأبعاد وتُرجع البعد. ينبغي توحيد القيم الموجودة في المصفوفة بين 0 و1.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113739" href="https://academy.hsoub.com/uploads/monthly_2022_12/63984758a05e2_04.PNG.78060c80ea79ecc9eea70d41c06be501.PNG" rel=""><img alt="قياس البعد الكسري لمجموعة ماندلبورت Mandelbrot" class="ipsImage ipsImage_thumbnailed" data-fileid="113739" data-unique="f84kzw46v" src="https://academy.hsoub.com/uploads/monthly_2022_12/63984758a05e2_04.PNG.78060c80ea79ecc9eea70d41c06be501.PNG" style="width: 550px; height: auto;"></a>
</p>

<h2>
	المتجهات المكانية
</h2>

<p>
	تشير المتجهات المكانية إلى الحالة التي تشارك فيها العناصر نفس الحساب ولكنها تتفاعل مع مجموعة فرعية فقط من العناصر الأخرى، وكانت هذه الحالة موجودةٌ فعلًا في لعبة الحياة، ولكن في بعض المواقف هناك صعوبة إضافية لأن المجموعة الفرعية ديناميكية وتحتاج إلى التحديث في كل تكرار؛ فمثلًا في أنظمة الجسيمات تتفاعل الجسيمات غالبًا مع الجيران المحليين، وينطبق هذا أيضًا على حالة "boids" التي تحاكي سلوكيات السرب flocking.
</p>

<h3>
	برنامج Boids
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113740" href="https://academy.hsoub.com/uploads/monthly_2022_12/05boids.jpg.920ebbe46174e89df7d5e2afb6e7849b.jpg" rel=""><img alt="حالة boids لمحاكاة سلوكيات السرب flocking" class="ipsImage ipsImage_thumbnailed" data-fileid="113740" data-unique="9s47909ev" src="https://academy.hsoub.com/uploads/monthly_2022_12/05boids.thumb.jpg.14ab3738fae644a8c39491c738a90c7a.jpg" style="width: 600px; height: auto;"></a>
</p>

<p style="text-align: center;">
	الطيور المتدفقة هي مثال على التنظيم الذاتي في علم الأحياء. صورة <a href="https://commons.wikimedia.org/wiki/File:Fugle,_%C3%B8rns%C3%B8_073.jpg" rel="external nofollow">Christoffer A Rasmussen</a>، 2012.
</p>

<p>
	يُعد Boids برنامج حياة اصطناعية طُور بواسطة كريج رينولدز Craig Reynolds في عام 1986 وهو يحاكي سلوك سرب الطيور. اسم Boid هو اختصار إلى " bird-oid object" والذي يشير إلى كائن يمثل الطيور.
</p>

<p>
	كما هو الحال مع معظم برامج محاكاة الحياة الاصطناعية، فإن Boids هو مثال على السلوك الناشئ، أي أن تعقيد Boids ينشأ من تفاعل العوامل الفردية والالتزام بمجموعة من القواعد البسيطة. القواعد المطبقة في عالم Boids هي كما يلي:
</p>

<ul>
<li>
		الانفصال separation: إرشاد لتجنب ازدحام رفاق السرب المحليين.
	</li>
	<li>
		المحاذاة alignment: إرشاد نحو متوسط اتجاه رفاق السرب المحليين.
	</li>
	<li>
		التماسك cohesion: الإرشاد للتحرك نحو متوسط الموضع (مركز الكتلة) للرفاق الحاليين.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113741" href="https://academy.hsoub.com/uploads/monthly_2022_12/6398475be61df_06.PNG.405fe10acf7f0984ed493f7b12ba8b18.PNG" rel=""><img alt="القواعد الثلاث المطبقة في عالم Boids" class="ipsImage ipsImage_thumbnailed" data-fileid="113741" data-unique="20x3hd4xf" src="https://academy.hsoub.com/uploads/monthly_2022_12/6398475be61df_06.PNG.405fe10acf7f0984ed493f7b12ba8b18.PNG" style="width: 600px; height: auto;"></a>
</p>

<h3>
	تنفيذ الشيفرة باستخدام تعليمات بايثون العادية
</h3>

<p>
	نظرًا لأن كل boid هو كيان مستقل له العديد من الخاصيات، مثل الموضع والسرعة فمن الطبيعي أن نبدأ بكتابة الصنف <code>Boid</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_59" style="">
<span class="kwd">import</span><span class="pln"> math
</span><span class="kwd">import</span><span class="pln"> random
</span><span class="kwd">from</span><span class="pln"> vec2 </span><span class="kwd">import</span><span class="pln"> vec2

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Boid</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">position </span><span class="pun">=</span><span class="pln"> vec2</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">
        angle </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">math</span><span class="pun">.</span><span class="pln">pi</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">velocity </span><span class="pun">=</span><span class="pln"> vec2</span><span class="pun">(</span><span class="pln">math</span><span class="pun">.</span><span class="pln">cos</span><span class="pun">(</span><span class="pln">angle</span><span class="pun">),</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sin</span><span class="pun">(</span><span class="pln">angle</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">acceleration </span><span class="pun">=</span><span class="pln"> vec2</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span></pre>

<p>
	الكائن <code>vec2</code> هو صنف بسيط جدًا يتعامل مع جميع عمليات المتجه الشائعة بمكونين، وهذا سيوفر علينا بعض الكتابة في صنف <code>Boid</code> الرئيسي. يوجد بعض حزم المتجهات في فهرس حزمة Python، ولكن استخدامها سيكون مبالغة في مثل هذا المثال البسيط.
</p>

<p>
	يُعد السرب حالةً صعبة لبايثون العادية لأنه يتفاعل مع الجيران المحليين، ومع ذلك ونظرًا لأن أسراب الطيور تتحرك فإن العثور على مثل هؤلاء الجيران المحليين يتطلب حسابات في كل مرة تقطع المسافة إلى سرب طيور آخر لفرز تلك الطيور الموجودة في نصف قطر تفاعل معين، وبالتالي تكون الطريقة النموذجية لكتابة القواعد الثلاثة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_61" style="">
<span class="kwd">def</span><span class="pln"> separation</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> boids</span><span class="pun">):</span><span class="pln">
    count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> other </span><span class="kwd">in</span><span class="pln"> boids</span><span class="pun">:</span><span class="pln">
        d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">position </span><span class="pun">-</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">position</span><span class="pun">).</span><span class="pln">length</span><span class="pun">()</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> d </span><span class="pun">&lt;</span><span class="pln"> desired_separation</span><span class="pun">:</span><span class="pln">
            count </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="pun">...</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> count </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">

 </span><span class="kwd">def</span><span class="pln"> alignment</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> boids</span><span class="pun">):</span><span class="pln"> </span><span class="pun">...</span><span class="pln">
 </span><span class="kwd">def</span><span class="pln"> cohesion</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> boids</span><span class="pun">):</span><span class="pln"> </span><span class="pun">…</span></pre>

<p>
	لإكمال الصورة، يمكننا أيضًا إنشاء كائن <code>Flock</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_63" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Flock</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> count</span><span class="pun">=</span><span class="lit">150</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">boids </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">count</span><span class="pun">):</span><span class="pln">
            boid </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Boid</span><span class="pun">()</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">boids</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">boid</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> run</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> boid </span><span class="kwd">in</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">boids</span><span class="pun">:</span><span class="pln">
            boid</span><span class="pun">.</span><span class="pln">run</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">boids</span><span class="pun">)</span></pre>

<p>
	يمكن أن نحصل باستخدام هذا النهج على ما يصل إلى 50 سربًا حتى يصبح وقت الحساب بطيئًا جدًا للحصول على رسم متحرك سلس. سنحصل بالاعتماد على مكتبة Numpy على أداء أفضل بكثير، ولكن قبل الانتقال إلى استخدام هذه المكتبة سنشير إلى المشكلة الرئيسية الموجودة في شيفرات بايثون السابقة؛ فكما تلاحظ يوجد في الشيفرات الكثير من التكرار، أي بتعبير أدق نحن لا نستغل حقيقة أن المسافة الإقليدية انعكاسية أي: <code>|x − y| = |y − x|</code>.
</p>

<p>
	والحقيقة أن كل دالة تحسب "n<sup>2</sup>" مسافة بينما حساب مسافة "n<sup>2</sup>/2" كافي، إذا خُزّنت تخزينًا مؤقتًا بطريقة صحيحة. وأيضًا تعيد كل قاعدة حساب كل مسافة دون تخزين نتيجة الدوال الأخرى تخزينًا مؤقتًا، وفي النهاية، نكون قد حسبنا "3n<sup>2</sup>" مسافة بدلًا من "n<sup>2</sup>/2".
</p>

<h3>
	كتابة الشيفرة باستخدام مكتبة NumPy
</h3>

<p>
	تتخذ كتابة الشيفرة باستخدام مكتبة Numpy نهجًا مختلفًا، سنجمع كل كائنات أسراب الطيور boids في مصفوفة الموضع ومصفوفة السرعة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_65" style="">
<span class="pln">n </span><span class="pun">=</span><span class="pln"> </span><span class="lit">500</span><span class="pln">
velocity </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
position </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">),</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span></pre>

<p>
	الخطوة الأولى هي حساب الجيران لكل كائنات boids، ولذلك نحتاج إلى حساب المسافات المزدوجة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_67" style="">
<span class="pln">dx </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">subtract</span><span class="pun">.</span><span class="pln">outer</span><span class="pun">(</span><span class="pln">position</span><span class="pun">[:,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">],</span><span class="pln"> position</span><span class="pun">[:,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">])</span><span class="pln">
dy </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">subtract</span><span class="pun">.</span><span class="pln">outer</span><span class="pun">(</span><span class="pln">position</span><span class="pun">[:,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">],</span><span class="pln"> position</span><span class="pun">[:,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">])</span><span class="pln">
distance </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">hypot</span><span class="pun">(</span><span class="pln">dx</span><span class="pun">,</span><span class="pln"> dy</span><span class="pun">)</span></pre>

<p>
	كان بإمكاننا استخدام دالة <code>scipy cdist</code> لكننا سنحتاج إلى المصفوفتين <code>dx</code> و <code>dy</code> لاحقًا، وبمجرد حسابها سيكون من الأسرع استخدام تابع <code>hypot</code>. لاحظ شكل المسافة (n,n) وكل خط يرتبط بكائن boid واحد، أي أن كل سطر يعطي المسافة إلى جميع كائنات boids الأخرى.
</p>

<p>
	يمكننا الآن حساب الجيران من هذه المسافات وفقًا للقواعد الثلاثة، مستفيدين من إمكانية دمجها معًا. يمكننا حساب قناع للمسافة والذي يكون موجبًا تمامًا (أي ليس له ارتباط ذاتي)، ثم جداء هذا القناع مع أقنعة المسافات الأخرى.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_69" style="">
<span class="pln">mask_0 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">distance </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
mask_1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">distance </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pun">)</span><span class="pln">
mask_2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">distance </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">50</span><span class="pun">)</span><span class="pln">
mask_1 </span><span class="pun">*=</span><span class="pln"> mask_0
mask_2 </span><span class="pun">*=</span><span class="pln"> mask_0
mask_3 </span><span class="pun">=</span><span class="pln"> mask_2</span></pre>

<p>
	<strong>ملاحظة:</strong> إذا افترضنا أن أسراب الطيور boids لا يمكن أن تحتل نفس الموضع، فكيف يمكن حساب <code>mask_0</code> بفعالية أكثر؟
</p>

<p>
	ثم نحسب عدد الجيران داخل نصف القطر المحدد ونتأكد من أنه 1 على الأقل لتجنب القسمة على الصفر.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_71" style="">
<span class="pln">mask_1_count </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">mask_1</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
mask_2_count </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">maximum</span><span class="pun">(</span><span class="pln">mask_2</span><span class="pun">.</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
mask_3_count </span><span class="pun">=</span><span class="pln"> mask_2_count</span></pre>

<p>
	الآن، سنكتب القواعد الثلاث:
</p>

<h4>
	المحاذاة
</h4>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_73" style="">
<span class="com"># حساب متوسط السرعة للجيران المحليين</span><span class="pln">
target </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">dot</span><span class="pun">(</span><span class="pln">mask</span><span class="pun">,</span><span class="pln"> velocity</span><span class="pun">)/</span><span class="pln">count</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">

</span><span class="com"># توحيد النتيجة</span><span class="pln">
norm </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">((</span><span class="pln">target</span><span class="pun">*</span><span class="pln">target</span><span class="pun">).</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">)).</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">divide</span><span class="pun">(</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> norm</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> where</span><span class="pun">=</span><span class="pln">norm </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="com"># المحاذاة بسرعة ثابتة</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> max_velocity

</span><span class="com"># الناتج steering  حساب مسار الإرشاد</span><span class="pln">
alignment </span><span class="pun">=</span><span class="pln"> target </span><span class="pun">-</span><span class="pln"> velocity</span></pre>

<h4>
	التماسك
</h4>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_75" style="">
<span class="com"># حساب مركز الجاذبية للجيران المحليين</span><span class="pln">
center </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">dot</span><span class="pun">(</span><span class="pln">mask</span><span class="pun">,</span><span class="pln"> position</span><span class="pun">)/</span><span class="pln">count</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">

</span><span class="com"># حساب الاتجاه إلى المركز</span><span class="pln">
target </span><span class="pun">=</span><span class="pln"> center </span><span class="pun">-</span><span class="pln"> position

</span><span class="com"># توحيد النتيجة</span><span class="pln">
norm </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">((</span><span class="pln">target</span><span class="pun">*</span><span class="pln">target</span><span class="pun">).</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">)).</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">divide</span><span class="pun">(</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> norm</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> where</span><span class="pun">=</span><span class="pln">norm </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="com"># (max_velocity) التماسك بسرعة ثابتة</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> max_velocity

</span><span class="com"># الناتج steering حساب مسار الإرشاد</span><span class="pln">
cohesion </span><span class="pun">=</span><span class="pln"> target </span><span class="pun">-</span><span class="pln"> velocity</span></pre>

<h4>
	الانفصال
</h4>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_77" style="">
<span class="com"># حساب قوة التنافر من الجيران المحليين</span><span class="pln">
repulsion </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">dstack</span><span class="pun">((</span><span class="pln">dx</span><span class="pun">,</span><span class="pln"> dy</span><span class="pun">))</span><span class="pln">

</span><span class="com"># تتناسب القوة عكسيًا مع المسافة</span><span class="pln">
repulsion </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">divide</span><span class="pun">(</span><span class="pln">repulsion</span><span class="pun">,</span><span class="pln"> distance</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)**</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">repulsion</span><span class="pun">,</span><span class="pln">
                      where</span><span class="pun">=</span><span class="pln">distance</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="com"># حساب الاتجاه بعيدًا عن الآخرين</span><span class="pln">
target </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">repulsion</span><span class="pun">*</span><span class="pln">mask</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)).</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">)/</span><span class="pln">count</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">

</span><span class="com"># توحيد النتيجة</span><span class="pln">
norm </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">((</span><span class="pln">target</span><span class="pun">*</span><span class="pln">target</span><span class="pun">).</span><span class="pln">sum</span><span class="pun">(</span><span class="pln">axis</span><span class="pun">=</span><span class="lit">1</span><span class="pun">)).</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">divide</span><span class="pun">(</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> norm</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> where</span><span class="pun">=</span><span class="pln">norm </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="com"># (max_velocity) الانفصال بسرعة ثابتة</span><span class="pln">
target </span><span class="pun">*=</span><span class="pln"> max_velocity

</span><span class="com"># الناتج steering حساب مسار الإرشاد</span><span class="pln">
separation </span><span class="pun">=</span><span class="pln"> target </span><span class="pun">-</span><span class="pln"> velocity</span></pre>

<p>
	يجب أن تكون مسارات الإرشاد الثلاث الناتجة (الانفصال والمحاذاة والتماسك) محدودةً من حيث الحجم. وسنترك لك الدمج بين هذه القواعد.
</p>

<p>
	التحديث الناتج للسرعة والموضع:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_79" style="">
<span class="pln">acceleration </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1.5</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> separation </span><span class="pun">+</span><span class="pln"> alignment </span><span class="pun">+</span><span class="pln"> cohesion
velocity </span><span class="pun">+=</span><span class="pln"> acceleration
position </span><span class="pun">+=</span><span class="pln"> velocity</span></pre>

<p>
	أخيرًا نتخيل النتيجة باستخدام مخطط مبعثر scatter موجه مخصص.
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe allowfullscreen="" frameborder="0" height="506" width="900" src="https://player.vimeo.com/video/778409656?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0"></iframe>
	</div>
</div>

<p>
	Boids هو برنامج حياة اصطناعية، طُوِّر بواسطة Craig Reynolds في عام 1986، والذي يحاكي سلوك الطيور المتدفقة.
</p>

<h3>
	تمرين
</h3>

<p>
	نحن الآن جاهزون لعرض أسراب الطيور boids، وأسهل طريقة لذلك هي استخدام دالة الرسوم المتحركة <code>matplotlib</code> ومخطط مبعثر. لسوء الحظ لا يمكننا توجيه التبعثر بطريقة فردية ونحتاج إلى صنع كائنات خاصة باستخدام توابع <code>PathCollection</code> العائد للدالة <code>matplotlib</code>. يمكن تعريف مسار المثلث البسيط كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_81" style="">
<span class="pln">v</span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">([(-</span><span class="lit">0.25</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.25</span><span class="pun">),</span><span class="pln">
             </span><span class="pun">(</span><span class="pln"> </span><span class="lit">0.00</span><span class="pun">,</span><span class="pln">  </span><span class="lit">0.50</span><span class="pun">),</span><span class="pln">
             </span><span class="pun">(</span><span class="pln"> </span><span class="lit">0.25</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.25</span><span class="pun">),</span><span class="pln">
             </span><span class="pun">(</span><span class="pln"> </span><span class="lit">0.00</span><span class="pun">,</span><span class="pln">  </span><span class="lit">0.00</span><span class="pun">)])</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">array</span><span class="pun">([</span><span class="typ">Path</span><span class="pun">.</span><span class="pln">MOVETO</span><span class="pun">,</span><span class="pln">
              </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">LINETO</span><span class="pun">,</span><span class="pln">
              </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">LINETO</span><span class="pun">,</span><span class="pln">
              </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">CLOSEPOLY</span><span class="pun">])</span></pre>

<p>
	يمكن تكرار هذا المسار عدة مرات داخل المصفوفة ويمكن جعل كل مثلث مستقلاً.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_83" style="">
<span class="pln">n </span><span class="pun">=</span><span class="pln"> </span><span class="lit">500</span><span class="pln">
vertices </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">tile</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> n</span><span class="pun">).</span><span class="pln">reshape</span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
codes </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">tile</span><span class="pun">(</span><span class="pln">c</span><span class="pun">.</span><span class="pln">reshape</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> n</span><span class="pun">)</span></pre>

<p>
	لدينا الآن مصفوفة (n, 4, 2) ومجموعة (n, 4) للشيفرات التي تمثل عدد <code>n</code> من boids. نحن مهتمون بمعالجة مصفوفة <code>vertices</code> لتعكس الترجمة والقياس والدوران لكل كائنات boids.
</p>

<p>
	كيف يمكن أن تكتب وظائف الترجمة والقياس والتدوير؟
</p>

<h2>
	الخلاصة
</h2>

<p>
	درسنا من خلال هذه الأمثلة الثلاثة ثلاثة أشكال لاستخدام المتجهات في الشيفرات:
</p>

<ul>
<li>
		المتجهات الموحدة، إذ تشترك العناصر في نفس الحساب دون قيد أو شرط وللمدة نفسها.
	</li>
	<li>
		المتجهات الزمانية، إذ تشترك العناصر في نفس الحساب ولكنها تتطلب عددًا مختلفًا من التكرارات.
	</li>
	<li>
		المتجهات المكانية، إذ تشترك العناصر في نفس الحساب ولكن على الوسطاء المكانية الديناميكية.
	</li>
</ul>
<p>
	ومن المحتمل أن يكون هناك العديد من أشكال متجهات الشيفرات. كما أوضحنا سابقًا يعد هذا النوع من المتجهات من أبسط الأنواع على الرغم من أننا رأينا أنه من الصعب حقًا تنفيذه ويتطلب بعض الخبرة أو بعض المساعدة أو كليهما.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://www.labri.fr/perso/nrougier/from-python-to-numpy/#code-vectorization" rel="external nofollow">Code vectorization</a> من كتاب From Python to Numpy لصاحبه Nicolas P. Rougier.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/" rel="">مفاهيم متقدمة حول مكتبة NumPy في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1819</guid><pubDate>Tue, 13 Dec 2022 10:14:39 +0000</pubDate></item><item><title>&#x645;&#x643;&#x62A;&#x628;&#x627;&#x62A; &#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; template libraries &#x627;&#x644;&#x645;&#x633;&#x62A;&#x639;&#x645;&#x644;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-template-libraries-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%B9%D9%85%D9%84%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1798/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_11/63789c1188140_----Python.png.0ee4a0af059a7ce94ac3e13689abaa74.png" /></p>

<p>
	محركات قوالب بايثون templating engine هي أدوات قوية للغاية تساعد المطورين على بناء تطبيقات ويب و<a href="https://academy.hsoub.com/apps/web/10-%D9%85%D8%B9%D8%A7%D9%8A%D9%8A%D8%B1-%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89-cms-r170/" rel="">أنظمة إدارة محتوى</a> كاملة وإنشاء تقارير ورسوم بيانية من مجموعة بيانات، ولا ينحصر استخدامها في مشاريع معقدة بل يمكن الاستفادة منها في مشاريع بسيطة أيضًا، لذا إن كنت تعمل على مشروع <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون Python</a> يحتاج إلى محرك قوالب لإنشاء صفحات <a href="https://academy.hsoub.com/programming/html/%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-html-r1702/" rel="">HTML</a> تلقائيًا، سيساعدك هذا المقال ببساطة على اختيار المكتبة الأنسب لك.
</p>

<p>
	نُشر استبيان يتضمن السؤال التالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"ما مكتبة قوالب بايثون التي تفضل استخدامها؟"
	</p>
</blockquote>

<p>
	وصلت الإجابات إلى 1644 إجابة وتظهر التفاصيل كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="112537" href="https://academy.hsoub.com/uploads/monthly_2022_11/63789c0e78b48_.PNG.c7ccf611d627300c2acd48d7ada8794e.PNG" rel=""><img alt="مكتبة بايثون" class="ipsImage ipsImage_thumbnailed" data-fileid="112537" data-unique="0cby0ifx9" src="https://academy.hsoub.com/uploads/monthly_2022_11/63789c0fa0389_.thumb.PNG.d2706bc31f533af5092c1f9ddc2fa84d.PNG" style="width: 700px; height: auto;"></a>
</p>

<p>
	وأشار شخص ما إلى تجربته مع مكتبات قوالب بايثون بتوفير وقت كبير بأتمتة بعض أعماله التي كانت تتطلب قضاء الكثير من الوقت بالاعتماد على النسخ واللصق من عدة مصادر وعرضها في في صفحة واحدة بنموذج موحد وهذه العملية كما ذكر تأخذ وقتًا كبيرًا ومعرضة للخطأ.
</p>

<h2>
	أهمية القوالب ومحرك القوالب templating engine
</h2>

<p>
	سنوضح فكرة القوالب من خلال الاستعانة بمثال لشخص يرغب بإنشاء صفحة صغيرة تتضمن جميع مقالات بايثون التي كتب عنها مؤخرًا والشيفرة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4838_12" style="">
<span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">My Python articles</span><span class="tag">&lt;/title&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;p&gt;</span><span class="pln">These are some of the things I have written about Python:</span><span class="tag">&lt;/p&gt;</span><span class="pln">
    </span><span class="tag">&lt;ul&gt;</span><span class="pln">
      </span><span class="tag">&lt;li&gt;</span><span class="pln">Python GUIs</span><span class="tag">&lt;/li&gt;</span><span class="pln">
      </span><span class="tag">&lt;li&gt;</span><span class="pln">Python IDEs</span><span class="tag">&lt;/li&gt;</span><span class="pln">
      </span><span class="tag">&lt;li&gt;</span><span class="pln">Python web scrapers</span><span class="tag">&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
  </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	تعتبر هذه الشيفرة كافية لعدد محدود من المقالات، ولكن عندما يرغب الكاتب بإجراء تعديل مثل إضافة مقال آخر أو عدد كبير من المقالات الإضافية سيحتاج لكتابة شيفرة هذه الصفحة يدويًا والذي يعد نشاطًا مُرهقًا ومضيعة للوقت.
</p>

<p>
	يمكن بدلًا من ذلك إنشاؤها من ملف CSV أو ملف بيانات آخر يحتوي على قائمة بجميع الصفحات التي يرغب بإضافتها، ثم إنشاء نسخ مكررة من هذا بسهولة مع إمكانية إجراء تغييرات عديدة مثل عنوان الملف أو عنوان الصفحة أو أجزاء من النص أو النص بالكامل، وتتم كل هذه العمليات برمجيًا وذلك باستخدام محرك القوالب.
</p>

<h2>
	محركات القوالب المستخدمة في بايثون
</h2>

<p>
	تتوفر خيارات عديدة وتختلف كل أداة من أدوات القوالب قليلًا عن الأخرى وينبغي قراءة التوثيق لفهم الاستخدام الدقيق لها، وسنذكر ثلاثة منها دون تفضيل إحداها عن الأخرى وهي:
</p>

<ul>
<li>
		<a href="https://www.makotemplates.org/" rel="external nofollow">Mako</a>
	</li>
	<li>
		<a href="https://jinja.palletsprojects.com/en/3.1.x/" rel="external nofollow">Jinja2</a>
	</li>
	<li>
		<a href="https://genshi.edgewall.org/" rel="external nofollow">Genshi</a>
	</li>
</ul>
<h3>
	أداة Mako
</h3>

<p>
	تتميز أداة القوالب Mako بالقوة والبساطة وسهولة الاستخدام حيث تتيح تصميم القوالب باستخدام عدد قليل فقط من التعليمات البرمجية.
</p>

<p>
	تعتبر غنية بالميزات مثل وجود المرشحات filters والوراثة والكتل القابلة للاستدعاء ونظام التخزين المؤقت المدمج، ويمكن تضمين جميع هذه الميزات في مشاريع الويب الضخمة أو المعقدة، ولها <a href="https://docs.makotemplates.org/en/latest/" rel="external nofollow">توثيق جيد</a>، كما أنها تتميز بسرعة أدائها على عكس Jinja2.
</p>

<p>
	تعد Mako لغة القوالب الافتراضية لأطر الويب مثل Pyramid و Pylons واستخدمت في موقع Reddit لعرض صفحات الويب الخاصة به، وتدعم كلاً من الإصدار 2 والإصدار 3 من بايثون، وتم إصدارها بموجب ترخيص MIT.
</p>

<h3>
	Jinja2
</h3>

<p>
	يعد Jinja2 خيارًا آخر سريع وغني بالميزات، فهو متاح لكل من الإصدار 2 والإصدار 3 من بايثون بموجب ترخيص BSD، ويستخدمه كل من Mozilla و SourceForge و NPR و Instagram وغيرها لامتلاكه مزايا عديدة.
</p>

<p>
	من مزاياه خاصية تهريب وسوم HTML ووضع الحماية sandboxing ووراثة القالب والقدرة على تطبيق وضع الحماية على أجزاء فقط من القوالب، بالإضافة إلى تجميع القوالب الخاصة بالمستخدم إلى شيفرة محمولة bytecode، كما يمتلك <a href="https://jinja.palletsprojects.com/en/2.10.x/" rel="external nofollow">توثيقًا قويًا</a>.
</p>

<p>
	يستخدم Jinja2 تركيب الجملة الخاص به على عكس Mako الذي يجعل القوالب الخاصة بك تستخدم منطق لغة بايثون البرمجي، ومع ذلك يتشابه Jinja2 مع Mako بالكثير من المزايا، أما تفضيل أحدهما على الآخر يكون تبعًا لنمط التنسيق الذي يفضله المستخدم.
</p>

<h3>
	Genshi
</h3>

<p>
	يعتبر <a href="https://genshi.edgewall.org/" rel="external nofollow">Genshi</a> أداة XML ذات محرك قوالب قوي مناسبة للعمل مع بيانات بتنسيق XML أو HTML (والذي هو نوع من XML أصلًا)، كما تتيح العمل بتنسيقات مغايرة لتنسيق <a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-r572/" rel="">صفحة الويب</a>، يتوفر Genshi بموجب ترخيص BSD ويدعم الإصدار 2 والإصدار 3 من بايثون.
</p>

<h2>
	مثال على استخدام مكتبة قوالب
</h2>

<p>
	لنعيد صياغة المثال السابق، فبدلًا من تحديث ملف HTML في كل مرة يكتب فيها عن موضوع جديد يمكن تحديثه برمجيًا، ويكون النموذج كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4838_15" style="">
<span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">My Python articles</span><span class="tag">&lt;/title&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;p&gt;</span><span class="pln">These are some of the things I have written about Python:</span><span class="tag">&lt;/p&gt;</span><span class="pln">
    </span><span class="tag">&lt;ul&gt;</span><span class="pln">
      %for topic in topics:
      </span><span class="tag">&lt;li&gt;</span><span class="pln">${topic}</span><span class="tag">&lt;/li&gt;</span><span class="pln">
      %endfor
    </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
  </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	وبعد ذلك يمكن تكرار كل موضوع من خلال مكتبة القوالب المستخدمة وهي Mako في هذا المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4838_19" style="">
<span class="kwd">from</span><span class="pln"> mako</span><span class="pun">.</span><span class="pln">template </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Template</span><span class="pln">

mytemplate </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Template</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">=</span><span class="str">'template.txt'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">mytemplate</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">topics</span><span class="pun">=(</span><span class="str">"Python GUIs"</span><span class="pun">,</span><span class="str">"Python IDEs"</span><span class="pun">,</span><span class="str">"Python web scrapers"</span><span class="pun">)))</span></pre>

<p>
	وبالطبع لا يتم في الواقع سرد المحتويات يدويًا في متغير بل يتم سحبها من مصدر بيانات خارجي مثل قاعدة بيانات أو <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-api%D8%9F-r1512/" rel="">واجهة برمجة تطبيقات</a>.
</p>

<p>
	يوجد الكثير من خيارات محركات قوالب بايثون المُساعدة على إنشاء النماذج في مختلف أنواع المشاريع، لذا يمكن الاطلاع على القائمة الكاملة من توثيق <a href="https://wiki.python.org/moin/Templating" rel="external nofollow">Python wiki</a> الرسمي واختيار المناسب منها ولكن عمومًا فقد ذكرنا لك أشهر مكتبات القوالب استخدامًا والتي سيكون اختيارك غالبًا محصورًا ضمنها.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/resources/python/template-libraries" rel="external nofollow">3 Python template libraries compared</a> لصاحبه Jason Baker.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
	<li>
		النسخة الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1798</guid><pubDate>Sat, 19 Nov 2022 09:28:47 +0000</pubDate></item><item><title>&#x645;&#x641;&#x627;&#x647;&#x64A;&#x645; &#x645;&#x62A;&#x642;&#x62F;&#x645;&#x629; &#x62D;&#x648;&#x644; &#x645;&#x643;&#x62A;&#x628;&#x629; NumPy &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28db9f6a_----Numpy---Python.png.3414bb2745c1262f71be6095e8f88ea3.png" /></p>

<p>
	تُعد مكتبة NumPy إحدى مكتبات <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">لغة بايثون Python</a> وتُستخدم للتعامل مع المصفوفات، وتهدف إلى توفير كائن مصفوفة أسرع بما يصل إلى 50 مرة من قوائم <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون</a> التقليدية.
</p>

<p>
	يطلق على كائن المصفوفة في مكتبة NumPy اسم ndarray، ويوفر العديد من الوظائف الداعمة التي تجعل التعامل مع المصفوفات أمرًا سهلًا جدًا.
</p>

<p>
	تعتمد مكتبة NumPy على العمليات على المتجهات vectorization، فإذا كنت معتادًا على التعامل مع لغة بايثون، فهذه هي الصعوبة الرئيسية التي ستواجهها لأنك ستحتاج إلى تغيير طريقة تفكيرك، كما ستتغير نوع العناصر التي ستستخدمها.
</p>

<p>
	أكثر العناصر شيوعًا في مكتبة NumPy هي المتجهات vectors والمصفوفات arrays والعروض views والدوال العمومية ufuns.
</p>

<p>
	هذا المقال جزء من سلسلة متقدمة حول NumPy وإليك كامل روابط السلسلة:
</p>

<ul>
<li>
		مفاهيم متقدمة حول مكتبة NumPy في <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>
	</li>
	<li>
		استخدام المتجهات vectorization في لغة بايثون مع مكتبة NumPy
	</li>
	<li>
		الاعتماد على المتجهات في حل المشاكل باستعمال مكتبة NumPy في بايثون
	</li>
	<li>
		تخصيص أسلوب المتجهات Custom vectorization عبر استعمال مكتبة NumPy
	</li>
	<li>
		ما بعد مكتبة NumPy في بايثون
	</li>
</ul>
<h2>
	مثال بسيط
</h2>

<p>
	سنأخذ مثالًا بسيطًا وهو المشي العشوائي random walk، إذ يتوجب علينا في الطريقة التقليدية المعتمدة على <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-r1375/" rel="">البرمجة كائنية التوجه <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></a> تعريف صنف class يأخذ الاسم <code>RandomWalker</code>، ثم إنشاء التابع <code>walk</code> لإرجاع الموقع الحالي بعد كل خطوة عشوائية. يمكن تنفيذ هذا المثال باستخدام التعليمات البرمجية التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_19" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">RandomWalker</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">position </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> walk</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">position </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">n</span><span class="pun">):</span><span class="pln">
            </span><span class="kwd">yield</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">position
            self</span><span class="pun">.</span><span class="pln">position </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">random</span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

walker </span><span class="pun">=</span><span class="pln"> </span><span class="typ">RandomWalker</span><span class="pun">()</span><span class="pln">
walk </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">position </span><span class="kwd">for</span><span class="pln"> position </span><span class="kwd">in</span><span class="pln"> walker</span><span class="pun">.</span><span class="pln">walk</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)]</span></pre>

<p>
	وتعطي تجربة قياس السرعة النتيجة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_21" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> tools </span><span class="kwd">import</span><span class="pln"> timeit
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> walker </span><span class="pun">=</span><span class="pln"> </span><span class="typ">RandomWalker</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"[position for position in walker.walk(n=10000)]"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">10</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">15.7</span><span class="pln"> msec per loop</span></pre>

<h3>
	النهج الإجرائي Procedural approach
</h3>

<p>
	يمكننا لحل مثل هذه المشكلة البسيطة حفظ تعريف الصنف والتركيز على دالة المشي <code>walk</code> التي تحسب المواقع المتتالية بعد كل خطوة عشوائية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_23" style="">
<span class="kwd">def</span><span class="pln"> random_walk</span><span class="pun">(</span><span class="pln">n</span><span class="pun">):</span><span class="pln">
    position </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    walk </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">position</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">n</span><span class="pun">):</span><span class="pln">
        position </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">random</span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)-</span><span class="lit">1</span><span class="pln">
        walk</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">position</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> walk

walk </span><span class="pun">=</span><span class="pln"> random_walk</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span></pre>

<p>
	توفر هذه الطريقة من استهلاك <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D8%B1%D9%83%D8%B2%D9%8A%D8%A9-%D9%88%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%D9%8A%D8%A9-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8-r1716/" rel="">وحدة المعالجة المركزية CPU</a> ولكن ليس لحدٍ كبير لأنها تشبه الطريقة السابقة المعتمدة على البرمجة كائنية التوجه.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_26" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> tools </span><span class="kwd">import</span><span class="pln"> timeit
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"random_walk(n=10000)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">10</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">15.6</span><span class="pln"> msec per loop</span></pre>

<h3>
	النهج المعتمد على المتجهات Vectorized approach
</h3>

<p>
	يمكننا باستخدام وحدة <a href="https://docs.python.org/3.6/library/itertools.html" rel="external nofollow">itertools</a> تحسين الأداء بطريقة أفضل، إذ تقدم هذه الوحدة مجموعةً من الدوال لإنشاء تكرارات لحلقات فعالة. نلاحظ أن مثال المشي العشوائي ما هو إلا تراكم خطوات، لذلك سنعيد كتابة الدالة بإنشاء جميع الخطوات أولًا، ثم تجميعها بدون استخدام أي حلقة، كما توضح التعليمات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_28" style="">
<span class="kwd">def</span><span class="pln"> random_walk_faster</span><span class="pun">(</span><span class="pln">n</span><span class="pun">=</span><span class="lit">1000</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">from</span><span class="pln"> itertools </span><span class="kwd">import</span><span class="pln"> accumulate
    </span><span class="com"># Only available from Python 3.6</span><span class="pln">
    steps </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">choices</span><span class="pun">([-</span><span class="lit">1</span><span class="pun">,+</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> k</span><span class="pun">=</span><span class="pln">n</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]+</span><span class="pln">list</span><span class="pun">(</span><span class="pln">accumulate</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">))</span><span class="pln">

walk </span><span class="pun">=</span><span class="pln"> random_walk_faster</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span></pre>

<p>
	اعتمدنا في هذا المثال على المتجهات في الدالة، فبدلًا من استخدام التكرار لاختيار الخطوات وإضافتها إلى الموضع الحالي، أنشأنا أولًا جميع الخطوات دفعةً واحدةً، ثم استخدمنا دالة التجميع <a href="https://docs.python.org/3.6/library/itertools.html#itertools.accumulate" rel="external nofollow">accumulate</a> لحساب جميع المواضع. تخلصنا من الحلقة وبالتالي أصبح تنفيذ التعليمات أسرع:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_30" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> tools </span><span class="kwd">import</span><span class="pln"> timeit
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"random_walk_faster(n=10000)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">10</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.21</span><span class="pln"> msec per loop</span></pre>

<p>
	لاحظ أننا وفرنا 85% من وقت الحساب مقارنةً بالإصدار السابق، لكن الإيجابية التي تميز الإصدار الجديد هي تبسيط العمليات المعقدة على المتجهات. سنحتاج إلى استبدال أدوات <code>itertools</code> بأدوات <code>numpy</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_32" style="">
<span class="kwd">def</span><span class="pln"> random_walk_fastest</span><span class="pun">(</span><span class="pln">n</span><span class="pun">=</span><span class="lit">1000</span><span class="pun">):</span><span class="pln">
    </span><span class="com"># No 's' in numpy choice (Python offers choice &amp; choices)</span><span class="pln">
    steps </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">choice</span><span class="pun">([-</span><span class="lit">1</span><span class="pun">,+</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> n</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">cumsum</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">)</span><span class="pln">

walk </span><span class="pun">=</span><span class="pln"> random_walk_fastest</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">)</span></pre>

<p>
	هذه الطريقة سهلة وتوفر الكثير من الوقت كما توضح النتائج التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_277_34" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> tools </span><span class="kwd">import</span><span class="pln"> timeit
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"random_walk_fastest(n=10000)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> usec per loop</span></pre>

<p>
	يركز هذا الدليل يركز على الاعتماد على المتجهات سواءٌ كان ذلك على مستوى المشكلة أو الشيفرات البرمجية، وسنوضح أهمية هذا الاختلاف قبل الانتقال إلى دراسة المتجهات المخصصة.
</p>

<h2>
	سهولة القراءة مقابل السرعة
</h2>

<p>
	قبل الانتقال إلى القسم التالي، سنلقي نظرةً على مشكلة محتملة قد تواجهها بعد أن تصبح على دراية بمكتبة NumPy؛ فمكتبة NumPy مكتبة قوية جدًا ويمكنك أن تصنع العجائب بها، ولكن هذا على حساب سهولة القراءة، لذلك إذا أهملت إضافة التعليقات أثناء كتابة التعليمات البرمجية، فلن تتمكن من معرفة وظيفة بعض التعليمات بعد بضع أسابيع أو ربما أيام.
</p>

<p>
	على سبيل المثال هل يمكنك معرفة ما هي نتيجة تنفيذ الدالتين التاليتين؟ ربما ستتمكن من فهم الدالة الأولى ولكن من غير المرجح أن تفهم الثانية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_36" style="">
<span class="kwd">def</span><span class="pln"> function_1</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">i </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">sub</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> seq</span><span class="pun">[</span><span class="pln">i</span><span class="pun">:</span><span class="pln">i</span><span class="pun">+</span><span class="pln">len</span><span class="pun">(</span><span class="pln">sub</span><span class="pun">)]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> sub</span><span class="pun">]</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> function_2</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">):</span><span class="pln">
    target </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">dot</span><span class="pun">(</span><span class="pln">sub</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">)</span><span class="pln">
    candidates </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">where</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">correlate</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> mode</span><span class="pun">=</span><span class="str">'valid'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> target</span><span class="pun">)[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
    check </span><span class="pun">=</span><span class="pln"> candidates</span><span class="pun">[:,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">newaxis</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">sub</span><span class="pun">))</span><span class="pln">
    mask </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">all</span><span class="pun">((</span><span class="pln">np</span><span class="pun">.</span><span class="pln">take</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> check</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> sub</span><span class="pun">),</span><span class="pln"> axis</span><span class="pun">=-</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> candidates</span><span class="pun">[</span><span class="pln">mask</span><span class="pun">]</span></pre>

<p>
	استخدمت الدالة الثانية مكتبة NumPy وهي أسرع بعشر مرات، ولكن المشكلة هي بصعوبة قراءة وفهم التعليمات البرمجية التي تستخدمها.
</p>

<h2>
	تشريح المصفوفة
</h2>

<p>
	كما أوضحنا سابقًا ينبغي أن تكون لديك خبرةً أساسيةً في التعامل مع مكتبة NumPy قبل المتابعة في هذا الدليل، وإذا لم يكن لديك هذه الخبرة فمن الأفضل أن تتعلم عنها قبل العودة إلى هنا، وبناءً على ذلك سنبدأ هذا الدليل بتذكير سريع على الهيكلية الأساسية للمصفوفات المعقدة، خاصةً بما يتعلق بتخطيط الذاكرة وعرضها ونسخ البيانات وتحديد نوعها، وهذه مفاهيم أساسية يجب أن تفهمها إذا كنت تريد أن تستفيد من فلسفة مكتبة numpy.
</p>

<p>
	لنفكر في مثال بسيط نريد من خلاله مسح جميع القيم في مصفوفة من النوع <code>np.float32</code>. كيف يمكن كتابة تعليمات تنفذ المثال السابق بسرعة؟ الصيغة أدناه واضحة إلى حد ما (على الأقل لأولئك الذين هم على دراية بمكتبة NumPy) ولكن السؤال أعلاه يطلب العثور على أسرع عملية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_38" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">4</span><span class="pun">*</span><span class="lit">1000000</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">float32</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z</span><span class="pun">[...]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	إذا دققت بنوع عناصر المصفوفة <code>dtype</code> وحجمها، يمكنك ملاحظة أنه يمكن تحويل هذه المصفوفة إلى العديد من أنواع البيانات "المتوافقة" الأخرى. نقصد هنا أنه يمكن تقسيم <code>Z.size * Z.itemsize</code> إلى أنواع عناصر <code>dtype</code> جديدة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_40" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.float16)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.72</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.int16)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.77</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.int32)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.29</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.float32)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.33</span><span class="pln"> msec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.int64)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">874</span><span class="pln"> usec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.float64)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">865</span><span class="pln"> usec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.complex128)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">841</span><span class="pln"> usec per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"Z.view(np.int8)[...] = 0"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">630</span><span class="pln"> usec per loop</span></pre>

<p>
	ولكن في الواقع فإن طريقة تصفية جميع القيم ليست هي الأسرع، فقد زاد معدل السرعة بنسبة 25% من خلال تحويل بعض عناصر المصفوفة إلى نوع البيانات <code>np.float64</code>، بينما زاد معدل السرعة بنسبة 50% من خلال عرض المصفوفة واستخدام نوع البيانات <code>np.int8</code>. تتعلق أسباب التسريع بهيكلية عمل مكتبة numpy.
</p>

<h2>
	تخطيط الذاكرة Memory layout
</h2>

<p>
	يُعرّف الصنف <code>ndarray</code> وفقًا لتوثيق Numpy كما يلي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		تتكون نسخة صنف ndarray من جزء أحادي البعد قريب من ذاكرة الحاسب (يملكه كائن معين أو مصفوفة) إلى جانب مخطط الفهرسة الذي يعين أعداد صحيحة N في موقع العنصر من الكتلة.
	</p>
</blockquote>

<p>
	المصفوفة هي كتلة مجاورة من الذاكرة يمكن الوصول إلى عناصرها باستخدام مخطط الفهرسة indexing scheme، الذي يحدد شكل ونوع البيانات، وهذا هو المطلوب لتعريف مصفوفة جديدة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_42" style="">
<span class="pln">Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">9</span><span class="pun">).</span><span class="pln">reshape</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int16</span><span class="pun">)</span></pre>

<p>
	حجم عناصر المصفوفة <code>Z</code> في التعليمة السابقة هو 2 بايت (<code>int16</code>)، وعدد أبعاد <code>(len(Z.shape</code> هو 2.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_44" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">itemsize</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">ndim</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	نظرًا لأن <code>Z</code> ليست طريقة عرض، يمكننا استنتاج خطوات المصفوفة التي تحدد عدد البايتات التي يجب أن تخطوها لاجتياز كل بعد من أبعاد المصفوفة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_46" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> strides </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">shape</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]*</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">itemsize</span><span class="pun">,</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">itemsize
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">strides</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span></pre>

<p>
	لنتمكن من الوصول إلى عنصر معين (مصمم بواسطة فهرس index tuple)، أي كيفية حساب إزاحة البداية والنهاية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_48" style="">
<span class="pln">offset_start </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">ndim</span><span class="pun">):</span><span class="pln">
    offset_start </span><span class="pun">+=</span><span class="pln"> strides</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]*</span><span class="pln">index</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
offset_end </span><span class="pun">=</span><span class="pln"> offset_start </span><span class="pun">+</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">itemsize</span></pre>

<p>
	سنستخدم الآن طريقة التحويل <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.tobytes.html" rel="external nofollow">tobytes</a> للتأكد من المعلومة السابقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_50" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">9</span><span class="pun">).</span><span class="pln">reshape</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="lit">3</span><span class="pun">).</span><span class="pln">astype</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int16</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> index </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">[</span><span class="pln">index</span><span class="pun">].</span><span class="pln">tobytes</span><span class="pun">())</span><span class="pln">
b</span><span class="str">'\x04\x00'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">ndim</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     offset </span><span class="pun">+</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]*</span><span class="pln">index</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">.</span><span class="pln">tobytes</span><span class="pun">()[</span><span class="pln">offset_start</span><span class="pun">:</span><span class="pln">offset_end</span><span class="pun">]</span><span class="pln">
b</span><span class="str">'\x04\x00'</span></pre>

<p>
	يمكن تمثيل هذه المصفوفة بطرق (تخطيطات) مختلفة:
</p>

<ul>
<li>
		تخطيط العنصر item layout
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113398" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28a82935_01_.png.9a551a8ed6d5d486032de2151ee05c7f.png" rel=""><img alt="تخطيط العنصر item layout" class="ipsImage ipsImage_thumbnailed" data-fileid="113398" data-unique="2i6zcnqq6" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28a82935_01_.png.9a551a8ed6d5d486032de2151ee05c7f.png" style="width: 500px; height: auto;"></a>
</p>

<ul>
<li>
		تخطيط العنصر المسطّح Flattened item layout
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113399" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28aed687_02__.png.93b8406dc2d6f85a80ea11d96521b808.png" rel=""><img alt="تخطيط العنصر المسطّح Flattened item layout" class="ipsImage ipsImage_thumbnailed" data-fileid="113399" data-unique="zcgtxe7z2" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28c24c9c_02__.thumb.png.c192c63edb88cae6c1ed9c1d4d1bb8d2.png" style="width: 500px; height: auto;"></a>
</p>

<ul>
<li>
		تخطيط الذاكرة Memory layout (C order, big endian)‎
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113400" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28d6949b_03_.png.39c997f00a73b5b4e08837db18461911.png" rel=""><img alt="تخطيط الذاكرة Memory layout (C order, big endian)‎" class="ipsImage ipsImage_thumbnailed" data-fileid="113400" data-unique="dpm57g3yw" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef28ecf294_03_.thumb.png.3ad45436942456bd9bc39dab8cebd0ba.png" style="width: 550px; height: auto;"></a>
</p>

<p>
	إذا أخذنا الآن شريحة من <code>Z</code>، فإن النتيجة هي عرض المصفوفة الأساسية <code>Z</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_57" style="">
<span class="pln">V </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[::</span><span class="lit">2</span><span class="pun">,::</span><span class="lit">2</span><span class="pun">]</span></pre>

<p>
	يُحدّد هذا العرض باستخدام نوع dtype وشكل وخطوات، إذ أصبح من غير الممكن استنتاج الخطوات strides من النوع والشكل فقط:
</p>

<ul>
<li>
		تخطيط العنصر item layout
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113401" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef2900c4bc_04_2.png.75becd6deae44b5d0f45cce154bcb883.png" rel=""><img alt="تخطيط العنصر item layout" class="ipsImage ipsImage_thumbnailed" data-fileid="113401" data-unique="qhjrn3exy" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef2917790d_04_2.thumb.png.e084051488f4d57af5207d27248442c6.png" style="width: 550px; height: auto;"></a>
</p>

<ul>
<li>
		تخطيط العنصر المسطّح Flattened item layout
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113402" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef2929ad00_05__3.png.a0c861c33af8569cb39a4cf92ca17324.png" rel=""><img alt="تخطيط العنصر المسطّح Flattened item layout" class="ipsImage ipsImage_thumbnailed" data-fileid="113402" data-unique="880kffdmc" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef2938fa0b_05__3.thumb.png.004f78d18d946ac92020007079ef1df5.png" style="width: 600px; height: auto;"></a>
</p>

<ul>
<li>
		تخطيط الذاكرة Memory layout (C order, big endian)‎
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113403" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef296019ff_06_.png.f02093123f993da55450f6cabbbac38d.png" rel=""><img alt="تخطيط الذاكرة Memory layout (C order, big endian)‎" class="ipsImage ipsImage_thumbnailed" data-fileid="113403" data-unique="0um9fshoa" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef29810c53_06_.thumb.png.2a2e6d7b441bbf1c78a6aa9290692607.png" style="width: 750px; height: auto;"></a>
</p>

<h2>
	العروض والنسخ
</h2>

<p>
	تُعد العروض Views والنسخ copies مفاهيمًا مهمة لتحسين حساباتك الرقمية. بالرغم من تعاملنا مع هذه المفاهيم في الفقرات السابقة إلا أن الموضوع أكثر تعقيدًا.
</p>

<h3>
	الوصول المباشر وغير المباشر
</h3>

<p>
	أولًا علينا التمييز بين نوعي الفهرسة indexing و fancy indexing؛ إذ يعيد النوع الأول عرضًا view دائمًا، بينما يعيد النوع الثاني نسخةً copy. يؤدي تعديل العرض في الحالة الأولى إلى تعديل المصفوفة الأساسية، بينما لن يحدث ذلك في الحالة الثانية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_63" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="lit">9</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z_view </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z_view</span><span class="pun">[...]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="lit">9</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z_copy </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z_copy</span><span class="pun">[...]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pun">]</span></pre>

<p>
	إذا كنت تريد استخدام نوع الفهرسة fancy indexing فمن الأفضل الاحتفاظ بنسخة الفهرس fancy index ثم التعامل معه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_65" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">(</span><span class="lit">9</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> index </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">1.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pln">  </span><span class="lit">0.</span><span class="pun">]</span></pre>

<p>
	إذا لم تكن متأكدًا مما إذا كانت نتيجة الفهرسة هي عرض أو نسخة، فيمكنك التحقق باستخدام الأداة base؛ فإذا كانت النتيجة "None"، فسيكون النوع هو نسخة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_67" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,(</span><span class="lit">5</span><span class="pun">,</span><span class="lit">5</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z1 </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[:</span><span class="lit">3</span><span class="pun">,:]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z2 </span><span class="pun">=</span><span class="pln"> Z</span><span class="pun">[[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="pun">:]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">allclose</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">,</span><span class="pln">Z2</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">.</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z2</span><span class="pun">.</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">False</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z2</span><span class="pun">.</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">True</span></pre>

<p>
	لاحظ أن بعض وظائف numpy تُعيد عرضًا view، مثل <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html" rel="external nofollow">ravel</a> عندما يكون ذلك ممكنًا، بينما يعيد البعض الآخر نسخةً copy، مثل <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.flatten.html#numpy.ndarray.flatten" rel="external nofollow">flatten</a>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_69" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">zeros</span><span class="pun">((</span><span class="lit">5</span><span class="pun">,</span><span class="lit">5</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">ravel</span><span class="pun">().</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z</span><span class="pun">[::</span><span class="lit">2</span><span class="pun">,::</span><span class="lit">2</span><span class="pun">].</span><span class="pln">ravel</span><span class="pun">().</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z
</span><span class="kwd">False</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z</span><span class="pun">.</span><span class="pln">flatten</span><span class="pun">().</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z
</span><span class="kwd">False</span></pre>

<h3>
	نسخة مؤقتة Temporary copy
</h3>

<p>
	يمكن إنشاء النسخ بطريقة صريحة كما في الأمثلة السابقة، ولكن الطريقة الأكثر استخدمًا هي الإنشاء الضمني للنسخ الوسيطة. يوضح المثال التالي إجراء العمليات الحسابية باستخدام المصفوفات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_71" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Y </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> A </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">X </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="pln">Y</span></pre>

<p>
	أنشأنا في هذا المثال ثلاث مصفوفات وسيطة: مصفوفة للاحتفاظ بنتيجة <code>X*‏2</code> والثانية للاحتفاظ بنتيجة <code>Y*‏2</code>، والأخيرة لإيجاد نتيجة <code>Y*‏2 + X*‏2</code>، وتكون المصفوفات في هذه الحالة صغيرة الحجم ولا تحدث هذه الطريقة أي فرق واضح؛ ولكن في حال كانت المصفوفات كبيرة الحجم فعليك أن تكون حذرًا مع هذه التعبيرات وتفكر بطريقة مختلفة لإيجاد الحل، فعلى سبيل المثال إذا كانت النتيجة النهائية هي فقط المهمة ولم تكن بحاجة إلى <code>X</code> أو <code>Y</code>، فسيكون الحل البديل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_73" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Y </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">multiply</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">X</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">multiply</span><span class="pun">(</span><span class="pln">Y</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">Y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">,</span><span class="pln"> out</span><span class="pun">=</span><span class="pln">X</span><span class="pun">)</span></pre>

<p>
	استغنينا باستخدام هذا الحل البديل عن فكرة إنشاء مصفوفات مؤقتة، لكن المشكلة أن هناك بعض الحالات التي تتطلب إنشاء هذه النسخ المؤقتة وهذا يؤثر على الأداء كما هو موضح في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_75" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">1000000000</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Y </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">ones</span><span class="pun">(</span><span class="lit">1000000000</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"X = X + 2.0*Y"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3.61</span><span class="pln"> ms per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"X = X + 2*Y"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3.47</span><span class="pln"> ms per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"X += 2*Y"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">100</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.79</span><span class="pln"> ms per loop
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> timeit</span><span class="pun">(</span><span class="str">"np.add(X, Y, out=X); np.add(X, Y, out=X)"</span><span class="pun">,</span><span class="pln"> globals</span><span class="pun">())</span><span class="pln">
</span><span class="lit">1000</span><span class="pln"> loops</span><span class="pun">,</span><span class="pln"> best of </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1.57</span><span class="pln"> ms per loop</span></pre>

<h2>
	الخلاصة
</h2>

<p>
	في الختام سندرس المثال التالي: لنفرض لدينا متجهين <code>Z1</code> و <code>Z2</code>، ونرغب في معرفة ما إذا كان <code>Z2</code> هو عرض view للمتجه <code>Z1</code>، وإذا كانت الإجابة نعم فما هو هذا العرض view؟
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_77" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z1 </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> Z2 </span><span class="pun">=</span><span class="pln"> Z1</span><span class="pun">[</span><span class="lit">1</span><span class="pun">:-</span><span class="lit">1</span><span class="pun">:</span><span class="lit">2</span><span class="pun">]</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113404" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef2999ad6d_07.png.7f7ed6f57e37d2d8f8a6c6f141878aa0.png" rel=""><img alt="المتجهين Z1 و Z2" class="ipsImage ipsImage_thumbnailed" data-fileid="113404" data-unique="7s68egkcb" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef29a3a418_07.thumb.png.7e1309641ef1c73ce40f6332428f6beb.png" style="width: 550px; height: auto;"></a>
</p>

<p>
	أولاً سنحدد نوع الفهرسة وهل <code>Z1</code> هي أساس <code>Z2</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_81" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">Z2</span><span class="pun">.</span><span class="pln">base </span><span class="kwd">is</span><span class="pln"> Z1</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">True</span></pre>

<p>
	حتى الآن تأكدنا أن <code>Z2</code> هي عرض view للمتغير <code>Z1</code>، مما يعني أنه يمكن التعبير عن <code>Z2</code>على النحو التالي: <code>[Z1[start:stop:step</code>.
</p>

<p>
	وتكمن الصعوبة في التعرف على البداية والتوقف والخطوة؛ إذ يمكننا بالنسبة للخطوة استخدام خاصية <code>strides</code> لأي مصفوفة تعطي عدد البايتات للانتقال من عنصر إلى آخر في كل بُعد. في حالتنا ولأن كلا المصفوفتين أحادي البعد، يمكننا مقارنة الخطوة الأولى فقط.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_83" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> step </span><span class="pun">=</span><span class="pln"> Z2</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">//</span><span class="pln"> Z1</span><span class="pun">.</span><span class="pln">strides</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">step</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	الصعوبة التالية هي العثور على مؤشرات البداية والتوقف، إذ يمكننا فعل ذلك بالاستفادة من طريقة byte_bounds التي تُرجع مؤشرًا إلى نقاط نهاية المصفوفة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="113405" href="https://academy.hsoub.com/uploads/monthly_2022_12/638ef29baadc4_08.png.c947baf10d8da5449b6aa1210978bd90.png" rel=""><img alt="مؤشرات النهاية في NumPy " class="ipsImage ipsImage_thumbnailed" data-fileid="113405" data-unique="u2i5sz4fy" src="https://academy.hsoub.com/uploads/monthly_2022_12/638ef29ce7858_08.thumb.png.f3f6f86dbfcaa584e6a89d9ebb2f0547.png" style="width: 550px; height: auto;"></a>
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_86" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> offset_start </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">byte_bounds</span><span class="pun">(</span><span class="pln">Z2</span><span class="pun">)[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">byte_bounds</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">)[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">offset_start</span><span class="pun">)</span><span class="pln"> </span><span class="com"># bytes</span><span class="pln">
</span><span class="lit">8</span><span class="pln">

</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> offset_stop </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">byte_bounds</span><span class="pun">(</span><span class="pln">Z2</span><span class="pun">)[-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">byte_bounds</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">)[-</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">offset_stop</span><span class="pun">)</span><span class="pln"> </span><span class="com"># bytes</span><span class="pln">
</span><span class="pun">-</span><span class="lit">16</span></pre>

<p>
	يعد تحويل هذه الإزاحات offset إلى مؤشرات أمرًا سهلاً باستخدام حجم العناصر مع الأخذ بالحسبان أن <code>offset_stop</code> سلبي (حد نهاية <code>Z2</code> أصغر منطقيًا من حد النهاية لمصفوفة <code>Z1</code>)، لذلك نحتاج إلى إضافة حجم عناصر <code>Z1</code> للحصول على فهرس النهاية الصحيحة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_88" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> start </span><span class="pun">=</span><span class="pln"> offset_start </span><span class="pun">//</span><span class="pln"> Z1</span><span class="pun">.</span><span class="pln">itemsize
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> stop </span><span class="pun">=</span><span class="pln"> Z1</span><span class="pun">.</span><span class="pln">size </span><span class="pun">+</span><span class="pln"> offset_stop </span><span class="pun">//</span><span class="pln"> Z1</span><span class="pun">.</span><span class="pln">itemsize
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">start</span><span class="pun">,</span><span class="pln"> stop</span><span class="pun">,</span><span class="pln"> step</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span></pre>

<p>
	وعند اختبار النتائج نحصل على ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_277_90" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">np</span><span class="pun">.</span><span class="pln">allclose</span><span class="pun">(</span><span class="pln">Z1</span><span class="pun">[</span><span class="pln">start</span><span class="pun">:</span><span class="pln">stop</span><span class="pun">:</span><span class="pln">step</span><span class="pun">],</span><span class="pln"> Z2</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">True</span></pre>

<p>
	يمكنك التمرين من خلال تحسين هذا التنفيذ الأول والبسيط جدًا من خلال مراعاة:
</p>

<ul>
<li>
		خطوات سلبية.
	</li>
	<li>
		مصفوفة متعددة الأبعاد.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصلين Introduction و Anatomy of an array من كتاب <a href="https://www.labri.fr/perso/nrougier/from-python-to-numpy/" rel="external nofollow">From Python to Numpy</a> لصاحبه Nicolas P. Rougier.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1809</guid><pubDate>Mon, 05 Dec 2022 16:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62F;&#x648;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x62E;&#x62F;&#x645;&#x629; &#x641;&#x64A; &#x628;&#x646;&#x627;&#x621; &#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x627;&#x62A; &#x627;&#x644;&#x631;&#x633;&#x648;&#x645;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1771/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_11/63661f2ca3b3f_------.png.c39da4a1790d8496b182bc0d5d720fa3.png" /></p>
<p>
	لا تقل <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1501/" rel="">واجهة المستخدم الرسومية GUI</a> أهميةً عن أي مكون آخر في التطبيق فهي النافذة التي يتفاعل عبرها المستخدم مع التطبيق بسهولة ويسر، وتعد <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">لغة بايثون</a> من أشهر اللغات المستخدمة في بناء تطبيقات بواجهة رسومية حديثة جذابة التصميم بخطوات بسيطة وغير معقدة إذ يجري ذلك بالاعتماد على <a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel="">أطر عمل Frameworks</a> مفتوحة المصدر وهذا ما المقال مخصص لمناقشة تلك الأطر المتاحة لهذه العملية.
</p>

<p>
	نُشر استبيان يتضمن السؤال التالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		"هل يمتلك آخر برنامج بايثون طورته واجهة مستخدم رسومية؟"
	</p>
</blockquote>

<p>
	وصل عدد الإجابات إلى 42447 إجابة وتظهر التفاصيل كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="PNG" data-fileid="111486" href="https://academy.hsoub.com/uploads/monthly_2022_11/63661f29040aa_.PNG.2a30c7376d2a59fd76cb6a1003647544.PNG" rel=""><img alt="إجابات استبيان" class="ipsImage ipsImage_thumbnailed" data-fileid="111486" data-unique="2dy6spacd" style="width: 650px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_11/63661f29e9ffe_.thumb.PNG.74edf8f0138252ca92396b8cf045aa53.PNG"></a>
</p>

<p>
	ولكن قبل اعتماد تصميم واجهة رسومية لتطبيق، ألم تتساءل إن كان التطبيق بحاجة ماسّة لها أم يمكن الاعتماد فقط على واجهة سطر الأوامر؟ عمومًا الواجهة الرسومية ضرورية في الحالات التي يحتاج فيها مستخدم التطبيق إلى التفاعل مع التطبيق عبر الفأرة أي تلك التطبيقات التي ينزلها المستخدم على حاسوبه المحلي ويستخدمها في حياته اليومية، أما التطبيقات التي تكون فيها السرعة وقابلية الاستخدام والتحكم فهنا يمكن الاستغناء عن الواجهة الرسومية واعتماد واجهة سطر الأوامر.
</p>

<p>
	يمكن إضافة مظهر جمالي بسيط لواجهة سطر الأوامر من خلال العديد من المكتبات مثل <a href="https://click.palletsprojects.com/en/5.x/" rel="external nofollow">Click</a> و <a href="https://builtoncement.com/" rel="external nofollow">Cement</a> و <a href="https://docs.openstack.org/cliff/latest/" rel="external nofollow">Cliff</a> التي تسهل البدء بهذه التصاميم.
</p>

<p>
	وقد تكون واجهة الويب حتى بالنسبة لبرنامج يفترض تشغيله محليًا خيارًا يستحق النظر خاصة إذا رغب المستخدم باستضافة البرنامج عن بُعد، وتوضح المشاريع التالية هذا الأمر: جانغو <a href="https://academy.hsoub.com/programming/python/django/" rel="">Django</a> أو فلاسك <a href="https://academy.hsoub.com/programming/python/flask/" rel="">Flask</a> أو بايراميد <a href="https://academy.hsoub.com/questions/5177-%D9%87%D9%84-%D9%8A%D8%AC%D8%A8-%D8%B9%D9%84%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pylons-%D8%A3%D9%88-pyramid%D8%9F/" rel="">Pyramid</a>.
</p>

<p>
	يمكن استخدام مكتبة مثل <a href="https://github.com/r0x0r/pywebview" rel="external nofollow">pywebview</a> لتحويل واجهة ويب إلى واجهة رسومية تشبه الواجهات الأصيلة، ويمكن بدلًا من ذلك استخدام <span ipsnoautolink="true">أطر العمل</span> مثل <a href="https://pyforms.readthedocs.io/en/latest/" rel="external nofollow">Pyforms</a> لبناء تجربة متسقة عبر الويب وسطر الأوامر وسطح المكتب وكل ذلك باستخدام شيفرة أساسية واحدة.
</p>

<h2>
	تصميم الواجهة الرسومية في بايثون
</h2>

<p>
	توفر بايثون للمبرمجين عدة خيارات لبناء واجهات رسومية وبرمجتها كلها تمر عبر ما يُعرف باسم الارتباطات Bindings أو مكتبات رابطة وهي عبارة عن <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-r1314/" rel="">واجهة برمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr></a> تتيح تضمين مكتبة خاصة بتصميم الواجهات الرسومية من منصات ومكتبات عديدة وربطها مع تطبيقك لبناء واجهة رسومية بتلك المنصات والمكتبات بالإضافة إلى الارتباطات الخاصة بأنظمة التشغيل المختلفة مثل <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس Linux</a> وويندوز Windows وماك Mac ويعمل العديد منها عبر الأنظمة الثلاثة أي بناء واجهة رسومية واجهة <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">لأنظمة التشغيل</a> تلك.
</p>

<h3>
	مكتبات PyQt و PySide و Qt لبايثون
</h3>

<p>
	<a href="https://riverbankcomputing.com/software/pyqt/intro" rel="external nofollow">PyQt</a> هو عبارة عن ارتباط Binding أو مكتبة ربط في بايثون يقوم بتضمين مكتبة <a href="https://www.qt.io/" rel="external nofollow">Qt</a> الشهيرة لتصميم الواجهات الرسومية التي تمتلك الكثير من الأدوات بالإضافة لمجتمع داعم كبير، لذا إن سبق لك استعمال مكتبة Qt بلغة برمجة مغايرة لبايثون مثل تطوير تطبيقات كي دي KDE أو أي بيئة سطح مكتب أخرى قائمة على Qt، وهذا يعني أن Qt مألوفة بالنسبة لك مما يجعل PyQt خيارًا مناسبًا لك.
</p>

<p>
	يمكن استخدام <a href="https://www.qt.io/product/development-tools" rel="external nofollow">QtCreator</a> عند إنشاء تطبيقات بايثون باستخدام Qt، وهو عبارة عن بيئة تطوير متكاملة IDE تتميز بتوفير وضع المصمم designer mode لإنشاء شيفرة من عملية تصميم الواجهة رسوميًا.
</p>

<p>
	هنالك خيار آخر لاستخدام مكتبة Qt مع بايثون وهو <a href="https://wiki.qt.io/Qt_for_Python" rel="external nofollow">Qt لبايثون</a> المعروف باسم PySide2.
</p>

<h3>
	Tkinter
</h3>

<p>
	مكتبة Tkinter هي مجموعة أدوات لبناء واجهة المستخدم الرسومية مبنية على مكتبة <a href="http://www.tcl.tk/" rel="external nofollow">Tcl/Tk</a>، حيث Tcl هي لغة برمجة أما Tk هي مجموعة أدوات واجهة المستخدم الرسومية، كما تتميز بكونها أول إطار عمل قدَّم مفهوم الزوج اللغوي language pair في أوائل التسعينيات والذي هو عبارة عن مُعرّف يصف مزيجًا من لغتين كما في عملية الترجمة ويحدد المتغيرات المحددة لكل من لغة المصدر واللغة الهدف.
</p>

<p>
	ننصح بمتابعة سلسلة <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1501/" rel="">بناء واجهة رسومية عبر مكتبة Tkinter</a> التي تشرح أساسيات المكتبة.
</p>

<h3>
	WxPython
</h3>

<p>
	تعمل المكتبة <a href="https://www.wxpython.org/" rel="external nofollow">WxPython</a> الرابطة على تضمين مكتبة <a href="https://wxwidgets.org/" rel="external nofollow">wxWidgets</a> الخاصة بلغة ++C في بايثون، وهي مكتبة واجهة المستخدم الرسومية الخاصة بالأنظمة متعددة المنصات.
</p>

<p>
	الواجهات المصممة عبر WxPython تكون متناسقة أكثر مع مختلف أنظمة التشغيل التي تعمل عليها، عكس إطار العمل Tkinter لأنه يستخدم عناصر واجهة مستخدم النظام المضيف لإنشاء واجهة مستخدم رسومية، ويمتلك WxPython مجتمع مطورين متنامٍ ومن السهل البدء باستخدامه، ولكن قد تحتاج إلى تضمين wxPython مع تطبيقاتك أو تطلب من المستخدم تثبيته بنفسه لأنه لا يُثبت تلقائيًا مع بايثون.
</p>

<h3>
	Python GTK+3
</h3>

<p>
	يُعرف مشروع <a href="https://python-gtk-3-tutorial.readthedocs.io/en/latest/" rel="external nofollow">Python GTK+ 3</a> سابقًا باسم PyGTK ويوفر ارتباطات لبايثون بكائنات GTK وهي مجموعة من عناصر النوافذ وعناصر واجهة المستخدم المستخدمة في بناء واجهة المستخدم.
</p>

<p>
	يعتمد Python GTK+3 على +GTK وهو واسع الاستخدام حيث يعد كأساس لسطح مكتب جنوم GNOME، كما يُستخدم في التطبيقات المستقلة على لينكس وويندوز وماك، وبالتالي فإن استخدام Python GTK+3 يوفر نفس الإطار وأدوات التطوير لمشاريع بايثون الخاصة بك، ومن أبرزها Glade وهو مُصمِّم واجهات رسومية لتطبيقات +GTK.
</p>

<p>
	يحفظ Glade الواجهات المصممة من خلاله بتنسيق XML ويمكنك استخدامها بواسطة كائن GtkBuilder في شيفرة تطبيقك، ويستخدم ميزة السحب والإفلات drag-and-drop مما يسهل إنشاء واجهة مستخدم ديناميكية وسريعة الاستجابة دون الحاجة إلى صياغة ما ترغب بتصميمه ضمن شيفرة التصميم.
</p>

<h3>
	Kivy
</h3>

<p>
	<a href="https://kivy.org/#home" rel="external nofollow">Kivy</a> هو مجموعة أدوات لأنظمة لينكس Linux (بما في ذلك <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%AC%D9%87%D8%A7%D8%B2-%D8%B1%D8%A7%D8%B3%D8%A8%D9%8A%D8%B1%D9%8A-%D8%A8%D8%A7%D9%8A-raspberry-pi-r1356/?do=getLastComment&amp;d=2&amp;id=1356" rel="">راسبيري باي Raspberry Pi</a>) وويندوز Windows وماك Mac وأندرويد Android.
</p>

<p>
	صُمِّمَ مع مراعاة التطور السريع والأجهزة الحديثة لذا يركز على واجهات المستخدم المبتكرة، واُستخدِمَ لتصميم تطبيقات الوسائط المتعددة مثل تطبيقات التحكم في الموسيقى للهواتف وتطبيقات السبورة البيضاء whiteboarding المستخدمة في غرف الاجتماعات.
</p>

<p>
	لا يمتلك Kivy برنامج تصميم مرئي مثل QtCreator و Glade ولكنه يستخدم لغة التصميم الخاصة به التي تساعد المستخدم على ربط تصميم واجهة المستخدم بكائنات التعليمات البرمجية مما يسهل تقسيم الأصناف والتوابع ضمن شيفرة التطبيق.
</p>

<p>
	يستضيف Kivy مستودع Kivy Garden الخاص بعناصر واجهة المستخدم والإضافات التي أنشأها المستخدم لذلك إذا كنت تفكر في إنشاء شيء لا يوفره Kivy فربما يكون موجودًا ضمن المستودع.
</p>

<h2>
	خاتمة
</h2>

<p>
	تطول القائمة لذكر أدوات تصميم الواجهات الرسومية في بايثون ولا يحتويها مقال واحد، لذا لمزيد من الخيارات يمكن التحقق من صفحة <a href="https://wiki.python.org/moin/GuiProgramming" rel="external nofollow">"برمجة واجهة المستخدم الرسومية في Python"</a> من توثيق <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> الرسمي والذي يسرد العشرات من الأدوات الأخرى.
</p>

<p>
	تتوفر الكثير من الحلول لربط بايثون بالعديد من مكتبات عناصر واجهة المستخدم المختلفة وأدوات واجهة المستخدم الرسومية مثل <a href="https://www.fltk.org/index.php" rel="external nofollow">FLTK</a> و <a href="http://fxpy.sourceforge.net/" rel="external nofollow">FOX</a> وخيارات أخرى تستحق النظر مثل مثل <a href="http://www.pygame.org/wiki/gui" rel="external nofollow">pygame</a> و<a href="https://bitbucket.org/pyglet/pyglet/wiki/Home" rel="external nofollow">pyglet</a> و<a href="https://www.panda3d.org/" rel="external nofollow">Panda3d</a> وغيرها الكثير، ولكن من المحتمل أن يتجنب المبتدئين المشاريع التي تقدم تطبيقات جزئية فقط أو التي لم تعد تتم صيانتها إلا أن هناك الكثير من الأدوات الجيدة التي تناسب الكثير من حالات الاستخدام.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/resources/python/gui-frameworks" rel="external nofollow">‎‎5 open source Python GUI frameworks</a> لصاحبه Jason Baker.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1501/" rel="">واجهات المستخدم الرسومية في بايثون باستخدام TKinter</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-widgets-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1502/" rel="">مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%B1%D8%A8%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D9%88%D8%A3%D8%B2%D8%B1%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D9%86%D8%AA%D9%82%D8%A7%D8%A1-%D9%88%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%A6%D9%85-%D9%81%D9%8A-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1511/" rel="">مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1771</guid><pubDate>Wed, 23 Nov 2022 16:09:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x622;&#x644;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x642;&#x630;&#x641; &#x625;&#x644;&#x649; &#x627;&#x644;&#x644;&#x639;&#x628;&#x629; &#x627;&#x644;&#x645;&#x637;&#x648;&#x631;&#x629; &#x628;&#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633c1c4c2686e_-------.png.97c3af4c8c8b1a858cf1d2220ef14517.png" /></p>

<p>
	تجنب الأعداء والركض بعيدًا عنهم شيء والقتال ضدهم شيء آخر تمامًا، فهو يزيد التفاعل بين المستخدم واللعبة، وهو موضوع المقال الختامي من سلسلة بناء لعبة من الصفر باستخدام بايثون، إليك مقالات السلسلة بالترتيب قبل أن نبدأ:
</p>

<ol>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون.
	</li>
</ol>
<p>
	لديك تفصيلين تهتم بهما في هذه الحالة، الأول هو إنتاج العنصر الذي سيُرمى والثاني هو المعيار أو الشرط الذي سيبقيه فعالًا فالسهام والكرات النارية لابد ستختفي في النهاية قد تختفي عند حافة الشاشة مثلًا أو تظل صالحة لفترة زمنية محدودة ينتهي مفعولها بعدها وهكذا.
</p>

<p>
	بالإضافة إلى تحديد قدرة اللاعب على القذف فهو يستطيع أن يقذف عنصرًا واحدًا فقط في كل مرة، يرفع هذا الخيار من مستوى التحدي بإعطاء اللاعب فرصةً وحيدة في كل مرة لإصابة العدو، ويساهم من جهةٍ ثانية بتبسيط تعليماتك البرمجية.
</p>

<p>
	يمكنك بعد نهاية القراءة وتعلم الموجود هنا أن تسعى لتطوير البرنامج وتعطي لاعبك القدرة على قذف أكثر من عنصر في وقتٍ واحد.
</p>

<h2>
	إنشاء صنف الكائن المقذوف
</h2>

<p>
	ستجد الدالة <code>__init__</code> ضمن تعليمات الصنف المبينة أدناه لإنتاج كائن بايثون للعنصر المقذوف، وهي الدالة نفسها المستخدمة سابقًا لإنتاج <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">البطل</a> و <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">الأعداء</a>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9856_9" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""</span><span class="pln">
    </span><span class="pun">إنتاج</span><span class="pln"> </span><span class="pun">الكائن</span><span class="pln"> </span><span class="pun">المقذوف</span><span class="pln">
    </span><span class="str">"""</span><span class="pln">
    def __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">throw</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln">img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect   </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">firing </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">throw</span></pre>

<p>
	الاختلاف الجوهري بين الدالة <code>__init__</code> الموجودة في هذا الصنف والدالة نفسها الموجودة في صنف اللاعب <code>Player</code> وصنف العدو <code>Enemy</code> هو المتغير <code>self.firing</code> الذي يتتبع حالة الكائن المقذوف فيما إذا كان لا يزال فعالًا وظاهرًا على الشاشة أم انتهت صلاحيته، وتتغير قيمته تبعًا لذلك فهو يحمل القيمة 1 عندما ينشئ الكائن.
</p>

<h2>
	قياس زمن فعالية الكائن المقذوف
</h2>

<p>
	تمامًا مثل البطل والعدو يحتاج هذا الكائن إلى الدالة <code>update</code> لتحديث موقع ظهوره على الشاشة حتى يتحرك في الهواء منطلقًا باتجاه العدو بعد أن رماه البطل.
</p>

<p>
	أسهل طريقة لقياس زمن فعالية الكائن المقذوف هي وصوله إلى حافة الشاشة وخروجه عن مدى الرؤية، لكن عليك أن تحدد أي حافة ستراقب تبعًا لحركة هذا الكائن إن كانت أفقية أو عمودية.
</p>

<ul>
<li>
		إذا كان البطل يقذفه أفقيًا مثل السهم أو الطاقة السحرية أو ماشابه فعليك مراقبة حافة الشاشة على المحور الأفقي وتحددها القيمة <code>worldx</code>.
	</li>
	<li>
		أما إذا كان يقذف الأشياء عموديًا أو بكلا الاتجاهين يتعين عليك مراقبة الحافة العمودية للشاشة باستخدام القيمة <code>worldy</code>.
	</li>
</ul>
<p>
	يفترض هذا المثال أن الجسم المقذوف يتحرك قليلًا للأمام ثم يسقط على الأرضية دون ارتداد فيتابع سقوطه إلى أسفل الشاشة، اطلع على التعليمات التالية وغيّر القيم الواردة فيها قليلًا لترى ما يناسب لعبتك أكثر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_11" style="">
<span class="pln">   </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln">worldy</span><span class="pun">):</span><span class="pln">
        </span><span class="str">'''
        فيزياء المقذوفات
        '''</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln"> </span><span class="com">#المحور العمودي</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x  </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">15</span><span class="pln"> </span><span class="com">#سرعة حركته إلى الأمام</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y  </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">  </span><span class="com">#سرعة سقوطه إلى أسفل</span><span class="pln">
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">kill</span><span class="pun">()</span><span class="pln">  </span><span class="com">#انتهاء فاعلية العنصر المقذوف</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">firing </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="com">#تحرير المتغير أو تصفيره </span></pre>

<p>
	ارفع قيم <code>self.rect</code> لتسريع حركة الكائن المقذوف.
</p>

<p>
	عندما يصل المقذوف إلى حافة الشاشة سيختفي أو بالأحرى يُدَمّر، وتتحرر الذاكرة المؤقتة التي أُشغلت بوجوده وتُضبط قيمة المتغير <code>self.firing</code> إلى الصفر ويتحرر تمهيدًا للرمية التالية.
</p>

<h2>
	ضبط إعدادات الكائن المقذوف
</h2>

<p>
	أنشئ في مقطع الإعدادات ضمن برنامج مجموعةً خاصة للكائنات التي يمكن أن يقذفها البطل، بصورةٍ مشابهة لمجموعات البطل والأعداء، وجهز كائنًا قابلًا للقذف غير فعال حتى يبدأ به البطل اللعبة، وإلّا فإن قذفته الأولى ستفشل.
</p>

<p>
	يفترض هذا المثال أن سلاح البطل هو الكرة النارية وتحدد مواصفاتها باستعمال المتغير <code>fire</code> ويمكنك في مستوياتٍ لاحقة تطوير السلاح وتغيير صورته ومواصفاته بالاعتماد على الصنف <code>Throwable</code> نفسه.
</p>

<p>
	اكتب التعليمات الآتية علمًا أن تعليمات أول سطرين لمعرفة السياق ولا حاجة لكتابتها مجددًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_13" style="">
<span class="pln">player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln"> </span><span class="com">#للسياق </span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">             </span><span class="com">#للسياق</span><span class="pln">
fire </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y</span><span class="pun">,</span><span class="str">'fire.png'</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
firepower </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span></pre>

<p>
	لاحظ أن مكان إنتاج الكائن المقذوف مطابق لمكان إنتاج كائن البطل وهذا يعطي انطباعًا بأنه ينطلق من جعبة البطل، بعد إنتاج كرة النار الأولى يأخذ المتغير <code>self.firing</code> القيمة صفر ليتيح إمكانية القذف.
</p>

<h2>
	إضافة القذف إلى الحلقة الرئيسية
</h2>

<p>
	المبدأ نفسه على طول السلسلة اذكر ما تريد تنفيذه في الحلقة الرئيسية، أضف في البداية تعليمات التحكم التي ستُطلق الكرة النارية عندما يستخدم اللاعب الزر المحدد على لوحة المفاتيح.
</p>

<p>
	عند تحريك البطل استخدمنا الضغط على الزر لتبدأ حركة البطل وتحرير الزر أو رفع الضغط عنه ليتوقف البطل عن الحركة، لا يوجد توقف في عملية القذف فلن تحتاج أكثر من إشارة اختر واحدة منهما الضغط أو التحرير.
</p>

<p>
	اكتب التعليمات التالية وأول سطرين لتبيان السياق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_15" style="">
<span class="pln">            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">(</span><span class="pln">platform_list</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_SPACE</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> fire</span><span class="pun">.</span><span class="pln">firing</span><span class="pun">:</span><span class="pln">
                    fire </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y</span><span class="pun">,</span><span class="str">'fire.png'</span><span class="pun">,</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
                    firepower</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">fire</span><span class="pun">)</span></pre>

<p>
	تُسند القيمة 1 للمتغير <code>self.firing</code> على عكس الكرة النارية الأولى غير الفعالة التي كُتبت سابقًا في مقطع الإعدادات.
</p>

<p>
	اكتب التعليمات الخاصة بتحديث الكائن المقذوف ورسمه على الشاشة، واحرص على كتابتها في الموقع الصحيح تمامًا كما هو مبين أدناه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_17" style="">
<span class="pln">   enemy</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">  </span><span class="com"># للسياق</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> fire</span><span class="pun">.</span><span class="pln">firing</span><span class="pun">:</span><span class="pln">
        fire</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(</span><span class="pln">worldy</span><span class="pun">)</span><span class="pln">
        firepower</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">screen</span><span class="pun">)</span><span class="pln">  </span><span class="com"># للسياق</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">screen</span><span class="pun">)</span><span class="pln">   </span><span class="com"># للسياق</span></pre>

<p>
	لاحظ أن تعليمات التحديث تعمل فقط عندما يحمل المتغير <code>self.firing</code> القيمة 1، أما إذا كانت قيمته 0 فإن الشرط لن يتحقق ويتجاوز البرنامج هذه التعليمات دون أن ينفذها، أما لو كتبت هذه التعليمات دون شروط وحاولت تطبيقها بغض النظر عن قيمة المتغير سيفشل عمل اللعبة لأنها لن تجد كرةً نارية لترسمها أو تحدّث ظهورها على الشاشة.
</p>

<p>
	شغل اللعبة الآن وحاول استخدام السلاح.
</p>

<h2>
	اكتشاف التصادم
</h2>

<p>
	فور تجريب اللعبة ستلاحظ أن البطل يقذف سلاحه باتجاه العدو وقد يصيبه لكن دون أي تأثير، فالبرنامج لا يملك حتى الآن أي آلية تكتشف تصادم الجسم المقذوف بالعدو.
</p>

<p>
	الآلية المطلوبة مشابهة جدًا للمذكورة في صنف اللاعب <code>Player</code>، لذا أضف الدالة <code>update</code> التالية في صنف العدو <code>Enemy</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_19" style="">
<span class="pln">    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln">firepower</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        اكتشاف التصادم مع الكرة النارية
        """</span><span class="pln">
        fire_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln">firepower</span><span class="pun">,</span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> fire </span><span class="kwd">in</span><span class="pln"> fire_hit_list</span><span class="pun">:</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span></pre>

<p>
	التعليمات بسيطة فهي تتحقق من حدوث التصادم بين كائن العدو وكل كرة نارية <code>firepower</code> تنتمي لمجموعة كائنات الكرات النارية التي يقذفها البطل، وفي حال تبين حدوث التصادم يُزال العدو من مجموعة الأعداء ويختفي عن الشاشة.
</p>

<p>
	أضف السطر الأخير من التعليمات الآتية إلى كتلة تعليمات <code>firing</code> في الحلقة الرئيسية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_21" style="">
<span class="pln">    </span><span class="kwd">if</span><span class="pln"> fire</span><span class="pun">.</span><span class="pln">firing</span><span class="pun">:</span><span class="pln">       </span><span class="com"># للسياق</span><span class="pln">
        fire</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(</span><span class="pln">worldy</span><span class="pun">)</span><span class="pln">         </span><span class="com"># للسياق</span><span class="pln">
        firepower</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">screen</span><span class="pun">)</span><span class="pln">  </span><span class="com"># للسياق</span><span class="pln">
        enemy_list</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(</span><span class="pln">firepower</span><span class="pun">,</span><span class="pln">enemy_list</span><span class="pun">)</span><span class="pln"> </span><span class="com"># تحديث العدو</span></pre>

<p>
	يتبقى لدينا أمر أخير للتعامل معه وهو اتجاه القذف.
</p>

<h2>
	تغيير اتجاه القذف
</h2>

<p>
	يقذف بطل اللعبة حاليًا كراته باتجاه اليمين فقط، فعندما ما عرفنا دالة التحديث في صنف القذف جعلناها تزيد عددًا من البكسلات لموقع الكرة وهي تتحرك على المحور X والزيادة على هذا المحور تعني التحرك يمينًا، فماذا لو استدار البطل وأراد القذف نحو اليسار؟
</p>

<p>
	يتمثل الحل المتبع هنا في تعريف متغير جديد يحدد توجه البطل ومن ثم تحديد اتجاه القذف الأنسب وفقًا لقيمته.
</p>

<p>
	عرّف المتغير <code>facing_right</code> في صنف اللاعب وأعطه القيمة الابتدائية <code>True</code> إذ إن صورة اللاعب المستخدمة في هذا المثال تتجه افتراضيًا نحو اليمين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_23" style="">
<span class="pln">       self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">  </span><span class="com"># أضف هذا السطر</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span></pre>

<p>
	وبذلك تكون القيمة <code>True</code> مؤشرًا على اتجاه البطل إلى اليمين والقيمة <code>False</code> تشير لاتجاهه يسارًا، وينبغي التبديل بينهما في كل مرة يغير البطل اتجاه حركته، وأنسب مكان ذلك هو التعليمات الخاصة بالتحكم بحركة البطل عبر أزرار لوحة المفاتيح وفق ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_25" style="">
<span class="pln">       </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># أضف هذا السطر</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">  </span><span class="com"># أضف هذا السطر</span></pre>

<p>
	عدّل أخيرًا الدالة <code>update</code> في صنف القذف <code>Throwable</code> لتجمع أو تطرح عددًا من وحدات البكسل إلى موقع الكرة النارية بناءً على اتجاه حركة البطل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_27" style="">
<span class="pln">        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">facing_right</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">15</span><span class="pln">
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">15</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span></pre>

<p>
	جرب اللعبة الآن وتفقد النتائج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109031" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-throw.png.66ae63a46f0b9adfe55b04f489c3863a.png" rel=""><img alt="pygame-throw" class="ipsImage ipsImage_thumbnailed" data-fileid="109031" data-unique="8g1dfgse5" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-throw.png.66ae63a46f0b9adfe55b04f489c3863a.png" style="width: 450px; height: auto;"></a>
</p>

<p>
	حاول تطوير اللعبة وامنح البطل بعض النقاط مع كل إصابة موفقة للعدو.
</p>

<h2>
	برنامج اللعبة كاملًا
</h2>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9856_32" style="">
<span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">
forwardx  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">600</span><span class="pln">
backwardx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">120</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">80</span><span class="pun">,</span><span class="pln"> </span><span class="lit">80</span><span class="pun">,</span><span class="pln"> </span><span class="lit">155</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

font_path </span><span class="pun">=</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">dirname</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">realpath</span><span class="pun">(</span><span class="pln">__file__</span><span class="pun">)),</span><span class="pln"> </span><span class="str">"fonts"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"amazdoom.ttf"</span><span class="pun">)</span><span class="pln">
font_size </span><span class="pun">=</span><span class="pln"> tx
pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
myfont </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">(</span><span class="pln">font_path</span><span class="pun">,</span><span class="pln"> font_size</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> stats</span><span class="pun">(</span><span class="pln">score</span><span class="pun">,</span><span class="pln"> health</span><span class="pun">):</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Score:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">score</span><span class="pun">),</span><span class="pln"> BLUE</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">72</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Health:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">health</span><span class="pun">),</span><span class="pln"> BLUE</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a throwable object
    """</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">,</span><span class="pln"> throw</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">firing </span><span class="pun">=</span><span class="pln"> throw

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">):</span><span class="pln">
        </span><span class="str">'''
        throw physics
        '''</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">facing_right</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">15</span><span class="pln">
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">15</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">kill</span><span class="pun">()</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">firing </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">


</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'walk'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x

    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># collisions</span><span class="pln">
        enemy_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">):</span><span class="pln">
                    self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">colliderect</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            idx </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">collidelist</span><span class="pun">(</span><span class="pln">enemy_hit_list</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> idx </span><span class="pun">==</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">   </span><span class="com"># set damage back to 0</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">  </span><span class="com"># subtract 1 hp</span><span class="pln">

        ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">

        </span><span class="com"># fall off the world</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># how high to jump</span><span class="pln">

        loot_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> loot_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> loot </span><span class="kwd">in</span><span class="pln"> loot_hit_list</span><span class="pun">:</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">score</span><span class="pun">)</span><span class="pln">

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> firepower</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        detect firepower collision
        """</span><span class="pln">
        fire_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> firepower</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> fire </span><span class="kwd">in</span><span class="pln"> fire_hit_list</span><span class="pun">:</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">550</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list

    </span><span class="kwd">def</span><span class="pln"> loot</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            loot_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            loot </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">tx</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'loot_1.png'</span><span class="pun">)</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> loot_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
fire </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> </span><span class="str">'fire.png'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
firepower </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="lit">80</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">
gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc </span><span class="pun">)</span><span class="pln">
loot_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">loot</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">facing_right </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_SPACE</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> fire</span><span class="pun">.</span><span class="pln">firing</span><span class="pun">:</span><span class="pln">
                    fire </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Throwable</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y</span><span class="pun">,</span><span class="pln"> </span><span class="str">'fire.png'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
                    firepower</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">fire</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># scroll the world forward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll

    </span><span class="com"># scroll the world backward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> fire</span><span class="pun">.</span><span class="pln">firing</span><span class="pun">:</span><span class="pln">
        fire</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(</span><span class="pln">worldy</span><span class="pun">)</span><span class="pln">
        firepower</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(</span><span class="pln">firepower</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">)</span><span class="pln">
    loot_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    stats</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">score</span><span class="pun">,</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/20/9/add-throwing-python-game" rel="external nofollow">Add throwing mechanics to your Python game</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب البرمجة <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1735</guid><pubDate>Tue, 04 Oct 2022 11:43:35 +0000</pubDate></item><item><title>&#x62A;&#x633;&#x62C;&#x64A;&#x644; &#x646;&#x62A;&#x627;&#x626;&#x62C; &#x627;&#x644;&#x644;&#x639;&#x628;&#x629; &#x627;&#x644;&#x645;&#x637;&#x648;&#x631;&#x629; &#x628;&#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x648;&#x639;&#x631;&#x636;&#x647;&#x627; &#x639;&#x644;&#x649; &#x627;&#x644;&#x634;&#x627;&#x634;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633c0c65ccd75_--------.png.e1de214ac824b4cc62375d469b6c16c4.png" /></p>
<p>
	عرض النتائج على الشاشة جزء مهم وحيوي من أي لعبة وهو موضوع المقال ما قبل الأخير من سلسلة بناء لعبة من الصفر باستخدام بايثون، سنعرض فيه نقاط اللاعب وصحته بناءً على ما اغتنمه من جوائز وما أصابه من ضرر جراء التصادم مع الأعداء.
</p>

<p>
	يمكنك مطالعة المقالات ضمن السلسلة:
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<p>
	اكتسبت على مدار السلسلة كل الأساسيات اللازمة لبناء لعبة فيديو <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بلغة بايثون</a> وستضيف لها اليوم مهارة جديدة جوهرية لكل مبرمج أيًّا كان اختصاصه، فإضافةً لعرض النتائج على الشاشة بتنسيق وخط مناسبين ستتعلم قراءة توثيقات المكتبة أو اللغة البرمجية ومعرفة إمكاناتها وكيفية استخدام ميزاتها التي لم تتعامل معها قبلًا وهو فعليًا الهدف الحقيقي المقال.
</p>

<h2>
	عرض النتائج في Pygame
</h2>

<p>
	يتضمن برنامج اللعبة كل المتغيرات اللازمة لتتبع نقاط اللاعب التي كسبها من الجوائز وأيضًا صحته أو أدواره المتأثرة بالتصادم مع الأعداء، إلّا أن هذه المتغيرات تعمل في الخلفية ولا تُظهر أي نتائج على شاشة اللعبة لذا ينصب اهتمامنا هنا على طريقة العرض واختيار الخط المناسب لها.
</p>

<h2>
	قراءة التوثيقات
</h2>

<p>
	معظم وحدات <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> ومن بينها Pygame لها توثيقات رسمية تشرحها وحتى الجزء البسيط من الوحدات الذي لا تشمله التوثيقات تشرحه <code>Help</code> دالة المساعدة من بايثون، والتوثيقات عمومًا هي توصيف لكافة دوال الوحدة وأصنافها وتكتب بلغة فنية دقيقة تحدد مثلًا أنواع المدخلات المطلوبة وما شابه، وقد تكون مربكة للبعض غير المعتاد عليها فهي لا تشبه السرد البسيط المتبع في المقالات التعليمية.
</p>

<p>
	بخصوص Pygame الوحدة التي نستخدمها تستطيع الوصول لتوثيقاتها الغنية عبر رابط في <a href="https://www.pygame.org/news" rel="external nofollow">صفحتها الرسمية</a>، ولكن قبل البحث في أي توثيق فكر أولًا بما تريد الحصول عليه، فهنا مثلًا نسعى لإظهار نقاط اللاعب وصحته على شاشة اللعبة، ومن بعدها حاول تخمين العناصر البرمجية المطلوبة لتحقيقه مثل المتغيرات والدوال وغيرها، وإن لم تتمكن من وصف احتياجك بهذه الدقة، صِفهُ بالعموم وببساطة، فهنا مثلًا تحتاج لنصوص ترسمها Pygame على الشاشة لتظهر النتائج، وربما شعرت بقدرتك على إظهارها بطريقة مشابهة لعرض المنصات والكائنات على شاشة اللعبة.
</p>

<p>
	تقنيًا لا يوجد ما يمنعك من فعل ذلك، واستخدام صور الأرقام بكل بساطة وعرضها على الشاشة لتمثل نتائج اللعبة عبر Pygame، قد لا تكون هذه الطريقة المثلى لتصل لهدفك لكنها صحيحة في نهاية المطاف وقد أوصلك إليها التفكير العام بأساليب عرض النتائج، بكل الأحوال لو تصفحت توثيقات Pygame ستلفت انتباهك على الفور وحدة الخط وتدعى Font وهي مختصة بتسهيل كتابة النصوص على الشاشة وتنسيق خطوطها.
</p>

<h2>
	فهم رموز التوثيق الفني
</h2>

<p>
	يبدأ توثيق وحدة الخط بالدالة <code>‎pygame.font.init‎(‎)‎</code> ويصفها التوثيق بأنها دالة التهيئة للوحدة، تُستدعى تلقائيًا بواسطة <code>()pygame.init</code> المستدعاة أساسًا في برنامج اللعبة، واستخدامها شبيه بما تعلمته خلال السلسلة، إذ ستتمكن من استخدام دوالها وكتابة النتيجة على الشاشة بقراءة بسيطة للتوثيق ومراجعة لما تعلمته.
</p>

<p>
	ولو استمريت باستعراض الوحدات في توثيقات Pygame ستصادف الوحدة <code>Pygame.freetype</code> ومن الاسم يتضح ارتباطها بحالتنا وهي أفضل من وحدة الخط إذ يصفها التوثيق بأنها:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		بديل وحدة الخط الخاصة بتحميل الخطوط وعرضها على الشاشة، وهي تتضمن وظائف الوحدة الأصلية جميعها مع العديد من الميزات الإضافية الجديدة.
	</p>
</blockquote>

<p>
	وفي صفحة التوثيق نفسها المخصصة للوحدة ستجد بعض الأمثلة على طريقة استخدامها ومنها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_10" style=""><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype</span></pre>

<p>
	السطر موجود لدينا في برنامج اللعبة وما نحتاجه هو السطر الثاني، أضفه إذًا لمجموعة تعليمات <code>import</code> لتصبح على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_12" style=""><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os
</span><span class="kwd">import</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype</span></pre>

<h2>
	استخدام الخطوط في Pygame
</h2>

<p>
	استنادًا للتوثيق تعرض الوحدتان النصوص على الشاشة باستعمال الخطوط الإفتراضية في Pygame أو أي خطوط أخرى تزودها بها، وستجد ضمن توثيق الوحدة <code>pygame.freetype</code> التوصيف الفني للدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_14" style=""><span class="pln">pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pln">
</span><span class="com"># إنشاء خط جديد انطلاقًا من أحد ملفات الخطوط المدعومة</span><span class="pln">

</span><span class="typ">Font</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> font_index</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> resolution</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> ucs4</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Font</span><span class="pln">

pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">.</span><span class="pln">name
</span><span class="com"># اسم ملف الخط</span><span class="pln">

pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">.</span><span class="pln">path
</span><span class="com"># مسار ملف الخط</span><span class="pln">

pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">.</span><span class="pln">size
</span><span class="com"># حجم الخط الافتراضي المستخدم في العرض</span></pre>

<p>
	وهي مسؤولة عن إنشاء كائن Object الخط في Pygame ومواصفاته ولو دققت فيها ستجدها مشابهة لتعليمات إنشاء كائنات اللعبة مثل الأبطال والأعداء فبدلًا من صورة الشخصية ستحدد هنا ملف الخط وبمجرد توفره يمكنك إنشاء كائن الخط باستخدام الدالة السابقة <code>pygame.freetype.Font</code> ومن ثم استدعائه للعرض على الشاشة.
</p>

<h2>
	إدارة الخط بصفته أحد أصول اللعبة
</h2>

<p>
	لتضمن عمل لعبتك بصورةٍ جيدة عليك تضمن الخط الذي تعتمده ضمن ملفات اللعبة فمجموعات الخطوط تختلف من حاسبٍ لآخر، لذا أنشئ مجلدًا خاصًا بالخطوط في المجلد الأب للعبتك تمامًا مثل مجلد الصور وضع فيه ملفات الخطوط التي تستخدمها.
</p>

<p>
	واحرص على عدم انتهاك حقوق الملكية الفكرية، فاستعمل خطوطًا مفتوحة المصدر أو تتمتع برخصة المشاع الإبداعي، فحتى استعمال أحد ملفات الخطوط المتوفرة على حاسبك الشخصي وجعله خطًا للعبتك لا يعد تصرفًا قانونيًا.
</p>

<p>
	وفيما يلي قائمة ببعض المواقع التي توفر خطوطًا مجانية واستخدامها قانوني يمكنك الاستفادة منها:
</p>

<ul>
	<li>
		<a href="https://fontlibrary.org/" rel="external nofollow">Font Library</a>.
	</li>
	<li>
		<a href="https://www.fontsquirrel.com/" rel="external nofollow">Font Squirrel</a>.
	</li>
	<li>
		<a href="https://www.theleagueofmoveabletype.com/" rel="external nofollow">League of Moveable Type</a>.
	</li>
</ul>

<p>
	حمّل الخط الذي أعجبك من هذه المواقع على شكل ملف مضغوط zip أو tar وفك ضغطه لاستخراج ملف الخط، ويكون عادةً بصيغة ttf. أو otf. ومن ثم ضعه في مجلد الخطوط الخاصة باللعبة.
</p>

<p>
	لا يوجد أي حاجة لتثبيت الخط في <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">نظام التشغيل</a> لديك بل يكفي وجوده في مجلد اللعبة لتستخدمه Pygame، وفي حال تضمن اسم الملف رموزًا أو فراغات أزلها وعدّل الاسم، ويفضل لو تختر له اسمًا بسيطًا ومختصرًا لتكتبه بسهولة في التعليمات البرمجية.
</p>

<h2>
	تعليمات الخط في Pygame
</h2>

<p>
	بناءً على توثيق الدالة <code>pygame.freetype.Font</code> يمكنك إنشاء كائن الخط عبر تحديد مسار ملف الخط المرغوب على الأقل المدخلات الأخرى فهي اختيارية وليست ملزمة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_17" style=""><span class="typ">Font</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> font_index</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> resolution</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> ucs4</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Font</span></pre>

<p>
	أنشئ متغيرًا جديدًا اسمه <code>myfont</code> وأسند له خرج الدالة <code>Font</code> المذكورة وفق التعليمات الآتية وملف الخط الذي اعتمدنا عليه هنا هو amazdoom.ttf على سبيل المثال.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_19" style=""><span class="pln">font_path </span><span class="pun">=</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">dirname</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">realpath</span><span class="pun">(</span><span class="pln">__file__</span><span class="pun">)),</span><span class="str">"fonts"</span><span class="pun">,</span><span class="str">"amazdoom.ttf"</span><span class="pun">)</span><span class="pln">
font_size </span><span class="pun">=</span><span class="pln"> tx
pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
myfont </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">(</span><span class="pln">font_path</span><span class="pun">,</span><span class="pln"> font_size</span><span class="pun">)</span></pre>

<h2>
	عرض النص على الشاشة في Pygame
</h2>

<p>
	بعد إنشاء الخط عرف الدالة <code>stats</code> التالية في مقطع الكائنات ضمن برنامج اللعبة، مهمتها رسم النصوص المطلوبة على الشاشة وهي تتطلب ذكر النصوص التي تريد عرضها وتحديد لون معين لها من باستخدام <a href="https://academy.hsoub.com/design/graphic/%d9%85%d8%a7-%d9%87%d9%88-%d8%a7%d9%84%d9%86%d9%91%d8%b8%d8%a7%d9%85-%d8%a7%d9%84%d9%84%d9%88%d9%86%d9%8a-color-model-r11/" rel="">النظام اللوني</a> RGB بالطريقة نفسها التي اتبعناها عند إظهار خلفية عالم اللعبة ومنصاتها، مع ضرورة التنويه إلى أن هذه الدالة عامة ومستقلة ولا تتبع لصنف معين من أصناف برنامج اللعبة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_21" style=""><span class="kwd">def</span><span class="pln"> stats</span><span class="pun">(</span><span class="pln">score</span><span class="pun">,</span><span class="pln">health</span><span class="pun">):</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Score:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">score</span><span class="pun">),</span><span class="pln"> BLACK</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">72</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Health:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">health</span><span class="pun">),</span><span class="pln"> BLACK</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span></pre>

<p>
	والآن استدعيها في <a href="https://academy.hsoub.com/programming/python/%d8%ad%d9%84%d9%82%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1-loops-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r291/" rel="">حلقة التكرار</a> الرئيسية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_24" style=""><span class="pln">    stats</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">score</span><span class="pun">,</span><span class="pln">player</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln"> </span><span class="com"># draw text</span></pre>

<p>
	إذا شغلت اللعبة الآن ستحصل على خطأ فهي ما زالت بحاجة لبعض التعديلات.
</p>

<h2>
	تفسير الأخطاء
</h2>

<p>
	تفسير الأخطاء ومحاولة فهمها عملية مهمة جدًا للمبرمجين وتفيدهم في اصلاح مشاكل البرامج، والأخطاء في لغة بايثون دلالية وسهلة الفهم نوعًا ما لكنها مع ذلك تحتاج لتفسير لتُحلل ما يحدث.
</p>

<p>
	عند تشغيل اللعبة في هذه المرحلة ستحصل على هذا الخطأ:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_27" style=""><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"/home/tux/PycharmProjects/game_001/main.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">41</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
    font_size </span><span class="pun">=</span><span class="pln"> tx
</span><span class="typ">NameError</span><span class="pun">:</span><span class="pln"> name </span><span class="str">'tx'</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> defined</span></pre>

<p>
	يدّل الخطأ صراحةً على عدم تعريف المتغير <code>tx</code> رغم أن المتغير معرف وقد استخدمناه مررًا ضمن البرنامج، ويشير أيضًا إلى السطر رقم 41 لا تعني هذه الإشارة بالضرورة أن الخطأ موجود في السطر 41 بل تعني أن التنفيذ توقف عنده.
</p>

<p>
	لو رجعت إلى برنامج اللعبة وتفقدت تعريف المتغير <code>tx</code> ستجده معرفًا مع المغير <code>ty</code> في مقطع الإعدادات ضمن البرنامج وهو يأتي بعد السطر 41 في تسلسل الأسطر.
</p>

<p>
	اتضحت الصورة الآن علينا نقل تعريف المتغير إلى موضعٍ آخر ضمن البرنامج ترتيبه يسبق السطر 41 وبذلك يمرّ عليه بايثون قبل الوصول لهذا السطر ويُحل الخطأ.
</p>

<p>
	جميع البرامج معرضة للأخطاء وستواجه هذه الحالات دائمًا، قد تكون صعبة أو سهلة دوّن المعلومات التي يظهرها الخطأ وراجع البرنامج في ضوئها بعنايةً وستصل للحل حتى أمهر المبرمجين يواجهون هذه الأخطاء وكلما زاد إتقانك <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">للغة بايثون</a> زادت قدرتك على تفسير الأخطاء وحلها.
</p>

<h2>
	تشغيل اللعبة
</h2>

<p>
	شغل اللعبة وتفقد نجاح العملية.
</p>

<p>
	يزداد رصيد اللاعب من النقاط مع كل جائزة يغتنمها، وتنخفض مؤشرات سلامته أو صحته كلما اصطدم بعدو.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109029" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-score_1.png.070f4ec601c41142c7fcf13307eba89d.png" rel="" data-fileext="png"><img alt="pygame-score" class="ipsImage ipsImage_thumbnailed" data-fileid="109029" data-unique="n7f4347in" style="width: 450px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-score_1.png.070f4ec601c41142c7fcf13307eba89d.png"></a>
</p>

<p>
	لكنك ستكتشف مع تقدم اللعبة مشكلةً بسيطة أخرى، فنقاط صحة اللاعب تنخفض كثيرًا بطريقةٍ غير عادلة مع كل تصادم بالعدو، وسنعالجها في الفقرة القادمة.
</p>

<p>
	لا يعطل هذا النوع من الأخطاء عمل البرنامج فهو ليس من الأخطاء "القاتلة" إنما يعد من المشكلات البسيطة التي تعطي نتائج غير منطقية أو تزعج المستخدم.
</p>

<h2>
	إصلاح عداد صحة البطل
</h2>

<p>
	المشكلة في عداد صحة اللاعب أن نقاطه تتناقص مع كل نبضة ساعة يكون فيها العدو والبطل في حالة تصادم، وهذا غير عادلة طبعًا بالعدو بطيء الحركة سينقص صحة اللاعب بمقدار 200- نقطة أو ربما أكثر، يمكنك بكل بساطة زيادة رصيد الصحة الابتدائي للاعبك إلى رقم كبير نسبيًا مثل 10000 سيخفف هذا من أثر المشكلة لكنه لا يعد حلًا مثاليًا.
</p>

<p>
	فالحل الأفضل يكتشف حادثتين عوضًا عن واحدة، فلن يكتشف التصادم فقط إنما أيضًا انتهاء التصادم.
</p>

<p>
	عرّف المتغير الموجود في السطر الأخير ضمن صنف اللاعب ليمثل حالة التصادم بين البطل والعدو:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_32" style=""><span class="pln">        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	والآن استبدل كتلة التعليمات التالية في دالة التحديث <code>update</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_34" style=""><span class="pln">        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="com">#print(self.health)</span></pre>

<p>
	بهذه الكتلة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_36" style=""><span class="pln">       </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">):</span><span class="pln">
                    self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">colliderect</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span></pre>

<p>
	يوجد بعض التشابه بين كتلة االتعليمات المحذوفة والكتلة البديلة فكلاهما يؤديان نفس الغرض إلّا أن الجديدة أعقد فهي تعمل لمرة واحدة فقط عند انتهاء التصادم ولا تعمل باستمرار وتنقص النقاط باستمرار مثل التعليمات القديمة، وتسنخدم دالتين من Pygame نتعرف عليهما للمرة الأولى في هذه السلسلة.
</p>

<p>
	الدالة الأولى هي <code>self.rect.contains</code> مهمتها معرفة فيما إذا كان العدو متواجدًا داخل المربع المحيط باللاعب في لحظة التنفيذ. والدالة الثانية <code>self.rect.colliderect</code> تعطي المتغير <code>self.damage</code> القيمة 1 إذا كانت نتيجة الدالة الأولى محققة أي أن العدو داخل المربع المحيط بالبطل بغض النظر عن عدد مرات تحققها.
</p>

<p>
	وبدءًا من الآن سيُعدّ التصادم بين العدو والبطل لمدة ثلاث ثواني حادث تصادم واحد فقط من وجهة نظر Pygame ويخصم عنه مرة واحدة فقط.
</p>

<p>
	يمكننا دومًا اكتشاف هذه الدوال بقراءة توثيقات Pygame وقد وفرت الكثير من العناء والبرمجة، ننصحك دائمًا بقراءة التوثيقات ولا نعني بذلك قراءة كل توثيقات المكتبة أو اللغة وقراءة كل كلمة فيها لكن اهتم بقراءة توثيقات الوحدات الجديدة التي تستخدمها، اطلع على مزاياها سيوفر ذلك عليك إعادة اختراع العجلة كما يقال ويغنيك عن المحاولات المضنية لاكتشاف الحلول لمشاكل محلولة أساسًا.
</p>

<p>
	اكتب أخيرًا التعليمات التالية لتكتشف انتهاء حالة التصادم أو التلامس بين اللاعب والعدو وعندها فقط يطرح البرنامج نقطة واحدة من رصيد صحة اللاعب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_38" style=""><span class="pln">        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            idx </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">collidelist</span><span class="pun">(</span><span class="pln">enemy_hit_list</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> idx </span><span class="pun">==</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">   </span><span class="com"># تصفير قيمة المتغير</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">  </span><span class="com"># إنقاص نقطة من صحة اللاعب</span></pre>

<p>
	لا تعمل التعليمات السابقة ما لم يحدث التصادم مع العدو فهي لا تتأثر بركض اللاعب في عالم اللعبة أو جمعه للجوائز والكنوز شرطها الوحيد هو تنشيط المتغير <code>self.damage</code>.
</p>

<p>
	وعندما تعمل فإنها تستخدم <code>Self.rect.collidelist</code> لتبيان إن كان تصادم البطل مع عدو ينتمي لمجموعة الأعداء ما زال مستمرًا أم أنه انتهى (ويعطي عنها <code>collidelist</code> القيمة 1-) وبمجرد انتهاء التصادم تعاد قيمة المتغير <code>self.damage</code> وتخصم نقطة من صحة اللاعب.
</p>

<p>
	شغل اللعبة الآن.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109028" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-02-pygame-health_1.png.df8b67dded501048d557d59568f46e5c.png" rel="" data-fileext="png"><img alt="pygame-health" class="ipsImage ipsImage_thumbnailed" data-fileid="109028" data-unique="n4lcmzthm" style="width: 450px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-02-pygame-health_1.png.df8b67dded501048d557d59568f46e5c.png"></a>
</p>

<p>
	يفتح لك إظهار النتائج خياراتٍ جديدة في لعبتك، يمكنك مثلًا إضافة نوع معين من الجوائز يعوض اللاعب بعضًا من نقاط صحته أو ربما تريد للاعبك أن يعود إلى بداية المستوى عندما يصل رصيد صحته إلى الصفر.
</p>

<p>
	كل ما عليك هو تجربة المبادئ التي تعلمتها لتكتشف هذه الأحداث المتنوعة وتطور عالم اللعبة وفق ما تريد.
</p>

<h2>
	طور مهاراتك
</h2>

<p>
	طوّر مهارتك في <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> واستفد من التوثيقات، تعرف على مكاتب ووحداتٍ جديدة وابتكر ألعابًا أو تطبيقات جديدة فهذه اللغة متعددة الأغراض والبرمجة تحتاج للمثابرة، واجعل برامجك مفتوحة المصدر ليساهم معك مطورو بايثون من مختلف أنحاء العالم.
</p>

<p>
	سنضيف في المقال التالي بعض الآليات القتالية للعبة، وننهي هذا المقال بتذكيرك ببرنامج اللعبة كامًلا حتى الآن:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7601_44" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">
forwardx  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">600</span><span class="pln">
backwardx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">120</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">80</span><span class="pun">,</span><span class="pln"> </span><span class="lit">80</span><span class="pun">,</span><span class="pln"> </span><span class="lit">155</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

font_path </span><span class="pun">=</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">dirname</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">realpath</span><span class="pun">(</span><span class="pln">__file__</span><span class="pun">)),</span><span class="pln"> </span><span class="str">"fonts"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"amazdoom.ttf"</span><span class="pun">)</span><span class="pln">
font_size </span><span class="pun">=</span><span class="pln"> tx
pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
myfont </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">freetype</span><span class="pun">.</span><span class="typ">Font</span><span class="pun">(</span><span class="pln">font_path</span><span class="pun">,</span><span class="pln"> font_size</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> stats</span><span class="pun">(</span><span class="pln">score</span><span class="pun">,</span><span class="pln">health</span><span class="pun">):</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Score:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">score</span><span class="pun">),</span><span class="pln"> BLUE</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span><span class="pln">
    myfont</span><span class="pun">.</span><span class="pln">render_to</span><span class="pun">(</span><span class="pln">world</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">72</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Health:"</span><span class="pun">+</span><span class="pln">str</span><span class="pun">(</span><span class="pln">health</span><span class="pun">),</span><span class="pln"> BLUE</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> size</span><span class="pun">=</span><span class="lit">64</span><span class="pun">)</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x

    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># collisions</span><span class="pln">
        enemy_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">):</span><span class="pln">
                    self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">colliderect</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            idx </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">collidelist</span><span class="pun">(</span><span class="pln">enemy_hit_list</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> idx </span><span class="pun">==</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">damage </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">   </span><span class="com"># set damage back to 0</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">  </span><span class="com"># subtract 1 hp</span><span class="pln">

        ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">

        </span><span class="com"># fall off the world</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># how high to jump</span><span class="pln">

        loot_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> loot_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> loot </span><span class="kwd">in</span><span class="pln"> loot_hit_list</span><span class="pun">:</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">score</span><span class="pun">)</span><span class="pln">

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">550</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list

    </span><span class="kwd">def</span><span class="pln"> loot</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            loot_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            loot </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">tx</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'loot_1.png'</span><span class="pun">)</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> loot_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="lit">80</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">
gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc </span><span class="pun">)</span><span class="pln">
loot_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">loot</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># scroll the world forward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll

    </span><span class="com"># scroll the world backward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    loot_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    stats</span><span class="pun">(</span><span class="pln">player</span><span class="pun">.</span><span class="pln">score</span><span class="pun">,</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/20/1/add-scorekeeping-your-python-game" rel="external nofollow">Add scorekeeping to your Python game</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1734</guid><pubDate>Wed, 26 Oct 2022 16:03:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x627;&#x644;&#x62C;&#x648;&#x627;&#x626;&#x632; &#x625;&#x644;&#x649; &#x627;&#x644;&#x644;&#x639;&#x628;&#x629; &#x627;&#x644;&#x645;&#x637;&#x648;&#x631;&#x629; &#x628;&#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633c07b03fde6_------.png.15ec0403cc8110f2b0a94e612362cf08.png" /></p>
<p>
	سيُمنح اللاعب بعضًا من الجوائز ليجمعها ويعزز نقاطه في هذا الإصدار من اللعبة المطورة باستخدام <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">بايثون 3</a> والوحدة <a href="https://www.pygame.org/news" rel="external nofollow">Pygame</a> المتخصصة بألعاب الفيديو، والبداية مع روابط مقالات هذه السلسلة.
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		إضافة الجوائز إلى اللعبة المطورة بلغة بايثون.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<p>
	عرضت هذه السلسلة المبادئ الأساسية لتطوير ألعاب الفيديو باستخدام <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a>، ولابدّ أنها منحتك أساسًا جيدًا تنطلق منه لبناء لعبتك الخاصة، لا تتقيد حرفيًا بأسلوب السلسلة، بل استخدم المبادئ نفسها بطرقٍ جديدة، عدّلها لتبرمج عناصرك الخاصة وشروط اللعب التي تريدها.
</p>

<p>
	مقال اليوم هو خيرُ مثالٍ على ذلك، إذ ستلاحظ التشابه الكبير في المبادئ بين إضافة المنصات التي تعلمتها سابقًا وإضافة الجوائز، فكلاهما من كائنات اللعبة التي لا تخضع لتحكم خارجي من قبل المستخدم، إنما تُمرر مع عالم اللعبة خلال مستوياتها المتتابعة، وفي الحالتين تحتاج إلى طريقةٍ برمجية لاكتشاف التصادم بين كائن البطل وهذه الكائنات واحتساب تأثيره على نقاط اللاعب وصحته سواءً سلبًا أو إيجابًا.
</p>

<p>
	وقبل أن تبدأ جهّز صورًا تمثل الكنوز أو الجوائز التي يجمعها اللاعب، اختر صورًا لعملات معدنية أو جواهر أو ما شابه، يمكنك تحميل حزمة الصور نفسها من موقع <a href="https://kenney.nl/assets/simplified-platformer-pack" rel="external nofollow">kenney.nl</a> التي أخذنا منها صور البلاطات المربعة لبناء منصات اللعبة فهي تتضمن صور جواهر ومفاتيح وكلاهما يفي بالغرض.
</p>

<h2>
	بناء دالة الجوائز
</h2>

<p>
	إضافة الجوائز والكنوز إلى لعبة مشابه جدًا لإضافة المنصات كما ذكرنا في المقدمة، في الواقع هو مشابه لدرجة تجعلنا نستدعي صنف المنصة نفسه <code>Platform</code> لإنتاجها.
</p>

<p>
	ابدأ بإنشاء دالة جديدة تحمل الاسم <code>loot</code> في صنف المستوى <code>level</code> إذ من المحتمل جدًا أن يتبدل نوع الجوائز بين مستوى وآخر، وتمامًا مثلما فعلنا مع المنصات العائمة والأرضية والأعداء أنشئ في هذه الدالة مجموعة خاصة بكائنات الجوائز سميها <code>loot_list</code> وأضف إليها الجوائز، ستُفيدك هذه المجموعة في عملية اكتشاف التصادمات.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_8" style=""><span class="pln">   </span><span class="kwd">def</span><span class="pln"> loot</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            loot_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            loot </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">tx</span><span class="pun">*</span><span class="lit">9</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'loot_1.png'</span><span class="pun">)</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> loot_list</span></pre>

<p>
	استخدم هذا المثال أبعاد قطع البلاط <code>ty</code> و <code>tx</code> لتحديد إحداثيات ظهور الجوائز من خلال مضاعفاتها للسهولة فقط، ستفيدك هذه الطريقة إن خططت للمستوى على أوراق الرسم البياني مع تمثيل كل بلاطة بمربع أو كان المستوى الذي صممته طويلًا، لكن في النهاية يعود الخيار لك إذ يمكنك عوضًا ذلك كتابة إحداثيات كل جائزة صراحةً برقم مقدر بالبكسل فتصبح هذه الأرقام مدمجة مع برنامج اللعبة hard-coded.
</p>

<p>
	لا تنسَ أن باستطاعتك إظهار القدر الذي تريده من الجوائز المتنوعة لكن بشرط أن تضيفها جميعًا لمجموعة الجوائز.
</p>

<p>
	أما بالنسبة لوسطاء صنف المنصة <code>Platform</code> في هذه الحالة فهم إحداثيات موقع ظهور الجائزة X و Y بالإضافة إلى أبعاد صورة الجائزة، وننصحك بالتخطيط لأماكن توضع الجوائز منذ البداية وتضمينها في مخطط تصميم المستوى واختيار صور مربعة لتمثيلها تعادل أبعادها أبعاد بلاطات الأرضية والمنصات فهذا سيوفر عليك الكثير.
</p>

<p>
	استدعِ الآن دالة الجوائز في مقطع الإعدادات ضمن البرنامج وفق التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_12" style=""><span class="pln">loot_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">loot</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span></pre>

<p>
	وأخيرًا اذكرها ضمن الحلقة الرئيسية لتظهر على الشاشة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_14" style=""><span class="pln">    loot_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span></pre>

<p>
	شغل اللعبة ولاحظ النتائج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="109027" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-loot.jpg.dda16aedfe11fdd14868b291c035c563.jpg" rel=""><img alt="img-01-pygame-loot.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="109027" data-unique="z2hxryd72" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-loot.thumb.jpg.2286b971ebc0af364bb9f646ae23443f.jpg"></a>
</p>

<p>
	ظهرت صورة الجائزة بعد تشغيل اللعبة، إلّا أنها لم تُحدث أي تأثير على اللاعب عندما اصطدم بها ولم تُمرر مع تحرك اللاعب وتمرير عالم اللعبة، وهذا هو موضوع فقراتنا اللاحقة.
</p>

<h2>
	تمرير الجوائز مع عالم اللعبة
</h2>

<p>
	تمامًا مثل المنصات ينبغي أن تُمرر الجوائز مع عالم اللعبة إلى الأمام والخلف تبعًا لحركة البطل.
</p>

<p>
	اكتب السطرين الأخيرين من التعليمات التالية لتُمرر الجوائز إلى الأمام:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_18" style=""><span class="pln">        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">     </span><span class="com"># تمرير الجوائز</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll  </span><span class="com"># تمرير الجوائز</span></pre>

<p>
	واكتب السطرين الأخيرين من التالي لتُمررها للخلف:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_20" style=""><span class="pln">        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">     </span><span class="com"># تمرير الجوائز</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll  </span><span class="com"># تمرير الجوائز</span></pre>

<p>
	تفقد اللعبة الآن واختبر التمرير بالاتجاهين، ولاحظ أن الجوائز أصبحت تتصرف وكأنها عنصر أصيل من عناصر عالم اللعبة وليست مجرد صورة.
</p>

<h2>
	اكتشاف التصادم
</h2>

<p>
	استخدم ما تعلمته سابقًا عند اكتشاف تصادم البطل مع الأرضية والمنصات العائمة والأعداء لتكتشف لتصادمه مع الجوائز، الطريقة نفسها تمامًا إلّا أن النتائج المترتبة على التصادم ستكون مختلفة فهي لن تتعلق بالجاذبية ولن تُنقص من صحة اللاعب وأدواره بل ستؤدي إلى زيادة نقاطه واختفاء الجائزة التي اصطدم بها من عالم اللعبة، وذلك عبر إزالتها من مجموعة كائنات الجوائز <code>loot_list</code> ما يعني أنها لن تظهر مجددًا في المرة القادمة التي تُعيد فيها الحلقة الرئيسية رسم عالم اللعبة، وهذا منطقي فالبطل اغتنمها وحاز على بعض النقاط بسببها.
</p>

<p>
	اكتب التعليمات التالية في الدالة <code>update</code> ضمن صنف اللاعب <code>Player</code> تمامًا فوق التعليمات المسؤولة عن اكتشاف التصادم مع المنصات، وانتبه للسطر الأخير فهو لتبيان السياق فقط وما من داعٍ لتعيد كتابته:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_22" style=""><span class="pln">                loot_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> loot_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
                </span><span class="kwd">for</span><span class="pln"> loot </span><span class="kwd">in</span><span class="pln"> loot_hit_list</span><span class="pun">:</span><span class="pln">
                        loot_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">
                        self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">score</span><span class="pun">)</span><span class="pln">

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span></pre>

<p>
	عرّف الآن المتغير الذي استخدمه لزيادة نقاط اللاعب بعد الاصطدام بالجائزة في الدالة <code>__init__</code> الموجودة في صنف اللاعب وهي المسؤولة عن تحديد خصائصه المختلفة، وذلك بكتابة السطر الثالث من التعليمات أدناه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_24" style=""><span class="pln">       self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<h2>
	طبق المهارات التي تعلمتها في السابق
</h2>

<p>
	طبق المهارات التي تعلمتها خلال هذه السلسلة وأضف الأعداء في أماكن مناسبة، خطط لذلك ومن ثم عدّل برنامج اللعبة، حاول أيضًا الاستفادة من المبادئ الأساسية، ووظفها بطرقٍ أخرى، وصمم ألعابًا متنوعة وإن كانت وحيدة المستوى في المرحلة كبداية، ولا تنسَ التخطيط الجيد للعبة قبل البرمجة، فكر بأوسع نطاق تريده وبرمج على هذا الأساس، يساعدك ذلك في الحصول على إصداراتٍ جيدة لا تتطلب كثيرًا من التعديلات.
</p>

<p>
	وفي ختام المقال نذكرك ببرنامج اللعبة كاملًا من بداية السلسلة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2231_26" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">
forwardx  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">600</span><span class="pln">
backwardx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">120</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x

    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># collisions</span><span class="pln">
        enemy_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="com"># print(self.health)</span><span class="pln">

        ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">

        </span><span class="com"># fall off the world</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># how high to jump</span><span class="pln">

        loot_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> loot_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> loot </span><span class="kwd">in</span><span class="pln"> loot_hit_list</span><span class="pun">:</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">score </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">score</span><span class="pun">)</span><span class="pln">

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">550</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list

    </span><span class="kwd">def</span><span class="pln"> loot</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            loot_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            loot </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">tx</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">*</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'loot_1.png'</span><span class="pun">)</span><span class="pln">
            loot_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">loot</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> loot_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">

gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc </span><span class="pun">)</span><span class="pln">
loot_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">loot</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># scroll the world forward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll

    </span><span class="com"># scroll the world backward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> l </span><span class="kwd">in</span><span class="pln"> loot_list</span><span class="pun">:</span><span class="pln">
            l</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    loot_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/20/1/loot-python-platformer-gam" rel="external nofollow">Put some loot in your Python platformer game</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة في بايثون</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1733</guid><pubDate>Sun, 23 Oct 2022 16:09:00 +0000</pubDate></item><item><title>&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x628;&#x64A;&#x626;&#x629; &#x627;&#x644;&#x639;&#x645;&#x644; &#x644;&#x644;&#x645;&#x634;&#x627;&#x631;&#x64A;&#x639; &#x645;&#x639; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%84%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D9%85%D8%B9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1751/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/Untitled-3.png.5630b88d6664873c8da50c55a19cec78.png" /></p>

<p>
	تُناسب <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> الكثير من التطبيقات البرمجية نظرًا لتمتعها بالعديد من المزايا المهمة كالمرونة العالية وتوفير المكتبات الجاهزة فيها للقيام بعمليات الأتمتة وتحليل البيانات ومعالجة مسائل <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-r1009/" rel="">تعلم الآلة</a> والتطوير الخلفي back-end وغيرها من المهام البرمجية بسرعة وسهولة. ظهرت النسخة الأولى منها في عام 1991 وسُميت تيمنًا بالفرقة الكوميدية البريطانية Monty Python هادفة جعل كتابة الكود فيها أمرًا ممتعًا، ويعد الإصدار الثالث أحدث نسخة وهو المستقبل الواعد <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A8%D9%86%D8%A7%D8%A1-%D8%B1%D9%88%D8%A8%D9%88%D8%AA%D8%A7%D8%AA-%D9%84%D9%84%D8%B9%D8%A8-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B7%D8%B1%D9%8A%D9%82%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D9%85%D8%B9%D8%B2%D8%B2-%D9%88%D9%85%D8%B4%D8%AA%D9%82%D8%A7%D8%AA%D9%87%D8%A7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-tensorflow-r1268/" rel="">لبايثون</a>.
</p>

<p>
	يعرض هذا المقال خطوات تثبيت بيئة بايثون على الحاسوب المحلي أو <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r574/" rel="">الخادم</a> البعيد لتطبيق المشاريع العملية اللاحقة في الكتاب، أما إذا كان بايثون مع أدواته pip و venv جاهزًا على حاسوبك فيُمكنك الانتقال مباشرة إلى الفصل التالي.
</p>

<h2>
	المتطلبات الرئيسية
</h2>

<p>
	نعمل في بيئة <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس Linux</a> أو الشبيهة بيونكس Unix-like ونستخدم ضمن <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">نظام التشغيل</a> ماكنتوش macOS <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر الأوامر command line</a> أو بيئة الطرفية terminal environment، أما في نظام ويندوز، فيمكن استعمال بورشيل PowerShell لتحقيق نفس النتائج عمليًا.
</p>

<h2>
	الخطوة الأولى: تثبيت بايثون
</h2>

<p>
	يثبت <a href="https://wiki.hsoub.com/Python" rel="external">بايثون </a>على العديد من أنظمة التشغيل بشكل افتراضي. للتأكد من وجود الإصدار 3 من بايثون مثبتًا على جهازك قم بفتح نافذة طرفية واكتب فيها ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_13" style="">
<span class="pln">python3 </span><span class="pun">-</span><span class="pln">V</span></pre>

<p>
	سيظهر، في حال كون الإصدار 3 من بايثون مثبتًا، رقم الإصدار والذي يُمكن بالطبع أن يختلف حسب النسخة المُنصبة، وفي جميع الأحوال، يكون الخرج مشابهًا لما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_15" style="">
<span class="typ">Python</span><span class="pln"> </span><span class="lit">3.7</span><span class="pun">.</span><span class="lit">2</span><span class="pln"> </span></pre>

<p>
	في حال لم تحصل على الإظهار السابق، فعليك أولًا تنزيل النسخة من موقع بايثون <a href="https://www.python.org/" rel="external nofollow">python.org</a> ومن ثم اتباع خطوات التثبيت المُحدّدة. بعد انتهائك من تثبيت بايثون وتأكدك من ذلك بمعاينة رقم الإصدار باتباع التعليمة السابقة يُمكنك الانتقال للخطوة التالية.
</p>

<h2>
	الخطوة الثانية: تثبيت pip
</h2>

<p>
	يجب تثبيت الأداة pip والتي تسمح بتثبيت وإدارة حزم البرمجيات المساندة لبايثون. ستكون هذه الأداة جاهزة فيما لو قمت بتثبيت بايثون من الموقع <a href="http://python.org/" rel="external nofollow">python.org</a>، أما إذ كنت على خادم أو حاسوب <a href="https://academy.hsoub.com/devops/linux/%D9%81%D9%8A-%D9%85%D8%A7%D8%B0%D8%A7-%D9%8A%D8%AE%D8%AA%D9%84%D9%81-ubuntu-%D8%B9%D9%86-debian%D8%9F-r235/" rel="">بتوزيعة أبنتو Ubuntu أو ديبيان Debian</a> فيُمكنك تنزيل pip بكتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_18" style="">
<span class="pln">sudo apt install </span><span class="pun">-</span><span class="pln">y python3</span><span class="pun">-</span><span class="pln">pip</span></pre>

<p>
	من الآن فصاعدًا، يُمكنك تنزيل أي حزمة برمجيات بكتابة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_20" style="">
<span class="pln">pip3 install package_name</span></pre>

<p>
	حيث package_name هي اسم أي مكتبة أو حزمة برمجية لبايثون مثل <a href="https://academy.hsoub.com/programming/python/django/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-django%C2%A0-r353/" rel="">جانغو Django</a> لتطوير مواقع الويب والحزمة NumPy للحسابات العلمية، فإذا كنت مثلًا تريد استخدام المكتبة NumPy فعليك تنزيلها بكتابة الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_22" style="">
<span class="pln">install numpy</span></pre>

<p>
	يوجد بعض الحزم البرمجية الأساسية الواجب تحميلها للحصول على بيئة عمل مريحة ومرنة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_24" style="">
<span class="pln">sudo apt install build</span><span class="pun">-</span><span class="pln">essential libssl</span><span class="pun">-</span><span class="pln">dev libffi</span><span class="pun">-</span><span class="pln">dev python3</span><span class="pun">-</span><span class="pln">dev</span></pre>

<p>
	يُمكن الآن بعد الانتهاء من المراحل السابقة إعداد بيئة عمل افتراضية.
</p>

<h2>
	الخطوة الثالثة: إعداد بيئة عمل افتراضية
</h2>

<p>
	تسمح بيئة العمل الافتراضية بعزل كل مشروع مع حزمه البرمجية التابعة له عن بقية المشاريع الأخرى وذلك عن طريق تخصيص مساحة خاصة له على الخادم، مما يسمح أيضًا بتنظيم الإصدارات المختلفة للمشروع. وهو أمر ضروري لاسيما عند استخدامنا لحزم برمجية خارجية.
</p>

<p>
	يُمكن إنشاء بيئة عمل افتراضية لكل مشروع وهي عمليًا عبارة عن مجلد معين على الخادم مع بعض الشيفرات البرمجية ضمنه. نستخدم عادةً الأداة <code>venv</code> لإنشاء بيئة عمل افتراضية والتي هي جزء من مكتبة بايثون وتُثبت تلقائيًا خلال تثبيت بايثون.
</p>

<p>
	إذ كنت على خادم أو حاسوب Ubuntu أو Debian فيُمكنك تحميل venv بكتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_29" style="">
<span class="pln">sudo apt install </span><span class="pun">-</span><span class="pln">y python3</span><span class="pun">-</span><span class="pln">venv</span></pre>

<p>
	انتقل لمجلد معين على حاسوبك لوضع بيئة العمل فيه أو قم بإنشاء مجلد جديد باستخدام تعليمة إنشاء مجلد <code>mkdir</code> ثم انتقل له باستخدام تعليمة الانتقال لمجلد <code>cd</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_33" style="">
<span class="pln">mkdir environments
cd environments</span></pre>

<p>
	يُمكنك الآن إنشاء بيئة العمل ضمن المجلد الذي انتقلت له وذلك بكتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_35" style="">
<span class="pln">python3</span><span class="pun">.</span><span class="lit">6</span><span class="pln"> </span><span class="pun">-</span><span class="pln">m venv my_env</span></pre>

<p>
	حيث <code>my_env</code> هو اسم بيئة العمل الذي تريده، مع ملاحظة كتابة القسم الأول من رقم الإصدار الذي حصلت عليه سابقًا باستخدام <code>python -V</code> (المثال أعلاه يستخدم الإصدار Python 3.6.3). لو كُنت مثلًا تستخدم الإصدار Python 3.7.3 فعليك كتابة:
</p>

<pre class="ipsCode">
python3.7 -m venv my_env
</pre>

<p>
	يسمح لك ويندوز بتجاهل رقم الإصدار كليةً وكتابة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_38" style="">
<span class="pln">python </span><span class="pun">-</span><span class="pln">m venv my_env</span></pre>

<p>
	بعد تنفيذ الأمر المناسب لإنشاء بيئة العمل، يُمكن التأكد من إتمام العملية بالاستمرار في الخطوات التالية والتي من أولها معاينة الملفات التي قام <code>venv</code> بإنشائها في المجلد الموافق والتي يُمكن إظهارها باستخدام أمر استعراض محتوى مجلد <code>ls</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_40" style="">
<span class="pln">ls my_env</span></pre>

<p>
	ليكون الخرج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_42" style="">
<span class="pln">bin include lib lib64 pyvenv</span><span class="pun">.</span><span class="pln">cfg share</span></pre>

<p>
	تعمل هذه الملفات على التأكد من العزل الكامل لملفات مشروعك عن باقي ملفات حاسوبك وبذا فلن تختلط ملفاتك مع ملفات نظام التشغيل أبدًا. تسمح هذه الممارسة الجيدة في التحكم بالإصدارات المختلفة للمشروع والتأكد من أن مشروعك يستخدم الحزم البرمجية التي يحتاج إليها.
</p>

<p>
	يُمكن استخدام الحزمة البرمجية الجاهزة Python Wheels التي تسمح بتسريع عملية تطوير البرمجيات وتنفيذ المشروع والموجودة في المجلد share في Ubuntu 18.04، ويجب تفعيل هذه الحزمة قبل بدء استخدامها بكتابة الأمر التالي والذي يقوم باستدعاء السكربت activate:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_44" style="">
<span class="pln">source my_env</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">activate </span></pre>

<p>
	من الآن فصاعدًا، ستبدأ أوامرك باسم بيئة العمل (المدعوة في أمثلتنا my_env). يُمكن للبادئة أن تظهر أحيانًا بشكل مختلف وذلك حسب الإصدار المستخدم من لينكس ديبيان Debian Linux إلا أنه، وفي جميع الأحوال، يجب أن تبدأ أوامرك باسم بيئة العمل ضمن قوسين:
</p>

<pre class="ipsCode">
(my_env) sammy@sammy:~/environments$
</pre>

<p>
	تُحدّد هذه البادئة بأن بيئة العمل my_env هي البيئة النشطة الحالية مما يعني أنه عندما نُنشئ برامج هنا فستستخدم إعدادات ومكتبات هذه البيئة.
</p>

<p>
	لاحظ أنه يُمكنك ضمن بيئة العمل الافتراضية استخدام python عوضًا عن python3 و pip عوضًا عن pip3 إن وجدت ذلك مناسبًا. أما خارج بيئة العمل الافتراضية فلا يُمكنك القيام بذلك بل عليك استخدام python3 و pip3.
</p>

<h2>
	الخطوة الرابعة: إنشاء البرنامج الأول
</h2>

<p>
	يُمكنك الآن إنشاء البرنامج التقليدي الترحيبي الأول "Hello, World" مما يسمح لك بالتأكد من جاهزية بيئة العمل.
</p>

<p>
	افتح مثلًا محرر النصوص nano وأنشئ ملفًا جديدًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_46" style="">
<span class="pun">(</span><span class="pln">my_env</span><span class="pun">)</span><span class="pln"> sammy@sammy</span><span class="pun">:~/</span><span class="pln">environments$ nano hello</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	ثم اكتب في نافذة المحرر المفتوحة أول برنامج بسيط في بايثون:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_48" style="">
<span class="kwd">print</span><span class="pun">(</span><span class="str">"Hello, World!"</span><span class="pun">)</span></pre>

<p>
	أغلق المحرر nano بالضغط على الاختصار Ctrl+X ولا تنسَ حفظ الملف بالإجابة بنعم y عندما تُسأل عن حفظ الملف.
</p>

<p>
	بعد إغلاق nano والعودة لصدفة shell النظام، يُمكنك تنفيذ البرنامج السابق hello.py:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_50" style="">
<span class="pun">(</span><span class="pln">my_env</span><span class="pun">)</span><span class="pln"> sammy@sammy</span><span class="pun">:~/</span><span class="pln">environments$ python hello</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	والذي سيُظهر على المحطة الطرفية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_52" style="">
<span class="typ">Hello</span><span class="pun">,</span><span class="pln"> </span><span class="typ">World</span><span class="pun">!</span></pre>

<p>
	للخروج من بيئة العمل والعودة للمجلد الأساسي، نفذّ الأمر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5250_54" style="">
<span class="pln">deactivate</span></pre>

<h2>
	النتائج
</h2>

<p>
	لقد حصلت نتيجة تطبيقك للخطوات السابقة على بيئة بايثون جاهزة لاحتضان المشاريع البرمجية على حاسوبك ويُمكنك الآن الانطلاق في تطبيق المشاريع البرمجية في الفصول التالية!
</p>

<p>
	إن أردت التعرف أكثر على بايثون، فيمكنك الرجوع إلى كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%B5%D9%84-%D9%85%D8%B9-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D8%B9%D8%A8%D8%B1-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1520/" rel="">التواصل مع نظام التشغيل عبر بايثون</a>
	</li>
	<li>
		النسخة الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1751</guid><pubDate>Fri, 21 Oct 2022 18:00:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x62E;&#x627;&#x635;&#x64A;&#x629; &#x627;&#x644;&#x642;&#x641;&#x632; &#x648;&#x627;&#x644;&#x631;&#x643;&#x636; &#x625;&#x644;&#x649; &#x644;&#x639;&#x628;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633bfec51951e_-------.png.aeae6b381c349cfe0301e64b8757bcdc.png" /></p>
<p>
	تناول <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">المقال السابق</a> من هذه السلسلة محاكاةً برمجية لقوى الجاذبية وتأثيرها على تحركات بطل اللعبة، وفي هذا المقال سيتوفر للبطل ما يعينه على مواجهة أثرها ولو للحظات معدودة عبر منحه خاصية القفز.
</p>

<p>
	سيَقفز اللاعب وعندما يصل لذروة قفزته ستُطبق عليه الجاذبية من جديد فيعود للسقوط، فما هي الآلية التي تحكم ذلك وكيف يميز البرنامج بين القفز والسقوط؟
</p>

<p>
	الآلية المستخدمة هنا تعتمد على المتغيرات، إذ سنعرف بدايةً متغير خاص يراقب حالة اللاعب ويخبر <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون</a> بأن اللاعب يقفز الآن ليطبق عليه الجاذبية فيسقط بتأثيرها على أقرب كائن لموقعه من كائنات اللعبة.
</p>

<p>
	قبل أن نبدأ نذكرك بمقالات السلسلة:
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		إضافة خاصية القفز والركض إلى لعبة بايثون.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<h2>
	ضبط متغيرات القفز
</h2>

<p>
	سنضيف متغيرين جديدين إلى صنف اللاعب.
</p>

<ul>
	<li>
		يتتبع المتغير الأول حالة القفز عند اللاعب، ويحدد في كل لحظة إن كان الكائن يقفز أم يقف على أرضٍ صلبة.
	</li>
	<li>
		أما المتغير الثاني فيسحب كائن اللاعب إلى أرضية اللعبة.
	</li>
</ul>

<p>
	بناءً على ما سبق عرّف المتغيرات المنطقية التالية ضمن صنف اللاعب علمًا أن أول سطرين لتبيان السياق فقط ولا حاجة لإعادة كتابتها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_9" style=""><span class="pln">        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        </span><span class="com"># أدناه المتغيرات الخاصة بالقفز</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span></pre>

<p>
	إنه الاستخدام الأول للمتغيرات المنطقية في هذه السلسلة والتي تسمى أيضًا بالمتغيرات البوليانية نسبةً إلى عالم الرياضيات جورج بول، تأخذ هذه المتغيرات إحدى قيمتين فقط لا ثالث لهما إما صحيح <code>True</code> أو خاطئ <code>False</code>، أي أن اللاعب يقفز أو لا يقفز وفقًا للمتغير الأول، ويسقط أو لا يسقط وفقًا للمتغير الثاني.
</p>

<p>
	لاحظ أننا أعطينا المتغير الأول <code>is_jumping</code> الذي يشير إلى القفز قيمةً ابتدائية هي <code>True</code>، ذلك أن كائن البطل في مثالنا يظهر بدايةً في سماء عالم اللعبة وينبغي سحبه إلى الأسفل مباشرةً ليبدأ اللعب، وكانت هذه أسهل الطرق لإنجاز ذلك رغم أنها لا توظف المتغير المنطقي توظيفًا مثاليًا لكنها تغنينا عن كتابة تعليمات خاصة تحدد موقع إنتاج البطل في كل مستوى، زد على أنها تُذكرنا بالألعاب الكلاسيكية التي يقفز فيها اللاعب إلى عالم اللعبة في لحظة البدء، فاعتمد هذه الخدعة البسيطة وسهّل برنامجك لا بأس في ذلك.
</p>

<p>
	أما المتغير الثاني <code>is_falling</code> فقد أُسندت له القيمة الابتدائية <code>False</code> ليهبط اللاعب إلى الأرضية فور بدء اللعبة.
</p>

<h2>
	شروط تفعيل أثر الجاذبية
</h2>

<p>
	القفز في العالم الحقيقي هو فعل مقاوم للجاذبية، وفي لعبتنا ستعمل الجاذبية في حالة واحدة فقط هي قفز اللاعب -أي عدم وقوفه على أرضٍ صلبة- وتتوقف في بقية الحالات، أما إن عملت باستمرار كما في المقال السابق فإن اللاعب سيعاني ارتدادًا دائمًا بسبب سحبه للاصطدام بالأرض.
</p>

<p>
	الجاذبية في ألعاب الفيديو هي دالة تُبنى خصيصًا في بعض الألعاب لتحاكي الجاذبية الأرضية الحقيقية، وليست ميزة مضمنة في محركات الألعاب مثل Pygame وهي بطبيعة الحال لا تُدار من قبلها، فبعض الألعاب المطورة باستعمال Pygame لا تحتاج للجاذبية مطلقًا وفقًا لقصتها وتصميمها، والسقوط ليس سقوطًا بالمعنى الفعلي للكلمة بل مجرد تحريك للكائن تفرضه الدالة، وحتى تمنح البطل قدرة القفز ومقاومة الجاذبية أو الاصطدام بالمنصات العائمة عليك بالتأكيد تعديل هذه الدالة وجعلها تنشط فقط عندما يقفز.
</p>

<p>
	عدّل إذًا دالة الجاذبية التي استخدمناها في المقال السابق لتصبح على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_11" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span></pre>

<p>
	تتسبب هذه الدالة في سقوط البطل إلى أسفل الشاشة مباشرةً متجاوزًا الأرضية والفقرة التالية ستُعالج ذلك من خلال اكتشاف تصادمه مع أرضية اللعبة.
</p>

<h2>
	برمجة الأرضية الصلبة
</h2>

<p>
	طبقنا في المقال السابق حيلةً بسيطة لمنع كائن البطل من السقوط بعيدًا إلى أسفل الشاشة وجعلناه يرتد إلى مسافة معينة تبقيه ضمن الشاشة، يمكننا تشبيه هذه الحيلة بإنشاء جدار غير مرئي بارتفاعٍ معين يمتد على عرض الشاشة من الأسفل، لا يسعنا فعليًا التمسك بهذه الطريقة فهي لا تحقق معيار الشيفرة النظيفة في البرمجة، ففي الشيفرة النظيفة تُمثل الكائنات بكائنات برمجية فعلية (ونعني بذلك الجدار الوهمي الذي ذكرناه)، أضف إلى ذلك أننا لابد سنحتاج في بعض الحالات إلى إسقاط بطلنا حتى أسفل عالم اللعبة ربما عقبًا له على قفزة خاطئة أو عند خسارة كل نقاطه أو ما شابه فهذه الحركة شائعة في تصميم الألعاب.
</p>

<p>
	اكتب التعليمات التالية في الدالة <code>update</code> ضمن صنف اللاعب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_13" style=""><span class="pln">ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># إيقاف القفز</span><span class="pln">

        </span><span class="com"># السقوط عبر عالم اللعبة</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty</span></pre>

<p>
	تتحقق هذه التعليمات من حدوث التصادم بين كائن الأرضية وكائن البطل وفق الأسلوب نفسه الذي استخدمناه للتحقق من التصادم بين البطل والعدو.
</p>

<p>
	وفي حال حدوث التصادم ستعدّل هذه التعليمات موضع البطل عبر تعديل قيمة <code>self.rect.bottom</code> التي تعني أخفض نقطة في صورة كائن البطل لتصبح مساوية لقيمة <code>g.rect.top</code> التي تعني قمة كائن الأرضية أو أعلى نقطة فيه، وبذلك يبدو البطل كأنه يقف تمامًا فوق أرضية اللعبة ويمنعه ذلك من السقوط إلى الأرضية فهو يقف عليها.
</p>

<p>
	علمًا أن هذه التفاصيل (مثل أخفض نقطة وأعلى نقطة في صورة الكائن) هي معلومات توفرها Pygame عن الكائنات عمومًا ويمكنك دائمًا الاستفادة منها.
</p>

<p>
	بعد تعديل موضع كائن البطل ستُغَيّر هذه التعليمات قيمة <code>self.is_jumping</code> إلى <code>False</code> ليعرف برنامج اللعبة أن البطل لم يعد في حالة قفز بعد الآن، وقيمة <code>self.movey</code> أيضًا إلى <code>0</code> حتى لا يخضع البطل لتأثير الجاذبية (في الواقع هي طرافة في فيزياء اللعبة أن تتوقف عن جذب الكائن إلى الأرض طالما أنه يقف عليها).
</p>

<p>
	أما مهمة <code>if</code> الشرطية في الجزء الأخير من التعليمات فهي اكتشاف القفزات الخاطئة لبطل اللعبة التي ينزل بموجبها تحت مستوى الأرضية، لتَخصم بناءً عليها نقطًا من صحته ومن ثم تعيد إنتاجه في أعلى يسار الشاشة باستخدام القيم <code>ty</code> و <code>tx</code> التي تمثل أبعاد بلاط الأرضية وقد استخدمناها للسهولة فقط في حين تستطيع تحديد الموضع الذي تريد، ويمكنك طبعًا عدم خصم نقاط من صحة اللاعب لقاء السقوط دون مستوى الأرضية فأنت من يحدد شروط اللعبة في نهاية المطاف.
</p>

<h2>
	القفز في Pygame
</h2>

<p>
	أنشئ أولًا دالة القفز <code>jump</code> لتقلب قيم المتغيرات <code>is_falling</code> و <code>is_jumping</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_15" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span></pre>

<p>
	عمليًا الانطلاق الفعلي للقفز يحدث في الدالة <code>update</code> ضمن صنف اللاعب.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_17" style=""><span class="pln">        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># مقدار علو القفزة</span></pre>

<p>
	تعمل هذه التعليمات بشرط تحقق أمرين أن تكون قيمة المتغير <code>is_jumping</code> هي <code>True</code> وقيمة المتغير <code>is_falling</code> هي <code>False</code>، وستُعَدّل عندها إحداثيات كائن البطل على المحور العمودي Y لتصبح 33- بكسل في فضاء عالم اللعبة وقيمتها سالبة بالطبع لأن الصفر في الأعلى والقيم الأصغر هي الأقرب إلى أعلى الشاشة، يعطيك هذا الرقم قفزةً جيدة لكن يمكنك تعديله لتحظى بقفزاتٍ أعلى أو أخفض.
</p>

<p>
	بعد تعديل الإحداثي العمودي تُغَيّر هذه التعليمات قيمة <code>is_falling</code> لتصبح <code>True</code> حتى لا تتراكم القفزات فيُطلق الكائن عاليًا في فضاء اللعبة.
</p>

<h2>
	استدعاء دالة القفز
</h2>

<p>
	أشرنا للقفز سابقًا في مقال <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة عن طريق PyGame</a> وربطناه بالضغط على السهم العلوي من أسهم الاتجاهات على لوحة المفاتيح قبل إنشاء دالة القفز ودون استدعائها وقد اكتفينا حينها بطباعة عبارة تشير للقفز في نافذة الطرفية باستخدام <code>print</code>، والآن يمكننا استدعاء دالة القفز في الحلقة الرئيسية بدلًا من الطباعة.
</p>

<p>
	عدّل القيمة المقابلة للضغط على السهم العلوي في الحلقة الرئيسية لتصبح على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_20" style=""><span class="pln">            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span></pre>

<p>
	يمكنك استخدام زر آخر بدل السهم العلوي مثل زر المسافة إن رغبت بذلك أو الجمع بين الخيارين باستخدام تعليمة <code>if</code> بسيطة، علمًا أن الرمز الذي يعبر عن المسافة في Pygame هو:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_22" style=""><span class="pln">pygame</span><span class="pun">.</span><span class="pln">K_SPACE </span></pre>

<h2>
	الهبوط على المنصات العائمة
</h2>

<p>
	تعاملنا في فقرةٍ سابقة مع اصطدام اللاعب بأرضية اللعبة وما نتج عنه من إيقاف لعمل الجاذبية، والآن سنعيد الخطوات نفسها مع بقية المنصات العائمة، إذ إن أرضية اللعبة والمنصات في مثالنا لا تنتميان لمجموعة الكائنات نفسها بل لمجموعتين مختلفتين، مع العلم أنك تستطيع دمجها معًا في مجموعةٍ واحدة، والتعامل مع الأرضية بصفتها منصة عادية، لكن المقال اعتمد الخيار الأوسع الذي يسمح بتفضيلات إضافية، في النتيجة السماح لكائن البطل بالوقوف على إحدى المنصات يعني أن يكتشف البرنامج تصادمه مع كائن المنصة ويمنع الجاذبية من سحبه إلى الأسفل.
</p>

<p>
	اكتب التعليمات التالية ضمن الدالة <code>update</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_24" style=""><span class="pln">        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># إيقاف القفز</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

            </span><span class="com"># اكتشاف محاولة الوصول للمنصة من الأسفل</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span></pre>

<p>
	تفحص هذه التعليمات كافة المنصات العائمة في اللعبة وتتحقق إن حدث أي تصادم بينها وبين كائن البطل، وفي حال ثبت حدوث التصادم تُعدّل قيمة متغير القفز إلى <code>False</code> وتُعطل حركة البطل على المحور العمودي.
</p>

<p>
	منصات اللعبة عائمة في الهواء ما يعطي الأريحية للاعب بالوصول إليها من الأعلى أو من الأسفل، عادةً ما تمنع الألعاب وصول البطل للمنصات من الأسفل وتسمح به من الأعلى فقط أي عندما يقفز البطل أعلى من مستوى المنصة، يمكنك تجربة الحالتين لكن هذا المثال تعامل مع المنصات على أنها سقوف والجزء الثاني من التعليمات يسمح للاعب بالقفز على المنصة طالما أن قفزته بلغت مسافةً أعلى من قمة المنصة ويمنعه عندما يحاول القفز عليها من الأسفل.
</p>

<p>
	يتحقق السطر الأول من التعليمة <code>if</code> الشرطية فيما إذا كانت قيمة أخفض نقطة من كائن البطل أقل من موقع المنصة ما يعني أن البطل أعلى منها على الشاشة لأن القيم سالبة، وإن تحقق ذلك يُسمح له بالهبوط على المنصة وتتعدل قيمة أخفض نقطة فيه لتصبح مساوية لقيمة قمة كائن المنصة، وإن لم يتحقق الشرط فيزداد الإحداثي Y لموقع لبطل مؤديًا إلى سقوطه نحو الأسفل بعيدًا عن المنصة العائمة التي كان يحاول الوصول إليها.
</p>

<h2>
	السقوط
</h2>

<p>
	إذا شغلت اللعبة الآن ستجد أن دالة القفز تعمل وبطلك يتنقل بين المنصات لكنه لا يسقط أرضًا بعد أن يهبط على أي منصة بل يبقى معلقًا في الهواء، والسبب في ذلك أننا عطلنا الجاذبية عند الهبوط على المنصة ولم نكتب أي تعليمة تعيدها للعمل ثانيةً عندما يصل البطل إلى حافة المنصة.
</p>

<p>
	عدّل دالة التحديث <code>update</code> في صنف اللاعب لتصبح مسؤولة عن تشغيل وإيقاف تشغيل الجاذبية أثناء حركة الكائن وفق التالي انتبه أنك ستحتاج لإضافة الأسطر التي تتضمن تعليقات فقط.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_26" style=""><span class="pln">        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">  </span><span class="com"># إيقاف تشغيل الجاذبية</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">  </span><span class="com"># تشغيل الجاذبية</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span></pre>

<p>
	إذا فشل التحقق من حدوث تصادم مع إحدى المنصات خلال فترة تشغيل الجاذبية فإن البطل سيسقط أرضًا.
</p>

<p>
	شغل اللعبة الآن، ولاحظ أن الوظائف كافة تعمل جيدًا، يمكنك تغيير قيم بعض المتغيرات لتجرب تأثيرها.
</p>

<p>
	إليك شيفرة اللعبة كاملًا حتى هذه النقطة، أما في القسم التالي سنمنح البطل القدرة على الركض بحرية عبر تمرير عالم اللعبة جانبيًا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_28" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x

    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># collisions</span><span class="pln">
        enemy_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="com"># print(self.health)</span><span class="pln">

        ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">

        </span><span class="com"># fall off the world</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># how high to jump</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">550</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">

gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<h2>
	تفعيل الركض ذهابًا وإيابا في عالم اللعبة
</h2>

<p>
	سنعطي البطل في هذه المرحلة القدرة على الركض ذهابًا وإيابًا عبر تمرير عالم اللعبة جانبيًا.
</p>

<p>
	خططت في مقالٍ سابق مستوى للعبة يتضمن عدة منصات وعندما نفذته لم تظهر كافة المنصات على شاشة العرض فقد تجاوزت أبعادها وأعدادها مساحة الشاشة الواحدة، والتمرير الجانبي لعالم اللعبة أو ما يسمى side-scroller هو الحل الأمثل لهذه الحالة ولإظهار المستوى المخطط له كاملًا.
</p>

<p>
	تمامًا كما يوحي الاسم، ستتحرك المنصات جانبيًا كلما اقترب البطل من حافة الشاشة لتعطي المستخدم شعورًا يشبه مشاهدة الفيديو وكأن كاميرا متحركة تتنقل في عالم اللعبة وتصوره، يتطلب التمرير حجز منطقة ميتة على جانبي الشاشة الأيمن والأيسر وعندما يصل البطل إلى هذه المناطق سيبقى ثابتًا بينما يُمرر العالم جانبيًا من حوله وتتحرك المنصات.
</p>

<h3>
	تثبيت نقاط التمرير الجانبي على الشاشة
</h3>

<p>
	إن رغبت بالسماح للاعب بالتحرك إلى الأمام والخلف فستحتاج إلى نقطتي تمرير على جانبي الشاشة، أما لو سمحت له بالتقدم للأمام فقط تكفيك عندها نقطةٌ واحدة.
</p>

<p>
	سنحدد نقاط التمرير باستخدام المتغيرات بمسافة 100 أو 200 بيكسل عن كل جانب من جوانب الشاشة.
</p>

<p>
	عرّف إذًا متغيرات التمرير في مقطع المتغيرات ضمن برنامجك على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_30" style=""><span class="pln">forwardx  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">600</span><span class="pln">
backwardx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">230</span></pre>

<p>
	والآن تحقق من اللحظة التي يصل فيها بطلك إلى نقاط التمرير ضمن الحلقة الرئيسية للبرنامج وذلك عبر تعليمة <code>if</code> الشرطية، وإذا وصل اللاعب إلى إحدى هذه النقاط حرك عندها عالم اللعبة يمينًا أو يسارًا.
</p>

<p>
	اكتب التعليمات التالية في حلقة التكرار الرئيسية للبرنامج وانتبه أن لا تتداخل مع الحلقة <code>for</code> الخاصة باكتشاف الضغط على أزرار لوحة المفاتيح، الأسطر الثلاثة الأخير هي للسياق فقط لن تحتاج لإعادة كتابتها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_32" style=""><span class="pln">        </span><span class="com"># تمرير عالم اللعبة إلى الأمام</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
                scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
                player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
                </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
                        p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll

        </span><span class="com"># تمرير عالم اللعبة إلى الخلف</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
                scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
                player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
                </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
                        p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll

    </span><span class="com"># تعليمات التمرير أعلى هذا السطر</span><span class="pln">
    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln"> </span><span class="com"># فحص الجاذبية</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span></pre>

<p>
	شغل اللعبة الآن وجرب التمرير.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109025" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-scroll.png.24bce8aa0c5dc896fa9ab67a428314c4.png" rel="" data-fileext="png"><img alt="pygame-scroll" class="ipsImage ipsImage_thumbnailed" data-fileid="109025" data-unique="1rqbe5on8" style="width: 550px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-01-pygame-scroll.png.24bce8aa0c5dc896fa9ab67a428314c4.png"></a>
</p>

<p>
	ستلاحظ بعد التشغيل أن التمرير الجانبي يعمل جيدًا والمنصات تتحرك مع البطل إلى الأمام والخلف أما العنصر الوحيد الذي لا يستجيب للتمرير فهو كائن شخصية العدو.
</p>

<p>
	اكتب التعليمات اللازمة لتمرير إن أردت أن يُمرر مثلهم، وتستطيع طبعًا تمريره للأمام فقط أو للخلف فقط أو بكلا الاتجاهين ليلاحق بطل اللعبة.
</p>

<h3>
	تمرير العدو مع عالم اللعبة
</h3>

<p>
	طبق التعليمات نفسها الخاصة بتمرير المنصات على شخصية العدو، والأفضل لك أن تطبقها على المجموعة التي تضم جميع كائنات العدو إذ إن اللعبة تتضمن أكثر من عدو، هذه ميزة جمع العناصر المتشابهة في مجموعات فهي تسهل على المبرمج تطبيق التعليمات عليها جميعًا دفعةً واحدة.
</p>

<p>
	أضف السطرين الأخيرين من التعليمات التالية ضمن الحلقة الرئيسية في كتلة التمرير إلى الأمام لتمرير العدو إلى الأمام:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_37" style=""><span class="pln">    </span><span class="com"># تمرير عالم اللعبة إلى الأمام</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">    </span><span class="com"># تمرير العدو</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll  </span><span class="com"># تمرير العدو</span></pre>

<p>
	ومن ثم السطرين الأخيرين من هذه التعليمات إلى كتلة التمرير إلى الخلف ضمن الحلقة الرئيسية لتمرير العدو بالاتجاه الآخر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_39" style=""><span class="pln">    </span><span class="com"># تمرير عالم اللعبة إلى الخلف</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">    </span><span class="com"># تمرير العدو</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll  </span><span class="com"># تمرير العدو</span></pre>

<p>
	والآن شغل اللعبة وتفقد النتائج.
</p>

<p>
	إليك الشكل النهائي لبرنامج اللعبة حتى هذه المرحلة ليبقى مرجعًا لديك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2247_41" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">
forwardx  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">600</span><span class="pln">
backwardx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">230</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x

    </span><span class="kwd">def</span><span class="pln"> jump</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># collisions</span><span class="pln">
        enemy_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> enemy_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="com"># print(self.health)</span><span class="pln">

        ground_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> ground_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> g </span><span class="kwd">in</span><span class="pln"> ground_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">

        </span><span class="com"># fall off the world</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> tx
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> ty

        plat_hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> plat_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span><span class="com"># stop jumping</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">&lt;=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">bottom </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">top
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
               self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_jumping </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">is_falling </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">33</span><span class="pln">  </span><span class="com"># how high to jump</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">550</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">

gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">jump</span><span class="pun">()</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># scroll the world forward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&gt;=</span><span class="pln"> forwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> forwardx
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> forwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">  </span><span class="com"># enemy scroll</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> scroll  </span><span class="com"># enemy scroll</span><span class="pln">

    </span><span class="com"># scroll the world backward</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> backwardx</span><span class="pun">:</span><span class="pln">
        scroll </span><span class="pun">=</span><span class="pln"> backwardx </span><span class="pun">-</span><span class="pln"> player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x
        player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> backwardx
        </span><span class="kwd">for</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> plat_list</span><span class="pun">:</span><span class="pln">
            p</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll
        </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">    </span><span class="com"># enemy scroll</span><span class="pln">
            e</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> scroll  </span><span class="com"># enemy scroll</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/19/12/jumping-python-platformer-game" rel="external nofollow">Add jumping to your Python platformer game</a> والمقال <a href="https://opensource.com/article/19/12/python-platformer-game-run" rel="external nofollow">Enable your Python game player to run forward and backward</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D9%88%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D9%82%D9%81%D8%B2-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B3%D9%83%D8%B1%D8%A7%D8%AA%D8%B4-r1668/" rel="">تصميم وبرمجة لعبة قفز باستخدام سكراتش</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/game-development/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%B3%D9%84%D8%A7%D9%84%D9%85-%D9%88%D8%AE%D8%AA%D8%A7%D9%85-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-r772/" rel="">إنشاء السلالم وختام اللعبة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1732</guid><pubDate>Wed, 19 Oct 2022 16:02:00 +0000</pubDate></item><item><title>&#x628;&#x631;&#x645;&#x62C;&#x629; &#x644;&#x639;&#x628;&#x629; &#x62D;&#x62C;&#x631;&#x629; &#x648;&#x631;&#x642;&#x629; &#x645;&#x642;&#x635; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D8%AD%D8%AC%D8%B1%D8%A9-%D9%88%D8%B1%D9%82%D8%A9-%D9%85%D9%82%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1701/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_09/631091d25b68e_-------.png.badb7a5398b0fbdb1524ed93bad20253.png" /></p>
<p>
	سنتعلم في هذا المقال كيفية إنشاء لعبة حجرة- ورقة- مقص، يكون خصمنا فيها هو الحاسوب، بحيث نُشكّل الحركات بيدنا ليتعرف عليها الحاسوب ويلعب الحركة المعاكسة. سنستخدم في هذا المشروع أساسيات تعلّم الآلة و<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">لغة بايثون python</a>، وسندرّب نموذجًا للتعرف على البيانات باستخدام أداة Teachable Machine.
</p>

<p>
	هدفنا الحصول على نسخة بسيطة مشابهة لعمل هذا الروبوت المدهش:
</p>

<div class="ipsEmbeddedVideo" contenteditable="false">
	<div>
		<iframe __idm_id__="2596871" allowfullscreen="" frameborder="0" height="400" src="https://player.vimeo.com/video/745363660?autoplay=0&amp;color=ffffff&amp;title=0&amp;byline=0&amp;portrait=0" width="485"></iframe>
	</div>
</div>

<p>
	يتطلب هذا المشروع وجود معرفة مُسبقة لدى القارئ بلغة <a href="https://wiki.hsoub.com/Python" rel="external">بايثون Python</a> وخاصًة الأفكار التالية:
</p>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r221/" rel="">المتغيرات Variables</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">الدوال Functions</a>، وكيفية إنشاء دوال تقبل وسطاء arguments.
	</li>
	<li>
		أساسيات إنشاء نموذج <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-r1009/" rel="">لتعلّم الآلة machine learning</a>.
	</li>
	<li>
		كيفية استخدام واجهة سطر الأوامر على حاسوبك للانتقال إلى مجلد ما.
	</li>
</ul>

<p>
	ننصحك بكتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a> الذي يغطي كل تلك الأفكار.
</p>

<p>
	ستحتاج في هذا المشروع إلى:
</p>

<ol>
	<li>
		حاسوب فيه كاميرا.
	</li>
	<li>
		اتصال بالإنترنت.
	</li>
	<li>
		حساب غوغل.
	</li>
</ol>

<p>
	ستتعلم في هذا المشروع:
</p>

<ul>
	<li>
		كيفية إنشاء نموذج Model رؤية آلية وتدريبه باستخدام موقع <a href="https://teachablemachine.withgoogle.com/" rel="external nofollow">Teachable Machine</a> من غوغل.
	</li>
	<li>
		ما يجب عليك أخذه بالحسبان عند إنشاء نموذج لضمان عمله عند تجربته.
	</li>
	<li>
		كيفية تضمين نموذج منُشأ مسبقًا في تطبيق سطح مكتب.
	</li>
</ul>

<p>
	كما يمكنك الحصول على <a href="https://rpf.io/p/en/rock-paper-scissors-by-hand-go" rel="external nofollow">الملفات المطلوبة لهذا المشروع من هنا</a>.
</p>

<h2>
	التعرف على موقع Teachable Machine
</h2>

<p>
	سنستخدم في مشروعنا موقع Teachable Machine، وهو أداةٌ مقدمةٌ من غوغل والتي تُتيح إنشاء نماذج لتعلّم الآلة في المتصفح، لذلك سننشئ نموذجًا يمكنه التعرف على الصور، ثم سنستخدم هذا النموذج في لعبة سننشئها على الحاسوب.
</p>

<p>
	يمكن للنماذج المنشأة على موقع Teachable Machine التعرف على الصور، والأصوات ووضعيات الجسم، ولكننا سنستخدم الصور فقط في مشروعنا هذا.
</p>

<p>
	أولًا، انتقل إلى صفحة <a href="https://teachablemachine.withgoogle.com/train/image" rel="external nofollow">تدريب نموذج للتعرف على الصور</a> في Teachable Machine، حيث ستجد واجهة النموذج الفارغ التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107201" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_start_screen.png.4a145e1611e666f058406333157e1fba.png" rel="" data-fileext="png"><img alt="tm_start_screen.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107201" data-unique="aglf61o3a" style="width: 700px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_start_screen.thumb.png.bc14d00909ddb665d8729c30ff9fc0cb.png"></a>
</p>

<p>
	لاحظ أن النموذج فيه صنفين، وبما أننا نريد إنشاء لعبة "حجرة، ورقة، مقص" فسنحتاج لإنشاء صنفٍ ثالث.
</p>

<p>
	ثانيًا، انقر على زر إضافة صنف Add a class، لإضافة صنف ثالث إلى النموذج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107198" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_add_class.png.5199e4dc2753bbe50221f4b4eac83bcb.png" rel="" data-fileext="png"><img alt="tm_add_class.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107198" data-unique="rzzk904pg" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_add_class.thumb.png.3998982dccb51a7cb3662a473ae38722.png"></a>
</p>

<p>
	ثالثًا، سمِّ الأصناف الثلاثة "rock, paper, scissors" على التتالي بالنقر على رمز القلم بجانب كل صنف، واحرص على تسمية الأصناف بالترتيب الصحيح وباللغة الانجليزية، أي الصنف الأول "rock"، والثاني "paper" والثالث "scissors" لتفادي حصول الأخطاء عند كتابة الشيفرة وتنفيذها في الخطوات التالية.
</p>

<h2>
	تجميع بيانات التدريب
</h2>

<p>
	نحن الآن بحاجة إلى إضافة بيانات لتدريب الأصناف الثلاثة. لاحظ أن لكل صنف خيارين لإضافة الصور، الأول باستخدام <strong>كاميرا الويب Webcam</strong> والثاني عن طريق <strong>تحميل الصور Upload</strong>. يمكنك تحميل مجموعة صور إيماءات "حجرة، ورقة، مقص" من حاسوبك، أو يمكنك استخدام خيار كاميرا الويب <strong>ًWebcam</strong> لإلتقاط صور للإيماءات الثلاث، كما يمكنك استخدام لوحة راسبيري باي مزودة بكاميرا لالتقاط صور وذلك بعد إعداد الكاميرا.
</p>

<p>
	أولًا، انقر على خيار <strong>الكاميرا</strong> لصنف المقص "rock"، فستظهر لك رسالةٌ على الشاشة تسألك إن كنت تريد السماح لموقع Teachable Machine بالوصول إلى كاميرا حاسوبك واستخدامها، انقر على خيار السماح Allow.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107203" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_webcam_images.png.35359fbf0da193258513e54e430ba178.png" rel="" data-fileext="png"><img alt="tm_webcam_images.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107203" data-unique="3ds153rch" style="width: 550px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_webcam_images.thumb.png.bba6a6030b44a835711cf8f073a4a5ba.png"></a>
</p>

<p>
	ثانيًا، انقر على زر التسجيل الأزرق لإلتقاط الصور وشَكّل بقبضة يدك الأخرى شكل الحجرة، وحرّك يدك وغير وضعيتها ليتكون لدينا بيانات متنوعة للتدريب.
</p>

<p>
	ستظهر الصور التي التقطها في قسم إضافة عينات الصور Add Image Samples على الجهة اليمنى، استمر بالتقاط الصور حتى تحصل على 300 عينة على الأقل، إذ كلما زاد عدد الصور كلما زادت دقة نموذج التعلم الآلي الذي سننشئه.
</p>

<p>
	إليك بعض الاقتراحات لتحسين جودة بيانات التدريب وتنويعها:
</p>

<ul>
	<li>
		استخدم يديك الاثنتين بالتناوب.
	</li>
	<li>
		اطلب من شخص آخر مساعدتك في تشكيل جميع الإيماءات الثلاثة، وإلا فإن النموذج سيربط الإيماءة مع الشخص الأول.
	</li>
	<li>
		غيِّر تعابير وجهك.
	</li>
	<li>
		غيّر المكان الذي تجلس فيه.
	</li>
	<li>
		غيّر مستوى الإضاءة في مكان جلوسك، أو تنقَّل بين أماكن مضيئة وأخرى مظلمة.
	</li>
</ul>

<p>
	ننصحك بعدم تسجيل الصور الخاصة بالصنف الواحد دفعةً واحدة، التقط بعض الصور للصنف الأول ثم الثاني، وهكذا، وذلك كي تتجنب تعلُّم النموذج أمرًا خاطئًا؛ كأن يربط تعبير وجهك أو حركة شخص ما في الخلفية بإيماءةٍ ما.
</p>

<p>
	هل لديك اقتراحات لأمور أخرى يجب أخذها بالحسبان؟
</p>

<p>
	ثالثًا، التقط صور الصنفين الآخرين بطريقة مماثلة.
</p>

<h2>
	إنشاء نموذج التعلم الآلي
</h2>

<p>
	حان الآن وقت إنشاء النموذج وتدريبه بعد أن حصلنا على البيانات اللازمة.
</p>

<p>
	أولًا، انقر على زر تدريب النموذج Train Model.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107202" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_train_model.png.e46237db010b3b6ad7b5c0f82c3af936.png" rel="" data-fileext="png"><img alt="tm_train_model.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107202" data-unique="zs3bxnrcb" style="width: 270px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_train_model.png.e46237db010b3b6ad7b5c0f82c3af936.png"></a>
</p>

<p>
	<strong>عند بدء تدريب النموذج يجب عليك إبقاء صفحة Teachable Machine مفتوحةً في المتصفح وإلا سيتوقف التدريب.</strong> لا تقلق، فلن يستغرق التدريب سوى فترة قصيرة، وسيظهر لك على الشاشة عدد مرات المرور على كامل بيانات التدريب أو ما يُدعى epoch، وستتمكن بعد انتهاء التدريب، من اختبار النموذج في مستطيل المعاينة Preview، شكّل الإيماءات باستخدام يدك واختبر دقة عمل النموذج، إذ أن النسب المئوية أدنى شاشة المعاينة تعبر عن مدى صحة تفسير الإيماءة.
</p>

<p>
	اختبر نموذجك بدقة، وإذا لم ترضَ عن النتائج فإليك بعض الاقتراحات لتحسينها:
</p>

<ul>
	<li>
		أضف مزيدًا من بيانات التدريب لكل من الأصناف.
	</li>
	<li>
		زَد عدد مرات المرور epoch لزيادة وقت التدريب، وذلك بالنقر على الخيارات المتقدمة Advanced في مربع التدريب:
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107195" href="https://academy.hsoub.com/uploads/monthly_2022_09/Advanced-options.png.e88bfb4020f3748e82080f73b006a1b3.png" rel="" data-fileext="png"><img alt="Advanced-options.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107195" data-unique="oub25pceh" style="width: 250px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/Advanced-options.png.e88bfb4020f3748e82080f73b006a1b3.png"></a>
</p>

<p>
	تذكر أن النموذج لا بُد له أن يخطئ، لذلك حين تشعر أنك حصلت على نتيجة ترضاها، انقر على زر تصدير النموذج Export Model كي تتمكن من استخدامه في اللعبة التي سننشئها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107200" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_export_model.png.e35251a159ec85a6b25c241eb0b132e3.png" rel="" data-fileext="png"><img alt="tm_export_model.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107200" data-unique="rjdnivpwl" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_export_model.png.e35251a159ec85a6b25c241eb0b132e3.png"></a>
</p>

<p>
	انقر على نافذة <strong>تنسرفلو TensorFlow</strong> في الشاشة التي ستظهر لك، ثم اختر نوع كيراس <strong>Keras</strong> لتحويل النموذج، ثم انقر بعدها على زر <strong>تنزيل النموذج Download my model</strong>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107199" href="https://academy.hsoub.com/uploads/monthly_2022_09/tm_download_model.png.7fb4b5154a697715ec1c62c803313a4c.png" rel="" data-fileext="png"><img alt="tm_download_model.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107199" data-unique="yz2ogo53w" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/tm_download_model.thumb.png.8a8a92dbed2476dcc9575144b28ac798.png"></a>
</p>

<p>
	أصبحت الآن جاهزًا لإنشاء اللعبة.
</p>

<h2>
	إعداد اللعبة
</h2>

<p>
	ستجد في هذه الخطوة أننا سنزودك ببرنامج اللعبة مكتوبًا بلغة بايثون، أي أنه ليس عليك كتابة الشيفرة وإنما التركيز على فهم آلية تعلّم الآلة في هذا المشروع، ومع ذلك يمكنك تحسين واجهة اللعبة إذا كانت لديك أساسيات التعامل مع <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1501/" rel="">واجهات المستخدم الرسومية GUI</a>، كما يمكنك تعديل آلية اختيار الحاسوب خطوته التالية؛ بحيث يفوز اللاعب دائمًا، أو يمكنك جعله يختار خطوته عشوائيًا.
</p>

<p>
	أولاً، نزّل الملف الأولي للمشروع وأعدّه للعمل وفق نظام تشغيل حاسوبك، كما يلي:
</p>

<h3>
	نظام ويندوز
</h3>

<ul>
	<li>
		نزّل الملف الأولي المضغوط للمشروع وفُك ضغطه في مجلد مناسب على حاسوبك.
	</li>
</ul>

<p>
	*نزّل المكتبات اللازمة لعمل المشروع باستخدام واجهة سطر الأوامر command line interface -أو اختصارًا CLI-، والتي تُدعى موجه الأوامر command prompt في نظام ويندوز.
</p>

<p>
	تذكر أن واجهة سطر الأوامر ليست واجهة رسومية، إذ يجب عليك كتابة دليل الملف للوصول إليه، بدلًا من مجرد الضغط عليه، سواءٌ كان الدليل نسبيًا relative path أي المكان الحالي للملف، أو كان الدليل مطلقًا absolute path أي دليل كامل بدءًا من قرص التخزين على الحاسب، أو من جذر نظام الملفات root أي يبدأ بهذه الإشارة <strong>/</strong>.
</p>

<ul>
	<li>
		انتقل إلى مجلد المشروع الذي نزلته، ثم انقر على شريط التنقل وانسخ دليل الملف.
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107197" href="https://academy.hsoub.com/uploads/monthly_2022_09/NavigationBar.png.83fbbe5615727b370f99431c63325519.png" rel="" data-fileext="png"><img alt="NavigationBar.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107197" data-unique="258qkh020" style="width: 750px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/NavigationBar.thumb.png.fbe0f19e90ac2a048337f09d71e9fde3.png"></a>
</p>

<ul>
	<li>
		استبدل اسم المجلد directory في نافذة موجه الأوامر باسم المجلد<code>[directory_path]</code> للانتقال إلى مجلد مشروعك، حتى يصبح بإمكانك تنفيذ أوامر بايثون.
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_32" style=""><span class="pln">cd </span><span class="pun">[</span><span class="pln">directory_path</span><span class="pun">]</span></pre>

<ul>
	<li>
		اكتب الأمر التالي الذي يستخدم نظام إدارة الحزم <strong>pip</strong> في بايثون لتنصيب المكتبات اللازمة من <a href="https://academy.hsoub.com/devops/networking/%D8%A2%D9%84%D9%8A%D8%A9-%D8%B9%D9%85%D9%84-%D8%B4%D8%A8%D9%83%D8%A9-%D8%A7%D9%84%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-r571/" rel="">الإنترنت</a>، والذي قد يستغرق بعض الوقت:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_34" style=""><span class="pln">pip install requirements</span><span class="pun">.</span><span class="pln">txt</span></pre>

<p>
	ننصحك بتنصيب المكتبات اللازمة باستخدام الأمر <code>pip</code> عوضًا عن تنزيلها يدويًا، لأن بعض المكتبات قد تحتاج إلى مكتبات أخرى أو ما يُعرف بالاعتماديات dependencies والتي ينصبها "pip" تلقائيًا، إذ يمكن استخدام "pip" لتنصيب قائمة من المكتبات التي يحتاجها المشروع، والتي غالبًا تضمن في مجلد يسمى "requirements.txt".
</p>

<h3>
	نظام ماك أو إس MacOS
</h3>

<p>
	تدعى واجهة سطر الأوامر في نظام ماك بالطرفية Terminal.
</p>

<ul>
	<li>
		اكتب الأمر التالي في الطرفية وذلك للانتقال إلى المجلد الرئيسي home والذي تدل عليه الإشارة التالية <strong>~</strong>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_37" style=""><span class="pln">cd </span><span class="pun">~</span></pre>

<ul>
	<li>
		الآن بعد أن أصبحنا في المجلد الرئيسي، اكتب الأمر التالي لتنصيب سكربت مكتوب بلغة <a href="https://wiki.hsoub.com/Bash" rel="external">باش Bash</a> لتسهيل تنزيل البرنامج الأولي للعبة:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7462_49" style=""><span class="pln">curl </span><span class="pun">-</span><span class="pln">L http</span><span class="pun">:</span><span class="com">//rpf.io/proj-rps | sudo bash -s $USER</span></pre>

<p>
	كما يمكنك الإطلاع على <a data-fileid="107204" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=107204" rel="" data-fileext="zip">السكربت</a>  إذا أحببت ذلك.
</p>

<p>
	قد يستغرق الأمر بعض الوقت أو بضع دقائق، بناءً على سرعة حاسوبك وسرعة اتصال الإنترنت لديك، وستلاحظ بمجرد انتهاء التثبيت مجلدًا جديدًا ضمن المجلد الرئيسي باسم "amazing_image_identifier".
</p>

<ul>
	<li>
		انتقل إلى المجلد الجديد باستخدام الأمر <code>cd</code>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_45" style=""><span class="pln">cd amazing_image_identifier</span></pre>

<h3>
	نظامي لينكس وراسبيان
</h3>

<p>
	يدعى <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D8%AC%D9%88%D9%84%D8%A9-%D9%81%D9%8A-%D8%B1%D8%A7%D8%B3%D8%A8%D9%8A%D8%A7%D9%86-%D9%86%D8%B8%D8%A7%D9%85-%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D8%B1%D8%A7%D8%B3%D8%A8%D9%8A%D8%B1%D9%8A-%D8%A8%D8%A7%D9%8A-r1371/" rel="">نظام التشغيل الخاص براسبيري باي بنظام راسبيان Raspbian</a>، أو راسبيري باي أو إس Raspberry Pi OS وهو مبنيٌ على إحدى <a href="https://academy.hsoub.com/devops/linux/%D8%B9%D8%B1%D8%B6-%D9%85%D9%88%D8%AC%D8%B2-%D9%84%D8%A3%D8%B4%D9%87%D8%B1-%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r631/" rel="">توزيعات لينكس</a>.
</p>

<ul>
	<li>
		انتقل إلى المجلد الرئيسي home:
	</li>
</ul>

<pre class="ipsCode">cd ~
</pre>

<ul>
	<li>
		الآن بعد أن أصبحنا في المجلد الرئيسي، اكتب الأمر التالي لتنصيب <a href="http://rpf.io/proj-rps" rel="external nofollow">سكربت</a> مكتوب بلغة <a href="https://wiki.hsoub.com/Bash" rel="external">باش Bash</a> لتسهيل تنزيل البرنامج الأولي للعبة:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_53" style=""><span class="pln">curl </span><span class="pun">-</span><span class="pln">L http</span><span class="pun">://</span><span class="pln">rpf</span><span class="pun">.</span><span class="pln">io</span><span class="pun">/</span><span class="pln">proj</span><span class="pun">-</span><span class="pln">rps </span><span class="pun">|</span><span class="pln"> sudo bash </span><span class="pun">-</span><span class="pln">s $USER</span></pre>

<p>
	قد يستغرق الأمر بعض الوقت أو بضع دقائق بناءً على سرعة حاسوبك وسرعة اتصال الإنترنت لديك، وستلاحظ بمجرد انتهاء التنصيب مجلدًا جديدًا ضمن المجلد الرئيسي باسم "rps_by_hand".
</p>

<ul>
	<li>
		انتقل إلى المجلد الجديد باستخدام الأمر <code>cd</code>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_55" style=""><span class="pln">cd rps_by_hand</span></pre>

<p>
	والآن بعد أن أصبح برنامج اللعبة جاهزًا ومنصبًا على حاسوبك، حان وقت تشغيله.
</p>

<p>
	ثانيًا، شغّل البرنامج باستخدام الأمر التالي في نظامي ويندوز <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">ولينكس</a>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_58" style=""><span class="pln">python project</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	والأمر التالي لنظام ماك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_60" style=""><span class="pln">python3 project</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	قد يستغرق تشغيل البرنامج بعض الوقت، ولكن عند تشغيله ستظهر لك الشاشة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107196" href="https://academy.hsoub.com/uploads/monthly_2022_09/app_start.png.b1d5deb75e9f4c4cfb4e23fcb5c78588.png" rel="" data-fileext="png"><img alt="app_start.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107196" data-unique="y26lc47tz" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/app_start.thumb.png.4c958be5aeef2ce729053d52c59c075b.png"></a>
</p>

<p>
	حان الآن وقت ربط النموذج باللعبة.
</p>

<h2>
	ربط النموذج باللعبة
</h2>

<p>
	أولًا، فُكَّ ضغط الملف "converted_keras.zip" الذي نزلته من موقع Teachable Machine، ثم انسخ منه الملف "keras_model.h5" والصقه في المجلد الذي يحتوي على شيفرة برنامج اللعبة.
</p>

<p>
	لاحظ أن ملف التسميات "labels.txt" في المجلد المضغوط، يحتوي على قائمة بالتسميات القابلة للقراءة وأرقام العقد التي تتطابق معها في خرج النموذج، وبما أنه ليس لدينا سوى ثلاث تصنيفات categories في مشروعنا: الحجرة، والورقة، والمقص، فقد ضمّنّا هذه التسميات في شيفرة اللعبة بقائمة list تدعى "THROWS"، لكن عندما يحتوي المشروع على تصنيفات عديدة فيفضل قراءة الملف "labels.txt" وتحميله إلى المشروع تلقائيًا باستخدام أوامر بايثون.
</p>

<p>
	ثانيًا، أصبح بإمكانك تحميل النموذج داخل اللعبة، بعد أن وضعته وبرنامج اللعبة في نفس المجلد، وذلك بإضافة السطر التالي قبل دالة <code>get_player_throw</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_63" style=""><span class="pln">model </span><span class="pun">=</span><span class="pln"> tf</span><span class="pun">.</span><span class="pln">keras</span><span class="pun">.</span><span class="pln">models</span><span class="pun">.</span><span class="pln">load_model</span><span class="pun">(</span><span class="str">'keras_model.h5'</span><span class="pun">,</span><span class="pln"> compile</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">)</span></pre>

<p>
	عدّل على دالة <code>get_player_throw</code> بإضافة الشيفرة التالية، التي تعمل على تمرير الصورة التي التقطتها اللعبة إلى النموذج ليتنبأ ما هي الإيماءة، ثم يمرر نتيجة التنبؤ إلى اللعبة، لتختار اللعبة على أساسها الحركة المعاكسة وفقًا لشيفرتها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7462_65" style=""><span class="kwd">def</span><span class="pln"> get_player_throw</span><span class="pun">():</span><span class="pln">
    image </span><span class="pun">=</span><span class="pln"> tf</span><span class="pun">.</span><span class="pln">keras</span><span class="pun">.</span><span class="pln">preprocessing</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load_img</span><span class="pun">(</span><span class="pln">IMG_NAME</span><span class="pun">,</span><span class="pln"> target_size</span><span class="pun">=(</span><span class="pln">IMAGE_SIZE</span><span class="pun">,</span><span class="pln"> IMAGE_SIZE</span><span class="pun">))</span><span class="pln">
    image </span><span class="pun">=</span><span class="pln"> tf</span><span class="pun">.</span><span class="pln">keras</span><span class="pun">.</span><span class="pln">preprocessing</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">img_to_array</span><span class="pun">(</span><span class="pln">image</span><span class="pun">)</span><span class="pln">
    image </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">expand_dims</span><span class="pun">(</span><span class="pln">image</span><span class="pun">,</span><span class="pln"> axis</span><span class="pun">=</span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    prediction_result </span><span class="pun">=</span><span class="pln"> model</span><span class="pun">.</span><span class="pln">predict</span><span class="pun">(</span><span class="pln">image</span><span class="pun">)</span><span class="pln">

    best_prediction </span><span class="pun">=</span><span class="pln"> THROWS</span><span class="pun">[</span><span class="pln">np</span><span class="pun">.</span><span class="pln">argmax</span><span class="pun">(</span><span class="pln">prediction_result</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])]</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> best_prediction</span></pre>

<p>
	إليك شرحًا مبسطًا للشيفرة السابقة:
</p>

<ul>
	<li>
		تُحوّل الأسطر التي تبدأ بالمعامل <code>image</code> الصور إلى الصيغة المناسبة للنموذج.
	</li>
	<li>
		يحتوي السطر <code>prediction_result</code> على نتيجة التنبؤ من النموذج بصيغة أرقام تدل على أرجحية صحة كل تخمين.
	</li>
	<li>
		يعتمد السطر <code>best_predicion</code> على التنبؤ ذي الأرجحية الأعلى، بينما يجلب التابع <code>np.argmax</code> دليل ذلك التنبؤ ويستخدمه ليعرف تسمية التنبؤ في القائمة <code>THROWS</code>
	</li>
</ul>

<p>
	شغّل البرنامج عدّة مرات، وإذا لم ترضَ عن جودة التخمينات، ففكر ما هي الاختلافات التي قد تحدث بين بيانات التدريب والمُدخلات التي تقدمها للعبتك والتي قد تؤثر على الجودة؟ فقد يؤثر اختلاف شدة الإضاءة أو ارتداءك ملابسًا مختلفة، لذلك سجّل مزيدًا من بيانات التدريب في Teachable Machine، ودرّب النموذج مرةً أخرى، ثم نزّله واستبدل نموذج اللعبة الحالي به.
</p>

<h2>
	خاتمة
</h2>

<p>
	تهانينا، فقد أتممت مشروع إنشاء لعبة "حجرة- ورقة- مقص" باستخدام <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">لغة بايثون</a>، والذي استخدمت فيه أساسيات تعلّم الآلة، ودرّبت نموذجًا للتعرف على البيانات باستخدام أداة Teachable Machine.
</p>

<p>
	أطلق العنان لإبداعك ونفّذ مشاريع مماثلة في خطوتك التالية.
</p>

<p>
	إذا واجهت مشاكلًا مع لغة بايثون، فيمكنك الحصول على الدعم والمساعدة عن طريق إضافة سؤالك في قسم الأسئلة والأجوبة في <a href="https://academy.hsoub.com/questions/" rel="">أكاديمية حسوب</a>.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://projects.raspberrypi.org/en/projects/rock-paper-scissors-by-hand/0" rel="external nofollow">Rock, paper, scissors by hand</a> من <a href="https://raspberrypi.org/" rel="external nofollow">الموقع الرسمي لراسبيري باي</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%af%d9%84%d9%8a%d9%84-%d8%a7%d9%84%d8%b3%d8%b1%d9%8a%d8%b9-%d8%a5%d9%84%d9%89-%d9%84%d8%ba%d8%a9-%d8%a7%d9%84%d8%a8%d8%b1%d9%85%d8%ac%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-python-3-r535/" rel="">الدليل السريع إلى لغة البرمجة بايثون Python 3</a>
	</li>
	<li>
		تعرف على <a href="https://academy.hsoub.com/programming/game-development/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8/" rel="">أشهر لغات برمجة الألعاب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%B0%D9%87%D9%86%D9%8A-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B3%D9%83%D8%B1%D8%A7%D8%AA%D8%B4-r1699/" rel="">برمجة لعبة اختبار ذهني باستخدام سكراتش</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/game-development/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%AA%D8%A7%D9%87%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D8%AD%D8%B1%D9%83-%D9%8A%D9%88%D9%86%D9%8A%D8%AA%D9%8A-unity-r1700/" rel="">برمجة لعبة متاهة باستخدام محرك يونيتي Unity </a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1701</guid><pubDate>Sat, 15 Oct 2022 16:00:00 +0000</pubDate></item><item><title>&#x645;&#x62D;&#x627;&#x643;&#x627;&#x629; &#x623;&#x62B;&#x631; &#x627;&#x644;&#x62C;&#x627;&#x630;&#x628;&#x64A;&#x629; &#x641;&#x64A; &#x644;&#x639;&#x628;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633bfab881652_-----.png.ed87c15f46f87a41fb6e2689a783faf3.png" /></p>
<p>
	عالمنا الحقيقي مليء بالحركة، والفيزياء هي ما يحكم ويفسر كافة ظواهره المتعلقة بحركة المادة، أما عالم ألعاب الفيديو فهو خالٍ من المادة ما يعني أنه منطقيًا خالٍ من الفيزياء أيضًا، لذا ينبغي على مطوري الألعاب محاكاة الفيزياء في ألعابهم لمنحها لمسة واقعية، وأكثر المبادئ الفيزيائية أهمية في عالم الألعاب هي الجاذبية والتصادم.
</p>

<p>
	تعلمنا قليلًا عن التصادم عندما <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">أضفنا شخصية العدو إلى اللعبة</a>، لكننا سنتناوله بمزيدٍ من التعمق في هذا المقال والذي يليه فالجاذبية تفرض علينا ذلك، فما هي العلاقة بين الجاذبية والتصادم؟ ستجيبك عن ذلك تعليماتنا البرمجية اللاحقة.
</p>

<p>
	الجاذبية في العالم الحقيقي كما نعرفها جميعًا من دروس الفيزياء هي ميل الأجسام ذات الكتلة إلى التجاذب المتبادل فيما بينها، وكلما زادت كتلة الجسم زاد تأثير الجاذبية التي يمارسها على غيره من الأجسام، فكيف سينعكس ذلك في عالم الألعاب؟
</p>

<p>
	في الواقع الأثر الأوضح للجاذبية الذي ينبغي علينا محاكاته في الألعاب هو ميل الأجسام للسقوط تجاه الكائن الذي يملك افتراضيًا أكبر كتلة في عالم اللعبة، وهو عالم اللعبة نفسه.
</p>

<p>
	قبل أن نبدأ نذكرك بمقالات السلسلة:
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		محاكاة أثر الجاذبية في لعبة بايثون.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<h2>
	إضافة دالة الجاذبية
</h2>

<p>
	سنستفيد من خاصية الحركة التي يملكها كائن اللاعب حتى نسحبه أو نحركه باتجاه أسفل شاشة العرض، بما يحاكي أثر الجاذبية الأرضية، وتذكر أن صفر المحور العمودي في Pygame يقع في الأعلى ما يعني أن الإحداثيات الأكبر هي أكثر قربًا لأسفل الشاشة.
</p>

<p>
	الجاذبية انتقائية في ألعاب المنصات فالمبرمج يختار أثرها ولن تؤثر على كل شيء كما في العالم الحقيقي، فلو فعلت ذلك لرأيت منصات اللعبة بأكملها تسقط إلى الأرضية، لذا سنطبق أثر الجاذبية على شخصيتي اللاعب والعدو فقط.
</p>

<p>
	أضف أولاً دالة الجاذبية في صنف اللاعب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_35_8" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln"> </span><span class="com"># معدل سرعة سقوط اللاعب</span></pre>

<p>
	الدالة بسيطة فقد ضبطنا حركة اللاعب العمودية لتكون باتجاه أرضية اللعبة دائمًا بغض النظر إن كان أساسًا بحالة حركة أو سكون، أي أنه سيسقط دائمًا وهذا بالفعل معنى الجاذبية الأرضية، واستخدمنا لذلك خاصية الحركة العمودية التي يمتلكها اللاعب.
</p>

<p>
	اكتب دالة الجاذبية في الحلقة الرئيسية ليصبح أثرها دائمًا كما في السطر الأول من التعليمات أدناه وبذلك سيُطبقها <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> على اللاعب مع كل نبضة ساعة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_35_10" style=""><span class="pln">    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln"> </span><span class="com"># تحقق من الجاذبية</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span></pre>

<p>
	شغل لعبتك الآن وشاهد النتائج، سيسقط اللاعب سقوطًا حادًا وسريعًا من سماء عالم اللعبة إلى أسفل الشاشة، ربما ترغب بتغيير مقدار سرعة السقوط لتحظى بنتيجة أفضل، لكن أثر الجاذبية يعمل وهذا يكفي في هذه المرحلة.
</p>

<h2>
	تعيين أرضية الجاذبية ليقف عندها اللاعب بعد السقوط
</h2>

<p>
	دائمًا ما يلي السقوط إجراءٌ معين في ألعاب الفيديو، قد يكون مسح اللاعب عن شاشة اللعبة وإعادة إنتاجه في مكانٍ مختلف، أو خصم بعض النقاط من رصيده أو ما شابه، بالنتيجة أيًا كان الإجراء الذي تريده فينبغي أولًا إيجاد طريقة تجعل البرنامج يكتشف حادثة السقوط ويقرر إن سقط اللاعب واختفى عن الشاشة، أم أن ذلك لم يحدث، ويُتخذ بعدها الإجراء المطلوب، أما أنسب تعليمة لهذا النوع من الكشف فهي تعليمة <code>if</code> الشرطية.
</p>

<p>
	ستتحقق إذًا فيما إذا سقط لاعبك أم لا، وماهو مدى سقوطه، فلو سقط بعيدًا جدًا متجاوزًا الأرضية إلى أخفض نقطة في الشاشة فالوضع غير مقبول ويحتاج لبعض التعديلات فمنطيقًا كان عليه الاستقرار على أرضية اللعبة.
</p>

<p>
	لنبسط الموضوع اضبط موقع اللاعب عند 20 بكسل، وعدّل دالة الجاذبية لتصبح:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_35_13" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln"> </span><span class="com"># معدل سرعة السقوط</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> worldy</span><span class="pun">-</span><span class="pln">ty</span></pre>

<p>
	ومن ثم شغل اللعبة ولاحظ أن اللاعب يسقط من الأعلى ويتوقف عند أسفل الشاشة، حتى أنك قد لا تتمكن من رؤيته خلف كائن الأرضية، سنعالج الموضوع بإضافة <code>ty-</code> ثانية إلى موقعه الجديد تجعله يرتد أعلى بعد اصطدامه بأسفل الشاشة فيظهر على مسافة معينة ضمن الشاشة، وذلك وفق الأوامر التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_35_15" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln"> </span><span class="com"># how fast player falls</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="pln">ty</span></pre>

<p>
	يحتاج بطل اللعبة إلى طريقة أو قوة دفع تساعده على مقاومة أثر الجاذبية ليجتاز المستويات ويتابع اللعب هذه القوة هي القفز سيناقشها المقال التالي مع توسع إضافي في تصادمه مع الأرضية والمنصات المختلفة.
</p>

<p>
	حاول بنفسك تطبيق أثر الجاذبية على كائن شخصية العدو، وانظر الشكل النهائي لكود اللعبة متضمنًا كل فعلناه في السلسلة حتى الآن:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_35_17" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> gravity</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3.2</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&gt;</span><span class="pln"> worldy </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="pln">ty

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> y

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">

gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">gravity</span><span class="pun">()</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	كان هذا المقال السابع من سلسلة بناء لعبة من الصفر باستخدام <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">بايثون 3</a> و <a href="https://www.pygame.org/news" rel="external nofollow">Pygame</a>.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/19/11/simulate-gravity-python" rel="external nofollow">Simulate gravity in your Python game</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/game-development/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-r771/" rel="">إنشاء الجاذبية في اللعبة</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1731</guid><pubDate>Wed, 12 Oct 2022 16:05:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x627;&#x644;&#x645;&#x646;&#x635;&#x627;&#x62A; &#x625;&#x644;&#x649; &#x644;&#x639;&#x628;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x648;&#x62D;&#x62F;&#x629; Pygame</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633be93a51733_-------Pygame.png.51c8c5ff2ae1370f3d929c7bae4050b4.png" /></p>
<p>
	يتمحور المقال السادس من سلسلة (بناء لعبة من الصفر باستخدام بايثون) حول إضافة المنصات إلى عالم اللعبة لتتفاعل معها الشخصيات وتتنقل عبرها فهذه اللعبة أولًا وأخيرًا لعبة منصات، ولكن قبل أن نبدأ نذكرك بمقالات السلسلة.
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<p>
	المنصات في <a href="https://www.pygame.org/" rel="external nofollow">Pygame</a> كائنات مثلها مثل الشخصيات، تُضاف إلى عالم اللعبة بالطريقة نفسها عبر برمجة كائن بايثون خاص بكل منصة وتحديد إحداثيات ظهورها على الشاشة، ويسهل هذا التشابه برمجة التفاعل بين الطرفين.
</p>

<h2>
	برمجة كائن المنصة
</h2>

<p>
	تمامًا مثل بناء <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">كائن شخصية اللاعب</a> فإن بناء كائن للمنصة يعني إنشاء صنف <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بلغة بايثون</a>، سنسميه <code>Platform</code> ويتطلب إنشائه عددًا من المعلومات عن المنصة مثل نوعها وصورتها وموقع ظهورها على الشاشة، قد لا تملك هذه المعلومات جميعها في لحظة بناء الصنف ولا بأس في ذلك فستُمررها له فيما بعد بالطريقة نفسها التي اتبعناها عند <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">تحريك اللاعب</a> فلم نحدد السرعة حتى نهاية المقال.
</p>

<p>
	عرّف الصنف وفق الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_20" style=""><span class="com"># ‫x الإحداثي, y الإحداثي, imgw عرض الصورة, imgh ارتفاع الصورة, img ملف الصورة</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc</span></pre>

<p>
	لابد أنك لاحظت تشابه التعليمات بين هذا الصنف وأصناف شخصيتي البطل والعدو، ومثلهما أيضًا سيؤدي استدعاؤه إلى إنشاء كائن المنصة وإظهار صورتها على الشاشة بالأبعاد المحددة ضمن الصنف وفي الموقع المحدد وفق الإحداثيات X و Y.
</p>

<h2>
	أنواع المنصات
</h2>

<p>
	هناك نوعان للمنصات وهي:
</p>

<h3>
	المنصات المبنية بطريقة قطع البلاط
</h3>

<p>
	تُذكرنا هذه المنصات بالألعاب الكلاسيكية الشهيرة مثل سوبر ماريو والقنفذ سونيك، ويعدّها البعض من أسهل طرق بناء المنصات من ناحية الصور المطلوبة -وإن لم تكن كذلك لجهة تعقيد الشيفرة والعمليات الحسابية- فكل ما تحتاجه هو مجموعة صور لقطع البلاط أو القرميد أو ما شابه، ومن ثم تبدأ بترتيبها بأشكالٍ مختلفة ضمن اللعبة، حوالي 8 أو 12 نمط تشكل بها الأرضية والمنصات العائمة وتكررها لتبني مستويات اللعبة.
</p>

<p style="text-align: center;">
	<img alt="Copy of img-01-supertux.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109018" data-unique="w63bsb7y8" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/633beb410c0ef_Copyofimg-01-supertux.gif.c2ad76f56c03ae25969592b6f692f3de.gif">
</p>

<h3>
	المنصات المبنية بطريقة الرسم اليدوي
</h3>

<p>
	تعني هذه الطريقة رسم أو تصميم كل منصة بصورة منفصلة، وتتطلب منك بذل بعض الوقت والجهد في العمل على برامج <a href="https://academy.hsoub.com/design/graphic/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%85%D9%81%D8%B5%D9%84%D8%A9-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D8%A7%D9%84%D8%AC%D8%B1%D8%A7%D9%81%D9%8A%D9%83%D9%8A-r558/" rel="">التصميم الجرافيكي</a> لإنشاء كل جزء من عالم اللعبة، إلاّ أنها بالمقابل تحتاج قدرًا أقل من العمليات الحسابية، إذ إن كافة الكائنات أو المنصات مجهزة وكاملة وكل ما عليك فعله هو إخبار <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> بمكان إظهارها على الشاشة.
</p>

<p>
	لكل طريقة مزايا وعيوب وأسلوب معين في كتابة التعليمات البرمجية، لذا سنشرح الطريقتين في الفقرات اللاحقة حتى تتمكن من استخدام الطريقة التي تناسبك أو تدمج الطريقتين معًا في مشروعك.
</p>

<h2>
	وضع مخطط المستوى
</h2>

<p>
	تعدّ هذه المرحلة جزءًا مهمًا من تصميم المستوى للعبة، يمكنك البدء باستخدام الورقة والقلم، ارسم مربعًا يمثل نافذة اللعبة وعليه المحورين الأفقي والعمودي، ومن ثم ابدأ برسم المنصات التي تريدها واحدةً تلو الأخرى وثبت على كل منها الإحداثيات X و Y وكذلك أبعاد الصورة عرض وارتفاع، لا داعِ لتكون المواقع على الورقة دقيقة جدًا لكن اجعلها منطقية، فمثلًا لا يمكنك وضع 8 قطع قياس كل منها 100 بكسل في شاشة واحدة حجمها 720 بكسل.
</p>

<p>
	بعد إنجاز شاشتك الأولى، استمر بالرسم تجاه اليمين حتى تمثل الشاشات التالية التي سينتقل خلالها بطل اللعبة وهو يجتاز المستوى حتى يصل لنهايته.
</p>

<p>
	ولو رغبت بتعزيز المخطط بمزيدٍ من الدقة استخدم أوراق الرسم البياني المقسمة إلى مربعات متساوية، فهي مفيدة خصيصًا في رسم منصات البلاط، إذ يمكنك تمثيل كل بلاطة بمربع.
</p>

<p style="text-align: center;">
	<img alt="img-02-level-graph-paper.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109023" data-unique="orvkj0fff" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-02-level-graph-paper.gif.a6c0ec5ac6ab2147c859fae1ad089df2.gif">
</p>

<h2>
	الإحداثيات
</h2>

<p>
	كل ما تعلمته في المدرسة عن <a href="https://ar.wikipedia.org/wiki/%D9%86%D8%B8%D8%A7%D9%85_%D8%A5%D8%AD%D8%AF%D8%A7%D8%AB%D9%8A_%D8%AF%D9%8A%D9%83%D8%A7%D8%B1%D8%AA%D9%8A" rel="external nofollow">نظام الإحداثيات الديكارتي</a> ينطبق هنا على إحداثيات Pygame باستثناء أن نقطة التقاء المحاور أو نقطة الصفر <code>0,0</code> تقع في الزاوية العلوية اليسرى للشاشة بدلًا من الوسط مثلما اعتدت سابقًا في دروس الهندسة.
</p>

<p style="text-align: center;">
	<img alt="img-03-pygame_coordinates.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109022" data-unique="ujb174yp5" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-03-pygame_coordinates.gif.aaa5e5ad21bc6d67d73fb2c31cf1fe22.gif">
</p>

<p>
	يبدأ المحور X عند النقطة 0 في أقصى اليسار ويمتد لا نهائيًا نحو اليمين، كذلك يبدأ المحور Y عند النقطة 0 في أعلى الشاشة لكنه يمتد للأسفل.
</p>

<h2>
	أبعاد الصور
</h2>

<p>
	معرفة أبعاد الصور التي تمثل كلًا من الأبطال والأعداء والمنصات مهمة جدًا ليكتمل مخطط المستوى، فبدونها سيغدو مخططك دون فائدة تُذكر، فكيف تعرف هذه الأبعاد؟
</p>

<p>
	لديك طريقتان، إما أن تفتح الصور باستخدام برنامج تصميم متخصص مثل <a href="https://academy.hsoub.com/design/graphic/krita" rel="">كريتا</a> وتستعلم عن خصائصها، أو تكتب برنامج بسيط بلغة بايثون يعطيك إياها وذلك بالاستفادة من الوحدة Pillow التي توفر مكتبة خاصة بالموضوع تسمى PIL، ولكن طبعًا بعد ذكر الوحدة ضمن ملف متطلبات المشروع requirements.txt وفق مايلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_24" style=""><span class="pln">pygame</span><span class="pun">~=</span><span class="lit">1.9</span><span class="pun">.</span><span class="lit">6</span><span class="pln">
</span><span class="typ">Pillow</span></pre>

<p>
	أنشئ ملفًا جديدًا ضمن Pycharm باسم <code>identify</code>، واكتب فيه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_26" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">

</span><span class="com"># GNU All-Permissive License</span><span class="pln">
</span><span class="com"># Copying and distribution of this file, with or without modification,</span><span class="pln">
</span><span class="com"># are permitted in any medium without royalty provided the copyright</span><span class="pln">
</span><span class="com"># notice and this notice are preserved.  This file is offered as-is,</span><span class="pln">
</span><span class="com"># without any warranty.</span><span class="pln">

</span><span class="kwd">from</span><span class="pln"> PIL </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Image</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">path
</span><span class="kwd">import</span><span class="pln"> sys

</span><span class="kwd">if</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">sys</span><span class="pun">.</span><span class="pln">argv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sys</span><span class="pun">.</span><span class="pln">argv</span><span class="pun">[</span><span class="lit">1</span><span class="pun">])</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">(</span><span class="str">'Syntax: identify.py [filename]'</span><span class="pun">)</span><span class="pln">

pic </span><span class="pun">=</span><span class="pln"> sys</span><span class="pun">.</span><span class="pln">argv</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
img </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Image</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="pln">pic</span><span class="pun">)</span><span class="pln">
X   </span><span class="pun">=</span><span class="pln"> img</span><span class="pun">.</span><span class="pln">size</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
Y   </span><span class="pun">=</span><span class="pln"> img</span><span class="pun">.</span><span class="pln">size</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">X</span><span class="pun">,</span><span class="pln"> Y</span><span class="pun">)</span></pre>

<p>
	والآن اضغط على تبويب الطرفية الموجود في أسفل شاشة Pycharm، الذي يفتح لك نافذة الطرفية في بيئتك الافتراضية واكتب فيها التالي حتى تثبت الوحدة Pillo.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_28" style=""><span class="pun">(</span><span class="pln">venv</span><span class="pun">)</span><span class="pln"> pip install </span><span class="pun">-</span><span class="pln">r requirements</span><span class="pun">.</span><span class="pln">txt
</span><span class="typ">Requirement</span><span class="pln"> already satisfied</span><span class="pun">:</span><span class="pln"> pygame</span><span class="pun">~=</span><span class="lit">1.9</span><span class="pun">.</span><span class="lit">6</span><span class="pln"> </span><span class="pun">[...]</span><span class="pln">
</span><span class="typ">Installed</span><span class="pln"> </span><span class="typ">Pillow</span><span class="pln"> </span><span class="pun">[...]</span></pre>

<p>
	وعند انتهاء التثبيت شغل البرنامج البسيط الذي كتبناه للحصول على الأبعاد، وشغله من مسار مجلد اللعبة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_30" style=""><span class="pun">(</span><span class="pln">venv</span><span class="pun">)</span><span class="pln"> python </span><span class="pun">./</span><span class="pln">identify</span><span class="pun">.</span><span class="pln">py images</span><span class="pun">/</span><span class="pln">ground</span><span class="pun">.</span><span class="pln">png
</span><span class="pun">(</span><span class="lit">1080</span><span class="pun">,</span><span class="pln"> </span><span class="lit">97</span><span class="pun">)</span></pre>

<p>
	بذلك تكون قد حصلت على أبعاد صورة الأرضية، وهي في حالتنا 1080 عرض و97 ارتفاع.
</p>

<h2>
	كتل المنصة
</h2>

<p>
	إذا رغبت بتصميم صورة خاصة لكل مُكَوِّن من مكونات اللعبة مثل المنصات والأرضية وغيرها، فهذا يعني أنك ستخصص ملفُا منفصلًا لكل مُكَوِّن مثل الظاهر في الصورة:
</p>

<p style="text-align: center;">
	<img alt="img-04-pygame_floating.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109020" data-unique="exd3ap8bw" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-04-pygame_floating.gif.b42091cbdbac4a3f3161bce9d8e9ddc6.gif">
</p>

<p>
	ويمكنك إعادة استخدام كل منصة عدة مرات ضمن لعبتك، بشرط أن يتضمن كل الملف مُكَوِّن واحد فقط كما ذكرنا، فلا يجوز مثلًا أن تتواجد جميع المكونات المبينة أدناه في ملف واحد:
</p>

<p style="text-align: center;">
	<img alt="img-05-pygame_flattened.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109019" data-unique="ui81nfasw" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-05-pygame_flattened.gif.f8a158bc651f6310526f0b15695e8e10.gif">
</p>

<p>
	وعلى فرض أنك أنشأتها جميعًا في ملف واحد كبير يتضمن كل مكونات الصورة، فلن تملك عندها أي طريقة تجعلك تُمييز المنصة عن خلفية اللعبة، لذا إما أن ترسم المكونات التي تريدها كلٌ في ملفه الخاص أو أن تقصها من الملف الكبير الذي ترغب بالوصول إليه وتحفظها في ملفات منفصلة.
</p>

<p>
	<strong>تنويه</strong>: يمكنك استخدام أحد برامج التصميم الجرافيكي <a href="https://academy.hsoub.com/design/graphic/gimp/" rel="">جيمب</a> أو <a href="https://academy.hsoub.com/design/graphic/krita/" rel="">كريتا</a> أو <a href="https://academy.hsoub.com/design/illustration/inkscape/" rel="">إنكسكيب</a> على سبيل المثال لا الحصر لتُصمم مكونات اللعبة.
</p>

<p>
	تظهر المنصات في بداية كل مستوى لذا عليك إضافة دالة المنصة <code>platform</code> إلى صنف المستوى <code>Level</code>، أما المنصة التي تشكل الأرضية سنفرد لها دالة خاصة فهي تتمتع ببعض الخصوصية إذ إنها تبقى ثابتة في بعض الألعاب بينما تطفو فوقها المنصات الأخرى، أو تتحرك في بعضها الآخر أو تُمرر في أثناء سير اللعبة.
</p>

<p>
	أضف إذًا الدوال التالية إلى صنف المستوى <code>Level</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_33" style=""><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln">x</span><span class="pun">,</span><span class="pln">y</span><span class="pun">,</span><span class="pln">w</span><span class="pun">,</span><span class="pln">h</span><span class="pun">):</span><span class="pln">
    ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
        ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln">y</span><span class="pun">,</span><span class="pln">w</span><span class="pun">,</span><span class="pln">h</span><span class="pun">,</span><span class="str">'block-ground.png'</span><span class="pun">)</span><span class="pln">
        ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> ground_list

</span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln"> lvl </span><span class="pun">):</span><span class="pln">
    plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
        plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">-</span><span class="lit">97</span><span class="pun">-</span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">285</span><span class="pun">,</span><span class="lit">67</span><span class="pun">,</span><span class="str">'block-big.png'</span><span class="pun">)</span><span class="pln">
        plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
        plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">-</span><span class="lit">97</span><span class="pun">-</span><span class="lit">320</span><span class="pun">,</span><span class="pln"> </span><span class="lit">197</span><span class="pun">,</span><span class="lit">54</span><span class="pun">,</span><span class="str">'block-small.png'</span><span class="pun">)</span><span class="pln">
        plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> plat_list</span></pre>

<p>
	الدالة الأولى في التعليمات السابقة هي دالة الأرضية <code>ground</code>، وتتطلب تحديد الإحداثيات X و Y لمعرفة موقع ظهور الأرضية على الشاشة وكذلك تحديد الأبعاد حتى يتبين للوحدة Pygame كيف ستمتد أرضيتك في كلا الاتجاهين، تستخدم هذه الدالة صنف المنصة <code>Platform</code> لإنشاء كائن الأرضية على الشاشة وإضافته إلى مجموعة الأرضيات <code>ground_list</code>.
</p>

<p>
	أما الدالة الثانية دالة المنصة <code>platform</code> فتماثل الأولى تمامًا باستثناء أنها تتضمن أكثر من عنصر في مجموعة المنصات، في حالتنا يوجد منصتين فقط لكن يمكنك إضافة القدر الذي تريده بشرط ضمها جميعًا لمجموعة المنصات <code>plat_list</code> وإلاّ فإنها لن تظهر على الشاشة.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		<strong>تلميح</strong>: إذا شعرت بالارتباك من كون الصفر في أعلى الشاشة والأرقام تزداد كلما هبطت للأسفل، فيمكنك استخدام الأرقام السالبة للتعبير عن الإحداثيات على المحور العمودي Y، وعندها ستقيس ارتفاع كل شيء بدءًا من الأرضية وليس من أعلى الشاشة.
	</p>

	<p>
		نعطيك مثالًا للتوضيح: إذا علمت أن أخفض نقطة في لعبتك هي القيمة <code>worldy</code> وأن ارتفاع أرضية اللعبة هو 97 فإن نقطة سطح الأرضية التي سيقف عليها اللاعب ستكون <code>worldy</code> مطروحًا منها 97، فلو كان طول اللاعب مثلًا هو 64 بكسل فإن سطح الأرضية مطروحًا منها 128 يعادل ضعفي طول اللاعب، ما يعني أن أي منصة تضعها عند هذه النقطة ستكون على ارتفاع يعلو طول اللاعب بمرتين، وأي منصة عند 320- ستعلو ذلك بثلاث مرات إضافية.
	</p>
</blockquote>

<p>
	تعلمنا على طول مقالات السلسلة أن الدوال والأصناف لا تعمل ما لم تستدعيها في البرنامج وهذا ما ستفعله بكتابة هذه التعليمات ضمن مقطع الإعدادات في شيفرة لعبتك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_35" style=""><span class="pln">ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">-</span><span class="lit">97</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1080</span><span class="pun">,</span><span class="pln"> </span><span class="lit">97</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span></pre>

<p>
	واكتب أيضًا الأسطر التالية في الحلقة الرئيسية، مع العلم أن السطر الأول لمعرفة السياق فقط وهو موجود لديك مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_37" style=""><span class="pln">enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">  </span><span class="com"># تحديث الأعداء</span><span class="pln">
ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">  </span><span class="com"># تحديث الأرضية</span><span class="pln">
plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">  </span><span class="com"># تحديث المنصات</span></pre>

<h2>
	منصات البلاط
</h2>

<p>
	يعد استخدام قطع البلاط لبناء عالم الألعاب أسلوبًا أسهل من استخدام الصور الكاملة كما عرضنا في الفقرة السابقة، فكل ما يترتب عليك هنا هو تجهيز أو رسم بعض الكتل مقدمًا ومن ثم استخدامها مرارًا وتكرارًا في كل منصات اللعبة.
</p>

<p>
	توفر مواقع مثل <a href="https://kenney.nl/assets/simplified-platformer-pack" rel="external nofollow">kenney.nl</a> أو <a href="https://opengameart.org/content/simplified-platformer-pack" rel="external nofollow">OpenGameArt.org</a> مجموعاتٍ واسعة من قطع البلاط التي تتمتع <a href="https://ar.wikipedia.org/wiki/%D8%B1%D8%AE%D8%B5_%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B9_%D8%A7%D9%84%D8%A5%D8%A8%D8%AF%D8%A7%D8%B9%D9%8A" rel="external nofollow">برخص المشاع الإبداعي</a>، يمكنك تحميلها واستخدامها، اعتمد مثالنا قطعًا من kenney.nl تبلغ مساحة كل قطعة 64 بكسل مربع، وفي حال اعتمدت قطعًا بأبعادٍ أخرى راعِ ذلك ضمن الشيفرة.
</p>

<p>
	لن يتغير صنف المنصة <code>platform</code> عمّا كتبنا في السابق، لكن الدوال <code>platform</code> و <code>ground</code> في صنف المستوى <code>Level</code> ستتضمن حلقاتٍ خاصة بحساب عدد الكتل اللازمة لبناء كل منصة.
</p>

<p>
	لنفترض أنك ترغب بإنشاء أرضية ثابتة عبر تكرار استخدام قطع البلاط على طول نافذة اللعبة، يمكنك إنجاز ذلك بعدة طرق إحداها إعداد قائمة يدوية بالإحداثيات X و Y لمواقع قطع البلاط على طول المسار المطلوب، وعندها سترسم حلقة التكرار قطعة بلاط في كل موقع، انظر السطر التالي لكن لا تكتبه في فهو مجرد مثال، إذ سنعتمد طريقة أخرى للتعامل مع الموضوع.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_39" style=""><span class="com"># لا تكتب هذا السطر في شيفرة اللعبة فهو مجرد مثال</span><span class="pln">
gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">64</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">128</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">192</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">256</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">320</span><span class="pun">,</span><span class="lit">656</span><span class="pun">,</span><span class="lit">384</span><span class="pun">,</span><span class="lit">656</span><span class="pun">]</span></pre>

<p>
	دقّق قليلًا في المصفوفة السابقة وستجد أن جميع القيم Y متماثلة وهي 656 دائمًا، بينما تزداد قيم X ازديادًا مطردًا بمقدار 64 في كل نقلة الذي يعادل عرض البلاطة الواحدة.
</p>

<p>
	أتمتة هذا النوع من التكرار المنتظم سهلة نوعًا ما فهي تتطلب بعض المنطق الرياضي والعمليات الحسابية لتتم آليًا.
</p>

<p>
	اكتب لذلك التعليمات التالية ضمن مقطع الإعدادات في برنامجك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_41" style=""><span class="pln">gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i</span><span class="pun">=</span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx</span><span class="pun">/</span><span class="pln">tx</span><span class="pun">)+</span><span class="pln">tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i</span><span class="pun">*</span><span class="pln">tx</span><span class="pun">)</span><span class="pln">
    i</span><span class="pun">=</span><span class="pln">i</span><span class="pun">+</span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">gloc</span><span class="pun">,</span><span class="pln">tx</span><span class="pun">,</span><span class="pln">ty </span><span class="pun">)</span></pre>

<p>
	يُجري بايثون من خلال التعليمات السابقة عملية قسمة يُقسم فيها عرض عالم اللعبة على عرض المربع الواحد أو قطعة البلاط الواحدة، وينتج بذلك مصفوفة تتضمن كافة قيم X اللازمة أما قيم Y فهي ثابتة لا تتغير طالما أن أرضية لعبتك مستوية.
</p>

<p>
	استخدم حلقة <code>while</code> لتستثمر المصفوفة السابقة في دالة بناء الأرضية فهي ستضيف بلاطة إلى الأرضية في الموقع المقابل لكل قيمة من قيم المصفوفة.
</p>

<p>
	وستصبح الدالة على الشكل التالي، اكتبها ضمن صنف المستوى <code>Level</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_43" style=""><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln">gloc</span><span class="pun">,</span><span class="pln">tx</span><span class="pun">,</span><span class="pln">ty</span><span class="pun">):</span><span class="pln">
    ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
    i</span><span class="pun">=</span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
            ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln">worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">,</span><span class="pln">tx</span><span class="pun">,</span><span class="pln">ty</span><span class="pun">,</span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
            ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
            i</span><span class="pun">=</span><span class="pln">i</span><span class="pun">+</span><span class="lit">1</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> ground_list</span></pre>

<p>
	تتشابه هذه الدالة في الغرض مع دالة الأرضية <code>ground</code> التي تعاملنا معها في الفقرة السابقة إلّا أنها تعتمد هنا على الحلقة <code>while</code>.
</p>

<p>
	المبادئ نفسها تقريبًا لدالة المنصات المتحركة، وسنعطيك بعض النصائح الكفيلة بتبسيط الموضوع، فبدلًا من تحديد مساحة كل منصة بالبكسل، يمكنك الاستعاضة عن ذلك بتحديد نقطة بداية المنصة (أو الإحداثي X) ومدى ارتفاعها عن الأرضية (أي الإحداثي Y) وأيضًا عدد قطع البلاط التي تحتويها، وبذلك لن تحتاج لتحديد أبعاد كل منصة.
</p>

<p>
	برمجة هذه العملية معقدة بعض الشيء فهي تتضمن حلقتي <code>while</code> الواحدة ضمن الأخرى، إذ إن إنشاء كل منصة يستلزم تحديد ثلاث محددات مقابل كل قيمة من قيم المصفوفة، في حالتنا مثلًا لا يوجد سوى ثلاث منصات تعرفها التعليمات <code>ploc.append</code> لكن بوسعك إضافة القدر الذي تريده من المنصات، وستلاحظ أنها لن تظهر دفعة واحدة عند تنفيذ الشيفرة بل ستظهر المنصات الخاصة بالشاشة الحالية فقط ومع تمرير الشاشة أثناء اللعب ستظهر البقية تباعًا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_45" style=""><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln">tx</span><span class="pun">,</span><span class="pln">ty</span><span class="pun">):</span><span class="pln">
    plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
    ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
    i</span><span class="pun">=</span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
        ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln">worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="lit">128</span><span class="pun">,</span><span class="lit">3</span><span class="pun">))</span><span class="pln">
        ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln">worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="lit">256</span><span class="pun">,</span><span class="lit">3</span><span class="pun">))</span><span class="pln">
        ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">500</span><span class="pun">,</span><span class="pln">worldy</span><span class="pun">-</span><span class="pln">ty</span><span class="pun">-</span><span class="lit">128</span><span class="pun">,</span><span class="lit">4</span><span class="pun">))</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
            j</span><span class="pun">=</span><span class="lit">0</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]+(</span><span class="pln">j</span><span class="pun">*</span><span class="pln">tx</span><span class="pun">)),</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln">tx</span><span class="pun">,</span><span class="pln">ty</span><span class="pun">,</span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                j</span><span class="pun">=</span><span class="pln">j</span><span class="pun">+</span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
            i</span><span class="pun">=</span><span class="pln">i</span><span class="pun">+</span><span class="lit">1</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> plat_list</span></pre>

<p>
	إذًا فقد أنشأت الدالة المسؤولة عن بناء المنصات، وعليك الآن استدعائها داخل البرنامج وفق الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_47" style=""><span class="pln">plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span></pre>

<p>
	وأخيرًا اكتب التالي في الحلقة الرئيسية حتى تظهر المنصات في عالم لعبتك (السطر الأول للحفاظ على السياق فقط فلا داعي لكتابته):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_49" style=""><span class="pln">        enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">  </span><span class="com"># تحديث الأعداء</span><span class="pln">
        ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln"> </span><span class="com"># تحديث الأرضية</span><span class="pln">
        plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">   </span><span class="com"># تحديث المنصات</span></pre>

<p>
	شغل اللعبة الآن، ولاحظ توضع المنصات وشكلها، وعدّل ما تريد، علمًا أنك لن تجد المنصات التي لا تنتمي للشاشة الأولى، لا تقلق سنتجاوز ذلك في المقالات اللاحقة عبر تمرير عالم اللعبة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="gif" data-fileid="109024" href="https://academy.hsoub.com/uploads/monthly_2022_10/img-06-pygame-platform.gif.7da7643736dac916e421fcf2561b689e.gif" rel=""><img alt="img-06-pygame-platform.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109024" data-unique="is2sra4x6" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/img-06-pygame-platform.thumb.gif.f9c97b6db43a60db687359df29391507.gif"></a>
</p>

<h2>
	طبق المهارات التي تعلمتها في السابق
</h2>

<p>
	لم يذكر هذا المقال أين يتوضع العدو أو كيف، لذا طبق المهارات التي تعلمتها سابقًا وأظهره على الأرضية أو فوق إحدى المنصات فهي الأماكن الأنسب له، أما البطل دعه حاليًا فهو محكوم بقوى خاصة بعالم الرسوم المتحركة تحاكي قوى الجاذبية في العالم الحقيقي ستتعلمها في مقالاتنا التالية.
</p>

<p>
	إليك الشكل النهائي للشيفرة حتى الآن:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3646_51" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xloc</span><span class="pun">,</span><span class="pln"> yloc</span><span class="pun">,</span><span class="pln"> imgw</span><span class="pun">,</span><span class="pln"> imgh</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> yloc
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> xloc

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> y

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">]</span><span class="pln">

        hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> ground</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        ground_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">):</span><span class="pln">
                ground </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">(</span><span class="pln">gloc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile-ground.png'</span><span class="pun">)</span><span class="pln">
                ground_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">ground</span><span class="pun">)</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> ground_list

    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list

    </span><span class="com"># x location, y location, img width, img height, img file</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> platform</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">):</span><span class="pln">
        plat_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
        ploc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">200</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">256</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln">
            ploc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">((</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> worldy </span><span class="pun">-</span><span class="pln"> ty </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">):</span><span class="pln">
                j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]:</span><span class="pln">
                    plat </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Platform</span><span class="pun">((</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)),</span><span class="pln"> ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">][</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tile.png'</span><span class="pun">)</span><span class="pln">
                    plat_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">plat</span><span class="pun">)</span><span class="pln">
                    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'run'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">ploc</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln">
                i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> plat_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">)</span><span class="pln">

gloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
tx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">
ty </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pln">

i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">worldx </span><span class="pun">/</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> tx</span><span class="pun">:</span><span class="pln">
    gloc</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> tx</span><span class="pun">)</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

ground_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">ground</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> gloc</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">
plat_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">platform</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> tx</span><span class="pun">,</span><span class="pln"> ty</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    ground_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    plat_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/18/7/put-platforms-python-game" rel="external nofollow">Put platforms in a Python game with Pygame</a> لصاحبيه Seth Kenlon و Jess Weichler.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة عبر مكتبة Pygame في بايثون</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
	<li>
		دليلك الشامل إلى:  <a href="https://academy.hsoub.com/programming/game-development/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8/" rel="">أشهر لغات برمجة الألعاب</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1730</guid><pubDate>Wed, 05 Oct 2022 16:04:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x634;&#x62E;&#x635;&#x64A;&#x629; &#x627;&#x644;&#x639;&#x62F;&#x648; &#x644;&#x644;&#x639;&#x628;&#x629; &#x639;&#x628;&#x631; &#x645;&#x643;&#x62A;&#x628;&#x629; Pygame &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_09/631c37a60bc83_----.png.1ed836ac8b7bc38c1513248b76b9c53a.png" /></p>

<p>
	وصلنا للمقال الخامس من سلسلة بناء لعبة من الصفر باستخدام بايثون، وقد تعلمنا في أجزائها الأربعة السابقة كيفية بناء لعبة فيديو باستخدام الوحدة Pygame وطورنا اللعبة بوجود بطل متحرك، والآن سنضيف إليها بعض الإثارة بإضافة شخصية شريرة للمشهد أو عدو ليواجه البطل فهذا تقليدي في عالم الألعاب، ومن ثم سنبني إطار عمل خاص بإضافة مستويات اللعبة.
</p>

<p>
	يمكنك مطالعة المقال ضمن السلسلة:
</p>

<ol>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		إضافة شخصية العدو للعبة.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>
<p>
	بناء شخصية العدو مشابه تمامًا لبناء شخصية البطل سنستخدم الوظائف نفسها، وفي حال لم تُحضّر له صورة حتى الآن يمكنك اختيارها من <a href="https://opengameart.org/content/opp2017-sprites-characters-objects-effects" rel="external nofollow">مجموعة الصور المجانية المتاحة على منصة OpenGameArt.org</a> أو نزلها من الملف المرفق <a class="ipsAttachLink" data-fileid="107684" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=107684" rel="">opp2_sprites</a>، وننصحك بتعلم المزيد عن <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B1%D8%A7%D8%AE%D9%8A%D8%B5-%D8%A7%D9%84%D8%A8%D8%B1%D8%A7%D9%85%D8%AC-%D9%85%D9%81%D8%AA%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-r1586/" rel="">رخصة المشاع الإبداعي</a> حتى لا تنتهك حقوق النشر في الصور التي تستخدمها.
</p>

<h2>
	إنشاء شخصية العدو
</h2>

<p>
	العملية مشابهة جدًا لعملية إنشاء كائن البطل، فلديك المفاتيح الرئيسة للعمل.
</p>

<ol>
<li>
		أنشئ صنفًا خاصًا بشخصية العدو لإنتاج كائن الشخصية.
	</li>
	<li>
		أنشئ دالة <code>update</code> لتحديث كائن العدو في الحلقة الرئيسية.
	</li>
	<li>
		أنشئ دالة <code>move</code> لتمنح شخصية العدو حركة عشوائية.
	</li>
</ol>
<p>
	ابدأ بالصنف بالطريقة نفسها لصنف البطل، ومن ثم حدد الصورة أو مجموعة الصور التي تعتمدها لشخصية العدو واحفظها في المجلد images الخاص بالصور ضمن مجلد مشروعك (المجلد نفسه الذي يتضمن صور البطل)، وأعطها اسمًا دلاليًا مثل enemy.png المستخدم في حالتنا.
</p>

<p>
	بالتأكيد ستبدو اللعبة أفضل لو جعلت كافة العناصر تتحرك، لكننا سنترك شخصية العدو دون حركة في هذه المرحلة حتى نخفف عليك التعقيد، ولو رغبت بتحريكه استذكر خطواتنا في <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">المقال السابق</a>.
</p>

<p>
	اكتب التعليمات التالية لإنشاء صنف العدو في أعلى المقطع الخاص بالكائنات <code>objects</code> ضمن برنامجك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_8" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln">x</span><span class="pun">,</span><span class="pln">y</span><span class="pun">,</span><span class="pln">img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln">img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y</span></pre>

<p>
	يمكنك استخدام الصنف نفسه لتوليد عدة أعداء، فكل ما عليك فعله هو استدعاء الصنف وإعطائه صورة لكل شخصية وإحداثيات ظهورها على الشاشة X و Y.
</p>

<p>
	تمامًا مثل صنف اللاعب، اكتب صنف العدو في مقطع الإعدادات <code>setup</code> ضمن البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_10" style="">
<span class="pln">enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="lit">300</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">   </span><span class="com"># إنتاج العدو</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">  </span><span class="com"># إنشاء مجموعة الأعداء</span><span class="pln">
enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">         </span><span class="com"># إضافة عدو للمجموعة</span></pre>

<p>
	أنتجت التعليمات السابقة كائنًا يسمى <code>enemy</code> إحداثيات موقعه هي 300 بيكسل على المحور X و 0 بيكسل على المحور Y، ما يعني أن زاويته العلوية اليسرى عند النقطة 0 وتمتد صورته للأسفل تبعًا لمساحتها، لذا تنبه لأحجام صور الأعداء والأبطال واضبط إحداثياتها لتكون مواضعها مناسبة على الشاشة، وولد الأعداء في مكانٍ يمكنك إيصال بطل اللعبة إليه ففي مثالنا وضعنا العدو في النهاية عند النقطة 0 بيكسل والبطل عند النقطة 30 بيكسل على المحور العمودي Y ليظهرا بنفس المستوى (وهذا بسبب افتقار اللعبة إلى الحركة العمودية)، علمًا أن الصفر على المحور Y يقع في الأعلى ما يعني أن الأرقام تزداد كلما اتجهت نحو أسفل الشاشة.
</p>

<p>
	ولاحظ أن صورة البطل مدمجة مع كود الصنف أي ثابتة hard coded في مثالنا، ذلك أن البطل وحيد في اللعبة، أما صور الأعداء متغيرة إذ قد ترغب باستخدام أكثر من نموذج لها، لذا حدد الصورة خلال عملية إنشاء الشخصية، والصورة المستخدمة في مثالنا هي <code>enemy.png</code>.
</p>

<h2>
	رسم شخصية على الشاشة
</h2>

<p>
	حاول تشغيل لعبتك الآن، ستعمل، لكن شخصية العدو لن تظهر على الشاشة، اعترضتنا هذه المشكلة قبلًا وبالتأكيد عرفت السبب فتعليمات إنشاء الشخصية لم تكتب ضمن الحلقة الرئيسية، تذكّر دومًا أن أي شيء تريد حدوثه باستمرار لابد من ذكره في حلقة التكرار، أما بدون ذلك فسيظهر العدو على الشاشة لمدة بسيطة جدًا لأجزاء من الثانية ويختفي دون أن تلحظه حتى.
</p>

<p>
	أضف السطر الأوسط من التعليمات التالية إلى الحلقة حتى تُحدّث ظهور مجموعة الأعداء <code>enemy_list</code> التي تتكون حاليًا من عدو واحد لكن يمكنك توسيعها بإضافة أعداء آخرين وسيظهرون جميعًا مع كل تكرار للحلقة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_12" style="">
<span class="pln">    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">  </span><span class="com"># تحديث مجموعة الأعداء</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span></pre>

<p>
	شغل اللعبة بعد التعديلات، وستجد شخصية العدو على الشاشة في الموقع الذي تحدده الإحداثيات X و Y.
</p>

<h2>
	إضافة مراحل للعبة
</h2>

<p>
	يخطط مطور الألعاب لمستويات أو مراحل اللعبة حتى وهي في مهدها، ورغم بساطة لعبتنا وعدم وجود أي مستوى فيها حتى الآن، إلّا أننا سنكتب التعليمات كما لو كنا نخطط لبناء عدة مستويات.
</p>

<p>
	فكر في ماهية المستوى الذي تعّده؟ عادةً عندما تلعب كيف تعرف أنك في مستوى معين أو أنك انتقلت لمستوى جديد؟
</p>

<p>
	يمكننا القول أن المستوى هو مجموعة من العناصر المميزة، وفي ألعاب المنصات مثل لعبتنا يتكون المستوى من مجموعة منصات مرتبة ترتيبًا معينًا، بالإضافة إلى نوع خاص بالمستوى من الأعداء والغنائم وما شابه، أما عن طريقة بناء المستوى سننشئ له صنفًا خاصًا يبني المستوى حول اللاعب، ونعيد استخدامه بعد الانتهاء لبناء المستويات اللاحقة.
</p>

<p>
	انقل الآن التعليمات التي كتبتها سابقًا لبناء شخصية العدو ومجموعة الأعداء، إلى دالة جديدة واستدعيها مع كل بناء لمستوى جديد، ستحتاج بالطبع لبعض التعديلات لإنتاج أنواع مختلفة من الأعداء لكل مستوى.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_14" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln">eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln"> </span><span class="com"># إنتاج العدو</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln"> </span><span class="com"># إنشاء مجموعة الأعداء</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">  </span><span class="com"># إضافة عدو لمجموعة الأعداء</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list</span></pre>

<p>
	مهمة التعليمة <code>return</code> السابقة هي إرجاع قائمة تتضمن مجموعة الأعداء <code>enemy_list</code> التي استخدمتها مع كل تنفيذ للدالة <code>Level.bad</code>.
</p>

<p>
	نظرًا لأن إنشاء العدو أصبح جزءًا من إنشاء المستوى، سنجري تعديلًا على مقطع الإعدادات <code>setup</code>، فبدلًا من إنشاء العدو، سنحدد المستوى الذي ينتمي إليه وأين سيتم إنتاجه، وذلك وفق الأوامر التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_16" style="">
<span class="pln">eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc </span><span class="pun">)</span></pre>

<p>
	شغل اللعبة مجددًا وتأكد من صحة إنشاء المستوى ومن ظهور البطل والعدو.
</p>

<h2>
	التصادم مع العدو
</h2>

<p>
	لا تُعدّ شخصية العدو فاعلة ما لم تسبب ضررًا للاعب أو تؤثر عليه، والتصادم هو أشيع أنواع الضرر في الألعاب.
</p>

<p>
	أما بعد التصادم علينا فحص حالة البطل أو صحته وسنجري ذلك في صنف البطل، يمكنك بالطبع فحص صحة العدو بالطريقة نفسها لكننا سنكتفي بتتبع صحة اللاعب، وذلك من خلال تعريف متغير خاص يشير إلى صحة اللاعب وفق السطر الثاني من التعليمات التالية أما السطر الأول فذُكر للإشارة إلى السياق فقط.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_18" style="">
<span class="pln">        self</span><span class="pun">.</span><span class="pln">frame  </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span></pre>

<p>
	وأيضًا أضف التعليمات التالية في الدالة <code>update</code> ضمن صنف اللاعب.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_20" style="">
<span class="pln">        hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span></pre>

<p>
	تكشف هذه التعليمات التصادم باستخدام <code>sprite.spritecollide</code> إحدى دوال Pygame ضمن المتغير <code>hit_list</code> لحظة التلامس بين صندوق البطل -الذي تفحص صحته- وصندوق أي شخصية تنتمي لمجموعة العدو <code>enemy_list</code>، ويرسل عندها إشارة إلى الحلقة <code>for</code> تؤدي إلى خصم نقطة من صحة اللاعب في كل مرة يحدث فيها التصادم.
</p>

<p>
	ولأن هذه التعليمات مكتوبة في الدالة <code>update</code> لصنف اللاعب التي تُستدعى مع كل تكرار للحلقة الرئيسية، فإن Pygame ستتحق من التصادم مع كل نبضة ساعة.
</p>

<h2>
	تحريك العدو
</h2>

<p>
	يعدّ نمط العدو الثابت الذي بنيناه هنا مقبولًا في الألعاب مثل المسامير والمصائد التي تعرقل سير اللاعب، إلاّ أن العدو المتحرك يضيف صعوبةً وإثارة للعبة.
</p>

<p>
	سنبدأ بتحريك العدو مع مراعاة أمرين، الأول أنه حركته آلية تُدار من قبل البرنامج ولا يتحكم بها المستخدم مثل حركة البطل، والثاني أن بيئة اللعبة أو عالمها متحرك، فكيف سنجعل العدو يتحرك داخله ذهابًا وإيابًا وهو أساسًا يتحرك؟
</p>

<p>
	لنفترض أنك ترغب ببرمجة حركة العدو ليتحرك 10 خطوات نحو اليمين ومن ثم 10 نحو اليسار، كائن العدو لا يملك في مواصفاته البرمجية ما يمكنه من عدّ الخطوات، لذا ستحتاج إلى تعريف متغير يتتبع خطواته ويعدها، ومن ثم تبرمج عدوك ليتحرك يمينًا أو يسارًا بناءً على عدد الخطوات التي أنجزها.
</p>

<p>
	لنبدأ إذًا بتعريف متغير العداد المسؤول عن عدّ الخطوات، عبر إضافة السطر الأخير من التعليمات التالية إلى صنف العدو:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_22" style="">
<span class="pln">        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="com"># متغير العداد</span></pre>

<p>
	ثم ننشئ دالة الحركة <code>move</code> في صنف العدو أيضًا، وذلك عبر الحلقة if-else بالشروط الآتية، التي ستجعلها حلقة لا نهائية.
</p>

<ul>
<li>
		تحرك يمينًا إذا كانت قيمة العداد بين 0 و 100.
	</li>
	<li>
		تحرك يسارًا إذا كانت قيمة العداد بين 100 و 200.
	</li>
	<li>
		صفّر العداد وأرجعه للقيمة 0 عندما تتجاوز قيمته العدد 200.
	</li>
</ul>
<p>
	ستحرك هذه الحلقة كائن العدو يمينًا ويسارًا إلى ما لا نهاية فلا يوجود قيمة للمتغير تجعلها تتوقف فهو دائمًا بين 0 و 100 أو بين 100 و 200.
</p>

<p>
	أما عن كيفية اختيار القيم التي ستشكل أقصى مسافة يمكن للكائن الوصول إليها فالموضوع نسبي، يتغير تبعًا لقياس شاشة العرض لديك وقياس منصة اللعبة، لذا ننصحك بالتجريب، ابدأ بأرقام صغيرة ولاحظ النتائج ثم زدها لتصل لغايتك، والأمر نفسه بالنسبة لسرعة الحركة، مثلًا جرب التالي في البداية ويمكنك تعديله حسب رضاك عن النتائج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_24" style="">
<span class="pln">    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">'''
        enemy movement
        '''</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">*</span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	بعد كتابة هذه التعليمات ستعرض عليك بيئة التطوير Pycharm تحذيرًا يتضمن اقتراحًا لتبسيط موازنة السلاسل بهدف تحسين أسلوب كتابة التعليمات، يمكنك قبول الاقتراح وتعلم المزيد عن الكتابة المتقدمة في بايثون، أو تجاهل التحذير بأمان والاستمرار.
</p>

<p>
	السؤال الآن، هل سيتحرك العدو عند تشغيل اللعبة؟ أم أننا تحتاج لخطوة إضافية؟
</p>

<p>
	الإجابة هي لا بالطبع، لن يتحرك ما لم تستدعِ الدالة <code>move</code> ضمن حلقة البرنامج الرئيسية، أضف السطرين الأخيرين من التعليمات التالية لتُنجز ذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_26" style="">
<span class="pln">    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln"> </span><span class="com">#حدّث العدو </span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span></pre>

<p>
	شغل اللعبة وشاهد ما يحدث عند اصطدام بطل اللعبة بالعدو، ربما ستحتاج لبعض التعديلات مثل تغيير مكان إنتاج العدو لتصنع التصادم، وعندما يحدث ذلك، تفقد النقاط التي خُصمت من رصيد صحة اللاعب من خلال بيئة التطوير IDLE أو Pycharm.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="107687" href="https://academy.hsoub.com/uploads/monthly_2022_09/img-01-pygame-hero-enemy.png.4206909b369fe7a5e19ec1758e713ae6.png" rel=""><img alt="img-01-pygame-hero-enemy.png" class="ipsImage ipsImage_thumbnailed" data-fileid="107687" data-unique="2ara6zwes" src="https://academy.hsoub.com/uploads/monthly_2022_09/img-01-pygame-hero-enemy.thumb.png.ad0f2ba9a0ffe4355f8ca4ed5cb8adbe.png" style="width: 450px; height: auto;"></a>
</p>

<p>
	قد تلاحظ أن النقاط تُخصم من صحة اللاعب (أو من أدوار اللاعب) في كل لحظة من الاصطدام، ستتعلم معالجة ذلك مع تطور مهاراتك في بايثون، أما حاليًا جرّب أن تنتج المزيد من الأعداء ووأيًا كانوا لا تنسَ إضافتهم إلى مجموعة الأعداء <code>enemy_list</code>، ومن ثم حاول تغير طريقة حركتهم استخدم حركة مختلفة لكل عدو.
</p>

<h2>
	الشكل النهائي لبرنامج اللعبة
</h2>

<p>
	إليك الشكل النهائي لبرنامج اللعبة متضمنًا كامل التعليمات البرمجية التي استخدمناها خلال السلسلة، ليبقى مرجعًا لك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1005_29" style="">
<span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> y

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame</span><span class="pun">//</span><span class="pln">ani</span><span class="pun">]</span><span class="pln">

        hit_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="pln">spritecollide</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> enemy_list</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> enemy </span><span class="kwd">in</span><span class="pln"> hit_list</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">health </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">health</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn an enemy
    """</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> img</span><span class="pun">))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> y
        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        enemy movement
        """</span><span class="pln">
        distance </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pln">
        speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> speed
        </span><span class="kwd">elif</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&gt;=</span><span class="pln"> distance </span><span class="kwd">and</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">&lt;=</span><span class="pln"> distance</span><span class="pun">*</span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> speed
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> bad</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">,</span><span class="pln"> eloc</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            enemy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enemy</span><span class="pun">(</span><span class="pln">eloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> eloc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="str">'enemy.png'</span><span class="pun">)</span><span class="pln">
            enemy_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
            enemy_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">enemy</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> lvl </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Level "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">lvl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> enemy_list


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
eloc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span><span class="pln">
enemy_list </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Level</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> eloc </span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    enemy_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> enemy_list</span><span class="pun">:</span><span class="pln">
        e</span><span class="pun">.</span><span class="pln">move</span><span class="pun">()</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/18/5/pygame-enemy" rel="external nofollow">What's a hero without a villain? How to add one to your Python game</a> لصاحبه Seth Kenlon.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية في لعبة باستخدام Pygame</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D8%AD%D8%AC%D8%B1%D8%A9-%D9%88%D8%B1%D9%82%D8%A9-%D9%85%D9%82%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1701/" rel="">برمجة لعبة حجرة ورقة مقص باستخدام لغة بايثون </a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى لعبة مطورة باستخدام بايثون ومكتبة Pygame</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1707</guid><pubDate>Wed, 28 Sep 2022 16:03:00 +0000</pubDate></item><item><title>&#x62A;&#x62D;&#x631;&#x64A;&#x643; &#x634;&#x62E;&#x635;&#x64A;&#x629; &#x641;&#x64A; &#x644;&#x639;&#x628;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Pygame</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/</link><description><![CDATA[<p>
	استخدمنا <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> لبناء لعبة نرد بسيطة معتمدة على النص في <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">مقالنا الأول</a> من هذه السلسلة، وفي <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">الثاني</a> تعلمنا كيفية تجهيز بيئة لعبة رسومية من الصفر أيضًا بلغة بايثون، أما في المقال الثالث <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">السابق</a> أضفنا كائنًا أو بطلًا للعبة الفارغة، والآن سنتعلم استخدام Pygame لتحريك الكائن والتحكم به مباشرةً من خلال لوحة المفاتيح، بطريقة شبيهة نوعًا ما ببرمجة زر مغادرة اللعبة التي اتبعناها في المقال الثاني، إلّا أنها أكثر تعقيدًا.
</p>

<p>
	يمكنك مطالعة المقال ضمن السلسلة:
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame</a>.
	</li>
	<li>
		تحريك شخصية اللعبة باستخدام PyGame.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<p>
	تدعم Pygame خياراتٍ أخرى للتحكم مثل الفأرة أو قبضة اللعب لن يغطيها هذا المقال، ولكن لا تقلق فمجرد فهمك لطريقة العمل مع لوحة المفاتيح سيفتح لك الباب لتعلُّم الخيارات الأخرى وتطبيقها بسهولة.
</p>

<h2>
	إعداد مفاتيح التحكم بحركة الشخصية
</h2>

<p>
	افتح السكربت الخاص باللعبة باستخدام بيئة التطوير المتكاملة IDLE أو PyCharm أو ما تفضل.
</p>

<p>
	والآن حاول أن تخمن، في أي مقطع من مقاطع السكربت ينبغي أن نكتب التعليمات البرمجية الخاصة بمفاتيح التحكم؟ وانتبه إلى أن اللعبة ستبقى في حالة ترقب دائمة لأوامر التحكم الواردة من لوحة المفاتيح، ما يعني أننا بصدد حدث سيتكرر دائمًا.
</p>

<p>
	لابد أنك أصبت، فهي بالفعل ستكتب في الحلقة الرئيسية وتذكر أن أي تعليمات لا توضع ضمن <a href="https://academy.hsoub.com/programming/python/%d8%ad%d9%84%d9%82%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1-loops-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r291/" rel="">حلقة التكرار</a> تُنفذ لمرة واحدة فقط، وقد لا تُنفذ أبدًا إن كانت ضمن وظيفة أو إجراء لم يُستدعى.
</p>

<p>
	إذًا، اكتب التعليمات التالية في الحلقة الرئيسية، ولاحظ أننا استخدمنا تعليمة <code>print</code> لاختبار صحة تنفيذها، إذ إن البرنامج الكلي لم يجهز بعد.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_9" style=""><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">();</span><span class="pln"> sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'left'</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'right'</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'left stop'</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'right stop'</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">  </span></pre>

<p>
	شاع عند الكثير استخدام الأزرار W و A و S و D في لوحة المفاتيح لتحريك شخصيات الألعاب بينما يفضل بعضهم الآخر أسهم الاتجاهات، لذا احرص على تضمين الخيارين في برنامجك.
</p>

<p>
	<strong>تنويه</strong>: راعي دومًا احتياجات وتفضيلات أوسع فئة ممكنة من المستخدمين عند تطوير أي تطبيق، خصوصًا إن كانت البرمجة هي مهنتك التي تكسب منها، فإعطاء خيارات متعددة للمستخدم يعدّ واحدًا من أفضل المؤشرات التي تدل على مهارة المبرمج وتمتع تطبيقه بقابلية الوصول وهي ميزة مهمة في تطوير التطبيقات.
</p>

<p>
	شغل لعبتك الآن باستخدام بايثون، وتفقد الخرج الظاهر في نافذة الطرفية عند ضغط الأزرار A أو W أو D أو أسهم الاتجاهات.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_11" style=""><span class="pln">$ python </span><span class="pun">./</span><span class="pln">your</span><span class="pun">-</span><span class="pln">name_game</span><span class="pun">.</span><span class="pln">py
  left
  left stop
  right
  right stop
  jump</span></pre>

<p>
	ستلاحظ أن Pygame تكتشف ضغطات الأزرار على المفاتيح بصورة صحيحة وتفهمها فالتعليمات صحيحة إذًا، لذا دعنا ننتقل إلى الجزء الأصعب وهو تحريك الكائن.
</p>

<h2>
	تحريك شخصية اللعبة
</h2>

<p>
	يتطلب تحريك شخصية إنشاء خاصية تمثل الحركة على كل محور، وتعريف متغير يحمل القيمة صفر عندما لا يتحرك الكائن، وأيضًا تتبع الأطر حتى تظل دورة المشي ضمن المسار الصحيح.
</p>

<p>
	عرّف المتغيرات التالية ضمن الصنف الخاص بشخصية اللاعب وذلك بإضافة الأسطر الثلاثة الأخيرة فقط أما السطر الأول والثاني فهما لديك أساسًا وأعدنا كتابتها هنا حتى يكون السياق واضحًا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_13" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="com"># X الحركة بالاتجاه الأفقي  </span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="com"># Y الحركة بالاتجاه العمودي </span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="com"># عدد الأطر</span></pre>

<p>
	لننتقل إلى برمجة الحركة بعد أن عرفنا المتغيرات.
</p>

<p>
	لا يُفترض بشخصية اللعبة أن تستجيب للضغط على أزرار لوحة المفاتيح طوال الوقت ففي بعض الأحيان لا يُطلب منه التحرك، فتعليمات التحكم إذًا هي جزء فقط من الأشياء التي يمكنه فعلها، ولتعمل هذه التعليمات باستقلالية عن بقية الكود سنضعها ضمن دالة خاصة فهذا أسلوب بايثون، والدوال في لغة بايثون تبدأ بالكلمة المفتاحية <code>def</code> وهي الحروف الأولى من كلمة define التي تعني تعريف.
</p>

<p>
	عرف إذًا دالة في الصنف الخاص باللاعب تكون مسؤولة عن التحريك عبر إضافة عدد معين من وحدات البكسل -سيحدد في أجزاء لاحقة من البرنامج- إلى الموضع الحالي للكائن، فالتحريك في Pygame يعني تحديد موضع جديد للكائن ليعيد بايثون رسمه فيه.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_15" style=""><span class="pln">    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln">x</span><span class="pun">,</span><span class="pln">y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> y</span></pre>

<p>
	سنخصص لعملية تحديث الموضع دالة جديدة في صنف اللاعب تسمى <code>update</code> تُكتب بعد دالة التحكم <code>control</code> السابقة، وذلك وفق التعليمات التي سترد لاحقًا.
</p>

<p>
	لتُظهر كائنًا ما على أنه يمشي (أو يطير أو أيًا كان ما عليه القيام به)، عليك أن تغير موضعه على الشاشة بما يتناسب مع الزر الذي ضغطه المستخدم، أما الموضع الجديد فيُحدد بكل من الخاصية <code>self.rect.x</code> و <code>self.rect.y</code> وأيضًا بعدد وحدات البكسل المطبق <code>movex</code> و <code>movey</code> (وهذا العدد سيحدد لاحقًا ضمن الكود).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_17" style=""><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span></pre>

<p>
	وبالمثل للموضع العمودي Y:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_19" style=""><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey</span></pre>

<p>
	لتحقق أثر الرسوم المتحركة، عدّل الأطر كلما تحرك الكائن واستخدم في كل مرة الإطار المناسب للحركة ليكون بمثابة صورة للاعب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_21" style=""><span class="pln">        </span><span class="com"># الحركة يسارًا</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame</span><span class="pun">//</span><span class="pln">ani</span><span class="pun">]</span><span class="pln">

        </span><span class="com"># الحركة يمينًا</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame</span><span class="pun">//</span><span class="pln">ani</span><span class="pun">]</span></pre>

<p>
	عرّف الآن متغيرًا يحدد عدد وحدات البكسل التي سيتحرك الكائن بمقدارها عند بدء تنفيذ الدوال الخاصة بذلك، واكتب هذا المتغير في مقطع الإعدادات ضمن سكربت اللعبة وفق الآتي (مع العلم أننا أعدنا كتابة أول سطرين توضيحًا للسياق فقط، أما تعريف المتغير فهو في السطر الأخير).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_23" style=""><span class="pun">…</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">  </span><span class="com"># عدد وحدات البكسل التي سيتغير بمقدارها موضع الكائن</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	الآن بعد أن جهزنا دالة التحكم بالحركة والمتغير الذي يحدد مقدارها، يمكننا تبديل التعليمة <code>print</code> باسم اللاعب (وهو player) متبوعًا باسم الدالة <code>control.</code> مع تحديد عدد الخطوات التي سيتحركها الكائن مع كل تكرار للحلقة سواء على المحور X الأفقي أو العمودي Y.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_25" style=""><span class="pln">        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span></pre>

<p>
	يشير المتغير <code>steps</code> لعدد وحدات البكسل التي تتحرك بموجبها الشخصية أو اللاعب عند الضغط على أحد أزرار التحكم بالحركة، فلو كان <code>steps</code> هو 10 بكسيل هذا يعني أننا سنضيف 10 خطوات لموضع اللاعب عند الضغط على الزر D مثلًا وفور تحرير الزر أو إيقاف الضغط عليه سنطرح 10 خطوات <code>steps-</code> من موضعه لإعادة زخم الكائن إلى الصفر (ويعرف <a href="https://ar.wikipedia.org/wiki/%D8%B2%D8%AE%D9%85_%D8%A7%D9%84%D8%AD%D8%B1%D9%83%D8%A9" rel="external nofollow">الزخم Momentum</a> في الفيزياء بأنه كمية تصف مقدار القوة المطلوبة لإيقاف جسم ما).
</p>

<p>
	جرب لعبتك الآن، لكنك لن تحظى بما تتوقع فما زالت تحتاج لبعض التعديلات.
</p>

<h2>
	تعديل صورة الشخصية عند تحريكها
</h2>

<p>
	ستجد بعد التجريب أن الكائن لم يتحرك، وذلك عائد لعدم استدعاء الدالة <code>update</code> في الحلقة الرئيسية، وهو ما سنقوم به عبر إضافة السطر الأول من التعليمات التالية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_27" style=""><span class="pln">    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">  </span><span class="com"># تحديث موضع اللاعب</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	شغل اللعبة مجددًا وشاهد حركة الكائن على الشاشة يمينًا ويسارًا واستجابته لضغط الأزرار، علمًا أننا لم نبرمج الحركة العمودية حتى الآن فلها قوانين ووظائف خاصة تحكمها مثل الجاذبية، ربما نستعرضها في مقالٍ آخر.
</p>

<p>
	يتبقى لدينا مشكلة بسيطة هي أن الكائن لا يلتفت وفقًا للاتجاه الذي يسير فيه، فلو كان وجهه مصممًا أساسًا إلى اليمين في الصورة التي اخترتها، سيبدو وكأنه يسير للخلف عندما يضغط المستخدم على السهم الأيسر ليحرّكه يسارًا، وسيعطي ذلك انطباعًا سيئًا عن اللعبة، فالمستخدم يتوقع استدارة البطل مع اتجاه الحركة.
</p>

<h2>
	توجيه الشخصية وفقا لاتجاه حركتها
</h2>

<p>
	تتيح لك Pygame وظيفةً جاهزة لقلب الصور تدعى <code>transform</code> يمكنك استخدامها بكل سهولة عبر كلمة مفتاحية واحدة دون أن تحتاج لكتابة تعليمات معقدة وتعلم مبادئ خاصة للرسم على الشاشة حتى تنجز الموضوع، وهنا تكمن قوة استخدام أطر العمل فكل ما عليك فعله هو استدعاء الدالة المناسبة وترك Pygame تكمل الباقي.
</p>

<p>
	إذًا غايتنا هي أن يدير الكائن وجهه وجسده بما يتوافق مع اتجاه الحركة، في حالتنا صورة الشخصية متجهة أساسًا لليمين هذا يعني أننا سنستخدم دالة قلب الصور ضمن كتلة التعليمات التي تحرك الشخصية لليسار حتى نوحي للمشاهد باستدارته يسارًا.
</p>

<p>
	بناءً على <a href="https://www.pygame.org/docs/ref/transform.html#pygame.transform.flip" rel="external nofollow">توثيقات Paygame</a> تحتاج الدالة <code>pygame.transform.flip</code> إلى ثلاثة وسطاء هم: ماذا ستقلب؟ وهل ستقلبه عموديًا؟ وهل ستقلبه أفقيًا؟ في حالتنا لو أعدت النظر للرسم الذي استخدمناه، ستجد أنه يحتاج للقلب أفقيًا ويقابل ذلك القيمة true، ولا يتطلب القلب عموديًا ما يعني تمرير القيمة false مقابل هذا الوسيط.
</p>

<p>
	حدّث الآن تعليماتك حتى تتضمن التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_29" style=""><span class="pln">        </span><span class="com"># الحركة يسارًا</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
         self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span></pre>

<p>
	لاحظ أن المتغير <code>self.image</code> ما زال يأخذ قيمه من قائمة صور الكائن التي حددناها للبرنامج، ولكنها تُدور أو تقلب في دالة القلب.
</p>

<p>
	انتهت خطواتنا في هذا المقال، سنعرض لك الشكل النهائي للكود كاملًا، باستطاعتك تعلم المزيد وتطوير مهاراتك باستكشاف مزايا التحكم الأخرى من Pygame فقد تكونت لديك فكرة جيدة عن الموضوع، جرب الفأرة أو قبضات التحكم وطور اللعبة وفق ما تريد.
</p>

<h2>
	اللعبة الكاملة
</h2>

<p>
	نعرض لك الشكل النهائي للكود كاملًا ليكون مرجعًا تستند إليه في تجاربك.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2190_31" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">
</span><span class="kwd">from</span><span class="pln"> typing </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">  </span><span class="com"># optimise alpha</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">  </span><span class="com"># set alpha</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> control</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        control player movement
        """</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">+=</span><span class="pln"> x
        self</span><span class="pun">.</span><span class="pln">movey </span><span class="pun">+=</span><span class="pln"> y

    </span><span class="kwd">def</span><span class="pln"> update</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="str">"""
        Update sprite position
        """</span><span class="pln">

        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex
        self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movey

        </span><span class="com"># moving left</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">transform</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">//</span><span class="pln"> ani</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">False</span><span class="pun">)</span><span class="pln">

        </span><span class="com"># moving right</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">movex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="pln">ani</span><span class="pun">:</span><span class="pln">
                self</span><span class="pun">.</span><span class="pln">frame </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="pln">self</span><span class="pun">.</span><span class="pln">frame</span><span class="pun">//</span><span class="pln">ani</span><span class="pun">]</span><span class="pln">


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">
steps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">

</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                    sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
                </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                    main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_UP </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'w'</span><span class="pun">):</span><span class="pln">
                </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'jump'</span><span class="pun">)</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYUP</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_LEFT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">K_RIGHT </span><span class="kwd">or</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">):</span><span class="pln">
                player</span><span class="pun">.</span><span class="pln">control</span><span class="pun">(-</span><span class="pln">steps</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player</span><span class="pun">.</span><span class="pln">update</span><span class="pun">()</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	تابع المقال التالي لتتعلم إضافة أعداء إلى اللعبة ومحاكاة أثر الجاذبية في الحركة العمودية، ولا تنسَ تطوير مهاراتك في <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> وهو الغرض من بناء هذه اللعبة.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/17/12/game-python-moving-player" rel="external nofollow">Using Pygame to move your game character around</a> لصاحبه Seth Kenlon.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/" rel="">إضافة لاعب إلى لعبة مطورة باستخدام بايثون ومكتبة Pygame</a>
	</li>
	<li>
		تعرف على أشهر <a href="https://academy.hsoub.com/programming/game-development/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8/" rel="">لغات برمجة الألعاب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">ناء لعبة رسومية باستخدام بايثون ووحدة الألعاب Pygame</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D8%AD%D8%AC%D8%B1%D8%A9-%D9%88%D8%B1%D9%82%D8%A9-%D9%85%D9%82%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1701/" rel="">برمجة لعبة حجرة ورقة مقص باستخدام لغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1706</guid><pubDate>Fri, 23 Sep 2022 16:03:00 +0000</pubDate></item><item><title>&#x625;&#x636;&#x627;&#x641;&#x629; &#x644;&#x627;&#x639;&#x628; &#x625;&#x644;&#x649; &#x644;&#x639;&#x628;&#x629; &#x645;&#x637;&#x648;&#x631;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x648;&#x645;&#x643;&#x62A;&#x628;&#x629; Pygame</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D9%84%D8%A7%D8%B9%D8%A8-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-r1705/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_09/631c2398af090_---------Pygame.png.707c366b01d1922070eb9120c00945d0.png" /></p>
<p>
	في مقال <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a> استخدمنا <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> لبرمجة لعبة نرد بسيطة معتمدة على النص، وفي <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">مقالنا السابق</a> تعلمنا كيفية تجهيز بيئة لعبة رسومية من الصفر أيضًا بلغة بايثون، والآن سنطوّر هذه اللعبة ونضيف إليها شخصية تلعب دور اللاعب أو بطل اللعبة.
</p>

<p>
	يمكنك مطالعة المقال ضمن السلسلة:
</p>

<ol>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame</a>.
	</li>
	<li>
		إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية اللعبة باستخدام PyGame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D8%AF%D9%88-%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-pygame-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1707/" rel="">إضافة شخصية العدو للعبة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-pygame-r1730/" rel="">إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%A7%D9%83%D8%A7%D8%A9-%D8%A3%D8%AB%D8%B1-%D8%A7%D9%84%D8%AC%D8%A7%D8%B0%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1731/" rel="">محاكاة أثر الجاذبية في لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%82%D9%81%D8%B2-%D9%88%D8%A7%D9%84%D8%B1%D9%83%D8%B6-%D8%A5%D9%84%D9%89-%D9%84%D8%B9%D8%A8%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1732/" rel="">إضافة خاصية القفز والركض إلى لعبة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1733/" rel="">إضافة الجوائز إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%B4%D8%A7%D8%B4%D8%A9-r1734/" rel="">تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة</a>.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A2%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D8%B0%D9%81-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%84%D8%B9%D8%A8%D8%A9-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D8%B1%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1735/" rel="">إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون</a>.
	</li>
</ol>

<p>
	يُطلق اسم الكائن أو الشخصية sprite على الأفاتار أو أيقونة الشخصية التي يتحكم بها اللاعب في Pygame، إن كنت لم تجهز له صورةً بعد، فيمكنك تنزيل الصور walk.png ذوات الأرقام 0 و2 و4 و5 من موقع <a href="https://github.com/SuperTux/supertux/tree/master/data/images/creatures/tux/small" rel="external nofollow">SuperTux</a> الخاصة بلعبة <a href="https://www.supertux.org/" rel="external nofollow">Supertux</a> وهي <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D8%A7%D9%84%D9%85%D9%82%D8%B5%D9%88%D8%AF-%D8%A8%D9%85%D8%B5%D8%B7%D9%84%D8%AD-%D9%85%D9%81%D8%AA%D9%88%D8%AD-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-open-source%D8%9F-r885/" rel="">مفتوحة المصدر</a> أو من <a data-fileid="107679" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=107679" rel="" data-fileext="zip">الملفات المرفقة</a>، ومن ثم إعادة تسميتها لتصبح hero1.png إلى hero4.png، أو استخدام <a href="https://academy.hsoub.com/design/graphic/krita/" rel="">كريتا</a> أو <a href="https://academy.hsoub.com/design/illustration/inkscape/" rel="">إنكسكيب</a> لتصميم صور مناسبة، أو الاستعانة بمنصة <a href="https://opengameart.org/" rel="external nofollow">OpenGameArt</a> مفتوحة المصدر لخياراتٍ أخرى، واحفظ كافة الصور التي ستعتمدها في المجلد images الموجود ضمن مجلد مشروعك، وإن لم يكن موجودًا أنشئ واحدًا.
</p>

<p>
	لتجعل لعبتك مثيرة وحقيقية استخدم كائنًا متحركًا، وتحتاج لذلك عدة رسومات للكائن في وضعيات مختلفة لتعطي وهم الحركة، أشهر الحركات المتعارف عليها في الرسوم المتحركة هي دورة المشي وتتطلب أربع صور لتحقق المطلوب.
</p>

<p style="text-align: center;">
	<img alt="img-01-walk-cycle-poses.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="107683" data-unique="z4aqzic8r" style="width: 550px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/img-01-walk-cycle-poses.jpg.31efdae838d76845ef13158ab00e0f4f.jpg">
</p>

<p>
	<strong>تنويه</strong>: كود اللعبة المستخدم هنا يصلح للكائنات الثابتة والمتحركة.
</p>

<p>
	سمي صورة كائن اللعبة بالاسم hero.png وإن رغبت بجعله متحركًا فسمي الصور الخاصة بدورة المشي بأرقامٍ متتابعة بدءً من hero1.png، واحفظها جميعًا في المجلد images الموجود ضمن مجلد مشروعك.
</p>

<h2>
	إنشاء صنف بايثون
</h2>

<p>
	يتطلب إظهار كائن بايثون Object على الشاشة إنشاء <a href="https://wiki.hsoub.com/Python/class_definition" rel="external">صنف class</a>.
</p>

<p>
	إن كنت تستخدم كائنًا ثابتًا ليمثل شخصية بطل اللعبة، فاكتب التعليمات التالية في المقطع الخاص بكائنات بايثون في ملفك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_15" style=""><span class="str">'''
Objects
'''</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">

        img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span></pre>

<p>
	ستُنشئ هذه التعليمات كائن بايثون افتراضي object يشير إلى بطل لعبتك، والكائنات في لغات البرمجة الكائنية تُشتق دومًا من الأصناف.
</p>

<p>
	توفر Pygame قوالب جاهزة للكائنات مثل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_19" style=""><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pln"> </span></pre>

<p>
	وهو ما يتيح لك اختيار الصورة التي تريدها لتمثل بطل لعبتك، وبدون هذه القوالب كنت ستحتاج لمعرفة ممتازة <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بلغة بايثون</a> لتبرمج الكائن من الصفر، وهذه ميزة استخدام مكتبة جاهزة مثل Pygame.
</p>

<p>
	أما في حال أردت استخدام دورة المشي لإنشاء شخصية متحركة، فاحفظ صور وضعيات المشي الأربع لبطل اللعبة بأربع صور منفصلة سمّها hero1.png إلى hero4.png ضمن مجلد الصور ومن ثم استخدم حلقة التكرار لينتقل بايثون من صورة إلى أخرى، في الواقع أن يكون لكل صنف مهمة محددة لا تؤثر "بعالم اللعبة" هو واحد من أفضل ميزات البرمجة الكائنية، ففي حالتنا سيعطي الانتقال بين وضعيات المشي وهم الحركة للمشاهد، وسيحدث ذلك بغض النظر أن كل ما يجري في المحيط.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_22" style=""><span class="str">'''
Objects
'''</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span></pre>

<h2>
	إحضار شخصية اللاعب إلى عالم اللعبة
</h2>

<p>
	بعد أن جهزنا الصنف الذي يشير إلى بطل اللعبة، يتعين علينا استدعائه ضمن اللعبة ليظهر في عالمها، فلو حاولت تشغيل لعبتك الآن ستجدها فارغة كما كانت عليه في نهاية مقالنا السابق، فالكائن الذي يشير لبطل اللعبة لم يرتبط بها بعد ولم يُضاف إلى مجموعة كائنات Pygame.
</p>

<p>
	لتنجز ذلك اكتب التعليمات التالية في مقطع الإعدادات ضمن برنامجك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_24" style=""><span class="pln">player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">   </span><span class="com"># إنتاج اللاعب</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">   </span><span class="com"># X توجه إلى </span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">   </span><span class="com"># Y توجه إلى</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span></pre>

<p>
	حاول الآن تشغيل اللعبة، لن تجد أي فرق، إذ إنك لن تلحظ بطل اللعبة فقد ظهر لأجزاء من الثانية فقط واختفى، تذكر ما شرحناه في مقالنا السابق لجهة أن إتاحة أي شيء باستمرار على الشاشة يستلزم إضافته إلى حلقة اللعبة الرئيسية، وبذلك سيرسمه بايثون مع كل تكرار للحلقة.
</p>

<p>
	أضف إذًا التعليمات التالية للحلقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_26" style=""><span class="pln">    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln"> </span><span class="com"># draw player</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	ومن ثم شغل اللعبة، ستجد شخصية اللاعب فيها.
</p>

<h2>
	ضبط قناة الشفافية ألفا لشخصية اللعبة
</h2>

<p>
	اعتمادًا على الطريقة التي أنشأت بها كائن اللعبة ستظهر حوله مساحة ملونة تحيط به تسمى في الألعاب الحديثة صندوق التصادم hit box، هذه المساحة تشغلها القناة ألفا ويفترض أن تكون غير مرئية، لكن بايثون لا يملك التوجيهات الخاصة بذلك بعد.
</p>

<p style="text-align: center;">
	<img alt="img-02-greenscreen.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="107680" data-unique="iplf2zd27" style="" src="https://academy.hsoub.com/uploads/monthly_2022_09/img-02-greenscreen.jpg.5c450c3d909ac48bc60d04cd604db5e7.jpg">
</p>

<p>
	يمكنك إخبار بايثون باللون الذي تعدّه غير مرئي عبر ضبط إعدادات القناة ألفا باستخدام قيم <a href="https://academy.hsoub.com/design/graphic/%d9%85%d8%a7-%d9%87%d9%88-%d8%a7%d9%84%d9%86%d9%91%d8%b8%d8%a7%d9%85-%d8%a7%d9%84%d9%84%d9%88%d9%86%d9%8a-color-model-r11/" rel="">النظام اللوني RGB</a>، إذا كنت لا تعرف قيمة RGB التي يستخدمها رسمك للقناة ألفا فافتح الشخصية باستخدام أحد البرامج الاختصاصية مثل بينتا أو إنكسكيب واملأ المساحة الفارغة حوله بلونٍ مميز مثل <code>‎#00ff00</code> الذي يكافئ اللون الأخضر "للشاشة الخضراء" ثم سجل هذه القيمة المكتوبة بالترميز الست عشري واكتبها في كود بايثون لتشكل قيمة القناة ألفا.
</p>

<p>
	أضف الآن السطرين التاليين إلى التعليمات الخاصة بإنشاء كائن اللعبة حتى تضبط القناة ألفا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_29" style=""><span class="pln">    img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">     </span><span class="com"># تحسين ألفا</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln"> </span><span class="com"># تحديد قيمة ألفا</span></pre>

<p>
	إذا كنت تعتقد أن الصورة التي تعتمدها تملك بالفعل قيمة لقناة ألفا فاضبط المتغير <code>ALPHA</code> على القيمة 0 أو 255 فكلاهما من القيم الشائعة، ولكن لخبرتي مجال المونتاج -يقول كاتب المقال- أفضل إنشاء قناة ألفا وضبطها بنفسي لتكون قيمتها أكيدة دون لبس.
</p>

<p>
	أضف المتغير التالي في المقطع الخاص بالمتغيرات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_31" style=""><span class="pln">ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span></pre>

<p>
	تكافئ القيمة 0,255,0 في نظام RGB اللون الأخضر، ويمكنك على الحصول قيم كافة الألوان باستخدام برنامج رسومات جيد مثل <a href="https://academy.hsoub.com/design/graphic/gimp/" rel="">جيمب</a> أو <a href="https://academy.hsoub.com/design/graphic/krita/" rel="">كريتا</a> أو <a href="https://academy.hsoub.com/design/illustration/inkscape/" rel="">إنكسكيب</a>، أو الاستعانة بأحد نظم اختيار الألوان الشهيرة مفتوحة المصدر مثل <a href="https://github.com/KDE/kcolorchooser" rel="external nofollow">KColorChooser</a> أو <a href="https://github.com/stuartlangridge/ColourPicker" rel="external nofollow">ColourPicker</a>.
</p>

<p style="text-align: center;">
	<img alt="img-04-kcolor.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="107682" data-unique="sw38b165s" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_09/img-04-kcolor.jpg.3b37cd661fa029de502ab6ababaf886a.jpg">
</p>

<p>
	إذا كانت الصور التي تعتمدها تملك قيمة مغايرة للقناة ألفا فاختر للمتغير قيمة مناسبة وفق ما يستلزم الأمر، ودائمًا القيم التي تضعها لألفا ستصبح غير مرئية أيًا كانت، ففي حال وضعت قيمة ألفا 000 مثلًا (وهي تعني اللون الأسود) فاجعل عندها خطوط رسمك التي تكون سوداء بالعادة باللون 111 وهو أقرب ما يمكن للأسود ولن يلاحظ المستخدم الفرق.
</p>

<p>
	شغل لعبتك الآن ولاحظ النتائج.
</p>

<p style="text-align: center;">
	<img alt="img-05-alpha.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="107681" data-unique="nms0kv2da" style="" src="https://academy.hsoub.com/uploads/monthly_2022_09/img-05-alpha.jpg.e765f6b9ce3f180db38d1cea54b1ddb0.jpg">
</p>

<p>
	أما الشكل النهائي للكود بعد كل هذه التعديلات سيكون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7916_36" style=""><span class="com">#!/usr/bin/env python3</span><span class="pln">
</span><span class="com"># by Seth Kenlon</span><span class="pln">

</span><span class="com"># GPLv3</span><span class="pln">
</span><span class="com"># This program is free software: you can redistribute it and/or</span><span class="pln">
</span><span class="com"># modify it under the terms of the GNU General Public License as</span><span class="pln">
</span><span class="com"># published by the Free Software Foundation, either version 3 of the</span><span class="pln">
</span><span class="com"># License, or (at your option) any later version.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># This program is distributed in the hope that it will be useful, but</span><span class="pln">
</span><span class="com"># WITHOUT ANY WARRANTY; without even the implied warranty of</span><span class="pln">
</span><span class="com"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span><span class="pln">
</span><span class="com"># General Public License for more details.</span><span class="pln">
</span><span class="com">#</span><span class="pln">
</span><span class="com"># You should have received a copy of the GNU General Public License</span><span class="pln">
</span><span class="com"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span><span class="pln">
</span><span class="kwd">from</span><span class="pln"> typing </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> pygame
</span><span class="kwd">import</span><span class="pln"> sys
</span><span class="kwd">import</span><span class="pln"> os

</span><span class="str">'''
Variables
'''</span><span class="pln">

worldx </span><span class="pun">=</span><span class="pln"> </span><span class="lit">960</span><span class="pln">
worldy </span><span class="pun">=</span><span class="pln"> </span><span class="lit">720</span><span class="pln">
fps </span><span class="pun">=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">  </span><span class="com"># frame rate</span><span class="pln">
ani </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">  </span><span class="com"># animation cycles</span><span class="pln">
world </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">set_mode</span><span class="pun">([</span><span class="pln">worldx</span><span class="pun">,</span><span class="pln"> worldy</span><span class="pun">])</span><span class="pln">

BLUE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln">
BLACK </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
WHITE </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">,</span><span class="pln"> </span><span class="lit">254</span><span class="pun">)</span><span class="pln">
ALPHA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="str">'''
Objects
'''</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">(</span><span class="pln">pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">):</span><span class="pln">
    </span><span class="str">"""
    Spawn a player
    """</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Sprite</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">images </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">):</span><span class="pln">
            img </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'hero'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.png'</span><span class="pun">)).</span><span class="pln">convert</span><span class="pun">()</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">convert_alpha</span><span class="pun">()</span><span class="pln">  </span><span class="com"># optimise alpha</span><span class="pln">
            img</span><span class="pun">.</span><span class="pln">set_colorkey</span><span class="pun">(</span><span class="pln">ALPHA</span><span class="pun">)</span><span class="pln">  </span><span class="com"># set alpha</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">img</span><span class="pun">)</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">image </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">images</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">rect </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">


</span><span class="str">'''
Setup
'''</span><span class="pln">

backdrop </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">image</span><span class="pun">.</span><span class="pln">load</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">path</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'stage.png'</span><span class="pun">))</span><span class="pln">
clock </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">time</span><span class="pun">.</span><span class="typ">Clock</span><span class="pun">()</span><span class="pln">
pygame</span><span class="pun">.</span><span class="pln">init</span><span class="pun">()</span><span class="pln">
backdropbox </span><span class="pun">=</span><span class="pln"> world</span><span class="pun">.</span><span class="pln">get_rect</span><span class="pun">()</span><span class="pln">
main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">

player </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Player</span><span class="pun">()</span><span class="pln">  </span><span class="com"># spawn player</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to x</span><span class="pln">
player</span><span class="pun">.</span><span class="pln">rect</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># go to y</span><span class="pln">
player_list </span><span class="pun">=</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">sprite</span><span class="pun">.</span><span class="typ">Group</span><span class="pun">()</span><span class="pln">
player_list</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="pln">player</span><span class="pun">)</span><span class="pln">


</span><span class="str">'''
Main Loop
'''</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> main</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> event </span><span class="kwd">in</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">event</span><span class="pun">.</span><span class="pln">get</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">QUIT</span><span class="pun">:</span><span class="pln">
            pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> pygame</span><span class="pun">.</span><span class="pln">KEYDOWN</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">key </span><span class="pun">==</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">):</span><span class="pln">
                pygame</span><span class="pun">.</span><span class="pln">quit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">finally</span><span class="pun">:</span><span class="pln">
                main </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
    world</span><span class="pun">.</span><span class="pln">blit</span><span class="pun">(</span><span class="pln">backdrop</span><span class="pun">,</span><span class="pln"> backdropbox</span><span class="pun">)</span><span class="pln">
    player_list</span><span class="pun">.</span><span class="pln">draw</span><span class="pun">(</span><span class="pln">world</span><span class="pun">)</span><span class="pln">
    pygame</span><span class="pun">.</span><span class="pln">display</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">()</span><span class="pln">
    clock</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">(</span><span class="pln">fps</span><span class="pun">)</span></pre>

<p>
	تابع معنا المقال التالي لتضيف بعض الإثارة وتتعلم كيفية تحريك الكائن.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/article/17/12/game-python-add-a-player" rel="external nofollow">How to add a player to your Python game</a> لصاحبه Seth Kenlon.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%B4%D8%AE%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%B9%D8%A8%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-pygame-r1706/" rel="">تحريك شخصية في لعبة باستخدام Pygame</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%88%D8%AD%D8%AF%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-pygame-r1704/" rel="">بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب Pygame</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%84%D8%B9%D8%A8%D8%A9-%D8%AD%D8%AC%D8%B1%D8%A9-%D9%88%D8%B1%D9%82%D8%A9-%D9%85%D9%82%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1701/" rel="">برمجة لعبة حجرة ورقة مقص باستخدام لغة بايثون </a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">البرمجة بلغة بايثون</a>
	</li>
	<li>
		تعرف على أشهر <a href="https://academy.hsoub.com/programming/game-development/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8/" rel="">لغات برمجة الألعاب</a><br>
		 
	</li>
</ul>
]]></description><guid isPermaLink="false">1705</guid><pubDate>Sun, 18 Sep 2022 16:02:00 +0000</pubDate></item></channel></rss>
