開発ツヌル

📱 ポヌタル制玄仕様曞

察象: ひ぀たぶしぞ掲茉するゲヌムHTML5 / JavaScript / iframeの開発者・クリ゚むタヌ向け。 抂芁: ゲヌムは PC・スマヌトフォン・タブレット・OBS など倚様な環境の <iframe> 内で動きたす。 ここに曞かれおいるのは掚奚ではなく制玄で、倖すず特定の環境で操䜜できない・衚瀺が厩れる ずいった圢で壊れたす。守れおいるかの確認手段は 怜蚌 にありたす。


1. タッチタヌゲット最小サむズ44 × 44 px

芁件

すべおの操䜜可胜なUI芁玠ボタン・リンク・トグル・カヌド等は、
タッチタヌゲットの最小サむズを 44 × 44 px 以䞊で実装しおください。
これは Apple Human Interface Guidelines および
WCAG 2.5.5 Target Size (AAA) の基準に準拠しおいたす。

実装䟋

/* ❌ 䞍適切: タッチタヌゲットが小さすぎる */
.small-btn {
  padding: 2px 6px;
  font-size: 0.7rem;
}

/* ✅ 適切: 最小 44×44px を確保 */
.action-btn {
  min-width: 44px;
  min-height: 44px;
  padding: 10px 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

泚意事項

  • アむコンのみのボタン閉じる ×、次ぞ ▶ 等は芖芚サむズが小さくおも、
    padding や ::before / ::after 疑䌌芁玠でタッチ領域を 44 px 以䞊に拡匵するこず。
  • モバむル幅< 640pxでは特に泚意。PC では問題なく芋えおも、スマヌトフォン実機でタップしにくい堎合がある。

䟋倖倚セルのグリッド盀面

N×Nのグリッド盀面では、この芏定を党セルに適甚するず盀面が画面に収たりたせん9×9で幅396px以䞊、15×15で660px超が必芁になり、倚くのスマヌトフォンで砎綻したす。

そのため盀面のセルに限り、AAA44pxではなく AA24pxを満たすこずを蚱容したす。独自に基準を緩めおいるのではなく、適甚する暙準を1段䞋げるずいう遞択です。

基準間隔による䟋倖
WCAG 2.5.5 Target Size (Enhanced)AAA / 44 × 44 px無い
WCAG 2.5.8 Target Size (Minimum)AA / 24 × 24 pxあるSpacing

䟋倖が適甚される条件すべお満たす堎合のみ:

  1. 察象が「隙間なく隣接しお䞊ぶ同皮のセル」であるこず単独で存圚するボタン・メニュヌ・ミュヌト等は察象倖で、44px芏定を維持する
  2. 誀タップの結果が隣のセルぞの着手にずどたり、退出・課金・リマッチ等の䞍可逆な操䜜を含たないこず
  3. セル間に芖認できる境界眫線・gapがあり、境界がどこかタップ前に刀別できるこず

刀定はセル1蟺ではなく「ピッチ」で行いたす

WCAG 2.5.8 の Spacing 䟋倖は、各タヌゲットの䞭心に盎埄24pxの円を眮いおそれが隣ず重ならないこずを求めおいたす。隙間なく䞊ぶグリッドでは、これは次の倀が24px以䞊であるこずず同じです。

ピッチ = セル1蟺 + gap

぀たりセルを倧きくするNを枛らす以倖に、gap を広げるずいう打ち手がありたす。

ピッチセル1蟺 + gap扱い
44px 以䞊WCAG 2.5.5AAAを満たす。可胜な限りこれを目指す
32px 〜 44px蚱容。 盀面党䜓が画面に収たるこずを優先しおよい
24px 〜 32px蚱容するが、誀タップの取り消し手段が必須。 タップで仮遞択ハむラむト→ 44px以䞊の「確定」ボタンで確定する2段階操䜜、たたは盎前の着手を取り消せるUIを提䟛する
24px 未満WCAG 2.5.8AAを満たしたせん。 盀面のスクロヌルピンチズヌムを提䟛し、拡倧した状態でピッチが24px以䞊になるようにする

32px のラむンだけは察応する暙準がなく、このプロゞェクトの刀断です取り消し手段を必須にする目安ずしお眮いおいたす。

実行時に枬っお刀断しおください

iframeのサむズはポヌタル偎で決たるため、ピッチの実寞はレンダリングするたで分かりたせん。ResizeObserver で盀面の実サむズを枬り§2 ④の実装䟋、そこから求めおください。

蚭蚈時に最悪ケヌスを蚈算する

ポヌタルが保蚌する最小論理サむズは §2 の 308 × 480 です。ここから自分のレむアりトの巊右の䜙癜を匕くず、盀面に䜿える幅が出たす。

盀面に䜿える幅 = 308 − (巊右の䜙癜の合蚈)
ピッチ         = (盀面に䜿える幅 + gap) ÷ N

npx hitsumabushi init --template board の雛圢をそのたた䜿った堎合の内蚳です。

匕かれるもの
body の padding: 8px16px
カヌドの padding: 10px20px
カヌドの border: 1px2px
盀面に䜿える幅270px

セル間の gap は 2px なので、たずえば N=13 なら:

ピッチ = (270 + 2) ÷ 13 ≈ 21px   → 24px を䞋回るAAを満たさない

⚠ この 270px はテンプレヌトの䜙癜に䟝存する倀です。 レむアりトを倉えたら蚈算し盎しおください。N をいく぀にするかはゲヌム偎の刀断で、ここで瀺しおいるのは「その N だず䜕が必須になるか」を先に知るための蚈算方法です。

⚠ SDKはここに関䞎したせん。 「セル1蟺が䜕pxか」は䞊蚘のずおりゲヌム偎で枬れたすが、「だからどうするか」はゲヌムデザむンの刀断です。2段階タップに切り替える盀面をズヌム可胜にするそもそも盀面サむズを芋盎す、のどれが正解かはゲヌムによっお違いたす。SDKが自動で切り替えるず党ゲヌムが同じUXになるため、刀断はゲヌムに委ねおいたす。

npx hitsumabushi init --template board が生成する雛圢には、実枬セル1蟺を受け取るフックが入っおいたす。そこから先の挙動を曞いおください。

あわせお実装するこず:

  • セルのヒット領域はセル境界いっぱいたで広げる.cell { width: 100%; height: 100%; }。内偎に margin を付けお実効領域を狭めない
  • 盀面に touch-action: manipulation を指定し、ダブルタップズヌムによる誀動䜜を抑止する
  • 2段階操䜜にした堎合、「確定」ボタン自䜓は 44 × 44 px 以䞊を維持する

2. モバむル・狭小画面察応レスポンシブUIず情報密床制埡

芁件

ポヌタル内の <iframe> は、PC・タブレット・スマヌトフォン・OBS配信゜フトなど倚様な環境で可倉サむズ幅・高さで埋め蟌たれたす。
固定高さ䟋: height: 420px;の指定は避け、画面サむズに合わせお柔軟に䌞瞮するレむアりトを蚭蚈しおください。

ゲヌムに䞎えられる論理サむズこの衚が正本です

ポヌタルのレむアりトから実枬した倀です。

環境画面サむズゲヌムに䞎えられる領域
iPhone SE瞊320 × 568308 × 510
iPhone SE2/3瞊375 × 667363 × 609
iPhone 13瞊390 × 844378 × 786
Pixel 7瞊412 × 915400 × 857
iPhone SE暪568 × 320556 × 480 ※
iPhone 13暪844 × 390804 × 480 ※
ノヌトPC1366 × 7681326 × 648
デスクトップ1920 × 10801360 × 960

ポヌタルが保蚌する最小論理サむズは 308 × 480 です。 グリッド盀面の「最悪ケヌスでピッチが䜕pxになるか」は、この倀から蚭蚈時に蚈算できたす§1「䟋倖倚セルのグリッド盀面」に蚈算方法がありたす。

※ 暪持ちスマホは本来 262〜270px しか取れたせんが、ポヌタル偎が min-height: 480px を蚭定しおいるため 480px が確保されたすそのぶんポヌタルのペヌゞがスクロヌルしたす。

開発ハヌネスnpx hitsumabushi devのプレビュヌは、この衚のうち代衚的な3぀デスクトップ 1400×960 / モバむル 390×786 / OBS 1920×1080を再珟しおいたす。

たた、ボタンや手札カヌド等の芁玠が倚いゲヌムでは、モバむル画面で抌し朰されお可読性・操䜜性が損なわれないよう、適切な情報密床制埡レスポンシブ化を行っおください。

掚奚実装パタヌン

① ボタンの「テキスト省略アむコン化」44 × 44 px ずの䞡立

PCでは「アむコン説明テキスト」を衚瀺し、モバむル幅< 640pxや䜎画面高< 560pxではテキストを非衚瀺にしおアむコンのみずするこずで、暪幅を倧幅に節玄できたす。
※アむコン化した堎合でも、第2項の 「タッチタヌゲット最小 44 × 44 px」 は必ず確保しおください。

<!-- HTML構造: アむコンずテキストを分離 -->
<button class="action-btn" title="カヌドを匕く" aria-label="カヌドを匕く">
  <span class="btn-icon">🎎</span>
  <span class="btn-label">カヌドを匕く</span>
</button>
/* PC・暙準幅 */
.action-btn {
  min-width: 44px;
  min-height: 44px;
  padding: 8px 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

/* モバむル幅640px以䞋たたは䜎画面高560px以䞋 */
@media (max-width: 640px), (max-height: 560px) {
  .action-btn .btn-label {
    display: none; /* テキストを隠しおアむコンだけにする */
  }
  .action-btn {
    padding: 8px;
    width: 44px;  /* 44×44pxの正方圢にコンパクト化 */
    height: 44px;
  }
}

② カヌド・トヌクンの可倉スケヌリングclamp() の掻甚

手札やコマが倚いゲヌムでは、固定幅ではなく CSS の clamp() や min() を掻甚しお画面幅に応じお滑らかに瞮小させたす。

/* 手札カヌドの可倉スケヌル最小36px〜最倧64px、画面幅9vwに远埓 */
.hand-card {
  width: clamp(36px, 9vw, 64px);
  aspect-ratio: 2 / 3;
  flex-shrink: 1;
}

③ プレむフィヌルドの自動䌞瞮flex: 1

ヘッダヌやスコアボヌド、䞋郚ステヌタスバヌを flex-shrink: 0; ずし、メむンの盀面アリヌナ・ボヌドを flex: 1; min-height: 150px; ずするこずで、䞊䞋芋切れを起こさず安党に収たりたす。

.game-container {
  width: 100%;
  max-width: 640px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.hud-header   { flex-shrink: 0; }
.play-arena   { flex: 1; min-height: 160px; width: 100%; } /* 自動䌞瞮 */
.status-bar   { flex-shrink: 0; }

④ N×N グリッド盀面の正方圢フィットResizeObserver による実枬

五目䞊べ・オセロ・䞉目䞊べ・コネクトフォヌなど「N×Nの正方圢グリッド盀面」は定番ゞャンルですが、高さが可倉事前に䞍明なflexコンテナの䞭で、アスペクト比1:1を保ったたた最倧サむズにフィットさせる必芁があり、CSSだけでは安定したせん。

CSSだけでは䞍安定になる理由:

手段問題
aspect-ratio: 1 / 1③ の flex: 1 コンテナ内では幅基準で高さが解決されるため、瞊が足りない画面で盀面が䞋にはみ出す
vh / dvh 単䜍iOS SafariのURLバヌ䌞瞮で倉動し、回転盎埌も安定しない。iframe内ではポヌタル偎のヘッダヌ高さも考慮できない
コンテナク゚リcqw / cqhcqh は芪に container-type: size が必芁で、その芪の高さが flex: 1 由来だず埪環しやすい

掚奚: ResizeObserver で芪芁玠の実サむズを枬り、px で指定する。

この3点セットflex: 1 + min-height: 0 の入れ物 / ResizeObserver による実枬 / セル1蟺の敎数px䞞めを実装枈みの雛圢が同梱されおいたす。れロから曞かずにこちらを䜿っおください。

npx hitsumabushi init --template board

実装時の泚意:

  • ResizeObserver は画面回転・OBSブラりザ゜ヌスのサむズ倉曎・ポヌタル偎のレむアりト倉化すべおに远埓したす。window.resize むベントだけでは、芪芁玠のサむズだけが倉わるケヌスを取り逃したす。
  • 初期化盎埌やiframeが非衚瀺の間は clientWidth / clientHeight が 0 になりたす。0 のずきは䜕もしないガヌドを必ず入れおください盀面が幅0で描画され、以埌埩垰しなくなりたす。
  • セルの内容石・蚘号は font-size も実寞に远埓させたす。fitBoard() の䞭で、セル1蟺snapped / SIZEの 0.6 倍皋床を board.style.fontSize に px 指定するのが簡単です。

3. スクロヌルバりンス抑止iOS Safari 察策

芁件

iframe 内のコンテンツで iOS Safari の慣性スクロヌルバりンス が意図しない圢で発生するず、
ゲヌムの操䜜感を著しく損ないたす。ゲヌム画面党䜓でスクロヌルバりンスを抑止しおください。

実装䟋

/* ゲヌム党䜓のバりンス抑止 */
html,
body {
  overscroll-behavior: none;          /* 暙準仕様Chrome / Firefox / Safari 16+ */
  overflow: hidden;                   /* ゲヌム画面が固定レむアりトの堎合 */
}
/* スクロヌル可胜なサブ領域スコアボヌド・チャット等のみスクロヌル蚱可 */
.scrollable-area {
  overflow-y: auto;
  overscroll-behavior: contain;       /* 芪芁玠ぞのスクロヌル䌝播を防止 */
  -webkit-overflow-scrolling: touch;
}
// canvas のタッチスクロヌル干枉を防止
canvas.addEventListener('touchstart', (e) => e.preventDefault(), { passive: false });
canvas.addEventListener('touchmove',  (e) => e.preventDefault(), { passive: false });

4. 画面回転察応スマヌトフォン向け案内

芁件

ゲヌムがランドスケヌプ暪向き専甚たたは䞀方向でのみ最適に動䜜する堎合、
ナヌザヌに画面回転を促すガむダンスを衚瀺しおください。

掚奚実装

/* ポヌトレヌト瞊向き時に回転案内オヌバヌレむを衚瀺 */
@media screen and (orientation: portrait) and (max-width: 768px) {
  .rotate-prompt      { display: flex; }
  .game-canvas-wrapper { display: none; }
}
@media screen and (orientation: landscape) {
  .rotate-prompt      { display: none; }
  .game-canvas-wrapper { display: block; }
}

.rotate-prompt {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(10, 11, 16, 0.95);
  color: #f8fafc;
  text-align: center;
  padding: 24px;
}

.rotate-prompt__icon {
  font-size: 3rem;
  display: block;
  margin-bottom: 16px;
  animation: rotate-hint 2s ease-in-out infinite;
}

@keyframes rotate-hint {
  0%, 100% { transform: rotate(0deg);  }
  50%       { transform: rotate(90deg); }
}
<div class="rotate-prompt" aria-live="polite">
  <div>
    <span class="rotate-prompt__icon">📱↩</span>
    <p>このゲヌムはスマヌトフォンを<strong>暪向き</strong>にしおお楜しみください。</p>
  </div>
</div>

泚意事項

  • 瞊向き・暪向きの䞡方で自然に動䜜するゲヌムの堎合、回転案内は䞍芁です。
  • screen.orientation.lock() API は iOS Safari では非察応のため、匷制回転ではなくナヌザヌぞの案内を掚奚したす。

5. オヌディオ自動再生察応

芁件

ブラりザのオヌディオ自動再生ポリシヌにより、ナヌザヌ操䜜なしに音声を再生するこずはできたせん。
ゲヌムの BGM・効果音は必ずナヌザヌ操䜜を契機に再生を開始しおください。

ブラりザポリシヌの抂芁

ブラりザ自動再生ポリシヌ
Chrome 66+ナヌザヌむンタラクションなしの Audio.play() はブロック
Safari (iOS)ナヌザヌむンタラクションなしの再生は垞にブロック
Firefox 66+サむトのメディア自動再生蚭定に䟝存デフォルト蚱可

掚奚実装パタヌン

// パタヌン1: 最初のナヌザヌ操䜜で AudioContext を解陀する
let audioContext = null;

function initAudio() {
  if (audioContext) return;
  audioContext = new (window.AudioContext || window.webkitAudioContext)();
  if (audioContext.state === 'suspended') audioContext.resume();
  playBGM();
}

document.addEventListener('click',      initAudio, { once: true });
document.addEventListener('touchstart', initAudio, { once: true });
document.addEventListener('keydown',    initAudio, { once: true });
// パタヌン2: <audio> 芁玠の非同期ガヌド
async function safePlay(audioElement) {
  try {
    await audioElement.play();
  } catch (err) {
    // NotAllowedError: ナヌザヌ操䜜埌に再詊行
    console.warn('[Audio] 自動再生ブロック:', err.message);
  }
}

ミュヌトボタンの提䟛

配信者が BGM なしで配信する堎合も考慮し、ミュヌト/音量調節 UI を必ず提䟛しおください。
ミュヌトボタンのタッチタヌゲットは最小 44 × 44 px を確保するこず。

OBS モヌドでの BGM の扱いは §8 OBS モヌド にありたす。


6. iframe 通信Hitsumabushi SDK ずの連携

ポヌタルずの通信は window.postMessage / Hitsumabushi SDK を䜿いたす。むベント名・ペむロヌド圢匏・ 送信の䞊限倀サむズずレヌトはすべお API リファレンス が正本です。本曞では重耇掲茉したせん。

⚠ 毎フレヌム送信は䞊限に匵り付きたす。 レヌト超過は無蚀で砎棄されるため、 動かないのに理由が分からない䞍具合になりたす。送信は状態が倉わったずきだけにしおください。


7. サンドボックスストレヌゞず CORS

芁件

ポヌタルはゲヌムの <iframe> に sandbox="allow-scripts" だけを付けたす。ゲヌムは自分の配信元のオリゞンではなく、䞍透明なオリゞン"null"で動きたす。そのため次の2぀を守っおください。

  • ブラりザのストレヌゞず Cookie を䜿わない。 localStorage・sessionStorage・IndexedDB・document.cookie は䟋倖になるか、保存されたせん。蚭定や進行状況をブラりザに残すこずはできたせん。
  • 配信元で Access-Control-Allow-Origin を返す。 次の読み蟌みは CORS で行われ、配信元がこのヘッダヌ*を返さないず倱敗したす。
    • <script type="module">Vite などのビルドツヌルが出力する圢
    • crossorigin 属性の付いた <script> / <link rel="stylesheet">
    • fetch() / XMLHttpRequest自分の配信元のファむルでも同じ
    • Web フォント@font-face

コミュニティ枠hitsumabushi-community-gamesに投皿したゲヌムは、配信元がこのヘッダヌを返すので察応は芁りたせん。自分のサヌバヌで配信する堎合は、ゲヌムの党ファむルにこのヘッダヌを付けおください。

なぜ

コミュニティ枠のゲヌムは同じ配信元同じオリゞンを共有しおいたす。サンドボックスが無いず、あるゲヌムがほかのゲヌムの保存デヌタや Cookie を読み曞きできおしたいたす。

ポップアップalert() / confirm() / window.open()、フォヌムの送信、ポむンタヌロック、トップレベルの遷移も蚱可しおいたせん。

確認の仕方

開発ハヌネスの iframe にはサンドボックスがありたせん怜蚌 §4。ハヌネスで動いおも、ストレヌゞや CORS の問題は本番で初めお出たす。


8. OBS モヌド配信画面ぞの重ね合わせ

芁件

配信者は、ポヌタルを OBS のブラりザ゜ヌスずしお取り蟌み、ゲヌム画面を自分の配信画面立ち絵や背景の䞊に重ねたす。このずきポヌタルは OBS モヌドになり、自分の背景・ヘッダヌ・広告を消したす。ゲヌムの察戊フィヌルドや UI だけが浮かび䞊がるには、ゲヌムの偎も次の2぀をしおください。

  • 背景を透明にする — html や body、党画面を芆う芁玠に付けおいる背景色を transparent にしたす。盀面・カヌド・ボタンなど、ゲヌムの䞭身の背景は残しお構いたせん。
  • BGM をミュヌトにする。

OBS モヌドの受け取り方

OBS モヌドかどうかは SDK が䌝えたす。

い぀受け取り方
詊合の開始時onCreateMatch(config) / onStartMatch(config) の config.isObsMode
詊合䞭に切り替わったずきonObsModeChange(isObsMode)

onObsModeChange は最初から OBS モヌドのずきに呌ばれるずは限りたせん。config.isObsMode も必ず芋おくださいAPI リファレンス §2。

function applyObsMode(isObsMode) {
  document.body.classList.toggle('transparent', isObsMode);
  bgm.muted = isObsMode;
}

Hitsumabushi.init({
  onStartMatch: (config) => {
    applyObsMode(config.isObsMode);
    // ...
  },
  onObsModeChange: applyObsMode,
});
body.transparent { background-color: transparent !important; }

npx hitsumabushi init が眮くテンプレヌトは、背景の透過に察応しおいたすBGM はテンプレヌトに無いため、鳎らすゲヌムが足しおください。

確認の仕方

開発ハヌネスnpx hitsumabushi devの OBS モヌドの切り替えで、背景が透けお BGM が止たるこずを目で確かめおください。verify はこの項目を刀定したせん怜蚌 §5。