سؤال

لدي الكود التالي، والذي يتم تشغيله كل 10 مللي ثانية كجزء من اللعبة:

private void gameRender()
{
    if(dbImage == null)
    {
        //createImage() returns null if GraphicsEnvironment.isHeadless()
        //returns true. (java.awt.GraphicsEnvironment)
        dbImage = createImage(PWIDTH, PHEIGHT);
        if(dbImage == null)
        {
            System.out.println("dbImage is null"); //Error recieved
            return;
        }
        else
        dbg = dbImage.getGraphics();
    }

    //clear the background
    dbg.setColor(Color.white);
    dbg.fillRect(0, 0, PWIDTH, PHEIGHT);

    //draw game elements...

    if(gameOver)
    {
        gameOverMessage(dbg);
    }
}

تكمن المشكلة في أنه يدخل عبارة if التي تتحقق من كون الصورة فارغة، حتى بعد محاولتي تعريف الصورة.نظرت حولي، ويبدو أن createImage() سترجع فارغة إذا كانت GraphicsEnvironment.isHeadless() ترجع صحيحًا.

لا أفهم بالضبط ما هو الغرض من طريقة isHeadless()، لكنني اعتقدت أنه قد يكون لها علاقة بالمترجم أو IDE، لذلك حاولت استخدام اثنين، وكلاهما يحصل على نفس الخطأ (Eclipse وBlueJ).هل لدى أي شخص أي فكرة عن مصدر الخطأ وكيف يمكنني إصلاحه؟

شكرا لك مقدما

جوناثان

...................................................................

يحرر:أنا أستخدم java.awt.Component.createImage(عرض int، ارتفاع int).الغرض من هذه الطريقة هو ضمان إنشاء وتحرير صورة تحتوي على عرض لاعب اللعبة، والذي سيتم رسمه لاحقًا على الشاشة عن طريق لوحة JPanel.إليك بعض التعليمات البرمجية الإضافية إذا كان هذا يساعد على الإطلاق:

public class Sim2D extends JPanel implements Runnable
{

private static final int PWIDTH = 500;
private static final int PHEIGHT = 400;
private volatile boolean running = true;
private volatile boolean gameOver = false;

private Thread animator;

//gameRender()
private Graphics dbg;
private Image dbImage = null;


public Sim2D()
{   
    setBackground(Color.white);
    setPreferredSize(new Dimension(PWIDTH, PHEIGHT));

    setFocusable(true);
    requestFocus(); //Sim2D now recieves key events
    readyForTermination();

    addMouseListener( new MouseAdapter() {
        public void mousePressed(MouseEvent e)
        { testPress(e.getX(), e.getY()); }
    });
} //end of constructor

private void testPress(int x, int y)
{
    if(!gameOver)
    {
        gameOver = true; //end game at mousepress
    }
} //end of testPress()


private void readyForTermination()
{
    addKeyListener( new KeyAdapter() {
        public void keyPressed(KeyEvent e)
        { int keyCode = e.getKeyCode();
            if((keyCode == KeyEvent.VK_ESCAPE) ||
               (keyCode == KeyEvent.VK_Q) ||
               (keyCode == KeyEvent.VK_END) ||
               ((keyCode == KeyEvent.VK_C) && e.isControlDown()) )
            {
                running = false; //end process on above list of keypresses
            }
        }
    });
} //end of readyForTermination()

public void addNotify()
{
    super.addNotify(); //creates the peer
    startGame();       //start the thread
} //end of addNotify()

public void startGame()
{
    if(animator == null || !running)
    {
        animator = new Thread(this);
        animator.start();
    }
} //end of startGame()


//run method for world
public void run()
{
    while(running)
    {
        long beforeTime, timeDiff, sleepTime;

        beforeTime = System.nanoTime();

        gameUpdate(); //updates objects in game (step event in game)
        gameRender(); //renders image
        paintScreen(); //paints rendered image to screen

        timeDiff = (System.nanoTime() - beforeTime) / 1000000;
        sleepTime = 10 - timeDiff;

        if(sleepTime <= 0) //if took longer than 10ms
        {
            sleepTime = 5; //sleep a bit anyways
        }

        try{
            Thread.sleep(sleepTime); //sleep by allotted time (attempts to keep this loop to about 10ms)
        }
        catch(InterruptedException ex){}

        beforeTime = System.nanoTime();
    }

    System.exit(0);
} //end of run()

private void gameRender()
{
    if(dbImage == null)
    {
        dbImage = createImage(PWIDTH, PHEIGHT);
        if(dbImage == null)
        {
            System.out.println("dbImage is null");
            return;
        }
        else
        dbg = dbImage.getGraphics();
    }

    //clear the background
    dbg.setColor(Color.white);
    dbg.fillRect(0, 0, PWIDTH, PHEIGHT);

    //draw game elements...

    if(gameOver)
    {
        gameOverMessage(dbg);
    }
} //end of gameRender()

} //end of class Sim2D

