【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏

我们知道,在平面世界,任何图形,几乎都可以看成是一个有起始点 (x,y) 和宽高 (width,height) 的矩形,不同的只是这个图形在矩形内部是如何绘制的

一般情况下,我们都把屏幕看成是一个起始点为 (0,0),宽高为屏幕像素宽高 (screenWidth,screenHeight) 的矩形

【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏

如果我们以 1px 横竖划分屏幕,那么每个小方块就是一个 1x1 的小正方形

【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏

这也是我们屏幕的网格系统,这种网格系统可以使用一个总长度为 width x height 的数组来表示

像素游戏

随着屏幕的分辨率越来越高,人眼已经看不清 1 x 1 像素的小正方形了,这时候我们就要把屏幕按照更高的像素单位来划分网格,当然,这是虚拟的,实际上我们没法改变屏幕本身的像素单位

例如以 w1px 来划分屏幕,那么屏幕的虚拟高宽就是 (width/w,height/w)

【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏

此时我们可以使用一个长度为 (width/w) x (height/w) 的数组来表示这个屏幕

当然了,可能屏幕就会像图中那样,右边和下边不完整,那么数组的长度就是

(width/w+1)x(height/w+1)

整体的计算方法就是

// 以 `10px` 像素大小划分屏幕

varunit=10;

varw=Math.ceil(c.width/unit);

varh=Math.ceil(c.height/unit);

// 数组长度

varsize[w*h];

这就是像素游戏划分屏幕的方法

虚拟网格

我们写一个范例,把上图中的虚拟网格给表现出来

game.js

varc=wx.createCanvas();

varctx=c.getContext('2d');

varunit=10;

varw=Math.ceil(c.width/unit);

varh=Math.ceil(c.height/unit);

// 数组长度

varpixls=newArray(w*h);

varcur=0;

varpos=0;

// 每一个数组的值,创建一个黑白相间的数组

for(vari=0;i<h;i++){

cur=i%2==0?0:1;

for(varj=0;j<w;j++){

// 数组位置位置

pos=(i*w)+j;

pixls[pos]=cur;

cur=cur==1?0:1;

}

}

functionrenderVirtualGrid(){

ctx.save();

ctx.fillStyle='green';

ctx.fillRect(0,0,c.width,c.height);

ctx.fillStyle="#fff";

pos=0;

for(vari=0;i<h;i++){

for(varj=0;j<w;j++){

pos=(i*w)+j;

ctx.fillStyle=pixls[pos]==0?"#000":"#fff";

ctx.fillRect(j*unit,i*unit,unit,unit)

}

}

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="13px Arial"// 字体大小 44 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-25))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-10));

ctx.restore();

}

renderVirtualGrid();

在微信中运行效果如下

【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏

范例: 贪吃蛇

虚拟网格有什么用呢?

比如做贪吃蛇游戏,小蛇每次只能前进一格子

我们写一个范例来模拟小蛇的移动吧

game.js

varc=wx.createCanvas();

varctx=c.getContext('2d');

varunit=10;

varw=Math.ceil(c.width/unit);

varh=Math.ceil(c.height/unit);

// 数组长度

varpixls=newArray(w*h);

varcur=0;

varpos=0;

// 每一个数组的值,创建一个黑白相间的数组

for(vari=0;i<h;i++){

cur=i%2==0?0:1;

for(varj=0;j<w;j++){

// 数组位置位置

pos=(i*w)+j;

pixls[pos]=cur;

cur=cur==1?0:1;

}

}

vartt=null;// 用于保存定时器

// 用来判断是否在游戏中

// 0 表示未开始

// 1 表示游戏进行中

// 2 表示游戏已经结束

varingame=0;

// 用来保存开始触摸点

varlasted={x:null,y:null};

// 降帧,每秒 2 帧

varfps=(60/2);

varfps_s=0;

