;============================================================ ; 2005/--/-- ; S.Programs RocketRace! sample ; for HSP 3.0 ; ;============================================================ /* サンプルゲーム ロケットレース! 【ルール】 [Space] を押して噴射を開始してから、200km 先の赤いゴール円 (直径 500m) に 着くまでのタイムを競います。機体がゴール円を通過できなければ失敗です。 超強力なメインエンジンを吹かすと機体が揺れて姿勢が変わるので、軌道を修正しながら 進んでください。 真空中を慣性で飛ぶので、フライトシミュレータとはまるで違った飛行感覚に なります。 【操作方法】 [Space] : メインロケット噴射 [←][→] : 機体ロール回転 (翼端ロケット) [↑][↓] : 機体ピッチ回転 (翼端ロケット) [Shift] + [←][→] : 機体ヨー回転 (翼端ロケット) [Esc] : ゲーム リトライ [A] : オートパイロット ON / OFF [S] : 視点切り替え 外部視点 / コックピット視点 【スペック】 ・推進加速度 : 100 m/s^2 (10G!) ・ロール角加速度 : 4 rad/s^2 ・ロール角速度制限 : 4 rad/s ・ピッチ角加速度 : 4 rad/s^2 ・ピッチ角速度制限 : 4 rad/s ・ヨー角加速度 : 4 rad/s^2 ・ヨー角速度制限 : 4 rad/s ・自動姿勢安定 ・推進剤無制限 */ #include "d3m.hsp" ;============================================================ title "S.Programs RR!" d3mkparticle 0, 255, 255, 255 d3mkparticle 1, 255, 192, 32 d3mkparticle 2, 64, 128, 255 d3mkparticle 3, 500, 500, 128 viewmode = 0 ; 視点設定 ;------------------------------------------------------------ ; ゲーム初期化 *init ; 姿勢マトリクス pm00 = 1 : pm01 = 0 : pm02 = 0 ; 前方ベクトル pm10 = 0 : pm11 = 1 : pm12 = 0 ; 左方ベクトル pm20 = 0 : pm21 = 0 : pm22 = 1 ; 上方ベクトル ; 位置 px = 0.0 : py = 0.0 : pz = 0.0 ; 速度 vx = 0.0 : vy = 0.0 : vz = 0.0 vm_r = 0.0 ; ロール角速度 vm_p = 0.0 ; ピッチ角速度 vm_y = 0.0 ; ヨー角速度 ; keymap xmm = 37 xpp = 39 ymm = 40 ypp = 38 trg = 32 ; game goal_x = 200000 ; [m] goal_r = 250 ; [m] time_s = 0 ; [ms] game-start time_e = 0 ; [ms] game-end game_f = 0 ; fail / goal sstr = "GOAL!", "FAIL! orz" mode_ap = 0 ; A/P mode time = d3timer() ; sim_start ;------------------------------------------------------------ ; ゲームループ *mainloop dt = 0.001 * (d3timer() - time) time = d3timer() ;------------------------------------------------------------ ; AUTO PILOT getkey k, 'A' mode_ap ^= (apk!k&k) ; A/P 切り替え apk = k ap_r = 0 ; ロール 自動操作量 ap_p = 0 ; ピッチ 自動操作量 ap_y = 0 ; ヨー 自動操作量 ap_v = 0 ; 推進 自動操作量 if mode_ap { ; いくつかの噴射パターンで、目標とのなす角の cos が最も大きく操作量を採用 maxp = -1.0 repeat 27 ; 噴射パターン tm_r = (cnt\3-1) tm_p = (cnt/3\3-1) tm_y = (cnt/9\3-1) ; copy tm00 = pm00 : tm01 = pm01 : tm02 = pm02 ; 前方ベクトル tm10 = pm10 : tm11 = pm11 : tm12 = pm12 ; 左方ベクトル tm20 = pm20 : tm21 = pm21 : tm22 = pm22 ; 上方ベクトル ; roll d3vrotate tm10,tm11,tm12, tm10,tm11,tm12, tm00,tm01,tm02, (vm_r + tm_r) * dt d3vrotate tm20,tm21,tm22, tm20,tm21,tm22, tm00,tm01,tm02, (vm_r + tm_r) * dt ; pitch d3vrotate tm00,tm01,tm02, tm00,tm01,tm02, tm10,tm11,tm12, (vm_p + tm_p) * dt d3vrotate tm20,tm21,tm22, tm20,tm21,tm22, tm10,tm11,tm12, (vm_p + tm_p) * dt ; yow d3vrotate tm00,tm01,tm02, tm00,tm01,tm02, tm20,tm21,tm22, (vm_y + tm_y) * dt d3vrotate tm10,tm11,tm12, tm10,tm11,tm12, tm20,tm21,tm22, (vm_y + tm_y) * dt vvx = 700.0 if px > goal_x : vvx = -100000.0 vvy = - vy - py - vy * absf(vy) / 70 - py * absf(py) / 50000 vvz = - vz - pz - vz * absf(vz) / 70 - pz * absf(pz) / 50000 a = (tm00 * vvx + tm01 * vvy + tm02 * vvz) / d3dist(vvx, vvy, vvz) if a > maxp { maxp = a ap_r = tm_r ap_p = tm_p ap_y = tm_y ap_v = (maxp > 0.80) * 100 } loop } ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;------------------------------------------------------------ ; ctrl stick k if k & 128 : goto *init ; [Esc] am_r = 0.0 + ap_r am_p = 0.0 + ap_p am_y = 0.0 + ap_y getkey k, trg : am_v = k * 100 | ap_v getkey k, 16 ; [Shift] if k { ; yow getkey k, xpp : am_y -= k * 4 getkey k, xmm : am_y += k * 4 } else { ; roll getkey k, xpp : am_r += k * 4 getkey k, xmm : am_r -= k * 4 } ; pitch getkey k, ypp : am_p += k * 4 getkey k, ymm : am_p -= k * 4 ;------------------------------------------------------------ ; v-move ; メインロケット噴射 if am_v { ; 加速 vx += pm00 * am_v * dt vy += pm01 * am_v * dt vz += pm02 * am_v * dt ; エンジン振動外乱 (max 8 rad/s^2) vm_r += (sin(0.02 * time) * 5 + sin(0.003 * time) * 5) * dt vm_p += (sin(0.03 * time) * 4 + sin(0.005 * time) * 4) * dt vm_y += (sin(0.05 * time) * 4 + sin(0.007 * time) * 4) * dt } dr = dt * 4 ; ロール制御噴射 rf = 0 if vm_r < am_r { vm_r = limitf(vm_r+dr, vm_r, am_r) rf = 1 } else:if vm_r > am_r { vm_r = limitf(vm_r-dr, am_r, vm_r) rf = -1 } ; ピッチ制御噴射 pf = 0 if vm_p < am_p { vm_p = limitf(vm_p+dr, vm_p, am_p) pf = 1 } else:if vm_p > am_p { vm_p = limitf(vm_p-dr, am_p, vm_p) pf = -1 } ; ヨー制御噴射 yf = 0 if vm_y < am_y { vm_y = limitf(vm_y+dr, vm_y, am_y) yf = 1 } else:if vm_y > am_y { vm_y = limitf(vm_y-dr, am_y, vm_y) yf = -1 } ;------------------------------------------------------------ ; p-move ; roll d3vrotate pm10,pm11,pm12, pm10,pm11,pm12, pm00,pm01,pm02, vm_r * dt d3vrotate pm20,pm21,pm22, pm20,pm21,pm22, pm00,pm01,pm02, vm_r * dt ; pitch d3vrotate pm00,pm01,pm02, pm00,pm01,pm02, pm10,pm11,pm12, vm_p * dt d3vrotate pm20,pm21,pm22, pm20,pm21,pm22, pm10,pm11,pm12, vm_p * dt ; yow d3vrotate pm00,pm01,pm02, pm00,pm01,pm02, pm20,pm21,pm22, vm_y * dt d3vrotate pm10,pm11,pm12, pm10,pm11,pm12, pm20,pm21,pm22, vm_y * dt ; move px += vx * dt py += vy * dt pz += vz * dt ;------------------------------------------------------------ ; setcam getkey k, 'S' viewmode ^= (vmk!k&k) ; 視点切り替え vmk = k if viewmode { d3setcam -40, 0, 10, 0, 0, 10 ; 機体姿勢行列の転置 d3setlocal -(pm00*px+pm01*py+pm02*pz),-(pm10*px+pm11*py+pm12*pz),-(pm20*px+pm21*py+pm22*pz), pm00,pm01,pm02, pm10,pm11,pm12, pm20,pm21,pm22 } else { f = 0.0004 * time d3setcam px-sqrt(absf(vx))*15 + sin(f)*200, py-vy + cos(f)*200, pz-vz + sin(f)*100, px, py, pz } ;------------------------------------------------------------ ; static obj redraw 0 color 16, 20, 20 : boxf gmode 5, , , 256 ; guide POLYS = 6 ; 分割数 dh = 6.2831853 / POLYS color 96, 96, 48 repeat POLYS x = cos(dh * cnt) * goal_r y = sin(dh * cnt) * goal_r repeat goal_x / 1000 d3pset cnt * 1000, x, y d3particlem 3, 15 loop loop ; goal color 192, 64, 64 d3initlineto repeat POLYS + 1 d3ribbonto goal_x, 0, 0, goal_x, cos(dh * cnt)*goal_r, sin(dh * cnt)*goal_r loop ; stars randomize 0 repeat 100 d3particle 0, (rnd(32768)-16384)*30, (rnd(32768)-16384)*30, (rnd(32768)-16384)*30, 2000 loop ;------------------------------------------------------------ ; ローカル座標系を機体座標系に設定 if viewmode { d3setlocal } else { d3setlocal px,py,pz, pm00,pm10,pm20, pm01,pm11,pm21, pm02,pm12,pm22 } ;------------------------------------------------------------ ; spacecraft POLYS = 8 ; 分割数 dh = 6.2831853 / POLYS color 255, 255, 255 repeat 10 r0 = cnt r1 = (cnt + 1) d0 = -(cnt * cnt - 50) d1 = -((cnt + 1) * (cnt + 1) - 50) d3initlineto repeat POLYS + 1 a = dh * cnt gmode 5, , , (sin(a) + 1) * 20 + rnd(16) + (50-d1)/2 d3ribbonto d0, cos(a)*r0, sin(a)*r0, d1, cos(a)*r1, sin(a)*r1 loop loop ;------------------------------------------------------------ ; tail color 255, 128, 128 gmode 5, , , 128 d3initlineto d3ribbonto -50, 0, 0, -20, 0, 0 d3ribbonto -50, 0, 30, -40, 0, 30 ;------------------------------------------------------------ ; wing repeat 2 ox = -50 if cnt : ox = 30 ; --- motor 1 x0 = ox + 5 y0 = 50 if cnt = 0 { df = (-pf - rf) } else { df = (pf - rf) } gosub *df_fire ; --- motor 1 x0 = ox + 5 y0 = -50 if cnt = 0 { df = (-pf + rf) } else { df = (pf + rf) } gosub *df_fire gmode 5, , , 128 d3initlineto d3ribbonto ox+10, 50, 0, ox, 50, 0 d3ribbonto ox+20, 0, 0, ox, 0, 0 d3ribbonto ox+10, -50, 0, ox, -50, 0 color 128, 128, 255 loop ; yow motor if yf { repeat 2 x0 = 40 - cnt * 85 y0 = 50 df = (cnt*2-1) * yf cf = (cnt*2-1) randomize 0 c = 7 repeat c a = rnd(32768) p = double((time / 10 + cnt)\c) / c r = p gmode 5, , , (1.0 - p) * 192 d3particle 2, sin(a)*r+x0 + p*11*cf, (p*11+y0)*df, cos(a)*r, 2 gmode 5, , , (1.0 - p) * 192 d3particle 1, sin(a)*r+x0 + p*18*cf, (p*18+y0)*df, cos(a)*r, 6 gmode 5, , , (1.0 - p) * 56 d3particle 0, sin(a)*r+x0 + p*35*cf, (p*35+y0)*df, cos(a)*r, p * 6 + 6 loop loop } ;------------------------------------------------------------ ; rocket gas if viewmode = 0 { gmode 5, , , 64 d3particle 0, 0,0,0, 50 } if am_v { gmode 5, , , 64 d3particle 2, -50, 0, 0, 60 ; gas randomize 0 c = 15 repeat c a = rnd(32768) p = double((time / 7 + cnt) \ c) / c r = p * 5 ; gas1 gmode 5, , , (1.0 - p) * 255 d3particle 2, -p * 100 - 50, cos(a) * r, sin(a) * r, (1.0 - p) * 5 + 10 ; gas2 gmode 5, , , (1.0 - p) * 48 d3particle 1, -p * 160 - 50, cos(a) * r, sin(a) * r, p * 20 + 20 p = double((time / 20 + cnt) \ c) / c r = p * 7 ; gas3 gmode 5, , , (1.0 - p) * 50 d3particle 0, -p * p * 400 - 50, cos(a) * r, sin(a) * r, p * 50 loop } ;------------------------------------------------------------ ; game ctrl ; time-start if (time_s = 0) & (am_v ! 0) { time_s = time } ; time-stop if (time_e = 0) & (px >= goal_x) { time_e = time game_f = (d3dist(py, pz) > goal_r) ; ファール判定 } color 192, 192, 192 pos 0, 0 font "Arial", ginfo_winx / 30, 1 mes ""+d3getfps()+" fps" if time_e { mes "TIME : "+(0.001 * (time_e - time_s))+" sec" font "Arial", ginfo_winx / 15, 1 mes sstr(game_f) font "Arial", ginfo_winx / 30, 1 mes "press [Esc] to retry." } else:if time_s { mes "TIME : "+(0.001 * (time - time_s))+" sec\nSpeed : "+d3dist(vx, vy, vz)+" m/s\nx = "+px+" m" } else { mes "press [Space] to start." mes "press [A] to auto-pilot." } mes "press [S] to change view." if time / 500 \ 2 & mode_ap { color 224, 96, 96 font "Arial", ginfo_winx / 25, 1 mes "[AUTO PILOT]" } ;------------------------------------------------------------ redraw await 10 goto *mainloop ;------------------------------------------------------------ *df_fire df = limitf(df, -1, 1) if df { randomize 0 c = 7 repeat c a = rnd(32768) p = double((time / 10 + cnt)\c) / c r = p gmode 5, , , (1.0 - p) * 192 d3particle 2, sin(a)*r+x0, cos(a)*r+y0, p*df*15, 2 gmode 5, , , (1.0 - p) * 192 d3particle 1, sin(a)*r+x0, cos(a)*r+y0, p*df*25, 6 gmode 5, , , (1.0 - p) * 56 d3particle 0, sin(a)*r+x0, cos(a)*r+y0, p*df*50, p * 6 + 6 loop } return