import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; //-------------------------------------------------- // ゲームクラス //-------------------------------------------------- class Game{ //-------------------------------------------------- // 定数 //-------------------------------------------------- // フォントサイズ final int FONT_SIZE = 14; final int LENGTH = 4; //最大4マス // メインフェイズフラグ static final int NORMAL_PHASE = 0; //何もない(選択カーソル動く) static final int CHARA_SELECT_PHASE = 1; //キャラ選択(メニュー描画) static final int MOVE_SELECT_PHASE = 2; //移動範囲選択(移動範囲描画) static final int MOVE_PHASE = 3; //移動状態 static final int TALK_SELECT_PHASE = 4; // 話し相手選択フェイズ static final int TALK_PHASE = 5; // 会話フェイズ static final int CHANGE_MAP_PHASE = 6; // マップ切り替え static final int ENCOUNT_PHASE = 7; // エンカウント static final int TO_SKY_PHASE = 8; // 空へ羽ばたく static final int BATTLE_PHASE = 9; // バトル //-------------------------------------------------- // 管理クラス //-------------------------------------------------- // 以下、受け継いだもの // グラフィックス Graphics g; // 親アプレット MapEdit applet; // 現在のフェイズ int now_phase; int GetNowPhase(){ return this.now_phase; } // 選択したキャラ(メイン) Chara m_selected_chara; // 選択したキャラの移動先 int moved_x; int moved_y; // 選択座標 int select_x, select_y; // 選択メニュー int selected_menu_no; // メニュー選択用マウス移動距離(Y座標の上下) int menu_move_length; // サブフェイズ int SubPhase = 0; // 次のマップID String m_next_map_id; // 主人公移動先 int m_next_x, m_next_y; // 移動可能マップ(可能なら0) byte LightMapData[][]; // 最短経路記憶 String mvrec[][]; // 移動処理フェイズ int MovePhase = 0; int goflag = 0; int golast = 0; // フェードアルファ int FadeAlpha; // 空を飛ぶ時用 int SkyPhase = 0; // マップ縮小状態 private int m_map_scale_sate; static final int NORMAL_SCALE_MAP = 0; // 通常 static final int SKY_SCALE_MAP = 1; // 空 static final int ENCOUNT_MAP = 2; // エンカウント int GetMapScaleState(){ return m_map_scale_sate; } // キー列挙 final int KEY_UP = 1; final int KEY_RIGHT = 2; final int KEY_DOWN = 4; final int KEY_LEFT = 8; final int KEY_ENTER = 0x10; final int KEY_TEST = 0x100; // テスト用 // キー状態 int KeyState; // 前回のキー状態 int PrevKeyState; // ゲーム内での時間 private int m_game_hour; private int m_game_minute; private int m_night_level; // 夜の明暗の度合い int GetGameHour(){return m_game_hour;} int GetNightLevel(){ return m_night_level; } // インスタンス static Game m_instance; static Game GetInstance(){return m_instance;} static void NewInstance( MapEdit applet ){ m_instance = new Game( applet ); } Game( MapEdit applet ){ this.applet = applet; } //-------------------------------------------------- // デバッグプリント //-------------------------------------------------- void DebugPrint( String str ){ System.out.println( str ); } //-------------------------------------------------- // グラフィックスセット //-------------------------------------------------- void SetGraphics( Graphics g ){ this.g = g; TalkManage.GetInstance().SetGraphics( g ); } // 初期化 void Initialize(){ now_phase = NORMAL_PHASE; KeyState = 0; PrevKeyState = 0; FadeAlpha = 0x00; // 9時開始 m_game_hour = 9; m_game_minute = 0; m_night_level = 0; } // 基本処理 void BasicAction(){ switch( now_phase ){ case NORMAL_PHASE:break; case CHARA_SELECT_PHASE: break; case MOVE_SELECT_PHASE: break; case MOVE_PHASE: // 指定のキャラを動かしてみる MoveChara(); break; case TALK_PHASE: // 会話処理 TalkManage.GetInstance().TalkAction(); break; // マップ切り替え case CHANGE_MAP_PHASE: ChangeMapAction(); break; // エンカウント case ENCOUNT_PHASE: EnCountAction(); break; // 空へ case TO_SKY_PHASE: ToSky(); break; // バトルフェイズ case BATTLE_PHASE: BattleManage.GetInstance().BattleAction(); break; } // ゲーム時間を進める ProcessGameTime(); } void ProcessGameTime(){ m_game_minute += 1; if( m_game_minute >= 60 ){ m_game_hour++; m_game_minute = 0; if( m_game_hour >= 24 ){ m_game_hour = 0; } } // 夜加算 3分に1回 つまり4時間かけて最大値に if( m_game_hour >= 17 && m_game_minute % 3 == 2 ){ m_night_level++; if( m_night_level > 80 ) m_night_level = 80; } // 夜減算 else if( m_game_hour >= 5 && m_game_minute % 3 == 2 ){ m_night_level--; if( m_night_level < 0 ) m_night_level = 0; } } // クリック処理 void ClickAction( int x, int y ){ boolean ret; // 左クリックで移動、右クリックで決定 // 画面中心からの距離 int length_x = BasicManage.MyAbs( MapManage.WIDTH / 2 - x ); int length_y = BasicManage.MyAbs( MapManage.HEIGHT / 2 - y ); // 画面の中央より左で、Xのほうが長いなら、左キーと同等 // ただしORはしない。マウスドラッグしながら方向を変えれるようにするため。 if( x < MapManage.WIDTH/2 && length_x > length_y ){ KeyState = KEY_LEFT; } else if( x > MapManage.WIDTH/2 && length_x > length_y ){ KeyState = KEY_RIGHT; } else if( y < MapManage.HEIGHT/2 && length_y > length_x ){ KeyState = KEY_UP; } else{ KeyState = KEY_DOWN; } // ここからシミュレーションRPGタイプ 一旦没 /* switch( now_phase ){ case NORMAL_PHASE: // その場所にいるキャラ検索 SearchChara( x, y ); break; // キャラ選択状態 case CHARA_SELECT_PHASE: // 移動を選んだ場合 if( selected_menu_no == 0 ){ now_phase = MOVE_SELECT_PHASE; } // 話すを選んだ場合 else if( selected_menu_no == 1 ){ now_phase = TALK_SELECT_PHASE; } break; case MOVE_SELECT_PHASE: // 移動先を指定 ret = SetMovePoint( x, y ); if( ret ){ now_phase = MOVE_PHASE; } break; case TALK_SELECT_PHASE: //DebugPrint("話キャラ選択"); // 話し相手を指定 Chara chara = SetTalkPoint( x, y ); // キャラいた? if( chara != null ){ //DebugPrint("話キャラ発見"); // そのキャラをこっちに向かせる(主人公と逆向き) int dir = 0; if( m_selected_chara.GetDir() == 0 ) dir = 2; else if( m_selected_chara.GetDir() == 1 ) dir = 3; else if( m_selected_chara.GetDir() == 2 ) dir = 0; else if( m_selected_chara.GetDir() == 3 ) dir = 1; chara.SetDir( dir ); // トークフェイズへ TalkManage.GetInstance().SetTargetChara( chara ); TalkManage.GetInstance().Initialize(); now_phase = TALK_PHASE; }else{ now_phase = NORMAL_PHASE; } break; // 会話中 case TALK_PHASE: // 会話が終了するまでは受け付けない if( TalkManage.GetInstance().IsExitTalk() ){ // スクリプトの続きを読む if( TalkManage.GetInstance().NextCommand.equals("#nextpage") ){ //DebugPrint("続き読む"); TalkManage.GetInstance().AnalyzeScript(); }else{ //DebugPrint("最初へ"); // 最初へ now_phase = NORMAL_PHASE; } } break; } */ } // マウスリリース処理 void MouseReleaseAction( int x, int y ){ KeyState = 0; } // マップ切り替え処理 void ChangeMapAction(){ int ret; switch( SubPhase ){ // 初期化 case 0: // フェードアウト開始 FadeAlpha = 0x00; SubPhase++; // そのまま次へ case 1: FadeOutAction(); // アルファがFFになったらマップ切り替え if( FadeAlpha == 0xFF ){ applet.ChangeMap( m_next_map_id ); // 主人公ワープ PlayerManage.GetInstance().SetPlayerLocation( m_next_x, m_next_y ); // カメラ調整 SetCameraPosition(); SubPhase++; } break; case 2: // フェードイン開始 FadeInAction(); // 終了 if( FadeAlpha == 0 ){ SubPhase++; now_phase = NORMAL_PHASE; } break; } } void MoveSelectPhase(){ switch( SubPhase ){ case 0: MoveSelectInit(); SubPhase = 1; break; case 1: break; } } // キーを押した場合 void KeyPressed( KeyEvent e ){ int key; key = e.getKeyCode(); switch( key ){ // 上 case KeyEvent.VK_UP: KeyState |= KEY_UP; break; // 右 case KeyEvent.VK_RIGHT: KeyState |= KEY_RIGHT; break; // 下 case KeyEvent.VK_DOWN: KeyState |= KEY_DOWN; break; // 左 case KeyEvent.VK_LEFT: KeyState |= KEY_LEFT; break; // 決定 case KeyEvent.VK_SPACE:case KeyEvent.VK_ENTER:case 0xe5:case KeyEvent.VK_Z: KeyState |= KEY_ENTER; break; // テスト case KeyEvent.VK_T: KeyState |= KEY_TEST; break; } } // キーを離した時 void KeyReleased( KeyEvent e ){ int key; key = e.getKeyCode(); switch( key ){ // 上 case KeyEvent.VK_UP: KeyState &= ~KEY_UP; break; // 右 case KeyEvent.VK_RIGHT: KeyState &= ~KEY_RIGHT; break; // 下 case KeyEvent.VK_DOWN: KeyState &= ~KEY_DOWN; break; // 左 case KeyEvent.VK_LEFT: KeyState &= ~KEY_LEFT; break; // 決定 case KeyEvent.VK_SPACE:case KeyEvent.VK_ENTER:case 0xe5:case KeyEvent.VK_Z: KeyState &= ~KEY_ENTER; break; // テスト case KeyEvent.VK_T: KeyState &= ~KEY_TEST; break; } } // その方向に障害物があるかチェック(マップとキャラ) boolean IsCanWalkByDir( int px, int py, int dir ){ boolean walk_flag; // 縮小マップ(飛行船モードならOK) if( this.now_phase == TO_SKY_PHASE ){ return true; } // 座標変換 int x = px / MapManage.CHIP_SIZE; int y = py / MapManage.CHIP_SIZE; // 上 if( dir == BasicManage.DIR_UP ){ y--; } // 右 else if( dir == BasicManage.DIR_RIGHT ){ x++; } // 下 else if( dir == BasicManage.DIR_DOWN ){ y++; } // 左 else if( dir == BasicManage.DIR_LEFT ){ x--; } // ループマップじゃなくて領域外なら無理 if( !applet.IsLoopMap() ){ if( x < 0 || y < 0 || x >= MapManage.GetInstance().width || y >= MapManage.GetInstance().height ) return false; } // ループマップの場合 else{ // 領域外ならループさせる if( x < 0 ) x = MapManage.GetInstance().width + x; if( y < 0 ) y = MapManage.GetInstance().height + y; if( x >= MapManage.GetInstance().width ) x = x - MapManage.GetInstance().width; if( y >= MapManage.GetInstance().height ) y = y - MapManage.GetInstance().height; } // そこに通過フラグのないキャラがいたら無理 Chara chara = CharaManage.GetInstance().SearchChara( x, y ); if( chara != null && !chara.GetMoveFlag() ){ walk_flag = false; } // 上層レイヤーが通行可能なら、下層レイヤーが通行不可能でも通れる(橋など対策) else if( MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ x ][ y ] ) > 0 && MapManage.GetInstance().MapUpCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ x ][ y ] ) ].GetWalkFlag() >= 1 ){ walk_flag = true; } // 上層レイヤーが通行不可能なら確実に通れない else if( MapManage.GetInstance().MapUpCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ x ][ y ] ) ].GetWalkFlag() == 0 ){ walk_flag = false; } // 下層レイヤーが通行不可能 else if( MapManage.GetInstance().MapDownCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapData[ x ][ y ] ) ].GetWalkFlag() == 0 ){ walk_flag = false; } else walk_flag = true; return walk_flag; } void BasicKeyAction(){ switch( now_phase ){ case NORMAL_PHASE: case TO_SKY_PHASE: NormalKeyAction(); break; // 会話中 case TALK_PHASE: // 決定を押した瞬間 if( ( ~PrevKeyState & KeyState & KEY_ENTER ) != 0 ){ // 会話が終了するまでは受け付けない if( TalkManage.GetInstance().IsExitTalk() ){ // スクリプトの続きを読む if( TalkManage.GetInstance().NextCommand.equals("#nextpage") ){ //DebugPrint("続き読む"); TalkManage.GetInstance().AnalyzeScript(); }else{ //DebugPrint("最初へ"); // 最初へ now_phase = NORMAL_PHASE; } } } break; } // 前回のキー格納 PrevKeyState = KeyState; } // 待機中キーボード処理 void NormalKeyAction(){ int i; // 主人公取得 Player player = PlayerManage.GetInstance().GetPlayerInstance( 0 ); // 歩いていない時 if( !player.WalkingFlag ){ // プレイヤーの移動開始 if( (KeyState & KEY_UP) != 0 ){ player.SetDir( BasicManage.DIR_UP ); // その方向に障害物があるかチェック(マップとキャラ) player.WalkingFlag = IsCanWalkByDir( player.px, player.py, BasicManage.DIR_UP ); } if( (KeyState & KEY_RIGHT) != 0 ){ player.SetDir( BasicManage.DIR_RIGHT ); player.WalkingFlag = IsCanWalkByDir( player.px, player.py, BasicManage.DIR_RIGHT ); } if( (KeyState & KEY_DOWN) != 0 ){ player.SetDir( BasicManage.DIR_DOWN ); player.WalkingFlag = IsCanWalkByDir( player.px, player.py, BasicManage.DIR_DOWN ); } if( (KeyState & KEY_LEFT) != 0 ){ player.SetDir( BasicManage.DIR_LEFT ); player.WalkingFlag = IsCanWalkByDir( player.px, player.py, BasicManage.DIR_LEFT ); } // 決定キー(話/調べる) if( ( ~PrevKeyState & KeyState & KEY_ENTER ) != 0 ){ // 向いてる方向をチェック Chara chara = SetTalkPointForKey( player.px, player.py, player.dir ); // キャラいた? if( chara != null ){ //DebugPrint("話キャラ発見"); // そのキャラをこっちに向かせる(主人公と逆向き) int dir = 0; if( player.GetDir() == 0 ) dir = 2; else if( player.GetDir() == 1 ) dir = 3; else if( player.GetDir() == 2 ) dir = 0; else if( player.GetDir() == 3 ) dir = 1; chara.SetDir( dir ); // トークフェイズへ TalkManage.GetInstance().SetTargetChara( chara ); TalkManage.GetInstance().Initialize(); now_phase = TALK_PHASE; } } // テストキー if( ( KeyState & KEY_TEST ) != 0 ){ } } // 歩いている時 if( player.WalkingFlag ){ boolean walk_stop; // 移動完了フラグ walk_stop = player.WalkAction(); // 領域外チェック player.AreaOutCheck( applet.IsLoopMap(), MapManage.GetInstance().width * MapManage.CHIP_SIZE, MapManage.GetInstance().height * MapManage.CHIP_SIZE ); boolean my_walk_flag = player.WalkingFlag; // イベントチェック if( walk_stop ){ // そこに主人公と接触イベントはあるのかい? Chara chara = CharaManage.GetInstance().SearchChara( player.px / MapManage.CHIP_SIZE, player.py / MapManage.CHIP_SIZE, 1 ); if( chara != null ){ // トークフェイズへ TalkManage.GetInstance().SetTargetChara( chara ); TalkManage.GetInstance().Initialize(); now_phase = TALK_PHASE; DebugPrint("イベント開始"); } } // 軌跡を残す player.PutHistory(); // 仲間は主人公の軌跡を辿る Player prev_player; int frame = MapManage.CHIP_SIZE / player.GetMoveSpeed(); for( i = 1; i < PlayerManage.PLAYER_MAX; i++ ){ prev_player = PlayerManage.GetInstance().GetPlayerInstance( i-1 ); player = PlayerManage.GetInstance().GetPlayerInstance( i ); // 前の人のchip/speed=4フレーム前の座標にセット player.px = prev_player.GetPxHistory( frame ); player.py = prev_player.GetPyHistory( frame ); player.dir = prev_player.GetDirHistory( frame ); player.WalkingFlag = my_walk_flag; player.PutHistory(); } } // カメラ調整 SetCameraPosition(); } // カメラ座標を主人公プレイヤーと同じにする。 void SetCameraPosition(){ Player player = PlayerManage.GetInstance().GetPlayerInstance( 0 ); int px = player.px + MapManage.GetInstance().CHIP_SIZE / 2; int py = player.py + MapManage.GetInstance().CHIP_SIZE / 2; // 端対策をきっちり(ループマップではない時) if( !applet.IsLoopMap() ){ if( px < MapManage.WIDTH / 2 ){ px = MapManage.WIDTH / 2; } else if( px > MapManage.GetInstance().width * MapManage.GetInstance().CHIP_SIZE - MapManage.WIDTH / 2 ){ px = MapManage.GetInstance().width * MapManage.GetInstance().CHIP_SIZE - MapManage.WIDTH / 2; } if( py < MapManage.HEIGHT / 2 ){ py = MapManage.HEIGHT / 2; } else if( py > MapManage.GetInstance().height * MapManage.GetInstance().CHIP_SIZE - MapManage.HEIGHT / 2 ){ py = MapManage.GetInstance().height * MapManage.GetInstance().CHIP_SIZE - MapManage.HEIGHT / 2; } } applet.SetCamera( px, py ); } // 移動範囲初期化 void MoveSelectInit(){ int i, j; //DebugPrint("移動範囲初期化"); // マップ情報の初期化 LightMapData = new byte[ MapManage.GetInstance().width ][ MapManage.GetInstance().height ]; mvrec = new String[ MapManage.GetInstance().width ][ MapManage.GetInstance().height ]; for( i = 0; i < MapManage.GetInstance().width; i++ ){ for( j = 0; j < MapManage.GetInstance().height; j++ ){ LightMapData[i][j] = 1; mvrec[i][j] = new String(""); } } // 座標系に int chara_x = m_selected_chara.px / MapManage.CHIP_SIZE; int chara_y = m_selected_chara.py / MapManage.CHIP_SIZE; // 四方向にアンカーを伸ばす Search( chara_x, chara_y - 1, LENGTH, 1, "1" ); Search( chara_x + 1, chara_y, LENGTH, 2, "2" ); Search( chara_x, chara_y + 1, LENGTH, 3, "3" ); Search( chara_x - 1, chara_y, LENGTH, 4, "4" ); // 今の場所は行けない LightMapData[ chara_x ][ chara_y ] = 1; } // 移動処理 void MoveChara(){ if( m_selected_chara != null ){ // 目的値に向かって進め // 座標系に int point_x = moved_x / 16; int point_y = moved_y / 16; // 初期化 switch( MovePhase ){ case 0: if( LightMapData[ point_x ][ point_y ] == 0 ){ // 到着してない if( !(m_selected_chara.px == moved_x && m_selected_chara.py == moved_y) ){ // いけ golast = mvrec[ point_x ][ point_y ].length(); //DebugPrint("str="+mvrec[ point_x ][ point_y ]+"golast="+golast); MovePhase++; // 移動開始 m_selected_chara.WalkingFlag = true; } }else{ now_phase = NORMAL_PHASE; } break; case 1: String sr = mvrec[ point_x ][ point_y ]; final int CHARA_SPEED = 4; // 指定の距離の文字(方角が格納)を取り出す if( sr.charAt( goflag ) == '1' ){ m_selected_chara.py -= CHARA_SPEED; m_selected_chara.SetDir( CharaManage.DIR_UP ); } if( sr.charAt( goflag ) == '2' ){ m_selected_chara.px += CHARA_SPEED; m_selected_chara.SetDir( CharaManage.DIR_RIGHT ); } if( sr.charAt( goflag ) == '3' ){ m_selected_chara.py += CHARA_SPEED; m_selected_chara.SetDir( CharaManage.DIR_DOWN ); } if( sr.charAt( goflag ) == '4' ){ m_selected_chara.px -= CHARA_SPEED; m_selected_chara.SetDir( CharaManage.DIR_LEFT ); } m_selected_chara.WaitTimer += CHARA_SPEED; if( m_selected_chara.WaitTimer >= 16 ){ m_selected_chara.WaitTimer = 0; goflag++; } // ゴール if( goflag >= golast ){ //DebugPrint( "ゴール" ); goflag = 0; now_phase = NORMAL_PHASE; MovePhase = 0; m_selected_chara.WalkingFlag = false; // そこに主人公と接触イベントはあるのかい? Chara chara = CharaManage.GetInstance().SearchChara( point_x, point_y, 1 ); if( chara != null ){ // トークフェイズへ TalkManage.GetInstance().SetTargetChara( chara ); TalkManage.GetInstance().Initialize(); now_phase = TALK_PHASE; DebugPrint("おい"); } } break; } } } // 基本描画 void BasicDraw(){ switch( now_phase ){ case NORMAL_PHASE: // 枠 //DrawSelectRect(); break; case CHARA_SELECT_PHASE: // メニュー表示 DrawMenu(); break; case MOVE_SELECT_PHASE: // 移動できる範囲表示 DrawCanMoveArea(); break; case MOVE_PHASE: break; // 話し相手選択フェイズ case TALK_SELECT_PHASE: TalkManage.GetInstance().DrawCanTalkArea( m_selected_chara.px, m_selected_chara.py ); break; // 会話中フェイズ case TALK_PHASE: TalkManage.GetInstance().DrawTalkWindow(); break; } // デバッグ情報 DrawDebugInfo(); } // デバッグ情報ウィンドウ void DrawDebugInfoWindow(){ // バージョン情報 fillRectToMemory( MapCanvas.GetInstance().GetOffPix(), 0 , MapManage.HEIGHT - FONT_SIZE, FONT_SIZE*9, FONT_SIZE, 0xFF000080 ); } // デバッグ情報 void DrawDebugInfo(){ Player player = PlayerManage.GetInstance().GetPlayerInstance( 0 ); // バージョン情報 g.setColor( Color.white ); //g.drawString( "("+player.px+","+player.py+")", 0, 240 - 2 ); g.drawString( "ver:13.1 F:"+(MapCanvas.FrameTime/10)+(MapCanvas.FrameTime%10)+ " "+(m_game_hour/10)+(m_game_hour%10) + "時"+(m_game_minute/10)+(m_game_minute%10)+"分", 0, MapManage.HEIGHT - 2 ); // ゲーム内時刻 } // ピクセル操作用 void BasicDrawForPixel( int OffPix[] ){ switch( now_phase ){ case CHARA_SELECT_PHASE: // メニューウィンドウ DrawMenuWindow( OffPix ); break; case TALK_PHASE: // 会話ウィンドウ TalkManage.GetInstance().DspDrawTalkWindow( OffPix ); break; } } // メニューウィンドウ void DrawMenuWindow( int OffPix[] ){ // 表示開始位置は、キャラの隣 int chara_x = m_selected_chara.px; int chara_y = m_selected_chara.py; // スクリーン座標へ int start_x = CharaManage.GetInstance().ToScreenX( chara_x ); int start_y = CharaManage.GetInstance().ToScreenY( chara_y ); fillRectToMemory( OffPix, start_x, start_y, 70, 50, 0x80000000 ); } // 移動先指定 boolean SetMovePoint( int x, int y ){ int world_x, world_y, len; // ワールド座標に変換 world_x = x / MapManage.CHIP_SIZE; world_x += MapManage.GetInstance().GetNowIndex().x; world_y = y / MapManage.CHIP_SIZE; world_y += MapManage.GetInstance().GetNowIndex().y; // 移動先 moved_x = world_x * MapManage.CHIP_SIZE; moved_y = world_y * MapManage.CHIP_SIZE; return true; } // 話し相手指定 Chara SetTalkPoint( int x, int y ){ int world_x, world_y, len; // ワールド座標に変換 world_x = x / MapManage.CHIP_SIZE; world_x += MapManage.GetInstance().GetNowIndex().x; world_y = y / MapManage.CHIP_SIZE; world_y += MapManage.GetInstance().GetNowIndex().y; // 方角確認 int dir = 0; // 上 if( m_selected_chara.py / MapManage.CHIP_SIZE > world_y ){ dir = 0; } // 右 else if( m_selected_chara.px / MapManage.CHIP_SIZE < world_x ){ dir = 1; } // 下 else if( m_selected_chara.py / MapManage.CHIP_SIZE < world_y ){ dir = 2; } // 左 else if( m_selected_chara.px / MapManage.CHIP_SIZE > world_x ){ dir = 3; } // その方向セット(自分) m_selected_chara.SetDir( dir ); // その場所は会話範囲? if( LightMapData[ world_x ][ world_y ] == 0 ){ // イベント開始方法が「話す・調べる」のキャラがいるか検索 Chara chara = CharaManage.GetInstance().SearchChara( world_x, world_y, 0 ); // もしいなくて、そこがカウンター属性のチップなら、さらにその先を調べる。 if( chara == null && MapManage.GetInstance().GetMapCell( world_x, world_y ).GetElement() == 1 ){ // 主人公の方向より先 if( m_selected_chara.GetDir() == 0 ){ world_y--; } else if( m_selected_chara.GetDir() == 1 ){ world_x++; } else if( m_selected_chara.GetDir() == 2 ){ world_y++; } else if( m_selected_chara.GetDir() == 3 ){ world_x--; } chara = CharaManage.GetInstance().SearchChara( world_x, world_y ); } // イベントスクリプト取得 return chara; }else{ return null; } } // 話し相手指定(キーボード操作) Chara SetTalkPointForKey( int px, int py, int dir ){ int x = px / MapManage.CHIP_SIZE; int y = py / MapManage.CHIP_SIZE; if( dir == CharaManage.DIR_UP ) y--; if( dir == CharaManage.DIR_RIGHT ) x++; if( dir == CharaManage.DIR_DOWN ) y++; if( dir == CharaManage.DIR_LEFT ) x--; // 領域外なら無理 if( x < 0 || y < 0 || x >= MapManage.GetInstance().width || y >= MapManage.GetInstance().height ) return null; // イベント開始方法が「話す・調べる」のキャラがいるか検索 Chara chara = CharaManage.GetInstance().SearchChara( x, y, 0 ); // もしいなくて、そこがカウンター属性のチップなら、さらにその先を調べる。 if( chara == null && MapManage.GetInstance().GetMapCell( x, y ).GetElement() == 1 ){ // 主人公の方向より先 if( dir == 0 ){ y--; } else if( dir == 1 ){ x++; } else if( dir == 2 ){ y++; } else if( dir == 3 ){ x--; } chara = CharaManage.GetInstance().SearchChara( x, y ); } // イベントスクリプト取得 return chara; } // キャラ検索 void SearchChara( int x, int y ){ int world_x, world_y; // ワールド座標に変換 world_x = x / MapManage.CHIP_SIZE; world_x += MapManage.GetInstance().GetNowIndex().x; world_y = y / MapManage.CHIP_SIZE; world_y += MapManage.GetInstance().GetNowIndex().y; // キャラマネージャーに任せる Chara chara = CharaManage.GetInstance().SearchChara( world_x, world_y ); if( chara != null ){ // イベント開始方法が「話す・調べる」以外の時は抜ける if( chara.GetEventWay() != 0 ){return;} // キャラがいたらキャラセレクトフェイズへ now_phase = CHARA_SELECT_PHASE; m_selected_chara = chara; selected_menu_no = 0; menu_move_length = 0; // 移動可能範囲初期化 MoveSelectInit(); }else{ } } void Search( int ax, int ay, int mv, int di, String mway ){ int down, num; // 領域外 if( ax < 0 || ay < 0 || ax >= MapManage.GetInstance().width || ay >= MapManage.GetInstance().height ) return; // 最短経路更新? if( !mvrec[ ax ][ ay ].equals("") && mway.length() > mvrec[ ax ][ ay ].length() ) return; down = 0; // 通行不可能エリア? // そこに通過フラグのないキャラがいたら無理 Chara chara = CharaManage.GetInstance().SearchChara( ax, ay ); if( chara != null && !chara.GetMoveFlag() ){ down = 1000; } // 上層レイヤーが通行可能なら、下層レイヤーが通行不可能でも通れる(橋など対策) else if( MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ ax ][ ay ] ) > 0 && MapManage.GetInstance().MapUpCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ ax ][ ay ] ) ].GetWalkFlag() >= 1 ){ down = 1; } // 上層レイヤーが通行不可能なら確実に通れない else if( MapManage.GetInstance().MapUpCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapUpData[ ax ][ ay ] ) ].GetWalkFlag() == 0 ){ down = 1000; } // 下層レイヤーが通行不可能 else if( MapManage.GetInstance().MapDownCell[ MapManage.GetInstance().ToUnsignedByte( MapManage.GetInstance().MapData[ ax ][ ay ] ) ].GetWalkFlag() == 0 ){ down = 1000; } else down = 1; // 移動できない場合 if( mv - down < 0 ) return; LightMapData[ ax ][ ay ] = 0; mvrec[ ax ][ ay ] = mway; if( di != 3 ) Search( ax, ay - 1, mv - down, 1, mway + "1" ); if( di != 4 ) Search( ax + 1, ay, mv - down, 2, mway + "2" ); if( di != 1 ) Search( ax, ay + 1, mv - down, 3, mway + "3" ); if( di != 2 ) Search( ax - 1, ay, mv - down, 4, mway + "4" ); } // 移動できる範囲描画 void DrawCanMoveArea(){ int i, j; int x, y; int len; // 座標系に int chara_x = m_selected_chara.px / MapManage.CHIP_SIZE; int chara_y = m_selected_chara.py / MapManage.CHIP_SIZE; // 描画 g.setColor( Color.cyan ); for( y = chara_y - LENGTH; y <= chara_y + LENGTH; y++ ){ for( x = chara_x - LENGTH; x <= chara_x + LENGTH; x++ ){ // 主人公との距離がLENGTH以内だけ描画 len = abs( chara_x - x ) + abs( chara_y - y ); if( len <= LENGTH && len >= 1 && x >= 0 && y >= 0 && x < MapManage.GetInstance().width && y < MapManage.GetInstance().height ){ // その場所が通行不可なら何も描かない if( 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 DrawSelectRect(){ g.setColor( Color.white ); g.drawRect( (select_x - MapManage.GetInstance().GetNowIndex().x) * MapManage.CHIP_SIZE, (select_y - MapManage.GetInstance().GetNowIndex().y) * MapManage.CHIP_SIZE, MapManage.CHIP_SIZE - 1, MapManage.CHIP_SIZE - 1 ); } // 移動の上だけ明るく void MouseMoved( int x, int y ){ // 表示開始位置は、キャラの隣 int chara_x = m_selected_chara.px; int chara_y = m_selected_chara.py; // スクリーン座標へ int start_x = CharaManage.GetInstance().ToScreenX( chara_x ) + MapManage.CHIP_SIZE; int start_y = CharaManage.GetInstance().ToScreenY( chara_y ); int no = ( y - start_y ) / FONT_SIZE; if( no < 0 ){ selected_menu_no = 0; }else if( no > 2 ){ selected_menu_no = 2; }else{ selected_menu_no = no; } } // メニュー表示 void DrawMenu(){ // 表示開始位置は、キャラの隣 int chara_x = m_selected_chara.px; int chara_y = m_selected_chara.py; // スクリーン座標へ int start_x = CharaManage.GetInstance().ToScreenX( chara_x ); int start_y = CharaManage.GetInstance().ToScreenY( chara_y ); // 背景は黒 // 半透明にするためにピクセル操作で //g.setColor( new Color(0,0,0) ); //g.fillRect( start_x, start_y, 70, 50 ); // 選択しているところは青色 // 1文字14pixで計算 g.setColor( Color.blue ); g.fillRect( start_x + 1, start_y + 1 + selected_menu_no * 14, 68, 15 ); // 文字は白 230 170 g.setColor( Color.white ); g.drawString("移動", start_x + 4, start_y + 14 ); g.drawString("話す/調べる", start_x + 4, start_y + 28 ); g.drawString("たたかう", start_x + 4, start_y + 42 ); } //-------------------------------------------------- // メモリイメージに塗りつぶし円描画 // 中心XY 距離 色 //-------------------------------------------------- void fillOvalToMemory( int []off, int x, int y, int width, int height, int color ){ int xx, yy; int point; // これから描画しようとする方がsrc 元々書いてあったのがdest // 加算する色 int in_alpha = (color >> 24) & 0xff; int in_r = ( color >> 16 ) & 0xff; int in_g = ( color >> 8 ) & 0xff; int in_b = color & 0xff; // 元の色 int dis_r; int dis_g; int dis_b; for( yy = -height; yy < height; yy++ ){ for( xx = -width; xx < width; xx++ ){ // 領域外なら書き込まない if( x + xx < 0 || x + xx > MapManage.WIDTH ){ continue; } if( y + yy < 0 || y + yy > MapManage.HEIGHT ){ continue; } // 円の中心までの距離 if( width * width < xx * xx + yy * yy ){ continue; } // 書き込む場所 point = x + xx + (yy+y)*MapManage.WIDTH; if( point >= 0 && point < MapManage.WIDTH * MapManage.HEIGHT ){ // アルファブレンド dis_r = ( ( in_r - ( ( off[ point ] >> 16 ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] >> 16 ) & 0xff ); dis_g = ( ( in_g - ( ( off[ point ] >> 8 ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] >> 8 ) & 0xff ); dis_b = ( ( in_b - ( ( off[ point ] ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] ) & 0xff ); off[ point ] = (0xff<<24)|(dis_r<<16)|(dis_g<<8)|(dis_b); } } } } //-------------------------------------------------- // メモリイメージに塗りつぶし四角形描画(アルファブレンド) //-------------------------------------------------- void fillRectToMemory( int []off, int x, int y, int width, int height, int color ){ int xx, yy, yyy; int point, max_point; // これから描画しようとする方がsrc 元々書いてあったのがdest // 加算する色 int in_alpha = (color >> 24) & 0xff; int in_r = ( color >> 16 ) & 0xff; int in_g = ( color >> 8 ) & 0xff; int in_b = color & 0xff; // 出力する色 int dis_r; int dis_g; int dis_b; max_point = MapManage.WIDTH * MapManage.HEIGHT; for( yy = 0; yy < height; yy++ ){ yyy = (yy+y)*MapManage.WIDTH; for( xx = 0; xx < width; xx++ ){ // 領域外なら書き込まない if( x + xx < 0 || x + xx > MapManage.WIDTH ){ continue; } if( y + yy < 0 || y + yy > MapManage.HEIGHT ){ continue; } // 書き込む場所 point = x + xx + yyy; if( point >= 0 && point < max_point ){ // アルファブレンド // 元の色 * ( 256 - α ) / 256 + 加算の色 * α / 256 // = ( 元の色 * ( 256 - α ) + 加算の色 * α ) / 256 // = ( 元の色 * 256 - 元の色 * α + 加算の色 * α ) / 256 // = ( ( 加算の色 - 元の色 ) * α + 元の色 * 256 ) / 256 // = ( ( 加算の色 - 元の色 ) * α ) / 256 + 元の色 // = ( ( ( 加算の色 - 元の色 ) * α ) >> 8 ) + 元の色 if( in_alpha != 0xff ){ dis_r = ( ( in_r - ( ( off[ point ] >> 16 ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] >> 16 ) & 0xff ); dis_g = ( ( in_g - ( ( off[ point ] >> 8 ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] >> 8 ) & 0xff ); dis_b = ( ( in_b - ( ( off[ point ] ) & 0xff ) ) * in_alpha >> 8 ) + ( ( off[ point ] ) & 0xff ); off[ point ] = (0xff<<24)|(dis_r<<16)|(dis_g<<8)|(dis_b); }else{ off[ point ] = color; } } } } } //-------------------------------------------------- // フェードアウト //-------------------------------------------------- void FadeOutAction(){ FadeAlpha += 20; if( FadeAlpha > 0xFF ){ FadeAlpha = 0xFF; } } //-------------------------------------------------- // フェードイン //-------------------------------------------------- void FadeInAction(){ FadeAlpha -= 20; if( FadeAlpha < 0 ){ FadeAlpha = 0; } } //-------------------------------------------------- // フェード描画 //-------------------------------------------------- void DrawFade(){ if( FadeAlpha == 0 ) return; // 黒い四角形のアルファを変えてブレンドしていく手法 int color = 0x00000000; color |= FadeAlpha << 24; fillRectToMemory( MapCanvas.GetInstance().GetOffPix(), 0, 0, MapManage.WIDTH, MapManage.HEIGHT, color ); } //-------------------------------------------------- // 空を飛ぶ //-------------------------------------------------- void ToSky(){ // 世界を小さく switch( SkyPhase ){ // 待機状態 case 0: break; case 1: // 空へ初期化 MapManage.GetInstance().m_scale_per = 1.0f; m_map_scale_sate = SKY_SCALE_MAP; SkyPhase++; break; case 2: // 縮小率を操作 MapManage.GetInstance().m_scale_per += 0.02f; // 最大値 if( MapManage.GetInstance().m_scale_per > 2.0f ){ MapManage.GetInstance().m_scale_per = 2; SkyPhase++; } break; case 3: break; case 4: // 縮小率を操作 MapManage.GetInstance().m_scale_per -= 0.02f; // 着陸 if( MapManage.GetInstance().m_scale_per < 1.0f ){ this.SkyPhase++; this.m_map_scale_sate = NORMAL_SCALE_MAP; this.now_phase = NORMAL_PHASE; } break; case 5: break; } } //-------------------------------------------------- // エンカウント初期化 //-------------------------------------------------- void EnCountInit(){ this.now_phase = ENCOUNT_PHASE; SkyPhase = 1; } //-------------------------------------------------- // エンカウント //-------------------------------------------------- void EnCountAction(){ // 世界を拡大 switch( SkyPhase ){ // 待機状態 case 0: break; case 1: // 初期化 MapManage.GetInstance().m_scale_per = 1.0f; m_map_scale_sate = ENCOUNT_MAP; SkyPhase++; break; case 2: MapManage.GetInstance().m_scale_per -= 0.04f; // ある程度大きくなれば、一旦逆の流れ if( MapManage.GetInstance().m_scale_per < 0.5f ){ SkyPhase++; } break; case 3: MapManage.GetInstance().m_scale_per += 0.04f; // ある程度小さくなれば、逆の流れ if( MapManage.GetInstance().m_scale_per > 0.7f ){ SkyPhase++; // フェードアウト開始 FadeAlpha = 0x00; } break; case 4: // 縮小率を操作 MapManage.GetInstance().m_scale_per -= 0.04f; // フェード FadeOutAction(); // 最大 if( MapManage.GetInstance().m_scale_per < 0.2f ){ // シーン暗転 applet.ChangeMap( "1203065187" ); // プレイヤー配置 BattleManage.GetInstance().SetPlayers(); // カメラ調整 SetCameraPosition(); SkyPhase++; // 通常スケールのマップへ m_map_scale_sate = NORMAL_SCALE_MAP; } break; case 5: // 戦闘用のマップをロード // フェードイン開始 FadeInAction(); // 終了 if( FadeAlpha == 0 ){ SubPhase++; // バトルフェイズへ now_phase = BATTLE_PHASE; BattleManage.GetInstance().Initialize(); } break; } } }