RPG01

MAGI JAVA -Make a game in Java-
JAVA Game作成講座2 09回
オブジェクトエディター作成1


RPGkouza2-09 zipファイル


[起動方法]
1. Java Runtime Environmentをインストールする。 http://java.com/ja/download/
2.ファイルを適当な場所で解凍する。
3.コマンドプロンプトのアイコンが入っているので起動。
4.j 一文字だけ入力して「Enter」。
これでゲームが始まるはず。

[オブジェクトエディター作成1]
どこかで書いたかもしれないが、イベント全般の起動に使うものを「オブジェクト」と呼称している。
宝箱、会話キャラ、場所移動イベント…全てオブジェクトとして扱っている。

調子にのってどんどん先へ行くところだった。まだ全然序盤だが、新処理ができたのでここでカットする。
そういいながら大分手を付けているが、ほとんどマップエディタでやった処理なので目新しい部分は一部しかない。
新しく作った部分は一つだけ。
「テンキーで数値入力できるようにした」
ちょっと長くなるが、ObjectEditorクラスを丸ごとコピペしておく。
まだ未完成なのでセーブやロードはこれから作っていく。

最低限に近い状態のプログラムなので、改造の母体として使いやすいと思う。
ボタンの位置とかは適当なので自由にいじっても支障はない。
絵の表示場所とクリックする位置をリンクさせること。

[ObjectEditor クラス]
import java.awt.Graphics;

