Home > javaの勉強 Archive

javaの勉強 Archive

pngファイルの表示は激重い!!

鋭意、新ゲーム制作中です!

アプレット上でTimerTaskを使ってゲームメインを呼び出し、バッファに描画ってことをやっているんですが、パズル+シューティングというゲームの性質上、小さめの画像をたくさん表示することになるんですよね。

そこで、どのくらいのFPSでどれくらいの描画量なら処理が追いつくのかをいろいろ試してみてました。

50fpsか40fpsで300個くらいの画像を表示させていたのですが、どうしても動きがカクカクになってしまってました。

VISTAとかPCのせいなのかとも思いましたが、何度か試していて、重大な事実に行き当たりました。

.

.

pngの画像ファイルは表示が激重い!!

.

.

jpgで画像を編集すると、不可逆圧縮とかハフマンなんとかでドット絵が再編集できなくなっちゃうんですよね。

同じ色が変換されて違う色に化けたりとかして・・・。

そこで、色が変わらないpngで画像を作っていたのですが、こいつを

g.drawImage

で描画しようとするとすごく重いらしいのです。

他のgifやbmpも試してみましたが、やはりpngだけやけに重かったです。

そこで、pngのファイルをbmp24ビットに変えてみたら結構スムーズに動くようになりました。

.

チャット部屋でグダグダ言ってた問題もすべてコレでした。お騒がせしてすみませんでした;;

.

.

.

pngの圧縮方法とか調べていないのですが、同じ種類の画像でpngが一番データ量が小さかったので、たぶん一番圧縮効率がいいものなのでしょう。

で、圧縮効率がいい分、戻す時に時間がかかるって感じなんでしょうか?

とりあえず、

・画像サイズが小さいものについてはpngは使わない!

・画像サイズが大きくて、なおかつ描画速度を気にしないのならばpngを使う

というふうに使い分ければよさそうです。

まぁ、今のPCなら画像の圧縮率が低いものでもメモリは余裕でしょうけど。

試しにJavaで画像フィルタ!

Javaで画像フィルタを作ってみました。

拡散フィルタテスト
.
.
作ろう!と思ってすぐできるわけもなく、今回もまたいろいろなサイトにお世話になりました。

Hey! Java Programming

↑Javaでの画像処理の基本的な考え方を学びました。
Imageからpixelの配列を取り出してpixelをいじったら再びImageにすることで画像フィルタを作ることができるようです。
だいぶ詳しく書かれているので後でもうちょっとじっくり読んでみようと思います。

.
.

Javaによる画像処理

↑pdfファイルですのでお気をつけて・・・。
処理の流れを図示していたり、サンプルのプログラムがあったりととても参考になりました。
(自分のプログラムの大枠はこちらのものを利用させてもらいました;;)

.
.

画像処理についてあれこれ

↑カラー画像を白黒画像にする方法について参考にさせてもらいました。
pixelからRGBの値を取り出して、その三つの最大値と最小値の平均をとって、それをRGB全部に入れればいいようです。
たぶん、他にも白黒画像を作るアルゴリズムがあるはずですが・・・。
(最大最小の平均ではなく3色の平均とか?あんまり偉そうなことは言えませんが)

.
.

今回、自分は上のホームページを参考にして、画像を砂っぽくぼやけさせる拡散フィルタと、カラー画像を白黒画像にするフィルタを作りました。
白黒画像を作るアルゴリズムは丸写しなので特に言っておくことはなさそうです。
拡散フィルタのほうは、だいたいこんな感じかな?と考えたアルゴリズムで作成。
具体的には注目画素の周り(今回は5×5の正方形)からランダムに画素を選び、それを注目画素にコピーするって感じで作りました。
3種類あるのは、それぞれ乱数の作り方が違うからです。

一つ目は、Javaのライブラリに入っているとても信頼性の高い乱数を作るMath.random()を使ったもの。
やはり、バラけ方が安定しています。