آمل أن يساعد هذا في توضيح الأمور قليلاً ، جوناثان

هل كانت مفيدة؟

المحلول

وبدلا من createImage (...)، وعادة ما تستخدم BufferedImage.

نصائح أخرى

وكان لي بالضبط نفس المشكلة بعد حاولت تنفيذ Doublebuffering لمولد كسورية. بلدي الحل: أخذت المثال من الكتاب ولكن تغييره (دون معرفة العواقب) في الطريقة التي ركضت createImage INSIDE المنشئ. أنتج هذا nullpointer. ثم أضع هذا

if (_dbImage == null) {
_dbImage = createImage(getSize().width, getSize().height);
_dbGraphics = (Graphics2D)_dbImage.getGraphics();
}

وداخل التحديث طريقة وعملت !! لأن يسمى التحديث بعد تم بناؤها الكائن.

ووفقا للمستندات لjava.awt.Component، createImage يمكن أيضا إرجاع لاغية إذا كان العنصر هو ليس للعرض، وهو على الأرجح ما يحدث.

لماذا تحاول أن تفعل يجب أن ننظر إلى الطبقة BufferedImage، وهذا ليست مرتبطة المكون.

وحاول تجاوز أسلوب addNotify () في JPanel الذي يتم تمديد. هذا هو مكان جيد لل'إطلاق الرسوم المتحركة الخاصة بك من، بدلا من أن منشئ على سبيل المثال. تأكد من تضمين خط super.addNotify ()؛

والجمهور الفراغ addNotify () {       super.addNotify ()؛      بدء اللعبة()؛ }

وحظا سعيدا

يبدو أن مؤشر الترابط يبدأ في وقت أبكر من عرض المكون فعليًا على الشاشة.للتأكد من عدم حدوث ذلك، يمكنك تجاوز طريقة الطلاء (Graphics g) الخاصة بـ JPanel ووضع الكود في طريقة run() الخاصة بسلسلة الرسائل داخل طريقة الطلاء.في أساليب run() الخاصة بخيطك، ما عليك سوى استدعاء repaint().

على سبيل المثال:

public void paint(Graphics g){
        **gameUpdate(); //updates objects in game (step event in game)
        gameRender(); //renders image
        paintScreen(); //paints rendered image to screen**
}

وفي طريقة التشغيل () الخاصة بك:

public void run(){
 while(running)
    {
        long beforeTime, timeDiff, sleepTime;

        beforeTime = System.nanoTime();

        **repaint();**

        timeDiff = (System.nanoTime() - beforeTime) / 1000000;
        sleepTime = 10 - timeDiff;

        if(sleepTime <= 0) //if took longer than 10ms
        {
            sleepTime = 5; //sleep a bit anyways
        }

        try{
            Thread.sleep(sleepTime); //sleep by allotted time (attempts to keep this loop to about 10ms)
        }
        catch(InterruptedException ex){}

        beforeTime = System.nanoTime();
    }
}

وisHeadless سيعود صحيحا فقط إذا كنت تعمل في بيئة غير واجهة المستخدم الرسومية (على سبيل المثال، داخل الخادم أو حاوية بريمج).

وأعتقد أن المشكلة هي في طريقة createImage الخاص نفسه. هل يمكنك أن تعطينا المزيد من السياق؟ الطريقة التي createImage يتم استدعاء وما هو تنفيذه؟

package javagame;

import java.awt.BorderLayout;
import javax.swing.JFrame;

/**
 *
 * @author stuart
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        JFrame frame= new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 500, 400);

        frame.add(new GamePanel(), BorderLayout.CENTER);
        frame.setVisible(true);
    }

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top