2011年8月11日木曜日

とりあえずゲーム作り(7)

さあ、またゲームが動くようになりました。

なのでまたまた、好きなように改造していきます。結果、コードが汚くなってきたら、また書き直しゃいーんです、的な気楽さでいきましょう。

さて、このあいだ岩を「赤い四角」から適当に「赤い石の写真」に置き換えただけで、雰囲気はえらく変わってしまいました。やっぱ見た目は大事ですねぇ、ということで。

PUBLIC-DOMAIN-PHOTOS.com さんのところで見つけた宇宙の画像を、背景に貼ってみました。


うん、更に宇宙旅行っぽくなりましたかね。コードはベタですが、まずGameViewに以下の変数を宣言しておき、

  Bitmap wall;
  Rect wall_f, wall_t;

初期化のところに以下のコードを追加して背景画像を準備し、

  wall = BitmapFactory.decodeResource(context.getResources(), R.drawable.galaxy);
  wall_f = new Rect(0, 0, wall.getWidth(), wall.getHeight());
  wall_t = new Rect(0, 0, s.cw, s.ch);

最後にdoDraw()で canvas.drawColor(Color.BLACK); の代わりに以下で背景をクリアするようにします。

  canvas.drawBitmap(wall, wall_f, wall_t, null);

もう少しマシな方法もある気はしますが、とりあえず簡単に実現できたのでコレで良しとしましょう。

次はゲーム性の向上を考えてみましょう。このゲームでは岩を避けるのがゲームの根っこですが、岩の出現のしかたが親切ではない気がします。いきなり出てきて、避けられないことがある。

そこで出現直後の一定時間は、自機との当たり判定が無いという仕様はどうでしょうか。更にそれがわかるように、出現時には半透明で、だんだんとはっきり見えてくる感じの表現が良いですね。半透明でなくなった時から当たり判定が発生する、であればプレイヤーに十分な情報を伝えることができます。

これを実現するために、GameBitmapObject を継承した Rock クラスを新しく作成してみましょう。

public class Rock extends GameBitmapObject {
  int count;
  public Rock(int _w, int _h, Bitmap b) {
    super(_w, _h, b);
    count = 0;
  }
}

動いた回数を記録する count変数を追加してみました。で、実際に動くmove()関数を上書きして、カウントアップしてあげないといけないですね。

  @Override public GameObject move() {
    super.move();
    count++;
    return this;
  }

で、最初の2秒ほどは衝突判定はないことにします。よって以下のように上書きしてみました。

  @Override public Boolean collision(GameObject o) {
    return count < 20 ? false : super.collision(o);
  }

あと、衝突判定がない間は、半透明表示でしたよね。なので以下のように上書きしています。

  @Override public GameObject draw(Canvas c) {
    if (count < 20) {
      Paint p = new Paint();
      p.setAlpha(count * 10);
      c.drawBitmap(bitmap, br, new Rect(cx, cy, cx + cw, cy + ch), p);
    } else {
      super.draw(c);
    }
    return this;
  }

それぞれ、countの値を条件として参照していて、条件によって動作を乗っ取る仕組みの上書き(Overrode)ですね。条件外のときには素直にsuper呼ぶのがポイントです。

透明度を count * 20 としているのは乱暴に見えますが、半透明の状態とふだんの表示(α値が255)は少しギャップがあったほうが、プレイヤーにわかりやすいと思って、この式にしています。

さて、この新しいクラス Rock を GameActivity に組み込みましょう。岩関係でクラス指定をしている、以下の二箇所を書き換えます。

List<GameBitmapObject> rocks = new ArrayList<GameBitmapObject>();

List<Rock> rocks = new ArrayList<Rock>();
 
GameBitmapObject o = new GameBitmapObject(s.w(0.01F * s.i(10, 5)), s.h(0.01F * s.i(10, 5)), b);
Rock o = new Rock(s.w(0.01F * s.i(10, 5)), s.h(0.01F * s.i(10, 5)), b);

あ、衝突判定の修正を生かすには、以下も忘れちゃ駄目ですね。

if (ship.collision(rock)) {
if (rock.collision(ship)) {

よし、これで大丈夫。プレイしてみましょう。


うん、これは良い。

新しい岩がじわじわ現れ、その間は衝突判定がないので、不条理な衝突が発生しなくなりました。運より実力が生かされるように調整されたと言えます。

修正点は少ないですが、満足してしまいましたので今日はこれで終了。暑くて汗だらだらなので、ガリガリ君でも食べてのんびりしますw

0 件のコメント:

コメントを投稿