二つ目は、注目画素のR値をフィルタサイズ(5×5)で割った余りを乱数として使ってます。
猫の画像とか割と色合いがごちゃごちゃしたものだとさほどおかしくはありませんが、風景などの同じ色が並ぶようなものだと明らかに拡散ではない画像変換になってます。乱数として作った数が乱数になりきれていないようです。

三つ目は、画素の座標(縦、横に何番目の画素か)に適当な値を掛け算したものを二つ目で使った値に加えて乱数にしてみました。同じような色でも位置が少しでも違えば数も変わってくるので乱数らしさは増していると思います。
ただ、画像の種類やフィルタの大きさ、掛け算する値の選び方によっては、斜めに延びたような拡散になてしまうということがあったので、完璧に乱数になりきっているってわけでもなさそうです。(うまく拡散するように、掛ける値はいろいろな組み合わせを試しまくりましたww)

.
.
.
それから、プログラム上のちょっとしたメモを・・・

フィルタをかける画像の読み込みですが、アプレットならばToolkitを使い、
img = Toolkit.getDefaultToolkit().getImage(”sample”+imgnum+”.jpg”);
で読み込むことができます。
ただし、これを使う場合は画像読込中にもプログラムが走り続けるようなので、読み込みを待つために
// MadiaTrackerでイメージのロードが終わるのを待つ
MediaTracker mt = new MediaTracker(this);
mt.addImage(img, 0);
try {
mt.waitForAll();
} catch (InterruptedException ie) { }
が必要になってきます。

また、アプリケーションではToolkitでの読み込みは使えないようなので、
try {
img = ImageIO.read(this.getClass().getResource(”sample”+imgnum+”.jpg”));;
} catch (IOException e1) {
e1.printStackTrace();
}
で読み込む必要があります。

こっちの場合は画像の読み込みを待つ必要はないようです!
.
.
.

今回はそんなたいしたものを作ってはいませんが、午後4時頃に作り始めて、7時頃にはほとんど形が完成していたので、けっこうプログラム作りにも慣れてきたのかな~って感じます。(ほとんどがコピーだからかもしれませんがww)

まぁ、この先も気分にまかせてプログラムを作っていきます。

とても深い落とし穴

今の今まで、アップロードした例のツールがうまく動かなくて四苦八苦してました。

まず、jnlpとjarファイルをアップロードした際に勝手に小文字になっていることに気付かず、
そのせいでうまく読み込めていないと気づくまでにだいぶ時間を消費。


さらに、jnlpを同じ名前でアップロードしなおしても更新されていないということに気づくまで相当時間を消費。


ファイル名を変えて、いざ試してみたら、自分が関与しているはずもないJExcelApiのjxl.jarライブラリから例外が返ってきて、
Excelファイルを読み込むことをやめようかとすら考え(というか、途中までtxtファイルに移植する作業をして、途中でtxt形式ではデータを適切に読み込めないことに気づき)さらに時間を消費。


結局は、jxl.jarをWeb上で使う場合には文字エンコーディングの種類を変えないといけないらしく(自分のPC上でjarを起動する分には全然大丈夫)それに気づくまでにかなりの時間を要しました。
で、結局は、
WorkbookSettings ws = new WorkbookSettings();
ws.setEncoding(”ISO-8859-2″);
Workbook workbook = Workbook.getWorkbook(xls, ws);
この真ん中のエンコーディングのcharsetName設定が問題だったらしいです。

ハンガリーの偉人!

Google翻訳版

↑このことに気付かせてくれたハンガリーの偉人とGoogle翻訳には本当に感謝です!!!




で、今日は一睡もしてないけどこれから大丈夫なのだろうか・・・。

Simulation Zero 完成!そして、そのまとめ。

この前作ろうと言っていた便利ツールがついに完成しました。
Simulation Zero(ver1.0)

↑でも、なぜかjnlpから起動してくれないという・・・jarまではちゃんと動いたんだけどな?

.

.

こいつは、金曜日(16日)の夜から本格的に作り始めて、土曜(17)、日曜(18)、月曜(19)、火曜(20)の5日かけてやっと完成させました・・・。

