【Advent Calendar 2022】任天堂のプログラミングソフト(はじプロ)で「スマブラ」を目指した話【12月3日担当】

【はじめに】

カレンダーはこちら:https://adventar.org/calendars/7667
2015年から続いているこの企画。もう7年の歳月が経つ。スマブラはチーム戦をする機会が増えてきた。
…が久しぶりに手を出したはじプロ熱が再上昇しているので今年はこの記事で勝負することにした。
最初にソフトの説明を軽くしてから、作る経緯をまとめていこうと思う。

スマブラを題材にしているものの直接のスマブラではない話。もしかするとこの7年で最もつまらない記事かもしれない。
あと、単純に文字ばかりで見ていて面白くない。記述しておいて雑なことを述べてしまうが。
結論だけ知りたい人は【完成させたもの】を参照してください。


【はじプロとは】

任天堂から2021年に発売した「ナビつき!つくってわかるはじめてゲームプログラミング」のこと。
「任天堂の開発室から生まれた」というキャッチコピーで登場したGUI形式のプログラミングソフトである。
※GUI:グラフィカルユーザーインターフェース 視覚的に操作が可能な機器のこと(Windowsとかがその例となる)

ゲームを作るために必要なツールが最低限そろっておりゲームを作るハードルがかなり低くなっていることが特徴。
物理演算(重力を含む)が適用されている環境にパッケージ化されたアイテムを組み合わせるだけで作成可能。

ちなみに、過去のツイートでスマブラでご存知の桜井さんも遊んで投稿していたことが確認できる。
また、過去に芸能人のよゐこの2人も任天堂公式チャンネルで遊んでいる。
ちょっとした自慢として書くが、公式の動画に筆者の作品が登場している(リンクの11:40あたり)。
プログラミングやゲーム作成に精通した人からすれば、発想次第で容易にその環境を作れるありがたいソフトである。
物理演算が導入されていることから実際に物理実験をイメージをするときにも使える。


【スマブラはできるのか】

先に答えておくが、要求した水準まで達成することはさすがに無理である。初代の水準にすら到達しない。
このゲームにはコストが存在するほか、1キャラクターでできることも(スマブラを目指すには)少ないのである。
従って、目指すのはなんとなくスマブラっぽい感じの操作・システムが含まれている遊べる2Dアクションということになる。

ちなみに、開発スタッフのインタビューでもゲームを完全に再現するのは難しいが、一部分を再現するのは可能というコメントがある。
このことからマリオパーティのミニゲームを再現することが得意なソフトでもある(筆者もいくつか再現させたこともある)。


【完成させたもの(はじプロのゲーム内でダウンロードすれば遊べます)】

あらかじめコントローラを2つ用意してもらえれば対戦可能。Switch本体に直接接続されているJoy-Conは反応しないので注意。
1人で動作確認しているのでゲームバランスは保証しない(したいが)。ミラーマッチなのでキャラ差はない。
完成物(詳細Tweet(動画)):こちら(筆者のTwitterに飛びます)
ゲームID:G 006 TK3 WV4
プログラマーID:P 008 BLY XHD

ルール

  • ・3ストックの終点ステージで対戦。先に3回落ちたほうが負け。
  • 1Pが赤色の[ヒト]を、2Pが青色の[ヒト]を操作して戦う。
  • ・画面の中央にストック数とダメージが表示。これを見て試合を行う。
  • ・本家と同じく上下左右に撃墜判定がある。一定のラインを超えた段階で1ストックマイナス。
  • ・蓄積ダメージの上限は本家と同じく999%。
  • ・ステージから落ちて復活した後、少しの間操作できない(操作できないが無敵)。
  • ・無敵中は[ヒト]にエフェクトが入る。
  • ・カメラは固定。
  • ・決着がつくと約5秒後にゲームがリセットされ再戦となる。

操作方法

  • A:ジャンプ(はじき入力ではジャンプできない)
  • ・地上ジャンプと1回だけ空中ジャンプが可能。
  • ・着地する、ミスをする、崖を掴むのいずれかで空中ジャンプは復活する。
  • ・ジャンプの高さは一定で小ジャンプはない。
  • B:各種アクション(攻撃アクションは3種類)
  • ・弱攻撃/横強攻撃/ダッシュ攻撃の操作で横パンチ(ダメージ10,ふっとび率1,ベクトル15度)になる。
  • ・・操作の差で威力に差はない。・・威力は低いが隙が短く後述するキックよりリーチが長い。
  • ・横スマッシュ攻撃の操作でキック(ダメージ20,ふっとび率3,ベクトル30度)になる。
  • ・・ダメージはパンチの2倍でふっとばし力はパンチの3倍。崖際なら100%あれば撃墜できる程度。
  • ・・このワザにのみOP相殺が採用されている。連発するとダメージとふっとばし力が低下する。
    ※1つ前には"-0.15"倍/2つ前には"-0.10"倍/3つ前には"-0.05"倍になるように調整されている。
    ※例えば、2連続で使うと"1"-"0.15"="0.85"倍のダメージとふっとばし力になる。
  • ・上強攻撃の操作で上パンチ(ダメージ12,ふっとび率1.3,ベクトル80度)になる。・・スマッシュ入力しても威力は変化しない。
  • ・・対空ワザ。判定は真上で正面の相手には使えない。
  • ・・崖際でこのワザを実行すると崖を掴める。掴んだ後は自動的にジャンプ復帰する(掴んだ瞬間から上がって少しだけ無敵)。
  • L/R/ZL/ZR:回避(どれを押しても良い)
  • ・使ってから18F間相手からの攻撃をかわせる。回避は連打可能だが後隙はある。
  • ・回避動作中でもジャンプと移動はできる(ここは本家と異なる)。ワザは出せない。
  • ・最初から回避動作なのでシールドは使えない。また、このゲームに掴みはない。

