HSP役立つ?スクリプト

初心者向けのような中級者向けのような…
HSP3の命令速度 適当に調査してみたので確認しておくといいかも。こんな感じとなった
;ジョイスティックの入力を受け取る(hsp3.0) ;GETJOY────────────────────────────────────────────────── #uselib "winmm.dll" #func GetJoy"joyGetPos" int,var;intに取得するジョイスティのID、varは配列のポインタ。 dim getjoyH,4;GETJOY用配列である。 ;以降GetJoyを呼び出すごとにその時の状態がgetjoyH(0〜3)に値が代入される。 ;statにジョイスティの状態: 0なら正常 ;getjoyH(0)にXキー情報:   ←0 ・32511 65535→ ;getjoyH(1)にYキー情報:   ↑0 ・32511 65535↓ ;getjoyH(2)にZキー(?)情報:  ↑0 ・32511 65535↓ ;getjoyH(3)に押ボタン情報: △(1) ○(2) ×(4) □(8) L2(16) R2(32) L1(64) R1(128) START(256) SELECT(512) …PSパッドコンバータの配置です。ボタン1、ボタン2…の順です。 ;───────────────────────────────────────────────────── ;↓ゲーム処理 repeat title "PUSHBUTTON="+getjoyH(3)+"| X="+getjoyH(0)+"| Y="+getjoyH(1)+"" GetJoy 0,getjoyH;配列の要素数を指定しない場合はその配列のポインタである wait 5 loop
;FPSをほぼ60にする。終了時は*finishに飛ぶ、ウェイト処理は*waittimeで行う。精度はたいした事無いけど問題もない(hsp3.0) ;--------------------------------------------- #uselib "winmm.dll" #func timegettime "timeGetTime" #func timeBeginPeriod "timeBeginPeriod" int #func timeEndPeriod "timeEndPeriod" int timeBeginPeriod 1;タイマーの精度を1ミリ秒単位に設定。やらないと10〜16ミリ秒ごとにしかタイマーカウントしてくれないとかいう非常事態になる事がある。 onexit goto *finish timegettime:lasttime=stat; ;--------------------------------------------- ;****************ゲーム中はここをひたすら繰り返し******************** repeat x++:y=rnd(150):pos x,y:mes "x":color x,x,x:if x>255:x=0;ここに本来はゲーム処理を書く gosub *waittime;ウェイトを行う loop ;****************ゲーム中はここをひたすら繰り返し******************** ;--------------------------------------------- *waittime repeat timegettime if stat-lasttime>16:lasttime=stat:break if stat-lasttime<=1:await 1:timegettime;余裕があればウェイトを挟んでCPU利用率を下げる getkey a,27:if a=1:goto *finish;ESCで終了 loop timegettime:lasttime=stat;ウェイトの為に今の時間計測 return ;--------------------------------------------- *finish timeEndPeriod 1:end
;HSP3レジストリ操作モジュール ;モジュールを作成した。 ;・数値型レジストリREG_DWORD の操作命令 ; intRegRead hkey,key,value ; intRegWrite hkey,key,value,writevalue ;・文字型レジストリREG_SIZ の操作命令 ; strRegRead hkey,key,value ; strRegWrite hkey,key,value,writevalue ;・レジストリの値の削除 ; regDelete hkey,key,value ;以上の5つ。これの利用で死んでも何の責任もとりません。 ;使用方法は、まずスクリプトの最初に include "regModule.hsp" ;と当ファイルをインクルードする。exeに埋め込み可能。 ;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable ;を読みたいなら、 intRegRead "HKEY_CURRENT_USER" , "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" , "ProxyEnable" ;p1が主キー、p2が副キー、p3が値名。この命令を実行するとシステム変数のstatに結果が返る。statはHSPで暗黙的に必ず使われるシステム変数。 mes stat;読み込んだ値を表示する。とか。 ;同様に書き込むときは intRegWrite "HKEY_CURRENT_USER" , "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" , "ProxyEnable" , 1 ;これでこのキーに1が書き込まれる。 ;また、キーが存在しない場合は新しくキーが作成されてしまうので注意すること。 ;文字列を読む場合 strRegRead "HKEY_CURRENT_USER" , "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" , "User Agent" ;数値型と違い、読み出した文字列は システム変数refstrに返るので注意。 ;文字列を書き込む場合 strRegWrite "HKEY_CURRENT_USER" , "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" , "Mozilla/4.0 (compatible; aii- 7.0; Win32)" ;これもキーが存在しない場合は新しくキーが作成されてしまうので注意すること。 ;レジストリを削除する場合 regDelete "HKEY_CURRENT_USER" , "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" , "User Agent" ;なんとなく個人的な意図でレジストリを変えるマクロ的なものをほしくなったときに便利かもしれません。 ;HKEY_〜〜とキーと値が分かれてるのがウザいが内部で使ってるAPIの引数がそーなってるからしょうがない… ;こんなもん作っててなんだが、レジストリで設定を保存する意味がまったくわからない ;アンインストールで消えてない場合が結構あるし、ファイルでかくなると重くなるし ;バックアップも取りづらいし、OS再インストールしたら消えるし… ;iniファイルで設定の保存をするのがいいと思うのだがアホだからまったくわからん。
;HSP3でパレットモードを使う ;HSP2.61だとBMP読み込んだら即パレットがそれのパレットになってたが ;HSP3だと最初は白黒になっているので自分でパレットを設定せねばならない。 ;---------------------------------------------- #include "hsp3util.as" screen 0,,,1 bmppalette "FileName.bmp" ;--------------------------------------------- ;↑でhsp3util.asにあるモジュールを使ってパレットを設定することができる。プログラムの頭でやったほうがいいだろう。 ;殆ど変わらんけどいらんモジュールまでインクルードされるのがイヤなら(何キロバイト程度の差だが) ;-------------- #module #deffunc bmppalette str filename exist filename :if strsize<1078 :return dim a,270 : bload filename,a,1078 ;BMPヘッダー読み出し if peek(a,$1c)>8 :return ;8bitBMPでなかったらreturn if wpeek(a,0)!$4d42 :return ;"BM"チェック:強制終了は避ける cols=lpeek(a,$2e) :if cols=0:cols=256 ;色数:cols=0は 256色 i=$36 repeat cols palette cnt,peek(a,i+2),peek(a,i+1),peek(a,i),cnt=cols-1 i+=4 loop dim a,0 return #global screen 0,,,1;スクリーン0をパレットモードで初期化 bmppalette "FileName.bmp";読み込むBMP ;------------- ;と、いるとこだけコピーして持ってこればよい。
;BMPなどのファイルに埋め込んだデータを文字列として読み込む ;とりあえずbmpとかにバイナリエディタとか(Stirlingとか)で ;データを書き込むとかわけわからんことするとき ;bloadで読み込むと文字として打ち込んでも数値として扱われてしまう。 ;…とみせかけて実は読み込み先の変数の型に合わせているだけである textdata="" ;空代入で文字列型宣言ぽく bload "tekito.bmp",x,4,0x10920 mes textdata ;これでtekito.bmpのアドレス0x10920番地から4バイト読み込んでmesで表示できる。 ;くっだらねぇ〜。 ;もちろん逆に書き込むこともできる。 x="あほ" bsave "ho.bmp",x ,4,0x10920 ;あほに書き換わる。はっきりいってあんま意味ないなこれ。 ;まぁバイナリエディタでファイルを覗くのは理解深めるのに良いです。 ;HSPの数値変数は全て4バイト。0か1のデータでも4バイトですげぇ重い
数値型の文字コードを文字型化する ;文字も内部ではただの数値ですので、文字型変数の内容をその数値に書き換えれば ;ただの数字を平仮名やアルファベットに変換することができます。 y=41090 z="" lpoke z,0,y mes z ;数値型のyに41090…つまるところ「あ」の文字コードを入れ、 ;文字型のzにlpokeで書き込む。(pokeだと8bitしか書きかえれず、2バイト文字だと1バイトしか書き込めず意図した処理にならない) ;ただlpokeも32bit単位での書き換えなので、2バイト文字なら2文字、1バイト文字なら4文字しか書けないので ;長い文なら工夫して繰り返し処理などで変換しよう。 ;いやまぁあんまいらんと思うけどこんなん。逆に文字から数値にするときはlpeekを使う。
;2バイト文字か否かの判断(hsp3.0) ;シフトJISはひらがななどを2バイトで表現します。 ;半角のアルファベットや数字や記号は1バイト。 ;2バイト文字の1バイトだけをstrmidなどで移動してしまうと予期せぬ文字になってしまいます。 ;2バイト文字の1バイト目は必ず0x82〜0x9F か 0xE1〜0xEF です。たぶん。 ;よってpeekで1バイトづつ調べて↑の数値を発見したら2バイト文字だから2バイトをstrmidなどで移動、 ;それ以外なら1バイト文字だから1バイトstrmidで移動、といった処理ができます。 ;あ、「0x」と書くと16進数で数字を書けるという仕組みにHSPは元からなってます。 ;「0x」以外にも、$を数字の前につけて例えば $ffff と書くと65535になります。 moziretu="あa" a=peek(moziretu,3) if ((a>=0x82)&(a<=0x9F))|((a>=0xE1)&(a<=0xEF)):mes "2BYTE文字" if a="\0":mes "esc" ;←"\0"は文字列の最後に必ずつく終わりですよのしるし。1BYTEである。 ;↑はまぁmoziretuの3BYTE目をpeekで取り出してaに代入してaを判断してるだけ。3BYTE目は\0があるのでescと表示されて終わり ;あと、peekでいっきに真中らへんの数値をとって2バイトか判断してどうたら、は無理。 ;2バイト文字の1バイト目は範囲が決まってるのだが、2バイト目も1バイト目と似た数値である場合がある為誤動作の元になる。 ;文字列の頭から1バイト2バイト1バイト1バイト…と繰り返しで進んでいく感じで調べないといけない。
;int型のSIN,COSテーブルを作る、ホーミングさせる。すげぇ適当(hsp3.0) ;---------------------SIN,COSテーブルを作るはじまり----------- dim vsin,1024 dim vcos,1024 for i,-512,512,1 a=sin(3.14159265358979323846264338327950288419*i/512) c=cos(3.14159265358979323846264338327950288419*i/512) vsin(i+512)=int(a*65536);ゲーム中に使用する配列に1024個のsin値を65536倍して入れる。 vcos(i+512)=int(c*65536);左が1024(0)、下が768、右が512、上が256 next ;---------------------SIN,COSテーブルを作るおわり------------- repeat redraw 1 await 10 redraw 0 kakudo=int(atan((mousey-y),(mousex-x))*163+512)&1023;●とマウスポインタを結ぶ線の角度(0〜1023) ix=vcos(kakudo)*2;ixは移動値。*2はスピード iy=vsin(kakudo)*2 sx=sx+ix;sxは計算用の●のx座標 sy=sy+iy; x=sx>>16; y=sy>>16;>>は右ビットシフト。1つビットシフトするごとに数値は半分になっていく。16回で65536で割るのと同じ color 0,0,0:boxf 0,0,400,400:color 255,255,255:pos x,y:mes "●":mes kakudo;表示 loop
;便利な&演算 x=x+1&1023 ;xは1づつ増加していき、1024になると0にもどります。(2のn乗-1)でのみ使えます。 y=y-1&63 ;yは1づつ減少していき、-1になると63になります。 &演算は二進数で考える。 09=1001   & 14=1110   ↓ 08=1000 と2つの値を1ビットづつ見て両方のビットが1の場合のみ1にするというものです。 1番左のビット以外は片方が0なので0になる。 63は 0111 1111  :2のn乗-1は最大の桁まで全てのビットが1の値である。 64は 1000 0000   &すると 0000 0000  :完全にゼロになります。カウンタに使いやすい。           :また0〜63の値なら63に&しても全て1なので全く同じ値が算出されます。 カウンタ処理以外だと配列の-1番目だとか、範囲外にアクセスしてエラーがでるのを防ぐのに便利。 あと、1ビットにつき1つのフラグを格納とかにも使える。1つの変数に32個のフラグを格納できるのでメモリ節約できる。 %010101000101;数値の前に%をつけると2進数で表記できます。 &    ;右から3番目のビットが1か0かを確認するには、 %000000000100;で&すればいいのです。    ↓ %000000000100;解はこうなる。解が0以外ならそのビットは1であると判断できる。
ビットがたってるか調べるマクロ(hsp3) 0か1だけの情報をもつフラグに1つづつ変数を使うと無駄にメモリを消費します。 1ビットで事足りる情報に32ビット使ってしまう。 以下てきとうマクロ #define ctype fget(%1,%2=0) zflag(%2)&(1<<%1) #define fset(%1,%2=0) zflag(%2)=zflag(%2)|(1<<%1) #defineでfget命令とfset命令を定義する。 zflagがフラグが格納されるグローバル変数とする これは用途によって変えればよい。 つかいかたは fset p1,p2 p1に何番目のビットを1にするか設定 p2に配列変数の何番目にするか設定。これを省略した場合、配列の0番目をチェック fset(10)でzflag.0の10番目のビットを1にする fget p1,p2 p1に何番目のビットを調べるか設定 p2に配列変数の何番目を調べるか設定。これも省略した場合、配列の0番目をチェック 実行すると調べたビットが0なら0が返り、それ以外ならそれ以外の値が返る a=fget(10) のように表記し、上記の場合10番目のビットが0かそれ以外かの値をaに格納する ただマクロなのでc言語みたいに融通が利かないので注意。 if fget(10,1)=0:mes "しっぱいれい" みたいにかくとダメかも。 if (fget(10,1))=0:mes "10番目は0" と括弧を余分につけなければならない。不便だっ てかなんかfget(10,1)みたいに書くとどうもうまく動かないかも… fget 10,2 と命令形式で書かないとだめかも(もーわけわかんね) 処理速度はフツーに変数使うより落ちる. 大体かけざん2発分ちょいくらい。 てかbool型みたいにフツーにサポートされてりゃいいのにな
MAP配列の読み込みのわりといいやり方(hsp2.61) メモリ配列に0なら空き地、1なら水、2なら山…みたいな配列のこと。 テキストで000000111000…とか描くのもやりづらいし自前でソフト作るのもタルいしめんどいので BMPファイルの色で判別するのが中々いいかと思う。 これなら編集も簡単だしわかりやすいしエディタも沢山あります。 リアルタイムで巨大なBMPを読ませなくても1度メモリ配列に読み込ませて あとはメモリから読むようにすれば速度も全く問題になりません。 hsp2のスクリプトですが…読み込み部分。↓ picload "0map.bmp";;-------------------MAP配列画像 for y,0,MAPY,1 ;MAPYはMAPの縦のでかさの定数です。仕様変更の際定数なら楽に直せます for x,0,MAPX,1 pget x,y if rval=64:map.x.y=-1;すり抜け床 if rval=255:map.x.y=1;ブロック if rval=254:map.x.y=2;棘 if rval=253:map.x.y=3;破壊可能ブロック if rval=1 :map.x.y=4;氷 if rval=128:map.x.y=5;ブロック2 next next 結構簡単に実装できますね。赤色成分だけを調べてます(rvalはシステム変数)。緑と青は自由。 敵の配置も同じようにビットマップで作れます。自分の近くだけメモリから読み込み ある程度接近すればそれに応じる敵を出現させればいい。メモリは0にする 画面切り替えとか死ぬとかしたらもう一度ビットマップから読み直せば敵は復活できます。 HSP3だとpgetやそれで取得するカラー情報の扱いが違うので注意。 HSP3は カレントカラーが0番screenだけでなく、bufferにもあります。 buffer2をgsel 2で選択してpgetした場合、buffer2のカレントカラーがそれになる。(自動で取得した色でcolor命令される) んでscreen0にgsel 0で戻ったらカレントカラーはscreen0のものを使用するのでうまくいかない。 buffer2のカレントカラーをginfo(16)〜ginfo(18)で取得(rvalやgvalは撤廃された)して変数に代入して使うという なんか退化してね?って感じの処理形態になってます。
効果音再生でのネタ 効果音の再生で注意すべきは大量の効果音を同時に鳴らしてしまう可能性がある場合。 50匹の「斬ると音が鳴る敵キャラ」が重なってるとそれを斬ったら50個のWAVEが鳴る。 音を鳴らす瞬間が同じだとひどい処理落ちが発生します。 しかもうるさいだけでゲーム的に意味がないので同時に鳴らす数を制限するといいです。 敵のやられの所にWAVE再生命令をするのでなく、 敵のやられの部分では音の再生を予約する、という形をとります。 同時に鳴らせる量は5個くらいあれば十分だと思います。 5つの再生枠に予約し、 1フレームに1回再生枠を確認して 予約されてれば予約した音を再生して再生枠は初期化すれば良いという事。 あ、同時再生は標準命令では無理なので HSP DirectSound Extensionってプラグインでやると楽。
多重条件式の処理の負荷を減らす IF文で if x>0&(x<=256)&(muteki=0)&(life>0){gosub *hit} と多重にするとき、&演算子を使うよりも if x>0{;● if x<=256{ if muteki=0{ if life>0{ gosub *hit } } } };● と言う風に汚くif文を増やしたほうが処理は軽くなります。 なぜなら多重に囲うと一つの条件が偽であると判った時点で 判定を終了して次に行くから。 &だと全ての条件を判定しなければ次に行きません。 かなりの頻度で判定される箇所なら&は使わないほうがいいです。 ただソースがわかりづらくなるので最初の{の後に何かコメントでマークをつけておきましょう。 ついでに( )を使うとわずかに処理が重くなります。
IF文の構文 ;初心者がデバッグでとれなくなるよくある原因、IF文の構文 if a=0:if b=0:end ;これを if a=0{if b=0:end} ;こう書くと構文エラー。「:」を使うifの後ろに「}」を置いてはならない。 if a=0{if b=0:end ;このように2行にわたって書くと通ります。 } if a=0{mes "a":if a=0{mes "b"}} ;1行にするならifに「:」を使わない。これなら通る if a=0:a=1:else:end ;あとElseは「:」ifでも使用可能 ;また、 #define aho if a=0:mes "a" ;このように#defineで「:」のifを内包するものを定義した場合も if a=0{aho} ;同様に「}」を後ろに置いてはならない。 ;まぁ基本的に{}を使えば問題は少ないはずだがエラーさえでなけりゃどっちでもいい
mes仕様 mesに数値変数aと文字を組み合わせるとき、 a=100 mes a+"円" と書くとまともに動きません。 なぜなら最初に数値型のaがあるので数値である、と認識されて 数値に文字列を足す、そりゃ無理だから無視、というわけで100とだけ表示するのです。 a=100 mes a+a なら 200 と出力されるはずです。数値どうしならまともに足し算。 100円と出力させるにはどうすればいいのかーというと a=100 mes ""+a+"円" とすればとりあえず最初の""で出力するのは文字列だ、と判断させれます 文字列と決め込んだHSPは数値も勝手に文字列として扱い「100円」と繋げてくれます。 a=100 mes a+"円"+a とすると出力は「200」になります。 数値と判断すると完全に文字列は無視するようです。
Win32API #uselib "user32.dll" #func invrec "InvertRect" int,var a=0,0,195,128 color 255,0,0 mes "ねがぽじねがぽじねがぽじはんてん" invrec hdc,a redraw 1 みたく書いて使うわけだが色々な引数への対応 dwordとかintとかlongとか数値→ intで大抵いいんじゃね *rect などの構造体のポインタ→ varで対応。構造体はa=0,0,64,64とか書いて配列作ってから aとだけ書けば配列の頭のポインタになるからそれを使う hdc、hwnd そんままhdcとかhwndって書いたらsystem変数にあるからいけるので簡単 *hpenなどのGDIオブジェのポインタ CreatePenとかで作るのが大抵だと思うのでそれやった後のstatにそれのポインタが返ってます あと sptr を引数にするのもいいみたい。数値だとそのまま、文字列だとそのポインタを自動で入れてくれるので殆どの引数に対応できる模様。
ホーミング色々 一番簡単なのが引き算で差を出してそれを埋めるように適当に動かすタイプ。これは置いといて atanで自狙いを常に行うタイプ(ある程度ゆっくり動く奴なら数フレーム毎に1回角度調整って感じでやると処理が軽くて良いです) そしてatanで自分の位置を常に確認しつつ、角度を増減させてじょじょに進行角度を修正して狙うものがあります。 この徐々に角度を増減させるタイプで問題になるのが大きい小さいでの判別がしにくいところ。 角度の幅が0〜1024なら 角度800の弾が角度900になろうと動くとしたら角度を+すればいい。 角度1000の弾が角度10になろうと動くとしても角度を+したほうが近いわけです。 数値は小さくなってるのに感覚的には大きくなってるので判別が面倒。 (↓変数neraiは自キャラへの角度、tamarは弾の現在角度) r=nerai-tamar if (((r>0)&(r<=512))|((r<0)&(r<=-512))){ tamar=tamar+10&1023 } else{ if (((r>0)&(r>512))|((r<0)&(r>-512))){ tamar=tamar-10&1023 } みたいなめんどくせー式になります。これの場合、10づつ角度を調整してます。
重い画像処理 回転処理は重いので大量にある物体なら最初からBMPに回転させた画像を用意する事をお勧めします。 ただ重いのにビビリ過ぎるのもよくないかもしれない…がHSPは遅いのでとにかくきつい。 半透明とか使いまくったエフェクトとかならON/OFFできるようにしたほうがいいかも。 あとHSPで2Dゲームやるならよっぽど負荷が薄いゲーム以外はパレットモード以外考えられません。 フルカラーはとにかく重いです。かなり早く限界に到達してしまう。 Ageとかプラグインを使えば加算描画とかもできるのでやっぱパレットモードお勧め。 EDGEなどで画像を作るといいでしょう。
数字表示 mesでやるより数字画像を用意してgcopyで1桁づつ表示したほうが軽い。 めんどいのでよっぽど大量に表示する可能性のあるもの以外はmesで十分だが。
どうでもいいこと if a{a=90};aが0以外なら、aを90にする。どうでもいい どうでもいいんだが ifとかのあとの{ }は中身かくまえに速攻後ろの}も書く癖つけたほうがいい。 forも同じく、 for i,0,10,1ってかいたら すぐに後ろにnextも書くと面倒じゃなくていい。 for文を多重にするときはコメントでnextの後ろにどれとどれが対応してるかかいといたほうがいい HTMLのタグ閉じもおなじ。 どうでもいい /^\*.*/k ↑サクラエディタでの正規表現(文字列検索マクロ)で左端に書いたラベル名の色設定 強調表示セットはとりあえずifとかgosubとかよく使う代表的なのだけやってりゃかなり見やすくなる 標準エディタはヘルプ見るときとコンパイルするときしか使わんでよし 面倒なので1タッチでコンパイルするサンプルスクリプトをつくってみた 標準エディタはなんかスムーズスクロールという悪のシステムを取り入れてるのかスクロールすると粘っこくひっかかる。 IEベースのブラウザとかでもインターネットオプションでスムーズスクロールは必ずOFFにしておこう。脱線した あと標準エディタは検索したときなんらかの条件でフリーズするので使いづらい。 タブの順番が変更できないのもやりづらい。 /* ないよう */ の複数行コメント化はあんまり正規表現詳しくないのでわからんかった ふつーにコメントスタイル-ブロック型のとこで機能が存在してるのに今更気づいた てか普通に考えたらここまで整備されてるのに無いはずないよね…アホらしー ちなみにセミコロンでのコメント化も同じとこの行型ってとこにセミコロン書くだけでOK これも無いと思って正規表現でやってた。
index