import java.awt.*; import java.applet.*; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.awt.image.*; import java.util.StringTokenizer; //-------------------------------------------------- // 会話用クラス //-------------------------------------------------- class TalkManage{ // フォントサイズ final int FONT_SIZE = 14; // 以下、受け継いだもの // グラフィックス Graphics g; // アプレット Applet applet; // 会話対象キャラ Chara m_target_chara; // 会話フェイズ int TalkPhase; // イベントスクリプト用文字列バッファ StringBuffer m_script_sb[]; // その行数 int ScriptLineNum; // トーク用バッファ StringBuffer m_talk_buffer; // 現在読んでいるスクリプトのライン int NowReadLine; // 現在のスクリプトコマンド String NowCommand; String NextCommand; // 表示した会話文字数 int NowDspTalkLength; // 最大文字数 int MaxTalkLength; // カーソル点滅用カウンタ int m_next_talk_timer; // インスタンス static TalkManage m_instance; static TalkManage GetInstance(){ return m_instance; } static void NewInstance( MapEdit applet ){ m_instance = new TalkManage( applet ); } TalkManage( MapEdit applet ){ this.applet = applet; } void Initialize(){ TalkPhase = 0; m_script_sb = new StringBuffer[ 256 ]; m_talk_buffer = new StringBuffer(); NowReadLine = 0; NowCommand = new String(""); NextCommand = new String(""); NowDspTalkLength = 0; MaxTalkLength = 0; m_next_talk_timer = 0; } void SetTargetChara( Chara chara ){ m_target_chara = chara; } //-------------------------------------------------- // デバッグプリント //-------------------------------------------------- void DebugPrint( String str ){ System.out.println( str ); } //-------------------------------------------------- // グラフィックスセット //-------------------------------------------------- void SetGraphics( Graphics g ){ this.g = g; } // 会話ウィンドウを半透明で描画 void DspDrawTalkWindow( int OffPix[] ){ final int FONT_WIDTH_SIZE = 12; final int LINE_WORD_NUM = 19; final int START_Y = (MapManage.HEIGHT-70); final int START_X = 10; // フォントサイズ final int FONT_SIZE = 14; // 会話コマンドのとき if( !NowCommand.equals("#talk") ){ return; } Game.GetInstance().fillRectToMemory( OffPix, START_X, START_Y, (MapManage.WIDTH-20) + 1, FONT_SIZE * 4 + 5, 0x80000060 ); } // 会話の文字描画 void DrawTalkWindow(){ int i, x, y; final int FONT_WIDTH_SIZE = 12; final int LINE_WORD_NUM = 19; final int START_Y = (MapManage.HEIGHT-70); final int START_X = 10; // 会話コマンドのとき if( !NowCommand.equals("#talk") ){ return; } // ウィンドウの枠 g.setColor( Color.white ); g.drawRect( START_X - 1, START_Y - 1, (MapManage.WIDTH-20) + 1, FONT_SIZE * 4 + 5 + 1 ); // 文字の色 g.setColor( Color.white ); // 1文字ずつ描画 int dsp_x, dsp_y; int start_line; x = 0; y = 0; // 会話の改行の数を数える int br_num = 0; for( i = 0; i < NowDspTalkLength; i++ ){ // 改行コードが来たら改行 if( m_talk_buffer.charAt(i) == '\n' ){ x = 0; y++; //i++; if( i+1 >= NowDspTalkLength )break; continue; } x++; // 一行最大文字数こえたら自動改行(親切設計) if( x >= LINE_WORD_NUM ){ x = 0; y++; } } br_num = y; int talk_start = br_num - 3; if( talk_start < 0 ){ talk_start = 0; } x = 0; y = 0; // 文字MAX行−4行から表示 for( i = 0; i < NowDspTalkLength; i++ ){ // 改行コードが来たら改行 if( m_talk_buffer.charAt(i) == '\n' ){ x = 0; y++; //i++; if( i+1 >= NowDspTalkLength )break; continue; } dsp_x = START_X + 4 + x * FONT_WIDTH_SIZE; if( y >= talk_start ){ int new_y; new_y = y - talk_start; if( new_y < 0 ){ new_y = 0; } dsp_y = START_Y + FONT_SIZE + new_y * FONT_SIZE; // 1行LINE_WORD_NUM文字 g.drawString( String.valueOf( m_talk_buffer.charAt(i) ), dsp_x, dsp_y ); } x++; // 一行最大文字数こえたら自動改行 if( x >= LINE_WORD_NUM ){ x = 0; y++; } } NowDspTalkLength++; // 会話終了 if( NowDspTalkLength > MaxTalkLength ){ NowDspTalkLength = MaxTalkLength; // 続きの会話があるなら、NEXTカーソル if( NextCommand.equals("#nextpage") ){ // 点滅 if( m_next_talk_timer < 10 ){ g.drawString( "▼", START_X + 150 - (FONT_SIZE>>1), START_Y + FONT_SIZE * 4 ); } m_next_talk_timer++; if( m_next_talk_timer > 20 ){ m_next_talk_timer = 0; } }else{ m_next_talk_timer = 0; } } } boolean IsExitTalk(){ return NowDspTalkLength == MaxTalkLength ? true : false; } // 会話できる範囲描画 void DrawCanTalkArea( int px, int py ){ int i, j; int x, y; int len; final int TALK_LENGTH = 1; // 座標系に int chara_x = px / MapManage.CHIP_SIZE; int chara_y = py / MapManage.CHIP_SIZE; // 描画 g.setColor( Color.cyan ); for( y = chara_y - TALK_LENGTH; y <= chara_y + TALK_LENGTH; y++ ){ for( x = chara_x - TALK_LENGTH; x <= chara_x + TALK_LENGTH; x++ ){ // 主人公との距離が1以内だけ描画 len = abs( chara_x - x ) + abs( chara_y - y ); if( len <= TALK_LENGTH && len >= 1 && x >= 0 && y >= 0 && x < MapManage.GetInstance().width && y < MapManage.GetInstance().height ){ // 移動可能範囲 Game.GetInstance().LightMapData[ x ][ y ] = 0; // 四角形描画 // スクリーン座標に変換 g.drawRect( CharaManage.GetInstance().ToScreenX(x*MapManage.CHIP_SIZE) +1, CharaManage.GetInstance().ToScreenY( y*MapManage.CHIP_SIZE + 1 ), MapManage.CHIP_SIZE - 2, MapManage.CHIP_SIZE - 2 ); } } } } int abs( int a ){ return a > 0 ? a : -a; } // 会話処理 void TalkAction(){ switch( TalkPhase ){ case 0: // 初期化 InitTalk(); TalkPhase++; break; case 1: // break; } } // 会話初期化 void InitTalk(){ // 対応イベントのスクリプトの読み込み String file = m_target_chara.GetEvent(); // スクリプトロード if( MapEdit.RELEASE_MODE ){ ScriptLineNum = LoadEventScript( "map/"+MapEdit.GetMapID()+"/"+file+".txt" + "?" + System.currentTimeMillis() , m_script_sb ); }else{ ScriptLineNum = LoadEventScript( "map/"+MapEdit.GetMapID()+"/"+file+".txt", m_script_sb ); } // エラー時 if( ScriptLineNum == 0 ){ Game.GetInstance().now_phase = Game.NORMAL_PHASE; return; } NowReadLine = 0; AnalyzeScript(); } // スクリプト解析 void AnalyzeScript(){ int i; String command; // トークン分割用クラス StringTokenizer st; NowCommand = ""; // 現在の行から解析 for( i = NowReadLine; i < ScriptLineNum; i++ ){ //DebugPrint(""+i+"行目" ); // 頭に#がついてるものがコマンド if( m_script_sb[i].length() > 0 && m_script_sb[i].charAt( 0 ) == '#' ){ command = m_script_sb[i].toString(); // マップ移動コマンド if( command.indexOf("#MoveMap") >= 0 ){ String next_map = ""; st = new StringTokenizer( command, " " ); // 引数確認 if( st.hasMoreTokens() ) NowCommand = st.nextToken(); if( st.hasMoreTokens() ) next_map = st.nextToken(); if( st.hasMoreTokens() ) Game.GetInstance().m_next_x = Integer.parseInt( st.nextToken() ); if( st.hasMoreTokens() ) Game.GetInstance().m_next_y = Integer.parseInt( st.nextToken() ); // マップ切り替え Game.GetInstance().SubPhase = 0; Game.GetInstance().now_phase = Game.CHANGE_MAP_PHASE; Game.GetInstance().m_next_map_id = next_map; // スクリプトを終える break; } // バトルコマンド else if( command.indexOf("#EnCount") >= 0 ){ // エンカウント開始 Game.GetInstance().EnCountInit(); // スクリプトを終える break; } // 会話コマンド開始 else if( command.equals("#talk") ){ NowDspTalkLength = 0; NowCommand = command; } // 今までが会話なら一旦終了 else if( NowCommand.equals("#talk") ){ // 会話の続きある? if( command.equals( "#nextpage" ) ){ // 次回のコマンド格納 NextCommand = m_script_sb[i].toString(); } // 次回はここから NowReadLine = i; break; } // 次のページの場合 else if( command.equals("#nextpage") ){ //m_talk_buffer.delete( 0, MaxTalkLength ); // 初期化 // NowDspTalkLength = 0; // コマンドをtalkにしておく NowCommand = "#talk"; }else{ NowCommand = command; } }else{ // 会話の場合、追加していく if( NowCommand.equals("#talk") ){ //DebugPrint( "i="+i+"nai="+m_script_sb[i].toString() ); m_talk_buffer.append( m_script_sb[i].toString() ); m_talk_buffer.append( "\n" ); } } } // 会話の場合 if( NowCommand.equals("#talk") ){ // 会話初期化 MaxTalkLength = m_talk_buffer.length(); } // 最後まで読みきっていた場合 if( i == ScriptLineNum ){ // エラーチェック NextCommand = ""; } } //-------------------------------------------------- // イベントスクリプト読み込み //-------------------------------------------------- int LoadEventScript( String file, StringBuffer sb[] ){ DebugPrint( file ); try{ InputStream is = new URL( applet.getDocumentBase(), file ).openStream(); // テキストだからリーダーを使う BufferedReader br = new BufferedReader( new InputStreamReader( is ) ); // ライン格納 String line; int i; DebugPrint( "script_load_start" ); // 一行ずつ読み込む int line_num = 0; while( ( line = br.readLine() ) != null ){ // コメント(;で始まるもの)は虫 if( line.length() > 0 && line.charAt( 0 ) == ';' ){ continue; } // バッファに追加していく(StringBufferは軽いはず…) sb[line_num] = new StringBuffer(); sb[line_num].append( line ); line_num++; } is.close(); return line_num; }catch( IOException e ){ DebugPrint( "load_fail" ); return 0; } } }