• 用canvas写一个h5小游戏


    这篇文章我们来讲一讲用canvas画一个躲水果的小游戏。就是通过手指控制一个人物移动来躲避水果,若发生碰撞,则游戏结束。

    我们定义一个game_control对象来处理初始化,事件绑定,游戏开始,游戏结果判定,游戏结束等判定。

    在游戏中,我们需要一个人物以及三种水果的图片,我们做成了雪碧图。

    接下来直接上代码吧~

    首先我们定义一个ship对象,3个水果、一个人物都是基于这个对象的。

    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;
    					}
    				}
    			}
    

      当我们用canvas绘制人物和水果时,可以采用离屏绘制的方法,就是先将每个水果,人物绘制一遍,然后每次重绘的时候,再用canvas将这个已绘制的绘制出来就可以了,这样效率会比每次都直接绘制图片要高

    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);
    
    
    
    
    ctx.drawImage(this.canvasOffscreen, this.x, this.y);
    

      接下来说一下game_control 初始化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.onload=function(){
    						var zjb=new hero({
    							image:img,
    							x:gettruesize(250),
    							y:gettruesize(56),
    							gettruesize(50),
    							height:gettruesize(50),
    							source104,
    							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),
    												gettruesize(50),
    												height:gettruesize(50),
    												source104,
    												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";					
    				}
    

      主要作用是当 雪碧图载入完成后,定义出一个人物对象以及3个水果对象,并通过draw方法将他们用canvas绘制出来,同时给人物对象进行手指事件的绑定(bindmove方法)

    接下来讲讲bindmove方法

    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方法),并注册移动事件,跟随手指移动而移动。

    start方法中定义一个循环,让canvas 一帧一帧的画。

    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);
    				}
    

      最后还要一个check方法,来判断人物与水果间有没有发生触碰,若有则游戏结束。

    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<monsters.length;i++){
    							monsters[i].speedx+=60;
    							monsters[i].speedy+=60;
    						}
    					}   
    					for(var i=0;i<monsters.length;i++){
    						var monster1=monsters[i];
    						if ((monster1.x - nansheng.width) <= nansheng.x && nansheng.x <= (monster1.x + monster1.width) && (monster1.y - nansheng.height) <= nansheng.y && nansheng.y <= (monster1.y + monster1.height)) {
    							this.end();
    						}
    					}
    				}
    

      这样一个简单的小游戏就完成啦~

  • 相关阅读:
    c# Array.Sort() 对数组排列
    【软件配置】JDK+AndroidStudio4.1开发安卓APP环境安装和配置教程详细
    【QT】跨线程的信号槽(connect函数)
    【QT】QtConcurrent::run()+QThreadPool实现多线程
    【QT】继承QRunnable+QThreadPool实现多线程
    【QT】子类化QObject+moveToThread实现多线程
    【QT】子类化QThread实现多线程
    【QT】QThread源码浅析
    【C++】 C++异常捕捉和处理
    【QT】 Qt之QComboBox删除下拉item时出现段错误
  • 原文地址:https://www.cnblogs.com/bobogoodgoodstudy/p/6024790.html
Copyright © 2020-2023  润新知