public class ObjectEditor {

public Graphics g;
private GameData gData=null;
public GraphicSet gSet=null;
public boolean editEnd=false;
public int[] cursorX=new int[60];
public int[] cursorY=new int[60];
public int[] cursorPos=new int[60];
public int[] cursorMax=new int[60];
public int mode=0;
public int[][] oData=null;

public int mapNumber=0;
public int floorNumber=0;
public int mouseX=0;
public int mouseY=0;
public int click=0;
public int mouseClicked=0;

public int mouseCX=0;
public int mouseCY=0;
public int clickC=0;
public int releaseC=0;

public int keepObjNumber=0;
public int keepNum1=0;

private final int OBJMAX=99;
public int[] setNumber=null;
public int setNumber_max=0;

public ObjectEditor() {
gData=new GameData();
gSet=new GraphicSet();
init();
}

public void init() {
editEnd=false;
mode=1;
for (int i=0;i<=59;i++) {
cursorX[i]=0;
cursorY[i]=0;
cursorPos[i]=0;
cursorMax[i]=0;
}
cursorMax[1]=99;
cursorMax[2]=9;
cursorMax[3]=10;
oData=new int[101][16];
for (int i=0;i<=99;i++) {
for (int j=0;j<=15;j++) {
oData[i][j]=0;
}
}

setNumberInit(4);
mapNumber=0;
floorNumber=0;
keepObjNumber=0;
keepNum1=0;
}

public void setNumberInit(int max) {
setNumber=new int[11];
for (int i=0;i<=10;i++) {
setNumber[i]=0;
}
setNumber_max=max;
}

public void dataSet(GameData gdt) {
init();
gData=gdt;
}

public void eventStart(GameData gdt) {
gData=gdt;
int pushKey=0;
int cPlus=0;
int modeChange=0;

mouseX=gData.pPlatform.mouseEvDragged[1];
mouseY=gData.pPlatform.mouseEvDragged[2];
click=gData.pPlatform.mouseEvDragged[0];

mouseCX=gData.pPlatform.mouseEv[1];
mouseCY=gData.pPlatform.mouseEv[2];
releaseC=gData.pPlatform.mouseEv[3];
clickC=gData.pPlatform.mouseEv[0];
if (releaseC==1 && mouseClicked==1) {
System.out.println("mouseRelease sitayo");
mouseClicked=0;
}
if (gData.pPlatform.keyPush[4]) {
gData.pPlatform.keyPush[4]=false;
pushKey=1;
gData.sePlay(1);
}
if (gData.pPlatform.keyPush[5]) {
gData.pPlatform.keyPush[5]=false;
pushKey=2;
gData.sePlay(2);
}
if (gData.pPlatform.keyPush[0]) {
gData.pPlatform.keyPush[0]=false;
cPlus=-1;
}
if (gData.pPlatform.keyPush[1]) {
gData.pPlatform.keyPush[1]=false;
cPlus=1;
}
if (gData.pPlatform.keyPush[2]) {
gData.pPlatform.keyPush[2]=false;
if (mode==1) cPlus=-20;
}
if (gData.pPlatform.keyPush[3]) {
gData.pPlatform.keyPush[3]=false;
if (mode==1) cPlus=20;
}
if (gData.pPlatform.keyPush[6]) {
gData.pPlatform.keyPush[6]=false;
pushKey=6;
}
if (gData.pPlatform.keyPush[7]) {
gData.pPlatform.keyPush[7]=false;
pushKey=7;
}
for (int i=10;i<=19;i++) {
if (gData.pPlatform.keyPush[i]) {
gData.pPlatform.keyPush[i]=false;
pushKey=i;
}
}
cursorPos[mode]+=cPlus;
if (cursorPos[mode] > cursorMax[mode]) cursorPos[mode]=0;
if (cursorPos[mode] < 0) cursorPos[mode]=cursorMax[mode];

int cpos=cursorPos[mode];
switch (mode) {
case 1://総合メニュー
if (pushKey==1) {
keepObjNumber=cpos;
modeChange=2;
}
if (pushKey==2) {
editEnd=true;
}
break;
case 2:
if (pushKey==1) {
oData[keepObjNumber][0]=cpos;
modeChange=3;
}
if (pushKey==2) modeChange=1;
break;
case 3:
//このコメントは数値の場所を参照するためにコピペした物。意味はない。
//basic 
//public void objKariSet2(int x,int y,int shift,int granum,int evnum,int dt1,int dt2) {
//設定データを増やしたパターン。指定要素の多い場所移動イベントに使う。1行き先固定か否か 2mapnum 3floor 4x 5y 6shift

//public void objKariSet3(int x,int y,int shift,int granum,int evnum,int dt1,int dt2,int dt3,int dt4,int dt5,int dt6) {
//特殊命令セット。フラグ状態により、消したり出したりする。2とほとんど同じだが、変数の設定が一要素増えている。

//public void objKariSet4(int x,int y,int shift,int granum,int evnum,int dt1,int dt2,int dt3) {
if (pushKey==1) {
keepNum1=cpos;
setNumberInit(4);
modeChange=4; //数値入力モードに入る
}
if (pushKey==2) modeChange=2;

break;
case 4: //数値入力モード
if (pushKey==1 || pushKey==6) {
String word="";
for (int i=0;i<=setNumber_max-1;i++) {
word+=setNumber[i];
}
oData[keepObjNumber][keepNum1]=Integer.parseInt(word);
modeChange=3; //入力後は一個前に戻す。
}
if (pushKey==7) {
int[] setNumber2=new int[11];
for (int i=0;i<=10;i++) {
setNumber2[i]=0;
}
for (int i=1;i<=setNumber_max-1;i++) {
setNumber2[i]=setNumber[i-1];
}
setNumber=setNumber2;
}
if (pushKey>=10 && pushKey<=19) {
if (setNumber[0]==0) {
for (int i=0;i<=setNumber_max-2;i++) {
setNumber[i]=setNumber[i+1];
}
setNumber[setNumber_max-1]=pushKey-10;
}

}
if (pushKey==2) modeChange=3;
break;
}
if (clickC==1) {
if (buttonCheck(20,0,60,30) ) editEnd=true; //終了ボタン
}
if (modeChange>=1) mode=modeChange;
}

public Boolean buttonCheck(int bx,int by,int width,int height) {
Boolean hit=false;
if (mouseCX>=bx && mouseCX<=bx+width) {
if (mouseCY>=by && mouseCY<=by+height) hit=true;
}
return hit;
}

public void paint(Graphics gr) {
g=gr;
//カーソル位置と無関係に独立した処理をするボタンの描画
int stx=20;
int sty=0;
String[] str= {"END","SAVE","LOAD"};
for (int i=0;i<=2;i++) {
gSet.rectSet2(gr,stx+i*60,sty,60,30,0,0);
gSet.wordDisp_short2(gr,str[i],stx+i*60,sty+20,0);
}
//編集するオブジェの番号選択と、簡単な概要の表示
stx=40;
sty=60;
int page=cursorPos[1]/20;
int cy=sty+(cursorPos[1]-page*20)*22;
gSet.rectSet2_2(gr,stx,cy,100,20,0,0);
for (int i=0;i<=19;i++) {
gSet.wordDisp_short2_2(g,""+(i+page*20),stx,sty+i*22,0);
gSet.wordDisp_short2_2(g,"------",stx+40,sty+i*22,0);
}

if (mode>=2) {
String[] otype_str= {"[OBJ属性]","会話","敵","場所移動","アイテム取得","フラグ操作","回復魔法陣","店"};
int stx2=stx+110;
int cy2=sty+cursorPos[2]*22;
gSet.rectSet2_2(gr,stx2,cy2,100,20,0,0);
for (int i=0;i<=otype_str.length-1;i++) {
gSet.wordDisp_short2_2(g,otype_str[i],stx2,sty+i*22-22,0);
}
}

//public void objKariSet3(int x,int y,int shift,int granum,int evnum,int dt1,int dt2,int dt3,int dt4,int dt5,int dt6) {
if (mode>=3) {
//int stx3=stx+200;
int stx3=stx+220;
int sty3=sty+22;
int cy3=sty+cursorPos[3]*22;
gSet.rectSet2_2(gr,stx3,cy3,100,20,0,0);
String[] ostr1= {"X座標","Y座標","方向","画像No.","EventNo.","Data1","Data2","Data3","Data4","Data5","Data6"};
for (int i=0;i<=ostr1.length-1;i++) {
gSet.wordDisp_short2_2(g,ostr1[i],stx3,sty3+i*22-22,0);
gSet.wordDisp_short2_2(g,""+oData[keepObjNumber][i],stx3+100,sty3+i*22-22,0);
}

}

if (mode==4) {
gSet.setNumberDisp(gr,setNumber,setNumber_max,360,60+cursorPos[3]*22);
}
}


}

