最近学习了下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学习实践:一款简单的动画游戏的更多相关文章

  1. ReactNative学习实践--动画初探之加载动画

    学习和实践react已经有一段时间了,在经历了从最初的彷徨到解决痛点时的兴奋,再到不断实践后遭遇问题时的苦闷,确实被这一种新的思维方式和开发模式所折服,react不是万能的,在很多场景下滥用反而会适得 ...

  2. canvas学习之制作动画

    html部分 ...... <body> <canvas id="myCanvas" width="400" height="400 ...

  3. Appium学习实践(二)Python简单脚本以及元素的属性设置

    1.简单的Python脚本 Appium中的设置与Appium学习实践(一)简易运行Appium中的一致 Launch后,执行脚本 #coding:utf-8 import unittest impo ...

  4. 带着canvas去流浪系列之九 粒子动画【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  5. canvas学习之API整理笔记(二)

    前面我整理过一篇文章canvas学习之API整理笔记(一),从这篇文章我们已经可以基本了解到常用绘图的API.简单的变换和动画.而本篇文章的主要内容包括高级动画.像素操作.性能优化等知识点,讲解每个知 ...

  6. Canvas 最佳实践(性能篇)

    Canvas 想必前端同学们都不陌生,它是 HTML5 新增的「画布」元素,允许我们使用 JavaScript 来绘制图形.目前,所有的主流浏览器都支持 Canvas. Canvas 最常见的用途是渲 ...

  7. canvas学习和面向对象(二)

    Canvas 学习(二) 上一篇Canvas 学习(一)中我是用canvas绘制了一些基本和组合的图形. 现在开始绘制图片和动画帧,以及面向对象的升级版本. 还是一样,看代码,所有的代码都托管在git ...

  8. ReactNative学习实践--Navigator实践

    离上次写RN笔记有一段时间了,期间参与了一个新项目,只在最近的空余时间继续学习实践,因此进度比较缓慢,不过这并不代表没有新进展,其实这个小东西离上次发文时已经有了相当大的变化了,其中影响最大的变化就是 ...

  9. 推荐一款简单易用线上引流测试工具:GoReplay

    一. 引流测试产生背景 日常大部分的测试工作都是在测试环境下,通过模拟用户的行为来对系统进行验证,包括功能以及性能.在这个过程中,你可能会遇到以下问题: 用户访问行为比较复杂,模拟很难和用户行为一致, ...

随机推荐

  1. java方法重写规则 重载

    方法的重写规则 参数列表必须完全与被重写方法的相同: 返回类型必须完全与被重写方法的返回类型相同: 访问权限不能比父类中被重写的方法的访问权限更低.例如:如果父类的一个方法被声明为public,那么在 ...

  2. PLAY2.6-SCALA(七) Streaming HTTP response

    1.从HTTP1.1开始,服务端为了在single connection下对HTTP请求及响应提供服务,需要在response中提供响应的Content-Length. 默认情况下,不需要显示的指明C ...

  3. HDU 4217

    点击打开题目链接 题型就是数据结构.给一个数组,然后又k次操作,每次操作给定一个数ki, 从数组中删除第ki小的数,要求的是k次操作之后被删除的所有的数字的和. 简单的思路就是,用1标记该数没有被删除 ...

  4. linux下清除tomcat缓存

    进入tomcat/bin目录下,执行命令:./shutdown.sh 然后执行命令:ps -aux ,查看tomcat是否真的关闭了 如果没有关闭则执行命令:kill -9 #pid来彻底关闭tomc ...

  5. 关于Apple Watch,听听开发了两个月Watch App的工程师怎么说

    今年1月份有幸应苹果邀请,秘密参与苹果 Watch App 的真机现场调试.4月份,Apple Watch 会正式上市.在这之前,也算是亲自抢先体验了 Apple Watch,以及开发了一下 Watc ...

  6. 开发者总结的WatchKit App提交技巧

    苹果4月初宣布所有注册开发者已经可以向App Store提交基于WatchKit开发的Apple Watch app了,不过不少开发者遇到了模拟器中没有发现的问题.这篇文章主要收集了一些提交tips和 ...

  7. Spark in action on Kubernetes - 存储篇(一)

    前言 在上篇文章中,我们分析了Spark Operator内部的机制,今天我们会讨论一个在大数据领域中最重要的话题 - 存储.大数据已经无声无息的融入了每个人的生活中.大到旅游买房,小到外卖打车,都可 ...

  8. 【C++】STL :栈

    c++stack(堆栈)是一个容器的改编,它实现了一个先进后出的数据结构(FILO) 使用该容器时需要包含#include<stack>头文件: 定义stack对象的示例代码如下: sta ...

  9. 文字渐变效果:图层中的mask属性

    http://www.cocoachina.com/ios/20150716/12571.html 前言 已经很久没写blog了,最近发生了太多事情,失去了生命中一位很重要的成员,使我不得不放下对技术 ...

  10. 【Objective-C】-空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储任何内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0. 下面两个都是空指针 ...