基于H5 canvas API 编写的扫雷游戏第二部分:方块类和工具对象

样式表文件

不好意思上篇没有贴样式表,先补充上来 /assets/css/style.css

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background-color: #fbe9e7;
}

.game-wrapper {
  width: 100%;
  max-width: 480px;
  margin: auto;
  padding: 0 6px 6px;
}

.game-wrapper canvas.game-ui {
  display: block;
  width: 100%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
复制代码

方块类

扫雷游戏界面由很多方块租成,方块应该有自己的坐标(行和列),还有它周围的雷数量,是否被标记(插上红旗),是否已被点开;方块应该有描述如何绘制自己的方法;这包括文本,图标,背景的绘制;最后我们会创建一个通用的绘制方法,实现方块的绘制功能;

class Block {
  constructor({ row, col, num = 0 }) {
    this.row = row
    this.col = col
    this.num = num
    this.isFlag = false
    this.isOpened = false
  }

  // 绘制文本 雷数量
  drawText({ context, size, space }) {
    let fontSize = size / 2 + 'px'
    let color = ({ 1: '#ff0', 2: '#0f0' })[this.num] || '#f00'
    let fw = context.measureText(this.num).width
    let tx = this.col * size + (size - space - fw) / 2
    let ty = this.row * size + (size - space - fw) / 2
    context.save()
    context.font = `bold ${fontSize} serif`
    context.textBaseline = 'hanging'
    context.fillStyle = color
    context.fillText(this.num, tx, ty)
    context.restore()
  }
  
  // 绘制图标 雷和旗帜
  drawIcon({ context, size, space, icon }) {
    let dw, dh
    if (icon.width > icon.height) {
      dw = size * .5
      dh = dw * (icon.height / icon.width)
    } else {
      dh = size * .5
      dw = dh * (icon.width / icon.height)
    }
    let dx = this.col * size + space + (size - space - dw) / 2
    let dy = this.row * size + space + (size - space - dh) / 2
    context.drawImage(icon, dx, dy, dw, dh)
  }
  
  // 绘制背景
  drawBG({ context, size, space, icon }) {
    context.drawImage(
      icon, 0, 0, icon.width, icon.height,
      this.col * size + space, this.row * size + space, size - space, size - space
    )
  }
  // 通用的绘制方法
  draw({ context, size, space = 6 }) {
    let params = { context, size, space }
    let { blockEnd, bomb, blockFront, flag } = source.icons
    if (this.isOpened) {
      this.drawBG({ ...params, icon: blockEnd })
      if (this.num > 0 && this.num < 9) {
        this.drawText(params)
      } else if (this.num === 9) {
        this.drawIcon({ ...params, icon: bomb })
      }
    } else {
      this.drawBG({ ...params, icon: blockFront })
      if (this.isFlag) {
        this.drawIcon({ ...params, icon: flag })
      }
    }
  }
}
复制代码

工具对象

把一些方法放到工具对象中,是为了减轻游戏类的重量

const utils = {
  // 创建一个画布包裹容器
  createWrapper(mountEl) {
    mountEl = mountEl || document.body
    const wrapper = document.createElement('div')
    wrapper.className = 'game-wrapper'
    mountEl.appendChild(wrapper)
    return wrapper
  },
  // 创建画布
  createCanvas(wrapper) {
    const canvas = document.createElement('canvas')
    canvas.className = 'game-ui'
    wrapper.appendChild(canvas)
    return canvas
  },
  // 获取设备像素比 基于像素比的尺寸是为了让画布适应高分屏
  getPixRatio(context) {
    var backingStore = context.backingStorePixelRatio ||
      context.webkitBackingStorePixelRatio ||
      context.mozBackingStorePixelRatio || 1
    return (window.devicePixelRatio || 1) / backingStore
  },
  
  // 生成初始方块数组
  genBlocks(rows, cols) {
    const blocks = []
    for (let row = 0; row < rows; row++) {
      for (let col = 0; col < cols; col++) {
        blocks.push(new Block({ row, col }))
      }
    }
    return blocks
  },

  // 判断是否是函数
  isFunc(func) {
    return typeof func === 'function'
  }
}
复制代码

今天的源码分享到此结束,明天我将分享游戏的核心部分,游戏类和游戏控制类;大家有什么不明白的地方可以评论区提问,谢谢观看;前端小白,初次写文章,写的不好还请见谅;

转载于:https://juejin.im/post/5be79bc55188256d983294b1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值