ページ 1 / 1
[質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月10日(月) 14:59
by LL
このサイトに掲載されているAndroidの館のプログラムについて質問があります。
Androidの館ではタスクリストを作り、そこに直接
コード:
GameMgr(){
mTaskList.add(new Player());
mTaskList.add(new Enemy());
mTaskList.add(new FpsController());
}
と言った具合に直接
add(new ○○)
としていますが、この手法では互いのオブジェクトの変数に干渉するようなプログラムは不可能な気がするのですが、
間違って無いでしょうか?
(例えばPlayerとEnemy3体の当たり判定を順番にし、当たっていたらライフを減らすと言った処理等)
現在このサイトの作り方を参考にモーションセンサーで自機を動かし、別の敵のオブジェクトにぶつけてダメージを与えると言ったチープなゲームを作っているのですが、
このタスクを利用した方法では、当たり判定で当たった際に、それぞれのオブジェクトのライフを減らしたり、移動ベクトルを変化させる(反発した様に見せかける)処理が不可能な感じがしたので質問させていただきました。
実際にAndroidの館のイライラ棒はゲーム全体のステータスをいじっているだけですし。
場合によっては今作っている物を破棄し、別の手段で組み直すことも考慮しています。
まだjava歴も1ヶ月程度なので抜け道があるのかもしれませんが・・・
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月10日(月) 15:25
by LL
後もう一つあるのですが、GameSurfaceViewのThread(スレッド)の処理の意味が分かりません。
Thread _thread;
と作って
コード:
@Override
public void run() {
while (_thread!=null) { //メインループ
onDraw(getHolder());
}
}
としてますが、
コード:
@Override
public void surfaceCreated(SurfaceHolder holder) {
_thread = new Thread(this); //別スレッドでメインループを作る
_thread.start();
}
new Thread(this); ←this?自分の中で自分のスレッド?どういうこと?
一体何をしているのか?(スレッドの意味自体は分かるがこのプログラムの処理の流れ(図解)が出来ず、どんな処理の流れをしているのかまったく理解不能)
等、所々このアプリ自体のライフサイクルで不明な点が出ています。
実際に動かしている間はどんな流れになっているのか図解で来ませんか?
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月10日(月) 15:51
by LL
Cみたいに敵のオブジェクトごとにプレイヤーのポインタを持たせて、そこから情報にアクセスしたり、書きかえれたら一番いいんだろうが、そんな機能javaにはないし、どうやって各オブジェクトがそれぞれの情報にアクセスし、書き換えられるのか・・・
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月10日(月) 17:50
by hide
Cみたいに敵のオブジェクトごとにプレイヤーのポインタを持たせて、そこから情報にアクセスしたり、書きかえれたら一番いいんだろうが、そんな機能javaにはないし、どうやって各オブジェクトがそれぞれの情報にアクセスし、書き換えられるのか・・・
参照をもてば同じことです。
ただ、Cであろうとjavaであろうと敵オブジェクトやプレイヤーオブジェクトのような横のつながりを
ポインタなどで直接いじるのはあまりいいやり方では無いと思います。
後もう一つあるのですが、GameSurfaceViewのThread(スレッド)の処理の意味が分かりません。
Threadクラスはrunnnableインタフェースを実装したクラスのオブジェクトを受け取り、
そのクラスのrunメソッドを新しいスレッドで実行します。
通常のアプリケーションでは勝手に画面が更新されることはあまりない(タッチなどに反応して更新されることが多い)ので
ゲームをつくるならなにもユーザが操作しなくとも更新される処理を自分で実装する必要があるのです。
しかし、コンストラクタがいつまでたっても終わらないのでは困るので、別スレッドになっています。
オフトピック
ちなみに確かそこの記事のonDrawメソッドは今の環境だと警告が出たように思うので気をつけてください
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月10日(月) 23:21
by Dixq (管理人)
特定のオブジェクトの情報を取得したいのならそのクラスにインターフェイスを作り、実装すればよいです。
例えばPlayerクラスが持っているprivateなHPを外から取得する例です。
/* Main.java */
コード:
public class Main {
public static void main(String[] args) {
Player player = new Player();
IHpGettable hpGettable = (IHpGettable)player;
System.out.println("Hp="+hpGettable.getHp());
}
}
/* IHpGettable.java */
コード:
public interface IHpGettable {
public int getHp();
}
/* Player.java */
コード:
public class Player implements IHpGettable {
private int _hp = 100;
@Override
public int getHp() {
return _hp;
}
}
Playerのオブジェクトを渡す必要は無く、例えば敵オブジェクトにはプレイヤーのIHpGettableにキャストしたインスタンスを渡します。
セットも同様にメソッドを返します。
情報の取得やセットが必要なオブジェクトには必要なインターフェイスを渡しましょう。
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月11日(火) 10:12
by LL
Dixq (管理人) さんが書きました:特定のオブジェクトの情報を取得したいのならそのクラスにインターフェイスを作り、実装すればよいです。
情報の取得やセットが必要なオブジェクトには必要なインターフェイスを渡しましょう。
つまり、これはアクセサを用いて、各オブジェクトのメンバ変数を直接[ mPlayer..mLife = 100;]みたいに直接いじらないようにすればいいということですか?
ということは、ここのオブジェクト同士のつながりに関わる当たり判定及び、それに伴う各オブジェクトのパラメーター変更はGameMgrで行うことを推奨するということでしょうか?
Cでの話ですが、今までは各キャラクタオブジェクトに関わりのあるオブジェクトのアドレス情報を保持させ、その各オブジェクト内の更新(player.update()やenemy.update())で当たり判定及び、それに伴う
パラメータの変更を行っていたので、まったくの外部で当たり判定やオブジェクトのパラメータ変更とかまったく想像がつきませんでした。
ここからは個人差になると思いますがやはり、当たり判定やそれに関わる別オブジェクトのパラメーター変更([攻撃]が当たったからHPの減少等)
はそれぞれのオブジェクトの中(外部からそのオブジェクトの情報を取得して)で更新した方がいいのか、
先ほど上記やAndroidの館の様に全く別の場所(GameMgrのような全体を一括するような箇所)で行ったほうがいいのかどっちでしょうか?
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月11日(火) 16:12
by softya(ソフト屋)
LL さんが書きました:ここからは個人差になると思いますがやはり、当たり判定やそれに関わる別オブジェクトのパラメーター変更([攻撃]が当たったからHPの減少等)
はそれぞれのオブジェクトの中(外部からそのオブジェクトの情報を取得して)で更新した方がいいのか、
先ほど上記やAndroidの館の様に全く別の場所(GameMgrのような全体を一括するような箇所)で行ったほうがいいのかどっちでしょうか?
オブジェクトは知らなくて済む情報はなるべく持た無いことが重要だと思います。
もし必要でも、神的なすべてを知っているオブジェクトと知らないで済む人間的オブジェクトに分けて知らないものには徹底して情報を渡さないことが派生的に修正を生み出さないコツだと思います。
Re: [質問]Androidの館で掲載されているプログラムについて。
Posted: 2014年11月19日(水) 11:35
by LL
返信が送れてしまい申し訳ございません。結論を出し、コードとして形にするまで返答出来ませんでした。
softya(ソフト屋) さんが書きました:
オブジェクトは知らなくて済む情報はなるべく持た無いことが重要だと思います。
もし必要でも、神的なすべてを知っているオブジェクトと知らないで済む人間的オブジェクトに分けて知らないものには徹底して情報を渡さないことが派生的に修正を生み出さないコツだと思います。
コードの保守性を考えると、余分な情報は一切排除した方がいいのは分かります。
後に立てたトピックの事になりますが、あまり余分な情報を持たせたくない、渡したくないという気持ちの反面、余分な情報を持たせないと目的の動作を達成出来ないと言うどつぼにハマってしまいました。
http://dixq.net/forum/viewtopic.php?f=3&t=15992
上のトピックで載せたコードではGameMgr.classでインテントやデータの保存機能(openFileInputやopenFileOutput)を使うのに結局MainActivityのContextを保持させることになりましたし、(最初は不要かと思っていましたが結局情報の保存の為に使うことになりました・・・あまり外部の外部に連続して情報を投げるのも汚いgoto文みたいで気持ち悪かったですし。(最初はGameStatusを元にGameSurfaceView側で保存させようか迷いました。この時の思考はひたすら外部でデータを受け取らせて処理するか、ひたすら内部に動作に必要な情報を渡して内部で処理させるかと言う究極の2択状態に陥ってました。))これはもう経験で感じていくしかないんだろうなと悟りました・・・説明下手で申し訳ございません。
今考えると無理やり内部クラスでprivateメソッドを作るのではなく、独立した外部クラスでContextを渡して処理するようなものを作っても良かったのではないかとどんどん深みにハマってました。
それこそsoftyaさんのおっしゃる神的なすべてを知っているオブジェクトのことを指しているのかと思っています。
これ以上は変な深みにハマり、余計に目的が見えなくなりそうなので一旦解決としてトピックを区切らせていただきます。
淡い考えで書いてみた神クラス。
コード:
//すべてから独立した神クラス(こんな感じかなぁ・・・)
class goIsGod{
public static void dataSave(Context contex, String filename,Object data){
FileOutputStream fos = null;
ObjectOutputStream objFos = null;
try{
fos = mContext.openFileOutput("testapi.txt", Context.MODE_PRIVATE);
objFos = new ObjectOutputStream(fos);
objFos.writeObject(data);
fos.close();
objFos.close();
return true;
}catch(IOException e){
e.printStackTrace();
Log.e("FileInput","ファイルの書き込みに失敗。");
return false;
}
}
}
一通り組終えた後に『あの時あの様に組めば良かった』と後悔するとは・・・