一塊兒來寫一個小球成長
的遊戲吧html
let's go!前端
需求:git
- 小球在畫布內不規則運動,不會發生碰撞,只會重疊在一塊兒
- 有和小球相同數量的按鈕
- 每一個小球都有本身都編號而且和相應編號的按鈕綁定
- 長按按鈕,相應的小球會變大
- 鬆開按鈕,小球中止變大
- 若是正在變大的小球和其餘任何一個小球相碰,兩個小球的大小縮小一半而且中止變大
- 每一個球只能變大一次
0. 先把簡單的框架搭起來github
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>growing circle</title> <style> * { margin: 0; padding: 0; } </style> </head> <body> <div id="game"></div> <script src="./phaser.min.js"></script> <script> let game let gameOptions = { ballSpeed: 300, // 小球運動速度 balls: 8, // 小球總數 ballRadius: 50, // 小球半徑 growRate: 1 // 增加速率 } class PlayGame extends Phaser.Scene { constructor() { super('PlayGame') } preload() { this.load.image('ball', 'ball.png') this.load.image('button', 'button.png') } create() { } update() { } } let gameConfig = { type: Phaser.AUTO, scale: { mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT, autoCenter: Phaser.Scale.CENTER_BOTH, parent: 'game', width: 750, height: 1464 }, physics: { default: 'arcade' }, scene: PlayGame } game = new Phaser.Game(gameConfig) </script> </body> </html>
引入 arcade
物理系統,方便小球作不規則運動app
1. 放置小球框架
class PlayGame extends Phaser.Scene { create() { // 設置小球的運動區域 this.physics.world.setBounds(0, 0, game.config.width, game.config.width) let gameArea = new Phaser.Geom.Rectangle(0, 0, game.config.width, game.config.width) // 物理組對象,存放全部的小球 this.ballGroup = this.physics.add.group() // 生成小球 for (let i = 0; i < gameOptions.balls; i++) { // 運動區域內隨機一個點 let randomPosition = Phaser.Geom.Rectangle.Random(gameArea) // 放置小球 let ball = this.ballGroup.create(randomPosition.x, randomPosition.y, 'ball') // arcade 物理系統中設置小球的邊界爲圓形 ball.setCircle(256) ball.setCollideWorldBounds(true) // 寬高 ball.displayHeight = gameOptions.ballRadius ball.displayWidth = gameOptions.ballRadius // 編號 ball.index = i let ballText = this.add.text(ball.x, ball.y, i, { fontFamily: 'Arial', fontSize: 24, color: '#000000' }) ballText.setOrigin(0.5, 0.5) } } }
2. 放置按鈕dom
class PlayGame extends Phaser.Scene { create() { let buttonPerRow = gameOptions.balls / 2 let buttonWidth = game.config.width / buttonPerRow this.buttonGroup = this.add.group() // 生成按鈕 for (let i < 0; i < gameOptions.balls; i++) { let buttonX = buttonWidth * (i % (gameOptions.balls / 2)) let buttonY = game.config.width + buttonWidth * Math.floor(i / (gameOptions.balls / 2)) let button = this.add.sprite(buttonX, buttonY, 'button') button.setOrigin(0, 0) button.displayWidth = buttonWidth button.displayHeight = buttonWidth button.index = i this.buttonGroup.add(button) let buttonText = this.add.text(button.getBounds().centerX, button.getBounds().centerY, i, { fontFamily: 'Arial', fontSize: 64, color: '#000000' }) buttonText.setOrigin(0.5, 0.5) } } }
3. 設置分數ide
class PlayGame extends Phaser.Scene { create() { this.scoreText = this.add.text(0, game.config.height, 'Score: 0', { fontFamily: 'Arial', fontSize: 64 }) this.scoreText.setOrigin(0, 1) } }
4. 讓小球動起來,不會碰撞,只會重疊this
class PlayGame extends Phaser.Scene { create() { this.ballArray = [] this.textArray = [] for (let i < 0; i < gameOptions.balls; i++) { this.ballArray.push(ball) this.textArray.push(ballText) // 隨機一個方向向量 let directionVector = Phaser.Math.RandomXY(new Phaser.Math.Vector2, gameOptions.ballSpeed) // 設置小球的運動方向和速度 ball.setVelocity(directionVector.x, directionVector.y) // 設置小球碰到邊界反彈 ball.setBounce(1) } } update() { for (let i = 0; i < gameOptions.balls; i++) { this.textArray[i].x = this.ballArray[i].x this.textArray[i].y = this.ballArray[i].y } } }
5. 給按鈕綁定事件spa
class PlayGame extends Phaser.Scene { create() { this.input.on('pointerdown', this.startGrowing, this) // 小球開始變大 this.input.on('pointerup', this.stopGrowing, this) // 小球中止變大 this.ballToGrow = null } startGrowing(pointer) { this.buttonGroup.getChildren().map(button => { if (Phaser.Geom.Rectangle.Contains(button.getBounds(), pointer.x, pointer.y) && button.alpha === 1) { button.alpha = 0.5 this.ballToGrow = button.index console.log(button.index) } }) } stopGrowing() { this.ballToGrow = null } update() { this.score = 0 for (let i = 0; i < gameOptions.balls; i++) { this.score += this.ballArray[i].displayWidth - gameOptions.ballRadius; } this.scoreText.text = 'Score: ' + this.score if (this.ballToGrow != null) { this.ballArray[this.ballToGrow].displayWidth += gameOptions.growRate this.ballArray[this.ballToGrow].displayHeight += gameOptions.growRate } } }
6. 兩個球重疊時觸發事件
class PlayGame extends Phaser.Scene { create() { // 設置重疊事件 this.physics.add.overlap(this.ballGroup, this.ballGroup, this.handleOverlap, null, this) } handleOverlap(ball1, ball2) { if (this.ballToGrow !== null && (ball1.index === this.ballToGrow || ball2.index === this.ballToGrow)) { // 相機拍照效果,不加也可 this.cameras.main.flash() ball1.displayWidth = Math.max(ball1.displayWidth / 2, gameOptions.ballRadius) ball2.displayWidth = Math.max(ball2.displayWidth / 2, gameOptions.ballRadius) ball1.displayHeight = ball1.displayWidth ball2.displayHeight = ball2.displayWidth this.ballToGrow = null } } }
至此,整個遊戲咱們就作完啦!🦍🦍🦍
前端phaser公衆號