• 0
muqawem

التحريك

سؤال

مقدمه

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

ملاحظة قبل المتابعة

هذا الدرس يعتمد بشكل كلي على ال Multi-Threading في جافا لذلك يجب عليك الاحاطه في هذا الموضوع. يمكنك الاطلاع على هذا الدرس الممتاز في منتيدات الفريق العربي.

public class AnimationCanvas extends Canvas implements Runnable {

protected void showNotify() {
Random r = new Random( System.currentTimeMillis() );
x = r.nextInt( getWidth() );
y = r.nextInt( getHeight() );
dirX = 4;
dirY = 4;

}

protected void paint(Graphics g) {
g.setColor( 0x0 );
g.fillRect( 0, 0, getWidth(), getHeight() );

g.setColor( 0xFFFFFF );
g.fillRect( x, y, WIDTH, HEIGHT );

}

public void run() {
while( !quit ) {
x += dirX;
y += dirY;

if( x <= 0 || x + WIDTH >= getWidth() ) {
dirX *= -1;

}

if( y <= 0 || y + HEIGHT >= getHeight() ) {
dirY *= -1;

}
repaint();
serviceRepaints();

try {
Thread.sleep( 50 );

} catch( Exception ex ) {
ex.printStackTrace();

}

}

}

public void start() {
Thread t = new Thread( this );
t.start();

}

public void stop() {
quit = true;

}
private boolean quit = false;
private int x;
private int y;

private int dirX;
private int dirY;
private final int WIDTH = 10;
private final int HEIGHT = 10;
}

في السطور ما بين 3 و 9 قمنا بأخذ قيمه عشوائيه لكل من الاحداثيات السينية والصادية. الاحداثايات السينية محصورة ما بين 0 و عرض شاشه الهاتف أما الاحداثيات الصادية فهي محصورة ما بين 0 و ارتفاع الشاشة. ثم قمنا بتجهيز متجهات الحركة على المحورين بقيم ابتدائية تساوي 4 لكل منهما.

لاحظ أن الفئة تقوم بعمل implementsلل Runnable أي أنها يمكن أن تكون قيمه مرسلة لخيط معين لتنفيذها في ذلك الخيط وهو ما تم عمله فعلا في ال start method ما بين السطور 50 و 54.

في ال run method نقوم بالتحرك خطوه على كل من المحاور ثم نقوم بفحص القيم الجديدة للاحداثايت فاذا تجاوزت أحدها الشاشه نقوم بعكس اتجاه الحركه. هذه ال method عالقه في حلقه تكراريه لا نهائيه لن تنتهي الا بتغيير قيمه المتغير quit الى false.

في كل حلقه نقوم باعاده رسم المربع في المكان الجديد ثم نجبر الخيط على الانتظار لمده 50 milliseconds.

الان نقوم بعرض هذه الشاشة على شاشه الهاتف كالتالي:

public class AnimationMidlet extends MIDlet implements CommandListener {
AnimationCanvas animator;

public void startApp() {
animator = new AnimationCanvas();
animator.start();
Display.getDisplay(this).setCurrent( animator );
animator.addCommand( new Command( "Exit", Command.EXIT, 0 ) );
animator.setCommandListener( this );

}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void commandAction(Command c, Displayable d) {
animator.stop();
destroyApp(true);
notifyDestroyed();
}
}

المثال في المرفقات

الدرس منقول من مدونتي

Animation.zip

تم تعديل بواسطه مهدي حجازي
3

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

28 إجابة على هذا السؤال .

  • 0

جميل جدا

لكن لنفرض انه يوجد عندنا اكثر من كائن لنسميه (Box)

ما هي الطريقة لكشف التصادم ما بين هذين الكائنين(2 Boxes)؟

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

تحتاج إلى جهة عليا يا محمد حتى تقوم بمراقبة الحركة وإصدار الأحداث المختلفة

ما الذي أحتاجعه يا شباب لنقل المحرك الخاص بي (AAnimation)