マップエディターで使った処理と共通する部分が多いので、大半の解説は省く。

case 4: //数値入力モード
if (pushKey==1 || pushKey==6) {
String word="";
for (int i=0;i<=setNumber_max-1;i++) {
word+=setNumber[i];
}
oData[keepObjNumber][keepNum1]=Integer.parseInt(word);
modeChange=3; //入力後は一個前に戻す。
}
if (pushKey==7) {
int[] setNumber2=new int[11];
for (int i=0;i<=10;i++) {
setNumber2[i]=0;
}
for (int i=1;i<=setNumber_max-1;i++) {
setNumber2[i]=setNumber[i-1];
}
setNumber=setNumber2;
}
if (pushKey>=10 && pushKey<=19) {
if (setNumber[0]==0) {
for (int i=0;i<=setNumber_max-2;i++) {
setNumber[i]=setNumber[i+1];
}
setNumber[setNumber_max-1]=pushKey-10;
}

}
if (pushKey==2) modeChange=3;
break;
}

ここをまず見ていくか…。
何をしているのかと言うと、4桁の数値を入力させようとしている。
setNumber変数(10桁まで)に一文字ずつ格納しているのを最終的に繋げてintに変換する。

pushKey == 1 or 6 space keyかenter keyの入力で決定。
0-10の要素を繋げて数値化。4,0,0,0と入っていたら4000になる。
0,0,1,0なら10。

pushKey==7はバックスペースに対応している。
一文字入力を戻す。0,0,3,0 と入っていたら、0,0,0,3になる。
0番を1、1番を2…と一個ずつずらして新しい変数を一時的に作成。
maxまで行ったら 0要素目を0にして完成。
元の変数に書き込み直す。
最初は元の変数を直接いじる形にしていたが、計算がややこしいので別変数にまとめる方を使った。
どちらの方法でも同じ結果が得られれば問題ない。