【作成する過程の前に1つ用語説明】

プログラムするにあたって「ノードン」というキャラクターが作中で何体も登場する。
Switch内に生息しているという設定のキャラクター。80種類以上いる。詳細は公式のリファレンスを参照。
それぞれのノードンにゲームを動かすための役割が設定されておりこれらの役割を組み合わせることでプログラムするというもの。

「ノードン」と毎回書くのは大変なので、本記事では[ ]で囲まれた単語はノードンであるとして記述する。
赤色:入力 緑色:中間 青色:出力 黄色:モノ として表記する。組み合わせ次第では高度なものも組める。

説明が必要なノードンの抜粋

[定数]
固定された値を出力し続ける。文字通りの定数。"-1000"から"1000"まで指定できる。

[ボタン]/[スティック]
コントローラの入力をチェックする。コントローラ番号の指定が可能。
ボタンは押されると"1"、スティックは入力の度合いに応じて"-1"から"1"までを出力する。

[タイマー]
信号が入った瞬間に、(0秒を含めた)指定時間後に指定時間だけ信号を出すことができる。

[フラグ]
2つの入口(オン("1")とオフ("0"))を持ち、信号が入るたびに出力をオン("1")とオフ("0")で切り替えられる。
オンとオフの両方同時に信号が来た場合はオフになる。

[計算]
四則演算が可能。2つの入口があり、それぞれに入力された値をもとに計算し、出口に流してくれる。
数学上あり得ない"0"で除算させようとした場合は自動的に"1"にすり替えてエラー回避してくれる。

[くらべる]
2つの入口があり、それぞれに入力された値を同値(=)/大なり(>,≧)/小なり(<,≦)で比較できる。
条件を満たしていた場合のみ信号を流してくれる。

[カウンター]
初期値とカウンターの動作範囲を指定し、そこから入力された値を使って増やすか減らすかできる。
リセット用の入口も存在し、ここに信号がくれば初期値に戻せる。

[AND]
文字通りのAND機能。2つの入口があり、両方から信号が入ったときだけ出口に信号を流す。

[NOT]
文字通りのNOT機能。入口に入っている信号が"0"である場合に出口に信号を流す。

[0から変わった瞬間]/[スタートした瞬間]
入口に信号が入った最初の"1F"/ゲームが開始された"1F"だけ信号を出してくれる。

[角度を位置に]
0以上360以下の値が入力されるとその値を角度として扱い、角度に応じた横位置(cos)と縦位置(sin)を出してくれる。
ワザで相手をふっとばす時のベクトル調整に使う。

[音を鳴らす]/[BGMを鳴らす]
条件を満たした時にヒット音などの効果音を鳴らせる。
BGMは信号が入っている間だけ再生され、一時停止もできる。

[時を止める]
信号の値に応じて時間の流れを遅くすることができる。
完全に止めることはできず、"0.001"倍までしかならない。

[リトライ]
ゲームを初期状態にリセットできる。試合が終了したときに自動的に再戦できるようにするために使う。
[スタートした瞬間]も信号を出し直す。

[ヒト]
実際に操作する人型のキャラクターをゲーム画面に出す。
前後移動/左右移動/ジャンプ/アクションの入口があり、それぞれに信号が入ると値に応じた行動をとる。

[モノ]/[動かせるモノ]
これと言った特徴のない、シンプルなモノ(直方体/円柱/球)をゲーム画面に出す。
[動かせるモノ]はX,Y,Zの入口があり、この入口に信号を送ると数値に応じて物体を動かせる。
なお、センサーを含めた全ての物体について「視認の可否」が設定可能。

[モノ(Joy-Con(L))]/[モノ(Joy-Con(R))]
正確には[オシャレなモノ]というカテゴリに含まれるアイテムの1つ。
見た目がJoy-Conの直方体をゲーム画面に出す。今回は2人いる[ヒト]の区別をする際に使用する。

