H5游戏开发之抓住小恐龙
第一次写技术性博文,以前都只是写一些生活感想,记录一些生活发生的事情。
博主大三学生一枚,目前学习JS一年多,还处于学习阶段,有什么说的不好的希望大牛指点下,由于第一次写博文,排版什么的有待改进,希望大家谅解。
这是我学习H5 canvas以来写的第一个游戏,第一次接触H5游戏呢,是看了一位大哥码农终结者的博客(http://www.cnblogs.com/chaogex/)(基础要求有点高,等以后一定要研究透彻),正好实验室老师准备喊我写H5的游戏游戏,看了很多canvas的API和大神vajoy(http://www.cnblogs.com/vajoy/)写的canvas教程,打好canvas的基础以后又看了HTML5研究小组第二期技术讲座《手把手制作HTML5游戏》的视频,下了源代码学习了很长一段时间,那段时间一直反反复复的写这个游戏,慢慢领悟很多游戏的概念,然后就有种成竹在胸的感觉(别逗了,我还什么都不懂),当然这种成就感是非常重要的,动力来源于此。这就是我游戏开发到现在将近3个星期的学习经历,分享给大家,希望对大家有用。
游戏做出来是这个效果,玩过黑白钢琴的人应该知道,这和那个游戏差不多。
一。图片渲染
写过游戏的人都知道大多数游戏都是以背景加精灵的方式开展的,这里渲染图片是经常要用的,本人自己封装了一个图片渲染的方法,希望大家给点意见。
/**
* author yh
* @param imgCount 图片数组 必须有id和src
* @param callback 回调函数
* @returns 每个精灵的canvas和context
*/
function getImg(imgCount,callback){
var total = imgCount.length,
load = 0,
img = {},
w = 0,
h = 0; for(var i = 0;i < total;i++){
var id = imgCount[i].id;
var imgs = new Image();
imgs.src = imgCount[i].src; //设置canvas的width和height
if(imgCount[i].width && imgCount[i].height){
w = imgCount[i].width;
h = imgCount[i].height;
}else{
w = imgs.width;
h = imgs.height;
} img["cvs"+id] = document.createElement("canvas");
img["cvs"+id].width = w;
img["cvs"+id].height = h;
img["ct"+id] = img["cvs"+id].getContext("2d");
img["ct"+id].drawImage(imgs,0,0,imgs.width,imgs.height,0,0,w,h); imgs.onload = function(){
load++;
delete imgs;
imgs = undefined;
};
}; if(typeof callback == "function"){
var me = this;
function check(){
if(load >= total)
callback.call(me,arguments);
else
setTimeout(check,300);
}
check();
};
return img;
}
因为考虑到性能的问题,所以每次加载一个图片都创建一个canvas来画这张图片,当然我们并不需要显示这个canvas,只为以后每次画图的时候可以直接用getImageData和putImageData方法来直接取canvas中的data就可以得到图片,而不用每次都去画图,等下会为大家展示画图的过程,这个方法的调用是这样的:
var global = getImg([
{id:"bg",src:"img/bg.png",width:game.width,height:game.height},
{id:"over",src:"img/over.jpg",width:game.width,height:game.height},
{id:"di1",src:"img/1.png",width:w-20,height:h-20},
{id:"di2",src:"img/2.png",width:w-20,height:h-20},
{id:"di3",src:"img/3.png",width:w-20,height:h-20},
{id:"di4",src:"img/4.png",width:w-20,height:h-20},
{id:"di5",src:"img/5.png",width:w-20,height:h-20},
{id:"di6",src:"img/6.png",width:w-20,height:h-20},
{id:"di7",src:"img/7.png",width:w-20,height:h-20},
{id:"di8",src:"img/8.png",width:w-20,height:h-20},
{id:"di9",src:"img/9.png",width:w-20,height:h-20},
{id:"hand",src:"img/hand.png",width:w-20,height:h-20},
],callback);
定义一个变量来存取getImg的返回对象,下面是画图的方法:
/**
* 根据id来获取global中的canvas和context,进行get和put ImageDa
* target放所有canvas的对象,上面的global
* context为目标画布的上下文
* x y 为初始坐标
* id 为精灵的id
*/
function draw(target,context,x,y,id){
var canvas = target["cvs" + id],
ct = target["ct" + id],
data = ct.getImageData(0,0,canvas.width,canvas.height); context.putImageData(data,x,y);
}
这个方法封装得不是很好,因为很多时候呢我们都需要精灵的动画,就是要随时改变截取图片的x和y,这里封装的只是这个游戏中用到的方法,因为这个游戏中无精灵动画。
二。游戏类
当图片渲染完以后呢我们需要定义一个game类,在这里写代码,为了提高性能,用的原型方法,这样每次加载JS文件的时候只加载一份,不浪费资源。
因为本人没有github(还没用过这么高端的东西),只能在这里贴代码了。
function Game(option){
//对象扩展
for(var attr in option)
this[attr] = option[attr];
}
Game.prototype = {
canvas:null,
ct:null,
width:999,
height:999,
x:0,
y:0,
n:4,
m:6,
FPS:30,
sleep:0,
arr:[],
dinoArr:[],
click:0,
init : function(){
this.canvas = document.createElement("canvas");
this.canvas.width = this.width;
this.canvas.height = this.height;
document.body.appendChild(this.canvas); this.ct = this.canvas.getContext("2d");
this.sleep = (1000/this.FPS)|0;
this.time = Date.now();
this.moused = false;
},
update:function(){
this.initDraw();
this.move();
},
initDraw : function(){
this.drawImg(global,this.ct,0,0,"bg");
var y = 0;
for(var i = 0;i<this.m;i++){
var x = 0;
var ran = ((Math.random()*4)|0); for(var j = 0;j<this.n;j++){
this.ct.fillStyle = "#fff";
this.ct.fillRect(x,y,97,97); if(j == ran && i != this.m-1){
this.drawImg(global,this.ct,x+10,y+10,"hand");
this.arr.push(j);
}else if(j == ran && i == this.m-1){
this.drawImg(global,this.ct,x+10,y+10,"di6");
}
x += 100;
}
y += 100;
}
this.listener(this.arr);
}, drawImg : function(target,context,x,y,id){
var canvas = target["cvs" + id];
var ctx = target["ct" + id];
var data = ctx.getImageData(0,0,canvas.width,canvas.height); context.putImageData(data,x,y);
}
}
上面这些代码呢完成了初始化,我们先把每个效果实现以后再进行动画,下面我们会设置鼠标事件,还有主循环,这是个很重要的东西,一般一个游戏只有一个主循环。
listener : function(arr,reloadImg){
this.arr = arr; //获取边界
var me = this,
index = this.arr.pop(); this.dinoArr.push(index);
this.reloadImg = reloadImg;
if(this.reloadImg){
console.log(this.dinoArr)
var dinoIndex = this.dinoArr.shift();
this.y = 500 + 10;
this.x = dinoIndex*100 + 10;
} var targetX = index*100 + 50,
targetY = 450; //添加鼠标事件,判断范围
this.canvas.onmouseup = function(event){
var cx = event.clientX - me.canvas.offsetLeft - targetX,
cy = event.clientY - me.canvas.offsetTop - targetY; if(-50<=cx&& cx <= 50 && -50<= cy && cy<= 50){
me.moused = true;
}
};
},
move : function(){
var me = this;
this.mainLoop = setInterval(function(){
me.loop();
},this.sleep);
},
loop : function(){
var time = document.getElementById("time");
Time = (Date.now() - this.time)/1000;
time.innerHTML = Time;
document.getElementById("grade").innerHTML = this.click;
if(this.moused){
this.moused = false;
this.click++;
this.reload();
}
if(Time >= 20){
this.drawImg(global,this.ct,0,0,"over");
clearInterval();
alert("你一共抓了"+this.click+"只恐龙");
}
},
reload:function(){
var data = this.ct.getImageData(0,0,this.width,this.height);
this.ct.clearRect(0,0,this.width,this.height);
this.reDraw();
this.ct.putImageData(data,0,100);
this.reDino();
},
reDino:function(){
var random = (Math.random()*9+1)|0,
id = null;
switch(random){
case 1:id = "di1";break;
case 2:id = "di2";break;
case 3:id = "di3";break;
case 4:id = "di4";break;
case 5:id = "di5";break;
case 6:id = "di6";break;
case 7:id = "di7";break;
case 8:id = "di8";break;
case 9:id = "di9";break;
}
this.drawImg(global,this.ct,this.x,this.y,id);
},
reDraw:function(){
this.drawImg(global,this.ct,0,0,"bg");
var y = 0;
var x = 0;
var ran = ((Math.random()*4)|0); for(var j = 0;j<this.n;j++){
this.ct.fillStyle = "#fff";
this.ct.fillRect(x,y,97,97); if(j == ran){
this.drawImg(global,this.ct,x+10,y+10,"hand");
this.arr.unshift(j);
}
x += 100;
} this.reloadImg = true;
this.listener(this.arr,this.reloadImg);
}
每次点击以后我们会得到一份当前context的getImageData,然后设置为putImageData(data,0,100),然后在第一行重新渲染一次,再把数组中的值更新,这样就可以看起来是个动画。比较水平有限,大牛看看就当玩玩,如果水平和我差不多的话可以学习下,以后我们也能成为大牛,也会分享更多更好的东西。
最近呢还在研究司徒正美的《JS框架设计》,这本书给我第一感觉就是思想高度太高,第一次看就把我看郁闷了,看了第一章什么都没看懂,然后我又从头到尾依次把不懂得新概念百度了一遍,历经2天终于把第一章搞完,慢慢的越来越喜欢这本书,写了一个自己框架的种子模块,打算等自己的框架出来以后再去找工作,到时候应该会更轻松一些。
H5游戏开发之抓住小恐龙的更多相关文章
- 关于h5游戏开发,你想了解的一切都在这儿!
2020年,受疫情影响,线下产业红利褪去,线上迎来的新一轮的高峰.众多商家纷纷抓住了转型时机,开启了流量争夺战.H5游戏定制无疑是今年引流的大热门.如何开发一款有趣.有爆点.用户爱买单的好游戏呢? ...
- 为什么选择H5游戏开发定制?
为什么选择H5游戏开发定制? 随着微信H5游戏推广带来的显著效果,越来越多的商家已经加入到游戏营销的队伍中来, 对H5小游戏有了解的商家都知道,[模板游戏]的价格往往低于[定制游戏]的价格,可是为什么 ...
- 今天我看了一个H5游戏EUI的例子,我都快分不清我到底是在用什么语言编译了代码了,作为刚刚学习H5游戏开发的菜鸟只能默默的收集知识
今天看了一个EUI的demo,也是接触H5游戏开发的第五天了,我想看看我能不能做点什么出来,哎,自己写果然还是有问题的.在看EUI哪一个demo的时候就遇见了一些摇摆不定的问题,我觉得提出来 1.to ...
- 最近这两天看了关于H5游戏开发的一个教程,实践很短暂,看了很多理论的东西,现在呢也只是想回忆回忆关于EUI的部分知识吧
首先我了解了什么是Egret: Egret中文就是白鹭的意思,Egret是一套H5游戏开发的软件.(纯粹属于个人理解) 其次我对以下几款软件的相关知识做了些了解: Egret Engine(引擎),E ...
- H5游戏开发之多边形碰撞检测
2D多边形碰撞检测介绍这是一篇论证如何在2D动作游戏中执行碰撞检测的文章(Mario,宇宙入侵者等),为了保证它的高效性和精确性,碰撞检测是以多边形为基础的,而不是以sprite为基础.这是两种不同的 ...
- H5游戏开发:贪吃蛇
贪吃蛇的经典玩法有两种: 积分闯关 一吃到底 第一种是笔者小时候在掌上游戏机最先体验到的(不小心暴露了年龄),具体玩法是蛇吃完一定数量的食物后就通关,通关后速度会加快:第二种是诺基亚在1997年在其自 ...
- DirectX游戏开发——从一个小游戏開始
本系列文章由birdlove1987编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/26364129 写在前面:自 ...
- 【h5游戏开发】egret引擎p2物理引擎 - 小球碰撞地面搞笑的物理现象
重力的方向和地面的问题 p2中默认的方向是从上到下,如果重力默认是正数的话,物体放到世界中是会从上面往下面飘的 p2中plane地面默认的方向是y轴的方向,而在p2中y轴的方向默认是从上往下 首先来看 ...
- 用微信小程序做H5游戏尝试
微信小程序发布后,公司虽然没有拿到第一批内测资格,但作为微信亲密合作伙伴,一定要第一时间去尝试啦.现在微信小程序刚发布还在测试阶段,可以说是1.0版本,所以框架和结构内容都还不多,相关的文档跟微信AP ...
随机推荐
- DedeCMS织梦系统head.htm里无法调用栏目描述
{dede:channel type='top'} [field:description/] {/dede:channel} channel 这个标签没有description属性你需要自己把这个属性 ...
- 安装 SSL 证书
http://www.itrus.cn/html/fuwuyuzhichi/fuwuqizhengshuanzhuangpeizhizhinan/
- Database Schemas Found in Oracle E-Business Suite
https://docs.oracle.com/cd/E26401_01/doc.122/e22952/T156458T659606.htm Table of Database Schemas in ...
- Java 程序性能优化
1. singleton延时初始化 class Singleton { private static Singleton _instance = null; public synchronized S ...
- Flume概述和简单实例
Flume概述 Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统.支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方( ...
- DeviceOne 竟然做出来如此复杂的App
分享来自DeviceOne论坛 此文章分享自DeviceOne的论坛,论坛上的用户分享,下面有二维码扫描,可以进行安装和试用.支持android和ios两个 操作系统. 这个还没做完,目前已经完成了初 ...
- 关于大型网站技术演进的思考(十三)--网站静态化处理—CSI(5)
讲完了SSI,ESI,下面就要讲讲CSI了 ,CSI是浏览器端的动静整合方案,当我文章发表后有朋友就问我,CSI技术是不是就是通过ajax来加载数据啊,我当时的回答只是说你的理解有点片面,那么到底什么 ...
- java提高篇(十三)-----equals()方法总结
equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...
- Linux sort命令
200 ? "200px" : this.width)!important;} --> 介绍 sort命令是一个文本排序命令,它能对标准输入和文本文件进行排序,并且能将结果通 ...
- [PCB设计] 2、畸形PCB板子的制作核心——AD14导入dwg格式文件的方法
本文参考园友:The Zone of up.Craftor http://www.cnblogs.com/craftor/archive/2012/06/28/2567259.html 硬件工程师在做 ...