اذهب إلى المحتوى

بعد أن تعرّفنا في مقالتنا السابقة على لغة برمجة بروسيسنج وبيئة التطوير الخاصة بها وهيكلة البرنامج، سنتابع في الجزء الثاني التعرف على أبرز توابع الرسم الموجودة فيها وكيفية استخدامها، بالإضافة للتفاعل مع دخل المستخدم.

رسم الأشكال والنصوص

إحداثيات الرسم

الآن سنتحدث عن بعض الأمور البصرية بما أننا أصبحنا نعرف كيفية ضبط المشروع باستخدام كتلة التهيئة ونعرف كيفية عمل رسم كتلة الرسم، كما سنتعلم الأمور المسلية في بروسيسنج processing مثل كيفية رسم الأشكال.

قبل البدء يجب أن نفهم محاور الإحداثيات، إذ يجب تحديد إحداثيات كل شكل يتم رسمه على الشاشة في بروسيسنج processing. الواحدات مقدرة بالبيكسل والمبدأ (نقطة البداية) هي الزاوية اليسرى العلوية، يجب أن تحدد الإحداثيات بالنسبة لهذه النقطة. شيء آخر يجب أن تعرفه هو أن لكل شكل نقطة مرجعية مختلفة، مثلًا النقطة المرجعية للدالة react() هي الزاوية اليسرى العلوية، أما بالنسبة لدالة ellipse()‎ فهي المركز. ويمكنك تغيير النقطة المرجعية باستخدام التوابع مثل rectMode()‎ و ellipseMode()‎ التي سنشرحها في قسم الخصائص والإعدادات.

سنقتصر على توفير رؤية عامة أساسية للغة بروسيسنج ولن نتطرق لأي أشكال معقدة مثل الأشعة والأشكال ثلاثية البعد، فالأشكال ثنائية البعد تكفي لإنشاء لعبتنا، رأينا في الصورة أمثلة عن كيفية رسم الأشكال، كل شكل لديه صياغة خاصة به ليُنشئ، والفكرة الأساسية هي إما تحديد أبعاده أو حجمه أو كلاهما، التالي هو بعض الأمثلة التي يجب أن تتعلمها (تعني القيم x و y الإحداثيات مقدرة بالبيكسل لكل من المحاور الإحداثية x و y، وتعني القيم h و w العرض والطول مقدرة بالبيكسل أيضًا).

  • الدالة point(): تستخدم لرسم نقطة بسيطة تحتاج قيمة إحداثيات واحدة، وتستخدم كما يلي:
point(x, y)

point(x, y, z) // في حالة الأبعاد الثلاثية
  • الدالة line() - لإنشاء سطر، يمكنك إنشاء سطر بتحديد نقطة البداية والنهاية، وتستخدم كما يلي:

 

line(x1, y1, x2, y2)
line(x1, y1, z1, x2, y2, z2) // في حالة الأبعاد الثلاثية
  • الدالة triangle()‎ - لإنشاء المثلثات، وتستخدم كما يلي:
triangle(x1, y1, x2, y2 ,x3 ,y3)‎
  • الدالة quad()‎ - لإنشاء المضلعات الرباعية، وتستخدم كما يلي:
quad(x1, y1, x2, y2 ,x3, y3, x4 ,y4)‎
  • الدالة rect()‎: تستخدم لرسم المربعات والأشكال المستطيلة. وتقع النقطة المرجعية في في الزاوية اليسارية العليا (راجع الصورة السابقة)، تستخدم الدالة كما يلي:
rect(x, y, w, h)

rect(x, y, w, h, r) // تعني‫ r نصف القطر مقدرًا بالبيكسل لجعل زوايا المربع مدورة

rect(x, y, w, h, tl, tr, br, bl) // أنصاف الأقطار للزاويتين العلوية اليسرى واليمنى والسفلية اليمنى واليسرى على الترتيب مقدرة بالبيكسل
  • الدالة ellipse()‎: تستخدم لرسم قطع ناقص ومن أجل رسم الدوائر إذ يجب تحديد قيم متساوية للعرض والارتفاع، إن النقطة المرجعية هي افتراضيًا في المنتصف. وتستخدم كما يلي:
