Javaで作るスタンドアローンゲーム

■ このスレッドは過去ログ倉庫に格納されています
1名前は開発中のものです。
垢版 |
2012/12/27(木) 16:04:18.62ID:rl+qGRHn
スレタイはアプレットとの対比的な意味と考えてください。
Javaでのゲーム開発は賛否ありますが、国外では割と盛んになってきているように思います。
裏を返せば日本語だけでは情報が得辛い状況であり、寂しく開発してる人が多いのでは・・・。

関連スレ
JAVAアプリでゲーム
http://toro.2ch.net/test/read.cgi/gamedev/1033926010/


参考になりそうなサイト
・どのイメージタイプを使うべき?
http://weblogs.java.net/blog/chet/archive/2004/08/toolkitbuffered.html
・弱点と言われる?ベクタグラフィックス関連の改善
http://docs.oracle.com/javase/1.5.0/docs/guide/2d/flags.html
・大量のソースコードを公開して下さっている国内サイト
http://aidiary.hatenablog.com/entry/20040918/1251373370
・Java 2D games tutorial
http://zetcode.com/tutorials/javagamestutorial/
・出入りが最も盛んな?フォーラム
http://www.java-gaming.org/index.php
・スプライトシートの切り方等(国内)
http://sky.geocities.jp/kmaedam/java2/java2.htm

動画
3D Game Programming tutorial
http://www.youtube.com/watch?v=iH1xpfOBN6M
2014/11/22(土) 05:43:04.14ID:YsbIPryz
自分も同じような段階なので非常に興味があります
僕の場合は通信にはプロトコルを定めて4バイト以下でやり取りしているので、オブジェクトの送受信は今ちょっと調べただけですが……

ハッキリとは分かりませんが、ObjectOutputStream自体がブロッキングするioなんじゃないでしょうか?

調べてみたところ以下の実装が綺麗な気がします
http://stackoverflow.com/questions/5862971/java-readobject-with-nio
ByteArrayOutputStreamでラップしてデータの長さを調べて、さらにByteBufferでラップして先頭に長さを埋め込んでおきます

受け取る側ではまず先頭の長さ情報(4バイト)を読み込みます
続いて長さ分確保したbufferに本体を読み込み、あとは逆順にObjectInputStreamに落とし込みます

僕も簡単なフレームワークがあったらなあとも思いますが、お互い頑張りましょう
2014/11/22(土) 13:31:16.69ID:fUGuXT+m
通信用スレッド作ってブロッキングでやれば簡単だと思うよ
ノンブロッキング化なんて後からやればいいじゃない
2014/11/22(土) 16:49:26.43ID:GtITkLZ+
TCPではなくUDPで通信するのは俺もわからんし興味はある

データを受け取った側が一々受け取り成功したことを発信側に返信していたら
遅いTCPと実質同じになってしまうとか、注意点ふぁありそうな気がするけど
この辺は言語問わず情報がなさすぎて困る
2014/11/22(土) 23:47:22.91ID:fUGuXT+m
UDPの主な問題点は、パケットの到着が保証されない(途中で消えることがある)、順序が保証されない(前後が入れ替わることがある)の2点
どうにかこれに対処しないといけないが、だからといってこれを完全に保証するのなら、素直にTCPを使った方がいいわけで、
UDPを使うなら、パケットが消えたり入れ替わったりすることを前提に、最初からそれを受け入れる方針で設計しないと意味が薄い
一部重要な情報だけ到着確認や再送信など手厚い保証を作り込むという選択肢もあるが、TCPと併用し情報の重要度によって送信し分けるという選択肢もある

俺が作ったときは、通常はTCPを使い、性能的な懸念のある一部の情報だけUDPで送るようにした
念のため、UDPがちゃんと届くか送信テストを行い(返事はTCPで貰う)、だめだったときは全部TCPで動くようにした
特定のメッセージをUDPで送るかTCPで送るかはbooleanの引数1個で簡単に変更できた
2014/11/23(日) 00:38:44.67ID:UddT0/lz
>>353
 提示されたソースを参照しながら色々と試しております。
 とりあえずシンプルチャットの文字列のマルチキャストはできましたが、インスタンスのやり取りはまだうまく行っていません。

 ObjectOutputStreamについては仰るとおり、ブロッキングが発生するストリームです。
 ブロッキングを回避するためにマルチスレッドにして、受信したメッセージとインスタンスをプールして一元的に処理しようとして・・・
などとやっているうちにデッドロックが発生して頭を抱えておりました。

 Webアプリケーションフレームワークでもそうであるように、通信部分はほぼ共通の処理だろうし、
C/S型MOGの実装とて大きな違いがあるとは思えないのですが、ないものですかね・・・

 一応、Jogreとか言うゲームエンジンがC/S型を想定したものらしいのですが、使い方がまるで判らず
オープンソースだからせめてどこか参考にできないかと見てみましたが私の頭では理解できませんでした。

>>354
 ゲームの根幹となるシステムはサーバ側で実装しようと考えており、その際にクライアントの通信待ちでブロックされてしまうと処理が進まなくなってしまうので、初めからノンブロッキングで行くつもりです。
 前述の通りマルチスレッド化の段階でうまく行かなくなってしまいました。

>>355
 通信方式には特にこだわっているわけではないのですが、今後内輪で一人複数キャラ起動で20〜100程の同時接続を想定しており、
そうなると今後はUDPでないとまずいのかな、などと漠然と考えておりますが、実装が楽なはずのTCPですら躓いている状態です。
2014/11/23(日) 02:19:06.05ID:Y/h3FQGO
ブロッキングの場合は通信相手1人ごとに受信用スレッド1個と送信用スレッド1個を作って、それに通信処理を全部まかせるのがいい
相手側に何があってもブロックするのはそこだけで済む
何か送信したいときは、その相手用の送信キューに情報を詰め込んで、送信スレッドに送信してもらう
受信の方はそのまま受信スレッド上で処理してもいいが、スレッド間の同期が心配なら、受信した情報をメインスレッドの処理キューに積んでメインスレッドに処理してもらってもいい
もちろん各キュー自身は同期しなければならないが、LinkedBlockingQueueでも使っとけば心配なかろう
欠点は通信相手が増えすぎるとスレッドが増えすぎることだが、まぁ100くらいは大丈夫じゃない?

