JS写小游戏(一):游戏框架
前言
前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here.
概述
一般,小游戏都要关注两个问题:刷新和交互。因为游戏一般是动态的,所以需要不断刷新。JavaScript是单线程,如果用C语言写过贪吃蛇之类的小游戏,应该知道,单线程一般是挂起一个时间来达到动态效果。比如C语言的Sleep(),JS的setInterval()等。但是js还有一种更高性能的方法requestAnimationFrame。可以在网上找些资料进行学习,在此不做赘述。另一个就是交互,即用户需要通过鼠标、键盘控制游戏,从编程角度来书就是要添加对应事件的监听器。
以下,正式开始。
HTML5
先创建一个canvas画布:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rembound.com Example</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<canvas id="viewport" width="640" height="480"></canvas>
</body>
</html>
JS
添加以下基本代码,代码详情可以看注释,最好单步调试加深理解:
//窗口加载完成后调用
window.onload = function() {
// 获取画布及context(上下文)
var canvas = document.getElementById("viewport");
var context = canvas.getContext("2d"); // 记录时间帧,这个最好通过单步调试来理解
var lastframe = 0;
var fpstime = 0;
var framecount = 0;
var fps = 0; // 初始化游戏,添加鼠标的监听事件
function init() {
canvas.addEventListener("mousemove", onMouseMove);
canvas.addEventListener("mousedown", onMouseDown);
canvas.addEventListener("mouseup", onMouseUp);
canvas.addEventListener("mouseout", onMouseOut); // 进入游戏主循环
main(0);
} // 主循环
function main(tframe) {
// 结束时继续调用main函数
window.requestAnimationFrame(main); // 更新游戏
update(tframe);
render();
} // 更新游戏状态,计算已经过去了的时间
function update(tframe) {
var dt = (tframe - lastframe) / 1000;
lastframe = tframe; //更新帧数计数器
updateFps(dt);
} function updateFps(dt) {
if (fpstime > 0.25) {
//计算帧数
fps = Math.round(framecount / fpstime); //重置时间
fpstime = 0;
framecount = 0;
} //增加帧时间、帧数
fpstime += dt;
framecount++;
} // 渲染(更新画布)
function render() {
drawFrame();
} //
function drawFrame() {
// 背景、边界
context.fillStyle = "#d0d0d0";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#e8eaec";
context.fillRect(1, 1, canvas.width-2, canvas.height-2); // 标题头
context.fillStyle = "#303030";
context.fillRect(0, 0, canvas.width, 65); // 标题
context.fillStyle = "#ffffff";
context.font = "24px Verdana";
context.fillText("HTML5 Canvas Basic Framework - Rembound.com", 10, 30); // 显示帧数
context.fillStyle = "#ffffff";
context.font = "12px Verdana";
context.fillText("Fps: " + fps, 13, 50);
} //鼠标监听
function onMouseMove(e) {}
function onMouseDown(e) {}
function onMouseUp(e) {}
function onMouseOut(e) {} // 获取鼠标位置
function getMousePos(canvas, e) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.round((e.clientX - rect.left)/(rect.right - rect.left)*canvas.width),
y: Math.round((e.clientY - rect.top)/(rect.bottom - rect.top)*canvas.height)
};
} // 游戏入口
init();
};
效果:

