【プチコン4講座】ワンパク君を猪突猛進させるための移動処理

プチコン4

プチコン4 きこりの与作

こんにちは。なおキーヌです。

ブログ毎日更新は285日目になります。

斧とワンパク君に衝突判定を実装の続きの記事になります。

今回はイノシシ役のワンパクくんを猪突猛進させてみましょう。

やることは至って簡単で、一定時間経ったら現れて現れた場所から反対方向に走っていくだけという処理です。

それでは木こりゲーム作り第5回目、始めていきましょう。

  1. ワンパクくんの出現フラグを作る
  2. ワンパク君を出現させて走らせる
  3. 消滅フラグを改良してやられ処理を作る

ワンパクくんの出現フラグを作る

まずは最初から出現してしまっているワンパク君の表示を制御しましょう。

きこりの与作では、イノシシは一定時間経つと現れて与作のいる方向に突っ走ってくるという単純な仕組みです。

イノシシは大体消えてから8秒ぐらいで出現してるようなので、それにならいます。

前回は再出現で300フレームにしましたが60FPSで見た場合480フレームになりますね。

それではワンパク君はゲーム開始時に非表示にして、
出現する直前にハカセの座標を見て出現する方向をきめたいと思います。

' 出現までのフレーム数
CONST #WANPAKU_POP = 480

' ワンパクくんの初期を非表示に設定
SPSET 1, 1436, 0

' 開始時にカウント開始するために1を入れておく
SPVAR 1, "HIDE", 1
' ワンパク君の座標変数
SPVAR 1, "X", -16
SPVAR 1, "Y", 160
' ワンパク君の向き変数
SPVAR 1, "DIRECT", #FALSE
' ワンパク君のスピード(後で使う)
SPVAR 1, "SPEED", 0

' ワンパク君の座標設定
SPOFS 1, SPVAR(1,"X"),SPVAR(1,"Y")



LOOP
  D_CONTROLLER

  ' 斧とハカセ以外のスプライトの判定を取る
  HITSP = SPHITSP(100,1,3)

  ' 衝突判定がワンパク君かつ表示中であれば
  IF HITSP == 1 && SPSHOW(1) == 1 THEN
    SPHIDE 1
    SPVAR 1, "HIDE", 1
  ENDIF

  HIDE_COUNT
ENDLOOP



' 消滅時のカウント
'───────────────────────────────
DEF HIDE_COUNT
  IF SPVAR(1,"HIDE") >= 1 THEN
    SPVAR 1, "HIDE", SPVAR(1, "HIDE")+1
    IF SPVAR(1, "HIDE") > #WANPAKU_POP THEN
      IF SPVAR(0,"X") < (400/2-1) THEN
        SPVAR 1, "X", 400-16
        SPVAR 1, "DIRECT", #TRUE
        SPCHR 1, 128,352,32,32,#A_REVH

      ELSE
        SPVAR 1, "X", -16
        SPVAR 1, "DIRECT", #FALSE
        SPCHR 1, 128,352,32,32,0
      ENDIF
      SPSHOW 1
      SPOFS 1, SPVAR(1,"X"),SPVAR(1,"Y")
      SPVAR 1, "SPEED", SPVAR(1,"SPEED") + 5
      SPVAR 1, "HIDE", 0
    ENDIF
  ENDIF
END

ワンパク君に関する設定をかなり変更しました。

衝突判定を取るのもワンパク君が表示中のみにすることで、消えている最中に当たらないようにしています。

後は現れる瞬間、ハカセの位置を見て位置と向きを変更するかどうかを決め再出現します。

ワンパク君を出現させて走らせる

ワンパク君の出現を制御できたので、次は走らせてみましょう。

とりあえず向いている方向によって移動方向をきめます。

ワンパク君の向きは変数で管理出来ているので、
それを利用してとりあえず出現したら走らせてみましょう。



' ワンパク君移動関数
'───────────────────────────────
DEF WANPAKU_DASH
  IF SPSHOW(1) == 1 THEN
    IF SPVAR (1, "DIRECT") == #FALSE THEN
      SPVAR 1, "X", SPVAR(1, "X") + SPVAR(1, "SPEED")
    ELSE
      SPVAR 1, "X", SPVAR(1, "X") - SPVAR(1, "SPEED")
    ENDIF
  ENDIF
  SPOFS 1, SPVAR(1, "X"), SPVAR(1, "Y")
ENDIF

ループのところにWANPAKU_DASHを呼び出せばOKです。

出現制御の時に出現時にSPEEDに+5をしているので出てくるたびに速度が上がるはずです。

通常時のゲームは倒しても速度は変わりませんが、現状これだけでもワンパク君を倒すゲームが出来ました(笑)

早すぎて倒し切れないと画面外にずっと動き続けてしまいます。

画面外に行ったら強制的に消滅フラグをONにするべきですね。