ellipse(x, y, w, h)
  • الدالة arc()‎: ترسم قوس، وتستخدم كما يلي:
arc(x, y, w, h, start, stop) 

تشير المتغيرات‫ start و stop في هذه الحالة إلى زاوية بداية ونهاية رسم القوس مقدرة بالراديان، ‫ويمكن استخدام القيم التالية PI و HALF_PI و HALF_PI و TWO_PI لحساب الأقواي والمسارات الدائرية بسهولة أكبر.

كما تستخدم أيضًا على النحو التالي:

arc(x, y, w, h, start, stop, mode) 

يحدد المتغير‫ mode ‏هنا طريقة تصيير أو رسم القوس وتمرر قيمته كسلسلة نصية وتكون الخيارت المتاحة لقيم ذلك المتغير ‫هي "OPEN" لرسم القوس فقط دون إغلاق الأطراف، و "PIE" لرسم قوس ووصل طرفيه بالمركز حيث نحصل على ما يشبه قطعة من فطيرة و "CHROD" لرسم القوس مع وصل طرفيه بخط مستقيم.

arc_mode.png

إن إظهار النصوص على الشاشة يشابه إظهار الأشكال عن طريق تحديد إحداثيات مكان إظهار النص

  • الدالة text()‎ تظهر النصوص، وتستخدم كما يلي:
text(c, x, y) // يشير المعامل‫ c إلى المحرف، ويتم إظهار أي محرف أبجدي
text(c, x, y, z) // في حال العمل في الأبعاد الثلاثة
text(str, x, y) // ‫تعني str السلسلة النصية المراد إظهارها
text(str, x, y, z) // في حال العمل في الأبعاد الثلاثة
text(num, x, y) // تعني‫ num القيمة الرقمية المراد إظهارها
text(num, x, y, z) // في حال العمل في الأبعاد الثلاثة

الإعدادات والخصائص

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

تذكر عند ضبط الخاصية أن الشيفرة تُنفّذ من الأعلى إلى الأسفل، لنقل أنك تريد ضبط خاصية التعبئة اللونية "fill" باللون الأحمر، وبالتالي كل الكائنات التي ستُرسم بعدها ستكون تعبئتها حمراء حتى نعيد تعريف الخاصية، والأمر نفسه ينطبق أيضًا على باقي الخصائص. لكن الجدير بالملاحظة هنا أن بعض الخصائص لا تستبدل بعضها البعض. على سبيل المثال، خاصية لا تستبدل خاصية لون الحد stroke قيمة خاصية التعبئة fill لأنهما يعملان مع بعضهما. يسهل الشكل التالي فهم منطق عمل الخاصيات       . لاحظ كيف تؤثر أوامر fill و stroke على جميع الأشكال المرسومة بعدها حتى تقوم بتغييرها أو إلغائها.

code_execution.JPG

كما رأيت في الشكل أعلاه يضبط السطر الأول لون التعبئة للأحمر، ويضبط السطر الثاني لون خط الحدود للأزرق، وبالتالي لدينا خاصتان فعالتان هنا وهما التعبئة باللون الأحمر ولون خط الحدود بالأزرق، وبالتالي سيكون كل كائن يرسم في الأسطر التالية من الكود بلون تعبئة حمراء وخط حد أزرق (إذا كان ذلك ممكنًا فبعض الأشكال قد لا تحتوي على حدود)، تمعّن بالشكل لتفهم المنطق بشكل أوضح.

فيما يلي نشرح بعض الخصائص والإعدادات المتداولة في التصميم.

إعدادات التصميم

  • الدالة fill():  تضبط نوع اللون لتعبئة الكائنات، تستخدم هذه الدالة لتلوين النصوص، ويكفي مبدئيًا تعلم الاستخدامات التالية:
