iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
1
Modern Web

三十天路邊賭場上線了!系列 第 13

DAY13 撲克牌、發牌動畫

  • 分享至 

  • xImage
  •  

前言

首先,我今天沒有使用常用的電腦,因為回老家的關係只能帶著筆電,當我到Github clone下來專案才發現,原來我都沒有push上去,可是印象中我都有推,不知道我常用電腦發生什麼事哈哈,所以其實Github七八天沒更新了,我今天就只能做先不要跟那些物件有關係的囉!

Sprite圖

我們要做撲克牌,撲克牌組成的有幾個部分,先看看我們壓成的散圖,沒錯就是長得這麼散。
https://ithelp.ithome.com.tw/upload/images/20190914/20109783xhTd5z9XEn.png

然後還需要蓋著的樣子!
https://ithelp.ithome.com.tw/upload/images/20190914/20109783hVJwY7C1Ep.png

別忘了我們的翻牌動畫
https://ithelp.ithome.com.tw/upload/images/20190914/20109783FlA3EgKWfB.png

有沒有發現我們翻牌的動畫的背牌跟我們的背牌好像不太一樣,看起來就是賣家唬爛我對吧,一定是給錯圖,可惡!
不過不影響我這三十天路邊賭場,OK的!

結構

以下結構米字號我們會新增的檔案。

└─src
    │  App.ts
    │  Game.ts
    ├─components
    │  ├─elements
    │  │      Animation.ts
    │  │      Sprite.ts
    │  │      Texture.ts
    │  │      Wrapper.ts
    │  │      WrapperContainer.ts
    │  │      WrapperContainerCenter.ts
    │  │      WrapperType.ts
    │  ├─groups
    │  │      Body.ts
    │  │      Casino.ts
    │  │      ChipBox.ts
    │  │      Loading.ts
    │  │      Navbottom.ts
    │  │      Navtop.ts
    │  │      Table.ts
    │  └─objects
    │          Bg.ts
    │          Chip.ts
    │          Countdown.ts
    │          CountdownNumber.ts
    │          Desk.ts
    │          DeskHover.ts
    │          Info.ts
    │          InfoMoneyNumber.ts
    │          Poker.ts ***
    ├─config
    │      chipType.ts
    │      imagePath.ts
    │      loadingPath.ts
    │      pokerPoint.ts ***
    │      pokerType.ts ***
    ├─loaders
    │      Loader.ts
    └─utils
            tools.ts

Poker.ts 是我們會新增牌就是這個,裡面會組成牌的花色數字位置等等,而且也會具備翻牌功能。
pokerPoint.ts 這是撲克牌的A-K對應的點數,沒什麼顯示上意義,單純針對這張牌點數是多少而已。
pokerType.ts 判斷Spades等等是什麼顏色。

撲克牌組件

程式碼非常冗長,拆分講太繁瑣,大概分析一下好了!

...省略引用

export default class Poker extends WrapperContainerCenter {
  private _front: Wrapper
  private _back: Wrapper
  private _fanPoker: Wrapper
  private _pokerType: string
  private _pokerColor: string
  private _pokerValue: string
  private _pokerPoint: number
  private _status: boolean = false

// 建構子需要什麼花色的牌、跟點數
  constructor(pokerConfig: keyof typeof pokerType, value: string, config?: any) {
    super()
    this._pokerType = pokerType[pokerConfig].type // 這邊挖出到底是什麼花色
    this._pokerColor = pokerType[pokerConfig].color // 這邊確定顏色
    this._pokerValue = value // 設定點數
    this._pokerPoint = pokerPoint[value] // 把點數換算成真的百家樂點數規則

    this._front = new WrapperContainerCenter() // 前面 牌面容器
    this._back = new WrapperContainer() // 背面 背面容器
    this._fanPoker = new WrapperContainer() // 動畫容器

    // 把牌面跟牌背取的sprite並放入。
    this._front.addContainer(new Sprite(imagePath.pokerPath, 'front').getContainer())
    this._back.addContainer(new Sprite(imagePath.pokerPath, 'back').getContainer())
    
    // 三個依序放入這一個容器
    this.addChild(this._front)
    this.addChild(this._back)
    this.addChild(this._fanPoker)

    // 畫出數字花色
    this.drawNumIcon()
    
    // 如果是JQK還要畫國王
    if (['J', 'Q', 'K'].includes(this._pokerValue)) { this.drawJQKIcon() }
  }
  
  // 取得這張牌實際點數多少
  public getPoint(): number {
    return this._pokerPoint
  }
  
  // 翻牌動畫
  public fanPoker(): void {
    this._status = !this._status
    this._back.setAlpha(false, 0)
    let fanPoker = new Animation(imagePath.fanpaiPath, 'fanpai')
    this._fanPoker.addContainer(fanPoker.getContainer())
    this._fanPoker.setPosition({ animation: false }, -this._fanPoker.width / 5, 0)
    let _icon = new WrapperContainer().addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerType}`).getContainer())
    let _num = new WrapperContainer().addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerValue}`).getContainer())
    _icon.setAlpha(false, 0)
    _num.setAlpha(false, 0)
    this._fanPoker.addChild(_icon)
    this._fanPoker.addChild(_num)

    fanPoker.getAnimatedSprite().onFrameChange = (f: any) => {
      if (f === 7) {
        _icon.setAlpha(false, 1)
        _num.setAlpha(false, 1)
        _icon.setPosition({ animation: false }, 125, 40)
        _icon.setRotation(false, 0.91)
        _icon.setScale(false, 0.4, 0.4)
        _num.setPosition({ animation: false }, 145, 27)
        _num.setRotation(false, 0.91)
        _num.setScale(false, 0.4, 0.4)
      }
    }

    fanPoker.play()

    this._front.setScale(false, 1.3, 1.3)
    this._front.setRotation(false, Math.PI * -0.25)
    this._front.setAlpha(false, 0)

    fanPoker.getAnimatedSprite().onComplete = () => {
      this._fanPoker.setAlpha(false, 0)
      this._front.setScale(true, 1, 1)
      this._front.setRotation(true, 0)
      this._front.setAlpha(false, 1)
    }
  }

  // 畫花色點數
  private drawNumIcon(): void {
    let flowerBase = {
      x: 10,
      y: 40,
      scale: 0.6
    }

    let numBase = {
      x: 10,
      y: 10,
      scale: 0.6
    }
    // 正向圖案
    let flower = new WrapperContainer()
    flower.addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerType}`).getContainer())
    flower.setScale(false, flowerBase.scale, flowerBase.scale)
    flower.setPosition({ animation: false }, flowerBase.x, flowerBase.y)
    this._front.addChild(flower)

    // 反向圖案
    let anti_flower = new WrapperContainer()
    anti_flower.addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerType}`).getContainer())
    anti_flower.setScale(false, flowerBase.scale, flowerBase.scale)
    anti_flower.setRotation(false, Math.PI)
    anti_flower.setPosition({ animation: false }, this._front.width - flowerBase.x, this._front.height - flowerBase.y)
    this._front.addChild(anti_flower)

    // 正向數字
    let num = new WrapperContainer()
    num.addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerValue}`).getContainer())
    num.setScale(false, numBase.scale, numBase.scale)
    num.setPosition({ animation: false }, numBase.x, numBase.y)
    this._front.addChild(num)

    // 反向數字
    let anti_num = new WrapperContainer()
    anti_num.addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}${this._pokerValue}`).getContainer())
    anti_num.setScale(false, numBase.scale, numBase.scale)
    anti_num.setRotation(false, Math.PI)
    anti_num.setPosition({ animation: false }, this._front.width - numBase.x, this._front.height - numBase.y)
    this._front.addChild(anti_num)
  }

  // 畫JQK國王
  private drawJQKIcon(): void {
    let iconBase = {
      x: 25,
      y: 18,
      scale: 0.8,
      padding: 8
    }
    // 圖案
    let icon = new WrapperContainer()
    icon.addContainer(new Sprite(imagePath.pokerPath, `${this._pokerColor}King`).getContainer())
    icon.setScale(false, iconBase.scale, iconBase.scale)
    icon.setPosition({ animation: false }, iconBase.x, iconBase.y)
    let maskGraphic = new PIXI.Graphics()
    maskGraphic.beginFill(0xff0000)
    maskGraphic.drawRect(iconBase.padding, iconBase.padding, this._front.width - iconBase.padding * 2, this._front.height - iconBase.padding * 2)
    maskGraphic.endFill()
    icon.getContainer().mask = maskGraphic
    this._front.addContainer(maskGraphic)
    this._front.addChild(icon)
  }

  get x(): number {
    return this._front.getContainer().x;
  }

  get y(): number {
    return this._front.getContainer().y;
  }

  get width(): number {
    return this._front.getContainer().width;
  }
  get height(): number {
    return this._front.getContainer().height;
  }
}

動畫影格

這一個部分是因為當動畫影格到七的時候,其實翻起來角落的地方要看到花色才對,感覺比較真實。

 fanPoker.getAnimatedSprite().onFrameChange = (f: any) => {
      if (f === 7) {
        _icon.setAlpha(false, 1)
        _num.setAlpha(false, 1)
        _icon.setPosition({ animation: false }, 125, 40)
        _icon.setRotation(false, 0.91)
        _icon.setScale(false, 0.4, 0.4)
        _num.setPosition({ animation: false }, 145, 27)
        _num.setRotation(false, 0.91)
        _num.setScale(false, 0.4, 0.4)
      }
    }

原圖
https://ithelp.ithome.com.tw/upload/images/20190914/20109783HCqsQXg4yl.png
加上判斷放上花色、角度。
https://ithelp.ithome.com.tw/upload/images/20190914/20109783fpzTavQffu.png

撲克牌定位

我們先把鋪排直接放在body上,這樣方便直接預覽。

...以上省略
    
let poker = new Poker('Heart','J') // 新增牌
poker.setPosition({animation: true}, 500, 400) // 會從0,0飛到 500,400
setTimeout(() => {
  poker.fanPoker() // 三秒後會翻牌
}, 3000)
this._centerContainer.addChild(this._table)
this._centerContainer.addChild(poker) // 加到這一個容器上 要蓋過talbe不然會被擋住

...以下省略

登愣!結果就是如此!
https://ithelp.ithome.com.tw/upload/images/20190914/201097830n4VUActSs.png

後記

沒錯今天完成了撲克牌,其實這樣已經快要完成簡易的版本了,動畫飛出跟一些提示字比較麻煩,但這樣已經可以玩了吧我猜!

連結

Github 2019-IT30-Game


上一篇
DAY12 玩家餘額、數字動畫
下一篇
DAY14 提示訊息、訊息動畫
系列文
三十天路邊賭場上線了!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2019-11-15 09:06:05

看起來就是賣家唬爛我對吧,一定是給錯圖,可惡!
/images/emoticon/emoticon10.gif/images/emoticon/emoticon09.gif/images/emoticon/emoticon01.gif

哈哈,好一陣子了,這專案有些問題,當笑話看就好。

不不 這個專案跨足部分非常非常廣 而且挺龐大的,看到那貝茲曲線我頭就痛起來 請受小弟一拜/images/emoticon/emoticon32.gif

我要留言

立即登入留言