徜徉在知识海洋的一群鲸鱼
原生项目整理,平台和2048游戏
原生项目整理,平台和2048游戏

原生项目整理,平台和2048游戏

平台游戏,经过我的多个版本的优化,也叫兔年小游戏,梦的开始,最开始接触并对前端感兴趣的项目,这个项目是阅读雄辩的javascript,(Eloquent javascript)

https://eloquentjavascript.net/

变量,类型,数据结构,函数,高阶函数,对象的生命,错误处理,正则,模块,浏览器对象,事件,plantform平台游戏,canvas,nodejs,中的平台游戏,基于这个我开始的前端学习,后面其实还有一个比较有意思的,参加网络安全的比赛,有个大佬写的游戏,需要打过boss才能获取最终payload,这个当时也给了我不少震撼

言归正传,我整理一下这个项目的实现思路

大概流程是,二维数组存储地图,基于玩家操作更新DOM,这个不得不说对性能其实有很大的影响

添加移动端适配,需要方向键适配,屏幕适配,进入之后默认横屏,然后上下左右都显示出来

方案1:JS处理

if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
 }else{
}

方案2,使用meta和media处理,触摸方向视图只有在视图小于750才会显示

判断,如果是触摸屏设备,就添加触摸屏元素,上左右,给触摸板添加touchstart和end事件

然后处理屏幕移动问题,设置body为绝对定位,然后根据玩家移动的距离,调整body的左边距,

Vector

x
y
plus:返回相加之后的vector
times:返回相乘之后的vector

actorchars保存地图物体的键值对

"@": Player,"o": Coin,"=": Lava,"|": Lava,"v": Lava

Player

pos位置,用vector标识
size大小,
speed速度
设置prototype.type为Player

Lava岩浆,接收位置和字符串,设置岩浆的数值,根据字符串判断岩浆的方向,从而设置速度,如果是上下方向,会有一个重复位置属性

Coin金币,设置位置和大小,wobble属性Math.random() * Math.PI * 2生成随机弧度

Level关卡,接收二维数组,设置宽高,记录grid和actors,双重循环读取地图,利用actorchars[ch]判断是否存在物体字符,存在就给actors添加,否则根据其他字符设置fieldType,然后把每一行都添加到grid中,利用filter把player读取出来,

obstacleAt是level的方法,判断当前传入的点的类型,通过grid返回type

actorAt是level方法,接收actor对象,和地图的actors进行对比,如果和之前的位置不一样返回之前的位置

animate是level的方法,

lava有act方法,player有act方法,金币有金币的act方法,岩浆更新位置,岩浆根据时间*方向更新,金币根据正弦函数进行上下摆动,玩家的左右移动基于速度相乘,上下移动基于牛顿第二定律,同时都需要加上碰撞检测

element创建元素,createElement创建,className设置类名

DOMDisplay接收parent和level,预先声明玩家domactorLayer,设置wrap为parent.appendChild(element(“div”, “game”)),this.wrap.appendChild(this.drawBackground());然后调用drawFrame

drawBackground是DOMDisplay一个方法,返回一个dom对象,设置table的宽高,遍历关卡的grid,创建tr和td作为地图

drawActors是DOMDisplay一个方法,返回actor的dom对象

drawFrame是DOMDisplay一个方法,删除actorLayer,用drawActors添加actorLayer

clear直接清除wrap

键盘事件,设置左右和上,

trackKeys函数,接收codes参数,添加键盘按下事件,返回一个表示三个方向的对象

总结:如果作为一个用来学习的案例来说的话,我觉得是很好的一个项目,因为涉及到了操作dom,面向对象,添加删除元素,布局,移动端适配,但是如果作为一个成熟的项目应该还需要继续优化,比如换成canvas减少回流,减少dom的操作,移动跟随这里应该可以继续优化,现在的效果是操作dom,我有一个比较好的想法是,不操作dom,只进行视图的切换和移动,还有很多地图的细节需要完善和优化,人物需要添加移动帧

2048游戏