[モノを発射]
指定した場所から[モノ(直方体/円柱/球)]を出すことができる。
固定砲台として使えるほか、物体に装着して移動砲台としても使える。
発射した物体が物理法則を受けて移動するか、そのまま固定されるかを選択することもできる。

[モノを壊す]
指定した場所にある物体を破壊することができる。破壊した物体はゲームをやり直さない限り復活しない。
ただし、[モノを発射]で生成された物体については砲台となる[モノを発射]本体が破壊されないため何回でも復活できる。

[モノをワープ]
入口用と出口用の2種類が存在する。信号が入ったタイミングで入口にある物体を出口へ"1F"で瞬間移動させることができる。
入口、出口共に物体に装着させることができる。操作キャラクターにワープ入口を装着させればいつでもワープさせられる。

[エフェクト]
指定した場所にエフェクトを出すことができる。爆発だったりダメージだったり煙だったり様々。
[ヒト][モノ]に装着させて対象からエフェクトが出ているように見せることもできる。

[位置センサー]
位置情報をX,Y,Z座標で出力できる。情報を知りたい物体に装着して使う。

[触っているセンサー]
物体の周囲(中央・前後・上下・左右)に装着し、センサーが対象に触れている場合に信号を出す。
信号については触れた瞬間の1Fだけか、触れている間ずっと出すかを指定できる。

[角度センサー]
向いている方向をX,Y,Z軸単位で出力できる。情報を知りたい物体に装着して使う。

[ゲーム画面]
指定した場所が実際のゲーム画面として表示されるようになる。
物体に装着可能で装着した物体を追従させることもできる。
X,Y,Zの入口があり、ここに値をいれると画面の位置をずらすことも可能。


【実際に作りはじめる】

まず、一言にスマブラと言ってもシチュエーションは山のようにあるので以下に絞って作る。

  • ・1on1(つまり操作キャラクターは2人)
  • ・ストック数を調整可能(つまり1回落ちても復活できる)
  • ・ステージは「終点」(つまり平坦でステージ外に出れる)
  • ・アイテムはなし(つまりシンプルな戦い)

【ステージを作る】

ステージ本体となる[モノ(直方体)]を空中に設置(固定)すれば終点を作れる。今回はこれでおしまい。

ちなみに「戦場」ステージを作ると難易度が激増する。空中にあるすり抜け床を作成するのがものすごく難しいからである。
当たり判定のある[モノ]を用意した場合、下からすり抜けられない。
当たり判定のない[モノ]を用意した場合、上から着地できない。といった問題がでるので別途工夫が必要になるからである。
…ので今回は「終点」として難しく考えないことにする。


【キャラクターを作る(はじき入力)】

前述のとおり[ヒト]を使う。1on1を想定して2人設置する。
この[ヒト]には左右の移動、ジャンプ、アクションの機能があるためこれらを組み合わせてスマブラっぽい動きを作っていく。
今後使う要素としてあらかじめ[フラグ(操作可能判定)]を用意する。これは基本的にはオンにしておくが以下の状態でオフになるようにする。
・ゲームが始まる前
・ステージから落下した直後からステージに戻るまで
以降は特に断りがない限り、この[フラグ]はオンであることを前提に進める。

はじき入力はスマブラの要ともいえる要素である。当然これは採用したい。
入力には当然[スティック]を使用する。今回は左右方向へのはじき入力のみを定義し、上下方向にははじきの概念を導入しない。

[スティック(左右)]の入力値が"0"以外になった瞬間をトリガーにし、[0から変わった瞬間]に信号を送る。
[0から変わった瞬間]から[タイマー]で"6F"の猶予時間を設ける。
[タイマー]が有効の間に[スティック]の入力値"-1(左最大)"か"1(右最大)"になったらはじき入力になったと判定する。
[スティック]の入力値と[定数("-1"と"1"をそれぞれ用意)][タイマー]の3つを[AND]でつなぐ。
☆後々使用することになるのではじき入力になったと判定できた場合を[フラグ(はじき判定用)]を用意して記録する。
→この[フラグ(はじき判定用)]は左右移動とスマッシュ攻撃に使う。オンにしたフラグは必要に応じてオフになるように後々調整する。


【キャラクターを作る(左右移動)】

前述ではじき入力できるようにしたので左右移動は通常入力とはじき入力で差が出るようにしたい。
その昔、カービィシリーズの十字ボタン2度押しによるダッシュが通常の1.4倍だった気がするのではじき操作で1.4倍の速度になるようにする。
キャラクターの移動モーションにステップ(本家で言う移動開始時のシールドを展開できない時間)はないのでこれは考慮しない。
また、[フラグ(ワザ入力判定用)]を用意する。ワザが入力されている間はオンになり、そうでないときはオフとして扱う。
これはワザを繰り出しているかを判定するためのフラグでワザを出している間は移動できないようにするために使用する。詳細は後述。

