السبت، 31 يوليو 2010

التحريك

مقدمة
في هذا الدرس سوف نتعرف على أسس التحريك وهي نفس الأسس التي تعتمد عليها جميع الألعاب حتى ألعاب الحاسوب تعتمد على طرق مشابهة للمبادئ المطروحة في هذا الدرس.
ملاحظة قبل المتابعة
هذا الدرس يعتمد بشكل كلي على ال 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();
    }
}

مقدمة في انشاء واجهة مستخدم منخفضة المستوى - الجزء الثالث

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

كيفيه انشاء خط لاستخدامه في الرسم
Font f = Font.getFont(int face, int style, int size);
أنواع الخطوط
  • FACE_SYSTEM
  • FACE_MONOSPACE
  • FACE_PROPORTIONAL
 تنسيق الخطوط
  • STYLE_PLAIN
  • STYLE_BOLD
  • STYLE_ITALIC
  • STYLE_UNDERLINED
حجم الخط
  • SIZE_SMALL
  • SIZE_MEDIUM
  • SIZE_LARGE
الصور
يتم رسم الصور عن طريق ال drawImage method الموجوده في الفئه Graphics.
public void drawImage(Image img,
                      int x,
                      int y,
                      int anchor)
محاذاه الصوره يشبه الى حد كبير محاذاه النصوص التي تم شرحها سابقا.

مجال الرسم
يمكن تحديد مجال للرسم بحيث أن لأي شيء خارج هذا المجال فانه لن يرسم باستخدام ال setClip method الموجوده في الفئه Graphics.
public void setClip(int x,
                    int y,
                    int width,
                    int height)
استقبال الأحادث في ال Canvas
عند الضغط على أزرار الهاتف فان مجموعه من ال methods سوف يتم تنفيذها لكي تعلمك بحدوث الحدث كما سترسل لك بعض المعلومات عن الزر الذي تم الضغط عليه.
protected void keyPressed(int keyCode)
protected void keyReleased(int keyCode)
Protected void keyRepeated(int keyCode)

Game Actions
يمكن معرفه ال Game Action المقابل لكل keycode تم استقباله في أحد ال methods السابقه عن طريق
int gameAction = getGameAction(keyCode);
أنواع ال Game Actions التي تدعمها JME هي كالتالي:
  • UP
  • DOWN
  • LEFT
  • RIGHT
  • FIRE
  • GAME_A
  • GAME_B
  • GAME_C
  • GAME_D
ال Game Actions يمكن أت ترتبط بأزرار مختلفه حسب نوع الجهاز وهي بذلك تريح المبرمج من عناء اختلاف الأجهزه فمثلا زر ال Fire في هواتف Nokia عاده هو الزر الموجود في منتصف لوحه التحرك أو الزر الذي يحمل الرقم 5 وبالتالي فانت عندما تقوم بعمل لعبه ما فان المستخدم سيستخدم نفس الأزرار التي تعود على استخدامها وبنفس الطريقه.

مثال
public class KeyCanvas extends Canvas {

    private Font mFont;
    private String mMessage = "[Press keys]";


    public KeyCanvas() {
        mFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
    }


    public void paint(Graphics g) {
        int w = getWidth();
        int h = getHeight();

        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, w - 1, h - 1);
        g.setColor(0x0);
        g.drawRect(0, 0, w - 1, h - 1);
        g.setFont(mFont);
        int x = w / 2;
        int y = h / 2;
        g.drawString(mMessage, x, y, Graphics.BASELINE | Graphics.HCENTER);
    }

    protected void keyPressed(int keyCode) {
        int gameAction = getGameAction(keyCode);

        switch (gameAction) {
            case UP:
                mMessage = "UP";
                break;

            case DOWN:
                mMessage = "DOWN";
                break;

            case LEFT:
                mMessage = "LEFT";
                break;

            case RIGHT:
                mMessage = "RIGHT";
                break;
            case FIRE:
                mMessage = "FIRE";
                break;
            case GAME_A:
                mMessage = "GAME_A";
                break;
            case GAME_B:
                mMessage = "GAME_B";
                break;
            case GAME_C:
                mMessage = "GAME_C";
                break;
            case GAME_D:
                mMessage = "GAME_D";
                break;
            default:
                mMessage = "";
                break;
        }
        repaint();
    }
}
في المثال السابق أعدنا تعريف keyPressed method وفي داخلها قمنا بمعرفه ال Game Action الذي حصل باستخدام جملة switch ثم أدخلنا اسم هذا ال Game Action في متغير اسمه mMessage وفي أخر سطر من ال method استدعينا repaint لكي تقوم باعاده رسم الشاشه.


في ال paint method نقوم برسم المتغير mMessage في منتصف الشاشه. لاحظ أن هذه الفئه ترث من الفئه Canvas وبالتالي نستطيع وضعها على شاشه الهاتف وهو ما سنقوم به في السطور الأتيه:
public class KeyEvents extends MIDlet {
    public void startApp() {
        KeyCanvas canvas = new KeyCanvas();
        Display.getDisplay(this).setCurrent( canvas );
        
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
}

الجمعة، 16 يوليو 2010

نوكيا سوف تجعل عمليه ال Signing لبرامج ال Symbian مجانا

أعلنت شركه نوكيا عن نيتها جعل ال Signing لبرامج ال Symbian مجانا بعد أن كانت تكلف هذه العمليه 215$ وقد بدأ العمل في هذه الخطوه التجربيه منذ 23 June. وهذا البرنامج سوف يغطيي البرامج التي من نوع Symbian بشقيها sis و sisx والتي من نوع Qt والتي من نوع Flash Lite. سوف لن يغطي البرنامج برامج الجافا وهو أمر مفهوم حيث ان تكاليف ال Signing لبرامج الجافا لا تذهب لشركه نوكيا وانما لشركه Oracle مالكه جافا.

خطوات نشر برنامج على Ovi أصبح كالتالي كما جاء نقلا عن موقع نوكيا:
  • Ovi Publisher emails support and requests more details  
  • Ovi Publish support asks publisher to review and accept new terms and conditions
  • Ovi Publisher accepts new terms and conditions and provides IMEI numbers for up to 5 devices
  • Ovi Publish support sends publisher UIDs, a cert installer, and developer cert/key pair for testing their app
  • Ovi Publisher packages their unsigned SIS file using the UID provided and tests on their device making sure is tested against Symbian’s signing criteria
  • Ovi Publisher submits their app (unsigned SIS file with the UID provided) to the intake tool
  • QA and moderation will test the app and if it passes it will be express signed by Nokia and put into Ovi Store