
誰かさんが作ったRPGのJavaソースコードを読解してみました。
以下ソース
import java.awt.*;
import java.awt.event.*;
import java.applet.*;//アプレットを動かすために必要
import java.io.*;
import java.net.URL;
import java.util.Random;//ここらへんは、アプリを動かすために必要なインポート
public class Rpg17 extends Applet implements Runnable,KeyListener{
Image buffer;//イメージバッファ
Graphics bufferg;//バックバッファ
Random rand = new Random();//乱数 randに乱数が格納されるRandomは参照型変数
volatile Thread th;//スレッド volatileは最適化抑制(毎回評価する)
final int CHIP_SIZE=32;//チップサイズ
final int MAX_EVENT_TABLE=100;//イベントテーブルの最大個数
final int KAKUHO_NO=99;//確保イベントNO(キャラが次に着く位置)
float FrameTime;//1フレームあたりの時間(秒)
long waitTime;//現在時刻保存用
Image chara_image;//キャラチップ画像
MyClass My = new MyClass(168);//自分クラス宣言(チップNO 168)
//方向テーブル(上下左右の順)
int dir_x[] = {0,0,-1,+1};//配列に引数を並べている
int dir_y[] = {-1,+1,0,0};
//キーの状態(離している=0、押し続けている=1、押した瞬間=2)
int key_states[] = new int[5];//4方向(上=0,下=1,左=2,右=3)+Zキー=4
//マップデータ
int now_map_no;//現在のマップNO
short map_data[][] = new short[256][256];//256×256
int map_width,map_height;//マップの横幅、高さ(チップ数)
Image map_image;//マップチップ画像
//イベントデータ
int event_data[][] = new int[256][256];
//イベントテーブル
Event eventtbl[] = new Event[MAX_EVENT_TABLE];
int event_num;//そのマップでのイベントの個数
//ゲーム進行スイッチ
boolean game_switch[] = new boolean[128];
//------------ゲーム管理フラグ-------------
//0=マップ移動(黒幕下がる)
//1=マップ移動(黒幕上がる)
//2=イベント中
//3=会話イベント
//4=文字が流れている途中
//7=デバッグフラグ
//8=テーブル更新予約フラグ
//9=ダイアログ中
//10=スクリプトスキップ中
//11=イベント強制移動中
//12=主人公強制移動中
boolean game_flags[] = new boolean[16];
//------------ゲーム管理ウェイト-----------
//0=黒い幕の昇降ウェイト
//1=会話の流れる文字ウェイト
float game_waits[] = new float[8];
//------------ゲーム管理バッファ-----------
//0=現在のイベントNO
//1=読み込むマップNO
//2=移動先X座標
//3=移動先Y座標
//4=移動後向き
//5=現在のスクリプトの行
//6=会話中の文字の位置。
//7=現在選択中選択肢
//8=選択肢の数
int game_buffer[] = new int[16];
//------------ゲーム管理文字列-----------
//0=現在のスクリプトファイル名
//1=現在の会話内容
//2=分岐1
//3=分岐2
//4=分岐3
String game_strings[] = new String[8];
char game_talks[] = new char[256];//会話内容char配列
//セルテーブル
MapCell celltbl[] = {
new MapCell(0,true), //平原
new MapCell(1,true), //芝1
new MapCell(2,true), //芝2
new MapCell(3,true), //家
new MapCell(4,false), //木1
new MapCell(5,false), //木2
new MapCell(6,true), //城
new MapCell(7,false), //海
new MapCell(8,true), //塔(上)
new MapCell(9,true), //塔(下)
new MapCell(10,true), //洞窟
new MapCell(11,false), //岩山
new MapCell(12,true), //宇宙1
new MapCell(13,true), //宇宙2
new MapCell(14,false), //クリスタル
new MapCell(15,true), //宇宙の城
new MapCell(16,true), //真っ黒
new MapCell(17,true), //茶色
new MapCell(18,false), //灰色
new MapCell(19,true), //ツボ
new MapCell(20,true), //空
new MapCell(21,true), //地面2
new MapCell(22,true), //宝箱
new MapCell(23,true), //青壁
new MapCell(24,true), //黒
new MapCell(25,false), //机
new MapCell(26,true), //川1
new MapCell(27,true), //川2
new MapCell(28,false), //洞窟岩
new MapCell(29,true), //洞窟地面
new MapCell(30,true), //草原1
new MapCell(31,true), //草原2
new MapCell(32,true), //雪地面
new MapCell(33,true), //雪芝1
new MapCell(34,true), //雪芝2
new MapCell(35,true), //雪家
new MapCell(36,false), //雪木
new MapCell(37,true), //雪城
new MapCell(38,false), //雪池
new MapCell(39,true), //雪洞窟
new MapCell(40,true), //雪木
new MapCell(41,true), //雪芝3
new MapCell(42,true), //木の壁
};
//マップデータ構造
MapFile mapfiles[] = {
new MapFile(1,"最終決戦",64,64),
new MapFile(2,"世界フィールド",64,64),
new MapFile(3,"テッペの街",64,32),
new MapFile(4,"雪山1",20,15),
new MapFile(5,"雪山2",64,64),
new MapFile(6,"雪山3",20,15),
new MapFile(7,"麓の村",20,15),
new MapFile(8,"オアシス村",20,15),
new MapFile(9,"ゴーマの神殿",20,15),
new MapFile(10,"ハルー博物館",20,15),
/*
new MapFile(11,"ラストダンジョン1",20,40),
new MapFile(12,"ラストダンジョン2",40,20),
new MapFile(13,"ラストダンジョン3",20,15),
new MapFile(14,"ラストダンジョン4",40,15),
new MapFile(15,"ラストダンジョン5",20,15),
new MapFile(16,"ラストダンジョン6",20,15),
new MapFile(17,"ラストダンジョン7",20,60),
new MapFile(18,"ラストダンジョン8",20,15),
new MapFile(19,"ラストダンジョン9",20,60),
new MapFile(20,"ラストダンジョン10",20,15),
new MapFile(21,"Aの塔1階",32,32),
new MapFile(22,"Aの塔2階",24,24),
new MapFile(23,"Aの塔4階",20,20),
new MapFile(24,"Aの塔3階",20,15),
new MapFile(25,"スタッフロール",20,15),
new MapFile(26,"幻の島",20,15),
new MapFile(27,"幻の町",64,32),
new MapFile(30,"学校",32,32),
new MapFile(32,"アスファル1階",32,32),
new MapFile(33,"アスファル2階",32,32),
new MapFile(34,"洞窟1",32,32),
new MapFile(35,"彼方",50,50),
new MapFile(40,"川1",80,15),
new MapFile(41,"川2",20,15),
new MapFile(42,"川3",80,15),
new MapFile(43,"海1",80,15),
new MapFile(44,"海2",80,15),
new MapFile(50,"宇宙",24,16),
new MapFile(51,"魔王の城1階",32,32),
new MapFile(52,"魔王の城2階",32,32),
new MapFile(60,"サンプル草原",20,15),
*/
};
final int MAXMAPNUM = 10;//マップの個数
//初期化
public void init(){
System.out.println("init()");
int i;
Dimension d = getSize();
MediaTracker mediaT = new MediaTracker(this);
//ボール画像ロード
chara_image = getImage(getDocumentBase(),"chara_chip.gif");//このGIF画を用意する
mediaT.addImage(chara_image,0);
//マップチップ画像ロード
map_image = getImage(getDocumentBase(),"map_chip.gif");//同様にGIF画
mediaT.addImage(map_image,0);
//ロード待ち
try{
mediaT.waitForAll();
}catch(InterruptedException e){}
//イベントテーブル初期化
for(i=0;i
eventtbl[i] = new Event(i);
}
//マップデータロード
readMapData(8);
//主人公の初期座標
My.x = 5;
My.y = 5;
My.px = My.x*CHIP_SIZE;
My.py = My.y*CHIP_SIZE;
My.speed = 128;//主人公の速度。1秒で128ドット。
//現在時刻保存
waitTime=System.currentTimeMillis();
addKeyListener(this);//キー入力リスナー
requestFocus();//フォーカス取得
//バッファを作成する
buffer = createImage(d.width,d.height);
}
//スタート(initの次に呼ばれる。最小化から復帰したときも呼ばれる。)
public void start(){
System.out.println("start()");
if(th == null){
th = new Thread(this);
th.start();
}
}
//ストップ(ウインドウが消えると呼ばれる。最小化でも。)
public void stop(){
System.out.println("stop()");
th = null;
}
//マップデータを読み込む
private void readMapData(int mapno){
System.out.println("readMapData()");
int i,j,x,y;
InputStream is = null;
int id;
String sid;
//マップデータ&イベントデータリセット
for(i=0;i<256;i++){
for(j=0;j<256;j++){
event_data[i][j]=0;
map_data[i][j]=0;
}
}
now_map_no = mapno;
//横幅、縦幅決定
id=1;
for(i=0;i if(mapno == mapfiles[i].no){
id = i;
break;
}
}
map_width = mapfiles[id].width;
map_height = mapfiles[id].height;
//文字列変換
if(mapfiles[id].no < 9){sid = "0"+mapfiles[id].no;}
else{sid = ""+mapfiles[id].no;}
//---------マップデータ読み込み-------------
System.out.println("Load:mapno="+sid);
String filename = "mapdata\\map"+sid+".dat";//datファイルを用意する
try{
is = new URL(getDocumentBase(),filename).openStream();
x=y=0;
while((i=is.read()) != -1){
map_data[x][y]=(short)i;
if(++x == map_width){
++y;
x=0;
if(y==map_height)break; //終了条件
}
}
is.close();
}catch(IOException e){}
//---------イベントデータ読み込み-------------
System.out.println("Load:event="+sid);
filename = "eventdata\\event"+sid+".dat";//datファイルを用意
try{
is = new URL(getDocumentBase(),filename).openStream();
x=y=0;
while((i=is.read()) != -1){
event_data[x][y]=(short)i;
//もし1以上のデータがあればイベントテーブルに代入
if(event_data[x][y] >= 1){
eventtbl[ event_data[x][y] ].x = x;
eventtbl[ event_data[x][y] ].y = y;
eventtbl[ event_data[x][y] ].px = x*CHIP_SIZE;
eventtbl[ event_data[x][y] ].py = y*CHIP_SIZE;
//その他初期化
eventtbl[ event_data[x][y] ].sum_move_length = 0.0f;
}
if(++x == map_width){
++y;
x=0;
if(y==map_height)break; //終了条件
}
}
is.close();
}catch(IOException e){}
//イベントを全てアクティブにする。0以外。
for(i=1;i eventtbl[i].sh = true;
}
//------------イベントテーブル更新----------------
Load_Event_Table();
//主人公の初期座標
My.x = game_buffer[2];
My.y = game_buffer[3];
My.moving_dir = game_buffer[4];
My.px = My.x*CHIP_SIZE;
My.py = My.y*CHIP_SIZE;
//フレーム時間初期化(ロード時間が長いので)
waitTime = System.currentTimeMillis();
}
//イベントテーブル更新
void Load_Event_Table(){
int i,j,x,y;
InputStream is = null;
int id;
String sid;
char line[] = new char[256];
String str="";
int no=0;//イベントNO保存用
int sw=0;//スイッチ
int maxno=0;
//マップNOから添え字取得
id=1;
for(i=0;i if(now_map_no == mapfiles[i].no){
id = i;
break;
}
}
//文字列変換
if(mapfiles[id].no < 9){sid = "0"+mapfiles[id].no;}
else{sid = ""+mapfiles[id].no;}
System.out.println("Load:eventtable="+sid);
String filename = "eventtable\\"+sid+".txt";
x=y=0;
try{
is = new URL(getDocumentBase(),filename).openStream();
while((i=is.read()) != -1){
//一行ずつ読み込む
line[x++] = (char)i;
//System.out.print((char)i);
//改行がきた場合
if(i == '\r'){continue;}
if(i == '\n'){
//改行コード以降切り捨てて、String型を読み込む
String sline = Harulib.HaruChop(line);
//条件を読む
//現在はゲーム進行スイッチのみ
str = Harulib.HaruSplit(sline,"<>",0);
//NULLと書いてるものはそのまま実行
if(str.equals("NULL")){;}
else{
//数字のものはゲーム進行スイッチにより読み込む
sw = Integer.parseInt(str);
//条件がマッチしているか?
if(game_switch[sw]){
;//続ける
}else{
//この行は破棄
x=0;
y++;
continue;
}
}
//イベントNO
str = Harulib.HaruSplit(sline,"<>",1);
no = Integer.parseInt(str);
eventtbl[no].no = Integer.parseInt(str);
//System.out.println("y="+y+" eventtbl[y].no="+eventtbl[y].no);
//スクリプト名
str = Harulib.HaruSplit(sline,"<>",2);
eventtbl[no].filename = str;
//グラフィックス
str = Harulib.HaruSplit(sline,"<>",3);
eventtbl[no].gra = Integer.parseInt(str);
//System.out.println("y="+y+" eventtbl[y].gra="+eventtbl[y].gra);
if(eventtbl[no].gra >= 1){
eventtbl[no].type_of_event = 1;
}
//動作フラグ
str = Harulib.HaruSplit(sline,"<>",4);
if(str.equals("true")){
eventtbl[no].move_flag = true;
}else{
eventtbl[no].move_flag = false;
}
//移動タイプ
str = Harulib.HaruSplit(sline,"<>",5);
eventtbl[no].type_of_move = Integer.parseInt(str);
eventtbl[no].speed = 32;
//最大値保存
if(maxno < no){
maxno = no;
}
x=0;
y++;
}
}
is.close();
}catch(IOException e){}
//イベントの数(最大値)
event_num = maxno+1;
//KAKUHO_NO番目に入れる
eventtbl[KAKUHO_NO].move_flag = true;
eventtbl[KAKUHO_NO].type_of_event = 1;
}
//実行
public void run(){
System.out.println("run()");
Thread thisThread = Thread.currentThread();
try{
//ここがゲームループ
while(th == thisThread){
//1フレーム時間計算(秒)
FrameTime = ( System.currentTimeMillis()-waitTime ) /1000.0f;
waitTime = System.currentTimeMillis();
action();//処理
repaint();//描画
//ちょっと休憩(0.01秒)
Thread.sleep(10);
}
th = null;
}
catch(Exception e){
}
}
//描画更新
public void update(Graphics g){
paint(g);
}
//描画
public void paint(Graphics g){
Dimension d = getSize();
int i;
int x,y;//描画位置
//バッファのグラフィックコンテキストを取得する
if(bufferg == null){
bufferg = buffer.getGraphics();
}
//バッファを描画する
bufferg.setColor(Color.white);
bufferg.fillRect(0,0,d.width,d.height);
//マップ&イベント描画
DispMap(bufferg);
//イベント描画
DispEvent(bufferg);
//主人公描画
DispMy(bufferg);
//エフェクト
//黒い幕(マップ移動時)
if(game_flags[0] || game_flags[1]){
bufferg.setColor(Color.black);
bufferg.fillRect(0,0,d.width,(int)(d.height*game_waits[0]));
}
//会話(ダイアログ中も表示)
if(game_flags[3] || game_flags[9]){
//ウインドウを作る(下1/3)
bufferg.setColor(Color.black);
bufferg.fillRect(0,2*d.height/3,d.width,d.height/3);
//文字
bufferg.setColor(Color.white);
//一文字ずつ書いていく
x=y=0;
for(i=0;i //19文字で改行
if(x==19){
x=0;
y++;
}
bufferg.drawString(String.valueOf(game_talks[i]),10+x*16,2*d.height/3+20 + y*16);
x++;
}
}
//ダイアログ
if(game_flags[9]){
//ウインドウを作る(真ん中上)
bufferg.setColor(Color.black);
bufferg.fillRect(d.width/4,d.height/4,d.width/2,(d.height/12) * game_buffer[8]);
//文字配置
bufferg.setColor(Color.white);
for(i=0;i bufferg.drawString(game_strings[i+2],d.width/4+20,d.height/4 + 14+i*16);
}
//カーソル
//キャラチップからグラフィックスの位置を取得
x = (197%16)*CHIP_SIZE;
y = (197/16)*CHIP_SIZE;
bufferg.drawImage(chara_image,
d.width/4, d.height/4 + 2 +game_buffer[7]*16,
d.width/4+CHIP_SIZE/2, d.height/4 + 2+game_buffer[7]*16+CHIP_SIZE/2,
x,y,x+CHIP_SIZE/2,y+CHIP_SIZE/2,this);
}
//フォント
bufferg.setColor(Color.black);
bufferg.drawString("マップサイズ("+map_width+","+map_height+")。イベントの個数("+event_num+")",10,20);
bufferg.drawString("現在の座標はmap(" +My.x+ "," +My.y+ ")。" +
"p(" +(int)My.px+ "," +(int)My.py+ ")。",10,40);
//bufferg.drawString("start(" +start_x+ "," +start_y+ ")。"+
// "end(" +end_x+ "," +end_y+ ")。",10,60);
//イベント中
if(game_flags[2]){
bufferg.drawString("イベント中",10,60);
}
//バージョン情報(右下)
bufferg.setColor(Color.blue);
bufferg.fillRect(d.width-130,d.height-16,d.width,16);
bufferg.setColor(Color.white);
bufferg.drawString("RPGを作ろう Ver.17",d.width-120,d.height-4);
//ウインドウを更新する
g.drawImage(buffer,0,0,this);
}
//---------------------マップ描画------------------------
void DispMap(Graphics bufferg){
int i,j,x,y;
int cell_data,gra;
Dimension d = getSize();
//画面中心座標を主人公の位置から取得
int view_x = (int)My.px + CHIP_SIZE/2;
int view_y = (int)My.py + CHIP_SIZE/2;
//カメラが行ける範囲(マップの端-画面半分)
int lim_left = d.width/2;
int lim_right = map_width * CHIP_SIZE - d.width/2;
int lim_top = d.height/2;
int lim_bottom = map_height * CHIP_SIZE - d.height/2;
//主人公がマップの端寄りの場合、カメラ固定
//世界マップ以外
if(now_map_no != 2){
if(My.px + CHIP_SIZE/2 < lim_left){
view_x = lim_left;
}
if(My.px + CHIP_SIZE/2 > lim_right){
view_x = lim_right;
}
if(My.py + CHIP_SIZE/2 < lim_top){
view_y = lim_top;
}
if(My.py + CHIP_SIZE/2 > lim_bottom){
view_y = lim_bottom;
}
}
//マップデータの範囲(主人公から6チップ分)
int start_x;
int start_y;
int end_x;
int end_y;
start_x = view_x/CHIP_SIZE - 6;
start_y = view_y/CHIP_SIZE - 6;
end_x = view_x/CHIP_SIZE + 6;
end_y = view_y/CHIP_SIZE + 6;
//描画位置IJ
//世界マップのみ
int disp_start_i,disp_i,disp_start_j,disp_j;
disp_start_i = start_y;
disp_start_j = start_x;
//限界
//世界マップ以外
if(now_map_no != 2){
if(start_x < 0){start_x = 0;}
if(start_y < 0){start_y = 0;}
if(end_x > map_width){end_x = map_width;}
if(end_y > map_height){end_y = map_height;}
}else{
//ループ
//世界マップのみ
if(start_x < 0){start_x += map_width;}
if(end_x >= map_width){end_x -= map_width;}
if(start_y < 0){start_y += map_height;}
if(end_y >= map_height){end_y -= map_height;}
}
//描画位置
int dsp_x;
int dsp_y;
for(i=start_y,disp_i=disp_start_i; ;i++,disp_i++){
//iがマップ端の場合、0に。(世界マップのみ)
if(i == map_height && now_map_no == 2){i = 0;}
//終了
if(i == end_y){break;}
for(j=start_x,disp_j=disp_start_j; ;j++,disp_j++){
//jがマップ端の場合、0に。
if(j == map_width && now_map_no == 2){j = 0;}
//終了
if(j == end_x){break;}
//セルデータ取得
cell_data = map_data[j][i];
//セルデータからマップグラフィックスを取得
gra = celltbl[ cell_data ].gra;
//マップチップからグラフィックスの位置を取得
x = (gra%16)*CHIP_SIZE;
y = (gra/16)*CHIP_SIZE;
//マップ描画位置
if(now_map_no == 2){
dsp_x = disp_j*CHIP_SIZE - (view_x - d.width/2);
dsp_y = disp_i*CHIP_SIZE - (view_y - d.height/2);
}else{
dsp_x = j*CHIP_SIZE - (view_x - d.width/2);
dsp_y = i*CHIP_SIZE - (view_y - d.height/2);
}
bufferg.drawImage(map_image,dsp_x,dsp_y,
dsp_x+CHIP_SIZE,dsp_y+CHIP_SIZE,x,y,x+CHIP_SIZE,y+CHIP_SIZE,this);
//イベントがある場合はEマークを表示(デバッグ用)
if(event_data[j][i] >= 1 && game_flags[7]){
//グラフィックスの位置を取得
x = (13%16)*CHIP_SIZE;
y = (13/16)*CHIP_SIZE;
bufferg.drawImage(chara_image,dsp_x,dsp_y,
dsp_x+CHIP_SIZE,dsp_y+CHIP_SIZE,x,y,x+CHIP_SIZE,y+CHIP_SIZE,this);
}
}
}
}
//--------------イベント(キャラクター)描画------------------
void DispEvent(Graphics bufferg){
int i;
int dsp_x,dsp_y;
int x,y;
Dimension d = getSize();
//画面中心座標を主人公の位置から取得
int view_x = (int)My.px + CHIP_SIZE/2;
int view_y = (int)My.py + CHIP_SIZE/2;
//カメラが行ける範囲(マップの端-画面半分)
int lim_left = d.width/2;
int lim_right = map_width * CHIP_SIZE - d.width/2;
int lim_top = d.height/2;
int lim_bottom = map_height * CHIP_SIZE - d.height/2;
//主人公がマップの端寄りの場合、カメラ固定
//世界マップ以外
if(now_map_no != 2){
if(My.px + CHIP_SIZE/2 < lim_left){
view_x = lim_left;
}
if(My.px + CHIP_SIZE/2 > lim_right){
view_x = lim_right;
}
if(My.py + CHIP_SIZE/2 < lim_top){
view_y = lim_top;
}
if(My.py + CHIP_SIZE/2 > lim_bottom){
view_y = lim_bottom;
}
}
for(i=0;i dsp_x = (int)eventtbl[i].px - (view_x - d.width/2);
dsp_y = (int)eventtbl[i].py - (view_y - d.height/2);
//グラフィックスの位置を取得(アクティブ時)
if(eventtbl[i].sh && eventtbl[i].gra != -1){
x = (eventtbl[i].gra%16)*CHIP_SIZE;
y = (eventtbl[i].gra/16)*CHIP_SIZE;
bufferg.drawImage(chara_image,dsp_x,dsp_y,
dsp_x+CHIP_SIZE,dsp_y+CHIP_SIZE,x,y,x+CHIP_SIZE,y+CHIP_SIZE,this);
}
}
}
//--------------主人公描画------------------
void DispMy(Graphics bufferg){
int i,j,x,y;
int cell_data,gra;
Dimension d = getSize();
//カメラが行ける範囲(マップの端-画面半分)
int lim_left = d.width/2;
int lim_right = map_width * CHIP_SIZE - d.width/2;
int lim_top = d.height/2;
int lim_bottom = map_height * CHIP_SIZE - d.height/2;
//描画開始位置
int view_x = d.width/2 - CHIP_SIZE/2;
int view_y = d.height/2 - CHIP_SIZE/2;
//マップの端に近づいてる時(カメラが行けない範囲)
//通常マップ
if(now_map_no != 2){
if(My.px + CHIP_SIZE/2 < lim_left){
view_x = (int)My.px;
}
if(My.px + CHIP_SIZE/2 > lim_right){
view_x += (int)My.px + CHIP_SIZE/2 - lim_right;
}
if(My.py + CHIP_SIZE/2 < lim_top){
view_y = (int)My.py;
}
if(My.py + CHIP_SIZE/2 > lim_bottom){
view_y += (int)My.py + CHIP_SIZE/2 - lim_bottom;
}
}
//主人公描画
//チップNO定義
int no = My.chip_no + My.moving_dir*2 + My.anime_no;
//チップNOからグラフィックスの位置を取得
x = (no%16)*CHIP_SIZE;
y = (no/16)*CHIP_SIZE;
//頭
bufferg.drawImage(chara_image,view_x,view_y-32,
view_x+CHIP_SIZE,view_y-32+CHIP_SIZE,x,y,x+CHIP_SIZE,y+CHIP_SIZE,this);
//胴体
y+=CHIP_SIZE;
bufferg.drawImage(chara_image,view_x,view_y,
view_x+CHIP_SIZE,view_y+CHIP_SIZE,x,y,x+CHIP_SIZE,y+CHIP_SIZE,this);
}
//処理
public void action(){
int i;
//上下左右キー状態で移動処理
//エフェクト中、イベント中、会話中は受け付けない
if(game_flags[0] || game_flags[1] || game_flags[2] || game_flags[3]){;}
else{
KeyForMove();
}
//Zキー(決定キー)を押した時
if(key_states[4] == 2){
//決定キーのいろんな処理
ZAction();
//キーの状態を押し続けに変更。
key_states[4] = 1;
}
//上下キーを押した時
for(i=0;i<2;i++){
if(key_states[i] == 2){
//上の場合
if(i==0){
if(game_buffer[7] > 0)game_buffer[7]--;
}
//下の場合
else if(i==1){
if(game_buffer[7] < game_buffer[8]-1)game_buffer[7]++;
}
//キーの状態を押し続けに変更。
key_states[i] = 1;
}
}
//移動中の場合
if(My.moving_flag){
MyMoving();
//アニメーション(0.2秒に1回)
My.anime_wait += FrameTime;
if(My.anime_wait >= 0.2f){
My.anime_no = 1 - My.anime_no;
My.anime_wait = 0.0f;
}
}
//イベント移動(エフェクト中、イベント中、会話中は受け付けない)
if(game_flags[0] || game_flags[1] || game_flags[2] || game_flags[3]){;}
else{
EventMove();
}
//イベント強制移動
if(game_flags[11]){
CharaMoving(eventtbl[ game_buffer[0] ]);
}
//主人公強制移動
if(game_flags[12]){
MyMoving();
}
//会話中の場合、文字が流れていく
if(game_flags[3]){
//0.05秒に1文字
game_waits[1] += FrameTime;
if(game_waits[1] >= 0.05f){
game_waits[1] = 0.0f;
game_buffer[6]++;
if(game_buffer[6] > game_strings[1].length()){
game_buffer[6] = game_strings[1].length();
//完了
game_flags[4] = false;
}
}
}
//マップ移動開始(幕閉じ)
if(game_flags[0]){
//黒い幕が降りてくる(1.1秒)
game_waits[0] += FrameTime;
if(game_waits[0] >= 1.1f){
game_flags[0] = false;
game_flags[1] = true;
//マップロード
readMapData(game_buffer[1]);
}
}
//マップ移動2(幕開け)
else if(game_flags[1]){
//黒い幕が上っていく(1.2秒)
game_waits[0] -= FrameTime;
if(game_waits[0] <= 0.0f){
game_flags[1] = false;
game_waits[0] = 0.0f;
}
}
//イベント中
if(game_flags[2]){
//マップ移動時、会話の時、ダイアログ中、強制移動は停止中
if(game_flags[0] || game_flags[1] || game_flags[3] || game_flags[9] ||
game_flags[11] || game_flags[12]){;}
else{
ActionScript();//スクリプト実行
}
}
}
//イベント移動開始
void EventMove(){
int i;
int ran;
int dir;
int next_x,next_y;
boolean ismove;
for(i=0;i //動くタイプの時
if(eventtbl[i].type_of_move == 1){
//休憩中の時
if(eventtbl[i].sum_move_length < 0.0f){
eventtbl[i].sum_move_length += FrameTime;
}else
//現在、移動中でないなら移動開始(2秒ペースで休憩)
if(!eventtbl[i].moving_flag){
//ランダムに方向を決める
ran=rand.nextInt();
if(ran<0){ran=-ran;}
dir = ran%4;//方向
//その方向は通行可能か?
next_x = eventtbl[i].x + dir_x[dir];
next_y = eventtbl[i].y + dir_y[dir];
//System.out.println("["+i+"]next("+next_x+","+next_y+")");
//領域外
if(next_x < 0 || next_y >= map_width ||
next_y < 0 || next_y >= map_height){
//通行不可
ismove = false;
}
//障害物
else if(!celltbl[ map_data[next_x][next_y] ].move_flag){
//通行不可
ismove = false;
}
//イベント
else if(event_data[next_x][next_y] >= 1){
//通行不可
ismove = false;
}
//主人公の位置
else if(next_x == My.x && next_y == My.y){
//通行不可
ismove = false;
}
//それ以外
else{
//通行可
ismove = true;
//移動開始
eventtbl[i].sum_move_length = 0.0f;
eventtbl[i].moving_dir = dir;
//移動先イベントデータにKAKUHO_NOを入れる
event_data[next_x][next_y] = KAKUHO_NO;
}
eventtbl[i].moving_flag = ismove;
}
//移動中の時
else{
//その方向に向かって移動
CharaMoving( eventtbl[i] );
}
}
}
}
//Zキーの処理
void ZAction(){
//ダイアログ中は決定
if(game_flags[9]){
game_flags[9] = false;
System.out.println("Done:Dialog");
}
//会話中の時はウインドウを消す(文字が流れ終わった時)
else if(game_flags[3] && !game_flags[4]){
game_flags[3] = false;
System.out.println("Done:Talk");
}
//そうでなくてイベント中でないなら、イベントチェック
else if(!game_flags[2]){
//その方向にイベントがあるかチェック
//決定ボタンが押されると実行するものを実行
check_event(My.x + dir_x[My.moving_dir] , My.y + dir_y[My.moving_dir],1);
}
}
//キー状態で移動処理
public void KeyForMove(){
int i;
int next_x,next_y;
boolean ismove;
//上下左右キー
for(i=0;i<4;i++){
if(key_states[i] == 1){
//現在移動中か?
if(!My.moving_flag){
//移動中でないなら移動
My.moving_dir = i;
//その方向は通行可能か?
next_x = My.x + dir_x[My.moving_dir];
next_y = My.y + dir_y[My.moving_dir];
//世界マップならループさせる
if(now_map_no == 2){
if(next_x < 0){next_x += map_width;}
if(next_x >= map_width){next_x -= map_width;}
if(next_y < 0){next_y += map_height;}
if(next_y >= map_height){next_y -= map_height;}
}
//System.out.println("My next("+next_x+","+next_y+")");
//領域外(通常マップ時)
if(next_x < 0 || next_y >= map_width ||
next_y < 0 || next_y >= map_height){
//通行不可
ismove = false;
}
//障害物
else if(!celltbl[ map_data[next_x][next_y] ].move_flag){
//通行不可
ismove = false;
}
//イベントで、通行不可タイプ
else if(!eventtbl[ event_data[next_x][next_y] ].move_flag){
//通行不可
ismove = false;
}
//確保イベント
else if(event_data[next_x][next_y] == KAKUHO_NO){
//通行不可
ismove = false;
}
//それ以外
else{
//通行可
ismove = true;
//移動開始
My.sum_move_length = 0.0f;
//移動先イベントデータにKAKUHO_NOを入れる(0の時)
if(event_data[next_x][next_y] == 0){
event_data[next_x][next_y] = KAKUHO_NO;
}
}
My.moving_flag = ismove;
}
}
}
}
//自分移動
public void MyMoving(){
//その方向に移動
My.px += FrameTime * My.speed * dir_x[My.moving_dir];
My.py += FrameTime * My.speed * dir_y[My.moving_dir];
//総合距離加算
My.sum_move_length += FrameTime * My.speed;
//一定距離動いたか
if(My.sum_move_length >= (float)CHIP_SIZE){
//ピッタリの位置にする
My.x += dir_x[My.moving_dir];
My.y += dir_y[My.moving_dir];
//世界マップの時
if(My.x < 0){My.x += map_width;}
if(My.x >= map_width){My.x -= map_width;}
if(My.y < 0){My.y += map_height;}
if(My.y >= map_height){My.y -= map_height;}
My.px = My.x*CHIP_SIZE;
My.py = My.y*CHIP_SIZE;
My.moving_flag = false;
//この位置の確保イベントを消す(KAKUHO_NOの時)
if(event_data[My.x][My.y] == KAKUHO_NO){
event_data[My.x][My.y] = 0;
}
//強制イベント移動の場合
if(game_flags[12]){
game_flags[12] = false;
My.sum_move_length = 0.0f;
}else{
//イベントチェック
//その上に重なると起動するもの。
check_event(My.x,My.y,0);
}
}
}
//キャラ移動
void CharaMoving(Event event){
int ran;
//その方向に移動
event.px += FrameTime * event.speed * dir_x[event.moving_dir];
event.py += FrameTime * event.speed * dir_y[event.moving_dir];
//総合距離加算
event.sum_move_length += FrameTime * event.speed;
//一定距離動いたか
if(event.sum_move_length >= (float)CHIP_SIZE){
//前の位置のイベントを消す
event_data[event.x][event.y] = 0;
//ピッタリの位置にする
event.x += dir_x[event.moving_dir];
event.y += dir_y[event.moving_dir];
event.px = event.x*CHIP_SIZE;
event.py = event.y*CHIP_SIZE;
event.moving_flag = false;
event_data[event.x][event.y] = event.no;
//強制イベント移動の場合
if(game_flags[11]){
game_flags[11] = false;
event.sum_move_length = 0.0f;
}else{
//小休止(ランダム1秒~3秒)
ran=rand.nextInt();
if(ran<0){ran=-ran;}
event.sum_move_length = -(ran%3+1);
}
}
}
//その場所のイベントチェック
void check_event(int x,int y,int type){
//領域外の時
if(x < 0 || y < 0 || x >= map_width || y >= map_height)return;
//イベントがあった場合(KAKUHO_NOは無視)
if(event_data[x][y] != 0 && event_data[x][y] != KAKUHO_NO){
//上に乗った時。それは重なると起動するものか?
if(type == 0 && eventtbl[ event_data[x][y] ].type_of_event != 0){
//違う場合は抜ける
return;
}
//決定ボタンを押した時。それは遠くから起動するものか?
if(type == 1 && eventtbl[ event_data[x][y] ].type_of_event != 1){
//違う場合は抜ける
return;
}
game_buffer[0] = eventtbl[ event_data[x][y] ].no;//イベントNO記憶
game_flags[2] = true;//イベントフラグセット
//スクリプトファイル名決定
game_strings[0] = "eventscript\\"+eventtbl[ game_buffer[0] ].filename+".txt";
}
}
//スクリプト実行
void ActionScript(){
String filename;
int i,x;
char line[] = new char[256];
InputStream is = null;
filename = game_strings[0];
System.out.println("Script("+filename+"):Load");
//指定の行まで行く
int line_num = 0;
boolean done_flag=true;//最後まで読みきったか
boolean next_flag;//次の行も読み取るか
try{
is = new URL(getDocumentBase(),filename).openStream();
Reader r = new BufferedReader(new InputStreamReader(is));
x=0;
while((i=r.read()) != -1){
//一行ずつ読み込む
line[x++] = (char)i;
//System.out.print((char)i);
//改行がきた場合
if(i == '\n'){
//System.out.println("("+line_num+")"+String.valueOf(line));
//その行は読み込む行か?
if(line_num == game_buffer[5]){
//そうであった場合、読み込んで解析
next_flag = AnalyzeScript(line);
game_buffer[5]++;
//マップ移動、会話イベント、ダイアログなら抜ける
if(!next_flag){
done_flag = false;
break;
}
//そうでないならそのまま読み込み続ける
line_num++;
}else{
//違うなら、改行数増やして探索続行
line_num++;
}
x=0;
}
}
is.close();
}catch(IOException e){}
//最後まで読み切った場合は、フラグ解除
if(done_flag){
System.out.println("Script("+filename+"):End");
game_flags[2] = false;
game_buffer[5] = 0;
//テーブル更新予約があればテーブル更新
if(game_flags[8]){
Load_Event_Table();
game_flags[8] = false;
}
}
}
//指定の行を読み込んで解析(戻り値がある時はそれを実行し次の行へ続く)
public boolean AnalyzeScript(char line[]){
int i,x,y;
String command;
String value;
String buffer;
boolean next_flag=true;
//改行コード以降切り捨て(改行含む)
String sline = Harulib.HaruChop(line);
//コマンド取得
command = Harulib.HaruSplit(sline,":",0);
//値取得
value = Harulib.HaruSplit(sline,":",1);
System.out.println("("+game_buffer[5]+")Script -- > com="+command+",value="+value);
//ラベル確認
if(command.equals("IF_SCENE1")){
//そのラベル以降は実行すべきか?
if(game_buffer[7] == 0){
game_flags[10] = false;//スキップ解除してそのまま実行
}
else{
game_flags[10] = true;
}
}else if(command.equals("IF_SCENE2")){
//そのラベル以降は実行すべきか?
if(game_buffer[7] == 1){
game_flags[10] = false;//スキップ解除してそのまま実行
}
else{
game_flags[10] = true;
}
}else if(command.equals("IF_SCENE3")){
//そのラベル以降は実行すべきか?
if(game_buffer[7] == 2){
game_flags[10] = false;//スキップ解除してそのまま実行
}
else{
game_flags[10] = true;
}
}else if(command.equals("END_SCENE")){
//スキップ終了
game_flags[10] = false;
}
//スキップ実行の時
if(game_flags[10]){
return true;//抜ける
}
//コマンドによってイベント実行
//マップ移動コマンド
if(command.equals("move")){
System.out.println("Do:Move");
//移動イベント開始
game_flags[0] = true;
//値を解析
buffer = Harulib.HaruSplit(value,"=",0);
game_buffer[1] = Integer.parseInt(buffer);//移動先マップNO
buffer = Harulib.HaruSplit(value,"=",1);
game_buffer[2] = Integer.parseInt(buffer);//X
buffer = Harulib.HaruSplit(value,"=",2);
game_buffer[3] = Integer.parseInt(buffer);//Y
buffer = Harulib.HaruSplit(value,"=",3);
game_buffer[4] = Integer.parseInt(buffer);//方向
next_flag=false;
}
//会話コマンド
else if(command.equals("talk")){
System.out.println("Do:Talk");
//会話イベント開始
game_flags[3] = true;
//流れ始める。
game_flags[4] = true;
//会話
game_strings[1] = value;
//char配列にコピー
game_strings[1].getChars(0,game_strings[1].length(),game_talks,0);
//文字の位置
game_buffer[6] = 1;//1文字目
next_flag=false;
}
//ゲーム進行スイッチオンコマンド
else if(command.equals("switch_on")){
System.out.println("Do:switch_on");
game_switch[ Integer.parseInt(value) ] = true;
//テーブル更新予約
game_flags[8] = true;
}
//分岐1
else if(command.equals("SCENE1")){
System.out.println("Do:SCENE1");
game_strings[2] = value;
}
//分岐2
else if(command.equals("SCENE2")){
System.out.println("Do:SCENE2");
game_strings[3] = value;
game_buffer[7] = 0;
game_buffer[8] = 2;//選択肢の数
}
//分岐3
else if(command.equals("SCENE3")){
System.out.println("Do:SCENE3");
game_strings[4] = value;
game_buffer[7] = 0;
game_buffer[8] = 3;//選択肢の数
}
//ダイアログを出す
else if(command.equals("DIALOG")){
System.out.println("Do:DIALOG");
game_flags[9] = true;
next_flag=false;
}
//イベントを一時的に消去
else if(command.equals("temperace")){
System.out.println("Do:temperace");
event_data[eventtbl[ game_buffer[0] ].x][eventtbl[ game_buffer[0] ].y] = 0;
eventtbl[ game_buffer[0] ].sh = false;
eventtbl[ game_buffer[0] ].move_flag = false;
next_flag=true;
}
//イベント強制移動
else if(command.equals("emove")){
System.out.println("Do:emove");
//方向
if(value.equals("up")){eventtbl[ game_buffer[0] ].moving_dir = 0;}
else if(value.equals("down")){eventtbl[ game_buffer[0] ].moving_dir = 1;}
else if(value.equals("left")){eventtbl[ game_buffer[0] ].moving_dir = 2;}
else if(value.equals("right")){eventtbl[ game_buffer[0] ].moving_dir = 3;}
game_flags[11] = true;
next_flag=false;
}
//主人公強制移動
else if(command.equals("mymove")){
System.out.println("Do:mymove");
//方向
if(value.equals("up")){My.moving_dir = 0;}
else if(value.equals("down")){My.moving_dir = 1;}
else if(value.equals("left")){My.moving_dir = 2;}
else if(value.equals("right")){My.moving_dir = 3;}
game_flags[12] = true;
My.sum_move_length = 0.0f;
next_flag=false;
}
//イベント速度変更
else if(command.equals("espeed")){
System.out.println("Do:emove");
eventtbl[ game_buffer[0] ].speed = (float)Integer.parseInt(value);
next_flag=true;
}
return next_flag;
}
//キーが押された瞬間(使わない)
public void keyTyped(KeyEvent e){}
//キーを押している時
public void keyPressed(KeyEvent e){
int key;
key=e.getKeyCode();
switch(key){
//上キー
case KeyEvent.VK_UP:
//最初に押した時に2を入れる
if(key_states[0] == 0){
key_states[0] = 2;
}
break;
//下キー
case KeyEvent.VK_DOWN:
//最初に押した時に2を入れる
if(key_states[1] == 0){
key_states[1] = 2;
}
break;
//左キー
case KeyEvent.VK_LEFT:
key_states[2] = 1;
break;
//右キー
case KeyEvent.VK_RIGHT:
key_states[3] = 1;
break;
//Zキー
case KeyEvent.VK_Z:
//最初に押した時に2を入れる
if(key_states[4] == 0){
key_states[4] = 2;
}
break;
}
}
//キーが放された瞬間
public void keyReleased(KeyEvent e){
int key;
key=e.getKeyCode();
switch(key){
//上キー
case KeyEvent.VK_UP:
key_states[0] = 0;
break;
//下キー
case KeyEvent.VK_DOWN:
key_states[1] = 0;
break;
//左キー
case KeyEvent.VK_LEFT:
key_states[2] = 0;
break;
//右キー
case KeyEvent.VK_RIGHT:
key_states[3] = 0;
break;
//Zキー
case KeyEvent.VK_Z:
key_states[4] = 0;
break;
}
}
}
このソースのままだと戦闘シーンとかがまだ書かれていません。
自分でeclipseとかでいじってみると面白いかと思います。