[フラグ(はじき判定用)][定数("0.4")][計算(乗法)]でつなぐ。はじき判定が出ていれば"0.4"が出力される。
☆上記の結果を[定数("1")][計算(加法)]でつなぐ。はじき判定が出ていれば"1.4"、出ていなければ"1.0"が出力される。
☆上記の結果を[スティック][計算(乗法)]でつなぐ。はじき判定が出ていれば[スティック]の入力が"1.4"倍で出力され、通常("1")倍より速く移動できる。
☆上記の結果と[フラグ(ワザ入力判定用)][計算(乗法)]でつなぎ、最終結果を[ヒト]の左右移動入力につなぐ。
[フラグ(ワザ入力判定用)]はフラグがオフの(ワザが出ていない)時を使いたいので[NOT]を挟んでおく。
[スティック]が入力されている状態でワザが実行されていなければ、はじきの状態に応じた移動が可能という形がこれで完成。


【キャラクターを作る(ジャンプ)】

当然だが、この[ヒト]は空中ジャンプなんて高度な動きはできない。空中ジャンプできるスマブラのファイターが異常なのである。
しかし、スマブラを目指すのであれば空中ジャンプは必須技能。ということで実装する。
方法は簡単である。空中でジャンプできないのなら一瞬だけ地上判定になるように調整してジャンプさせれば良い。

ちなみに、初期状態では壁ジャンプは可能である。
これはジャンプモーションで片足を前に出し、壁にめり込むことで地面に接している判定がでてしまうからである。

A.地上ジャンプと空中ジャンプの判別
☆あらかじめ、[触っているセンサー(直方体)][ヒト]の足元に装着しておく。
→このセンサーは[ヒト]が地上(ステージとなる直方体)と空中のどちらにいるのか判定する際に使用する。
[ボタン(A)][ヒト]のジャンプ入力に接続してジャンプできるようにする。今回ははじき入力によるジャンプは考慮しない。
[カウンター("初期値:空中ジャンプ可能回数")]を仕込み、[触っているセンサー]が反応してない(空中にいる)時かつ[ボタン(A)]が入力された場合に[カウンター]を"-1"する。
→地上ジャンプでは[カウンター]の値は減らない。[ヒト]の標準機能でジャンプは地上でしかできないので地上ジャンプについては深く考慮しなくても良い。
[カウンター][定数("0")][くらべる]で比較し、[カウンター]の値が0より大きければ空中ジャンプできる条件になるようにしておく。
[触っているセンサー]が反応した(地面である直方体に接した)瞬間、落下判定(後述)が出た瞬間、崖を掴んだ(後述)瞬間に[カウンター]の値をリセットし再び空中ジャンプできるようにする。

B.実際の空中ジャンプ処理(上記の条件を満たしてジャンプ信号が入力された場合の処理)
[モノを発射(円柱)][ヒト]の足元に装着しておく。この円柱はあたり判定はあるが視認できない状態にしておく。
☆上記の空中ジャンプの信号を[モノを発射]に接続する。
→空中ジャンプ信号が入ったタイミングで円柱を上方向([ヒト]の真下)に発射される。[ヒト]にこの足場を利用させて空中で地上ジャンプをさせる。
[ヒト]が触れた[モノ(円柱)]を破壊できるように設定変更し、足場にした円柱を即座に破壊されるようにする。

ちなみに、[モノを発射]において上方に速度をつけて発射させることで
勢いのついた円柱が[ヒト]に衝突する→玉突き効果で[ヒト]に勢いが移る→結果的に高く上昇する を実現可能。
発射速度の調整でジャンプ力を調整できる。これは主にジャンプ上昇中に追加ジャンプされた場合の処理に影響する。


【キャラクターを作る(ストック数/落下判定)】

キャラクターが動かせるようになったのでストック数の扱いと落下判定を実装する。

A.ストック数の定義
☆ストック数は[カウンター(初期値:開始時のストック数)]で定義し、後述する落下判定が出るたびに"-1"する。
[カウンター][定数("0")][くらべる]で比較してイコール([カウンター]の値が"0")になった時、試合終了とする。

B.落下処理
ストック制スマブラで落下したときにやらなければいけない処理は以下の通り。これらができるように準備する。
本家では撃墜回数や累計ダメージなども裏方で計算している(結果画面で出している)が今回はそこまで考慮しない。

  • ・ストックが残っている場合は一定時間後にキャラクターをステージ上に戻す
  • ・ストック数を"-1"する
  • ・蓄積ダメージを"0"にリセットする(蓄積ダメージについては後述)
  • ・ワンパターン相殺をリセットする(ワンパターン相殺についても後述)
  • ・空中ジャンプ回数をリセットする
  • ・勝敗が決まった(最終ストックだった)場合に試合終了の演出を出す