vargame={

v:1,

direction:1,// 0 1 2 3 分别表示上右下左

boxes:[],

draw_boxes:function(ctx){

for(vari=0;i<this.boxes.length;i++){

this.boxes[i].draw(ctx);

}

},

hit:function(){

varb=this.boxes[0];

varx=(b.x+1)*unit;

vary=(b.y+1)*unit;

// +1 是因为原点在左上角

returnx<0||y<0||(x+unit)>c.width||(y+unit)>c.height;

},

move:function(){

// 把数组里底部弹出来,然后在从数组头部插入一个元素

varbox=this.boxes[0];

varx=box.x;

vary=box.y;

switch(game.direction){

case0://向上

y--;

break;

case1://向右

x++;

break;

case2://向下

y++;

break;

case3:// 向左

x--;

}

varb=newBox();

b.x=x;

b.y=y;

this.boxes.unshift(b);

this.boxes.pop();

returnthis;

},

add:function(){

varbox=newBox();

varb2=this.boxes[0];

varx=b2.x;

vary=b2.y;

switch(game.direction){

case0://向上

y--;

break;

case1://向右

x++;

break;

case2://向下

y++;

break;

case3:// 向左

x--;

}

box.x=x;

box.y=y;

this.boxes.unshift(box);

returnthis;

}

}

// 蛇

functionBox(){

this.x=5;

this.y=5;

this.color='black';

this.draw=function(ctx){

ctx.save();

ctx.fillStyle="#000";

ctx.fillRect(this.x*unit,this.y*unit,unit,unit);

}

};

functionreset_game(){

game.v=1;

game.direction=1;

game.boxes=[];

varbox=newBox();

box.x=5;

box.y=5;

game.boxes.unshift(box);

}

functionreset(){

ctx.save();

ctx.fillStyle='#fff';

ctx.fillRect(0,0,c.width,c.height);

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillStyle="#aaa";

ctx.font="13px Arial"// 字体大小 44 像素

ctx.fillText("简单教程,简单编程",c.width/2,(c.height-25))

ctx.fillText(" © 2015-2018 www.twle.cn",c.width/2,(c.height-10));

ctx.restore();

if(ingame==0){

drawTip("请点击屏幕开始任意位置开始");

}

}

functiondrawTip(text){

ctx.save();

ctx.font="22px Arial"// 字体大小 44 像素

ctx.fillStyle='#333333';

ctx.textAlign="center"// 居中对齐

ctx.textBaseline="middle"//垂直居中绘制

ctx.fillText(text,c.width/2,c.height/2);

ctx.restore();

}

functionanimate_it(){

fps_s++;

// 降帧

if(fps_s%fps!=0){

requestAnimationFrame(animate_it);

return;

}

reset();

if(fps_s%(fps*10)==0){

game.add();

}else{

game.move();

}

game.draw_boxes(ctx);

if(game.hit()){

ingame=2;

drawTip("你失败了....,请点击画面重新开始");

cancelAnimationFrame(tt);

return;

}

requestAnimationFrame(animate_it);

}

// 绘制文本

functiondrawText(ctx,text){

ctx.save();

ctx.font="14px Arial"// 字体大小 44 像素

ctx.fillText(text,10,25);

ctx.restore();

}

// 触摸开始事件

wx.onTouchStart(function(e){

if(ingame==0||ingame==2){

return;

}

lasted.x=e.touches[0].clientX

lasted.y=e.touches[0].clientY

})

// 手指离开屏幕

wx.onTouchEnd(function(e){

console.log("wx.ontouchend:");

if(ingame==0||ingame==2){

ingame=1;

reset_game();

tt=requestAnimationFrame(animate_it);

return;

}

varx=e.touches[0].clientX

vary=e.touches[0].clientY

varx0=x-lasted.x;

vary0=y-lasted.y;

// 左右滑动

if(Math.abs(x0)>Math.abs(y0)){

game.direction=x0>0?1:3;

}else{// 上下滑动

game.direction=y0>0?2:0;

}

lasted.x=null;

lasted.y=null;

})

reset();

其它

大家还可以对这个小游戏做一些改动,比如

  1. 绘制边界,就是不使用屏幕边界,而是使用自己绘制的边界

  2. 加入另一个点,编程贪吃蛇游戏

  3. 加入如果是反方向可以掉头或者失败,因为自己撞了自己

  4. 改变每次重新画的局面,而是重绘变化的部分,提高帧率

以上是 【微信小游戏开发】小游戏屏幕虚拟网格 - 像素游戏 的全部内容, 来源链接: utcz.com/a/129894.html

回到顶部