;=========================================================== ; 2008/09/27 ; 蟲 1.2 ; http://gmr.blog.shinobi.jp/Category/35/ ; GAM-22 ;=========================================================== /*---------------------------------------------------------- ; log ;----------------------------------------------------------- [0.1] 蟲がマウスに集まる [0.2] 配色変更、仲間同士で距離を保つように [0.3] 脚の追加 [0.4] 蟲の変数管理を、var(個体, 長さ)→ var(節) に変更 クリックで蟲回避、右クリックで蟲ランダム破壊 r) 蟲の間接破壊を想定 m) AXsize マイナス、2次元配列の Error7 から解放 d) 処理速度が低下(重大) [0.5] ドラックで描ける線分で、蟲を切断する処理を実装 蟲の長さにより、判定の大きさを変化 起動時、蟲の長さ(10or20)をランダムに決定 [0.6] 蟲がレザーに触れたときの効果 [0.7] 血しぶきを再現(廃止するかもしれません) 蟲のグラデーションをランダムに調整 [0.8] 蟲を全てバラバラにするゲームに HSPTVランキングに対応 [0.9] ルール変更、制限時間内で頑張るゲームに [1.0] 三角関数を使う都度、90°補正してたのを、 計算の時から左に傾けて、描画する時だけ戻すように [1.1] "winmm.dll"で効果音を再現。練習モード廃止 [1.2] midiOutCloseの引数を忘れてたのを修正 exe版にもランキングを実装 効果音を微調整 ;----------------------------------------------------------- ; パラメータ省略 ;----------------------------------------------------------- 0. color 22,0,0 → color 22 : -4byte 0. color 222,0,22 → color 22,,22 : -0byte 1. color 0,0,0 → color 2. var(2,0) → var(2) 3. redraw 1 → redraw ;----------------------------------------------------------- ; 数学系メモ ;----------------------------------------------------------- 1. 内積 = ax*bx + ay*by 2. ベクトル(x,y)の法線 = (-y,x) ;----------------------------------------------------------- ; その他 ;----------------------------------------------------------- 1. 人に見せるようなレベルじゃないことは自覚しています 2. コメントの「;」と「//」の使い分けが微妙です ;---------------------------------------------------------*/ #define __debug 0 #define __ss 0 #define __hsptv 1 ;----------------------------------------------------------- ; HSPTV ;----------------------------------------------------------- #if __hsptv #runtime "hsptv" #regcmd 18 #cmd hsptv_send $00 #endif #if __hsptv=0 title "蟲" #define user sysinfo.1 #endif ;----------------------------------------------------------- ; midi ;----------------------------------------------------------- #uselib "winmm.dll" #func midiOutOpen "midiOutOpen" int, int, int, int, int #func midiOutShortMsg "midiOutShortMsg" int, int #func midiOutClose "midiOutClose" int #define ctype midi_msg(%1,%2,%3) %1 | (%2<<8) | (%3<<16) ; メッセージを定数化 #const midi_laser_set midi_msg($C0, 102, 0) #const midi_laser_play midi_msg($90, 80, 100) #const midi_laser_stop midi_msg($80, 80, 100) #const midi_bld_set midi_msg($C0+1, 120, 0) #const midi_bld_play midi_msg($90+1, 75, 100) ;----------------------------------------------------------- ; 定数 ;----------------------------------------------------------- ; ファイル名 #packopt name "worms" ; 画像バッファ #const buf_win 1 ; 円周率 (無駄に桁が多い) π = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068 ; 円周率/2 #define πh 1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534 ; 1° #define ° 0.017453292519943295769236907684886127134428718885417254560971914401710091146034494436822415696345094 ; key code #const esc 128 ; 非トリガーキー (esc以外) #const non_trigger $7FF^esc ;----------------------------------------------------------- ; 起動 ;----------------------------------------------------------- // midiOutOpen midiOutOpen varptr(midi); (,0,0,0,0) 略しても大丈夫!? onexit *exit // 乱数初期化 randomize ;------------------------------------------------------- ; rank ;------------------------------------------------------- notesel rank #if __hsptv hsptv_send rank, -1 #endif #if __hsptv=0 exist "rank" if strsize>=0 : noteload "rank" #endif // comment comment = "comments please" goto *reset *send ;----------------------------------------------------------- ; スコア送信 ;----------------------------------------------------------- #if __hsptv hsptv_send rank, score, comment #endif #if __hsptv=0 repeat noteget v1, cnt*3 if score>=int(v1) { noteadd ""+score+"\n"+user+"\n"+comment, cnt*3 break } loop #endif // mode dim mode *reset ;----------------------------------------------------------- ; 部品描画 ;----------------------------------------------------------- buffer buf_win color : boxf ;------------------------------------------------------- ; Aパーツ(体) ;------------------------------------------------------- // 形状生成 color 48,48,48 circle 65,3, 76,32 circle 84,3, 95,32 circle 64,0, 96,30 // グラデーション加工 repeat 16 gmode 5, 32,32, cnt*cnt+20 pos 16+cnt/4, 16+cnt/4 grotate buf_win, 64,0, 0, 32-0.5*cnt*(rnd(7)+2),32-cnt loop // ダメージ用 color 255 circle 32,0, 63,31 gsel 0 : clrobj ;----------------------------------------------------------- ; 初期化 ;----------------------------------------------------------- ; 蟲の最大数 i_max_limit = 280/(mode+1) // 蟲の種類 (長さ変えてるだけ) ; 普通 i_base_len = 10 i_draw_h = 1 if rnd(2) { ; ムカデ i_base_len = 20 i_draw_h = 10 } dim mcnt dim i_max dim bld_max dim score playing = mode *main ;----------------------------------------------------------- ; main start ;----------------------------------------------------------- // stick key_log = key stick key, non_trigger // draw start redraw 0 // background color : boxf ; 点滅 チカチカ blink = mcnt\2 ;----------------------------------------------------------- ; レーザー 判定 ;----------------------------------------------------------- ; レーザーの法線 ax = laser_y -mousey ay = -laser_x +mousex ; 正規化 v1 = sqrt(ax*ax + ay*ay) if v1>0 : v1 = 1.0/v1 ax *= v1 ay *= v1 repeat (i_max-1) *(i_max>=1), 1 i_dam(cnt) = 0 ; 蟲を線分に bx1 = i_x(cnt-1 +i_type(cnt)) by1 = i_y(cnt-1 +i_type(cnt)) bx2 = i_x(cnt) by2 = i_y(cnt) #if __debug color 255 line bx1,by1, bx2,by2 #endif ; 以下、説明不可 if (ax*(bx2-bx1) + ay*(by2-by1))!0 { v2 = -(ax*bx1 + ay*by1 - (laser_x*ax + laser_y*ay)) / (ax*(bx2-bx1) + ay*(by2-by1)) if v2>0 & v2<=1 { x = bx1+(bx2-bx1)*v2 y = by1+(by2-by1)*v2 if (laser_x-x)*(mousex-x)+(laser_y-y)*(mousey-y) < 0 { if key_log { if key:else{ ; スコア換算 if bld_max { point.bld_max = limit(100-mcnt+bld_cnt(bld_max-1),0,$7FFFFFFF) if point(bld_max)>=100 : point.bld_max = 333 score += point(bld_max) *playing } ; 切断!! i_type.cnt = 1 ; 血しぶき bld_t.bld_max = cnt bld_cnt.bld_max = mcnt bld_max++ ; 断末魔の叫び(謎?) midiOutShortMsg midi, midi_bld_set; +(bld_max\8) midiOutShortMsg midi, midi_bld_play; +(bld_max\8) } i_dam(cnt) += blink } } } } loop ;----------------------------------------------------------- ; 蟲、AI ;----------------------------------------------------------- // 蟲ループ開始 repeat i_max rcnt = cnt if i_type.rcnt { ;------------------------------------------------------- ; 頭 ;------------------------------------------------------- // 長さ計測 repeat , rcnt+((rcnt+2)<=i_max) if i_type(cnt) | (cnt+1)>=i_max { i_len.rcnt = cnt-rcnt break } loop // ターゲット(マウス)に接近、クリック中は逆方向 i_target.cnt = atan(i_y(cnt)-mousey, i_x(cnt)-mousex) +π*(key=0) v1 = i_len(cnt)*4 #if __debug circle i_x(cnt)-v1,i_y(cnt)-v1, i_x(cnt)+v1,i_y(cnt)+v1, 0 #endif repeat i_max if rcnt!cnt & i_type.cnt { // 仲間が近くにいたら (相手の長さで有効範囲を動かす) x = i_x(rcnt) -i_x(cnt+i_len(cnt)/2) y = i_y(rcnt) -i_y(cnt+i_len(cnt)/2) if (x*x+y*y) <= v1*v1 { ; 回避 i_target.rcnt = atan(y,x) } } loop #if __debug line i_x(rcnt),i_y(rcnt), i_x(rcnt)+cos(i_target(rcnt))*50, i_y(rcnt)+sin(i_target(rcnt))*50 #endif // ターゲットから角度がついたら (内積) if cos(i_r.cnt)*cos(i_target.cnt)+sin(i_r.cnt)*sin(i_target.cnt) <= 0.5 { ; 右か左、曲がる方向を決定 (片側を法線にして、内積) i_snake.cnt = -0.05 + 0.1*(-sin(i_r.cnt)*cos(i_target.cnt) + cos(i_r.cnt)*sin(i_target.cnt)>=0) } // 頭移動 i_r.cnt += i_snake.cnt i_x.cnt += 1.75 *cos(i_r(cnt)) *(i_len(cnt)>=2) i_y.cnt += 1.75 *sin(i_r(cnt)) *(i_len(cnt)>=2) } else { ;------------------------------------------------------- ; 体 ;------------------------------------------------------- // 体移動(っていうか引っ張る) i_r.cnt = atan( i_y(cnt-1)-i_y(cnt), i_x(cnt-1)-i_x(cnt) ) i_x.cnt = i_x(cnt-1) - cos(i_r(cnt))*8 i_y.cnt = i_y(cnt-1) - sin(i_r(cnt))*8 } ;----------------------------------------------------------- ; 描画 ;----------------------------------------------------------- // 蟲 x = i_x.cnt y = i_y.cnt r = i_r(cnt) +πh ; 脚 v1 = r +sin (π *(mcnt+cnt)/10) /2 v2 = 9 +(0.15/i_draw_h)*i_w(cnt) color 200,200,200 line x,y, x+cos(v1)*v2, y+sin(v1)*v2 color 128,128,128 line x,y, x-cos(v1)*v2, y-sin(v1)*v2 ; 体 gmode 2, 32,32 pos x,y grotate buf_win, 32*i_dam(cnt),0, r, 17 +(0.2/i_draw_h)*i_w(cnt),9 // 蟲ループ終了 loop // 血しぶき repeat bld_max v1 = bld_t(cnt) v2 = mcnt-bld_cnt(cnt) // point if v2<=10 { color limit(point(cnt)-v2*4,10,255) pos i_x(v1)+10,i_y(v1)+10 mes "+"+point(cnt) } repeat v2*(v2<=26), 8 v3 = °*(rnd(180)+90) +i_r(v1) pos i_x(v1)-cos(v3)*cnt, i_y(v1)-sin(v3)*cnt gmode 4, 32,32, 222-v2*v2/5 grotate buf_win, 32,0, v3, 5-cnt/8, 2 loop loop // レーザー if key { if key_log:else { // 始点 laser_x = double.mousex laser_y = double.mousey ; 効果音 再生 midiOutShortMsg midi, midi_laser_set midiOutShortMsg midi, midi_laser_play } if blink { // 描画 hsvcolor mcnt\192,200,255; カラフル♪ line laser_x,laser_y, mousex,mousey } } else { if key_log { ; 効果音 停止 midiOutShortMsg midi, midi_laser_stop } } ;----------------------------------------------------------- ; 仕上げ ;----------------------------------------------------------- gmode 5, 1,1, 80 color 222,222,222 if key&esc { ; [ESC] リセット dim mode goto *reset } if mode { ;--------------------------------------------------- ; 本番 ;--------------------------------------------------- if playing:else { pos 320, 240 : grotate buf_win, 78,2, 0, 400,150 pos 188,200 if (mousex>=4) + blink { mes "time over..." } else { mes "かわいそうだからいじめないでください" } } if (time=0)*playing { ; タイムオーバー dim playing pos 188,228 : input comment, 200,24, 16 pos 388,228 : button "send", *send } time -= playing } else { ;------------------------------------------------------- ; タイトル ;------------------------------------------------------- if key { ; スタート mode ++ time = 2222 goto *reset } // 蟲 font "MS 明朝", 75 pos 270,50 : mes "蟲" // ランキング pos 320,300 : grotate buf_win, 78,2, 0, 550,222 font "", 15 repeat 30, ((mcnt/100)\3)*30 noteget v1, cnt y = ((cnt/3)\10)*20+200 if cnt\3:else{ pos 80,y : mes "no."+((cnt/3)+1) v1 += "pt" } pos (cnt\3)*100+150,y : mes v1 loop } // 得点 pos 10,4 : mes "score: "+score+"pt\ntime: "+time+"\nbeing: "+i_max ;----------------------------------------------------------- ; main - end ;----------------------------------------------------------- // draw end redraw // screen shot #if __ss if key&16 : bmpsave "ss_"+gettime(0)+"."+gettime(1)+"."+gettime(3)+"_"+gettime(4)+"."+gettime(5)+".bmp" #endif // wait await 30 // mcnt mcnt++ if (mcnt\20) | (i_max >= i_max_limit): else {; (mcnt\20)=0 & (i_max < i_max_limit) { (2byteしか削れない) // 蟲生成 repeat i_base_len i_type.i_max = (i_max\i_base_len)=0 i_len(i_max)++ i_snake.i_max = π i_target.i_max = π i_w.i_max = (3-cnt)*(cnt-4) i_x.i_max = π*rnd(204) i_y.i_max = 640.0*rnd(2) -80 i_r.i_max = π i_max++ loop } // loop goto *main *exit // midiOutClose midiOutClose midi // ランキング保存 #if __hsptv=0 notesave "rank" #endif end