共计 5498 个字符,预计需要花费 14 分钟才能阅读完成。
本节教程通过一个简略的游戏小例子,解说 Canvas 的基础知识。
最终成果:
点击挪动的方块,方块上的分数会减少,方块的前进方向会扭转,并且方块的速度会减少。
在线演示
源码
HTML5 引入了 canvas 元素。canvas 元素为咱们提供了一块空白画布。咱们能够应用此画布来绘制和绘制咱们想要的任何货色。JavaScript 为咱们提供了动静制作动画并绘制到画布上所需的工具。它不仅提供绘图和动画零碎,还能够解决用户交互。在本教程中,咱们将应用纯 JavaScript 制作根本的 HTML5 Canvas 框架,该框架可用于制作实在的游戏。在本教程的结尾创立了一个非常简单的游戏,以演示 HTML5 Canvas 与 JavaScript 联合的劣势。
HTML5 Canvas 根本游戏框架
让咱们围绕 canvas 元素创立一个根本的游戏框架。咱们须要一个 HTML5 文件和一个 JavaScript 文件。HTML5 文件应蕴含 canvas 元素和对 JavaScript 文件的援用。JavaScript 文件蕴含将代码绘制到 canvas 元素的代码。
这是 HTML5 文件 index.html:
<head>
<meta charset="UTF-8">
<title>Canvas Example</title>
<script type="text/javascript" src="framework.js"></script>
</head>
<body>
<canvas id="viewport" width="640" height="480"></canvas>
</body>
</html>
如您所见,JavaScript 文件 game.js 蕴含在 html 文件的头部。画布元素以名称“viewport”定义,其宽度为 640 像素,高度为 480 像素。在咱们的 framework.js 中,咱们须要应用其名称查找 canvas 元素,以便能够在其上进行绘制。咱们正在创立的框架应反对渲染循环以及玩家与鼠标的交互。对于渲染循环,咱们将应用 Window.requestAnimationFrame()。通过增加鼠标事件侦听器来启用鼠标交互。
这是 JavaScript 文件 framework.js:
// The function gets called when the window is fully loaded
window.onload = function() {
// Get the canvas and context
var canvas = document.getElementById("viewport");
var context = canvas.getContext("2d");
// Timing and frames per second
var lastframe = 0;
var fpstime = 0;
var framecount = 0;
var fps = 0;
// Initialize the game
function init() {
// Add mouse events
canvas.addEventListener("mousemove", onMouseMove);
canvas.addEventListener("mousedown", onMouseDown);
canvas.addEventListener("mouseup", onMouseUp);
canvas.addEventListener("mouseout", onMouseOut);
// Enter main loop
main(0);
}
// Main loop
function main(tframe) {
// Request animation frames
window.requestAnimationFrame(main);
// Update and render the game
update(tframe);
render();}
// Update the game state
function update(tframe) {var dt = (tframe - lastframe) / 1000;
lastframe = tframe;
// Update the fps counter
updateFps(dt);
}
function updateFps(dt) {if (fpstime > 0.25) {
// Calculate fps
fps = Math.round(framecount / fpstime);
// Reset time and framecount
fpstime = 0;
framecount = 0;
}
// Increase time and framecount
fpstime += dt;
framecount++;
}
// Render the game
function render() {
// Draw the frame
drawFrame();}
// Draw a frame with a border
function drawFrame() {
// Draw background and a border
context.fillStyle = "#d0d0d0";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#e8eaec";
context.fillRect(1, 1, canvas.width-2, canvas.height-2);
// Draw header
context.fillStyle = "#303030";
context.fillRect(0, 0, canvas.width, 65);
// Draw title
context.fillStyle = "#ffffff";
context.font = "24px Verdana";
context.fillText("HTML5 Canvas Basic Framework", 10, 30);
// Display fps
context.fillStyle = "#ffffff";
context.font = "12px Verdana";
context.fillText("Fps:" + fps, 13, 50);
}
// Mouse event handlers
function onMouseMove(e) {}
function onMouseDown(e) {}
function onMouseUp(e) {}
function onMouseOut(e) {}
// Get the mouse position
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)
};
}
// Call init to start the game
init();};
下面的代码绘制了一个带有边框,题目和每秒帧数的简略框架。这是代码生成的内容
带有弹跳方块的游戏
当初咱们有了一个框架,让咱们用它创立一个简略的游戏。咱们将创立一个在屏幕上具备反弹方块的游戏。当玩家单击它时,方块上的分数会减少,方块的前进方向会扭转,并且方块的速度会减少。
首先,咱们定义一些对象和属性。该级别定义了方块能够反弹的区域。方块自身具备地位,尺寸和静止属性。最初,有一个分数。
// Level properties
var level = {
x: 1,
y: 65,
width: canvas.width - 2,
height: canvas.height - 66
};
// Square
var square = {
x: 0,
y: 0,
width: 0,
height: 0,
xdir: 0,
ydir: 0,
speed: 0
}
// Score
var score = 0;
咱们须要在 init()函数中初始化对象和属性。
// Initialize the game
function init() {
// Add mouse events
canvas.addEventListener("mousemove", onMouseMove);
canvas.addEventListener("mousedown", onMouseDown);
canvas.addEventListener("mouseup", onMouseUp);
canvas.addEventListener("mouseout", onMouseOut);
// Initialize the square
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;
// Initialize the score
score = 0;
// Enter main loop
main(0);
}
这些对象须要更新,因而让咱们批改 update()函数。方块须要挪动,并且应该检测并解决与标高边缘的碰撞。
// Update the game state
function update(tframe) {var dt = (tframe - lastframe) / 1000;
lastframe = tframe;
// Update the fps counter
updateFps(dt);
// Move the square, time-based
square.x += dt * square.speed * square.xdir;
square.y += dt * square.speed * square.ydir;
// Handle left and right collisions with the level
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;
}
// Handle top and bottom collisions with the level
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()函数中实现。
// Render the game
function render() {
// Draw the frame
drawFrame();
// Draw the square
context.fillStyle = "#ff8080";
context.fillRect(square.x, square.y, square.width, square.height);
// Draw score inside the square
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);
}
最初一步是增加鼠标交互。让咱们将代码增加到 onMouseDown()函数中。
function onMouseDown(e) {
// Get the mouse position
var pos = getMousePos(canvas, e);
// Check if we clicked the square
if (pos.x >= square.x && pos.x < square.x + square.width &&
pos.y >= square.y && pos.y < square.y + square.height) {
// Increase the score
score += 1;
// Increase the speed of the square by 10 percent
square.speed *= 1.1;
// Give the square a random position
square.x = Math.floor(Math.random()*(level.x+level.width-square.width));
square.y = Math.floor(Math.random()*(level.y+level.height-square.height));
// Give the square a random direction
square.xdir = Math.floor(Math.random() * 2) * 2 - 1;
square.ydir = Math.floor(Math.random() * 2) * 2 - 1;
}
}
这是通过根本框架和一些批改而成的最终游戏。单击方块以减少您的分数并后退到下一个方块。