XenMai ソースコード
HSPプログラムコンテスト2012に応募したゲームのソースコードです。
; XenMai ; ver.1.2 ; http://dev.onionsoft.net/seed/info.ax?id=193 ; HSP 3.31rc1 #runtime "hsptv" #regcmd 18 #cmd hsptv_send $00 #include "obaq.as" ; outer wall (screen 640x480) #const CENTER_X -80 #const CENTER_Y -60 #const AREA_WIDTH 640 #const AREA_HEIGHT AREA_WIDTH * 3 / 4 #const AREA_LEFT CENTER_X - AREA_WIDTH / 2 #const AREA_TOP CENTER_Y - AREA_HEIGHT / 2 #const AREA_RIGHT CENTER_X + AREA_WIDTH / 2 #const AREA_BOTTOM CENTER_Y + AREA_HEIGHT / 2 #const MAT_WALL MAT_WIRE2 | MAT_DELAY ; pi #const PI_D2 M_PI / 2 #const PI_D4 M_PI / 4 ; scene #enum SC_TITLE = 0 #enum SC_MAIN ; pad #uselib "winmm" #func joyGetPosEx "joyGetPosEx" int, var #const JS_BORDER_LOW 32768 - 4096 #const JS_BORDER_HIGH 32768 + 4096 ; *start ; エリア背景作成 buffer 1 picload dir_tv + "sozai6.jpg" buffer 2 picload dir_tv + "sozai12.jpg" gmode 6, 640, 480, 230 gcopy 1 ; scoreBoard にランキング情報を格納 ; n*3行目:score, n*3+1行目:user, n*3+2行目:comment (n:0-29) notesel scoreBoard hsptv_send scoreBoard, -1 dim jsdata, 15 : jsdata = 52, 255 ; JOYINFOEX jsButtonDef = 1, 2, 4 ; 自機モデル ; 頂点登録は左周り(Y軸は下が正) t = "*4-/'/*4* '%-%* *,,**((**," repeat 26 myModel(cnt) = double(peek(t, cnt) - 42) / 10 loop gsel *init ; OBAQ 初期化 qreset ; 外壁 qborder AREA_LEFT, AREA_TOP, AREA_RIGHT, AREA_BOTTOM qgroup , $8, $3, $3 ; 的の衝突は除外しないと接触時の速度をちゃんと取れない qmat , MAT_WALL, $ff0000, $880000 ; エリア背景 ; サイズは外壁と合わせる x=AREA_WIDTH/2/cos(M_PI/4), y=x*3/4 少数切り捨て qaddpoly id, 4, , , , 452, 339, 0, $4, $b qmat id, MAT_SPR, 2 ; 自機 qaddmodel myObjId, myModel, , , , , 30, 30 qgroup myObjId, $1, , $2 qweight myObjId, 20 qmat myObjId, MAT_WIRE2, 0, $bbbb66 ; ゼログラ qgravity , 0 zoom = 0.1 dim frm dim rCnt dim slowCnt ; 壁ぶつけ得点用 dim scoreE, 10 ; scoreE は表示タイマーとフラグを兼用 ; ↓は初期化しなくても大丈夫、なはず…(代入→参照の順) ;dim scoreX, 10 ;dim scoreY, 10 ;dim scoreA, 10 ; 的出現固定(内容的に固定させないほうが良かったかも randomize 1 *mainLoop redraw 0 color boxf stick key, 15 * scene ; PadID変更用にトリガー joyGetPosEx jsID, jsdata jsStat = (stat == 0) jsButton = jsdata(8) if (scene) { ; パッドでPadID変更させない x = jsdata(2) y = jsdata(3) key |= (x < JS_BORDER_LOW) + (y < JS_BORDER_LOW) * 2 + (x > JS_BORDER_HIGH) * 4 + (y > JS_BORDER_HIGH) * 8 } notEsc = (key & 128) == 0 ; [Esc] frm++ if (scene) { ; SC_MAIN ; 残タイム・esc処理 leftTime = 100 - frm / 60 if (leftTime * notEsc) : else { dim scene ; SC_TITLE submitable++ qdel myObjId } rank = sqrt(0.13 * frm) rankVal = 44 - rank addRot = 0.025 + rank * 0.001 qgetpos myObjId, myX, myY, myAng qgetspeed myObjId, mySpdX, mySpdY, mySpdAng ; 自機移動・回転 dim r if (rCnt) { rCnt-- } else { getkey k, 'Z' : k |= jsButton & jsButtonDef : if (k) : r-- getkey k, 'X' : k |= jsButton & jsButtonDef(1) : if (k) : r++ if (r) { rCnt = rankVal } } lspd = limitf(0.15 - absf(mySpdAng), 0.05, 0.20) qspeed myObjId, lspd * (((key & 4) != 0) * (mySpdX < 0.8) - (key & 1) * (mySpdX > -0.8)), lspd * (((key & 8) != 0) * (mySpdY < 0.8) - ((key & 2) != 0) * (mySpdY > -0.8)), addRot * r * (0.5 * ((mySpdAng * r) < 0) + 1) ; ズームイン if (zoom < 1.4) { zoom += (1.5 - zoom) * 0.04 } ; 的生成 if (frm \ rankVal) : else { r = PI_D2 * rnd(4) + PI_D4 x = cos(r) * 400 y = sin(r) * 300 t = 1.3 + rank / 30 dir = atan(myY - y, myX - x) qaddpoly id, 3, x, y, dir - M_PI, 12, 12 qspeed id, cos(dir) * t, sin(dir) * t qgroup id, $2 qweight id, 10 qmat id, MAT_WIRE2, 0, $ff0000 } ; 自機と的との衝突判定 getColi_id = myObjId getColi_proc = *coliproc_player gosub *getColi } ; 外壁と自機・的との衝突判定 dim getColi_id getColi_proc = *coliproc_wall gosub *getColi ; ビュー t = zoom / 1.3 qview zoom, zoom, 320 - myX * t, 240 - myY * t ; OBAQ内部の演算と描画 qexec qdraw 1 if (scene) { ; SC_MAIN ; 溜めエフェクト qcnvaxis x, y, myX, myY color 140, 140, 60 sz = rCnt * (addRot * 4000 + 20) / rankVal circle x - sz, y - sz, x + sz, y + sz, 0 } else { ; SC_TITLE palcolor 19 ; ランキング repeat 30 i = 3 * cnt noteget rScore, i noteget rUser, i + 1 noteget rComment, i + 2 pos 320 * (cnt >= 15) - 40, (cnt \ 15) * 20 + 90 mes strf("%16d%4s %s", rScore, rComment, rUser) loop ; タイトル mes "\n\n\n- XenMai -" ; 位置は上のランキングで調整 ; ランクイン if ((score > rScore) * submitable) { getkey k, 'R' if (k) { hsptv_send scoreBoard, score, "" + leftTime dim submitable } if ((frm \ 80) > 40) { pos 260, 55 mes "R key to submit" } } ; アサインモードトグル if (key & 32) { ; [Enter] assMode ^= 1 dim keyID } ; ボタンアサイン if (assMode) { jsID += ((key & 4) >> 2) - (key & 1) jsID &= 15 pos 295, 400 mes "Pad " + jsID if (jsStat) { if (jsButton != jsPreButton) { ; 押しっぱなし回避 jsPreButton = jsButton if (jsButton) { ; 前回押してなかった jsButtonDef(keyID) = jsButton keyID++ keyID \= 3 } } pos 289 mes "assign " + (keyID + 1) } } else { ; スタート if ((key & 16) | (jsButton & jsButtonDef(2))) { ; [Space] scene++ ; SC_MAIN dim score getkey disableSlow, 'S' : enableSlow = disableSlow ^ 1 goto *init } } } palcolor 19 pos 200, 20 mes strf("%8d%15d%c", score, leftTime, disableSlow * $22) ; 壁ぶつけ得点表示 repeat 10 if (scoreE(cnt)) { pos scoreX(cnt), scoreY(cnt) mes scoreA(cnt) scoreE(cnt)-- } loop redraw if (slowCnt * scene * enableSlow) { await slowWait slowCnt-- } else { await 15 } goto *mainLoop *getDist2 return x * x + y * y *getColi qcollision getColi_id dim preId repeat qgetcol id, x, y if (id < 1) : break ; id 0 は外壁なので除外 if (id <= preId) : continue ; 前回以下 id のログは読まない(id が小さい順に並ばない場合も… preId = id gosub getColi_proc loop return *coliproc_player qgetpos id, x, y, r qinner in, x, y, myObjId if (in > 0) { ; 重心が内部侵入 score += 1000 qdel id return } qgetspeed myObjId, x, y, r gosub *getDist2 if (refdval > 2) { ; スロー発生条件 slowWait = 30 + (refdval - 2) * 30 slowCnt = 8 } else { dim slowCnt } score++ qgetuser id, f, dummy, dummy if (f) : else { quser id, 1 ; 自機との初接触フラグ qmat id, MAT_WIRE, $ffff00 score += 100 } return *coliproc_wall if (id == myObjId) { ; 死んでしまった dim scene ; SC_TITLE submitable++ } else { if (scene) { qgetuser id, f, dummy, dummy if (f) { ; 自機と接触している的のみ qgetpos id, x, y, r qcnvaxis x, y, x, y dir = atan(240 - y, 320 - x) scoreX(scrIdx) = 320 - cos(dir) * 150 scoreY(scrIdx) = 240 - sin(dir) * 150 qgetspeed id, x, y, r gosub *getDist2 scoreA(scrIdx) = 10 * (refdval * 50) + 10 score += scoreA(scrIdx) scoreE(scrIdx) = 100 scrIdx++ scrIdx \= 10 } } } qdel id return
コードの利用はNYSLで。
あと、スクリプトのHTML変換に(X)HTMLコンバータ for HSP3を利用しています。はてなダイアリーにはシンタックスハイライト機能があるけど、HSPには対応していないのでかなり重宝します。cssで簡単に色も変えれるし。