[位置センサー][ヒト]に装着し、X座標とY座標を参照できるようにしておく。
[位置センサー(X値,Y値)][定数(撃墜ラインとなる数値)][くらべる]で比較し、条件を満たした([ヒト]がステージより外側に出た)場合に落下したと判定する(信号を出す)。
→この判定(信号)を使ってストック"-1"や各種数値のリセットを行う。
→また、[フラグ(操作可能判定)]をオフにしてプレイヤーの操作を受け付けないようにする。
☆落下判定の信号を[タイマー(復活待機用)]に送り、"60F"後に[モノをワープ][ヒト]をステージに戻す。
[フラグ(操作可能判定)]もオンに戻してプレイヤーが再び操作できるようにする。
☆ワープしたタイミングで[タイマー(復帰直後無敵用)]を"60F"持続で用意し、ワープしてから"60F"間は無敵であるように調整する。
→後述するあたり判定で「相手が無敵になっていない」という条件でこれを使用する。

これで[ヒト]を戻せるようになるが「復活土台」が登場しない。
今回は実装しないが[ヒト]がステージに戻ったタイミングで[モノを発射(円柱)]を使って[ヒト]の下に台を出せばそれらしいものは作れる。
[フラグ(操作可能判定)]がオンの状態で[ヒト]に対する操作が行われた時に[モノを壊す(円柱)]で台を破壊すれば良い。


【キャラクターを作る(ワザ)】

今回操作している[ヒト]だが、標準で搭載されているアクションが以下の4つしかないのでこの4つでやりくりしていく。
スマブラ並のワザ数を搭載するのはさすがに無理である。

  • ・やったぜ(上方向に拳を突き上げる、いわゆる勝利ポーズ)
  • ・パンチ(正面に拳を突き出す、キックより見た目のリーチは長い)
  • ・キック(正面に脚を突き出す、パンチより見た目のリーチは短い)
  • ・ターン(両手を上げてその場で1回転する、全体モーションが長い)

ということで前方に対する攻撃は「パンチ」と「キック」で、上方向への攻撃は「やったぜ」で作る。
「ターン」はボタンを押したら回避できる形で採用することを目指す。アクションは[ボタン(B)]で行うようにする。

ここで前述した[フラグ(ワザ入力判定用)]が登場する。1度ワザが入力されたらオンになり、ワザの動作終了後にオフになるような形で使う。
フラグをオフにする(ワザの動作終了と扱う)タイミングは[タイマー]で調整する。
この仕組みを用意しておかないとワザを"1F"単位で連発できる状態になり、[ヒト]が各種アクションをしながらスライドして移動できるようになってしまう。
ただし、回避動作にあてるターンに対しては攻撃ワザは出せないが[スティック]の左右移動は受け付けるように調整する。
本家の緊急回避ほどメリハリはないが、移動しながらの回避をこれで採用する。

A.あたり判定/ワザの発生と持続
☆あたり判定には[触っているセンサー(ヒト)]を使う。大きさを調整した状態で[ヒト]に装着する。
→装着した[ヒト]はセンサーの対象にならない仕様があるので判定が出るのは相手の[ヒト]だけである。
→今回は1on1なので[ヒト]がセンサーに反応したかだけ見れば良い。[ヒト]が複数いる場合は「どの[ヒト]だったか」を区別する工夫が必要。
☆ワザの発生調整に[タイマー]を使う。[ボタン](+[スティック])が入力された直後に[タイマー]を作動させ、発生させるFと持続Fを調整する。
[タイマー][触っているセンサー][AND]で接続する。
[タイマー]が有効になっている状態で[触っているセンサー]が相手の[ヒト]に触れていた場合にワザがあたったと判定する仕組みである。
[触っているセンサー]は各攻撃ごとにつける。従って[触っているセンサー]はパンチ用、キック用、やったぜ用の計3つ。
☆上記の判定に追加して前述(落下判定)、後述(回避動作、崖)する
 「相手が無敵になっていない(落下無敵、手動回避、崖無敵の全てが該当しない)」条件を[AND]で接続する。
→プログラム上では「無敵になっている」状態が"1"として出るので[NOT]を中継して「無敵になっていない」状態を用意する。
☆あたった場合、ダメージ計算及び吹っ飛びの力を加えるように調整する。
→ダメージ計算には[カウンター(ダメージ用)]を使う。スタートは"0"で攻撃を当てるたびに加算されるようにする。ミスしたら"0"にリセット。
→ふっとびの計算は後述。

B.無敵の扱い
スマブラには「無敵」という概念が存在している。物理的にあたっていてもあたっていない扱いする処理。
今回では以下の条件で無敵を付ける。いずれか1つでも満たしていた場合に「無敵になっている」として扱う。

  • ・回避動作が行われた時
  • ・ミスしてステージに戻ってくるまで(前述で"60F"の[タイマー]を採用している)
  • ・崖を掴んで上がるまで(後述)

