前言
前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here.
概述
一般,小游戏都要关注两个问题:刷新和交互。因为游戏一般是动态的,所以需要不断刷新。JavaScript是单线程,如果用C语言写过贪吃蛇之类的小游戏,应该知道,单线程一般是挂起一个时间来达到动态效果。比如C语言的Sleep(),JS的setInterval()等。但是js还有一种更高性能的方法requestAnimationFrame。可以在网上找些资料进行学习,在此不做赘述。另一个就是交互,即用户需要通过鼠标、键盘控制游戏,从编程角度来书就是要添加对应事件的监听器。
以下,正式开始。
HTML5
先创建一个canvas画布:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Rembound.com Example</title> 6 <script type="text/javascript" src="script.js"></script> 7 </head> 8 <body> 9 <canvas id="viewport" width="640" height="480"></canvas> 10 </body> 11 </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
注:这只是众多小游戏合集中的一个,今后会继续添加。
时间: 2024-10-25 08:52:53