最近学习了下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. django其他

    聚合查询 聚合函数必须在分组之后使用 没有分组默认整体为一组 聚合函数 Max, Min, Sum, Avg, Count 从django.db.models 导入方法,然后使用关键字aggregat ...

  2. Directx11教程(66) D3D11屏幕文本输出(1)

    原文:Directx11教程(66) D3D11屏幕文本输出(1)      在D3D10中,通过ID3DX10Font接口对象,我们可以方便的在屏幕上输出文字信息,一个DrawText函数就能解决所 ...

  3. Directx11教程(18) D3D11管线(7)

    原文:Directx11教程(18) D3D11管线(7) 光栅化阶段(RS)之后,将进入PS/OM阶段. 参考外文资料:http://fgiesen.wordpress.com/2011/07/01 ...

  4. vue2-vux-fitness-project

    非常感谢那些无私开源的程序员,希望我也能够有能力像你们那样,开源很多很有意思的东西~~ //index.html <!DOCTYPE html> <html> <head ...

  5. hdu1730 尼姆博弈

    抽象一下把距离当做石子个数.虽然在这里石子个数可以增加,但是不管怎么增加,不会影响结果,因为你增加了,必须会有减少的. 所以类似取石子,观察平衡状态,如果(x2-x1-1)^...==0,必输. wa ...

  6. C++之加密机访问

    WininetHttp.h: #pragma once#include <iostream>#include <windows.h>#include <wininet.h ...

  7. json 2016-09-18 22:03 207人阅读 评论(18) 收藏

    JSON:JavaScript 对象表示法(JavaScript Object Notation) JSON是什么? JSON(JavaScript Object Notation) 是一种轻量级的数 ...

  8. Java练习 SDUT-4303_简单的复数运算(类和对象)

    简单的复数运算(类和对象) Time Limit: 2000 ms Memory Limit: 65536 KiB Problem Description 设计一个类Complex,用于封装对复数的下 ...

  9. C++复制初始化的限制

    相比于直接初始化,复制初始化有更加严格的限制. 1:在复制初始化时,不能使用声明为explicit的构造函数进行的隐式转换.而直接初始化则是允许的: struct Exp { explicit Exp ...

  10. 【转载】Combination Sum

    Combination Sum Given a set of candidate numbers (C) and a target number (T), find all unique combin ...