من العمل على swing إلى العمل على JavaMe

أنا أستخدم Container وأحرك عليه Component

هل يوجد شيء يشبه هذا في JavaMe

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

يمكننا صناعة واحد مثيل لل Container

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

تقصد مثيل للـ Component يا محمد

لأني أظن Canvas هو مثيل Container

هل أنا مصيب؟

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

مممم

صدقا لم اقرأ كود مكتبتك

لن بأمكاننا صنع Custom Component من خلال الكنفاس

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ما هي الحاوية الرئيسية لبرنامج في JavaMe؟

وهل يمكن أن أضع عليها الأزرار الخاصة بي في أي نقطة (أقصد استخدام null Layout)؟

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

:P

لا يوجد

لكن نستطيع رسمها بالكنفاس

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لماذا عندما اعوض dirx and diry بقيمها المعكوسة التي هي -4 -لا يعمل ويكون مختلفا عن عمل الصيغة المكتوبة -4

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لماذا عندما اعوض dirx and diry بقيمها المعكوسة التي هي -4 -لا يعمل ويكون مختلفا عن عمل الصيغة المكتوبة -4

وضح سؤالك اكثر لو سمحت

انا لم افهم سؤالك بصراحة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

جميل جدا

لكن لنفرض انه يوجد عندنا اكثر من كائن لنسميه (Box)

ما هي الطريقة لكشف التصادم ما بين هذين الكائنين(2 Boxes)؟

تحياتي

طبعا ليس هدف الدرس هو اكتشاف التصادم ولكن ان أردت اكتشاف ذلك فعليك استخدام احدى خوارزميات ال collision detection كما أنه يوجد methods جاهزه في ال javax.microedition.lcdui.game.Sprite تدعى collidesWith تساعدك على اكتشاف التصدامات في ألعاب JME ولكن يجب أن يكون الكائن المتحرك هو Sprite بالطبع أو فئه ترث منها.

لماذا عندما اعوض dirx and diry بقيمها المعكوسة التي هي -4 -لا يعمل ويكون مختلفا عن عمل الصيغة المكتوبة -4

عند استخدام قيم سالبه بدل الموجبه يعمل البرنامج بشكل جيد, رجاء وضح المشكله والسؤال..

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الا يمكن اخراج هدا الشكل بدون استخدام الثريد

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الا يمكن اخراج هدا الشكل بدون استخدام الثريد

لا لا يمكن ذلك..لان التحريك يعتمد بالأساس على اعاده الرسم كل فتره معينه وهو ما لا يتم الا باستخدام Thread أو Timer

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

وهل يمكن أن أضع عليها الأزرار الخاصة بي في أي نقطة (أقصد استخدام null Layout)؟

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لا يوجد أصلا Layouts في Java ME ولا حاويات وال Canvas في Java ME لا يعادل ال Container بل هناك Canvas في Java SE يتصرف بطريقه مشابهه لمثيله في Java ME. أظن أن محركك يمكن أن تسفيد منه باستخدام LWUIT وهي اطار عمل شبيه ب Swing لذلك فهي تحتوي على Components, Container, Layouts وهذا ما قصده محمد عندما قال اننا يمكننا صنع واحده شبيه بها

تحياتي

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الأخ LWUIT هل هو مدعوم في كل الجوالات التي تدعم JavaMe?

أعتقد أني سأعمل على نسخة جديدة من AAnimation بحيث تعمل بشكل منفصل عن المكونات

لا أدري متى بالضبط لكني وجدت أن هذا سيكون مفيد (أو ربما أكف عن تطوير الحزمة أصلاً)

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

نعم LWUIT تعمل على جميع هواتف Java ME ما عدا الضعيفه منها..قبل اتخاذ هكذا قرار راجع طريقه ال Animation في LWUIT لأنهم يعتمدون على طريقه معينه ربما تكون انسب لهم من طريقتك وفي النهايه انت تستطيع ان تقرر ما هو الأصح..