ノンブロッキングの場合は一箇所で全ソケットの送受信の面倒を見ることになる
基本的には Selector#select を回し続け、個々のソケットがそれぞれ受信可能になっていれば受信し送信可能になっていれば送信するわけだが、
受信したいときに受信したい量が受信できるとは限らないし、送信したいときに送信したい量が送信できるとも限らないので、
ブロックさせずに1スレッドですべてを回すためには送受信共にバッファ管理が必要になる
相手に何か送信したいときは、その相手用の送信バッファにデータを詰め込んでselectのループに戻り、
ソケットが送信可能な状態になったときに送信できる量ずつ送信する(そしてまたselectのループに戻る)
受信の方も、必要な量のデータが受信バッファに溜まるまでselectのループを回しておき、
じゅうぶん溜まったら受信バッファから必要量のデータを取り出して処理する感じ?
通信相手が増えてもスレッド数を抑えられるのが利点だが、実装は面倒い
2014/11/23(日) 08:51:36.48ID:2oDwsjHs
Java信者がまだ生き残っていて嬉しい
360348
垢版 |
2014/11/24(月) 01:33:12.16ID:sj/Z1D1w
今日一日がんばってはみたがやはり実装できず。
シンプルチャットは動いたものの、画像を含めたバイナリデータのやり取りはできておらず、
何故か353で提示していただいたコード部分でOutOfMemoryErrorが発生する始末。
使わなくなった瞬間に明示的にnullを入れてみたりはしたものの、全く解決せずで、
相変わらず手に負えない感じがあります。

今度はブロッキングのマルチスレッドを試してみようとは思いますが、以前この方法を取った際、
キューの中に受け取ったメッセージを格納しておき、メインスレッドで順番に処理する、
というようなコードを書いてみたところ、キューへのアクセスで何故かデッドロックが発生して
動作しなくなってしまったこともあり、うまく行くようにできるか心配です。
また、なんだか最終的に数千人規模の運営にも耐えられるようなもの(MMOみたいなものか)
みたいな要望(若干語弊がありますが)もあり、スレッドの数とか心配ですが。
2014/11/24(月) 12:33:21.54ID:qbg8eFAd
どうしても上手くいかないならソース晒せば添削しよう
そのときはzipにまとめて適当なところにupしてくれ
362348
垢版 |
2014/11/24(月) 23:57:10.52ID:sj/Z1D1w
ブロッキングのマルチスレッドを試していた所、
今度はループ上で2度目のObjectInputStraemのreadObjectメソッドで
StreamCorruptedException: invalid type code: ACが発生し、
シンプルチャットすら動作しなくなりました。

ObjectIOストリームを使うこと自体が間違いなのかもしれませんが、
今後サーバ側のDBに保存してある画像ファイル等をクライアント側に送信して表示することを考えると、
他にどうすべきかが判りませんが。

一応ソースを挙げてみました。
http://fileup.jp/up/4753.zip.htm
363名前は開発中のものです。
垢版 |
2014/11/25(火) 01:54:43.35ID:5bX3A50t
 
お世話になります。
私、責任者の加茂と申します。以後、宜しくお願い致します。
http://www.apamanshop.com/membersite/27009206/images/kamo.jpg
浪速建設様の見解と致しましては、メールによる対応に関しましては
受付しないということで、当初より返信を行っていないようで、今後につい
てもメールや書面での対応は致しかねるというお答えでした。
http://www.o-naniwa.com/index.html 事務員 東条 南野
http://www.o-naniwa.com/company/
このように現在まで6通のメールを送られたとのことですが、結果一度も
返信がないとう状況になっています。
http://www.apamanshop-hd.co.jp/
http://www.data-max.co.jp/2010/10/01/post_11983.html
私どものほうでも現在までのメール履歴は随時削除を致しております
ので実際に11通のメールを頂戴しているか不明なところであります。
  
・ハンガー・ゲーム   http://s-at-e.net/scurl/TheHungerGames-Aircraft.html
・アバター        http://s-at-e.net/scurl/Avatar-Shuttle.html
 
・艦これ   http://s-at-e.net/scurl/KanColle.html
・BRS     http://s-at-e.net/scurl/BRS.html
・ベヨネッタ http://s-at-e.net/scurl/BAYONETTA.html
・風ノ旅ビト http://s-at-e.net/scurl/JOURNEY.html
 
      http://s-at-e.net/scurl/kabetokyojinto.html
 
・2012    http://s-at-e.net/scurl/2012.html
 
大阪府八尾市上之島町南 4-11 クリスタル通り2番館203
に入居の引きこもりニートから長期にわたる執拗な嫌がらせを受けています。
この入居者かその家族、親類などについてご存知の方はお知らせ下さい。
hnps203@gmail.com
2014/11/25(火) 03:27:39.50ID:elCn5ht8
マルチスレッドにだけは手を出すな、というのが定説だよ

なぜならタイミングによって、
デッドロックになったりならなかったりして、
バグが再現できず、まともにテストができない

結局、バグが出ても、気のせいにしてリリースするので、
本番でバグが出て、どうにもならない

マルチスレッドはスレッド間で、リソースを共有するから、
共有リソースを使うすべての関数で、排他処理が必要

それでも資源A→B、B→Aの順で、
ロックするスレッドがあると、デッドロックが生じるため、
資源をロックする順番にも、矛盾があってはならない
2014/11/25(火) 08:05:46.97ID:6uceNdu9
コンカレント・パッケージを使ったら?
2014/11/25(火) 08:11:55.29ID:mNAq4UK+
ソース見た。
エラーの原因は、サーバ側では送信のたびにObjectOutputStreamを作り直してるのに、クライアント側では同じObjectInputStreamを使い続けていることだ。
作り直すなら両方とも作り直す(この場合resetは要らない)、使い続けるなら両方とも使い続ける。混ぜてはいけない。