添加游戏元素
以上就是一个通用的游戏框架了,虽然它在不断刷新,但是没什么直观感受,以下建立一个简单游戏来感受一下:
......
var framecount = 0;
var fps = 0; // 游戏平面
var level = {
x: 1,
y: 65,
width: canvas.width - 2,
height: canvas.height - 66
}; // 小方块
var square = {
x: 0,
y: 0,
width: 0,
height: 0,
xdir: 0,
ydir: 0,
speed: 0
} // 分数
var score = 0; // 初始化游戏,添加鼠标的监听事件
function init() {
....
在init()函数中添加:
....
canvas.addEventListener("mouseout", onMouseOut);
// 初始化方块
square.width = 100;
square.height = 100;
square.x = level.x + (level.width - square.width) / 2;
square.y = level.y + (level.height - square.height) / 2;
square.xdir = 1;
square.ydir = 1;
square.speed = 200; // 初始化分数
score = 0; // 进入游戏主循环
main(0);
....
在update()函数中更新方块
....
//更新帧数计数器
updateFps(dt); // 基于时间移动方块
square.x += dt * square.speed * square.xdir;
square.y += dt * square.speed * square.ydir; // 处理碰撞
if (square.x <= level.x) {
// Left edge
square.xdir = 1;
square.x = level.x;
} else if (square.x + square.width >= level.x + level.width) {
// Right edge
square.xdir = -1;
square.x = level.x + level.width - square.width;
} if (square.y <= level.y) {
// Top edge
square.ydir = 1;
square.y = level.y;
} else if (square.y + square.height >= level.y + level.height) {
// Bottom edge
square.ydir = -1;
square.y = level.y + level.height - square.height;
}
...
render()函数中还要渲染方块
....
// 绘制方块
context.fillStyle = "#ff8080";
context.fillRect(square.x, square.y, square.width, square.height); // 绘制内部
context.fillStyle = "#ffffff";
context.font = "38px Verdana";
var textdim = context.measureText(score);
context.fillText(score, square.x+(square.width-textdim.width)/2, square.y+65);
...
添加鼠标事件
function onMouseDown(e) {
// 获取鼠标位置
var pos = getMousePos(canvas, e);
// 检查是否碰到了方块
if (pos.x >= square.x && pos.x < square.x + square.width &&
pos.y >= square.y && pos.y < square.y + square.height) {
// 增加分数
score += 1;
// 增加速度
square.speed *= 1.1;
// 随机给一个新的位置
square.x = Math.floor(Math.random()*(level.x+level.width-square.width));
square.y = Math.floor(Math.random()*(level.y+level.height-square.height));
// 随机方向
square.xdir = Math.floor(Math.random() * 2) * 2 - 1;
square.ydir = Math.floor(Math.random() * 2) * 2 - 1;
}
}
效果

完整源代码:Click Here
注:这只是众多小游戏合集中的一个,今后会继续添加。
JS写小游戏(一):游戏框架的更多相关文章
- 用JS写了一个打字游戏,反正我是通不了关
今天想写个简单的游戏, 打字游戏好像都没写过, 那么就写打字游戏吧, gamePad包含了关卡的信息, 可以用来调整给个关卡字符下落的速度: getRandom函数会返回一个字符对象, 这个对象包含了 ...
- 用原生js写小游戏--Flappy Bird
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 这个程序员有点牛,现场直接用JS写了个飞机游戏,半小时吸粉三千
程序员昨晚在b站直播的时用JavaScript代码写了一个飞机大战游戏,半小时不到粉丝关注就上千了. 今日就拿出来跟大家分享一下,对许多大佬来说做这个特效也不是很难,但是对于刚开始学习前端这方面还是有 ...
- 快速上手小程序的mpvue框架
一.什么是mpvue框架? mpvue 是一个使用 Vue.js 开发小程序的前端框架.框架基于 Vue.js 核心(所以建议熟练掌握vue再使用mpvue框架,否则还是建议去使用原生框架去写小程序) ...
- 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”
这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...
- pixi.js 微信小游戏 入手
pixi是什么?一款h5游戏引擎 优点:简单简洁性能第一 缺点:大多数用的国产三大引擎,pixi资料少,工具少, 为什么学,装逼 用pixi开发小游戏行吗? 行.但要简单处理下 下载官网上的 weap ...
- 原生JS实战:写了个斗牛游戏,分享给大家一起玩!
本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5869953.html 该程序是本人的个人作品,写的不好,未经本人允许,请 ...
- 排名前10的H5、Js 3D游戏引擎和框架
由于很多人都在用JavaScript.HTML5和WebGL技术创建基于浏览器的3D游戏,所有JavaScript 3D游戏引擎是一个人们主题.基于浏览器的游戏最棒的地方是平台独立,它们能在iOS.A ...
- 原生js写的贪吃蛇网页版游戏特效
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <bo ...
随机推荐
- fillStyle径向渐变
<!DOCTYPE HTML> <head> <meta charset = "utf-8"> <title>canvas</ ...
- yii2分页的基本使用及其配置详解
作者:白狼 出处:http://www.manks.top/yii2_linkpager_pagination.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...
- Java源码分析之LinkedList
LinkedList与ArrayList正好相对,同样是List的实现类,都有增删改查等方法,但是实现方法跟后者有很大的区别. 先归纳一下LinkedList包含的API 1.构造函数: ①Linke ...
- sql monitor生成不了报告& FFS hint不生效两个问题思考
事情的发生就是这么偶然,一步步的深入才能汲取到更深入的知识~~ -------------------START------------------------------------------- ...
- db2start启动失败
db2start启动失败 [db2inst1@localhost ~]$ db2start db2start: error while loading shared libraries: libaio ...
- StarkSoft题库管理系统(二)--生成word格式试卷
一.功能介绍 1.自定义试题库管理系统目录.难易程度,题型,知识库等. 2.试题录入. 3.强大的试题编辑功能,并与通常应用编辑工具有共通. 4.灵活的试卷构造功能,用户可自定 ...
- [Java入门笔记] 面向对象编程基础(三):成员变量和局部变量
在类中,变量根据定义的位置不同,可以分为成员变量和局部变量.
- C语言调用curl库抓取网页图片
思路是先用curl抓取网页源码,然后以关键字寻找出图片网址. #include <stdio.h> #include <stdlib.h> #include <str ...
- HttpUrlConnection 的 setDoOutput 与 setDoInput
1 前言 在使用java中的HttpUrlConnection请求一个http网络地址时,我们有时候需要用到此类中的setDoOutput和setDoInput这两个方法,以前学习java的时候,根本 ...
- 双11遇上ZBrushCore,如此优惠还等什么!
对不起!让大家久等了,ZBrush简体中文版ZBrushCore这次是真的来了,恰逢双11,老板说了,钱不是问题,你们开心就好,特别是热爱3D的单身狗们!你们那么热爱这个行业,1099元/套终身授权使 ...