2009年11月23日

うっがー、壁の判定がうまくいかない

前回のダンジョン自動生成の続き。
東西南北に壁があるかどうかの判定の他、ダンジョン自動生成には東西南北に通路があると確定しているかどうかという判定も必要だ。
なぜなら壁の自動生成の際には既に、壁となっているところや通路となっているところは壁・通路のままにしておかなきゃいけないからだ。
そうじゃないとすでにできている壁を塗りつぶしちゃったり、通路に穴をあけようとしちゃったりするから。
  
すなわち、壁となる24個のフラグには
  1. 壁確定
  2. 通路確定
  3. 未確定
の3つの状態がある。これはtrue-falseしか状態を持たないbooleanのフラグでは現しきれない。ということで、しょうがないからフラグを48個確保した。

これで通路の状態が完全に表現できるようになった。あとは候補となるフロアの作り方だ。

これから候補になるフロアは、東西南北がすべて確定状態になるに決まっているので、4つのbooleanフラグで表現できる。すなわち0〜15までのintの値で表現可能だ。

この15の数値が現在の東西南北の壁・通路の確定・未確定と適合するのかを調べるテストプログラムを、以下に作った。黒い線が壁確定、緑の線が通路確定、白の線が未確定の場所で、線に囲まれた四角内部をクリックしたら判定結果が標準出力に吐き出される。このプログラムが正常に動けば、自動生成ダンジョンのアルゴリズムまで後一歩だ!

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class WallMazer extends JFrame implements MouseListener {

    boolean[] walls = new boolean[48];

    /**
     * @param args
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new WallMazer();
            }

        });
    }

    public WallMazer() {
        for (int i = 24; i < 48; i++) {
            // walls[i] = true;
        }

        walls[0] = true;
        walls[13] = true;
        walls[9 + 24] = true;
        walls[10 + 24] = true;
        walls[11 + 24] = true;
        walls[13 + 24] = true;
        JPanel canvas = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                reflesh((Graphics2D) g);
            }
        };

        addMouseListener(this);
        add(canvas);

        setSize(480, 480);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void reflesh(Graphics2D g) {
        g.translate(40, 40);
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                g.setColor(Color.WHITE);
                g.drawRect(x * 40, y * 40, 32, 32);
                g.setColor(Color.GREEN);
                if (!calcWall(y * 4 + x, 0, 24)) {
                    g.drawLine(x * 40, y * 40, x * 40, y * 40 + 32);
                }
                if (!calcWall(y * 4 + x, 1, 24)) {
                    g.drawLine(x * 40, y * 40, x * 40 + 32, y * 40);
                }
                if (!calcWall(y * 4 + x, 2, 24)) {
                    g.drawLine(x * 40 + 32, y * 40, x * 40 + 32, y * 40 + 32);
                }
                if (!calcWall(y * 4 + x, 3, 24)) {
                    g.drawLine(x * 40, y * 40 + 32, x * 40 + 32, y * 40 + 32);
                }
                g.setColor(Color.BLACK);
                if (calcWall(y * 4 + x, 0, 0)) {
                    g.drawLine(x * 40, y * 40, x * 40, y * 40 + 32);
                }
                if (calcWall(y * 4 + x, 1, 0)) {
                    g.drawLine(x * 40, y * 40, x * 40 + 32, y * 40);
                }
                if (calcWall(y * 4 + x, 2, 0)) {
                    g.drawLine(x * 40 + 32, y * 40, x * 40 + 32, y * 40 + 32);
                }
                if (calcWall(y * 4 + x, 3, 0)) {
                    g.drawLine(x * 40, y * 40 + 32, x * 40 + 32, y * 40 + 32);
                }

            }
        }
    }

    boolean calcWall(int pos, int quota, int offset) {
        if (quota % 2 == 0) {
            if (pos % 4 == quota * 3 / 2) {
                return true;
            }
            return walls[pos - (pos / 4) + (quota / 2) - 1 + offset];
        } else {
            int pos2 = pos + quota * 2 + 6;
            if (pos2 < 12) {
                return true;
            }
            if (pos2 >= 24) {
                return true;
            }
            return walls[pos2 + offset];
        }
    }

    boolean fitWall(int pos, int wall) {
        for (int i = 0; i < 4; i++) {
            if (calcWall(pos, i, 0)) {
                if ((wall & (1 << i)) == 0) {
                    System.out.print("no fit -" + i);
                    return false;
                } else {
                    continue;
                }
            }
            if (!calcWall(pos, i, 24) && ((wall & (1 << i)) == 0)) {
                System.out.print("no fit +" + i);
                return false;
            }
        }
        return true;
    }

    public void mouseClicked(MouseEvent e) {
        int x = (e.getX() / 40) - 1;
        int y = ((e.getY() - getInsets().top) / 40) - 1;
        if (x < 0 || 3 < x) {
            return;
        }
        if (y < 0 || 3 < y) {
            return;
        }
        for (int i = 0; i < 16; i++) {
            String out = "0000" + Integer.toString(i, 2);
            if (fitWall(y * 4 + x, i)) {
                System.out.println("** fit    "
                        + out.substring(out.length() - 4));
            } else {
                System.out.println(" " + out.substring(out.length() - 4));
            }
        }
        System.out.println("----");

    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }
}

・・・でも、判定関数「fitWall」がうまく動かなくて悩み中。
んー。なぜだろう・・・
posted by LoyalTouch at 22:06| Comment(0) | TrackBack(0) | 5つの宝島 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック