ウチツクシ

ゲームをしたり作ったり

とどけ蟻 スタンドアロン版(+ソースコード) とaxダイエット

HSPコンテストの季節がやってきた。今年で14年目、長寿なコンテストだなあと思う。作品応募者としては目標ができるし、ユーザーとしてはいろんな作品見られるし、今後もどんどん続いて欲しいな。
で、前回自分が応募したページ見ていてソース公開してなかったのに気づいて、せっかくなんでexeも作って公開しました。以下URLより。
https://1drv.ms/f/s!Ar6lqe2DjQo0gif3iUp0It6oqEC7

久々にスクリプト見て、ちょっとやり忘れ?な部分と memfile+picload で気づいたことを以下書く。

続きを読む

今覚醒めの時 Psyvariar

7月にiOSで配信予定のサイヴァリア新作リアセンブルのキャンペーンでデジタル新録AC版楽曲「Earth (MediumUnit Ver.)」が配信された。


サイヴァリアはゲーセン本格的に行きだした頃にハマったゲームで、Buzzの快感だけでなくBGMのトリップ感に心打たれて連日通い詰めだった。近場のゲーセンは音が小さくてスタッフに大きくしてもらえないかと頼んでみたら少し上げてもらえたけど、周りとの兼ね合いもあるしサイヴァリアやってるの自分くらいしか見たことなかったからあまり無理は言えない…それでちょっと遠くにあるゲーセンで大音量のサイヴァリア発見して興奮したのだった。

トリップ感溢れるBGMに相まって好きなのが出撃シーン。ほんとこれ体感するためにサイヴァリアにコイン入れてるんじゃないかってくらいに気に入ってしまっていた。今なおSTGにおけるマイベスト出撃シーン第一位を飾っている*1

その出撃シーンに流れるBGM「Earth」を聞いて、居ても立ってもいられなくなって深夜にPS2引っ張りだして録画した。

コイン入れる→スタートのテンションさ。周りが静かな中、大音量で聞くとヤバイ。
そこからあの出撃で一気にMAXになるのよ。
あとクリア→エリアセレクトの流れるようなシーケンス、BGMとのシンクロも堪らん…

……

ひとしきり懐古に浸って、リアセンブル。とても楽しみでしかたないんだけど、問題が一つあって。
iOSどうしよう…流石にACに移植ってのは無いよな…

*1:これが出たら一位の座は危なかった

特定のディスプレイの解像度を変更する

f:id:K-s:20160619184957p:plain

多分できる、で試してなかった。できたけど ChangeDisplaySettings じゃなくて Ex 付きの方だった。前者はメインディスプレイしか変更できないよう。EnumDisplaySettings に DeviceName 渡してるから DEVMODE にその情報入ってるのかと思ったよ…

#include "user32.as"

  screen 0, 400, 120
  dim moniInfo, 10 + 8  ; MONITORINFOEX
    moniInfo(0) = 40 + 32
  dim devMode, 44 ; DEVMODE
*mainLoop
  mx = ginfo_mx
  my = ginfo_my
  MonitorFromPoint mx, my, 0 ; MONITOR_DEFAULTTONULL
  if (stat) {
    GetMonitorInfo stat,  varptr(moniInfo)
    getstr dn, moniInfo, 40 ; szDevice
  } else {
    dn = ""
  }
  stick key, , 0
  if (key & 32) : goto *genList
  redraw 0
  color 255, 255, 255 : boxf
  color
  pos 0, 0
  mes strf("ginfo_mx,y = (%5d,%5d)", mx, my)
  mes strf("DeviceName = %s", dn)
  mes
  mes "[Enter]を押すと現在マウスカーソルのあるモニタの"
  mes "モード変更リストが表示されます"
  redraw
  await 15
  goto *mainLoop

*genList
  sdim buf
  num = 0
  repeat
    EnumDisplaySettings dn, cnt, varptr(devMode)
    if (stat == 0) : break
    buf += strf("%4d x %4d", devMode(27), devMode(28))
    buf += strf(", %2d bit, %3d hz", devMode(26), devMode(30))
    buf += strf(", %x\n", devMode(14))
    num++
  loop
  cls
  SetWindowPos hwnd, 0, mx, my, 0, 0, $5
  mes strf("DeviceName = %s", dn)
  mes strf("ModeNum = %d", num)
  mes
  mes "リストから選んで変更ボタンを押してください"
  objsize 100, 24
  pos 280, 84
  button gosub "変更", *changeMode
  pos 20, 84
  objsize 240
  objmode 2
  font msgothic, 14
  combox idx, 0, buf
  stop

*changeMode
  EnumDisplaySettings dn, idx, varptr(devMode)
  ChangeDisplaySettingsEx dn, varptr(devMode), 0, $4, 0 ; CDS_FULLSCREEN
  res = stat
  cls
  SetWindowPos hwnd, 0, ginfo_mx, ginfo_my, 0, 0, $5
  mes res
  if (res) {
    dialog "正常に変更できませんでした"
  } else {
    dialog "正常に変更されました\n終了すると元に戻ります"
  }
  goto *mainLoop

モードの最後のパラメータは解像度は同じでも比率を無視して画面全体に引き延ばすとかそういう設定?
モード変更すると戻った時に元あったウィンドウのサイズが変わったり別のディスプレイに飛んだりするし、マルチディスプレイだと位置も変わったりするからあまりソフト側で弄りたくはないなあ。

近況(スターフォックス零 感想)

なんとか生きてる。ツイートは自主規制中。もうすぐ新年だし一発目はなんかゲーム作って勝手に盛り上がろうか!と思ってたら全然作れなくて今に至る。愚か過ぎる…別に誰かと約束したわけじゃないけどここまで来たらな。

f:id:K-s:20160503102906j:plain:right:w240ゲーセン通いは随分減ったけど、WiiU買ったよ。スタフォ零。
GCと一緒にアサルト買って以来のハードと同時買い。アサルトはちょっと自分に合わなくて残念だったが、零は心配も吹っ飛んだぞ!30時間、一気に勲章コンプまでプレイしてしまった。右は初クリア時の写真。やっぱり字汚い。

普通に楽しいと思うんだけど、レビューとか見るとネガティブなのも結構あって複雑な気分でもある。期待が大き過ぎたのか、今のプレイヤーのレベルが高すぎるのか分からないけど。自分はシリーズはSFCの初代、64、アサルト、と今回の零やってて、操作系や面白さの方向も結構違ってて一概に比較するのは難しいが、今のところ零が一番好き。

まず立体音響に驚かされて、パイロットビューのジャイロ操作のもどかしさに笑わされて、リアルタイムでスムーズな変形に快感して。立体音響はほんと凄い。初め音声が右側に寄ってて位置が悪いのかと思ったらバイザー表現で味方は右から聞こえるようになってたのね。今生配信時々やっててその時ヘッドセット付けるんだけど、これ異常に臨場感あって楽しいw コメント読み上げ設定しててまだコメント来たことないけど、プレイ中に来たら混乱すると思う。ジャイロ操作が特に楽しかったのがタイタニアのボス。もうちょいもうちょいって身体すごい横にひねってた。昔レースゲームやってて身体が勝手に傾く人とかいたけど、あれを自発的にやってる感じがして面白い。あと変形、これはサテライト2が良い。このステージはタイムアタックになってて、コース取りや変形タイミングを詰めていく段階で変形が楽しくなってきた。

基本やってて楽しいのだけど、自分には合わないところもあって一部スコアアタックが。ゾネスやベノムの稼ぎは時間かかる上に地味であまり楽しくない…
あと裏ルート通ると仲間との掛け合いが少なくてちょっと寂しい感じ。父さんの演出は64版が思い出補正あり過ぎてそうじゃないだろ…ってなる。
そして対戦無いのはほんとなんでなんだ。64は対戦かなりやったし、アサルトも対戦楽しいらしい(やったことない)、ネット時代の今なら絶対だろうと思ったのだが。技術的な問題なんかな。

いまいちなとこもあるけど、やってて楽しいから買って良かったと思う。ちょうど店にWiiU本体入荷してた&5kmくらい手で持って帰った経験含めてw

とスタフォ零感想な近況でした。自作ゲーム超地味だけど年内には作るぜ!(旗は舞う

マルチディスプレイで解像度などの情報を取得する

追記:修正版をQiitaに書きました。


f:id:K-s:20160618182220j:plain
HSPの ginfo_dispx(y) はメインディスプレイの解像度しか得られないため、サブディスプレイで全画面ウィンドウを作るときなどには使えない。モニタを1つしか持ってないから気にならなかったのだけど、モニタに複数入力したらマルチできると気づき興味が出て調べた。リモコンで入力モード切り替える似非マルチ。

モニタの全ハンドルを取得するのは普通コールバックを使うらしいのだが、HSPは標準ではコールバック使えないから別の関数使って気合で取得した。EnumDisplayDevices とかは複数回呼ぶと全部取得できるのになんでこれはコールバックなんだ…
ただ、 コールバック用モジュールができました - HSPTV!掲示板 のモジュールを使えばコールバックもできるので使う場合は mod_clbk3.hsp で保存して1行目のコメント部分をアレしてください。

; #define USE_CALLBACK

#ifdef USE_CALLBACK
#include "mod_clbk3.hsp"
#endif
#include "user32.as"
#include "gdi32.as"

  ; 仮想画面の原点・サイズ取得
  GetSystemMetrics $4c ; SM_XVIRTUALSCREEN
  vsOriginX = stat
  GetSystemMetrics $4d ; SM_YVIRTUALSCREEN
  vsOriginY = stat
  GetSystemMetrics $4e ; SM_CXVIRTUALSCREEN
  vsSizeX = stat
  GetSystemMetrics $4f ; SM_CYVIRTUALSCREEN
  vsSizeY = stat

  dim hmoni
  moniNum = 0

#ifdef USE_CALLBACK
  ; コールバックを使ってモニタハンドルを列挙
  newclbk3 clbk, 4, *MonitorEnumProc
  EnumDisplayMonitors 0, 0, clbk, 0
  if 0 {
  *MonitorEnumProc
    clbkargprotect prm
    hmoni(moniNum) = prm(0)
    moniNum++
    return 1
  }
#else
  ; 仮想画面上の各点を調べてモニタハンドルを列挙
  sft = 100 ; 調べる各点の間隔
  repeat
    x = vsOriginX + cnt * sft \ vsSizeX
    y = vsOriginY + cnt * sft / vsSizeX * sft
    if (y > vsSizeY) : break
    MonitorFromPoint x, y, 0 ; MONITOR_DEFAULTTONULL
    h = stat
    if (h == 0) : continue
    f = 0
    if (moniNum) {
      ; ハンドルの重複チェック
      repeat moniNum
        if (h == hmoni(cnt)) : break
        if (cnt == moniNum - 1) : f = 1
      loop
    } else {
      f = 1
    }
    if (f) {
      hmoni(moniNum) = h
      moniNum++
    }
  loop
#endif

  ; 各ディスプレイの情報取得
  dim moniInfo, 10 + 8  ; MONITORINFOEX
      moniInfo(0) = 40 + 32
  dim devMode, 44 ; DEVMODE
  dim px, moniNum
  dim py, moniNum
  dim sx, moniNum
  dim sy, moniNum
  dim bit, moniNum
  dim hz, moniNum
  dim flag, moniNum
  sdim dn, 32, moniNum
  repeat moniNum
    GetMonitorInfo hmoni(cnt), varptr(moniInfo)
    px(cnt) = moniInfo(1) ; rcMonitor.left
    py(cnt) = moniInfo(2) ; rcMonitor.top
    flag(cnt) = moniInfo(9) ; dwFlags
    getstr dn(cnt), moniInfo, 40 ; szDevice
    EnumDisplaySettings dn(cnt), -1, varptr(devMode) ; ENUM_CURRENT_SETTINGS
    sx(cnt) = devMode(27) ; dmPelsWidth
    sy(cnt) = devMode(28) ; dmPelsHeight
    bit(cnt) = devMode(26) ; dmBitsPerPel
    hz(cnt) = devMode(30) ; dmDisplayFrequency
  loop
  
  ; デスクトップ全体のビットマップを取得
  buffer 1, vsSizeX, vsSizeY
  GetDC 0
  dc = stat
  BitBlt hdc, 0, 0, vsSizeX, vsSizeY, dc, vsOriginX, vsOriginY, $40CC0020 ; SRCCOPY | CAPTUREBLT
  ReleaseDC 0, dc
  celdiv 1, , , vsSizeX / 2, vsSizeY / 2
  
  ; 以下描画
  
  ; screen 0, 1024, 768
  gsel
  winsx = ginfo_sx
  winsy = ginfo_sy
  
  if (vsSizeX > vsSizeY * winsx / winsy) {
    rate = double(winsx - 40) / vsSizeX
    dox = 20
    doy = winsy / 2 - rate * vsSizeY / 2
  } else {
    rate = double(winsy - 40) / vsSizeY
    dox = winsx / 2 - rate * vsSizeX / 2
    doy = 20
  }
  
  font "arial", 12
  
  color 220, 220, 220
  box vsOriginX, vsOriginY, vsSizeX, vsSizeY
  pos ginfo_cx, ginfo_cy - 16
  color
  mes strf("pos(%d, %d), res(%d x %d)", vsOriginX, vsOriginY, vsSizeX, vsSizeY)
  repeat moniNum
    if (flag(cnt)) {
      color 220, 170, 170
    } else {
      color 150, 200, 200
    }
    box px(cnt), py(cnt), sx(cnt), sy(cnt)
    pos ginfo_cx + 6, ginfo_cy + 4
    color
    mes strf("pos(%d, %d)", px(cnt), py(cnt))
    mes strf("res(%d x %d)", sx(cnt), sy(cnt))
    mes strf("color %d bit", bit(cnt))
    mes strf("refresh %d hz", hz(cnt))
    mes dn(cnt)
  loop
  
  gmode 5, vsSizeX, vsSizeY, 40
  pos winsx / 2, winsy / 2
  celput 1, 0, rate, rate
  
  stop

#deffunc box int _x, int _y, int _w, int _h
  x1 = rate * (_x - vsOriginX) + dox
  y1 = rate * (_y - vsOriginY) + doy
  x2 = rate * (_x + _w - vsOriginX) + dox
  y2 = rate * (_y + _h - vsOriginY) + doy
  boxf x1, y1, x2 - 1, y2 - 1
  color ginfo_r + 20, ginfo_g + 20, ginfo_b + 20
  boxf x1 + 4, y1 + 4, x2 - 5, y2 - 5
  pos x1, y1
  return

GetMonitorInfo で得られた szDevice を EnumDisplaySettings に指定してそれで得た DEVMODE を ChangeDisplaySettings(6.19修正: ChangeDisplaySettingsEx じゃないとダメ)に渡せば特定のディスプレイの解像度変更なんかも多分できる。(→できた


今回調べてて分かったのは、

  • ソフトは起動すると基本的にメインディスプレイに表示される
  • ginfo_dispx(y) はメインディスプレイの解像度
  • MonitorFromPoint の引数は3つ(https://msdn.microsoft.com/ja-jp/library/cc410472.aspxだと2つに見える…初め配列のポインタ渡してて動かなかった、ずるい)