5日というと短いように感じられるかもしれませんが、金夜→土→日→月朝までほとんどずっとPCに向かって「あーでもない、こーでもない」言っていたのですから5日といっても恐ろしいものですよ;;

しかも、その間ずっと「さすがに4時で疲れたから寝るか」→朝10時に再開みたいな生活パターンでした(ひどい;;)。

.

で、これを作ってきてしんみりと感じたのですが、今まで自分が問題にぶち当たり、どこのページを参考にして問題を解決してきたかをこのブログに残しておくことで確実にプログラムで悩むことが減ってきている気がします。

今回も、このブログを見直していろいろヒントを得ました。

そして、またもや未来の自分のために、今回のツール作成でいろいろわかったことを書き残しておこうと思います。

1.JavaからExcelファイルを読み込む

結局はjxl.jarのライブラリを使ってString[][]の型に持ってくることで解決しました。

エクセルファイル読み込みサンプル

ここのページを参考にしました。

また、まえもあったのですが、

workbook = Workbook.getWorkbook(new File("C:/input.xls"), ws);
のようにFileの方でだいるを読み込もうとすると、classファイルのある場所から参照したり、
jarにした時によみこめなかったりするので、inputStreamという型をFileの代わりに使うといいっぽいです。

気の向くままに・・・
↑ここではそれを使っています。



2、Javaアプレット、アプリケーション両対応
基本はアプレット形式をextendsして書いて、アプリケーションで起動する際には、main関数内で自分自身を作る。
で、そのあと適当なFrameやJframeを作り、自分をそのフレームに貼り付ける。
そして、自分自身のinit(); starts();を呼び出せばOK!


3、ドラッグなどのアプレット上での実装
Javaアプレット・サンプル集
↑ここのを参考にしました。
なんとなく、アプレットでマウス操作をどう入力するのかはわかってきた・・・はず。


4、ボタンとかダイアログとかいろいろな部品
とほほのJava入門
ButtonとJButtonなどいろいろな部品の使い方例がまとまってます。
なんか、いつもButtonよりJButtonのほうが良いと思い、Jのつく部品をついつい使っちゃうんですが、必ずしもJのほうがいいってわけではなさそうです;;
TextAreaはJなしのほうが勝手にスクロールしてくれるので便利ですし、
JPanelをアプレットのComponetPaneにaddしたら表示してくれないのにPanelのほうなら大丈夫だったりとか・・・(自分の使い方が悪いせいか?)
とにかく、Jとなにもついてないやつは使い分けたほうがよさそうです。


5、↑のような部品の配置について
配置のレイアウト方法は色々とありますが、やっぱり一番自由度が高いのはnullだと感じました。
JavaApplet(10)
↑ここのページを見て、
setLayout(null);
がアリなことを知りました。
今まで一生懸命setLocation()を使って「なんで位置変えられないんだろ~」とか悩んでいましたが、貼り付け元のほうのレイアウトをnullにしないとロケーションは反映されないんですね。
これでレイアウトの束縛から解放されますwww(どうでもいい配置の場合は便利なんだけどね・・・)


6、文字のフォントを変える
setFont(new Font(”MS ゴシック”,Font.BOLD,9))
↑で、OK.
いつもどこかのソースからコピーしないと書き方を忘れちゃうんです;;
最初の引数は特にいじらなくていいとして、
Font.PLAINが普通文字 .BOLD が太文字 .ITARIC (で綴りあってるのか?)で斜体 は結構使いますね。あとサイズ。


7、その他、いろいろと細かいところ

g.fillPolygon(new int[]{288+38,288,288},new int[]{124+57-114,124+37-114,124+77-114} , 3);
でポリゴンが書けるよ!
ポリゴンはpolygon(int[] x座標たち,int[] y座標たち,int 点の数 )
で作れる。


Collections.shuffle(List list )で、LinkedListとかArrayLIstをシャッフルできる。


list1.addAll(list2)でlist2の全部をlist1の最後につなげることができる。