[ヒト][エフェクト]を装着し、回避の判定が出ている間はエフェクトが出て視認できるようにする。
☆手動の回避には[ボタン(L/R/ZL/ZR)]を使用する。どのボタンを押しても良い。
[タイマー]を2つ用意する。無敵時間を扱う[タイマー(無敵時間用)]と回避動作の全体Fを扱う[タイマー(全体動作用)]である。
→1度の回避動作で「無敵F」と「全体F」に差があるため別々に管理する。
[フラグ(ワザ入力判定用)][NOT]で接続し、ワザが出ていない状態を用意する。
[タイマー(全体動作用)][NOT]で接続し、回避動作が出ていない状態を用意する。
☆上記の2つと[ボタン]の計3つを[AND]で接続し、ワザも回避も出してない状態でボタンが押された状態を作る。
☆上記の[AND]結果を[タイマー(無敵時間用)][タイマー(全体動作用)]に接続し、無敵時間と全体動作を行えるようにする。
これで無敵判定が可能である。

C.攻撃の判別
まず、各種アクションは以下の状況で出すようにする。各ワザの特徴は冒頭で説明している。
ワザに優先度(同時に条件を満たした場合、どちらを使用するか)も定義する。

パンチ
弱攻撃、横強攻撃、ダッシュ攻撃の操作で出る。見た目の区別ができないため性能に差はない。ワザの優先度は最も低い。
「キック操作を満たしていない([スティック]が横はじき入力されていない)」かつ
「やったぜ操作を満たしていない([スティック]が上入力されていない)」状況で[ボタン(B)]が入力された場合に実行する。

キック
横スマッシュ攻撃の操作で出る。また、この攻撃に対してのみワンパターン相殺のようなシステムを取り入れる(後述)。優先度は最も高い。
スマッシュ攻撃の扱いは以下のように実装する。
[フラグ(はじき判定用)][0から変わった瞬間][タイマー]の3つを順に接続し、[タイマー]には"6F"間だけ信号を流すように調整しておく。
→はじき入力がでてから"6F"間という制限がこれでつけられる。
[タイマー]が信号を出している状態で[ボタン(B)]が入力された場合に「スマッシュ攻撃」と判定しキックをだす。

やったぜ
上強攻撃の操作で出る。今回、上下入力にははじきの概念を含めていないので上スマッシュ攻撃の操作でも出る。優先度は中間。
使用時に小さくジャンプするのでこのワザを崖下で使った場合に崖を取れるようにし、復帰ワザに見立てる。
といっても「64リンクの回転斬り」並の高さしか出ないのだが(崖については後述)。
「キック操作を満たしていない([スティック]が横はじき入力されていない)」かつ
[スティック]が上入力されている」状況で[ボタン(B)]が入力された場合に実行する。


【ゲームシステムに関する調整(ふっとび計算)】

スマブラは相手をふっとばすゲーム。ダメージを与える処理を入れても実際にふっとばす処理を入れないとゲームにならない。
しかし、[ヒト]に勢いよくふっとんでくれる機能は存在していないので[動かせるモノ(球)]を使って球にふっとんでもらう。
ふっとんだ球に追従する形で[ヒト]をふっとばしていく。
ふっとんでいる時間(硬直時間)も併せて定義する。本当はダメージに応じて長くするべきだろうが、今回は一律"24F"とする。

A.角度の計算とふっとび硬直
☆あらかじめ、各種ワザのベクトルを定義する。今回はパンチ:30/キック:45/やったぜ:80とする。
☆この定義には[角度を位置に]を使用し[定数("15","30","80")]を入力してそれぞれのcosとsinの値を出しておく。
[ヒト]が左向きか右向きか、どちらの向きで攻撃をあてたか判定するため[ヒト][角度センサー]を装着する。
→左を向いていれば"-90"が、右を向いていれば"90"が出力されるのでこれを向き判定に使う。
☆上記の結果を[角度を位置に]の入力に使用し、横位置の出力を使う。
→"-1"か"1"が出るのでこれを向き計算に使用する。
☆ベースとなる[定数("90")]とそれぞれのワザのベクトルを調整するための[定数("10","45","60")]を用意する。
[定数("90")]とそれぞれのベクトルの[定数("10","60","75")][計算(減法)]で接続する。
→右向きであれば"90"-"10"="80"/"90"-"60"="30"/"90"-"75"="15"が出る。
→左向きであれば"90"-"-10"="100"/"90"-"-60"="150"/"90"-"-75"="165"が出る。
→これで右向きも左向きも正しい角度でベクトル計算されるようになる。
☆何かしらのワザがあたったタイミングで[タイマー(ふっとび硬直用:"24F")]をつける。
[タイマー]の結果とベクトルの結果を使い、後述するふっとばし計算をする。

