范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

教你用ECharts轻松做一个FlappyBird小游戏

  本文分享自华为云社区《没想到吧!这个可可爱爱的游戏居然是用 ECharts 实现的!-云社区-华为云》,作者:DevUI。前言
  echarts是一个很强大的图表库,除了我们常见的图表功能,echarts有一个自定义图形的功能,这个功能可以让我们很简单地在画布上绘制一些非常规的图形,基于此,我们来玩一些花哨的。
  Flappy Bird小游戏体验地址(看看你能玩几分):
  foolmadao.github.io/echart-flap…
  下面我们来一步步实现他。1 在坐标系中画一只会动的小鸟
  首先实例化一个echart容器,再从网上找一个像素小鸟的图片,将散点图的散点形状,用自定义图片的方式改为小鸟。const myChart = echarts.init(document.getElementById("main")); option = {   series: [     {       name: "bird",       type: "scatter",       symbolSize: 50,       symbol: "image://bird.png",       data: [         [50, 80]       ],       animation: false     },   ] };  myChart.setOption(option);
  要让小鸟动起来,就需要给一个向右的速度和向下的加速度,并在每一帧的场景中刷新小鸟的位置。而小鸟向上飞的动作,则可以靠角度的旋转来实现,向上飞的触发条件设置为空格事件。option = {   series: [     {       xAxis: {         show: false,         type: "value",         min: 0,         max: 200,       },       yAxis: {         show: false,         min: 0,         max: 100       },       name: "bird",       type: "scatter",       symbolSize: 50,       symbol: "image://bird.png",       data: [         [50, 80]       ],       animation: false     },   ] };  // 设置速度和加速度 let a = 0.05; let vh = 0; let vw = 0.5  timer = setInterval(() => {   // 小鸟位置和仰角调整   vh = vh - a;   option.series[0].data[0][1] += vh;   option.series[0].data[0][0] += vw;   option.series[0].symbolRotate = option.series[0].symbolRotate ? option.series[0].symbolRotate - 5 : 0;    // 坐标系范围调整   option.xAxis.min += vw;   option.xAxis.max += vw;    myChart.setOption(option); }, 25);
  效果如下
  2 用自定义图形绘制障碍物
  echarts自定义系列,渲染逻辑由开发者通过renderItem函数实现。该函数接收两个参数params和api,params包含了当前数据信息和坐标系的信息,api是一些开发者可调用的方法集合,常用的方法有:api.value(…),意思是取出 dataItem 中的数值。例如 api.value(0) 表示取出当前 dataItem 中第一个维度的数值。api.coord(…),意思是进行坐标转换计算。例如 var point = api.coord([api.value(0), api.value(1)]) 表示 dataItem 中的数值转换成坐标系上的点。api.size(…), 可以得到坐标系上一段数值范围对应的长度。api.style(…),可以获取到series.itemStyle 中定义的样式信息。
  灵活使用上述api,就可以将用户传入的Data数据转换为自己想要的坐标系上的像素位置。
  renderItem函数返回一个echarts中的graphic类,可以多种图形组合成你需要的形状,graphic类型。对于我们游戏中的障碍物只需要使用矩形即可绘制出来,我们使用到下面两个类。type: group, 组合类,可以将多个图形类组合成一个图形,子类放在children中。type: rect, 矩形类,通过定义矩形左上角坐标点,和矩形宽高确定图形。// 数据项定义为[x坐标,下方水管上侧y坐标, 上方水管下侧y坐标] data: [   [150, 50, 80],   ... ]  renderItem: function (params, api) {     // 获取每个水管主体矩形的起始坐标点     let start1 = api.coord([api.value(0) - 10, api.value(1)]);     let start2 = api.coord([api.value(0) - 10, 100]);     // 获取两个水管头矩形的起始坐标点     let startHead1 = api.coord([api.value(0) - 12, api.value(1)]);     let startHead2 = api.coord([api.value(0) - 12, api.value(2) + 8])     // 水管头矩形的宽高     let headSize = api.size([24, 8])     // 水管头矩形的宽高     let rect = api.size([20, api.value(1)]);     let rect2 = api.size([20, 100 - api.value(2)]);     // 坐标系配置     const common = {         x: params.coordSys.x,         y: params.coordSys.y,         width: params.coordSys.width,         height: params.coordSys.height     }     // 水管形状     const rectShape = echarts.graphic.clipRectByRect(       {         x: start1[0],         y: start1[1],         width: rect[0],         height: rect[1]       },common     );     const rectShape2 = echarts.graphic.clipRectByRect(       {         x: start2[0],         y: start2[1],         width: rect2[0],         height: rect2[1]       },       common     )      // 水管头形状     const rectHeadShape = echarts.graphic.clipRectByRect(       {         x: startHead1[0],         y: startHead1[1],         width: headSize[0],         height: headSize[1]       },common     );      const rectHeadShape2 = echarts.graphic.clipRectByRect(       {         x: startHead2[0],         y: startHead2[1],         width: headSize[0],         height: headSize[1]       },common     );      // 返回一个group类,由四个矩形组成     return {         type: "group",         children: [{             type: "rect",             shape: rectShape,             style: {               ...api.style(),               lineWidth: 1,               stroke: "#000"             }         }, {             type: "rect",             shape: rectShape2,             style: {               ...api.style(),               lineWidth: 1,               stroke: "#000"             }         },         {             type: "rect",             shape: rectHeadShape,             style: {               ...api.style(),               lineWidth: 1,               stroke: "#000"             }         },         {             type: "rect",             shape: rectHeadShape2,             style: {               ...api.style(),               lineWidth: 1,               stroke: "#000"             }         }]     };   },
  颜色定义, 我们为了让水管具有光泽使用了echarts的线性渐变色对象。itemStyle: {   // 渐变色对象   color: {     type: "linear",     x: 0,     y: 0,     x2: 1,     y2: 0,     colorStops: [{         offset: 0, color: "#ddf38c" // 0% 处的颜色     }, {         offset: 1, color: "#587d2a" // 100% 处的颜色     }],     global: false // 缺省为 false   },   borderWidth: 3 },
  另外,用一个for循环一次性随机出多个柱子的数据function initObstacleData() {     // 添加minHeight防止空隙太小     let minHeight = 20;     let start = 150;     obstacleData = [];     for (let index = 0; index < 50; index++) {       const height = Math.random() * 30 + minHeight;       const obstacleStart = Math.random() * (90 - minHeight);       obstacleData.push(         [           start + 50 * index,           obstacleStart,           obstacleStart + height > 100 ? 100 : obstacleStart + height         ]       )     }   }
  再将背景用游戏图片填充,我们就将整个游戏场景,绘制完成:
  3 进行碰撞检测
  由于飞行轨迹和障碍物数据都很简单,所以我们可以将碰撞逻辑简化为小鸟图片的正方形中,我们判断右上和右下角是否进入了自定义图形的范围内。
  对于特定坐标下的碰撞范围,因为柱子固定每格50坐标值一个,宽度也是固定的,所以,可碰撞的横坐标范围就可以简化为 (x / 50 % 1) < 0.6
  在特定范围内,依据Math.floor(x / 50)获取到对应的数据,即可判断出两个边角坐标是否和柱子区域有重叠了。在动画帧中判断,如果重叠了,就停止动画播放,游戏结束。// centerCoord为散点坐标点 function judgeCollision(centerCoord) {   if (centerCoord[1] < 0 || centerCoord[1] > 100) {     return false;   }   let coordList = [     [centerCoord[0] + 15, centerCoord[1] + 1],     [centerCoord[0] + 15, centerCoord[1] - 1],   ]    for (let i = 0; i < 2; i++) {     const coord = coordList[i];     const index = coord[0] / 50;     if (index % 1 < 0.6 && obstacleData[Math.floor(index) - 3]) {       if (obstacleData[Math.floor(index) - 3][1] > coord[1] || obstacleData[Math.floor(index) - 3][2] < coord[1]) {         return false;       }     }   }   return false }  function initAnimation() {   // 动画设置   timer = setInterval(() => {     // 小鸟速度和仰角调整     vh = vh - a;     option.series[0].data[0][1] += vh;     option.series[0].data[0][0] += vw;     option.series[0].symbolRotate = option.series[0].symbolRotate ? option.series[0].symbolRotate - 5 : 0;      // 坐标系范围调整     option.xAxis.min += vw;     option.xAxis.max += vw;      // 碰撞判断     const result = judgeCollision(option.series[0].data[0])      if(result) { // 产生碰撞后结束动画       endAnimation();     }      myChart.setOption(option);   }, 25); }总结
  echarts提供了强大的图形绘制自定义能力,要使用好这种能力,一定要理解好数据坐标点和像素坐标点之间的转换逻辑,这是将数据具象到画布上的重要一步。
  运用好这个功能,再也不怕产品提出奇奇怪怪的图表需求。
  源码地址:github.com/foolmadao/e…
  点击下方,第一时间了解华为云新鲜技术~
  华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

广州自助游小记(二)第1天因为是前一天晚上到的广州,所以把这一天算作在广州开玩的第一天,从早餐开始,去感受这座城市的魅力。早茶点都德食在广州,来到广州肯定要吃最有特色的早茶,传统老字号早茶点都德就在酒看完电影满江红,一定要来漯河这里打卡!这个春节档张艺谋执导的满江红好评不断你知道吗据说著名民族英雄岳飞正是站在咱临颍的小商桥上写下了千古绝唱满江红小商桥景区开展诵读满江红赠二消门票活动随着电影满江红的热播,漯河市临颍县焦点访谈热气腾腾好食光央视网消息(焦点访谈)今年春节,随着疫情防控政策的优化,返乡潮旅游潮叠加各地出台的刺激消费政策,让这个春节的旅游消费市场出现了火热的局面。消费者们热情回归,线下消费生机勃勃。很多餐张家口赤城入选省全域旅游示范区日前,省文化和旅游厅发布关于第四批省级全域旅游示范区认定名单的公示,经市级文化和旅游行政部门初审推荐专家组资料审核现场检查等综合评审,全省共有5个县(市区)入选名单,赤城县成为张家浙江黄岩游在富山乐在其中律转鸿钧佳气同,肩摩毂击乐融融。春节期间,随着天气逐日回暖,各地游客邀约三五好友,携家带口前往旅游景点赏景度假。地处浙江省台州市黄岩西部的富山乡这些天热闹非凡,众多游客纷至沓来,打这里不是巴黎,是哈尔滨!东北卢浮宫爆火年前,社交媒体上,东北留学生参观法国卢浮宫的感叹这卢浮宫真浪漫,修得跟哈尔滨差不多的视频,让哈尔滨版卢浮宫爆火网络。不少游客,根据众多平台的推送,已把位于哈市南直路上的卢浮宫列为到所有的执念都是不够爱自己我从来没有我曾经有我还想要更多都会让人产生我不需要,但我偏要的执念。你为什么对坏人有毒的旧情人昂贵的东西,保持着不可磨灭的希望其实就是不甘和贪念。心有不甘被当作错失真爱。欲壑难填被活着就是为了装逼?人都是自负狂傲固执自私的,重复着历史的轮回,过着祖祖辈辈那无趣的生活。当你在为生活奔波的时候,灵魂就已经死了,只剩下躯壳。怕所有人笑话,怕亲戚朋友笑话,被人看不起,于是大部分人就那嵊州陵园下的触动该走咯,圆满的三天。去远离乡音的地方看看,打开地图,往南。嵊州。一个听过嵊州小吃招牌但从未去了解过的城市。走吧,不远。大巴安排上。01美食小吃安排上阿烤年糕(相当脆噶)黄泽豆腐小笼合院里合院里位于太原市五一路130号,是住宿餐饮为一条龙服务,有咖啡厅,小酒吧,虽然面积不是很大,但是五脏俱全,四合的小院古朴优雅,给人一种回到古代的感觉,入住酒店就好像回了家一样,里面很庆幸,我在春节遇到他们春节不愧是中国人最重视的节日。这个假期,三年没回家的打工人,再次与亲人相聚。躺满三亚沙滩的游客,打响旅游业复苏的第一枪。在最红火的春节档,华语电影群雄相争,类型丰富,为颓靡的行业持
睡眠面膜真的有那么神奇吗?推荐几款自用后超好用的睡眠面膜你真的了解睡眠面膜吗?睡眠面膜,就是可以敷着睡觉的面膜。可为什么独独它能无需洗掉敷着过夜,而其他的涂抹式面膜却不行?这是因为睡眠面膜大多是清爽零负担的凝冻剂型,高分子胶的含量比普通一件开衩旗袍,招谁惹谁了沪上阿姨茶杯图案上的女子旗袍被人质疑开衩过高。一句不雅,吓得商家瑟瑟发抖。商家为了息事宁人,很快就认怂了,表示将加强聆听消费者的声音。那意思就是都怪我们考虑不周,没想到你们会这么敏爆火的能喝的玻尿酸,真有效还是智商税?针对小仙女从注射玻尿酸到口服,美容界还不满足,如今不少商家甚至开出许多脑洞,比如在内衣被子里添加玻尿酸,然后宣称穿上它盖上它就等于穿着面膜。关于玻尿酸的传说,到底哪些有真凭实据,哪些是智商税她的葬礼都是一场精彩的大秀!西太后VivienneWestwood在去年的12月29日去世,享年81岁。这位时尚界唯一的太后,就这样和大家告别。上周伦敦时装周前夕,这位时尚界传奇人物的葬礼在伦敦Southwa又长见识了,原来淑女大小姐的华美穿搭,才是扮美天花板!文洛薇Hi,我是洛薇,继续我们的时尚穿搭之旅,变美永远不迷路。其实,女人真正的美,是属于霓裳华服的。穿得华美隆重,于人于己都不亚于一道视觉盛宴。比如,华丽端庄的淑女大小姐穿搭。穿衣卡戴珊姐妹集体下车!大屁股不再流行?潮流总会有寿命,我原以为大屁股会永垂不朽,看来如今算是错付了!那时的我天真的一位卡戴珊家族翘臀能一日比一日壮大,直到装下整个美国但现在,那些巨臀们纷纷丢掉了临时使用权,让自己的屁股王坚院士算力不再是开发者瓶颈,ChatGPT带来方法论天翻地覆变化ChatGPT没有超出当年比尔盖茨对一台PC的希望,当时比尔盖茨说,希望PC能够像跟人一样的方法来与用户交流,只不过当时只是PC时代,没有互联网带来的数据,也没有数据带来的人工智能SpringBootDruidDataSource实现监控MySQL性能1。基本概念我们都使用过连接池,比如C3P0,DBCP,hikari,Druid,虽然HikariCP的速度稍快,但Druid能够提供强大的监控和扩展功能,也是阿里巴巴的开源项目。奋进的春天常州金坛速度刷新进度条省重大项目掀建设热潮来源常州日报常州网一年之计在于春,重大项目建设打头阵。今年,常州市金坛区7个项目列入省重大项目清单,产业类项目数量位列常州各辖市区第一,创历史新高。当前,这些重大项目正热火朝天地建元宇宙里办业务,机器人跳鬼步舞香港传媒高层人士大湾区参访团走进广深莞戴上VR眼镜,在元宇宙政务大厅里体验便捷政务服务走在广州的弥敦道,看港澳青年创业者在会议室里头脑风暴站在河套深港科技创新合作区远眺一河之隔的香港在松山湖国际机器人基地看产学研结合孵地方全力扩投资,18省份今年重大项目投资近10万亿稳经济背景下,多地不断加大重大项目投资力度。广西内蒙古甘肃和江苏等省份近期陆续发布省级重大项目名单,加上1月的已经发布的省份,多数省份都已经安排好今年的重大项目,这些项目呈现投资总