JTextAreaに文字を加えたいときは、append(String)
逆に文字を全部消したいときはsetText(String)で中の文字を適当に初期化すればOKだった。
これをずっと「どうやって消せばいいんだろ~?」って悩んでいた自分が馬鹿らしかった;;




今回は色々な機能をつけたので、プログラミングで使える技がだいぶ増えたような気がします。
J~とかButtonとかのawtやswingの部品の使い方にも慣れてきた感じです。
今度からはもうチョットスムーズにゲームを作れるといいんですけどね。

  • Comments (Close): 0
  • Trackbacks (Close): 0

参考ページのメモ書き

とりあえず、私用便利ツールを作るためにちょっと調べ物をしています。

・javaアプレット サンプルページ

http://sakkun.cc.yokohama-cu.ac.jp/~sakkun/uoa/program_j/samples/

(↑いろいろなGUIの使い方とか)

http://sea-cross.jp/java/java.html

(↑アナログ時計とかテキストスクロール)

・アプレットをアプリケーションとしても動かせるようにする方法

http://www.mars.dti.ne.jp/~kazuto/WaterMind/JBuilder/jb5createapl.htm

・マウスドラッグで画像表示位置を移動

http://www.iplab.is.tsukuba.ac.jp/~baru/Java/6/text.html

(↑なぜか普通にページとして表示できなくダウンロードしないといけない;;そして筑波大のページらしい)

・エクセルファイルの操作関係

http://www.ra13.org/java/ExcelFileReaderByJxl.html

(↑ jexcel のjarファイルを使用しているよう)

http://www.emxas.co.jp/itblog/item_133.html

(↑Java Excel APIを使用している)

http://javatec.blog105.fc2.com/blog-entry-27.html

(↑apache poi を利用しているよう)

アプレットをアプリケーションで動かす方法やドラッグ操作の書き方の基本はだいたいわかりましたが、エクセルデータの読み込み方法はもう少し調べる必要がありそうです。

  • Comments (Close): 0
  • Trackbacks (Close): 0

4章のロビーフォーム表示が・・・

ロビーフォームのサンプルプログラムを動かそうと思い、4章を読みながら作業をすすめ、XAMPPのAPACHE起動とtestserver.jarの起動はうまく行きました。

(APACHEはちょっと前まではうまく起動できていませんでしたが、XAMPPをインストールしていた外側のフォルダの名前に漢字を使っていたのが悪かったみたいでした。Cドライブのすぐの所にXAMPPのフォルダをインストールしたら大丈夫でした。)

そして、Code64とLobbyFormのプロジェクトをコピーして、ビルドパスなどの設定もして実行してみたのですが、これがうまくいかない状態です。

実行すると、まず「チャット」のアプリケーションが起動され、接続エラーが出てくる状態です。

eclipse上には例外が投げられていて

==========================

java.net.SocketException: Address family not supported by protocol family: connect
at sun.nio.ch.Net.connect(Native Method)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at java.nio.channels.SocketChannel.open(Unknown Source)
at jp.libroworks.GameCommunicator.connectServer(GameCommunicator.java:33)
at LobbyFormMain.<init>(LobbyFormMain.java:85)
at LobbyFormMain.main(LobbyFormMain.java:28)
何らかの理由でログインに失敗
Exception in thread “AWT-EventQueue-0″ java.lang.NullPointerException
at jp.libroworks.GameCommunicator.disconnect(GameCommunicator.java:68)
at LobbyFormMain$1.windowClosed(LobbyFormMain.java:55)
at java.awt.Window.processWindowEvent(Unknown Source)
at javax.swing.JFrame.processWindowEvent(Unknown Source)
at java.awt.Window.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
==========================

↑のような感じです。

”なんらかの理由でログインに失敗”の後の例外は、アプリケーションを閉じた時に出てきたものなので直接は関係なさそうです。

どういう状態になっているのかわからないです!!助けてください!!

セーブ、ロード機能完成!!

