P 5で遊ぶゲームロジックの実装


これはp 5の3部シリーズの2番目です.JP(ここから' p 5 ')-はるかに簡単にキャンバスAPIでの作業を行うクリエイティブコーディングライブラリ.In part one , 我々は、画面上の要素を描画する方法をカバーし、キーボードとマウスの入力に反応します.
今日、我々は理論的な知識を取っているし、ゲームを作成するときに必要ないくつかの機能を構築する.次に、来週の最後の部分では、我々は深層を使用してゲームに音声機能を追加します.

衝突検出


あなたがP 5スケッチで描くあらゆる要素は、特定の配置とサイズを持ちます.ゲーム内の衝突検出を使用すると、1つの要素が別の、または壁などの場所に触れると重複するときに知ることができます.これはしばしば、ユーザーが壁や床を通り抜けるのを避けるために使用されたり、食べ物や心などのアイテムを拾う.
あなたと(他の実体(a ' pick up))の間の衝突チェックを仮定して、衝突検出は4つの条件チェックに依存します:
  • あなたのX位置は、ピックアップの左端のX位置より大きいですか?
  • あなたのX位置はピックアップの右側のX位置よりも小さいですか?
  • あなたのYポジションは、ピックアップの最上位のy位置より大きいですか?
  • あなたのYポジションはピックアップの一番下のy位置より少ないですか?
  • これを実行に移しましょう.クリエイトアindex.html ファイルを開き、コードエディターで開き、次のように追加します.
    <!DOCTYPE html>
    <html>
    <head></head>
    <body>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
        <script>
            const pickupX = 200
            const pickupY = 50
            const pickupSize = 100
    
            function setup() {
                createCanvas(500, 200)
            }
    
            function draw() {
                background(100)
    
                const collisionX = mouseX>pickupX && mouseX<pickupX+pickupSize
                const collisionY = mouseY>pickupY && mouseY<pickupY+pickupSize
                if(collisionX && collisionY) fill('green')
                else fill('red')
    
                square(pickupX, pickupY, pickupSize)
            }
        </script>
    </body>
    </html>
    
    あなたのスケッチを実行するにはindex.html ファイルエクスプローラでファイルを開き、デフォルトのブラウザで開きます.コードを保存したら、新しい変更を表示するには、ブラウザを再表示します.

    プレイヤーが単一のピクセルポイントよりも大きい場合は、プレーヤーのサイズで条件を相殺する必要があります.次のようにしてください.
    const pickupX = 225
    const pickupY = 75
    const pickupSize = 50
    const playerSize = 50
    
    function setup() {
        createCanvas(500, 200)
    }
    
    function draw() {
        background(100)
    
        fill('black')
        square(pickupX, pickupY, pickupSize)
    
        const collisionX = mouseX>pickupX-pickupSize && mouseX<pickupX+pickupSize
        const collisionY = mouseY>pickupY-pickupSize && mouseY<pickupY+pickupSize
        if(collisionX && collisionY) fill('green')
        else fill('white')
    
        square(mouseX, mouseY, playerSize)
    }
    

    あなたが衝突検出についてもっと勉強したいならば、ダンシフマンによってチェックしてください.

    壁をブロックする例


    p 5提供width and height 変数は常にcreateCanvas() . あなたは、ユーザーがキャンバスの外に移動することができないように上記の衝突検出条件と一緒にこれらを使用することができます.
    我々のキーボードユーザー入力導入で拡大することlast week's post , 次のようにしてください.
    let playerX = 20
    let playerY = 20
    const playerSize = 10
    
    function setup() {
        createCanvas(500, 200)
    }
    
    function draw() {
        background(100)
    
        if(keyIsPressed) {
            if(key == 'ArrowLeft') playerX -= 1
            if(key == 'ArrowRight') playerX += 1
            if(key == 'ArrowUp') playerY -= 1
            if(key == 'ArrowDown') playerY += 1
        }
    
        // Not allowing out-of-bounds values
        if(playerX < 0) playerX = 0
        if(playerX > width - playerSize) playerX = width - playerSize
        if(playerY < 0) playerY = 0
        if(playerY > height - playerSize) playerY = height - playerSize
    
        square(playerX, playerY, playerSize)
    }
    
    プレーヤーがセットしようとするならばplayerX or playerY 許された境界の外側に、彼らは境界に設定されます.これは、プレーヤーが彼らの広場停止移動を見ることを意味します.

    エンティティ管理


    ゲームはしばしば多くのエンティティ:プレイヤー、敵、およびアイテムがあります.同じカテゴリのエンティティは、同様のロジックを持っている可能性がありますが、自分の状態を維持する必要があります.P 5スケッチでは、ゲームエンティティ管理用のJavaScriptクラスを使用するのが一般的です.クラスはオブジェクトの青写真を提供します.彼らはデータや関数(クラス内で'メソッド'と呼ばれる)を含む独自のプロパティを持っています.このコードを試してみてください.
    const bubbles = []
    
    function setup() {
        createCanvas(500, 200)
        for(let i = 0; i < 100; i++) {
            bubbles.push(new Bubble(250, 100))
        }
    }
    
    function draw() {
        background(100)
        for(let bubble of bubbles) {
            bubble.move()
            bubble.display()
        }
    }
    
    class Bubble {
        constructor(x, y) {
            this.x = x
            this.y = y
            this.xOff = random(0, 1000)
            this.yOff = random(0, 1000)
        }
    
        move() {
            this.xOff += 0.01
            this.yOff += 0.01
    
            this.x = noise(this.xOff) * width
            this.y = noise(this.yOff) * height
        }
    
        display() {
            circle(this.x, this.y, 5)
        }
    }
    

    で始まるBubble クラス.新しいクラスインスタンスが作成されると、開始されたxとyの値が期待されますthis.x and this.y . 他の2つのメンバープロパティも作成されます.xOff ( xオフセット)、yOff ( Yオフセット).後でこれらの上でより多くの.
    このクラスには2つのメソッドがありますmove and display P 5スケッチで一般的です.
    The move() メソッドは、P 5noise() perlinノイズシーケンスで値を返す関数です.Perlinノイズは、より自然に見えるシーケンスに存在するランダムな値を生成しますnoise() , 泡は'パス'に従うように見える小さな変化xOff and yOff スムーズに泡を移動するために使用されます.パーリンノイズは魅力的であり、私はあなたにread more about noise() .
    The display() メソッドは、this.x and this.y .
    setup() , 100Bubble インスタンスは、(250, 100) そして、bubbles 配列.あらゆるdraw() , それぞれbubble それはmove() and display() メソッドが実行されます.
    次の例では、衝突検出とエンティティ管理を組み合わせたものです.
    const bubbles = []
    
    function setup() {
        createCanvas(500, 200)
        frameRate(10)
        for(let i = 0; i < 10; i++) {
            bubbles.push(new Bubble(250, 100))
        }
    }
    
    function draw() {
        background(100)
        for(let bubble of bubbles) {
            bubble.move()
            bubble.checkIfTouched()
            bubble.display()
        }
    }
    
    class Bubble {
        constructor(x, y) {
            this.x = x
            this.y = y
            this.xOff = random(0, 1000)
            this.yOff = random(0, 1000)
    
            this.radius = 10
            this.touched = false
        }
    
        move() {
            this.xOff += 0.01
            this.yOff += 0.01
    
            this.x = noise(this.xOff) * width
            this.y = noise(this.yOff) * height
        }
    
        checkIfTouched() {
            const d = dist(mouseX, mouseY, this.x, this.y)
            if(d < this.radius) {
                this.touched = true
            }
        }
    
        display() {
            if(this.touched) fill('green')
            else fill('white')
            circle(this.x, this.y, this.radius * 2)
        }
    }
    
    何が変わったのか
  • The frameRate(10) ファンクションsetup() 大幅に速度を減速させるdraw() は、毎秒約60回から10回まで実行されます.これは、このゲームをプレイできるように行われます.
  • のインスタンスは10ですBubble 100の代わりに作成.
  • つの新しいプロパティが含まれていますBubble - radius and touched . The radius 衝突検出とバブルを描画するときに使用されます.
  • 新しいcheckifTouched() メソッドはBubble . このメソッドは距離を決定します(dist() ) マウス位置とバブル中心(X、Y)の間.半径未満の場合は、衝突が起こっていることを知っているthis.touched to true .
  • かつてバブルの色が変わった.
  • The checkIfTouched() すべてのバブルに対してdraw() .

  • 維持


    現在、すべてのバブルは現在、自分の状態を追跡しますが、プレーヤーが獲得した方法のグローバルな表示はありません.グローバル変数で実装できます.次の手順に従います
  • グローバル変数score 値の0 .
  • 内部のBubble.checkIfTouched() メソッド以前this.touchedtrue , チェックするthis.touched はまだ偽で、その後も増加するscore .
  • draw() 関数は、白に色を設定するfill('white') , そして、score 使用によってtext() .
  • 場合には、パラメータを覚えていないtext() 我々が前のポストで行ったので.text() つの引数-表示するテキスト、および(x、y)座標をとります.
    ステップ2については、追加のチェックを停止する必要がありますscore インクリメント以上.成功すると、スケッチは次のように機能します.

    スタート、勝利、そして失う


    ほとんどのゲームの状態の数が-負荷の上に着陸ページ、ゲーム自体、およびエンドゲーム.この状態は多くの場合、グローバルスコープで、draw() 結果として変更できます.リーブ・ユアBubble クラスを変更しないでください.
    const bubbles = []
    let score = 0
    let win = false
    
    function setup() {
        createCanvas(500, 200)
        frameRate(10)
        for(let i = 0; i < 3; i++) {
            bubbles.push(new Bubble(250, 100))
        }
    }
    
    function draw() {
        background(100)
    
        if(score >= 3) win = true
    
        if(!win) {
            for(let bubble of bubbles) {
                bubble.move()
                bubble.checkIfTouched()
                bubble.display()
            }
            fill('white')
            text(score, 10, 20)
        } else {
            textSize(36)
            textAlign(CENTER)
            text('You Win!', width/2, height/2-16)
        }
    }
    
    The win 変数はfalse、score 3つ以上に達すると、ゲームのロジックを実行し、停止するテキスト';が代わりに表示されます.
    これは単純な例ですが、より多くのゲーム状態を実装するために、同じアプローチを取ることができます.

    要約する


    一緒にこのシリーズの最初のポストと、私はあなたがP 5と楽しいゲームを構築するために必要なツールがあることを願っています.これらのゲームロジック実装によるJS.更なるインスピレーションのために、私の大好きなP 5例のいくつかは、ここにあります:

  • Particles in a flow field - この例では、perlinノイズをどのように動作するかを示すのに役立つ方法で使用します.
  • A game of snake
  • Full 2D platformer game
  • A kaleidoscope drawing program
  • Interactive artwork with animated interactive stars
  • A generative painting program
  • John Conway's Game of Life cellular automata
  • L-Systems generative art
  • Applying realistic forces like gravity

  • Rainbow meatballs shader - これは先進的な話題である遮光物を書くことに関係していました、しかし、それは非常にクールに見えます.
  • このシリーズの3番目と最後の部分で来週、我々はあなたのP 5スケッチに音声を統合する方法をカバーします.それまでは、質問や考えがある場合はTwitterで私たちに手を伸ばす自由に感じてください.