B.ふっとびの計算
[カウンター(ダメージ用)][定数("各ワザの基本ふっとばし率")][計算(乗法)]で接続して計算する。
→ダメージが高いほど乗算した結果は大きくなる。これだけでもダメージ次第で大きくふっとばせるというシステムは作れる。
[定数]はスマッシュ攻撃にする「キック」で高めに設定しておく。
☆上記の結果と前述した[角度を位置に]の横位置と縦位置をそれぞれ[計算(乗法)]で接続する。
→横方向と縦方向のふっとびの度合いがこれで確定する。
☆上記の確定したふっとびと[タイマー(ふっとび硬直用)][計算(乗法)]で接続する。
→タイマーが出ている(ふっとびの"24F")間はふっとびの値が出る。
☆最終結果を[動かせるモノ(球)]に接続する。
[ヒト]が球に追従するので球に力が入ればそれに合わせてふっとぶ。


【ゲームシステムに関する調整(ワンパターン相殺)】

自らがプログラミングしている以上、調整し放題なので後隙やリーチは考えるのだが
キックだけ露骨にふっとばすようになっているのでキックだけでゲームを成立しかねない。
なのでワンパターン相殺を取り入れる。同じワザばかりを使っていざというときに失敗した経験をこの場でも味わえるようにする。

本家では基本的にすべてのワザを対象に取るが、今回はワザが3つしかなく必然的に重なりやすい。
したがって、リターンの最も大きい「キック(スマッシュ攻撃)」にのみワンパターン相殺の仕組みを取り入れる。
本家ではキュー9回分を記録するが今回はゲーム内で使用できるコストも考慮してキュー3回分として採用する。
また、何かしらの攻撃を当てた場合にキューをずらし、ミスをした場合はリセットされる処理も本家に合わせる。

倍率は1回目:"0.15"/2回目:"0.1"/3回目:"0.05"とし、本家と同じく合算で倍率を減らしていく。
過去3回で1度もキックをしていなければ"1"倍に、この状態からもう1度あてれば"1"-"0.15"="0.85"倍に
1回前と3回前であてた状態でもう1度あてれば"1"-("0.15"+"0.05")="0.80"といった具合になるようにする。

☆3回分記録するので[フラグ]を3つ用意する。それぞれが1,2,3回目の履歴を担当することになる。
☆ワザがあたった段階で[フラグ(2回前)]の結果を[フラグ(3回前)]に移し、[フラグ(1回前)]の結果を[フラグ(2回前)]に移す。
☆ワザがあたったかつそれが「キック」だった場合のみ[フラグ(1回前)]をオンにする。違うワザであれば[フラグ(1回前)]はオフにする。
[フラグ(1,2,3回前)][定数("0.15","0.1","0.05")]をそれぞれ[計算(乗法)]で接続する。
[フラグ]がオン(キックだった場合)であれば記録に応じて"0.15","0.1","0.05"が出力されるようになる。
[定数("1")]と上記の結果を[計算(減法)]で接続する。
→もとの"1"倍からフラグがオンになっていた場所のみ引き算されるのでワザの記録に応じて倍率が減るという寸法である。
☆最終的な結果をもとにして[カウンター(ダメージ用)]とふっとび計算に使うようにすればワンパターン相殺を反映できる。


【ゲームシステムに関する調整(崖掴まり)】

復帰ルートが上からに限られているとスマブラはかなりやりづらい。
下から復帰できる選択肢がないと復帰阻止が簡単になってしまう。
それを上手く調整しているのが「崖を掴む」という行為である。このシステム、昔から思っていたが画期的である。

前述の通り「やったぜ(上パンチ)」が小さくジャンプして拳を突き上げる。
これで崖に手を伸ばしたように見せることで崖を取った扱いにする。

☆本家と異なりキャラクターによって崖を掴める範囲が異なるということは今回ない。
→崖の判定については共通の値を参照できるので[ヒト]でなくステージに崖を掴める判定を用意する。
☆崖を掴めるのは「やったぜ」が実行されたときのみする。
→本家のようにスティックを下に倒していた場合は掴めないなどの複雑な条件は今回は無視する。
☆崖を掴める判定には[触っているセンサー(ヒト)]を使う。このセンサーを崖下に配置する。
☆崖を掴める場所への実際の移動には[モノをワープ(Joy-Con(L),Joy-Con(R))]をそれぞれ用意する。
[ヒト]をワープさせる形で採用すると[ヒト]が2人とも崖際にいた状態で片方が崖を掴める条件を満たした時に両方とも崖をとるようになってしまうため。
 今更になるが無重力状態の(重さに影響しない)[モノ(Joy-Con(L))][モノ(Joy-Con(R))]をそれぞれのヒトに装着し区別できるようにする。
