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 ...
随机推荐
- php面向对象编程 设计模式
面向对象编程的基本原则: 单一职责:一个类,只需要做好一件事 开放封闭:一个类,应该是可扩展的,而不是可修改的 依赖倒置:一个类,不应该强依赖另一个类.每个类对应另外一个类都是可替换的 配置化:尽可能 ...
- 125个工具与技术(PMBOK2008)
名称 定义 适用场景 适用过程 专家判断 对某方面擅长的人就是专家,找专家协助就是专家判断,专家可能是顾问.干系人.PMO.团队成员 制定项目章程.制定项目管理计划.指导与管理项目执行.监控项目工作. ...
- String.Empty、null、“” 区别
概念准备: 1.引用类型是将对象是实际数据保存在堆中, 将对象在堆中的地址保存在栈中. 2.值类型直接将实际数据存放在堆中,不会将对象在堆中的地址保存在栈中. 一.String.Empty和" ...
- Write on ……… failed: 112(failed to retrieve text for this error. Reason: 15105)
早上检查数据库的备份邮件时,发现一台Microsoft SQL Server 2008 R2 (SP2)数据库的Maintenance Report有错误 在SSMS里面执行Exec YourSQLD ...
- SQL SERVER中的OLEDB等待事件
OLEDB等待事件介绍 OLEDB等待类型是SQL SERVER 数据库中最常见的几种等待类型之一.它意味着某个会话(SPID)通过SQL Server Native Client OLEDB Pro ...
- 【hive】——Hive sql语法详解
Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件映射为一张数据库表,并提供完整的SQL查 ...
- mapreduce导出MSSQL的数据到HDFS
今天想通过一些数据,来测试一下我的<基于信息熵的无字典分词算法>这篇文章的正确性.就写了一下MapReduce程序从MSSQL SERVER2008数据库里取数据分析.程序发布到hadoo ...
- Spark调度管理(读书笔记)
Spark调度管理(读书笔记) 转载请注明出处:http://www.cnblogs.com/BYRans/ Spark调度管理 本文主要介绍在单个任务内Spark的调度管理,Spark调度相关概念如 ...
- [Java入门笔记] Java语言基础(二):常量、变量与数据类型
常量与变量 什么是常量和变量 常量与变量都是程序在运行时用来存储数据一块内存空间 常量: 常量的值在程序运行时不能被改变,Java中声明常量必须使用final关键字.常量还可以分为两种意思: 第1种意 ...
- shell统计指定范围内的所有质数以及它们的和
#!bin/bash a= $) ;do n= $x);do ];then n=$[$n+] fi done ];then { echo -n -e "$x\t" sum=$[$s ...