ちょっと改良してみましょう。

' ワンパク君移動関数
'───────────────────────────────
DEF WANPAKU_DASH
  IF SPSHOW(1) == 1 THEN
    IF SPVAR (1, "DIRECT") == #FALSE THEN
      SPVAR 1, "X", SPVAR(1, "X") + SPVAR(1, "SPEED")
    ELSE
      SPVAR 1, "X", SPVAR(1, "X") - SPVAR(1, "SPEED")
    ENDIF
  ENDIF
  SPOFS 1, SPVAR(1, "X"), SPVAR(1, "Y")

  IF SPVAR(1, "X") > 400+32 || SPVAR(1, "X") < -32 THEN
    SPVAR 1, "HIDE", 1
    SPHIDE 1
  ENDIF

ENDIF

これで画面外に行ったら消滅した状態になります。

消滅フラグを改良してやられ処理を作る

現状、ワンパク君に斧を当てたら一瞬で消えてしまって面白くないので、
斧が当たったら消滅モーションをつけたいですね。

具体的には斧が当たったらその場で止まって萎んでいったり、
進んでる方向とは逆の斜め方向に飛んで行ったりですね。

後者の方が簡単なので、当たったらワンパク君の進行方向を変更するようにしてみましょう。

SPVAR 1, "DAMAGE", #FALSE


LOOP
  D_CONTROLLER

  ' 斧とハカセ以外のスプライトの判定を取る
  HITSP = SPHITSP(100,1,3)

  ' 衝突判定がワンパク君かつ表示中であれば
  IF HITSP == 1 && SPSHOW(1) == 1 THEN
    SPVAR 1, "DAMAGE", #TRUE
    BEEP 120
  ENDIF

  HIDE_COUNT

  WANPAKU_DASH
ENDLOOP


' 消滅時のカウント
'───────────────────────────────
DEF HIDE_COUNT
  IF SPVAR(1,"HIDE") >= 1 THEN
    SPVAR 1, "HIDE", SPVAR(1, "HIDE")+1
    IF SPVAR(1, "HIDE") > #WANPAKU_POP THEN
      IF SPVAR(0,"X") < (400/2-1) THEN
        SPVAR 1, "X", 400-16
        SPVAR 1, "DIRECT", #TRUE
        SPCHR 1, 128,352,32,32,#A_REVH

      ELSE
        SPVAR 1, "X", -16
        SPVAR 1, "DIRECT", #FALSE
        SPCHR 1, 128,352,32,32,0
      ENDIF
      SPSHOW 1
      SPVAR 1, "DAMAGE", #FALSE
      SPVAR 1, "Y", 160
      SPOFS 1, SPVAR(1,"X"),SPVAR(1,"Y")
      SPVAR 1, "SPEED", SPVAR(1,"SPEED") + 5
      SPVAR 1, "HIDE", 0
    ENDIF
  ENDIF
END

' ワンパク君移動関数
'───────────────────────────────
DEF WANPAKU_DASH
  IF SPSHOW(1) == 1 THEN
    IF SPVAR (1, "DIRECT") == #FALSE THEN
      IF SPVAR (1, "DAMAGE") == #FALSE THEN
        SPVAR 1, "X", SPVAR(1, "X") + SPVAR(1, "SPEED")
      ELSE
        SPVAR 1, "X", SPVAR(1, "X") -10
        SPVAR 1, "Y", SPVAR(1, "Y") -10
      ENDIF
    ELSE
      IF SPVAR (1, "DAMAGE") == #FALSE THEN
        SPVAR 1, "X", SPVAR(1, "X") - SPVAR(1, "SPEED")
      ELSE
        SPVAR 1, "X", SPVAR(1, "X") +10
        SPVAR 1, "Y", SPVAR(1, "Y") -10
      ENDIF
    ENDIF
  ENDIF
  SPOFS 1, SPVAR(1, "X"), SPVAR(1, "Y")

  IF SPVAR(1, "X") > 400+32 || SPVAR(1, "X") < -32 THEN
    SPVAR 1, "HIDE", 1
    SPHIDE 1
  ENDIF

ENDIF

斧が当たったら消えていたので、その処理を消してダメージを与えたという変数をTRUEにするようにしました。

その変数によってワンパク君の移動の挙動を変更させています。

斧が当たったら逆方向の斜め上に飛んでいくはずです。

だいぶゲームらしくなってきました!

次回はハカセがワンパク君にぶつかったらミスになる仕組みを作りましょう。

最後に完成版ソースコードを置いておきます。

それでは。

ACLS

' 地面と判定するための座標定数
CONST #GND = 160
' 出現までのフレーム数
CONST #WANPAKU_POP = 480