☆[触っているセンサー(ヒト)]と「やったぜ」の操作(1P,2P)それぞれを[AND]で接続する。
☆1Pの「やったぜ」と[触っているセンサー(ヒト)][AND]が出力された場合はJoy-Con(L)がワープされる。
☆2Pの「やったぜ」と[触っているセンサー(ヒト)][AND]が出力された場合はJoy-Con(R)がワープされる。
→これでそれぞれが条件を満たした時だけワープできるようになる。[ヒト][Joy-Con]は装着関係にあるので[Joy-Con]がワープされると[ヒト]もついていく。
☆崖下に[モノを発射(直方体)]を設置し、ワープさせた直後に直方体を[ヒト]の足元に出すようにする。
[ヒト][モノ(直方体)]に触れた場合、ジャンプ回数がリセットされるようには既になっているのでジャンプ回数はリセットされる。
→これを足場にして崖上がりジャンプできるようにする。足場にした直後は[モノを壊す(直方体)]で足場となる直方体を破壊する。
☆ワープさせた瞬間に[タイマー(崖無敵用)]を起動させる。この[タイマー]が有効になっている間は攻撃を受けないように調整する。


【ゲームシステムに関する調整(ゲーム画面)】

キャラクターの位置取りによってカメラの位置が調整されるようになっているが実はこの段階で残りコストが少なくなってきている。
…ので[ゲーム画面]をステージ中央に配置し、今回は固定画面乱闘に該当する状態で終わらせる。

実際に画面を動かしたい場合はそれなりの工夫が必要。実装しなかったが簡易的に採用するなら以下の通りになると思われる。
しかし、このままでは場外まで見えてしまうので何かしらの形で上限をつける処理も必要である。
[モノ(球)]を2つ用意する。片方はステージ中央に固定、もう片方は固定された球と[フリースライド連結]によって結合する。
☆固定されていない球に[ゲーム画面]を装着させる。
[フリースライド連結]のX,Yポートに[ヒト]に接続されている[位置センサー]の値を参照し、その中間値を入れるようにする。
→これで球が常に[ヒト]2人の間に来るようになる。この球の動きに合わせ、装着されている[ゲーム画面]が動く。
[ゲーム画面]のZポートに[ヒト]に接続されている[位置センサー]の値を使って2人の[ヒト]との距離を計算してズームイン、ズームアウトさせる。
→これで状況に応じたカメラ移動自体は可能になる。精度は高くなさそうだが。


【ゲームシステムに関する調整(試合の前後)】

試合だけを成立させてもゲームとしては完成しない。試合前や試合終了後の処理も重要なゲームパーツである。
☆試合開始時に[エフェクト(3カウント)]を採用する。
[エフェクト]はあくまで見た目だけなので実際に3カウント計る[タイマー]を用意する。
[タイマー][エフェクト]には[スタートした瞬間]で信号を送って起動させる。
[フラグ(試合中判定用)]を用意し、[タイマー]が3カウント計り終えたらオンになるようにする。
[フラグ]がオンである間は試合中であると判定できる。[ヒト]の操作はこの[フラグ]がオンであるときに操作できるようにしておけば良い。
☆試合の終了は2人分ある[カウンター(ストック用)]のどちらかが"0"になった瞬間である。
→この瞬間に[フラグ]をオフにすれば試合終了の状態を作れる。
☆試合終了と同時に[時を止める]を採用し、ゲームをスロー演出にする。本家に沿った試合終了もこれで再現可能。
☆試合終了と同時に[タイマー(リセット用)]を起動させ、"5"秒後に[リトライ]へ信号を流せばスロー演出してしばらくしてからゲームをリセットできる。


【ゲームシステムに関する調整(音の扱い)】

これが最後の話題になるがここまで、音に関する話を全くしていない。
つまり、アクションゲームとして成立させてもヒット音はないし撃墜時の効果音もないしで味気ない。
上記で用意してきた数々のタイミングで必要に応じて[音を鳴らす]/[BGMを鳴らす]を入れる。


【おわりに】

まず…ここまで読んでくれてありがとう。
正直、長すぎる上に画像などの補足もないのでここまで読みきる人もそう多くはなさそうだが。

桜井さんがYoutubeでゲーム開発に関する動画を投稿しており、それと今回のを見比べると実感できるところは多かった。
今回のスマブラ再現にはヒットストップのようなわかりやすい演出もない。そういったところは本家との差になっている。
雑な感想になるが、本家のすごさを再認識できたきっかけとなった。

単純に作っていて楽しかったゲームでもある。製作時間は40-50時間ほど。
自分が展開した理論でモノが形作られていくのは爽快である。良い時間だった。ありがとう。


2022年12月3日 00時00分に投稿

お気に入りしたユーザー

コメント

2022年12月4日 19時57分

初めまして!突然コメントすみません。
すごく面白い記事でした!まさかスマメイトの日記でゲーム制作の話が読めるとはw
ゲーム制作に興味があって、昔すこーしだけ足を踏み入れたことがあったのですが、今回の記事を読んでまたやってみたいなと思えました。
ありがとうございました!

2022年12月7日 19時36分

最後まで読むのは大変だったと思います コメントありがとうございました
本職はプログラマーではないですがこれだけの質で落とし込める 良いゲームエンジンだと思っています