HTML5趣味台球案例

2015年03月05日 14:10 0 点赞 0 评论 更新于 2025-11-21 16:42

案例概述

本文将介绍一个基于 HTML5 Canvas 的撞球动画示例,其中包含碰撞检测功能。在演示过程中,页面上会始终显示 FPS(Frames Per Second,每秒帧数)相关信息,如 “FPS AVG: 84.61 CUR: 83.42 number:1” 等。该示例支持定义缓冲和无缓冲模式,点击 “buffer” 按钮后,页面上会出现多个小球进行无规则运动,当小球撞到画布边缘时会自动弹回。这个案例对于理解 HTML5 Canvas 的使用非常有帮助。

代码实现

HTML 部分

<!DOCTYPE HTML>
<html>
<title>html5 canvas 撞球实例 碰撞检测</title>
<body>
<div style="width:400px;margin:0 auto">
<canvas id="main" style="background-color:green;width:400px;height:400px"></canvas>
<div id="fps"></div>
<input type="button" value="stop" onclick="cancel()"/>
<input type="button" value="noBuffer" onclick="addCreatures(10)"/>
<input type="button" value="Buffer" id="buf"/>
</div>
</body>
</html>

在上述 HTML 代码中,我们创建了一个宽度和高度均为 400px 的绿色画布,用于展示撞球动画。同时,还添加了三个按钮,分别用于停止动画、添加无缓冲小球和触发缓冲功能。另外,有一个用于显示 FPS 信息的 div 元素。

JavaScript 部分

// 全局变量定义
var ctx;
var width;
var height;
var delta;
var lastTime;
var frames;
var totalTime;
var updateTime;
var updateFrames;
var creats = new Array();
var id;
var nobufferArr = [], bufferArr = [];

// 操作对象,用于处理缓冲相关逻辑
var manipulate = {
MAX: 300,
head: 0,
tail: 0,
history: [],
id: -1,
clickHander: function (e) {
this.history[this.head] = 1;
this.head = (this.head + 1 + this.MAX) % this.MAX;
},
init: function () {
// 初始化历史记录数组
for (var i = 0; i < 300; i++) {
this.history[i] = 0;
}
var that = this;
this.id = setInterval(function () {
var len = (that.head - that.tail + that.MAX) % that.MAX;
if (len > 0) {
for (var i = 0; i < len; i++) {
that.tail = that.tail % that.MAX;
if (that.history[that.tail] === 1) {
addCreatures(10);
that.history[that.tail] = 0;
if (that.head > 300) clearInterval(that.id);
}
that.tail++;
}
}
}, 0);
}
};

// 初始化操作对象
manipulate.init();

// 获取缓冲按钮元素并绑定点击事件
var buf = document.getElementById("buf");
buf.onclick = function (e) {
manipulate.clickHander(e);
};

// 停止动画函数
function cancel() {
if (id) clearInterval(id);
}

// 添加指定数量的小球函数
function addCreatures(count) {
for (var i = 0; i < count; i++) {
addCreature(i);
}
}

// 初始化函数
function init() {
var canvas = document.getElementById('main');
width = canvas.width = 400;
height = canvas.height = 400;
ctx = canvas.getContext('2d');
// 初始添加一个小球
for (var i = 0; i < 1; ++i) {
addCreature();
}
lastTime = (new Date()).getTime();
frames = 0;
totalTime = 0;
updateTime = 0;
updateFrames = 0;
// 每隔 10 毫秒更新一次动画
id = setInterval(update, 10);
}

// 延迟函数(未使用)
function delay(time) {
var st = new Date();
while (new Date() - st < time);
}

// 添加单个小球函数
function addCreature() {
var c = new Creature(Math.random() * 100, Math.random() * 200);
creats.push(c);
}

// 更新函数,用于更新动画状态和计算 FPS
function update() {
var now = (new Date()).getTime();
delta = now - lastTime;
lastTime = now;
totalTime += delta;
frames++;
updateTime += delta;
updateFrames++;
if (updateTime > 1000) {
document.getElementById('fps').innerHTML = "FPS AVG: " + (1000 * frames / totalTime).toFixed(2) + " CUR: " + (1000 * updateFrames / updateTime).toFixed(2) + " number:" + creats.length;
updateTime = 0;
updateFrames = 0;
}
// 移动所有小球
for (var i = 0; i < creats.length; ++i) {
creats[i].move();
}
draw();
}

// 绘制函数,用于清空画布并绘制所有小球
function draw() {
ctx.clearRect(0, 0, width, height);
creats.forEach(drawCreat);
}

// 绘制单个小球函数
function drawCreat(c, i, a) {
if (!onScreen(c)) {
return;
}
ctx.strokeStyle = "#FFFFFF";
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(c.x, c.y, 5, 0, Math.PI * 2, true);
ctx.closePath();
ctx.stroke();
ctx.fill();
}

// 判断小球是否在画布内的函数
function onScreen(o) {
return o.x >= 0 && o.y >= 0 && o.x <= width && o.y <= height;
}

// 小球构造函数
function Creature(x1, y) {
this.x = x1;
this.y = y;
this.dx = Math.random() * 2;
this.dy = Math.random() * 2;
this.move = function () {
this.x += this.dx;
this.y += this.dy;
// 碰撞检测,当小球撞到边缘时改变运动方向
if (this.x < 0 || this.x > width) {
this.dx *= -1;
}
if (this.y < 0 || this.y > height) {
this.dy *= -1;
}
};
}

// 初始化动画
init();

代码解释

  1. 全局变量:定义了一系列全局变量,用于存储画布上下文、画布尺寸、时间间隔、帧数等信息。
  2. 操作对象 manipulate:用于处理缓冲相关逻辑,通过 init 方法初始化历史记录数组,并使用 setInterval 定时检查是否需要添加小球。
  3. cancel 函数:用于停止动画,通过清除定时器实现。
  4. addCreatures 函数:用于添加指定数量的小球。
  5. init 函数:初始化画布、添加初始小球,并设置定时器以更新动画。
  6. update 函数:更新动画状态,计算 FPS 信息,并调用 draw 函数进行绘制。
  7. draw 函数:清空画布并绘制所有小球。
  8. drawCreat 函数:绘制单个小球。
  9. onScreen 函数:判断小球是否在画布内。
  10. Creature 构造函数:定义小球的属性和移动方法,包含碰撞检测逻辑。

通过以上代码和解释,你可以深入理解这个 HTML5 趣味台球案例的实现原理,并且可以根据自己的需求进行扩展和修改。

作者信息

boke

boke

共发布了 3994 篇文章