トップページgamedev
191コメント74KB

【JAVA】2Dアクションゲームを作る【初級】

■ このスレッドは過去ログ倉庫に格納されています
0001ヤンス04/09/08 09:17ID:Qk2n0ep6
JAVAアプレットでファミコンのゲームにありそうな2Dアクション物を作ろうと思い
二ヶ月くらい前から勉強を始めて最近やっと、ショボイながらも記念すべき
人生初の自作ゲームを作って今、第二作目を作っている所なのですが、やり方の
分からない処理が多すぎて困っております。
勿論ネットや本等で調べまわった上でスレを立てました、何でこんな処理が
分からないんだよと思われるでしょうけれど指導の方お願いします。
上級者の方達と質問のやり取りをしたいのです。

当面の目標は倉庫番、ロードランナー、ドンキーコング等の1画面固定タイプの
やつを作ろうと思います、とりあえず現段階で二次元配列を使っての
マップと自機の表示まで出来てます、二次元配列を使って表示した
マップの壁などに、どうやって当たり判定を付けるかで躓いてます
当たり判定の付け方の考え方など教えて貰えたら、ありがたいです。

ちょっと爪垢が溜まってきたので、また後ほど書きたいと思います。
0141名前は開発中のものです。2008/10/05(日) 22:48:03ID:B28yXkKi
アプレットとかJWSとかでJOGLやるやつってdll類はどうしてんの?
全部署名つけてオレオレ証明書でダイアログ出す?
それでユーザに「危ないってダイアログ出すけど信用してOK押して」って言うわけ?
0142名前は開発中のものです。2008/10/05(日) 22:55:31ID:Za20XjLJ
Sunの署名付きのjar(DLL入り)が配布されてるのでそれを使う
0143名前は開発中のものです。2009/02/21(土) 10:06:43ID:rhB09fqh

if(isJump == false && jumpKey == ture) { // ジャンプ中でなく、ジャンプキーが押されたら
isJump = true; // ジャンプ中にする
vy = -jumpSpeed; // ジャンプスピード(初速)
}

vy += gravity; // 重力をかける

----------------------------------------

