#東方弾幕風 #Title[プロトタイプ:「二つの月・其の壱(仮)」] #Text[ 交互に実体化する幻視。 ] #Image[.\Proto-「二つの月・其の壱(仮)」.png] #BackGround[Default] #BGM[.\music\Reisen.wav] #ScriptVersion[2] /********************************************************************* * プロトタイプ 「二つの月・其の壱(仮)」 * * 狂符「幻視調律(ビジョナリチューニング)」の上下挟撃バージョン。 * 幻視は交互に実体化する。 ********************************************************************/ /** * TODO: 激しく処理落ちするのをなんとかしないと…。 * ↓ * どのへんが足を引っ張ってるのか調べてみました。多少速くなったと思い * ますが、リライトして頂いたものに比べるとまだまだ見劣りします。 * * * 弾の速度計算をループ内で行うのをやめて、ループ外で幻視/非幻視時の * 速度をあらかじめ計算 * * -> ほとんど効果がなかった。 * * * ボスのグラフィックを毎回設定せず @Initialize で1回だけ設定する * * -> 効果なし。 * * * obj_* 系の関数を全て組み込み関数を使うように置き換える * * -> 30fps -> 45fps に上がった。関数呼び出しのオーバヘッドはかなり大き * いようだ。 * * * constな(つもりの)変数をすべてマジックナンバーに書き換える * * -> いまいち効果なし。もっとも配列を使ってるところは簡単には書き換え * られないのでなんともいえないが。 * * * Obj_SetSpeed() を利用する(もしこれが効果あるなら、弾の向きと移動方向 * は独立にするよう要望しなきゃならない) * * -> 効果なし。かえって微妙に遅くなった気もするのでやめました。 * * * 毎回 vector_angle() で角度計算するのをやめる * * -> 予想に反してほとんど効果がない。 * * 見直してみるとかなり無駄な計算を行っていたが、それが重くなる原因か * というとそうでもないらしい。関数呼び出し、および配列/変数の参照にか * なりのオーバヘッドがかかっているんじゃないだろうか…。 */ script_enemy_main { /***************************************************************** * 描画関連パラメータ ****************************************************************/ let ENEMY_IMG_SIZE = [64, 64]; let ENEMY_IMG_FRONT = PATH("image\dot\ExRumia.png"); let ENEMY_IMG_FRONT_RECT = [0, 0, ENEMY_IMG_SIZE[0]-1, ENEMY_IMG_SIZE[1]-1]; let CUTIN_ENABLE = true; let CUTIN_TYPE = YOUMU; let CUTIN_NAME = "「二つの月・其の壱(仮)」"; let CUTIN_IMG = PATH("image\stand\ExRumia.png"); let CUTIN_IMG_SIZE = [360, 360]; let CUTIN_IMG_RECT = [0, 0, CUTIN_IMG_SIZE[0]-1, CUTIN_IMG_SIZE[1]-1]; let RESOURCE_GRAPHIC = [ ENEMY_IMG_FRONT ]; /***************************************************************** * 各種定数 ****************************************************************/ /** 幻視状態ID */ let PH_NONE = 0; let PH_1 = 1; let PH_2 = 2; /***************************************************************** * 弾幕関連パラメータ ****************************************************************/ let SPELL_TIME_LIMIT = 50; // 時間制限(sec) let SPELL_IS_DURABLE = false; // 耐久弾幕か? let SPELL_IS_LAST = false; // ラストスペルか? let SPELL_BONUS = 1000000; // スペルカードボーナス基本値 /** 敵キャラ */ let ENEMY_INITIAL_POS = [GetCenterX(), GetClipMinY() + 60]; // 初期位置 let ENEMY_HIT_SIZE = 16.0; // 当たり判定の半径 let ENEMY_INITIAL_DMG_RATE = [30.0, 30.0]; // 初期ダメージレート /** 幻視 */ let PHANTASM_INITIAL_DELAY = 120; // 最初の幻視までの時間(frames) let PHANTASM_INTERVAL = 120; // 幻視が切り替わる間隔(frames) /** 使い魔 */ let FAMILIAR_SOURCE = [ // 使い魔出現地点 [GetClipMinX(), GetClipMinY()], // 画面左上隅 [GetClipMaxX(), GetClipMinY()], // 画面右上隅 [GetClipMinX(), GetClipMaxY()], // 画面左下隅 [GetClipMaxX(), GetClipMaxY()] // 画面右下隅 ]; let FAMILIAR_SOURCE_RAND = [ // 実際の使い魔出現地点に加味するズレ [[0, 0], [0, 45]], [[0, 0], [0, 45]], [[0, 0], [0, -45]], [[0, 0], [0, -45]] ]; let FAMILIAR_SPEED = 1.0; // 使い魔の移動スピード let FAMILIAR_VEL = [ // 各地点より出現する使い魔の速度 [ FAMILIAR_SPEED, 0.0], // 右へ移動 [-FAMILIAR_SPEED, 0.0], // 左へ移動 [ FAMILIAR_SPEED, 0.0], // 右へ移動 [-FAMILIAR_SPEED, 0.0] // 左へ移動 ]; let FAMILIAR_VEL_ANGLE = [ // その極座標形式(毎回計算するのを避けるため) [vector_distance(FAMILIAR_VEL[0]), vector_angle(FAMILIAR_VEL[0])], [vector_distance(FAMILIAR_VEL[1]), vector_angle(FAMILIAR_VEL[1])], [vector_distance(FAMILIAR_VEL[2]), vector_angle(FAMILIAR_VEL[2])], [vector_distance(FAMILIAR_VEL[3]), vector_angle(FAMILIAR_VEL[3])] ]; let FAMILIAR_PH_ID = [ // 各地点より出現した使い魔が発射する弾の幻視ID PH_1, PH_1, PH_2, PH_2 ]; let FAMILIAR_BULLET = [ // 各地点より出現した使い魔が発射する弾 RED23, BLUE23, BLUE23, RED23 ]; let FAMILIAR_DELETE_MARGIN = 8.0; // 使い魔が画面外のこの距離まで遠ざかったら削除する let FAMILIAR_DELAY = [30, 0, 30, 0]; // 各地点で召喚を開始するまでのディレイ(frames) let FAMILIAR_INTERVAL_RANGE = [90, 120]; // 召喚間隔の上限、下限(frames) let FAMILIAR_GRAPHIC = WHITE01; // 使い魔のグラフィック /** 壁 */ let WALL_INTERVAL = 10; // 連射間隔(frames) let WALL_SPEED = FAMILIAR_SPEED; // 非幻視状態時のスピード let WALL_SPEED_PH = FAMILIAR_SPEED; // 幻視状態時のスピード let WALL_LOOP_MARGIN = 8; // 画面端でループする際の画面外マージン let WALL_ALPHA = 255; // 非幻視状態でのα値 let WALL_ALPHA_PH = 128; // 幻視状態でのα値 /***************************************************************** * 弾幕本体 ****************************************************************/ // let phantasm = PH_NONE; // 幻視状態 let phantasm = 0; // 幻視状態 task main() { // 一回 @MainLoop を実行しておく yield; control_phantasm(); ascent(i in 0 .. length(FAMILIAR_SOURCE)){ summon_familiar(i); } } task control_phantasm() { // WAIT(PHANTASM_INITIAL_DELAY); WAIT(120); loop{ // phantasm = [PH_2, PH_1][phantasm == PH_NONE || phantasm == PH_2]; phantasm = [2,1][phantasm == 0 || phantasm == 2]; // WAIT(PHANTASM_INTERVAL); WAIT(120); } } task summon_familiar(source_id) { WAIT(FAMILIAR_DELAY[source_id]); loop{ let rand_x = (FAMILIAR_SOURCE_RAND[source_id])[0]; let rand_y = (FAMILIAR_SOURCE_RAND[source_id])[1]; let dpos = [rand(rand_x[0], rand_x[1]), rand(rand_y[0], rand_y[1])]; let pos = FAMILIAR_SOURCE[source_id] + dpos; // let familiar = shot_new(pos, 0, FAMILIAR_GRAPHIC); let familiar = shot_new(pos, 0, WHITE01); // obj_set_bomb_resist(familiar, true); ObjShot_SetBombResist(familiar, true); create_wall(source_id, familiar); // let frames = rand_int(FAMILIAR_INTERVAL_RANGE[0], FAMILIAR_INTERVAL_RANGE[1]); let frames = rand_int(90, 120); loop(frames){ while(phantasm == FAMILIAR_PH_ID[source_id]) { WAIT(1); } WAIT(1); } } } task create_wall(source_id, familiar) { fire_shot(source_id, familiar); // while(obj_get_x(familiar) >= GetClipMinX() - FAMILIAR_DELETE_MARGIN && // obj_get_x(familiar) <= GetClipMaxX() + FAMILIAR_DELETE_MARGIN && // obj_get_y(familiar) >= GetClipMinY() - FAMILIAR_DELETE_MARGIN && // obj_get_y(familiar) <= GetClipMaxY() + FAMILIAR_DELETE_MARGIN){ // while(Obj_GetX(familiar) >= GetClipMinX() - FAMILIAR_DELETE_MARGIN && // Obj_GetX(familiar) <= GetClipMaxX() + FAMILIAR_DELETE_MARGIN && // Obj_GetY(familiar) >= GetClipMinY() - FAMILIAR_DELETE_MARGIN && // Obj_GetY(familiar) <= GetClipMaxY() + FAMILIAR_DELETE_MARGIN){ while(Obj_GetX(familiar) >= GetClipMinX() - 8 && Obj_GetX(familiar) <= GetClipMaxX() + 8 && Obj_GetY(familiar) >= GetClipMinY() - 8 && Obj_GetY(familiar) <= GetClipMaxY() + 8){ // obj_move_rel(familiar, FAMILIAR_VEL[source_id]); Obj_SetX(familiar, Obj_GetX(familiar) + (FAMILIAR_VEL[source_id])[0]); Obj_SetY(familiar, Obj_GetY(familiar) + (FAMILIAR_VEL[source_id])[1]); while(phantasm == FAMILIAR_PH_ID[source_id]) { WAIT(1); } WAIT(1); } // obj_delete(familiar); Obj_Delete(familiar); } task fire_shot(source_id, familiar) { // while(!obj_is_deleted(familiar)){ while(!Obj_BeDeleted(familiar)){ ascent(i in 0 .. 2){ let bullet = FAMILIAR_BULLET[source_id]; // let shot = shot_new(obj_get_pos(familiar), 0, bullet); let shot = Obj_Create(OBJ_SHOT); Obj_SetX(shot, Obj_GetX(familiar)); Obj_SetY(shot, Obj_GetY(familiar)); ObjShot_SetGraphic(shot, bullet); let fam_dir = FAMILIAR_VEL_ANGLE[source_id]; // obj_set_dir(shot, [fam_dir+90.0, fam_dir-90.0][i==1]); Obj_SetAngle(shot, [fam_dir+90.0, fam_dir-90.0][i==1]); // obj_set_bomb_resist(shot, true); control_shot(source_id, shot); } // let frames = WALL_INTERVAL; let frames = 10; loop(frames){ while(phantasm == FAMILIAR_PH_ID[source_id]) { WAIT(1); } WAIT(1); } } } task control_shot(source_id, shot) { // let vel = get_shot_velocity(source_id, shot); let ph_id = FAMILIAR_PH_ID[source_id]; let ph_prev = phantasm; // let vel_ph = polar2rect([WALL_SPEED_PH, FAMILIAR_VEL_ANGLE[source_id]+180.0]); // let vel_normal = polar2rect([WALL_SPEED, obj_get_dir(shot)]); let vel_ph = polar2rect([2.0, FAMILIAR_VEL_ANGLE[source_id]+180.0]); let vel_normal = polar2rect([2.0, Obj_GetAngle(shot)]); let vel = [vel_normal, vel_ph][phantasm == ph_id]; // while(!obj_is_deleted(shot)){ while(!Obj_BeDeleted(shot)){ if(phantasm != ph_prev && phantasm == ph_id){ // 幻視状態に切り替わったとき vel = vel_ph; // obj_set_collision_player(shot, false); // obj_set_alpha(shot, WALL_ALPHA_PH); Obj_SetCollisionToPlayer(shot, false); // Obj_SetAlpha(shot, WALL_ALPHA_PH); Obj_SetAlpha(shot, 128); } else if(phantasm != ph_prev && phantasm != PH_NONE && phantasm != ph_id){ // 非幻視状態に切り替わったとき vel = vel_normal; // obj_set_collision_player(shot, true); // obj_set_alpha(shot, WALL_ALPHA); Obj_SetCollisionToPlayer(shot, true); // Obj_SetAlpha(shot, WALL_ALPHA); Obj_SetAlpha(shot, 255); } // obj_move_rel(shot, vel); Obj_SetX(shot, Obj_GetX(shot) + vel[0]); Obj_SetY(shot, Obj_GetY(shot) + vel[1]); loop_shot(source_id, shot); ph_prev = phantasm; WAIT(1); } } // function get_shot_velocity(source_id, shot) // { // if(phantasm == FAMILIAR_PH_ID[source_id]){ // return polar2rect([WALL_SPEED_PH, FAMILIAR_VEL_ANGLE[source_id]+180.0]); // } // else{ // return polar2rect([WALL_SPEED, obj_get_dir(shot)]); // } // } function loop_shot(source_id, shot){ // if(obj_get_dir(shot) % 180.0 == 0){ // if(obj_get_y(shot) < GetClipMinY()-WALL_LOOP_MARGIN){ // obj_set_y(shot, GetClipMaxY()+WALL_LOOP_MARGIN); // } // if(obj_get_y(shot) > GetClipMaxY()+WALL_LOOP_MARGIN){ // obj_set_y(shot, GetClipMinY()-WALL_LOOP_MARGIN); // } // } // else{ // if(obj_get_x(shot) < GetClipMinX()-WALL_LOOP_MARGIN){ // obj_set_x(shot, GetClipMaxX()+WALL_LOOP_MARGIN); // } // if(obj_get_x(shot) > GetClipMaxX()+WALL_LOOP_MARGIN){ // obj_set_x(shot, GetClipMinX()-WALL_LOOP_MARGIN); // } // } // if(Obj_GetAngle(shot) % 180.0 == 0){ // if(Obj_GetY(shot) < GetClipMinY()-WALL_LOOP_MARGIN){ // Obj_SetY(shot, GetClipMaxY()+WALL_LOOP_MARGIN); // } // if(Obj_GetY(shot) > GetClipMaxY()+WALL_LOOP_MARGIN){ // Obj_SetY(shot, GetClipMinY()-WALL_LOOP_MARGIN); // } // } // else{ // if(Obj_GetX(shot) < GetClipMinX()-WALL_LOOP_MARGIN){ // Obj_SetX(shot, GetClipMaxX()+WALL_LOOP_MARGIN); // } // if(Obj_GetX(shot) > GetClipMaxX()+WALL_LOOP_MARGIN){ // Obj_SetX(shot, GetClipMinX()-WALL_LOOP_MARGIN); // } // } if(Obj_GetAngle(shot) % 180.0 == 0){ if(Obj_GetY(shot) < GetClipMinY()-8){ Obj_SetY(shot, GetClipMaxY()+8); } if(Obj_GetY(shot) > GetClipMaxY()+8){ Obj_SetY(shot, GetClipMinY()-8); } } else{ if(Obj_GetX(shot) < GetClipMinX()-8){ Obj_SetX(shot, GetClipMaxX()+8); } if(Obj_GetX(shot) > GetClipMaxX()+8){ Obj_SetX(shot, GetClipMinX()-8); } } } /***************************************************************** * 描画処理 ****************************************************************/ function draw() { draw_enemy(); } function draw_enemy() { DrawGraphic(GetX(), GetY()); } /***************************************************************** * 定型処理 ****************************************************************/ @Initialize { SetLife(2000); SetEnemyMarker(true); load_graphic_list(RESOURCE_GRAPHIC); SetTimer(SPELL_TIME_LIMIT); if(SPELL_IS_DURABLE) { SetDurableSpellCard(); } if(SPELL_IS_LAST) { LastSpell(); } if(SPELL_BONUS) { SetScore(SPELL_BONUS); } SetX(ENEMY_INITIAL_POS[0]); SetY(ENEMY_INITIAL_POS[1]); SetDamageRate(ENEMY_INITIAL_DMG_RATE[0], ENEMY_INITIAL_DMG_RATE[1]); if(CUTIN_ENABLE){ CutIn(CUTIN_TYPE, CUTIN_NAME, CUTIN_IMG, CUTIN_IMG_RECT[0], CUTIN_IMG_RECT[1], CUTIN_IMG_RECT[2], CUTIN_IMG_RECT[3]); } let img = ENEMY_IMG_FRONT; let rect = ENEMY_IMG_FRONT_RECT; SetTexture(img); SetGraphicRect(rect[0], rect[1], rect[2], rect[3]); main(); } @MainLoop { SetCollisionA(GetX(), GetY(), ENEMY_HIT_SIZE); SetCollisionB(GetX(), GetY(), ENEMY_HIT_SIZE); yield; } @DrawLoop { draw(); } @Finalize { delete_graphic_list(RESOURCE_GRAPHIC); } #include_function ".\include\common.h.txt" #include_function ".\include\object.h.txt" }