本节教程通过一个简略的游戏小例子,解说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 loadedwindow.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; } }
这是通过根本框架和一些批改而成的最终游戏。单击方块以减少您的分数并后退到下一个方块。