بالمناسبه LWUIT في الأساس تعتمد على ال Canvas في Java ME اي جميع هذه المكونات تم بناؤها على شيء موجود قديما في Java ME لذلك هي تعمل على جميه الهواتف دون الحاجه لوجود API خاصه بها..

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

قرأت عن آلية التحريك في LWUIT وهذا ملخص اقتبسته من كتاب اسمه LWUIT_1.1_for_Java_ME_Developers

In order to be capable of being animated, an object has to implement the Animation

interface which has two methods:

1-animate—this is a callback method invoked once for every frame.

2-paint—This method is called if animate returns true. If the object being

animated is a component, then it will have a paint method and that is the

one to be called as the signatures of the two methods are identical.

The Component class implements Animation. This makes every widget

animation-capable. However, in order to actually carry out animation, an object

must also be registered for animation by calling the registerAnimated method

on its parent form. The animate method of a registered object is called once for

every frame of animation as determined by the Display class. Only if animate

returns true, then the paint method of the object is called, and a repaint takes

place. In order to stop animation, the object must be deregistered by calling the

deregisterAnimated method on the parent form.

الموضوع بسيط جداً لكنه مكلف على المعالج

لكني غير مدرك لماذا يقومون بها بهذه الطريقة مع أنهم قادرون على فعل ذات الشيء باستخدام Scheduler بسيط

بالمناسبة هل حزمة collection (بالأخص Priority Queue) موجودة في JavaMe؟

تحياتي

تم تعديل بواسطه علاء الصالحي
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الموضوع بسيط جداً لكنه مكلف على المعالج

لكني غير مدرك لماذا يقومون بها بهذه الطريقة مع أنهم قادرون على فعل ذات الشيء باستخدام Scheduler بسيط

بأمكانك تحديد مدة الرسم و الاختلاف بين كل رسم و اخر (Interval) حيث كما وضح الكتاب بأن اعادة الرسم فقط في حالة اعادت الدالة Animate قيمة true.

بالمناسبة هل حزمة collection (بالأخص Priority Queue) موجودة في JavaMe؟

لم ارها

تحياتي

تم تعديل بواسطه محمد عرسان
سقط سهوا
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أعرف يا محمد لكن واضح لك ولي أن أي كائن متحرك سيتم سؤاله عن إذا كان يريد التحرك أو لا في كل إطار

تصور أن لدينا مئة كائن متحرك والتعقيد في السؤال كبير

أتوقع أن هذا قد يسبب مشاكل كبيرة

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

انا بصراحة احبذ البدء من الصفر بكل الموضوع

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لا مشكلة من البدء بالصفر

لكني أريد أن أفهم لماذا هذا التصميم

هل هناك أسباب دفعتهم إليه؟

شيء آخر ما هي المعوقات التي أمامي غير موضوع الرسم؟

أقصد إلى أين تدعم JavaMe من جافا؟

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أعرف يا محمد لكن واضح لك ولي أن أي كائن متحرك سيتم سؤاله عن إذا كان يريد التحرك أو لا في كل إطار

تصور أن لدينا مئة كائن متحرك والتعقيد في السؤال كبير

أتوقع أن هذا قد يسبب مشاكل كبيرة

تحياتي

اذا فهمت انتقادك بشكل جيد فان حلهم أفضل لأنه في ال Micro World يفضل عدم انشاء ال Threads قدر المستطاع فوجود Thread واحد يقوم بجميع ال Animations أفضل بكثير من وجود مائه Scheduler وهو ما سيدمر برنامجك حرفيا..اذا كنت تقصد شيء أخر أرجو توضيحه..أما بالنسبه للمشاكل فهل يمكن سردها فأنا أعمل على هذه البيئه وحتى الأن أجد ال Animation بالتحديد جيد ولم يؤثر علي..

شيء آخر ما هي المعوقات التي أمامي غير موضوع الرسم؟

أقصد إلى أين تدعم JavaMe من جافا؟

تحياتي