禁酒貯金をしたいと思います。
禁酒を一日するごとに一万円貯金します。
飲酒をするごとに、1500円~2000円の出費がでます。
おつまみなども含むからです。
もちろん、それに比べたらかなり割高なご褒美だと思うんですが、
今の自分にはそれくらいのご褒美が無いと禁酒できないのです。
いろいろなことが辛すぎて。
順調に禁酒がいったら一回の貯金額を減らしてもいいかもしれません。
しかし、当分は、でしょう・・・・。
5日続いたら、1回につき1000円に減額するとか考えます。
キャンプラル(アカンプロセート)も飲んでいます。
なので、渇望感みたいなのは抑えられています。
この金で海外旅行とか考えてます。
・・・・・・・・
レヴィアは飲んだけど、効果はイマイチでした。
ノックビンは怖くて使っていません。
キャンプラルが一番効いているんでしょう。
一回一万円の貯金は高過ぎだと思うかもしれませんが、今の自分にはちょうど良い値段です。
酒が好きというよりも、
眠れないのです。
焦燥感というか。
鬱というか。
~ 韓国語学習日記 ~
왕년에 잘나갔던 영화들이 잇따라 3D로 변신해 관객들에게 선보입니다.
어마어마한 제작비를 들여 입체 영상으로 다시 보는 명작 영화들, 과연 그때 그 감동이 되살아날까요?
정인성 기자입니다.
往年にうまく行った映画が相次いで3Dに変身して観客らにリリースします。
ものすごい製作費を入れて立体映像でまた見る名作映画ら、果たしてその時その感動がよみがえりましょうか?
チョン・インソン記者です。
왕년에・・・ワネンエ 往年に
잘나갔던・・・チャルナガットン うまく行った
영화들이・・・ヨンファドゥリ 映画が
잇따라・・・イッタラ 相次いで
3D로・・・スリーディロ 3Dに
변신해・・・ミョンシンヘ 変身して
관객들에게・・・ゴァンゲクドゥレゲ 観客らに
선보입니다.・・・ソンボイムニダ リリースします
어마어마한・・・オマオマハン ものすごい
제작비를・・・チェジャクピルル 製作費を
들여・・・ドゥロ 入れて
입체・・・イプチョ 立体
영상으로・・・ヨンサンウロ 映像で
다시・・・タシ また
보는・・・ボヌン 見る
명작・・・ミョンチャク 名作
영화들・・・ヨンファドゥル 映画ら
과연・・・ゴァヨン 果たして
그때・・・クデ その時
그 감동이・・・クカムドンイ その感動が
되살아날까요・・・ドゥイサラナルッカヨ よみがえりましょうか
정인성・・・チョンインソン
기자입니다・・・キチャイムニダ 記者です
・・・・・・・・・・・
・・・・・・・・・・・
今からこのペースで学習していたら、韓国語検定4級は間違いないと思う。
問題は中国語検定3級だ。
受かっているだろうか・・・・
・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・
禁酒をすると、多少眠りたらなさがあるが、気分は良い。
これがいいんだろう。
できれば続けていきたい。
禁酒は、2日目、3日目、と辛くなるんです。
分かりますか。
渇望感みたいなのが出てくるんです。
でも、生活習慣に根差したものですから。
一か月は続けないと無くならないものなんでしょう。
・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・・
色々な人が書いたゲームのソースを読むというのは勉強になりますね。
今回もRPGの他人が書いたソースを読みましたが、自分が知っている知識とは違うことがいろいろと学習できました。
今後も精進していきたいです。
ファミコンクオリティのゲームを今年も作っていきたいですね。
・・・・・・・・・・・・・・・・
日
今後も精進していきたい。
英
I would like to continue to purify myself.
韓
앞으로도 정진해 가고 싶다
アプロド チョンジンヘ カゴ シプタ
中
今后也想精进
jin1 hou4 ye3 xiang3 jing1 jin4
