コメント6/13

今回は、オブジェクト指向によるゲームの作り方の基本を説明します。

まず、次のようなゲームのプログラムを考えます。


class Game {
   private int zibunx;
   private int zibuny; 
   private Image zibunimage;
   private int teki1x;
   private int teki1y;
   private int teki1vx;
   private int teki1vy;
   private Image teki1image;
   private int teki2x;
   private int teki2y;
   private int teki1vx;
   private int teki1vy;
   private Image teki2image;
   private int haikeix;
   private int haikeiy;
   private Image haikeiimage;

   public Game(){
     zibunx=0;
     zibuny=0;
     zibunimage=Image("自機の画像ファイル名");
     teki1x=0;
     teki1y=0;
     teki1vx=0;
     teki1vy=0;
     teki1image=Image("敵1の画像ファイル名");
     teki2x=0;
     teki2y=0;
     teki2vx=0;
     teki2vy=0;
     teki2image=Image("敵1の画像ファイル名");
     haikeix=0;
     haikeiy=0;
     haikeiimage=Image("背景の画像ファイル名");
  }
  public void move(Graphic g, Event e){
     // Event e を解釈して、自機の次の座標を計算
     // teki1vx, teki1vy を計算
     // teki2vx, teki2vy を計算
     g.draw(haikeiimage,haikeix,haikeiy);
     teki1x+=teki1vx;
     teki1y+=teki1vy;
     g.draw(teki1image,teki1x,teki1y);
     teki2x+=teki2vx;
     teki2y+=teki2vy;
     g.draw(teki2image,teki2x,teki2y);
     g.draw(zibunimage,zibunx,zibuny);
  }
}

このプログラムは何をしたいのかは良く読み取れますが、プログラム全体 を把握したり、改造したりするのは骨が折れそうです。 さらに、プログラムは似たような構造が続いています。

そこでオブジェクト指向を使います。つまり、敵や自分をそれぞれオブジェ クトとし、プログラムを切り分けます。 また、敵や自分や背景自体はそれぞれ微妙に違いますが、同じような処理 になっています。 そこで、プログラムの共通化を考えます。 つまり画面上に座標を元に表示するようなものを Mono という(インターフェ イス)型とし、共通のプログラムを AbstractMono クラスに書きます。 さらに、Mono の集まりを MonoList とし、まとめた指示をMonoListに対 して行います。

すると、上記の move メソッドは座標計算と、表示を行っているので、 Mono には move と draw メソッドを実装すると、下記のようなプログラ ムになります。


interface Mono {
    void move(Event e);
    voide draw(Graphic g);
}
abstract class AbstractMono implements Mono {
    protected int x;
    protected int y;
    protected int vx;
    protected int vy;
    protected Image image;
    
    protected AbstractMono(String filename){
        x=0;
        y=0;
        vx=0;
        vy=0;
        image = new Image(filename);
    }
    @Override 
    public void draw(Graphic g){
        x+=vx;
        y+=vy;
        g.draw(image,x,y);
    }
}
class Zibun extends AbstractMono {
    public Zibun(){
        super("自機の画像ファイル名");
    }
    @Override
    public void move(Event e){
        //Event e を解釈して vx, vy を計算する
    }
}
class Teki extends AbstractMono {
    public Teki(String filename){
        super(filename);
    }
    @Override
    public void move(Event e){
        //Event e を無視し、vx, vy のパターンを計算する
    }
}
class Haikei extends AbstractMono {
    public Haikei(){
        super("背景画像ファイル");
    }
    @Override
    public void move(Event e){
        //Event e を無視し、背景に関するvx, vy のパターンを計算する
    }
}
class MonoList extends ArrayList<Mono> {
    public void move(Event e){
        for(Mono m : this){
             m.move(e);
        }
    }
    public void draw(Graphic g){
        for(Mono m : this){
             m.draw(g);
        }
    }
}
class Game {
  private MonoList list;
  public Game(){
    list = new MonoList();     
    list.add(new Haikei());
    list.add(new Teki("敵1の画像"));
    list.add(new Teki("敵2の画像"));
    list.add(new Zibun());
  }
  public void move(Graphic g, Event e){
    list.move(e);
    list.draw(g);
  }
}

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科