سؤالك صعب هل لك أن تحدده بصوره أكبر..هل هناك حزم معينه تخشى عدم وجودها؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أخ مهدي حجازي

دعني أخبرك بالطريقة التي تعمل بها حزمة المحرك حتى تتضح الصورة أكثر

الحزمة تقوم بشكل أساسي على خيط وحيد

إذا أردت أن تحرك كائن واحد تقوم بإضافته إلى الحزمة

فيقوم المجدول بجدولته في قائمة الكائنات المتحركة (علماً بأن الحزمة تعتمد على مجدول واحد للجميع)

كل كائن له مجموعة الحركات التي سيتحركتها محددة بالوقت الذي سيتم أداء الحركة فيها

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

ويضبط وقت الصحيان من السبات على الوقت الذي سيتحرك فيه أول كائن متحرك

في حال كون الكائنات المتحركة ليس لديها حركات فيبقى المحرك في حالة سبات حتى الوقت الذي تضاف فيه حركات جديدة

فيقوم بجدولتها وتنبيه المحرك للعمل

لاحظ أن المحرك يعرف فعلياً متى عليه تنفيذ الحركة

بدون أن يمر على كل كائن ويسأله متى ستتحرك يا أستاذ

فهناك مدير يعرف بالضبط من سيتحرك ومتى سيتحرك وإلى أين ستحرك بدون أي تخاطب مع المطور (أقصد عملية الرسم paint)

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

بالنسبة للنظام الموجود في الحزمة LWUIT

فهو لا يعرف وإنما يظل يسأل هل ستتحرك يا أستاذ هل ستتحرك يا أستاذ بالطبع لو كان عدد الأساتذة كثر والقرار الذي يأخذه كل أستاذ ليقول لك سأتحرك أو لا يأخذ وقتاً جيداً

ستجد أن هناك إجمالي وقت مهدر بدون فائدة فعلية

على كل أنا اعتمدت على هيكلية إرسال التحديثات من قبل العملاء (لو هناك كائن متحرك يريد أن يتحرك بعد 100 ثانية سيرسل لي يقول أريد أن أتحرك)

بينما الحزمة اعتمدت على هيكلية اطلب التحديثات من العملاء (لو هناك كائن متحرك يريد أن يتحرك بعد 100 ثانية سينتظر حتى تمر المئة ثانية ثم يجيب علي عندما أسأله إن كان يريد أن يتحرك بالإيجاب)

والأخيرة مشهورة بأنها تضيع الوقت في طلب

هنا تكمن النقطة أريد أن أفهم لماذا استخدم هذه الهيكلية ولم يستخدم الأولى

هل اتخذ قراره بناءاً على بعض المعوقات في بيئة المحمول؟ (إنسان انلدع من المعوقات في بيئة المحمول laugh.gif )

أم أن قراره بني على السهولة؟ بمعنى أنه وجد أن هذه الآلية تسهل عليه بناء الحزمة فاستخدمها وأراح نفسه

الرد طول وخايف يضيع

لذا أرسله وسأكمل في رد آخر بالنسبة للسؤال الآخر

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

هذه الخصائص أو الفئات التي استخدمها وأخشى أنها غير موجودة في JavaMe

1- استخدم enum

2-استخدم Generics

3- الفئات Comparable و Iterable من الحزمة java.lang

4- استخدم reflection

5- استخدم collection

بالأخص الفئات التالية

ArrayList

List

Iterator

PriorityQueue

Collections

6- استخدم foreach

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

أخ مهدي حجازي

دعني أخبرك بالطريقة التي تعمل بها حزمة المحرك حتى تتضح الصورة أكثر

الحزمة تقوم بشكل أساسي على خيط وحيد

إذا أردت أن تحرك كائن واحد تقوم بإضافته إلى الحزمة

فيقوم المجدول بجدولته في قائمة الكائنات المتحركة (علماً بأن الحزمة تعتمد على مجدول واحد للجميع)

