博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
canvas画一个h5小游戏
阅读量:6688 次
发布时间:2019-06-25

本文共 9115 字,大约阅读时间需要 30 分钟。

  这两年,随着移动互联网的发展,h5小游戏也大火了一把。这里我就来讲讲实现一个躲水果的小游戏。如截图所示

  

  再附上demo二维码~

  

  目前游戏的套路,基本上是先载入游戏,然后触发游戏开始,游戏结束时记录游戏分数,诱导你转发盆友圈炫耀,或者再来一次。

  这里我们可以定义一个game_control 对象来控制这一系列流程,同时我们还需要一个人物对象,3个水果对象。

  我们可以定义一个基础原型对象ship作为类,可以记录位置,大小,x,y轴的移动速度,相应的图片,然后人物对象和水果对象就是它的几个实例啦。然后通过canvas的drawImage方法将它们画出在画布中。

function ship(options){                if (options) {                    var width=options.width,                        height=options.height;                    this.x=options.x;                    this.y=options.y;                    this.width=width;                    this.height=height;                    this.first_x=options.x;                    this.first_y=options.y;                    this.speedx=options.speedx;                    this.speedy=options.speedy;                    this.csspeedx=options.speedx;                    this.csspeedy=options.speedy;                    this.xDirection=options.xDirection||1;//x轴移动方向                    this.yDirection=options.yDirection||1;//y轴移动方向                    var canvasOffscreen = document.createElement('canvas');                    canvasOffscreen.width =width;                    canvasOffscreen.height =height;                    canvasOffscreen.getContext('2d').drawImage(options.image, options.sourcex, options.sourcey, options.sourcewidth, options.sourceheight, 0, 0, width, height);                    this.canvasOffscreen=canvasOffscreen;                    this.init();                }            }             ship.prototype={                init:function(){                                     },                reset:function(){                 },                draw:function(ctx){                    //let canvasOffscreen=this.canvasOffscreen;                    ctx.drawImage(this.canvasOffscreen, this.x, this.y);                },                move:function(modifier){                    this.x+=this.xDirection*this.speedx * modifier;                    this.y+=this.yDirection*this.speedy * modifier;                    if(this.x>winwidth-this.width){                        this.x=winwidth-this.width;                        this.xDirection=-1;                    }else if(this.x<0){                        this.x=0;                        this.xDirection=1                    }                    if(this.y>winheight-this.height){                        this.y=winheight-this.height;                        this.yDirection=-1;                    }else if(this.y<0){                        this.y=0;                        this.yDirection=1;                    }                }            }

  这个对象有个移动方法需要注意一下,我们需要判断物体到边界时,物体的移动方向需要转变(也就是将yDirection或者xDirection反向)。

  在这里我们可以将3个水果图片,和人物图片做成雪碧图。然后先将他们用canvas画出来,然后游戏进行中的每一帧将这些canvas再画出来,这样效率比每次都从雪碧图截取要高。

var canvasOffscreen = document.createElement('canvas');canvasOffscreen.width = dw;canvasOffscreen.height = dh;canvasOffscreen.getContext('2d').drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);// 在绘制每一帧的时候,绘制这个图形context.drawImage(canvasOffscreen, x, y);

  然后通过game_control中的draw方法画出

draw:function(obj,ctx){					var ctx=this.ctx,						monsters=this.monsters;					var now=Date.now(),					def=now-this.then;					this.clear();					for(var i=0,len=monsters.length;i

  game_control 对象定义几个方法,init,start,draw,end,reset等方法。

  init方法主要是初始化游戏的,主要处理图片加载,图片加载完后,几个对象的初始化。

  

init:function(){                    var canvas=document.getElementById('game-canvas'),                        self=this,                        ctx=canvas.getContext('2d');                    self.ctx=ctx;                    canvas.width=winwidth;                    canvas.height=winheight;                    let img=new Image();                    img.οnlοad=function(){                        var zjb=new hero({                            image:img,                            x:gettruesize(250),                            y:gettruesize(56),                            width:gettruesize(50),                            height:gettruesize(50),                            sourcewidth:104,                            sourceheight:104,                            sourcex:0,                            sourcey:0                        });                        for(var i=0;i<3;i++){                            var x=60,y=110;                            if(i==1){x=38,y=330;}                            if(i==2){x=218,y=338;}                            var monster=new ship({                                                image:img,                                                x:gettruesize(x),                                                y:gettruesize(y),                                                width:gettruesize(50),                                                height:gettruesize(50),                                                sourcewidth:104,                                                sourceheight:104,                                                speedx:gettruesize(getrandom(60,100)),                                                speedy:gettruesize(getrandom(60,100)),                                                sourcex:104*(i+1),                                                sourcey:0                                            });                            self.monsters.push(monster);                        }                        self.objs=zjb;                        self.draw();                        self.bindmove(canvas,zjb);                    }                    img.src="all.png";                                 }

  然后调用给bindmove方法给canvas注册手指触摸事件,如果手机触摸在人物对象这个位置,那么代表游戏开始,调用start方法。

  

bindmove:function(canvas,hero){                    let self=this;                    canvas.addEventListener('touchstart', function(e) {                        var event = e||window.event,                            csx = event.touches[0].clientX,                            csy = event.touches[0].clientY,                            nanshengcsx = hero.x,                            nanshengcsy = hero.y;                        if (csx <= hero.x + hero.width && csx >= hero.x && csy <= hero.y + hero.height && csy >= hero.y) {                            if (!self.startstate) {                                self.start();                                timer = setInterval(function(){                                    self.draw();                                }, 1);                            }                            document.addEventListener('touchmove', move,false);                            function move(e){                                e.preventDefault();                                var event = e||window.event,                                    nowx = event.touches[0].clientX,                                    nowy = event.touches[0].clientY;                                hero.x = nanshengcsx + nowx - csx;                                hero.y = nanshengcsy + nowy - csy;                                if(hero.x<0){                                    hero.x=0;                                }else if(hero.x+hero.width>winwidth){                                    hero.x=winwidth-hero.width;                                }                                if(hero.y<0){                                    hero.y=0;                                }else if(hero.y+hero.height>winheight){                                    hero.y=winheight-hero.height;                                }                            }                            function moveend(e){                                document.removeEventListener('touchend',moveend);                                document.removeEventListener('touchmove',move);                            }                            document.addEventListener('touchend', moveend ,false);                        }                    },false);                }

  

   start方法主要是实现每一帧的循环方法。

var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {					window.setTimeout(callback, 20);				};

  不断的去调用raf(fun)就可以啦,这里我直接用了setInterval方法

start:function(){                    var self=this;                    this.startstate=true;                    this.then=Date.now();                    this.starttime=this.then;                    document.getElementById('tips').style.display="none";                    timer = setInterval(function(){                        self.draw();//在画布中画出                    }, 1);                }

   在循环方法中,通过手指的移动来计算 人物的x,y 轴的位置,通过时间 和 水果x,y 轴的速度计算出相应的位置,然后再进行一一比较,看是否发生触碰,同时,随着时间的推移,物体移动的速度慢慢新增,这里我们定了每5秒增加速度,这里我们将模型当作矩形(复杂模型我也不造怎么算~~),当发生触碰时,则判定游戏结束,将坚持了的时间输出。

check:function(){                    var last=this.then-this.starttime;                     var monsters=this.monsters;                    var nansheng=this.objs;                    if (this.monsterSum != Math.floor(last / 5000)){//如果时间经过5秒就增加速度                        this.monsterSum ++;                          for(var i=0;i

  

    至于持续性的与后台的数据交互可以通过websocket来实现(不过我没有试过~~,当时做项目的时候只是结束的时候去保存了一下),游戏结束时提示 分享页面或者在玩一次即可。

  

  

  

转载于:https://www.cnblogs.com/bobogoodgoodstudy/p/6028256.html

你可能感兴趣的文章
Android MimeTypeMap使用--MIME类型
查看>>
LeanEngine 中使用 WebSocket
查看>>
Android高仿微信照片选择器+预览+显示照片
查看>>
阿里云CDN的一些资料记录
查看>>
深入理解JVM虚拟机1:JVM内存的结构与永久代的消失
查看>>
SpringMVC执行流程及工作原理
查看>>
如何利用百度长尾高指数词,提高网站百度权重
查看>>
震惊!这个控件绝对值得收藏。轻松实现圆角、文字描边、状态指示等效果
查看>>
迎双11十周年,OceanBase 2.0挑战新巅峰
查看>>
安卓手机为什么越用越卡, 程序员来告诉你!
查看>>
添加百度统计,有利于网站SEO,百度终于发声了
查看>>
Redis(一) 安装
查看>>
轻松搞定分组报表中的各种排序
查看>>
阿里云服务器购买价格-阿里云服务器购买流程
查看>>
Model-driven IIoT System for Manufacturing Activities
查看>>
shiro实战系列(七)之Realm
查看>>
android eventbus ui sqlite http
查看>>
浅入分析和Linux内核相关的文件夹/proc和/sys .
查看>>
awk分析日志得到响应时间的最大最小和平均值
查看>>
轻量级的 Windows Lite OS 截图曝光:界面向 Chrome OS 看齐
查看>>