基于scss,和原生实现的,相比于上面的更加复杂一点,结构也更加清晰

优化:添加移动端适配,添加按键

整体页面布局按照H5新标准,分为nav,main和一个用来展示游戏结果的mask

nav展示分数和一些其他数据

main主要放置格子和数字块,其中格子是静态的,数字块根据情况进行变化

面向对象分为了格子,监听器,游戏进程控制器,渲染器,存储器,数字块

格子对象:

size,cells[],init,recover,add,remove,availableCells,randomAvailableCell,get,outOfRange,serialize,

init:初始化,接收size参数,初始化cells二维数组,单值为空
recover:还原,接收size和cells进行还原
add:添加,接收tile对象,tile的行和列作为索引,赋值索引所在的cells为当前的tile对象
remove:删除,接收tile对象,设置当前索引的cells为空
availableCells:获取可用方格位置,遍历cells,如果值为空,返回空的cells数组
randomAvailableCell:随机获取可用方格,利用availableCells获取空格子,随机数返回一个随机索引,返回cells索引元素
get:获取,接收position,如果满足outOfRange方法,返回空,否则用position的行和列作为索引,返回cells元素
outOfRange:判断是否超过边界,接收position,两个边界0和size,返回是否越界的布尔
serialize:序列化,格子有一个序列化,数字块也有一个序列化,返回当前对象

数据块:

row,column,value,prePosition{},mergedTiles[],updatePosition,serialize

updatePosition:更新位置,接收position,prePosition存储之前的行和列,row和column设置为新的position位置

监听器:

直接挂载到window上添加按键,执行函数

进程控制器:

size,aim,render对象,storage对象,listener对象,定义事件函数move和start,defaultStart,start,_render,addRandomTile,listenerFn,moveTile,getPaths,getNearestAvaibleAim,checkFailure,

defaultStart:开始,通过storage获取cells和分数,
start:初始化,随机生成两个tile
_render:渲染,调用render的render函数
addRandomTile:随机添加数字块,获取空余格子,
moveTile:接收tile和aim,把当前tile的cells元素置空,调用tile的updatePosition更新位置
getPaths:接收方向,返回一个对象,记录行和列的数组,数组元素是从0-size,默认是0-size,如果是向右或者下,就反过来,
getNearestAvaibleAim:接收direction和aim,返回一个更新的aim,通过grid获取更新后的aim格子,利用while找出就是找到最后一个空白且不超过边界的方格,最后返回aim和next,next是格子,aim是位置
checkFailure:检查游戏是否失败,首先确定有空格子,然后确定每一个格子的四个方向没有相同的,就是失败
listenerFn:接收方向,根据方向获取getPaths,循环路线,获取位置和tile,如果有tile开始移动,getNearestAvaibleAim获取next的值,如果next和当前数字快相同,合并为新的tile,加分,然后格子添加合并的,删除旧的,然后判断是否胜利,tile更新位置,如果没有next的值直接移动就可以

let self = this用来在内部引用外部的this

渲染器:css中添加了样式,通过添加类名实现动画效果

定义数字块容器,分数容器,状态,最高分

renderBestScore,renderScore,innerHTML写分

renderStatus判断状态控制display

empty清空tile的数字

renderTile渲染单个tile,动态添加类名,一共有三个属性类名,tile,tile-value,tile-position-row-column,其中value和row和column都是动态的,如果当前tile是移动的,首先添加移动的类名,利用setTimeout延迟添加类名,逻辑是,首先把之前的位置类名添加好,过了16毫秒再把现在的类名添加上去,这样会一个动画效果,如果是合并添加合并的类名

存储器:存储分数和cells状态

CSS逻辑和样式

利用top和left把左上角固定在中心,利用transform把中心固定在中心,top和left的百分之50保证左上角在中心,为了让元素中心在中心transform向左移动和向上移动50%

mask蒙版利用position的absolute实现,上下左右的位置都是0

利用关键帧和animation实现动画效果,主要用到了放大缩小,透明度