fill(r, g, b) // قيم الأحمر والأخضر والأزرق كأعداد صحيحة
fill(r, g, b, a) // ‫قيمة alpha إضافية، قيمتها العظمى هي 225
  • الدالة noFill()‎: تستخدم لضبط لون التعبئة ليكون شفاف
  • الدالة stroke()‎: تستخدم لضبط نوع لون خط الحدود للكائنات، يمكن تطبيق خاصية الحد للخطوط والحدود حول الكائنات، ويكفي مبدئيًا تعلم الاستخدامات التالية:
stroke(r, g, b) // قيم الأحمر والأخضر والأزرق كأعداد صحيحة
stroke(r, g, b, a) // ‫قيمة alpha إضافية، قيمتها العظمى هي 225 
  • الدالة noStrok(): تًزيل الحد
  • الدالة strokeWeight()‎ تضبط سماكة خط الحد، وفيما يلي مثال على طريقة الاستخدام:
strokeWeight(x) // ‫إن قيمة x هو عدد صحيح يمثل عرض الخط مقدرة بالبيكسل
  • الدالة background()‎: تضبط لون الخلفية، ويكفي مبدئيًا تعلم الاستخدامات التالية:
background(r, g, b) // تمرر قيم الأحمر والأخضر والأزرق كأعداد صحيحة.
background(r, g, b, a) // ‫قيمة alpha إضافية، وقيمتها العظمى هي 225

إعدادات المحاذاة

  • الدالة ellipseMode()‎: تستسخدم لضبط موضع النقطة المرجعية للقطع الناقص، وهذا مثال عن طريقة الاستخدام:
ellipseMode(mode) 

يملك المعامل‫ mode القيم الممكنة التالية التي تتحكم في كيفية رسم القطع الناقص:

  • CENTER(default) يحدد المركز كنقطة المرجعية وتكون قيم   w و h هي عرض وارتفاع القطع الناقص ككل.
  • RADIUS ‫تأخذ المركز كالنقطة المرجعية، ولكن في هذا النمط تكون قيم w و h المحددة هي نصف العرض ونصف الارتفاع (كما في حالة نصف قطر الدائرة بدل القطر بالكامل)
  • CORNER تحدد الزاوية اليسرى العلوية كنقطة مرجعية، وتكون قيم w و h هما قيمتي العرض والارتفاع.
  • CORNERS تحدد المعاملين الأول والثاني (x و y) كموقع الزاوية اليسرى العلوية، والمعاملين الثالث والرابع (w و h) كموقع الزاوية اليسرى السفلية للقطع الناقص، لذا في هذا النمط قيم العرض و الطول غير مهمتان، ولفهم أفضل يمكن اعتبار الدالة بالشكل التالي ellipse(x_tl,y_tl,x_br,y_br)‎ لتكون أكثر منطقية.
  • الدالة rectMode()‎: تحدد مكان النقطة المرجعية لمحاذاة المستطيلات، وفيما يلي طريقة الاستخدام:
rectMode(mode) 

يملك المعامل mode لديه المعاملات التالية :

  • CENTER يحدد المركز كنقطة المرجعية للمستطيل وتكون قيم w و h المحددة هي عرض وارتفاع المستطيل.
  • RADIUS تأخذ المركز كالنقطة المرجعية، ولكن في هذا النمط تكون قيم w و h المحددة هي نصف العرض ونصف الارتفاع.
  • CORNER تحدد الزاوية اليسرى العلوية كنقطة مرجعية وقيم w و h المحددة هي عرض وارتفاع المستطيل هذه هي القيمة الافتراضية للمتغير.
  • CORNERS تحدد المعاملين الأول والثاني (x و y) كموقع الزاوية اليسرى العلوية، والمعاملين الثالث والرابع (w و h) كموقع الزاوية اليسرى السفلية للمستطيل، لذا في هذا النمط تكون قيم العرض و الطول غير مهمين، ولفهم أفضل يمكن اعتبار الدالة بالشكل التالي rect(x_tl,y_tl,x_br,y_br)‎ لتكون أكثر منطقية.