pushKey10-19はキー入力0-9に対応している。
マックス値-1にその入力した数値を入れたいのだが、その前に今の数値を全てスライドさせる必要がある。
0,1,2,3 と入っていて、4を入力した場合は1,2,3,4にしたいわけだ。
0要素目に1要素の数値を入れ、1要素目に2、2は3。max-2まで到達したら処理は終わり。
最後の要素max-1に入力値を打ち込んで完成させる。
ひとつだけ入力をハネる前提条件がある。
if (setNumber[0]==0) {
この例なら4桁全て入力完了していた場合。
この時は新しく入力しても何もさせないで終了させる。
電卓の打ち込みと同じやり方にした。
新しく打ちたい場合はbackSpaceキーで文字を消すしかない。

会話だの敵イベントだの色々設定できるが、現時点ではどれも一緒にしてある。
これからそこらへんは修正していく。
どう変えるかと言うと、内部的にマスクする処理を入れていく。
会話イベントならイベントナンバーは固定でいいし、敵も同様。
打ち込む数値を極力減らすのだ。
自由に全部いじれるカスタム入力も入れておく。

このクラスは大体こんなもの。
最後にPlayerPlatformクラスの変更点を書いておく。

public void eventKeyCheck() {

//keyPressTbl=kPTbl;
if (keyDelay>=1) {
keyDelay--;
}
if (keyDelay<=0) {
if (isKeyCodePressed (KeyEvent.VK_SPACE)) {
keyPush[4]=true;
keyDelay=10;
} else {
keyPush[4]=false;
}
if (isKeyCodePressed (KeyEvent.VK_D)) {
keyPush[5]=true;
keyDelay=10;
} else {
keyPush[5]=false;
}
if (isKeyCodePressed (KeyEvent.VK_UP)) {
keyPush[0]=true;
} else {
keyPush[0]=false;
}
if (isKeyCodePressed (KeyEvent.VK_DOWN)) {
keyPush[1]=true;
} else {
keyPush[1]=false;
}
if (isKeyCodePressed (KeyEvent.VK_LEFT) ) {
keyPush[2]=true;
} else {
keyPush[2]=false;
}
if (isKeyCodePressed (KeyEvent.VK_RIGHT) ) {
keyPush[3]=true;
} else {
keyPush[3]=false;
}
if (keyPush[0]==true || keyPush[1]==true || keyPush[2]==true || keyPush[3]==true) {
keyDelay=5;
}

//テンキーとリターンキーを読み取る。エディタで多用する予定。
if (isKeyCodePressed (KeyEvent.VK_ENTER) ) {
keyPush[6]=true;
keyDelay=6;
} else {
keyPush[6]=false;
}
if (isKeyCodePressed (KeyEvent.VK_BACK_SPACE) ) {
keyPush[7]=true;
keyDelay=6;
} else {
keyPush[7]=false;
}
if (isKeyCodePressed (KeyEvent.VK_0) ) {
keyPush[10]=true;
} else {
keyPush[10]=false;
}
if (isKeyCodePressed (KeyEvent.VK_1) ) {
keyPush[11]=true;
} else {
keyPush[11]=false;
}
if (isKeyCodePressed (KeyEvent.VK_2) ) {
keyPush[12]=true;
} else {
keyPush[12]=false;
}
if (isKeyCodePressed (KeyEvent.VK_3) ) {
keyPush[13]=true;
} else {
keyPush[13]=false;
}
if (isKeyCodePressed (KeyEvent.VK_4) ) {
keyPush[14]=true;
} else {
keyPush[14]=false;
}
if (isKeyCodePressed (KeyEvent.VK_5) ) {
keyPush[15]=true;
} else {
keyPush[15]=false;
}
if (isKeyCodePressed (KeyEvent.VK_6) ) {
keyPush[16]=true;
} else {
keyPush[16]=false;
}
if (isKeyCodePressed (KeyEvent.VK_7) ) {
keyPush[17]=true;
} else {
keyPush[17]=false;
}
if (isKeyCodePressed (KeyEvent.VK_8) ) {
keyPush[18]=true;
} else {
keyPush[18]=false;
}
if (isKeyCodePressed (KeyEvent.VK_9) ) {
keyPush[19]=true;
} else {
keyPush[19]=false;
}

if (isKeyCodePressed (KeyEvent.VK_NUMPAD0) ) {
keyPush[10]=true;
} else {
keyPush[10]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD1) ) {
keyPush[11]=true;
} else {
keyPush[11]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD2) ) {
keyPush[12]=true;
} else {
keyPush[12]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD3) ) {
keyPush[13]=true;
} else {
keyPush[13]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD4) ) {
keyPush[14]=true;
} else {
keyPush[14]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD5) ) {
keyPush[15]=true;
} else {
keyPush[15]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD6) ) {
keyPush[16]=true;
} else {
keyPush[16]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD7) ) {
keyPush[17]=true;
} else {
keyPush[17]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD8) ) {
keyPush[18]=true;
} else {
keyPush[18]=false;
}
if (isKeyCodePressed (KeyEvent.VK_NUMPAD9) ) {
keyPush[19]=true;
} else {
keyPush[19]=false;
}

for (int i=10;i<=19;i++) {
if (keyPush[i]==true) keyDelay=6;
}
}


}

長いけど大したことはやっていない。
Enter、Backspaceの読み取り。
テンキー0-9とキーボードの0-9の読み取り。
"VK_0" - "9" がキーボードの0-9で "VK_NUMPAD0" - "9"がテンキー。
無駄に行が長くなったので、VKとVK_NUMPADは次回まとめてしまう。
||条件で指定すれば同じ行で使える。
keyDelay=6;
がポイント。程よくディレイをかけないと一回押しただけで2個も3個も打ってしまう。
ディレイが長すぎると逆に二回目押しても反応が間に合わなくなる。
10だと長いので6ぐらいにすると程よいタイミングで打ち込める。

今回はここまで。次回もオブジェエディタの作成を引き続き行う。。
あらかた入力はできるようになったので、例のごとくセーブ・ロードできるようにする。
それができたらいよいよゲーム内部でそのデータを使えるかテストする。
データ作成、テスト、データ作成の繰り返しでプログラムを作っていくのがスタイルです。
少しずつ完成させていくので、成果がすぐに見えるのが利点。


・トップページへ戻る
inserted by FC2 system