كل كائن له مجموعة الحركات التي سيتحركتها محددة بالوقت الذي سيتم أداء الحركة فيها

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

ويضبط وقت الصحيان من السبات على الوقت الذي سيتحرك فيه أول كائن متحرك

في حال كون الكائنات المتحركة ليس لديها حركات فيبقى المحرك في حالة سبات حتى الوقت الذي تضاف فيه حركات جديدة

فيقوم بجدولتها وتنبيه المحرك للعمل

لاحظ أن المحرك يعرف فعلياً متى عليه تنفيذ الحركة

بدون أن يمر على كل كائن ويسأله متى ستتحرك يا أستاذ

فهناك مدير يعرف بالضبط من سيتحرك ومتى سيتحرك وإلى أين ستحرك بدون أي تخاطب مع المطور (أقصد عملية الرسم paint)

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

بالنسبة للنظام الموجود في الحزمة LWUIT

فهو لا يعرف وإنما يظل يسأل هل ستتحرك يا أستاذ هل ستتحرك يا أستاذ بالطبع لو كان عدد الأساتذة كثر والقرار الذي يأخذه كل أستاذ ليقول لك سأتحرك أو لا يأخذ وقتاً جيداً

ستجد أن هناك إجمالي وقت مهدر بدون فائدة فعلية

على كل أنا اعتمدت على هيكلية إرسال التحديثات من قبل العملاء (لو هناك كائن متحرك يريد أن يتحرك بعد 100 ثانية سيرسل لي يقول أريد أن أتحرك)

بينما الحزمة اعتمدت على هيكلية اطلب التحديثات من العملاء (لو هناك كائن متحرك يريد أن يتحرك بعد 100 ثانية سينتظر حتى تمر المئة ثانية ثم يجيب علي عندما أسأله إن كان يريد أن يتحرك بالإيجاب)

والأخيرة مشهورة بأنها تضيع الوقت في طلب

هنا تكمن النقطة أريد أن أفهم لماذا استخدم هذه الهيكلية ولم يستخدم الأولى

هل اتخذ قراره بناءاً على بعض المعوقات في بيئة المحمول؟ (إنسان انلدع من المعوقات في بيئة المحمول laugh.gif )

أم أن قراره بني على السهولة؟ بمعنى أنه وجد أن هذه الآلية تسهل عليه بناء الحزمة فاستخدمها وأراح نفسه

الرد طول وخايف يضيع

لذا أرسله وسأكمل في رد آخر بالنسبة للسؤال الآخر

تحياتي

حسنا يبدو أن الأمر غير واضح لك بالنسبه ل LWUIT. LWUIT لا تقوم بسؤال كل المكونات بل فقط المكونات التي تريد التحرك وأنت تسجل المكون الذي تريد تحريكه عن طريق registerAnimated وبعدها سيقوم المحرك بسؤاله عن هل يريد التحرك أم لا؟ الان بالنسبه لمتى يتحرك الكائن فهذه غالبا لا نحتاجها, في غالب الاحيان الكائن الذي يريد الحركه سيتحرك مباشره أو سينتظر فتره بسيطه ثم يبدأ الحركه فالاهدار ليس كبير ثم لا زلت أنت تستخدم خيطان وهو خيط واحد..طبعا لن أخبرك عن مدى سوء ال Scheduling بين ال Threads في JME ثم هنالك مشكله أعم وأكثر ظهورا عندي في المحمول وهي أنني أريد القيام بحركات متقطعه أي أريد أن أحرك المكون لثانيتان ثم أقف لثانيتان ثم أعيد الكره وهكذا..هذه الحاله تتكرر كثيرا معي وباستخدام LWUIT الموضوع ممتاز حيث لا حاجه لي لاعده جدوله الكائن كل ما علي ان أخبر المحرك أنني الان اريد التحرك أو التوقف وعندما انتهي أخبره بازالته من قائمه الكائنات المتحركه..هل لك أن تطلعني على كيفيه معالجه هذه الحاله عندك.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .