KUOKUO又上一款开源游戏+教程,绝对经典(附 Github 地址)

摘要转载自 「Creator星球游戏开发社区」 ( mp.weixin.qq.com ) By Creator星球

预计阅读时间 0 分钟(共 0 个字, 0 张图片, 0 个链接)

游戏演示

一个月前就想做了,结果先鸽了半个月,16 天前完成 demo,后来又加入了方块数据编辑场景。再后面几天做了一些修改,加了一些注释,今天才做了出来,大家千万不要学我,要克服懒惰 O(∩_∩)O~

关系图

首先我们看下脚本的关系图:

写些枚举

枚举的好处不再多说,我们先理一理俄罗斯方块这个游戏都需要些什么枚举。第一个是游戏中方块渲染,在 12 * 7 的格子中,每个格子应该有八种状态,或者说是不渲染与七种颜色;第二个是触摸事件,我们手指上下左右操作对应的事件名称;第三个就是各种音效对应的枚举;最后一个,是我为了方便使用 cc.find 找到节点的路径写的枚举。

enum.ts

  1. /** 不渲染与7个颜色 */

  2. export enum ItemColor {

  3. NULL = 0,

  4. Color1,

  5. Color2,

  6. Color3,

  7. Color4,

  8. Color5,

  9. Color6,

  10. Color7,

  11. }


  12. /** 触摸事件-上下左右滑动 */

  13. export enum TouchEvent {

  14. UP = 'touch-up',

  15. DOWN = 'touch-down',

  16. LEFT = 'touch-left',

  17. RIGHT = 'touch-right'

  18. }


  19. /** 音效事件 */

  20. export enum MusicEvent {

  21. BGM = 'bgm',

  22. ACTION = 'action',

  23. GAME_OVER = 'over',

  24. /** 方块消除 */

  25. ELIMINATE = 'eliminate'

  26. }


  27. /** 节点路径 */

  28. export enum NodeUrl {

  29. Canvas = 'Canvas',

  30. Music = 'Music'

  31. }

render渲染模块

游戏主场景是 12 * 7 方格,这个渲染模块就是通过一个 12 * 7 的数据数组对应,进行渲染。首先,将 12 * 7 个方格里面铺满带图片的节点(预制体 item 就是带有精灵组件的一个节点,config 中存着一些常量):

  1. init () {

  2. const height = config.row * config.blockHeight

  3. const width = config.col * config.blockWidth

  4. // 初始化所有节点

  5. for (let i = 0; i < config.row; i++) {

  6. this.itemArray[i] = []

  7. for (let j = 0; j < config.col; j++) {

  8. const x = -width / 2 + config.blockWidth / 2 + j * config.blockWidth

  9. const y = height / 2 - config.blockHeight / 2 - i * config.blockHeight

  10. const item = this.createItem(x, y)

  11. this.itemArray[i][j] = item

  12. }

  13. }

  14. }


  15. createItem (x: number, y: number): cc.Node {

  16. let item = cc.instantiate(this.item)

  17. this.node.addChild(item)

  18. item.setPosition(x, y)

  19. item.setContentSize(config.itemWidth, config.itemHeight)

  20. return item

  21. }

render.ts 中的渲染函数,根据传入数据进行图片替换,不渲染时数组越界为 undefined,取消掉纹理:

  1. /** 根据传入二维数组进行渲染 */

  2. render (dataArray: ItemColor[][]) {

  3. for (let i = 0; i < config.row; i++) {

  4. for (let j = 0; j < config.col; j++) {

  5. const color = dataArray[i][j]

  6. // 拖入图片的下标是 0-6,颜色枚举对应 1-7

  7. this.itemArray[i][j].getComponent(cc.Sprite).spriteFrame = this.itemSpriteFrames[color - 1]

  8. }

  9. }

  10. }

这样渲染模块的 render 函数只接受一个二维数组数据,主逻辑那边只操作数据,最后调用下 render 即可!看下 render.ts 整体:

  1. import { config } from "./config"

  2. import { ItemColor } from "./enum"


  3. const {ccclass, property} = cc._decorator


  4. @ccclass

  5. export default class Render extends cc.Component {


  6. @property(cc.Prefab)

  7. item: cc.Prefab = undefined


  8. @property([cc.SpriteFrame])

  9. itemSpriteFrames: cc.SpriteFrame[] = []


  10. /** 游戏层上应该铺满节点,然后根据数据渲染 */

  11. itemArray: cc.Node[][] = []


  12. onLoad () {

  13. this.init()

  14. }


  15. init () {

  16. const height = config.row * config.blockHeight

  17. const width = config.col * config.blockWidth

  18. // 初始化所有节点

  19. for (let i = 0; i < config.row; i++) {

  20. this.itemArray[i] = []

  21. for (let j = 0; j < config.col; j++) {

  22. const x = -width / 2 + config.blockWidth / 2 + j * config.blockWidth

  23. const y = height / 2 - config.blockHeight / 2 - i * config.blockHeight

  24. const item = this.createItem(x, y)

  25. this.itemArray[i][j] = item

  26. }

  27. }

  28. }


  29. /** 根据传入二维数组进行渲染 */

  30. render (dataArray: ItemColor[][]) {

  31. for (let i = 0; i < config.row; i++) {

  32. for (let j = 0; j < config.col; j++) {

  33. const color = dataArray[i][j]

  34. // 拖入图片 0-6,颜色枚举 1-7

  35. this.itemArray[i][j].getComponent(cc.Sprite).spriteFrame = this.itemSpriteFrames[color - 1]

  36. }

  37. }

  38. }


  39. createItem (x: number, y: number): cc.Node {

  40. let item = cc.instantiate(this.item)

  41. this.node.addChild(item)

  42. item.setPosition(x, y)

  43. item.setContentSize(config.itemWidth, config.itemHeight)

  44. return item

  45. }

  46. }

逻辑数据处理

方块的数据我是这样规定的:

绿色那里代表(0,0)位置,这样有相对位置,方便处理数据,我就这样定义了当前方块的数据结构:

  1. /** 当前形状 */

  2. currentShape: CurrentShapeData = {

  3. center: cc.v2(0, 0),

  4. index: 0,

  5. color: ItemColor.NULL

  6. }

身为程序员(懒人),必然得方便自己搞个编辑数据的场景(举例:7形状的数据就是上面图片表格对应的一个数组)

我们在 main 主脚本维护一个二维数组数据:

  1. /** 二维数组 */

  2. dataArray: ItemColor[][] = []

这样比如我们新添加一个形状到游戏里,只要先获取这个数组[cc.v2(-1, -1), cc.v2(-1, 0), cc.v2(0, 0), cc.v2(1, 0)],然后遍历一次添加到 dataArray 最后走一次 render,方块就出来了:

  1. /** 根据当前中心点和形状类型加入数据 */

  2. setCurrentData (currentShape: CurrentShapeData) {

  3. const { center, color, index } = currentShape

  4. const shape = `shape${color}`

  5. const shapeData: cc.Vec2[][] = config[shape]

  6. shapeData[index].forEach(ele => {

  7. const row = center.x + ele.x

  8. const col = center.y + ele.y

  9. this.dataArray[row][col] = color

  10. })

  11. // 刷新视图

  12. this.render()

  13. }

好了,剩下的逻辑大家去 GitHub 上下载一波看一看吧,注释还是蛮多的!

结语

源码已经开源,喜欢的记得给点个 Star!

开源地址(阅读源文):https://github.com/KuoKuo666/CocosCreator-Tetris


欢迎加我微信,我们一起成长!
more_vert