0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Tonyu System 2であほげーを作ろう - その8 物理エンジンなど

Last updated at Posted at 2018-07-12

記事一覧

第1回 設定とタイトル
第2回 メイン画面
第3回 ターゲットと敵と
第4回 スコア・時間など
第5回 ゲームを公開する
第6回 Twitterにスコアを投稿
[第7回 サウンド関係]
(https://qiita.com/hoge1e3/items/a5b1726f6c95bbb4e852)
[第8回 物理エンジンなど]
(https://qiita.com/hoge1e3/items/b2a0df1d5aaba773310f)

はじめに

さて,気づいたら明日はお題発表じゃないか!ということで,駆け込みでもう少しゲームの中身について改造をしてみたいと思います.

Tonyu2 で作っているゲームの内容について「こういう改造をしてみたいけどどうやったらいいの?」という疑問が出たら,ドキュメント内に

用途別リファレンス

というのがありますので,参考にしてください.

今回は,その中の一例として,物理エンジンを使ったゲームを作ってみようと思います.

今回のプログラムを開く

今回のゲームは前回同様<<第26回のテーマ>>を,<<テーマに関連する何か>>をよけながら集めます.前回と違って,サイドビューで重力が働いています.上を押すとジャンプします.

プログラム

床の追加

まず,重力が働くため,床がないと落ちてしまいます.そこで,Floor(床)クラスを新たに追加しています.

Floor
extends BodyActor;
width=200;
height=10;
fillStyle="white";
isStatic=true;

物理運動に関係する(物理運動するオブジェクトとぶつかる)オブジェクトは,BodyActorクラスを継承して作ります.床のテクスチャを用意するのが面倒なので,代わりにwidthheightfillStyleフィールドに値を設定すると,指定した大きさ,色をもつキャラクタが表示されるようになります.また,widthheightが当たり判定の大きさになります.
isStatic=true;は,落下などの物理運動をしない,他の物理オブジェクトとの衝突だけを行うオブジェクトに対して用います.

Mainの最初に床の出現を行っています.rotationを指定しているので,床が傾いています.

Main(一部)
new Floor{x=200,y=400,rotation=10};
new Floor{x=300,y=250,rotation=-10};

物理運動

既存のキャラクタ達も,物理運動させるため,BodyActor を継承したクラスに変更しています.
例えばEnemyクラスでは,1行目にextends節を追加し,物理的な当たり判定の形状を「円形」にするため,radiusフィールドを定義しています.radiusは当たり判定の大きさの設定も兼ねています.Targetクラスでも同様の変更をしています.

また,BodyActorではvxvyは予約されているフィールドで,これらに値を代入するだけでオブジェクトの速度を変更することができます.したがって,従来のオブジェクトにあったx+=vxなどは不要になります.

Enemy
extends BodyActor;//★追加

radius=16;//★追加
p=$pat_ahoge26+2;
while(true) {
    //x+=vx;  ★削除
    //y+=vy;
    if (screenOut()) die();
    update();
}

Playerクラスはもっとあちこちいじっています.

Player
extends BodyActor;//★A 追加
pad=new APad;
p=$pat_ahoge26+0;
radius=16;//★A 追加
while(true) {
    vx+=pad.vx*0.3;//★B 変更 移動の処理
    //x+=pad.vx*5; ← これまでの処理
    //y+=pad.vy*5;
    t=contactTo(Target);//★C変更 crashTo → contactTo
    if (t) {
        $sound.playSE($se_coin) {rate:1+$score*0.1};
        $score+=1;
        t.die();
        if ($score>=10) {
            $state="clear";
            break;
        }
    }
    //---★Dジャンプの処理
    cp=contactPoint(Floor);
    if (cp && cp.y>y) {
        jumpable=1;
    }
    if (pad.vy<-0.1 && jumpable) {
        jumpable--;
        vy=-10;
    }
    //---★Dジャンプの処理ここまで
    e=contactTo(Enemy);//★C 変更 crashTo → contactTo
    if (e) {
        $state="gameover";
        die();
    }
    if (screenOut()) $state="gameover";
    update();
}
  • ★AはEnemyクラスと同じ変更です.ちなみに当たり判定を「四角形」にしたい場合は,radiusの代わりにwidthheightを設定します.
  • ★Bでは,物理オブジェクトを移動させるときの方法を変更しています.物理オブジェクトに対して,従来のようにxやyを直接書き換えるのはおすすめしません(正しい物理シミュレーションができなくなる).代わりにvxvyを変更してください.
  • ★Cでは crashToメソッドをcontactToメソッドに変更しています.物理オブジェクト同士の衝突判定にはcontactToを使ってください.
  • ★Dは,次に詳説します
    • ★D-1 contactPointメソッドは,contactToメソッドの強化版です.当たっているオブジェクトだけでなく,どの点で当たったかを返します.(cp.x,cp.y)が当たった点,cp.targetが当たったオブジェクトになります.引数にFloorクラスが指定されているので,床に当たっている場合,当たっている点を返しています.
    • ★D-2 当たってた点がある(nullやundefinedでない)場合で,かつ当たった点のy座標がプレイヤーのy座標より大きい,というのはつまり「床に当たっていて,当たりどころが自分より下,つまり頭とかじゃなくて足元」ということです.この場合,今プレイヤーは足場にいることになります.したがってjumpable(ジャンプできるよー)変数に1を入れています.
    • ★D-3 パッドを上に入れていて,ジャンプできるよきにはvyに負の値を入れて,上方向に力を加えます.そのときjumpableは0に戻します.
    cp=contactPoint(Floor);//★D-1
    if (cp && cp.y>y) {// ★D-2
        jumpable=1;
    }
    if (pad.vy<-0.1 && jumpable) {//★D-3
        jumpable--;
        vy=-10;
    }

最後に,Mainクラスにおける敵やターゲットの出方を変更しています.

Main(一部)
while($state=="play") {
    if (rnd(30)==0) {//出現確率UP
        new Target{x=rnd($screenWidth),y=0,vx=rndFloat(-5,5),vy=1};//vxをランダムに
    }
    if (rnd(10)==0) {//出現確率UP
        new Enemy{x=rnd($screenWidth),y=$screenHeight,vx=rndFloat(-5,5),vy=-10-rnd()*5};//vxをランダム,vyも上方向にランダム
    }
    $frames++;
    $time=floor($frames/$Boot.getFrameRate());
    update();
}

おまけ - キーボードショートカット

今回の変更と直接関係ありませんが,最終バージョンになるので,もう1つ地味ながらプレイアビリティ?を上げる変更をしています.

Title(一部)
//スタートボタン
new Button{
    text="Start",
    top=300,
    onClick=start,
    key="space" //追加
};

タイトルのスタートボタンにkey="space"という属性を加えています.PCでプレイしているときに,ボタンをマウスで押す代わりにスペースキーで代用できるようにしています.Mainクラスでゲームオーバーになったときの「Title」ボタンにも同様に追加してます.これで,キーボードから手を放さず何度でもプレイできるようになります.

さいごに

というわけで,明日にはテーマ発表なので,連載はたぶんこれで完了です.読んでくださった方はありがとうございます.
連載冒頭でも申し上げましたが,ゲーム内容もグラフィックスも音楽も手抜きです.これはあくまで「タイトル」「クリア」「ゲームオーバー」などの枠組みを提供するためのものだと思ってください.皆様のセンスでたくさんの「あほね!1」を稼いでくだされば幸いです.

  1. あほげーのエントリされた各作品に「あほね!」というボタンがついているのです.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?