' ループ用変数
VAR G_I = 0
' 衝突判定用変数
VAR HITSP = -1
' ジャンプ配列アクセス用変数
VAR JPPC = 0
' ジャンプ配列
DIM JUMP_PROCESS[] = [-14,-10,-8,-6,-4,-2,2,4,6,8,10,14] 


' スプライト定義
SPSET 0, 1432
SPCOL 0
SPVAR 0, "X", 35
SPVAR 0, "Y", #GND
SPVAR 0, "DIRECT" , #FALSE
SPVAR 0, "SWING" , #FALSE
SPOFS 0, SPVAR(0,"X"), SPVAR(0,"Y")
SPVAR 0, "JUMP" , #FALSE

' 斧スプライト定義(非表示にしておく)
SPSET 100, 161, 0
SPCOL 100
SPVAR 100, "ROTATE", 0
' アトリビュートの基準点を変更
SPHOME 100, 8, 16



' その他スプライト定義
SPSET 2, 1438
SPSET 3, 1442

SPOFS 2, 100,200
SPOFS 3, 300,50

SPCOL 2
SPCOL 3


' ワンパクくんの初期を非表示に設定
SPSET 1, 1436, 0
SPCOL 1

' 開始時にカウント開始するために1を入れておく
SPVAR 1, "HIDE", 1
' ワンパク君の座標変数
SPVAR 1, "X", -16
SPVAR 1, "Y", 160
' ワンパク君の向き変数
SPVAR 1, "DIRECT", #FALSE
' ワンパク君のスピード(後で使う)
SPVAR 1, "SPEED", 0
' ワンパク君が斧に当たったかどうか
SPVAR 1, "DAMAGE", #FALSE

' ワンパク君の座標設定
SPOFS 1, SPVAR(1,"X"),SPVAR(1,"Y")


' 青空ぽい背景描写
FOR G_I=0 TO 240
  GLINE 0,I,400,I,RGB(I/2, 125+ROUND(I/2), 255)
NEXT

' 地面を描写
FOR G_I = 0 TO 24
  TPUT 0, G_I, 14, &HECC2
  TPUT 0, G_I, 14, &HED02
  TPUT 0, G_I, 14, &HED02
NEXT

LOOP
  D_CONTROLLER

  ' 斧とハカセ以外のスプライトの判定を取る
  HITSP = SPHITSP(100,1,3)

  ' 衝突判定がワンパク君かつ表示中であれば
  IF HITSP == 1 && SPSHOW(1) == 1 THEN
    SPVAR 1, "DAMAGE", #TRUE
    BEEP 120
  ENDIF

  HIDE_COUNT

  WANPAKU_DASH
ENDLOOP