あと、現時点では大丈夫かもしれないが、潜在的な問題がある。
受信がブロックするのは当然なので別スレッドにするのは自然だけど、実は送信もブロックするから別スレッドにした方がいいんだ。
TCPには一定サイズのバッファがあって、相手側が読み出してくれなければ、バッファが一杯になった時点でそれ以上書き込めなくなり、ブロックする。
相手側が読み出してるつもりでも、例えば何かネットワークのトラブルでデータが届かなくなれば、同じようになる。
サーバ側で synchronized (this.recvMessageQueue) { } の中で sendClients 呼んでその中で writeObject してるけど、こういうロックを握ったままブロックする可能性があるのは非常によくない。
受信キューを握ったままブロックすると受信スレッドがみんな動けなくなるし、そうなるといずれクライアントの送信側もバッファが一杯になってみんな止まってしまう。

あとは、 clientSocketList が複数のスレッドから読み書きされてるから synchronized するべき。
いちいち synchronized するのが面倒なら元からスレッドセーフな CopyOnWriteArrayList を使うという手もある。
キューも LinkedBlockingQueue とか使えば synchronized する必要なくなる。 まぁこのへんはどっちでもいいけど。

ObjectIOストリームは、性能面では劣るけど、開発は楽だから、使いたければそれでいいんじゃない。
他の方法といっても、ファイルと一緒で、フォーマットを決めて読み書きするだけだよ。
いわゆるType-Length-Value的なやり方が普通だと思うけど、例えば文字列化して行単位で送るとか、XML形式で送るという方法もなくはない。
こういうのは性能やらメンテナンス性やら開発速度やらのトレードオフだから、好みの方法を使えばいいと思うよ。
367348
垢版 |
2014/11/26(水) 18:49:10.33ID:yQ5yK0Ih
>>366
 添削ありがとうございます。とりあえず基本的な通信周りは動くようになりました。

 エラーの原因は結局の所Streamの基本的な利用方法を理解していなかったことであり大変お恥ずかしい限りです。

 受信以外に送信もスレッド化しなくてはならないとなると、1クライアント接続毎に2スレッド起動することになるのですね。
 100の接続があれば200、1000の接続があれば2000も起動するということで、今後仕様に耐えられるか心配ではあります。
 364の方が仰るようなバグの内包は自分はやらかしそうなので。

 こういったミスがなくなるよう、通信周りで信頼性の高い実装済みのフレームワークを利用したいと切に願います。

 ともあれ、ようやく動くようになりました。ありがとうございました。
2014/11/26(水) 20:44:59.58ID:EUSw3GAJ
心配なら簡単なテストプログラムを作って実際に高い負荷をかけてみるのもひとつの方法
大量のソケットを作って自分のサーバに接続しまくるとか
何か簡単なメッセージでもやり取りすればより実際の状況に近い
もう1台PCを用意してネットワーク越しに実験できればもっと良い

仮にフレームワークがあったとしても十中八九マルチスレッドだろうからその種の心配は無くならないんじゃないかな
このマルチコア時代に1コアしか活用できないとか汎用のフレームワークとしてはありえないだろう
何かプログラマの負担を多少なりとも軽くする仕組みはあるかもしれんけどね
2014/11/29(土) 01:20:26.07ID:X/DpHkls
教えてJava仙人!
2014/11/29(土) 22:21:48.97ID:tbWotyUc
こちらで聞いて良いものかどうか判りませんが、一応Javaも絡んでいるので質問。

プレイヤーキャラクターが装備を変えた時、見た目も変わる2Dの作品を作っています。
パーツごとに見た目が変わるため、頭部、胴体、下半身、右手、左手等に
パーツを分け、それぞれでアニメーションのスプライトを製作しています。

しかし、全体像が判らないとパーツの動きがわかりにくくて製作が大変面倒な上、
PGに起した時に正面を向いている場合には髪→顔の順に表示するが、
後ろを向いた場合には顔→髪のように順番を変えて表示をする必要があり、
全体像になったときにパーツの表示位置も調整しなければならず、
難しくはないが大変手間がかかって製作が難航しています。

複数のパーツの画像を組み合わせて全体像およびアニメーションを表示しつつ画像編集ができ、
且つ保存時にアニメーションのソースコード(位置情報や表示順序・java、できればLibGDXフレームワーク準拠の)
に自動的に起すようなツールは何かないでしょうか。

Unityに似たようなツール?があるようですが、言語がJavaではないので手を出していません。
Googleでも「画像編集 パーツ アニメーション 組み合わせ」などで探していますが、
望むような情報が得られていません。
2014/11/29(土) 22:32:26.42ID:bnooxQNY
一人称視点にしてプレイヤーキャラを表示しない
2014/11/30(日) 21:40:35.22ID:nwszzSQi
キャラクタークラスで制御すれば済むはなしじゃないの?
ツール、それもソース生成ツールなんて大げさなもの必要ないでしょ
2014/11/30(日) 21:43:40.21ID:n78F4afF
髪でサンドイッチして、片方透明にするだけだわな
374370
垢版 |
2014/12/01(月) 16:06:44.26ID:m/6pnraT
>>371
2Dの作品ですし、他キャラクターも同様にパーツの組み合わせで表示しているので、
全く解決になっていません。

>>372 373
前の書き込みどおり、難しくはないのですが手間がかかりすぎるので、
作業を楽にするためにツールを所望しています。
2014/12/01(月) 16:25:25.12ID:osWTP4D1
ツールをツクールべし
2014/12/02(火) 03:00:01.68ID:cSamQ6Ju
画像素材を規格化してピクセル単位の調整不要にするのが普通だと思う
377名前は開発中のものです。
垢版 |
2014/12/22(月) 20:19:34.55ID:CZQUzeXC
ゲームは一応動いてはいるのですが、
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at GameManager.MainPanel.paintComponent(MainPanel.java:127)
at javax.swing.JComponent.paint(JComponent.java:1053)
at javax.swing.JComponent.paintChildren(JComponent.java:886)
at javax.swing.JComponent.paint(JComponent.java:1062)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(JComponent.java:886)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5230)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1572)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1495)
at javax.swing.RepaintManager.paint(RepaintManager.java:1265).......

