Chinaunix首页 | 论坛 | 博客
  • 博客访问: 940856
  • 博文数量: 110
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1997
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-15 22:39
个人简介

HT for Web 3D. HT for modern web and mobile app development. www.hightopo.com

文章分类

全部博文(110)

文章存档

2020年(1)

2018年(28)

2017年(21)

2016年(10)

2015年(28)

2014年(19)

2013年(3)

我的朋友

分类: HTML5

2014-12-28 21:07:54

HTML5版的String Avoider小游戏  蛮简单也蛮考验耐心,从游戏起始点移动鼠标到终点位置,鼠标移动过程绘制出移动轨迹的String平滑曲线,整个过程不能碰撞到边界,从技术角度来说其核心就是根据鼠标移动位置生成String线的算法,该游戏是ActionScript写的Flash版,这里将其改造成HTML5版的JavaScript实现,并增加可自定义关卡功能的一种设计思路。

Screen Shot 2014-12-28 at 3.39.34 PM

String连线我是缓存了300个点信息的数组,鼠标移动时不断调整300个点的新位置信息,每次更新时先将新鼠标点设置给第一个元素,后续更新x点时,计算其与x-1点的角度,在此方向长度为1的位置更新坐标,这样就达到了平滑曲线的效果。

除了绘制String线外还有个技术点就是监测碰撞,该Flash游戏的边界都是线段,因此第一想到的监测方式就是线线相交的思路,算法可参考  ,如果以LineLine的相交思路只需要遍历所有point间的线段,判断是否与游戏关卡定义的边界线相交,但这种方式对不规则边界就比较麻烦,监测性能也不高。

考虑到我们还需要提供用户可DIY自定义游戏关卡的功能,我们将采用监测颜色透明度信息的方式,由于正常游戏时场景无需用户动态修改,因此边界的信息可提前缓存到ImageData内存中,并且我们300个点的距离都是1,监测只需根据点进行就可以。

Screen Shot 2014-12-28 at 3.38.33 PM

整个程序采用的拓扑图组件,再其上通过addTopPainter添加顶层画笔绘制曲线,当曲线碰到Node图元时绘制成红色,否则绘制成黄色,监听拓扑图的interaction事件,在该事件中设置dirty的脏标志,在绘制时根据dirty的标志进行更新,采用这样的方式可将多次变换最终聚合成一次更新,这也是图形刷新绘制常用的基本技巧。同时通过GraphView.setEditable(true)开启了拓扑图的可视化编辑功能,用户可随时改变界面图元位置和旋转等形状信息,相当于自定义关卡的效果。

所有代码和运行效果如下:

点击(此处)折叠或打开

  1. function init(){
  2.     dataModel = new ht.DataModel();
  3.     graphView = new ht.graph.GraphView(dataModel);
  4.     graphView.handleScroll = function(){};
  5.     graphView.setEditable(true);
  6.     graphView.setPannable(false)

  7.     view = graphView.getView();
  8.     view.style.left = '10px';
  9.     view.style.top = '10px';
  10.     view.style.width = '600px';
  11.     view.style.height = '400px';
  12.     view.style.background = 'black';
  13.     document.body.appendChild(view);

  14.     createNode(20, 20, 80, 40, 'rect');
  15.     createNode(200, 300, 80, 40, 'star');
  16.     createNode(400, 100, 80, 40, 'oval');
  17.     createShape();

  18.     length = 1;
  19.     count = 300;
  20.     points = [];
  21.     for(var i=0; i<count; i++){
  22.         points.push({x: 0, y: 0});
  23.     }
  24.     view.addEventListener('mousemove', function(e){
  25.         var point = graphView.lp(e);
  26.         points[0].x = point.x;
  27.         points[0].y = point.y;
  28.         for (var i = 1; i < count - 1; i++) {
  29.             var angle = Math.atan2(points[i].y - points[i - 1].y, points[i].x - points[i - 1].x);
  30.             points[i].x = points[i - 1].x + length * Math.cos(angle);
  31.             points[i].y = points[i - 1].y + length * Math.sin(angle);
  32.         }
  33.         if(imageData){
  34.             hit = false;
  35.             for (var i = 0; i < count; i++) {
  36.                 var x = Math.floor(points[i].x);
  37.                 var y = Math.floor(points[i].y);
  38.                 var index = (y * graphView.getWidth() + x) * 4;
  39.                 if(imageData.data[index+3] !== 0){
  40.                     hit = true;
  41.                     break;
  42.                 }
  43.             }
  44.         }
  45.         graphView.redraw();
  46.     });

  47.     dirty = true;
  48.     imageData = null;
  49.     graphView.mi(function(e){
  50.         dirty = true;
  51.     });
  52.     graphView.addTopPainter(function(g){
  53.         if(dirty){
  54.             dirty = false;
  55.             hit = false;
  56.             imageData = g.getImageData(0, 0, graphView.getWidth(), graphView.getHeight());
  57.             ht.Default.callLater(graphView.redraw, graphView);
  58.         }else{
  59.             g.beginPath();
  60.             g.lineWidth = 3;
  61.             g.strokeStyle = hit ? 'red' : 'yellow';
  62.             g.moveTo(points[0].x, points[0].y);
  63.             for (var i = 1; i < count - 1; i++) {
  64.                 g.lineTo(points[i].x, points[i].y);
  65.             }
  66.             g.stroke();
  67.         }
  68.     });
  69. }
  70. function createNode(x, y, w, h, shape){
  71.     var node = new ht.Node();
  72.     node.setRect(x, y, w, h);
  73.     node.s({
  74.         'shape': shape,
  75.         'select.width': 0
  76.     });
  77.     dataModel.add(node);
  78.     return node;
  79. }


阅读(2632) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~