' コントローラー関数
'───────────────────────────────
DEF D_CONTROLLER
  ' 0番目のコントローラー(つまり1コン)の押されているボタンを取得
  VAR B = BUTTON(0)

  ' 斧を振っていなかったら
  IF SPVAR(0,"SWING") == #FALSE THEN
    ' 左ボタン処理
    IF (B AND 1 << #B_LLEFT) != 0 THEN
      SPVAR 0, "X", SPVAR(0,"X")-1
      SPVAR 0, "DIRECT", #TRUE
    ENDIF

    ' 右ボタン処理
    IF (B AND 1 << #B_LRIGHT) != 0 THEN
      SPVAR 0, "X", SPVAR(0,"X")+1
      SPVAR 0, "DIRECT", #FALSE
    ENDIF

    ' 向き変更
    IF SPVAR(0, "DIRECT") == #TRUE THEN
      SPCHR 0,,,32,32,#A_REVH
      SPCHR 100,,,,,#A_REVH
      ' 向きに合わせて斧の位置を変える
      SPOFS 100, SPVAR(0,"X"), SPVAR(0,"Y")+24
    ELSE
      SPCHR 0,,,32,32,0
      SPCHR 100,,,,,0
      ' 向きに合わせて斧の位置を変える
      SPOFS 100, SPVAR(0,"X")-32, SPVAR(0,"Y")+24
    ENDIF

    ' 移動処理
    IF SPVAR(0,"X") < -16 THEN
      SPVAR 0,"X", -16
    ELSEIF SPVAR(0,"X") > 400-16 THEN
      SPVAR 0,"X", 400-16
    ENDIF
    SPOFS 0, SPVAR(0,"X"), SPVAR(0,"Y")

    ' Yボタン処理
    IF (B AND 1 << #B_LRIGHT) != 0 THEN
      ' 振った音を鳴らす
      BEEP 100

      ' ハカセのグラを変更
      IF SPVAR(0, "DIRECT") == #TRUE && SPVAR(0,"JUMP") != #TRUE THEN
        SPCHR 0,1433,,32,32,#A_REVH
      ELSE
        SPCHR 0,1433,,32,32,0
      ENDIF

      ' 斧振りフラグON
      SPVAR 0,"SWING", #TRUE
    ENDIF


    ' ジャンプ中か調べる
    IF SPVAR(0,"JUMP") != #TRUE THEN
      ' ジャンプ中じゃなければAボタン処理が効く
      IF (B AND 1 << #B_RRIGHT) != 0 THEN
        ' ジャンプフラグをONにする
        SPVAR 0,"JUMP", #TRUE
        ' 上昇中フラグに切り替える
        SPVAR 0,"UPDOWN", #TRUE
      ENDIF
    ELSE
      ' 現在座標にジャンプ配列の該当する値を取り出して足す
      SPVAR 0, "Y", SPVAR(0,"Y") + JUMP_PROCESS[JPPC]
      ' 次のジャンプ配列にアクセスするためにインクリメント
      INC JPPC
      ' もしアクセス変数と配列の長さが同じになったら
      IF JPPC == LEN(JUMP_PROCESS)-1 THEN 
        ' プレイヤーのY座標補正
        SPVAR 0, "Y", #GND
        ' ジャンプフラグを解除
        SPVAR 0,"JUMP", #FALSE
        ' 次のジャンプのためにアクセス変数を初期化しておく
        JPPC = 0
      ENDIF
    ENDIF


  ENDIF
END



' 斧振り関数
'───────────────────────────────
DEF D_SWING_AXE
  IF SPVAR(0,"SWING") == #TRUE THEN
    ' 斧を出現させる
    SPSHOW 100

    ' 向きによって振る方向を変更
    IF SPVAR(0, "DIRECT") == #TRUE THEN

      ' 斧を指定位置まで回転させる
      IF SPVAR(100, "ROTATE") > -90 THEN
        SPVAR 100, "ROTATE", SPVAR(100, "ROTATE")-5
        SPROT 100, SPVAR(100, "ROTATE")
      ELSE
        SPHIDE 100
        SPVAR 100, "ROTATE", 0
        SPROT 100, SPVAR(100, "ROTATE")
        SPVAR 0,"SWING", #FALSE
      ENDIF
    ELSE

      ' 斧を指定位置まで回転させる
      IF SPVAR(100, "ROTATE") < 90 THEN
        SPVAR 100, "ROTATE", SPVAR(100, "ROTATE")+5
        SPROT 100, SPVAR(100, "ROTATE")
      ELSE
        SPHIDE 100
        SPVAR 100, "ROTATE", 0
        SPROT 100, SPVAR(100, "ROTATE")
        SPVAR 0,"SWING", #FALSE
      ENDIF


    ENDIF

  ENDIF
END


' 消滅時のカウント
'───────────────────────────────
DEF HIDE_COUNT
  IF SPVAR(1,"HIDE") >= 1 THEN
    SPVAR 1, "HIDE", SPVAR(1, "HIDE")+1
    IF SPVAR(1, "HIDE") > #WANPAKU_POP THEN
      IF SPVAR(0,"X") < (400/2-1) THEN
        SPVAR 1, "X", 400-16
        SPVAR 1, "DIRECT", #TRUE
        SPCHR 1, 128,352,32,32,#A_REVH

      ELSE
        SPVAR 1, "X", -16
        SPVAR 1, "DIRECT", #FALSE
        SPCHR 1, 128,352,32,32,0
      ENDIF
      SPSHOW 1
      SPVAR 1, "DAMAGE", #FALSE
      SPVAR 1, "Y", 160
      SPOFS 1, SPVAR(1,"X"),SPVAR(1,"Y")
      SPVAR 1, "SPEED", SPVAR(1,"SPEED") + 5
      SPVAR 1, "HIDE", 0
    ENDIF
  ENDIF
END

' ワンパク君移動関数
'───────────────────────────────
DEF WANPAKU_DASH
  IF SPSHOW(1) == 1 THEN
    IF SPVAR (1, "DIRECT") == #FALSE THEN
      IF SPVAR (1, "DAMAGE") == #FALSE THEN
        SPVAR 1, "X", SPVAR(1, "X") + SPVAR(1, "SPEED")
      ELSE
        SPVAR 1, "X", SPVAR(1, "X") -10
        SPVAR 1, "Y", SPVAR(1, "Y") -10
      ENDIF
    ELSE
      IF SPVAR (1, "DAMAGE") == #FALSE THEN
        SPVAR 1, "X", SPVAR(1, "X") - SPVAR(1, "SPEED")
      ELSE
        SPVAR 1, "X", SPVAR(1, "X") +10
        SPVAR 1, "Y", SPVAR(1, "Y") -10
      ENDIF
    ENDIF
  ENDIF
  SPOFS 1, SPVAR(1, "X"), SPVAR(1, "Y")

  IF SPVAR(1, "X") > 400+32 || SPVAR(1, "X") < -32 THEN
    SPVAR 1, "HIDE", 1
    SPHIDE 1
  ENDIF

ENDIF