なエラーが2/5の頻度で発生します。
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, WIDTH, HEIGHT);

gsm.draw(g2d); ココが(MainPanel.java:127)
}
gsmはちゃんとインスタンス化してあります。

原因究明の為調べていた所、スレッドの非同期が問題なのかな?と思い、
//enableEvents(AWTEvent.KEY_EVENT_MASK); を無効化しましたが解決には至りませんでした。

エラーが発生してもゲームは一応動いているので表示系統の問題ではないとおもうのですが。
2014/12/23(火) 00:24:18.43ID:hTBgtj1H
gsm.draw(g2d); の前に
System.out.println("gsm=" + gsm);
って入れて本当にインスタンス化されてるか見てみるべき
379名前は開発中のものです。
垢版 |
2014/12/23(火) 17:37:34.54ID:5kqJ3HYv
改行多すぎとエラーが出てしまった。
>>378
gsm=null
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at GameManager.MainPanel.paintComponent(MainPanel.java:128)
at javax.swing.JComponent.paint(JComponent.java:1053).......
のあとに
gsm=GameState.GameStateManager@13236af
と出ました。

public MainPanel() {
// set the recommended panel size
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true); // allow panel to receive key-enters
requestFocus(); }

public void addNotify() {
super.addNotify();
if (gameLoop == null) {
gameLoop = new Thread(this);
addKeyListener(this); // register the key-event listener
//enableEvents(AWTEvent.KEY_EVENT_MASK); // [髱槫酔譛溘く繝シ]縺悟次蝗�縺ァ[繝後Ν繝昴〒繧ャ�シ‐?
gameLoop.start();}}
380名前は開発中のものです。
垢版 |
2014/12/23(火) 17:39:08.59ID:5kqJ3HYv
連投すいません。続きです。


private void inti() {
running = true;
gsm = new GameStateManager(WIDTH, HEIGHT);}

public void run() {
inti();
while (running) {
gsm.update();
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}}}
という構成になっています。このMainPanelが呼ばれた時の基本的な流れがおかしいのですかな?
2014/12/24(水) 04:22:27.25ID:ZOZo6NXr
おそらくそのコードでは、intiが必ずpaintComponentより先に実行されるという保証がないだろう
保証がなければ、どちらが先に実行されても (paintComponentがinitより先に実行されても) いいように書かねばならないのが当然
382名前は開発中のものです。
垢版 |
2014/12/25(木) 01:55:41.41ID:CDRHNiiy
ありがとうございます。
addNotify()の中身をMainPanelのコンストラクタに放り込んだらエラーが出なくなった。

ところで皆さんはゲームのキー処理の問題で、
ゲームメッセージや選択肢なのでず〜っとキーを長押ししていても「一回しか押してない」というのはどういう風にしてます?
2014/12/25(木) 10:44:35.48ID:Af82Po9s
swingだとどうすべきか難しいところだな
DirectInputだと毎フレームすべてのキーの状態を取得しちゃうのが一般的だけど
384名前は開発中のものです。
垢版 |
2014/12/25(木) 19:34:18.02ID:CDRHNiiy
中々サンプルコードみたいなのが見つからない。日本語と英語両方検索したけど。

while(true){....}
public void keyPressed(KeyEvent e) {...}
public void keyReleased(KeyEvent e) {...}
な構造にしているから
ずっとあるキーを押していたらkeyPressed()での処理が行われるし。その関数の中でwhileを使ったら永久ループなりそうだし。

推理ゲームのサンプル探したほうがいいですかね?
2014/12/26(金) 03:39:10.02ID:lHrPo1LI
1↓ 2↓ 3↓ 4↓ 5↑

もし2↓を取ったら、これに対応するのは5↑だから、
3,4は無視しないといけないのでは?
2014/12/27(土) 05:02:14.11ID:ypf29vev
普通に入力関係をラッピングすればいい話じゃ…?
//フィールド
bool isPressed;
bool tmpPressed;

//ループ内
void keyPressed(event e){
isPressed = true;
}
void keyReleased(event e){
isPressed = false;
}
if( !tmpPressed && isPressed ){ //押された1フレーム目だけ
onFirstPressed();
}
tmpPressed = isPressed;

//ループ外
void onFirstPressed(){}

みたいな感じで
387名前は開発中のものです。
垢版 |
2014/12/27(土) 09:25:11.81ID:vPGjZ0DT
>>385, 386
なるほど。
ちょっとそれ試してみます。
今ソースはこんな感じでしています。http://pastebin.com/u/TortoiseshellCat
2014/12/27(土) 14:06:38.18ID:ypf29vev
>>387
すまん>>386は冗長だったかも

bool isPressed;

void keyPressed(event e){
if(isPressed) return;
isPressed = true;
onFirstPressed(e);
}

void keyReleased(event e){
isPressed = false;
}

void onFirstPressed(event e){}

フラグを外から参照して使わないなら
これで充分な話だった。
389名前は開発中のものです。
垢版 |
2014/12/27(土) 21:04:54.34ID:vPGjZ0DT
>>388
ありがとうございます。
そのコードだったら確かにず〜っとキー押していても大丈夫みたいですね。
ケド、思ったんじゃけど、多くのゲームにあるように
たとえばセレクトボタンを一回押したらアイテム欄が表示されて、その間ずっとボタンを押してなくてもいいような感じのをがんばろうとしているのですが。