横スクロール(マリオ型)アクションゲームで、上記みたいにジャンプを実装している場合、
「ジャンプキーが押された時間が短い場合は小ジャンプにする」
という風にするには根本的にプログラムを変更しないといけないですか?
0144名前は開発中のものです。2009/02/21(土) 10:44:45ID:Wn6D0K7q
物理的にはおかしいけど空中でもボタンが押されてたら上向きにちょっと加速度与えればいいだけ
実際マリオはそうだろ
01451432009/02/23(月) 19:48:11ID:8ReVmxnp
>>144
マリオはそうなんですか、知りませんでした。
それでやってみます、ありがとうございました。
0146名前は開発中のものです。2009/03/04(水) 20:49:06ID:BgNcpKU6
>>51
(´・ω・`)ショボーン
http://imepita.jp/20090124/089930
0147名前は開発中のものです。2009/03/22(日) 07:24:47ID:O3SVwcBu
JOGLのGLCanvasで自前ループ内display()させてるとどうもちらつく
別スレッドでAnimator使ったりしないとまずいのだろうか
垂直同期との明示化がわからん(環境によって自動的にできたりできなかったり?)
0148名前は開発中のものです。2009/03/22(日) 12:09:18ID:t26wnkyW
displayってコールバックだから自分で呼ばないほうがええんじゃ
0149名前は開発中のものです。2009/03/23(月) 20:58:13ID:UqizvfMn
というか、それで例外吐かないんだ。
JOGL使いは占めのころは、OpenGL系のAPIを別スレッドからアクセスしたら
いきなり例外吐いてびっくりしたものだが。
0150名前は開発中のものです。2009/03/23(月) 21:25:56ID:uzXOwN2A
TextureIOの初期読み取りロジックを別に抜き出した時は別スレッド扱いの例外吐かれて困まった。
一本道のつもりだったのだけどイベントリスナスレッドとかが影響してるのか。
0151名前は開発中のものです。2009/03/23(月) 22:17:05ID:dbyr6AlE
>>150
自分はTextureIOのnewTextureがコンテクスト依存と思っていなくて
半泣きになったことがある。
enableとかbindをしなければ、別スレッドから呼んでも大丈夫だろうと
思っていたんだよなあ…

結局、テクスチャ登録は絵だけ準備してフラグを立てて、
displayメソッドの中からフラグをチェックしてテクスチャオブジェクトを生成するという
めんどうな動きになった。
01521502009/03/23(月) 22:38:48ID:uzXOwN2A
>>151

同じ症状だったと思う。とった解決策も同じだ(w
もうちょい綺麗に書くイデオムみたいのはあるのかな。
01531512009/03/23(月) 23:00:18ID:ZB3pm8mv
>>152
仲間がいたようなのでついでに聞いてみる。

テクスチャオブジェクトのガベージコレクションってどうしてる?
ファイナライザにdisableを仕込みたいところだけど、
ファイナライザはGLAutoDrawableとは別スレッドから呼ばれるだろうから、
同じ理由で例外吐いて死にそうな気がする。

自分の場合、これはまだ解決してない。
オブジェクトが破棄されるたびにVRAMにゴミが残るわけで、
どうしたものかと思っているんだが…

やっぱり、ゲームエンジン側で管理すべきなのかな。
テクスチャオブジェクトの管理用コレクションとモデルオブジェクト管理用コレクションを見比べて、
「そのテクスチャを利用しているモデルオブジェクトがもはや存在しない」
となった時点で明示的にdisableをかけて、それからremoveする、と。
0154名前は開発中のものです。2009/03/23(月) 23:22:49ID:uzXOwN2A
>>153
シーン中にインテリジェントに捨てる事に関してはオブジェクトに関してもテクスチャに関しても考えてないや
シーン中は(理論上)無限にプーリングしてシーン終了時の後始末でシーンコンテキストのテクスチャを全disable & 削除っていう方針
テクスチャ画像の重複登録をしないのは当然として、そこまで多種の画像を読み込む事を想定していないってのが正直な所
01551512009/03/23(月) 23:27:33ID:ZB3pm8mv
>>154
なるほど。その辺は割り切っちゃうという手もあるな。
自分のゲームエンジンでもテクスチャは共用されるから、
確かに、さほど厳密に管理しなくともVRAMを圧迫しない気はする。

考えてみれば、256x256x32bitなら、たかだか256KBだからなあ。
01561542009/04/02(木) 19:49:00ID:rnxHGA2h
過疎っているなぁ。
基本的な方針は同じだけどdisableに関してはテクスチャを使うときに
enable → bind → 表示 → disableを毎回するように変えた。
やっぱりカレントスレッド問題が色々と面倒くさいので。
0157名前は開発中のものです。2009/04/09(木) 01:21:53ID:QVY5xGft
>>156
総合スレとの区別があいまいだしねえ…

ちなみに、enableしてないテクスチャオブジェクトをdisableすると例外吐くんだっけ?
これを受け付けてくれるなら、いきなりdisableしてもいいような気がする。

逆に、enableを多重にやると、VRAMに同じテクスチャイメージが多重登録されたりしそうで心配だが、
取り越し苦労だろうか。
0158名前は開発中のものです。2009/04/14(火) 17:40:52ID:Wx3DB5EW
>>144
すげえあたまいい・・・と感動してしまった
0159名前は開発中のものです。2009/05/14(木) 21:04:29ID:jnlC9FY/
>>146
     オハヨー!!
    ∧∧ ∩
    (`・ω・)/
   ⊂  ノ
    (つノ
     (ノ
 ___/(___
/  (___/
 ̄ ̄ ̄ ̄ ̄ ̄
0160名前は開発中のものです。2009/11/04(水) 00:17:42ID:mdwZ7HUY
アニメーションの表示ってどうやってます?
俺はコンピュータ内蔵の時計呼び出してその値からやってるんだけど、
そうするとポーズ画面のあと再開したときにアニメーションがずれちゃうんだよ
どうしたらいいかな
0161名前は開発中のものです。2009/11/04(水) 10:26:18ID:MgRdkNpl
経過時間を算出するようにして
ポーズ中は経過時間が増えないようにするとか
0162名前は開発中のものです。2009/11/04(水) 21:22:33ID:OEwandvL
ゲームのはなしじゃないの?
フレーム単位で処理するからずれるとかはないとおもうけど

可変フレームのはなし?
0163名前は開発中のものです。2009/11/04(水) 21:46:58ID:wmTV4PxT
可変フレームでもアニメのコマnからn+1へ描画させるタイミングをフレームを考慮した時間後に書き換えるからずれはしない。
何か忘れてる。
0164名前は開発中のものです。2010/03/02(火) 23:08:25ID:Ex3WWwU3
test
0165名前は開発中のものです。2010/05/07(金) 20:42:20ID:WillkCAw
javaはpng画像の表示は重いですか?
マリオ風をつくってるんですがgifで表示させてた時よりカクカクします。
フルカラー+透過を実現したくてpngにしたんですが…。
0166名前は開発中のものです。2010/05/07(金) 21:15:05ID:j/r3kS3U
ソフトウェア描画だからな
それでなくても透過合成は重い部類だし
0167名前は開発中のものです。2010/05/07(金) 23:37:10ID:KEJO6T7M
αブレンディング使ってるならハードウェアアクセラレーションがきいていても使っていないときよりは速度は落ちる
スペックにもよるが32*32のスプライト10万個くらいだすと60fps維持できないと思う
0168名前は開発中のものです。2010/05/08(土) 20:58:02ID:2Mve6/zz
アルファチャンネルじゃなくて、普通の透過なんですけどね…。
別の方法試してみようと思います。ありがとうございました。
0169名前は開発中のものです。2010/05/08(土) 22:13:03ID:+nu9nO6K
ならコードが悪いだけだな
01701682010/05/09(日) 01:02:49ID:f5Ph/Aqm
>>169
drawImageでダブルバッファリングしながら表示させてます。
1000*1000くらいの大きな画像に24*24くらいのマップチップやキャラチップを並べて、
drawImage(img, x1, y1, x2, y2, imgX1, imgY1, imgX2, imgY2, observer);
でimgX1〜imgY2を指定してチップを表示してるんですが、もしかして各チップを
一つずつのファイルに分けた方が高速ですかね?それともdrawImage使うのがそもそもダメですか?;;
0171名前は開発中のものです。2010/05/09(日) 10:10:47ID:Pu1jTf/z
転送元と転送先のImageはなに?
あとJavaはJavaSE6update10以上つかってる?
01721682010/05/09(日) 16:51:18ID:f5Ph/Aqm
転送元と転送先のImageというのは、描画する画像の型と描画先の画像の型という意味でいいですか?
一応Image型をBufferedImage型に描画してます。
転送元がImage型だからカクカクするのかなと思ってBufferedImage型→BufferedImage型も試してみましたが
あまり改善されませんでした。
JavaバージョンはJavaSE6update18です。
0173名前は開発中のものです。2010/05/09(日) 21:02:07ID:Pu1jTf/z
転送元がImageということはどういうフォーマットになっているかわからないってことかな。

描画バッファから画面への転送の方法とかどうしているかも気になる。

あとはピクセルフォーマットを同設定しているかか。

転送もとのフォーマット
描画バッファのフォーマット
画面のフォーマット

これらをどう設定しているかにもよる。

あとImageの分割もやってみた?32bppだと1000*1000で4MBも食うわけで。
0174名前は開発中のものです。2010/05/09(日) 21:14:11ID:o2jE/Yfm
もうハードウェアアクセラレーションが効く環境に変えちゃえばいいのに
アホみたいに速いよw
0175名前は開発中のものです。2010/05/09(日) 22:56:26ID:eCAtLDK5
>>168
カラーが24bitなら透過は8bitになってると思うよ
そして全ての透過値が0xffか0x00しかなくても、8bitのアルファチャネルがあるのと同様のロジックが走る
アクセラレーションが効いてなければ結構描画効率は落ちる

マリオみたいなゲームなら1チップに255色以上使う必要性も少ないだろうし、
リソース合成時かゲーム起動時に減色して透過インデックスを指定するようにしたらどうかな
01761682010/05/10(月) 01:29:54ID:CH9wxDuw
皆さんありがとうございます。
http://javagame.skr.jp/index.php?%A5%A2%A5%AF%A5%C6%A5%A3%A5%D6%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0
に書いてある、repaint()を使わないで描画する方法(アクティブレンダリング)というのをやってみたら大分カクカクが収まりました。

>>173
すいません、勉強不足で仰られていることの意味がわからないんでコード晒します。
>>168からいろいろ変えてみて、今現在、

Image img = Toolkit.getDefaultToolkit().getImage(getClass().getResource(filename));
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(img, 0);

try {
tracker.waitForID(0);
} catch (InterruptedException e) {
e.printStackTrace();
}

BufferedImage bimg= new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = bimg.createGraphics();
g.drawImage(img,0,0,null);

でpng画像をbimgに読み込んだ後、drawImageでオフスクリーンバッファに描画してます。
画面への転送方法は先程も書きましたがrepaint()を使わない方法に変えてみました。

あと、画像を最初にBufferedImageで読み込んでいても、チップは分割しておいたほうがいいですか?

>>174 すいません、軽く調べましたがなんか難しそうなので諦めます。
>>175 そうなんですか。うーん、どうしてもフルカラーでいきたいんですよね…。無理そうならgifに戻すことにします。
0177名前は開発中のものです。2010/05/10(月) 22:09:49ID:rdBA97qw
画像のロードは遅延読み込みやりたいわけじゃないならImageIOつかうとよいよ。転送待ちをする必要ないし。

あとABGRとかARGBとか順番によって大きく速度が変わるからピクセルフォーマットは意識したほうがよい。

転送先はVRAM、もしくはコンパチブルピクセルフォーマットのほうがいいよ。
そして転送元もあわせたほうがよい場合が多い。

あとは特定色の透過をしたい場合TransparencyがBITMASKになってると大概早いはず。
0178名前は開発中のものです。2010/05/11(火) 10:35:00ID:RB0dCl6F
初級って書いてあるから開いてみたけど
話が難しすぎてさっぱりわからないwww
ダメだ俺orz
0179アジェグ4倍 ◆4xAJeG.COM 2010/12/27(月) 17:55:37ID:tvzx1ncl
BufferStrategy クラスがこのスレでは出てこないねぇ。
いまどきはこれが必須と言われている。
0180名前は開発中のものです。2011/08/09(火) 10:57:03.78ID:B85eOPiC
画像を描画するときに回転させるのではなく、
あらかじめ画像を1度ずつ回転させたImageオブジェクトの配列を作成するにはどうしたらいいですか?
今のところGraphics2Dのrotate()で描画先のGraphicsを回転させているのですが、無駄が多いような気がしまして・・・
0181名前は開発中のものです。2012/03/05(月) 23:18:01.39ID:S6tKV2yC
>>180
回転済みのBufferedImageの用意すると
描写時にグラフィックメモリが大量に必要になるから
回転済みの用意しない方がいいと思うよ
1回描写すればキャッシュで速くなるし
回転もグラボ使うから遅くならない
0182名前は開発中のものです。2012/03/05(月) 23:22:53.23ID:S6tKV2yC
>>179
ダブルバッファだったら
Swingが自動的にやってくれているから
意識しなくていいと思う
0183名前は開発中のものです。2012/05/11(金) 14:13:36.56ID:K3ACPeVc
斜めに動かす場合なんですけど例えば 1.4,-1 で動かす場合
固定少数で14として扱う方法は知っていますが
ビットシフトでやる場合どうやってやるのか知りたいです
1.4<<7 で 179.2だから 179として扱えばどうかと思っているところです
精度的に3桁あっても厳しいでしょうか?
0184名前は開発中のものです。2012/05/11(金) 23:32:16.98ID:dAZRIFlQ
固定少数で14として扱うじゃなくて、1.4を整数で扱いたいから14なんじゃないの?
でこの場合10倍してるど、ビットシフトなら2の乗数倍するだけだから考え方は同じだね。
精度的な話は自分がほしい精度なんで厳しいかどうかの基準がわからん。
0185名前は開発中のものです。2012/05/13(日) 11:09:53.39ID:52g24kKa
1を65536で扱うのが固定少数でしたかね
それなら1.4はだいたい91750だからこの数値で扱えばいいんだろうか
面倒だから10倍でやるほうがよさそうですね
0186名前は開発中ものです。2012/05/13(日) 22:10:38.79ID:nrwURmq8
このスレ結構まとも(笑)
0187名前は開発中のものです。2012/05/14(月) 17:57:49.15ID:v4rkIglG
全角スペースを半角に置換して下さい

public class DebugFrameResizeMouse {
  private JFrame frame = null;
  public static void main(String[] args){ new DebugFrameResizeMouse().runApp(); }  
  public class EnableMouseResizeAction extends AbstractAction {
    public EnableMouseResizeAction(){ this.putValue(NAME, "Enable Mouse Resize"); }
    public void actionPerformed(ActionEvent arg0) { frame.setResizable(true); }
  }
  public class DisableMouseResizeAction extends AbstractAction {
    public DisableMouseResizeAction(){ this.putValue(NAME, "Disable Mouse Resize"); }
    public void actionPerformed(ActionEvent arg0) { frame.setResizable(false); }
  }
  private JMenu createMouseMenu(){
    JMenu m = new JMenu("Mouse");
    m.add(new JMenuItem(new EnableMouseResizeAction()));
    m.add(new JMenuItem(new DisableMouseResizeAction()));
    return m;
  }
  public void runApp(){
    frame = new JFrame("Test");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setPreferredSize(new Dimension(640,480));    
    JMenuBar mbar = new JMenuBar();
    mbar.add(this.createMouseMenu());
    frame.setJMenuBar(mbar);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
01881872012/05/14(月) 18:00:07.71ID:v4rkIglG
当方の環境は、windows 7、Java SE 1.6 update 32 です

setResizable のオンオフでウィンドウの大きさが
変わってしまうのですがどういう理由だと思いますか

動作はこれでいいのでしょうか
0189名前は開発中のものです。2012/05/18(金) 05:00:51.09ID:Zf//QytW
frame.pack();によってウィンドウのサイズを出来るだけ小さくなる(最適化する)ように指定してるからじゃない?
サイズ変更の可能/不可にかかわらずウィンドウの内側のサイズは一定+サイズ変更禁止用の細いウィンドウ枠
の全体としては小さくなったんだと思うよ

サイズ変わるの嫌ならsetSizeで解決すると思う
0190名前は開発中のものです。2012/05/18(金) 17:05:18.99ID:1wIe6pNo
インセットが変わるみたいでした。

public void actionPerformed(ActionEvent arg0) {
    frame.setResizable(true);
    frame.pack();
    System.out.println("Resizable");
    System.out.println(frame.getSize());
    System.out.println(frame.getInsets());
}

Nonresizable
java.awt.Dimension[width=640,height=480]
java.awt.Insets[top=25,left=3,bottom=3,right=3]

Resizable
java.awt.Dimension[width=640,height=480]
java.awt.Insets[top=30,left=8,bottom=8,right=8]
0191名前は開発中のものです。2012/12/12(水) 15:41:49.52ID:5f65KrKy
俺も素直にBufferStrategy使ったほうが良い気がする
■ このスレッドは過去ログ倉庫に格納されています