إعدادات متعلقة بالنص

  • الدالة textSize()‎: تحدد حجم الخط، وطريقة الاستخدام كالتالي:
testSize(size) قيمة حجم الخط كعدد صحيح دالة 
  • الدالة textLeading()‎:  تحدد ارتفاع الخط للنصوص، الاستخدام:
  • الدالة textLeading(lineheight): تحدد قيمة الفراغ بين الأسطر مقدر بالبيكسل
  • الدالة textAlign()‎: تحدد أين هي النقطة المرجعية لمحاذاة النصوص، وهذا مثال على طريقة الاستخدام:
    textAlign(alignX)// تستخدم alignX للمحاذاة الأفقية وتأخذ القيم LEFT,CENTER,RIGHT
    textAlign(alignX,alignY) //تستخدم alignY للمحاذاة الشاقولية وتأخذ القيم TOP,BOTTOM,CENTER,BASELINE

التحريك

تعلمنا حتى الآن كيفية رسم الكائنات والنصوص، ولكنها كلها كائنات ثابتة لا تتحرك؛ سنتعلم الآن تحريكها عن طريق إعطاء الإحداثيات قيم متغيرة بدلًا من أعداد صحيحة ثابتة ويمكننا زيادتها أو إنقاصها، لاحظ الشيفرة التالية

// تهيئة‫ x و y إلى القيمة 0
int x=0;
int y=0;

void setup(){
  size(800,600);
  background(255); // ضبط لون الخلفية للون الأبيض
}

void draw(){
  fill(255,0,0); // لون التعبئة أحمر
  stroke(0,0,255); // لون خط الحد هو الأزرق
  ellipseMode(CENTER); // نقطة المرجع هي المركز

  ellipse(x, y, 20, 20); // رسم القطع الناقص

  // زيادة‫ x و y
  x+=5;
  y+=5;
}

هل تستطيع معرفة كيفية إدارة عملية التحريك؟ لقد ضبطنا قيم x و y كمتغيرات عامة بقيم أولية 0، وأنشأنا في حلقة الرسم القطع الناقص، ثم ضبطنا لون التعبئة للأحمر، ولون خط الحد للأزرق وضبطنا قيم الإحداثيات x و y، إذ تغير الكرة مكانها عندما نزيد قيمتي x و y ولكن هناك مشكلة في الشيفرة هل تستطيع معرفتها كاختبار لك؟ حاول تجربتها:

التحريك

الهدف هنا أن تعرف كيفية عمل الحلقات في لغة بروسيسنج، تذكر المثال الذي أوردناه في قسم كتلة الرسم في المقال السابق ولماذا حصلنا على "111…" بدلًا من "1234.." إنه السبب ذاته الذي جعل الكرة تترك أثرًا، حيث في كل مرة تكرّر الكرة تزداد قيمة x و y بقيمة 5 وتُرسم الكرة نحو اليمين والأسفل بمقدار 5 بيكسل، ولكن تبقى الكرة المرسومة من التكرار السابق، كيف نستطيع إزالتها؟

لإزالة أثر الكرة نزيل ببساطة background(255)‎ من كتلة التهيئة ونضعها في أول سطر من كتلة الرسم، فعندما كانت شيفرة الخلفية في كتلة التهيئة نُفذت الشيفرة مرة واحدة في البداية لجعل الخلفية بيضاء، ولكن ذلك لا يكفي يجب إعادة ضبط الخلفية للأبيض في كل حلقة لتغطية الكرات المرسومة من الحلقات السابقة. بما أن الخلفية هي السطر الأول فهذا يعني تنفيذه أولًا وتصبح الطبقة الأساسية، وتصبح الخلفية بيضاء في كل حلقة وتُرسم العناصر عليها لذا لا يبقى أي أثر.

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