387でそれっぽく動いているのすが、アイテムの売り買いや色々な機能を追加しようとしたらスバゲッティーは確実なので。
2014/12/28(日) 07:16:21.15ID:AKjP+Lg6
そういうのは普通setVisible()とかsetActive()とかいうメソッドで
パネルの表示/非表示を切り替えればOK
2014/12/29(月) 17:45:26.91ID:k/14dtiW
いつかきっと、SOAだとかクラウドだとか実現する方式は何にせよ、無料でサーバが持てて個人でネトゲ、ちょっとがんばればMMORPGみたいなのが簡単に作れる時代が来ると、自分は思っている。
今でも個人で作っている人は居るが、技術的にも金銭的のも負担が大きい。これがもっと楽になる時代がきっと来る。

そんな時、マルチプラットホーム、オープンソースで無料、完全なオブジェクト指向で学習も比較的容易、例外処理でエラーも比較的追いやすい、速度も大分改善しているJavaは、今後のスタンダードになるに違いないと思っている。

これで後はゲームエンジンやゲーム用統合開発環境等ののキラーソフトがあれば、もっと盛り上がると思うんだが。
Android系では色々あるようだが今一これというものがない。(日本語情報が少ないというのもあるが)
2014/12/30(火) 11:42:24.92ID:/nzVCgt/
iPhoneがダメな時点でマルチプラットフォーム()なんだよなぁ
393名前は開発中のものです。
垢版 |
2014/12/30(火) 22:41:52.73ID:qq+vzibr
>>390
なるほど。Listの中にメッセージダイアログボックスを格納して管理をしているのですが
キーとの関連で表示、非表示をするのが大変だ。
2014/12/30(火) 23:47:34.77ID:e1Qg6kJJ
アプレットをスタンドアローンでうごかしたいんだけど
アプレットをswingのパネルにhsったりできるの?
2014/12/30(火) 23:48:24.13ID:e1Qg6kJJ
×hsったり
○貼ったり
2014/12/31(水) 01:58:36.30ID:6bY7ACR2
appletviewerっていうコマンドがある
2014/12/31(水) 18:34:59.42ID:VBAHoYqR
人に渡すとき
APPLET viwerなるもので動かせますか
2014/12/31(水) 19:05:26.17ID:6bY7ACR2
JREを同梱して渡せば無問題であろう
JREは(一定の条件下で)再配布が認められている
2014/12/31(水) 19:07:03.24ID:6bY7ACR2
あ、ごめん
JREにappletviewer入ってなかったかも
だめだわ
2014/12/31(水) 20:31:57.02ID:VBAHoYqR
ありがとう

swingパネルにアプレット貼れたら
実行ファイルにできそうだけどねえ
2015/01/01(木) 03:29:50.87ID:x71JTDJa
ゲームのメインループだけど
PCのモニタ環境によってリフレッシュレートが60ヘルツとか50ヘルツの
場合があるけど60FPSで画面書き換えると50ヘルツ設定時にカクつくし
60と50FPSに切り替え可能にした場合はそれぞれ1秒辺りのゲーム速度が
変わってしまうし(フレーム毎に1ドットスクロールとか)。その辺は皆どうしてるんだろ?
単純な2Dゲーム作りたいだけなんだけど。
2015/01/01(木) 03:35:19.22ID:uaHkAOC+
deltaTime
403名前は開発中のものです。
垢版 |
2015/01/03(土) 23:03:13.93ID:RYcLH3w9
Java過疎ってんなぁ

ところでJRE8で日本語入力ができないんだが
今はJRE7をメインで使ってる
2015/01/06(火) 04:39:59.03ID:PnAg4DMI
960×544の解像度でBufferdImageで前回の背景表示内容をキャプチャし、
ずらして画像表示して擬似スクロールしてスクロールした分だけ新規描画というのを
60FPSでやってみたけどCore i3でCPU40%消費。ちょっと食いすぎじゃん?
スクロールはブロック単位で再描画した方が良いのかねー。
2015/01/13(火) 17:49:27.95ID:Cut3q1mT
自分もスクロールやろうとしたことあったけど厳しかった
Win7 発売され始め時期のかたおちPCだけど。

>>404 と同じぐらいの画面サイズで
BufferedImage だと 30 fps でもかなりカクカクな感じで
OpenGL使っても 60 fps だとたまにカクッとなった。

組み方が悪いのか、スペックが足りないのか、
ビデオメモリに入りきらないのか、ガベコレか、Javaの限界か、
Cとかでハードウェアに密着して書けば早くなるのか、
ようわからんかった
2015/01/13(火) 22:55:52.16ID:IQ52oWIM
>>405
たぶんそれはモニタのリフレッシュレートが描画と合ってないからだわ。
少なくともセレロン程度でも60FPS程度ではカクカクなんてしない、CPUは食うけど。
2015/02/09(月) 00:06:19.88ID:R2EuJPGg
質問させて下さい
どこかで、JavaのGUIがAWT/SwingからJavaFXへ移行するとの記事を読みました
これからゲーム作る場合、SwingではなくJavaFXを勉強すべきですか?

よろしくお願いいたします
2015/02/14(土) 03:23:03.34ID:2h9+EhUj
あんまり詳しくないけど、2Dのゲームを作る分にはSwingでも十分だし、いろいろな解説サイトや本もだいたいSwingだからJavaFXをわざわざ勉強する必要はないんじゃないかと
2015/02/15(日) 12:01:07.84ID:3+LUOTIJ
>>408
レスありがとうございます
確かに、ネットで勉強していると、ほとんどSwingなんですよね
ただ、これからJavaが本当にGUIをJavaFXに絞る場合、そちらに切り替えたほうがいいのかと心配しています
JavaFXに対するOracleの本気度を知りたいですね
2015/02/16(月) 00:35:23.69ID:IObbTgF7
GUIが変更されても大丈夫な設計にしてSwingで作ればいいじゃない
2015/02/17(火) 01:02:02.75ID:chIOmG3A
>>410
そのレスで、もう一個質問したいことを思い出しました
私はシミュレーションやRPGが作りたいです
色々と、windowを作る必要があると思うのですが、ゲームの場合、それらは自作すべきですか?

