HTML5版的String Avoider小游戏

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

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

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

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

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

所有代码和运行效果如下:http://v.youku.com/v_show/id_XODU4NzY5MzQ0.html

function init(){                    
    dataModel = new ht.DataModel();                   
    graphView = new ht.graph.GraphView(dataModel); 
    graphView.handleScroll = function(){};
    graphView.setEditable(true);
    graphView.setPannable(false)

    view = graphView.getView();
    view.style.left = '10px';
    view.style.top = '10px';
    view.style.width = '600px';
    view.style.height = '400px';
    view.style.background = 'black';
    document.body.appendChild(view);

    createNode(20, 20, 80, 40, 'rect');                
    createNode(200, 300, 80, 40, 'star');
    createNode(400, 100, 80, 40, 'oval');
    createShape();

    length = 1;
    count = 300;
    points = [];
    for(var i=0; i<count; i++){
        points.push({x: 0, y: 0});
    }
    view.addEventListener('mousemove', function(e){
        var point = graphView.lp(e);
        points[0].x = point.x;
        points[0].y = point.y;
        for (var i = 1; i < count - 1; i++) {
            var angle = Math.atan2(points[i].y - points[i - 1].y, points[i].x - points[i - 1].x);
            points[i].x = points[i - 1].x + length * Math.cos(angle);
            points[i].y = points[i - 1].y + length * Math.sin(angle);
        }
        if(imageData){
            hit = false;
            for (var i = 0; i < count; i++) {
                var x = Math.floor(points[i].x);
                var y = Math.floor(points[i].y);
                var index = (y * graphView.getWidth() + x) * 4;
                if(imageData.data[index+3] !== 0){
                    hit = true;
                    break;
                }
            }                        
        }                    
        graphView.redraw();
    });

    dirty = true;                
    imageData = null;
    graphView.mi(function(e){
        dirty = true;
    });                
    graphView.addTopPainter(function(g){
        if(dirty){
            dirty = false;    
            hit = false;
            imageData = g.getImageData(0, 0, graphView.getWidth(), graphView.getHeight());                                                                                                                                              
            ht.Default.callLater(graphView.redraw, graphView);  
        }else{
            g.beginPath();
            g.lineWidth = 3;
            g.strokeStyle = hit ? 'red' : 'yellow';                   
            g.moveTo(points[0].x, points[0].y);
            for (var i = 1; i < count - 1; i++) {
                g.lineTo(points[i].x, points[i].y);
            }
            g.stroke();                        
        }
    });
}    
function createNode(x, y, w, h, shape){
    var node = new ht.Node();
    node.setRect(x, y, w, h);
    node.s({
        'shape': shape,
        'select.width': 0
    });
    dataModel.add(node);
    return node;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Angular&服务

关于angular2通道使用ts

663
来自专栏听雨堂

深入理解字符串和字节数组转换

      前文中,论及字符串和字节数组的转换,虽然能够找到某个代码页,保证转换的可逆,但是在实际处理中,仍然还有一些细节问题需要注意.       最重要的...

1678
来自专栏青蛙要fly的专栏

图片操作系列 —(1)手势缩放图片功能

项目开发中,大家APP开发一般都会用到上传图片,比如是上传了自己的生活照,然后在某个界面处查看上传的图片,这时候一般在这个查看详情的界面,会有手势放大缩小功能,...

701
来自专栏racaljk

2017第八届蓝桥杯决赛(C++ B组)2.磁砖样式

小明家的一面装饰墙原来是 310 的小方格。 现在手头有一批刚好能盖住2个小方格的长方形瓷砖。 瓷砖只有两种颜色:黄色和橙色。 小明想知道,对于这么简陋的...

674
来自专栏Angular&服务

JS的一些技巧

根据当前文字选择返回 TextRange 对象,或根据控件选择返回 ControlRange 对象。

693
来自专栏lonelydawn的前端猿区

面向对象+模块化设计绘制canvas星空动画

require.js的相关内容已在我的博文 《requireJs的使用,以canvas绘制星空为例》中描述, 可查看:https://cloud.tencent...

3756
来自专栏工科狗和生物喵

对菜鸟教程的Python一百例的个别改进

好吧,其实是小妹子Python公选课结课,所以我来帮忙做个大作业(简单到哭的大作业好吗?)!她的大作业就是老师把菜鸟教程的Python一百例扒下来做成文档,然后...

3646
来自专栏郭霖

Android多点触控技术实战,自由地对图片进行缩放和移动

在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果,虽然这种效果很炫很酷,但其实还只能算是一个半成品,因为照片墙中所有的图片都是只能看不能点的。...

2075
来自专栏me的随笔

给图片添加文字水印

水印图片透明度设置和旋转(下面这段代码和上面一段代码都位于Watermark类中,因为代码量较大,所以分开来展示):

874
来自专栏木子墨的前端日常

纯css3跑马灯demo

我们写跑马灯一般都是用js控制定时器不断循环产生,但是定时器消耗比较大,特别是程序中很多用到定时器的时候,感觉有的时候比较卡。但是css3样式一般不会。这里主要...

512

扫码关注云+社区