التفاعل مع الفأرة ولوحة المفاتيح

إن التفاعل مع الفأرة ولوحة المفاتيح أمر سهل في لغة بروسيسنج، إذ توجد توابع تُستدعى لكل حدث وما يُنفّذ كل ما يتم كتابته داخلها عند حصول الحدث، و هناك أيضًا متغيرات عامة مثلmousePressed و keyPressed يمكن استخدامها في كتلة الرسم للاستفادة من الحلقة، التالي هي بعض التوابع مع شرحها

void setup() {
  size(500, 500);
}

void draw() {

  if (mousePressed) {
    // تُنفَّذ الشيفرات هنا طالما زر
    // الفأرة مضغوط

    if (mouseButton == LEFT){
      // تُنفَّذ الأسطر طالما
      // زر الفأرة المنقور هو زر الفأرة
      // اليسار
    }
  }

  if (keyPressed) {
    // تُنفَّذ الشيفرات هنا طالما هناك مفتاح
    // مضغوط على لوحة المفاتيح

    if (key == CODED) {
      // ‫تتحقق هذه تعليمة if هذه إذا كان المفتاح
      // مُتَعرف عليه من لغة بروسيسنج

      if (keyCode == ENTER) {
        // تُنفَّذ الأسطر إذا كان المفتاح
        // هو مفتاح‫ enter
      }
    }
    else{
      // تُنفَّذ هذه الأسطر إذا لم يتم التعرف
      // على السطر من لغة بروسيسنج
    }
  }

}

void mousePressed() {
  // تنفذ هذه الشيفرات مرة عندما تنقر الفأرة 
  // ‫لاحظ أن المتغير mouseButton
  // مستخدم هنا
}

void keyPressed() {
  // تنفذ هذه الشيفرات مرة عندما يضغط المفتاح
  // ‫لاحظ أن المتغيرات key و keyCode
  // مستخدمة هنا
}

كما ترى من السهل التحقق إذا ما كانت الفأرة قد تم نقرها أو هناك زر تم الضغط عليه، ولكن هناك خيارات أكثر للمتغيرات mousePressed و keyCode، إن الخيارات المتاحة للمتغير mousePressed هي LEFT و RIGHT و CENTER، وهناك العديد من الخيارات المتاحة للمتغير keyCode مثل (UP و DOWN و LEFT و RIGHT و ALT و CONTROL و SHIFT و DELETE ...إلخ.)

هناك أمر وحيد يجب معرفته في متغيرات الفأرة وهو كيفية الحصول على إحداثيات مؤشر الفأرة، وهو أمر سنستخدمه كثيرًا، فللحصول على إحداثيات المؤشر يمكنك استخدام المتغيرين mouseX و mouseY مباشرة في كتلة draw()‎، وأخيرًا وليس آخرًا هناك العديد من الدوال التي يجب أن تتطلع عليها موثقة في مراجع لغة بروسيسنج.

الخاتمة

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

التمرين الأول

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

التمرين الثاني

هل تذكر شاشة توقف DVD المشهورة التي يرتد بها شعار DVD حول الشاشة وننتظر بشوق أن تصطدم في الزاوية؟ أريد منك تكرار شاشة التوقف هذه باستخدام مستطيل بدلًا من شعار DVD، عند تشغيل التطبيق يجب أن تكون الشاشة سوداء وينطلق المستطيل من موقع عشوائي، وفي كل مرة يصطدم بزاوية يجب على المستطيل تغيير لونه (وبالطبع اتجاهه). وعند تحريك الفأرة يجب على المستطيل الاختفاء وأن تصبح الشاشة بيضاء، لن تحصل على الحل في هذه المقالة يجب عليك أن تحاول كل جهدك أن تنفذها وسنقدم الشيفرة في المقال التالي.

ترجمة -بتصرف- لمقال Guide to the Processing Language Part I: Fundamentals لكاتبه Oguz Gelal.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...