2

(そうではない)ここで短い質問。私は、コンソールではなく UI として Swing を使用して単純なローグライクを作成することに取り組んでいます (これにより、特に Eclipse での作業が容易になります) が、障害にぶつかったようです。

困っているのは、ゲーム ループに入ると UI が正しく表示されないことです。全体を通して「ソリティア」効果を与える醜いウィンドウフレームが表示され、実行中にRAMの使用量が急速に増加します。

ここで Swing について何か重要なことを見逃していますか? これを行うには Swing の同時実行設定を使用する必要がありますか? もしそうなら、最善のアプローチは何でしょうか?

完全なコードは以下のとおりです。

package roguelike;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedList;

import javax.swing.*;
import javax.swing.text.*;

public class roguelike {
    Color c_black = new Color(0x000000);
    Color c_white = new Color(0xffffff);
    Color c_red = new Color(0xff0000);
    Color c_blue = new Color(0x0000ff);
    Color c_green = new Color(0x00ff00);

    UI ui = null;
    Player me = null;
    Map gamemap = null;
    LinkedList<Character> keyqueue = new LinkedList<Character>();

    int charheight = 20;
    int charwidth = 80;

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                roguelike game = new roguelike();
                game.run();
            }
        });
    }
    public roguelike(){
        gamemap = new Map();
        ui = new UI(charheight,charwidth,"Monospaced");
        me = new Player();
    }
    private class UI extends JFrame implements KeyListener{
        private static final long serialVersionUID = 9065411532125953842L;
        JPanel disp_screen = null;
        JTextPane disp_screen_text = null;
        StyledDocument disp_doc = null;
        Font mono_norm = null;
        int pxheight = 0;
        int pxwidth = 0;
        String[][] ctemp = new String[charheight][charwidth];
        String[][] stemp = new String[charheight][charwidth];


        public UI(int h,int w,String fontname){
            setVisible(true);
            charheight = h;
            charwidth = w;
            addKeyListener(this);

            this.setResizable(false);
            mono_norm = new Font(fontname,0,25);
            initScreen(h,w);
            add(disp_screen);
            makeStyles();
            try {
                disp_doc.insertString(0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20", disp_doc.getStyle("Default"));
            } catch (BadLocationException e) {
                e.printStackTrace();
            }

            Dimension temp = disp_screen.getSize();
            this.setSize(temp);
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);           


            pack();
            try {
                disp_doc.remove(0, disp_doc.getLength());
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
            renderMap(gamemap.getText(),gamemap.getStyles());

        }
        @Override
        public void keyPressed(KeyEvent e) {
            // TODO Auto-generated method stub

        }
        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub

        }
        @Override
        public void keyTyped(KeyEvent e) {
            keyqueue.add(e.getKeyChar());
        }
        private void initScreen(int height, int width){
            FontMetrics metric = getFontMetrics(mono_norm);
            String temp = null;

            //generate a string of the right width from which to grab metrics
            for(int x=0;x<=width;x++){
                temp += '.';
            }
            pxwidth = SwingUtilities.computeStringWidth(metric, temp);
            pxheight = (metric.getHeight())*charheight;

            disp_screen = new JPanel();
            disp_screen_text = new JTextPane();
            disp_screen_text.setEditable(false);
            disp_screen_text.setAlignmentX(LEFT_ALIGNMENT);
            disp_screen_text.setAlignmentY(TOP_ALIGNMENT);
            disp_screen_text.setFont(mono_norm);
            disp_screen_text.setBackground(c_black);
            disp_screen_text.setForeground(c_green);
            disp_doc = disp_screen_text.getStyledDocument();


            disp_screen.add(disp_screen_text);
            disp_screen.setAlignmentX(LEFT_ALIGNMENT);
            disp_screen.setAlignmentY(TOP_ALIGNMENT);
            disp_screen.setLayout(new BoxLayout(disp_screen,BoxLayout.Y_AXIS));
        }
        private void makeStyles(){
            //The default style removes all special formatting and returns the text to standard nonsense
            Style sty_default = disp_doc.addStyle("Default", null);
            StyleConstants.setFontFamily(sty_default, "Monospaced");
            StyleConstants.setFontSize(sty_default, 18);
            StyleConstants.setForeground(sty_default, c_green);
            StyleConstants.setBackground(sty_default, c_black);
            StyleConstants.setItalic(sty_default, false);
            StyleConstants.setBold(sty_default, false);
            //StyleConstants.setSpaceAbove(sty_default, 0);
            //StyleConstants.setSpaceBelow(sty_default, 0);

            //The following styles apply certain effects. They are meant to be set without replacing styles
            Style sty_bold = disp_doc.addStyle("Bold", disp_doc.getStyle("Default"));
            StyleConstants.setBold(sty_bold,true);

            Style sty_ital = disp_doc.addStyle("Italic", disp_doc.getStyle("Default"));
            StyleConstants.setItalic(sty_ital, true);

        }
        private void clearMap(){
            try {
                disp_doc.remove(0, disp_doc.getLength());
            } catch (BadLocationException e1) {
                e1.printStackTrace();
            }
            try {
                //CLEAR THE MAP
                //For every row...
                for(int y=0;y<charheight;y++){
                    //For every column location in a row...
                    for(int x=0;x<charwidth;x++){
                        disp_doc.insertString(disp_doc.getLength(),".", disp_doc.getStyle("Default"));
                    }
                    disp_doc.insertString(disp_doc.getLength(),"\n", disp_doc.getStyle("Default"));
                }
            } catch (BadLocationException e){
                    e.printStackTrace();
            }
        }
        public void renderMap(String[][] chars, String[][] styles){
            System.out.print("Rendering map...");
            clearMap();
            ctemp = chars;
            stemp = styles;

            try {

                //For every row...
                for(int y=0;y<charheight;y++){
                    //For every column location in a row...
                    for(int x=0;x<charwidth;x++){
                        if(ctemp[y][x] != null){
                            if(stemp[y][x] == "D"){
                                disp_doc.remove((y*charwidth)+x, 1);
                                disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Default"));
                            } else if(stemp[y][x] == "B"){
                                disp_doc.remove((y*charwidth)+x, 1);
                                disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Bold"));
                            } else if(stemp[y][x] == "I"){
                                disp_doc.remove((y*charwidth)+x, 1);
                                disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Italic"));
                            } else{
                                disp_doc.remove((y*charwidth)+x, 1);
                                disp_doc.insertString((y*charwidth)+x,ctemp[y][x], disp_doc.getStyle("Default"));
                            }
                        }
                    }
                }
            } catch (BadLocationException e){
                e.printStackTrace();
                System.err.print(e.getCause());
            }
        }
    }

    //Handles the virtualized information of characters on the map. Does NOT handle display of map on screen
    //Displaying the screen happens by passing required data to the ui member
    private class Map{
        //Holds an array of map characters
        String[][] text = new String[charheight][charwidth];
        //Holds an array of styles associated with each map character
        String[][] styles = new String[charheight][charwidth];


        public Map(){
        }
        public String[][] getText(){

            return text;
        }
        public String[][] getStyles(){
            return styles;
        }
        public void putch(String thing, String styledef,int y, int x){
            text[y][x] = thing;
            styles[y][x] = styledef;
        }
    }

    private class Player{
        //Player location, [y][x]
        int[] location = {0,0};
        String sym = "@";
        public Player(){
        }
        public int[] getLocation(){
            return location;
        }
        public String getSymbol(){
            return sym;
        }
        public void setLocation(int y, int x){
            location[0]=y;
            location[1]=x;
        }
        public void setSymbol(String newsym){
            sym = newsym;
        }
        public void move(int dir){
            //Movement will be handled in an 8 directional fashion
            //North is 1, like below
            //     812
            //     703
            //     654
            //////////////////////
            switch(dir){
                case 0:
                    break;
                case 1:
                    location[0] += 1;
                    break;
                case 2:
                    location[0] += 1;
                    location[1] += 1;
                    break;
                case 3:
                    location[1] += 1;
                    break;
                case 4:
                    location[0] -= 1;
                    location[1] += 1;
                    break;
                case 5:
                    location[0] -= 1;
                    break;
                case 6:
                    location[0] -= 1;
                    location[1] -= 1;
                    break;
                case 7:
                    location[1] -= 1;
                    break;
                case 8:
                    location[0] += 1;
                    location[1] -= 1;
                default:
                    System.err.print("ERROR! "+dir+" is not a valid direction!");
                    break;
            }
        }
    }

    /////////////////////////////////////////////////////
    /////////////FUNCTIONS///////////////////////////////
    /////////////////////////////////////////////////////
    public void run(){
        boolean running = true;
        while(running){
            //Render Map
            gamemap.putch(me.getSymbol(), "D", me.getLocation()[0], me.getLocation()[1]);
            ui.renderMap(gamemap.getText(), gamemap.getStyles());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //Wait for player input
            if(keyqueue.isEmpty()){
                continue;
            }
            //Act on input
            else{
                char input = keyqueue.getFirst();
                keyqueue.removeFirst();
                if(input == 'w'){
                    me.move(1);
                }
                if(input =='a'){
                    me.move(7);
                }
                if(input == 's'){
                    me.move(5);
                }
                if(input == 'd'){
                    me.move(3);
                }
            }
        }

    }
}
4

1 に答える 1

5

Swing アプリはイベント ドリブンである必要があります。game.run()呼び出しにより、Swing は他の有用な処理をブロックされます。「イベント」は、ユーザーイベント、タイマー、またはおそらくその他のものである可能性があることに注意してください。

デザインが必要game.run()であるか、そのようなものが実行されて戻らない場合は、別のスレッド (または SwingWorker バックグラウンド スレッド) で実行できますが、すべての UI コンポーネントは Swing スレッドでアクセスする必要があります。

推奨事項: キーボード処理は、作成したKeyListenerを使用して簡単に実行でき、ウィンドウまたはその他のコンポーネントのイベント ハンドラーにアタッチされ、ユーザーがキーを押すたびに呼び出されます。つまり、この設計ではポーリングする必要はありません。 .

于 2012-07-19T21:25:51.013 に答える