たとえば、モンスターが出てきたときに、windowで「たたかう」「にげる」「防御」「魔法」とか表示するとします
その場合、その4個の選択しを表示する枠のようなものはJavaのDialogを使うべきなのか、それとも自前で絵として描画すべきなのかどっちなのかイマイチわかりません
一般的な方法を知りたいです

仮に、自前で絵として表示する場合、SwingでもJavaFXでもあんまり変わらない気になりました
2015/02/17(火) 03:25:28.71ID:6qHepVXs
自作というか、継承してカスタマイズするパターンが一番多いよ
JPanelを継承してCommandPanelとか、そういう感じ。
ボタンとかも押した時のイベント処理とか画像の変化とか備わってるものをベースにするのが現実的。
2015/02/17(火) 10:37:33.20ID:gXwJ1qVD
guiを自前で実装しようとするとフォーカス制御という面倒事が待ってるからswingなりfxなり使った方が手堅いよ。
414191
垢版 |
2015/02/22(日) 11:24:59.12ID:x5Svrr+/
199を参考にマップの処理を実装しようとしているのですが、いまだに詰まっていることがあります。
現在実装中の方法
1000万x1000万等の巨大なマップは自分じゃ一気に作れないので、20x30位のエリアを何個か作り最後に結合する。
一エリアはpublic class Area {
private int[][] map = { {1,1,...,1,1}, .. {1,0,...,0,1} };に格納。
マップはpublic class Map {
    private Area[][] map;//全体地図
private int[][] area;// 画面に表示する範囲(エリアじゃない)
map[0][0] = new Area(1);map[0][1] = new Area(2);map[0][2] = new Area(3);
map[1][0] = new Area(4);map[1][1] = new Area(5);map[1][2] = new Area(6);
map[2][0] = new Area(7);map[2][1] = new Area(8);map[2][2] = new Area(9);のように格納。

そしてプレイヤーの現在位置からどの”エリア”にいるかを算出して
int indexTPX = (int) (topLeft.getX() / (areaWidth * TILE_SIZE));//topLeftは表示画面の為の座標
int indexTPY = (int) (topLeft.getY() / (areaWidth * TILE_SIZE));
area = map[indexTPY][indexTPX].getArea();

そのエリアを描画する。

問題は、例えばmap[0][0],map[0][1],map[1][0]とmap[1][1]の境界付近(+)にプレイヤーがいて
「そのときの描画はどうやればいいのか?」です。
for (int i = 0; i < areaHeight; i++) {for (int j = 0; j < areaWidth; j++) {.....}}だと4つの該当するエリア描画できないし。
2015/02/22(日) 12:11:59.61ID:9tzD8toT
先ず、更新と描画は別。
2015/02/23(月) 10:06:47.59ID:Lz998WDk
表示される範囲座標一つ一つ、どのエリアのどこの座標になるか見ればいいんじゃないの。
2015/02/23(月) 12:44:13.38ID:0EQ3KecF
複数の座標系は変換して使うもの。
グローバル座標、タイル座標(=グローバル座標の場合あり)、エリア座標は相互変換できないとおかしい。
そしてそれら座標系が描画時にウインドウのクライアント座標に変換できないといけない。

この辺が整理できていないからやり方が判らないんだよ。
418名前は開発中のものです。
垢版 |
2015/02/24(火) 00:16:43.29ID:zq7H1j8+
>>415 ~ 417
変換系の整理ですか...
int indexTPX等で表示画面の左上座標を算出して後は表示画面の幅や高さでそれぞれの座標計算は出来るのですが。
/** private Area[][] map
* [1][2][3]
* [4][5][6] 5 -> はじまりの町
* [7][8][9]
*/
1,2,4,5の中心付近にいて4つのエリアを描画するとき、
どうやって各エリア情報を取得して使用するかが確かに整理できない気がします。
2015/02/24(火) 00:53:43.94ID:hT1osW/a
>>418
4つの中心付近とか関係ないだろ…?
今プレイヤーは何番のマップにいるのか。
そのマップはどれだけオフセットしてるのか。
チップのサイズ、マップのサイズはいくらか。
2015/02/24(火) 04:46:34.32ID:FyTelkQO
>>418
エクセルでも方眼紙でも何でもいいから、簡単に入子の箱書いてみれば理解しやすいんじゃない。
421名前は開発中のものです。
垢版 |
2015/02/24(火) 23:23:20.49ID:zq7H1j8+
>>419~420
一つの大きなマップはいくつのも小さなエリアの集合体で構成されているので,
その小さなエリアの幅が決まっています。
よって描画画面がそのエリア幅を超えたら、そのエリアに接している別のエリアも映し始めなければならないので。
後、今プレイヤーが何番のマップにいるのかはわかる様にしています。

ちょっと説明が出来ないのでソース上げてもいいですか?
2015/02/25(水) 00:02:04.33ID:wwS95ney
仕組みは理解できてると思うよ。

表示範囲が1エリアの範囲を超えるでもなければ、プールしておくべきは最大4エリア
その4エリアから表示範囲分を表示すれば良いだけ。
2015/02/25(水) 00:41:58.65ID:sF3guJ4N
エリア座標(0, 0)               エリア座標(1, 0)
    グローバル座標(0, 0), (1, 0)        グローバル座標(2, 0), (3, 0)
              (0 1), (1, 1)                  (2, 1), (3, 1)
エリア座標(0, 1)               エリア座標(1, 1)
    グローバル座標(0, 2), (1, 2)        グローバル座標(2, 2), (3, 2)
              (0 3), (1, 3)                  (2, 3), (3, 3)


描画するべき範囲が四つのエリアに跨っていようとも、
グローバル座標で考えればいいんだよ。

グローバル座標(1, 1), (2, 1)
          (1, 2), (2, 2)

グローバル座標からエリア座標に変換する関数が一つあれば十分でね。

プレイヤーの居る座標(グローバル座標)が判るのだから、
後はプレイヤーを中心に表示する仕様だとして、
クライアント領域に描画する必要なタイル数も判るのだから、
描画の開始点となるグローバル座標も判るし、その座標から何座標分(もしかするとタイル分)描画するかも判るよね。

後はその範囲をfor文でループでもさせて、毎回グローバル座標からエリア座標に変換させて、
エリア上の該当する位置の情報にアクセスすればいいだけでしょ。

これは理屈の話であって、もっと効率的にアクセスできるように設計し実装することも、個々の仕様により可能な場合もあるでしょう。
とかくこれで問題ない筈だよね?
424名前は開発中のものです。
垢版 |
2015/02/25(水) 01:19:14.73ID:Opsz/SjB
>>422~423

なるほどなるほど。グローバル座標などで処理する等で問題は解決しそうです。
ちょっと道が見えてき始めたのでがんばってみます。
ありがとうございます。
425>>199
垢版 |
2015/02/25(水) 17:58:43.51ID:Jzpyh/K8
2年経っても同じことやっててワロタ

4エリアだと計算が難しいから、エリアを少し小さくして
主人公の周り全方向8エリアを処理するようにすれば?
2015/02/25(水) 23:36:51.01ID:wwS95ney
全体マップをエリア単位で分けた座標をブロック座標とした場合、
現在位置の要素を調べるのには、全体マップでの現在位置を1エリアの大きさで割って、商が全体マップ中のエリアのブロック座標、余りがエリア内の要素座標。
これは現在位置の足元の要素を調べる考え方だけど、右隣の要素を調べたいなら右隣を現在位置座標とした同じ計算をしてみればいいだけ。
プレイヤー周囲3x3の要素を調べたいのなら、計9回分基準となる座標を入れ替えて同じ事をすればいい。
2015/02/26(木) 02:32:54.21ID:BXfNXTEu
巨大マップを作るのにしても迷路状のMAPなら、迷路生成の為のツール作って大枠を作成、その上で細部を手直しするとか、
2Dのフィールドマップならマップタイル1つを1色の色に見立ててペイントで大雑把に描いて、その後に通常のマップタイルを組み合わせた表示で細部を手直しするとか。
3Dのフィールドマップなら上記のやり方に組み合わせて、等高線地図的なもので凸凹のMAPを生成し、細部を手直しようにするとか。

巨大な皿に一つ一つ米粒並べるよりも、米をぶちまけて均等にならした方が早い。
グローバル座標からブロック座標、エリア内座標を生成するのも、それと似たような考え方。
428名前は開発中のものです。
垢版 |
2015/02/27(金) 13:30:27.20ID:RNDSqU89
ふお===
何かスパゲッティー通りこしてペペロンチーノになってきた。
ちょっと今思ったのですが、もう一つグローバル変数だけのマップをつくればいいかな。
小さいエリア集合のマップを最初から一つの大きなマップ(グローバル座標もち)にすればいいんじゃね?
そうすればエリアからG座標の計算やエリアが跨った時の計算も楽になるので。

しかし、問題はどうやって
エリア座標(0, 0)               エリア座標(1, 0)
    グローバル座標(0, 0), (1, 0)        グローバル座標(2, 0), (3, 0)
              (0 1), (1, 1)                  (2, 1), (3, 1)
エリア座標(0, 1)               エリア座標(1, 1)
    グローバル座標(0, 2), (1, 2)        グローバル座標(2, 2), (3, 2)
              (0 3), (1, 3)                  (2, 3), (3, 3)

(0, 0), (1, 0), (2, 0), (3, 0)
(0 1), (1, 1), (2, 1), (3, 1)
(0, 2), (1, 2), (2, 2), (3, 2)にするのにはどういう風にループまわそう?
concatみたいなものjavaにありますかね?

皆さんの助言凄く助かるのですが、如何せん実装時にペペロンチーノ化する。
2015/02/27(金) 16:35:54.45ID:KBJyPpkG
グローバルマップのサイズはGX256xGY256。
エリアマップのサイズはAX32xAY32。
すると、グローバルマップは、BX4xBY4のブロックマップとなります。

プレイヤーの現在位置は、PX72,PY24。
この場合、プレイヤーが存在する場所は、

PX72 (プレイヤーのグローバル座標)
PY24

(PX72 / AX32) = bPX2 (プレイヤーの存在するブロック座標)
(PY24 % AY32) = bPY0

(PX72 / AX32) = aPX8 (エリア内のプレイヤー座標)
(PY24 % AY32) = aPY24

演算子は理解できてるよね?
2015/02/27(金) 16:39:11.64ID:KBJyPpkG
エリアマップの集合体がグローバルマップなわけで、その集合体を管理するのがブロックマップでありブロック座標。
エリアマップの集合体を管理する座標体系が、まるっきりすっぽ抜けてんだよ。
431>>199
垢版 |
2015/02/27(金) 17:28:35.90ID:H3arKG/F
チップ単位 32x32(ピクセル)
エリア単位 16x16(チップ)
ワールド単位 64x64(エリア)

int theWarldWidth = 32 x 16 x 64; // 全ての合計
int theWarldHeight = 32 x 16 x 64;
int oneAreaWidth = 32 x 16; // エリアひとつ当たり
int oneAreaHeight = 32 x 16;
int oneTipWidth = 32; // チップひとつ当たり
int oneTipHeight = 32;

プレイヤー座標(Pixel単位)
int x;
int y;

int getAreaX() {
return x / oneAreaWidth;
}

int getTipX() {
return (x % oneAreaWidth) / oneTipWidth;
}

int getPixelX() {
return (x % oneAreaWidth) % oneTipWidth;
}

※真になる
boolean isOK = (x == getAreaX() * oneAreaWidth + getTipX() * oneTipWidth + getPixcel()):
432名前は開発中のものです。
垢版 |
2015/02/27(金) 19:15:31.20ID:RNDSqU89
>>429
はい。 % は余りで、/は除です。
>>430~431
こんなに助けて貰っていてまだ出来ない自分が情けなく思います。まじで。
ちょっと今までの過程を上げて見ます。
ttp://fileup.jp/up/6184.zip.html
433>>199
垢版 |
2015/02/28(土) 01:23:44.46ID:P1K9vzQz
2DのアクションRPGとかその辺かねぇ
ttp://gesei.sub.jp/kami/src/up0358.zip
434名前は開発中のものです。
垢版 |
2015/02/28(土) 11:34:50.48ID:oenNrJIA
>>433
おおおおお。すごい。
完璧に出来ている。
今コードを読んでいて関心させられるばかりです。
もう少し完全把握に時間がかかるので出来次第また書きます。
本当にありがとうございます。これでまたちょっとがんばれるかな。
435名前は開発中のものです。
垢版 |
2015/03/03(火) 01:03:54.17ID:g0dj32rR
漸く432で上げたコードに組み込むことが出来たました。
一つ質問があります。

例えば敵がある一定のエリアにいてArea.update()で更新するのがいいのか。
若しくは、Areaクラスの集合管理をしているMapに敵(自己のエリア番号保有)を格納しているのがいいのか。
クラスダイアグラム考えているんですけど、普通は前者ですかね?
2015/03/03(火) 03:03:27.31ID:5dXFwol9
1.ゲーム仕様的に敵が少なければ敵全員forループで回す
実装が簡単、どこかに敵全員入ったList<Enemy>があれば良い

2.全エリア合計で10万とか敵がいる場合、巨大なforループ自体を回したくない
その場合はAreaクラスにList<Enemy>をもたせておき、Area.update()する
こちらの場合、敵が動いてエリアを跨いだ時に移動前と移動後のエリアに変更を通知する
2015/03/03(火) 03:10:16.30ID:5dXFwol9
>>433をベースにした場合、これで十分だろう

Application.java

public class Application {
 private static List<Enemy> enemys = new List<>();
 public static List<Enemy> getEnemyAll() { return enemys; }
}

MainPanel.java

private void onUpdate(){
 Map map = Application.getMap();
 map.update();

 Player player = Application.getPlayer();
 player.update();

 List<Enemy> enemys = Application.getEnemyAll();
 for(Enemy e : enemys){
  e.update();
 }
}
438名前は開発中のものです。
垢版 |
2015/03/03(火) 19:20:02.12ID:g0dj32rR
なるほど。わかりました。次は当たり判定を実装してみます。


後、皆さんゲーム作るときって何か雛形や構造など参照にしてるものってあります?
自分はテンプレにある-> 大量のソースコードを公開して下さっている国内サイト
ttp://aidiary.hatenablog.com/entry/20040918/1251373370
を使っていますが。
2015/03/03(火) 21:08:17.36ID:zJ99hZfx
さすがにちょっとenemysは頂けないわ
2015/03/03(火) 21:59:26.85ID:5dXFwol9
がびーん
441名前は開発中のものです。
垢版 |
2015/03/03(火) 23:22:11.93ID:Ww58oNEN
>>439
enemies?
442名前は開発中のものです。
垢版 |
2015/03/06(金) 19:06:03.53ID:qOuLf7E5
一つのエリア内での壁の当たり判定は出来ましたが、またエリア境界を跨ぐ所で詰まった。
>>426みたいにするのを考えていますが中々うまくいかない。
いっそのこと>>428の方法を取ったほうが周りのエリアのことを考えなくて住むので計算は楽になるかな?
2015/03/06(金) 21:12:18.88ID:cuamb/V2
いや、何でやねんww
同じ座標変換で、進行方向のオブジェクト調べりゃええだけやがなw
2015/03/06(金) 22:03:19.10ID:YhHE8cN4
これは流石に草
2015/03/06(金) 22:42:29.33ID:DlVBEjuz
まるで成長していない
2015/03/07(土) 01:16:46.43ID:Q1pyrL0N
基本的にプレイヤーの操作によっていじる座標は、キャラの位置を示すグローバル座標のみ。
その他の、全体マップ内でのエリアの位置を示すブロック座標や、該当エリア内でのプレイヤーの位置を示すエリア座標は、必要なときに都度グローバル座標から変換すればいい。
そうすりゃエリア跨いだ場合の処理がー、とか悩む必要もなくなるよ。
2015/03/07(土) 12:44:59.80ID:CIOoXfhb
横から補足すると、
エリアというのも、全エリアの中の更新範囲のエリア群になる筈なんだよ。
それを決定するのもプレイヤーまたはカメラのグローバル座標から行われる。

一度、セーブ・ロードの視点でデータの持ち方、データへのアクセスフローを考えてみるといいよ。
何をトリガーにしてフローが産れるのか?が理解できる。
448名前は開発中のものです。
垢版 |
2015/03/07(土) 16:22:57.20ID://3hG3Y3
>>446~447
ありがとうございます。
>>431の変換関数を基本にしてグローバル座標からエリア座標に変換していますが、
多分壁判定に使っているarea[y][x] == 1系に不備があるんだと思います。

一応シーケンス図を考えながらフローに気をつけて見ます。
4日位でギブアップはやはり早いのでもう少し頑張ってみてみます。
449名前は開発中のものです。
垢版 |
2015/03/08(日) 13:24:37.46ID:GjmzByZt
http://www.m9-www.com/lwjglgameproject
450448
垢版 |
2015/03/17(火) 18:05:16.44ID:NjDAqUGi
ttp://gesei.sub.jp/kami/src/up0358.zip
が限界。頭禿げそう。
451199
垢版 |
2015/03/17(火) 20:39:10.17ID:2aANesll
まずは速度をタイル単位(32)からはじめるこった
ttp://gesei.sub.jp/kami/src/up0360.zip
452名前は開発中のものです。
垢版 |
2015/03/18(水) 01:15:50.35ID:PXfFT047
>>451
199さんでしたか。色々助言やコードなどありがとうございます。
しかも世界ループ機能まで実装してもらってますし。読み易い。
今からプログラムを追っていく作業に取り掛かります。

これでなんとか地図上で動き回れるようになりそうです.
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況