尝试用canvas写小游戏
还是习惯直接开门见山,这个游戏是有一个老师抓作弊的学生,老师背身,点学生开始加分,老师会不定时回头,如果老师回头还在点学生在,就会被抓住,游戏game over。
1、写游戏首先是loading条,于是我们就有了以下的一端js代码
function game() {
var that = this;
this.isStart = false;
this.isFlag = true;
this.percent = 0;
this.init = function () {
}
this.loading = function (percent) {
this.percent = this.percent + percent;
$("#progressbarbj").css("width", this.percent + "%");
$(".game-percent").text(this.percent);
if (this.percent == 100) {
$(".game-loading").animate({ top: "-100%" }, 500, function () {
that.isStart = true;
that.start();
});
}
};
this.start = function () {
};
}
以上代码可以看出,对外开放了一个Init的function,在页面里面调用Init,既可以完成游戏的初始化,因为加载是多段的,所以封装了一个Loading方法,用来加载各类图片资源。
2、游戏里面的角色分为,老师和学生(分左右两个学生),于是我们定义了三段配置。
var role_config = {
teacher: {
first: {
path: "img/10001.png"
},
front: {
imgs: [
{ path: "img/10001.png?v=2" },
{ path: "img/10002.png?v=2" },
{ path: "img/10003.png?v=2" },
{ path: "img/10004.png?v=2" },
{ path: "img/10005.png?v=2" },
{ path: "img/10006.png?v=2" },
{ path: "img/10007.png?v=2" },
{ path: "img/10008.png?v=2" }
],
time: 50,
isLoop: true,
loopTime: 500
},
trunback: {
imgs: [{ path: "img/20001.png" }, { path: "img/20002.png" }, { path: "img/20003.png" }, { path: "img/20004.png"}],
time: 50
},
back: {
imgs: [
{ path: "img/30001.png?v=2" },
{ path: "img/30002.png?v=2" },
{ path: "img/30003.png?v=2" },
{ path: "img/30004.png?v=2" },
{ path: "img/30005.png?v=2" }
],
time: 50,
isLoop: true,
loopTime: 400
},
strun: {
imgs: [
{ path: "img/40001.png?v=2" },
{ path: "img/40002.png?v=2" },
{ path: "img/40003.png?v=2" },
{ path: "img/40004.png?v=2" },
{ path: "img/40005.png?v=2" },
{ path: "img/40006.png?v=2" },
{ path: "img/40007.png?v=2" }
],
time: 50
},
trunfront: {
imgs: [
{ path: "img/50001.png?v=2" },
{ path: "img/50002.png?v=2" },
{ path: "img/50003.png?v=2" },
{ path: "img/50004.png?v=2" },
{ path: "img/50005.png?v=2" }
],
time: 50
},
catchup: {
imgs: [
{ path: "img/60001.png?v=2" },
{ path: "img/60002.png?v=2" },
{ path: "img/60003.png?v=2" },
{ path: "img/60004.png?v=2" },
{ path: "img/60005.png?v=2" },
{ path: "img/60006.png?v=2" },
{ path: "img/60007.png?v=2" },
{ path: "img/60008.png?v=2" }
],
time: 50
}
},
studentLeft: {
up: {
imgs: [{ path: "img/student_10001.png"}],
time: 100
},
bow: {
imgs: [
{ path: "img/student_10002.png" },
{ path: "img/student_10005.png" },
{ path: "img/student_10006.png" }
],
time: 100,
isRandom: true
}
},
studentRight: {
up: {
imgs: [{ path: "img/student_10003.png"}],
time: 100
},
bow: {
imgs: [
{ path: "img/student_10004.png" },
{ path: "img/student_10007.png" },
{ path: "img/student_10008.png" }
],
time: 100,
isRandom: true
}
}
};
front、back、trunback、up等,均为动作,其中的time是图片切换的时长,这样就可以调解动画的速度,loopTime,是单轮循环的时长,因为图片切换到最后一张了以后,可能会有停顿。
3、开始写角色类了。
首先我们定义了一个角色的基类,代码如下:
function role(target) {
var that = this;
this.target = target;
this.actionHandler;
this.clearHandler;
this.index = 0;
this.load = function (array, holder, point, total, callback) {
var index = 0;
for (var i = 0; i < array.length; i++) {
var img = new Image();
img.src = array[i].path;
var p = {
img: img,
x: point.x,
y: point.y,
w: point.w,
h: point.h
};
holder.push(p);
img.onload = function () {
index++;
if (index == total - 1) {
that.invoke(callback);
}
};
}
};
this.animate = function (points, model, callback) {
var loopTime = model.loopTime || 1000;
if (this.clearHandler) {
clearInterval(this.clearHandler);
}
if (model.isRandom) {
var random = Math.random();
var index = Math.floor(random * points.length);
var p = [];
p.push(points[index]);
this.action(p, model.time, callback);
} else {
this.action(points, model.time, callback);
}
if (model.isLoop) {
this.clearHandler = setInterval(function () {
that.action(points, model.time, callback);
}, loopTime);
}
};
this.action = function (points, time, callback) {
var i = 0;
if (this.actionHandler) {
clearInterval(this.actionHandler);
}
var point = points[i];
this.draw(point);
i++;
this.actionHandler = setInterval(function () {
if (i == points.length) {
clearInterval(that.actionHandler);
that.invoke(callback);
return;
}
point = points[i];
that.draw(point);
i++;
}, time);
};
this.draw = function (point) {
this.target.clearRect(point.x, point.y, point.w, point.h);
this.target.beginPath();
this.target.drawImage(point.img, point.x, point.y, point.w, point.h);
this.target.fill();
};
this.invoke = function (callback) {
if (typeof callback == "function") {
callback();
}
};
this.stop = function (callback) {
if (this.actionHandler) {
clearInterval(this.actionHandler);
}
if (this.clearHandler) {
clearInterval(this.clearHandler);
}
this.invoke(callback);
};
};
我们有个draw方法用来绘制,有个action方法用来连续绘制形成动画,有个animate则是根据逻辑进行动画播放了。
接着我们开始写teacher类和Student类,代码如下:
function teacher(target) {
role.call(this, target);
var that = this;
this.model;
this.first = {};
this.imgs = {
front: [],
trunback: [],
back: [],
strun: [],
trunfront: [],
catchup:[]
};
this.init = function (point, callback) {
this.model = role_config.teacher;
this.load(this.model.front.imgs, this.imgs.front, point, this.model.front.imgs.length, callback);
};
this.loadtrunback = function (point, callback) {
this.load(this.model.trunback.imgs, this.imgs.trunback, point, this.model.trunback.imgs.length, callback);
};
this.loadback = function (point, callback) {
this.load(this.model.back.imgs, this.imgs.back, point, this.model.back.imgs.length, callback);
};
this.loadstrun = function (point, callback) {
this.load(this.model.strun.imgs, this.imgs.strun, point, this.model.strun.imgs.length, callback);
};
this.loadtrunfront = function (point, callback) {
this.load(this.model.trunfront.imgs, this.imgs.trunfront, point, this.model.trunfront.imgs.length, callback);
};
this.loadcatchup = function (point, callback) {
this.load(this.model.catchup.imgs, this.imgs.catchup, point, this.model.catchup.imgs.length, callback);
};
this.front = function (callback) {
this.animate(this.imgs.front, this.model.front, callback);
};
this.trunback = function (callback) {
this.animate(this.imgs.trunback, this.model.trunback, callback);
};
this.back = function (callback) {
this.animate(this.imgs.back, this.model.back, callback);
};
this.strun = function (callback) {
this.animate(this.imgs.strun, this.model.strun, callback);
};
this.trunfront = function (callback) {
this.animate(this.imgs.trunfront, this.model.trunfront, callback);
};
this.catchup = function (callback) {
this.animate(this.imgs.catchup, this.model.catchup, callback);
};
}
function studentLeft(target) {
role.call(this, target);
var that = this;
this.model;
this.first = {};
this.imgs = {
bow: [],
up: []
};
this.init = function (point, callback) {
this.model = role_config.studentLeft;
this.load(this.model.up.imgs, this.imgs.up, point, this.model.bow.imgs.length);
this.load(this.model.bow.imgs, this.imgs.bow, point, this.model.bow.imgs.length, callback);
};
this.bow = function (callback) {
this.animate(this.imgs.bow, this.model.bow, callback);
};
this.up = function (callback) {
this.animate(this.imgs.up, this.model.up, callback);
};
}
function studentRight(target) {
role.call(this, target);
var that = this;
this.model;
this.imgs = {
bow: [],
up: []
};
this.init = function (point, callback) {
this.model = role_config.studentRight;
this.load(this.model.up.imgs, this.imgs.up, point, this.model.bow.imgs.length);
this.load(this.model.bow.imgs, this.imgs.bow, point, this.model.bow.imgs.length, callback);
};
this.bow = function (callback) {
this.animate(this.imgs.bow, this.model.bow, callback);
};
this.up = function (callback) {
this.animate(this.imgs.up, this.model.up, callback);
};
}
分别继承于role,然后有一些自己的动作。
4、然后就是拼接了,根据游戏逻辑来拼接各个动作,于是我们最初的game类,就有了充实,代码如下:
function game() {
var that = this;
this.teacher;
this.studentLeft;
this.studentRight;
this.isOver = false;
this.isStart = false;
this.isFlag = true;
this.index = 0;
this.success = false;
this.username = '';
this.percent = 0;
this.number = 0;
this.overHandler;
this.left = {};
this.right = {};
this.time = 0;
this.score = 0;
this.number = 0;
this.status = 0;
this.interval = 0;
this.sInterval = 0;
this.level = [3, 2, 1];
this.difficulty = 0;
this.gameTime = 1000;
this.ticket = '';
this.totalScore = 0;
this.totalRankingCount = 0;
this.init = function () {
this.left = {
scoreContainer: ".game-score-left",
name: "left",
isPress: false,
handler: null,
score: 0,
step: 5,
time: 0
};
this.right = {
scoreContainer: ".game-score-right",
name: "right",
isPress: false,
handler: null,
score: 0,
step: 5,
time: 0
};
var teacher_board = document.getElementById("gameteacher");
var studentLeft_board = document.getElementById("gamestudentleft");
var studentRight_board = document.getElementById("gamestudentright");
this.teacher = new teacher(teacher_board.getContext("2d"));
this.studentLeft = new studentLeft(studentLeft_board.getContext("2d"));
this.studentRight = new studentRight(studentRight_board.getContext("2d"));
this.teacher.init({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.teacher.loadtrunback({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.teacher.loadback({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.teacher.loadstrun({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.teacher.loadtrunfront({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.teacher.loadcatchup({ x: 0, y: 0, w: teacher_board.width, h: teacher_board.height }, function () {
that.loading(10);
});
this.studentLeft.init({ x: 0, y: 0, w: studentLeft_board.width, h: studentLeft_board.height }, function () {
that.loading(20);
});
this.studentRight.init({ x: 0, y: 0, w: studentRight_board.width, h: studentRight_board.height }, function () {
that.loading(20);
});
};
this.loading = function (percent) {
this.percent = this.percent + percent;
$("#progressbarbj").css("width", this.percent + "%");
$(".game-percent").text(this.percent);
if (this.percent == 100) {
$(".game-loading").animate({ top: "-100%" }, 500, function () {
that.isStart = true;
that.start();
that.event();
});
}
};
this.start = function () {
this.isFlag = false;
that.studentLeft.up();
that.studentRight.up();
$(".game-time-text").text((this.gameTime - this.time).toFixed(1));
this.teacher.front(function () {
that.teacher.trunback(function () {
that.status = status_config.back;
that.isFlag = true;
that.teacher.back();
});
});
this.listen();
};
this.listen = function () {
this.overHandler = setInterval(function () {
if (that.isStart && !that.isOver) {
that.isCatch();
that.startCount();
if (that.isFlag) {
if (that.status == status_config.back) {
that.front(that.level[that.difficulty]);
} else {
that.back();
}
}
}
}, 100);
};
this.gameOver = function () {
this.teacher.catchup(function () {
$(".game-catch-up").show();
});
};
this.timeEnd = function () {
$(".game-over").show();
};
this.gameEnd = function () {
this.isOver = true;
if (this.overHandler) {
clearInterval(this.overHandler);
}
};
this.front = function (intervel) {
var r = Math.random();
if (this.time - this.interval >= intervel) {
if (r < 0.6) {
this.isFlag = false;
this.teacher.trunfront(function () {
that.interval = that.time;
that.status = status_config.front;
that.isFlag = true;
that.teacher.front();
});
}
} else if (this.time - this.sInterval >= 1) {
if (r < 0.1) {
this.isFlag = false;
that.sInterval = that.time;
this.teacher.strun(function () {
that.isFlag = true;
that.teacher.back();
});
}
}
};
this.back = function () {
var r = Math.random();
if (this.time - this.interval >= 1) {
if (r < 0.8) {
this.isFlag = false;
that.status = status_config.back;
this.teacher.trunback(function () {
that.interval = that.time;
that.isFlag = true;
that.teacher.back();
});
}
}
};
this.isCatch = function () {
if (!this.isOver) {
if (this.status == status_config.front) {
if (this.left.isPress || this.right.isPress) {
this.catchUp();
return true;
}
}
}
return false;
};
this.catchUp = function () {
this.gameEnd(that.gameOver());
};
this.startCount = function () {
this.time = this.time + 0.1;
this.difficulty = parseInt(this.time / 10);
this.difficulty = this.difficulty >= this.level.length ? this.level.length - 1 : this.difficulty;
this.score = this.left.score + this.right.score;
$(".game-score-text").text(this.score);
if (this.time >= this.gameTime) {
this.timeEnd(that.gameEnd());
}
};
this.pressDown = function (model) {
if (model.handler) {
clearInterval(model.handler);
}
if (this.isStart && !this.isOver) {
model.score = model.score + model.step;
model.isPress = true;
this.scoreAction(model.step, model.scoreContainer);
model.handler = setInterval(function () {
if (model.isPress) {
model.time = model.time + 0.2;
if (model.time >= 0.6) {
model.step = 10;
}
if (model.time >= 1.2) {
model.step = 50;
}
if (model.time >= 1.8) {
model.step = 100;
}
model.score = model.score + model.step;
that.scoreAction(model.step, model.scoreContainer);
}
}, 200);
}
};
this.scoreAction = function (score, container) {
var img = $('<img src="img/' + score + '.png" />');
$(container).append(img);
img.animate({ "top": "-60" }, 500, function () {
setTimeout(function () {
img.fadeOut(1000, function () {
img.remove();
});
}, 1000);
});
};
this.pressUp = function (model) {
clearInterval(model.handler);
model.isPress = false;
model.time = 0;
model.step = 5;
};
this.event = function () {
$(".game-student-left").bind({
"mousedown": function () {
that.studentLeft.bow();
that.pressDown(that.left);
return false;
},
"mouseup": function () {
that.studentLeft.up();
that.pressUp(that.left);
return false;
},
"touchstart": function () {
that.studentLeft.bow();
that.pressDown(that.left);
return false;
},
"touchend": function () {
that.studentLeft.up();
that.pressUp(that.left);
return false;
}
});
$(".game-student-right").bind({
"mousedown": function () {
that.studentRight.bow();
that.pressDown(that.right);
return false;
},
"mouseup": function () {
that.studentRight.up();
that.pressUp(that.right);
return false;
},
"touchstart": function () {
that.studentRight.bow();
that.pressDown(that.right);
return false;
},
"touchend": function () {
that.studentRight.up();
that.pressUp(that.right);
return false;
}
});
};
};
var status_config = {
front: 0,
back: 1
}
代码到这里就结束了,是不是很简单,欢迎各位大神指正,小弟刚学js,只因C#博文都没人赞,所以试试js看看。
试玩地址:点这里
尝试用canvas写小游戏的更多相关文章
- 尝试用React写几个通用组件 - 带搜索功能的下拉列表,开关切换按钮,弹出框
尝试用React写几个通用组件 - 带搜索功能的下拉列表,开关切换按钮,弹出框 近期正在逐步摸索学习React的用法,尝试着写几个通用型的组件,整体项目还是根据webpack+react+css-me ...
- JS写小游戏(一):游戏框架
前言 前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here. 概述 ...
- 用Canvas写桌球游戏!!!
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 昨天上班的时候闲着无事,就用Canvas写了个桌球游戏来玩玩....所以就拿这游戏上来水一发.或许对一些刚学canvas的人有帮助. 话说 ...
- 前端开发 | 尝试用Markdown写一下近几个月的总结
近期总结 回顾 半年前 半年前,接触了前端一年多(工作半年)的我了解的东西只有下面这些.因为在公司里的工作就是切静态页,捣鼓CMS. HTML (比较简洁的编写HTML) CSS/CSS3 (PC兼容 ...
- 用Canvas制作小游戏——贪吃蛇
今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...
- canvas入门级小游戏《开关灯》思路讲解
游戏很简单,10行10列布局,每行每列各10盏灯,游戏初始化时随机点亮其中一些灯,点击某盏灯,其上下左右的灯及本身状态反转,如果点击前是灭着的,点击后即点亮,将所有灯全部点亮才算过关.游戏试玩: 下面 ...
- 尝试用 Python 写了个病毒传播模拟程序
病毒扩散仿真程序,用 python 也可以. 概述 事情是这样的,B 站 UP 主 @ele 实验室,写了一个简单的疫情传播仿真程序,告诉大家在家待着的重要性,视频相信大家都看过了,并且 UP 主也放 ...
- 用原生js写小游戏--Flappy Bird
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- DOM+CSS3实现小游戏SwingCopters
前些日子看到了一则新闻,flappybird原作者将携新游戏SwingCopters来袭,准备再靠这款姊妹篇游戏引爆大众眼球.就是下面这个小游戏: 前者的传奇故事大家都有耳闻,至于这第二个游戏能否更加 ...
随机推荐
- 【AR实验室】ARToolKit之制作自己的Marker/NFT
0x00 - 前言 看过example后,就会想自己动动手,这里改改那里修修.我们先试着添加自己喜欢的marker/nft进行识别. 比如我做了一个法拉利的marker: 还有网上找了一个法拉利log ...
- JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...
- 前端框架 EasyUI (0) 重新温习(序言)
几年前,参与过一个项目.那算是一个小型的信息管理系统,BS 结构的,前端用的是基于 jQuery 的 EasyUI 框架. 我进 Team 的时候,项目已经进入开发阶段半个多月了.听说整个项目的框架是 ...
- Socket聊天程序——初始设计
写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答(问题A,问题B),那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了 ...
- 最新 去掉 Chrome 新标签页的8个缩略图
chrome的新标签页的8个缩略图实在让人不爽,网上找了一些去掉这个略缩图的方法,其中很多已经失效.不过其中一个插件虽然按照原来的方法已经不能用了,但是稍微变通一下仍然是可以用的(本方法于2017.1 ...
- 常见CSS与HTML使用误区
误区一.多div症 <div class="nav"> <ul> <li><a href="/home/"> ...
- 在线浏览PDF之PDF.JS (附demo)
平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html#skill 下载地址:http://mozilla.gith ...
- 实例操作JSONP原理
絮语:按这个步骤走,你就会明白JSONP是什么鬼. 1.工程目录: ng-mywork demo.html test.js 2.nginx的server配置 server { listen ; ser ...
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...
- ubuntu15 coreclr
看了很多文章心里痒痒,也下载个ubuntu想发布个asp.net5试试,自然是下载的最新版本15.结果涉及dnu restore,dnx...什么的都没反应,切换为mono就正常,奇怪了,按说core ...