↑四苦八苦していたセーブ・ロード機能が完成しました。

ほんと長かった;;

String→byte[] 変換の問題は、
Javaで文字列の暗号化/複合化(※外部ライブラリを使わずに)

やまろうのJavaなわけVol.26 Base64エンコード & デコード & LDAPパスワード変換

↑ここのサイトさんを参考にしてなんとかなりました・・・

が!

この暗号化、復号化プログラムにはいろいろと問題があり、

・秘密鍵は8バイト以上じゃないといけない

・復号化するStringが長すぎるとエラーが起こる

・暗号化するStringが8文字(8バイト?)より小さいと、穴埋めに”□”が出てきてしまう

というような癖を発見するのにすごく時間がかかってしまいました。

結局、この癖に合わせてすでに作っておいたセーブデータの読み込みメソッドを書き換えることになってしまいました;;

(追記)

復号化するStringが長すぎるとうまくいかなかったのは、復号化のメソッドのせいではなく、ゲーム上に表示させた時に長すぎる文字列が勝手に2行にされてしまい(折り返しとかのせいではなく)暗号として読み取れなくなってしまっていたのが原因でした。

そのため、セーブデータがあまり長くならないように、また仕様をいじりまわして複雑怪奇なものになり始めています;;

やはり、新しい機能をつけようとすると労力が半端ないですね。

もう空が明るみ始めてきたよ・・・。

  • Comments (Close): 0
  • Trackbacks (Close): 0

セーブ機能迷走中;;

セーブ機能がわけわからんことになっています。

String(セーブデータ)→byte[]→暗号化→暗号byte[]→暗号String(復活の呪文)

までは何とかできたのですが、

暗号String(復活の呪文)→暗号byte[]→復号化

この「復号化」のところで、byte[]のサイズがおかしかったりしてエラーが起きるという状態から抜け出せないでいます;;

String→byte[]変換やbyte[]→String変換の文字コードを合わせてみたりしたのですが、なんともうまくいかない状態です。

  • Comments (Close): 0
  • Trackbacks (Close): 0

暗号で復活の呪文式セーブ

この前、文字入力を可能にすることができました。

これを使ってセーブ名を決めてもらい、セーブデータのテキストファイルを作る予定だったのですが、実装しようといろいろ調べていくうちに、JARファイル内のファイルの読み込みはできてもJARファイル内に新しくファイルを作ったり、書き換えたりすることができないことが判明;;

JARはJAVAファイルとか画像とかをまとめて変換しているものなので、出来上がったものに付け加えとかはできないんですね。

ということで、データのセーブをどうやってやろうかと悩んでいたのですが、Javaアプレットのゲームを公開してるサイトの中で復活の呪文方式のセーブをやっていたことを思い出したので、今度はそれを実装しようと試行錯誤していました。

文字列を暗号化するためにいろいろなサイトを見てまわり、
簡単な暗号化

↑ここで紹介されていた方法で暗号化を行ってみました。

他のもいろいろ試してみたのですが、暗号化したbyte[]をStringとして表示することができないという欠点があったので(ただ単に自分の力不足かも;;)結局これに落ち着きました。

ただ、これも実行すると時々エラーが出ちゃうんですよね;;なんでだろ?

  • Comments (Close): 0
  • Trackbacks (Close): 0

Javaアプリケーションでの文字入力

セーブするプレイヤー名を入れてもらうための文字入力の方法をいろいろと調べて試していたのですが、なかなかうまくいかずだいぶ時間が過ぎていってしまいました。

結局、Javaの学習ならJavaDrive←ここのサイトを参考にして、別ウインドウを開いて入力する方法を作ることができました。

このサイトには、前にやろうとしてできなかったJButtonの使い方も載っていてだいぶ参考になります。

やはりわからないところで引っかかるとプログラミングもなかなか進みませんね;;

ただ、途中で「魔女の宅急便」を見ていたので、進まなかったのはそっちのせいかもしれません。

Home > javaの勉強 Archive

Search
Feeds
Meta

Return to page top