Canvas学习实践:一款简单的动画游戏
最近学习了下Canvas绘图。。。突发奇想就有了下面这款简单的小游戏,纯属娱乐~
废话不多说,直接上代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>小怪兽吃豆豆</title>
<style>
#canvas { border: 1px solid #aaaaaa; display: block; margin: 20px auto; }
#score {text-align: center;position: relative;left: -565px;font-size: 24px;color: green; }
#title { display: block; margin: 10px auto; }
</style>
</head>
<body>
<div id="canvas-warp">
<canvas id="title"></canvas>
<div id="score">得分: 0</div>
<canvas id="canvas">
你的浏览器居然不支持Canvas?!赶快换一个吧!!
</canvas>
</div> <script>
setTitle();
var width = 1200, height = 600, //画布大小
x = 400, y = 300, //小怪兽圆心坐标
r = 30, //小怪兽半径
r1 = 10, //豆豆半径
speed = 5, //小怪兽移动速度(px)
direction = 'right', //小怪兽当前移动方向
ddList = [], //存储画布当前所有豆豆
score = 0; //分数
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
//绘制背景画布
drawCanvas(context);
//随机生成5个豆豆
randomCircle();
drawCircle(context);
//生成小怪兽
drawRole(context);
//定时生成豆豆
var timer = setInterval(function(){
if(ddList.length > 100) {
clearInterval(timer);
alert('Game over!!!');
return;
}
clearCanvas(context);
drawCanvas(context); randomCircle();
drawCircle(context); drawRole(context);
}, 10000)
//定义键盘方向键事件
document.onkeydown = function(e) {
if(ddList.length > 100) {
clearInterval(timer);
alert('Game over!!!');
return;
}
e = e || window.event;
e.preventDefault();
switch(e.keyCode) {
case 37: //左
direction = 'left';
if(x > r) { x = x - speed; }
break;
case 38: //上
direction = 'up';
if(y > r) { y = y - speed; }
break;
case 39: //右
direction = 'right';
if(x < width - r) { x = x + speed; }
break;
case 40: //下
direction = 'down';
if(y < height - r) { y = y + speed; }
break;
}
//吃掉豆豆简单算法
for(var i = 0; i < ddList.length; i++) {
if((Math.abs(ddList[i].y - y) <= 2*r1 && Math.abs(ddList[i].x - x) <= r1)
|| (Math.abs(ddList[i].x - x) <= 2*r1 && Math.abs(ddList[i].y - y) <= r1)) {
ddList.splice(i, 1);
score++;
break;
}
}
clearCanvas(context);
drawCanvas(context);
drawCircle(context);
drawRole(context);
//刷新得分
document.getElementById('score').innerText = '得分: ' + score;
}
};
//绘制画布
function drawCanvas(context) {
context.fillStyle = "#000";
context.fillRect(0, 0, width, height);
}
//清除画布
function clearCanvas(context) {
context.clearRect(0, 0, width, height);
}
//一次随机生成5个豆豆
function randomCircle() {
for(var i = 0; i < 5; i++) {
var x0 = Math.floor(Math.random()*(width - r1));
x0 = x0 - x0%speed;
if(x0 < r1) { x0 = r1;}
var y0 = Math.floor(Math.random()*(height - r1));
y0 = y0 - y0%speed;
if(y0 < r1) { y0 = r1;}
ddList.push({x: x0, y: y0});
}
}
//重新绘制豆豆
function drawCircle(context) {
context.beginPath();
context.fillStyle = "yellow";
for(var i = 0; i < ddList.length; i++) {
context.moveTo(ddList[i].x, ddList[i].y);
context.arc(ddList[i].x, ddList[i].y, r1, 0*Math.PI, 2*Math.PI);
}
context.fill();
}
//绘制小怪兽
function drawRole(context) {
if(direction == 'right') {
drawRightRole(context);
}else if(direction == 'left') {
drawLeftRole(context);
}else if(direction == 'up') {
drawUpRole(context);
}else {
drawDownRole(context);
}
}
//向右走小怪兽
function drawRightRole(context) {
context.lineWidth = 2;
context.strokeStyle = "red"; context.beginPath();
context.arc(x, y, r, 0.2*Math.PI, 1.8*Math.PI);
context.lineTo(x, y);
var x0 = x + parseFloat(r * Math.cos(0.2*Math.PI).toFixed(2));
var y0 = y + parseFloat(r * Math.sin(0.2*Math.PI).toFixed(2));
context.lineTo(x0, y0); context.stroke(); context.beginPath();
var offsetx = parseFloat(0.5*r * Math.cos(0.2*Math.PI).toFixed(2));
var offsety = parseFloat(0.5*r * Math.sin(0.2*Math.PI).toFixed(2));
context.moveTo(x + offsetx, y + offsety);
context.quadraticCurveTo(x, y + 0.6*r, x - offsetx, y + offsety);
context.stroke(); context.beginPath();
context.arc(x, y - 0.5*r, 5, 0*Math.PI, 2*Math.PI);
context.stroke();
}
//向左走小怪兽
function drawLeftRole(context) {
context.lineWidth = 2;
context.strokeStyle = "red"; context.beginPath();
context.arc(x, y, r, 1.2*Math.PI, 0.8*Math.PI);
context.lineTo(x, y);
var x0 = x - parseFloat(r * Math.cos(0.2*Math.PI).toFixed(2));
var y0 = y - parseFloat(r * Math.sin(0.2*Math.PI).toFixed(2));
context.lineTo(x0, y0); context.stroke(); context.beginPath();
var offsetx = parseFloat(0.5*r * Math.cos(0.2*Math.PI).toFixed(2));
var offsety = parseFloat(0.5*r * Math.sin(0.2*Math.PI).toFixed(2));
context.moveTo(x + offsetx, y + offsety);
context.quadraticCurveTo(x, y + 0.6*r, x - offsetx, y + offsety);
context.stroke(); context.beginPath();
context.arc(x, y - 0.5*r, 5, 0*Math.PI, 2*Math.PI);
context.stroke();
}
//向上走小怪兽
function drawUpRole(context) {
context.lineWidth = 2;
context.strokeStyle = "red"; context.beginPath();
context.arc(x, y, r, 1.7*Math.PI, 1.3*Math.PI);
context.lineTo(x, y);
var x0 = x + parseFloat(r * Math.sin(0.2*Math.PI).toFixed(2));
var y0 = y - parseFloat(r * Math.cos(0.2*Math.PI).toFixed(2));
context.lineTo(x0, y0); context.stroke(); context.beginPath();
var offsetx = parseFloat(0.5*r * Math.sin(0.2*Math.PI).toFixed(2));
var offsety = parseFloat(0.5*r * Math.cos(0.2*Math.PI).toFixed(2));
context.moveTo(x + offsetx, y + offsety);
context.quadraticCurveTo(x + 0.6*r, y, x + offsetx, y - offsety);
context.stroke(); context.beginPath();
context.arc(x - 0.5*r, y, 5, 0*Math.PI, 2*Math.PI);
context.stroke();
}
//向下走小怪兽
function drawDownRole(context) {
context.lineWidth = 2;
context.strokeStyle = "red"; context.beginPath();
context.arc(x, y, r, 0.7*Math.PI, 0.3*Math.PI);
context.lineTo(x, y);
var x0 = x - parseFloat(r * Math.sin(0.2*Math.PI).toFixed(2));
var y0 = y + parseFloat(r * Math.cos(0.2*Math.PI).toFixed(2));
context.lineTo(x0, y0); context.stroke(); context.beginPath();
var offsetx = parseFloat(0.5*r * Math.sin(0.2*Math.PI).toFixed(2));
var offsety = parseFloat(0.5*r * Math.cos(0.2*Math.PI).toFixed(2));
context.moveTo(x - offsetx, y + offsety);
context.quadraticCurveTo(x - 0.6*r, y, x - offsetx, y - offsety);
context.stroke(); context.beginPath();
context.arc(x + 0.5*r, y, 5, 0*Math.PI, 2*Math.PI);
context.stroke();
}
//设置标题
function setTitle() {
var canvas = document.getElementById("title");
canvas.width = 600;
canvas.height = 100;
var context = canvas.getContext("2d"); //绘制背景画布
context.fillStyle = "#fff";
context.fillRect(0,0,600,100); context.font = "italic bolder 50px serif"; //设置字体 //设置渐变色
var grd = context.createLinearGradient(150,50,450,50);
grd.addColorStop(0,"green");
grd.addColorStop(0.8,"red");
context.fillStyle = grd; context.textAlign = "center"; //文本的中心被放置在指定的位置。
context.textBaseline="middle"; //文本基线是 em 方框的正中。 context.globalAlpha = 0.5; //透明度 context.fillText("小怪兽吃豆豆",300,50); //显示填充文本
context.strokeText("小怪兽吃豆豆",300,50); //显示描边文本
} </script>
</body>
</html>
复制代码到.html文件,直接浏览器打开,用键盘方向键控制移动,游戏界面如下图所示:

学习资料:
1、https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API
2、http://caibaojian.com/canvas/
Canvas学习实践:一款简单的动画游戏的更多相关文章
- ReactNative学习实践--动画初探之加载动画
学习和实践react已经有一段时间了,在经历了从最初的彷徨到解决痛点时的兴奋,再到不断实践后遭遇问题时的苦闷,确实被这一种新的思维方式和开发模式所折服,react不是万能的,在很多场景下滥用反而会适得 ...
- canvas学习之制作动画
html部分 ...... <body> <canvas id="myCanvas" width="400" height="400 ...
- Appium学习实践(二)Python简单脚本以及元素的属性设置
1.简单的Python脚本 Appium中的设置与Appium学习实践(一)简易运行Appium中的一致 Launch后,执行脚本 #coding:utf-8 import unittest impo ...
- 带着canvas去流浪系列之九 粒子动画【华为云技术分享】
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...
- canvas学习之API整理笔记(二)
前面我整理过一篇文章canvas学习之API整理笔记(一),从这篇文章我们已经可以基本了解到常用绘图的API.简单的变换和动画.而本篇文章的主要内容包括高级动画.像素操作.性能优化等知识点,讲解每个知 ...
- Canvas 最佳实践(性能篇)
Canvas 想必前端同学们都不陌生,它是 HTML5 新增的「画布」元素,允许我们使用 JavaScript 来绘制图形.目前,所有的主流浏览器都支持 Canvas. Canvas 最常见的用途是渲 ...
- canvas学习和面向对象(二)
Canvas 学习(二) 上一篇Canvas 学习(一)中我是用canvas绘制了一些基本和组合的图形. 现在开始绘制图片和动画帧,以及面向对象的升级版本. 还是一样,看代码,所有的代码都托管在git ...
- ReactNative学习实践--Navigator实践
离上次写RN笔记有一段时间了,期间参与了一个新项目,只在最近的空余时间继续学习实践,因此进度比较缓慢,不过这并不代表没有新进展,其实这个小东西离上次发文时已经有了相当大的变化了,其中影响最大的变化就是 ...
- 推荐一款简单易用线上引流测试工具:GoReplay
一. 引流测试产生背景 日常大部分的测试工作都是在测试环境下,通过模拟用户的行为来对系统进行验证,包括功能以及性能.在这个过程中,你可能会遇到以下问题: 用户访问行为比较复杂,模拟很难和用户行为一致, ...
随机推荐
- 显示调用dll
原dll中导出的接口如图: Head.h: struct zint_render_line { float x, y, length, width; struct zint_render_line * ...
- python 类的创建
- laravel 项目本地版本为5.5,线上mysql 为5.7.21版本,执行严格模式
看到网上很多说修改 但是在mysql 5.7中没有这个参数设置,故放弃: 结合本项目sina_id 10位超过int的最大范围4294967295,所以报错,修改为bigint 即可.
- 中文乱码在java中URLEncoder.encode方法要调用两次解决
中文乱码在java中URLEncoder.encode方法要调用两次解决 一.场景: 1.我在客户端要通过get方式调用服务器端的url,将中文参数做utf-8编码,需要在js中两次的进行编码,服务器 ...
- 【Leetcode链表】环形链表(141)
题目 给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1,则在该链表中没有环. 示例 1: ...
- UVa 495【大数加法】
UVa 495 求第n位斐波那契数列,n<=5000. 还是大数问题,这次是大数加法.仿照UVa 623的解法来做.623位数可以一位一位的增,但是这个需要预先给够位数,要是按六位存一个数组元素 ...
- WPF疑难杂症之二(全屏幕窗口)
原文:WPF疑难杂症之二(全屏幕窗口) 近日的学习中遇到一个非常奇怪的问题:用XAML文件创建了一个全屏幕窗口,然后,在窗口中建立了一个非常简单的动画.一切都在我的掌控之中,实现非常的顺利. WPF中 ...
- 洞见数据库前沿 阿里云数据库最强阵容 DTCC 2019 八大亮点抢先看
摘要: 作为DTCC的老朋友和全球领先的云计算厂商,阿里云数据库团队受邀参加本次技术盛会,不仅将派出重量级嘉宾阵容,还会为广大数据库业内人士和行业用户奉上8场精彩议题.下面小编就为大家提前梳理了8大亮 ...
- 模板—FFT
卷积:$C[i]=\sum \limits_{j=0}^{i}A[j]*B[i-j]$可以画图理解一下其实就是交叉相乘的和. 卷积可以看作两个多项式乘积的形式,只不过求出的结果的项数不同. FFT讲解 ...
- 谈一谈Python的上下文管理器
经常在Python代码中看到with语句,仔细分析下,会发现这个with语句功能好强,可以自动关闭资源.这个在Python中叫上下文管理器Context Manager.那我们要怎么用它,什么时候用它 ...