`
blessdyb
  • 浏览: 234317 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Canvas做游戏实践分享(十)

阅读更多

6    用户交互——移动物体

      游戏的核心在于交互,很多时候需要用户动手来操作游戏对象,很基本的一个操作就是移动物体。接下来我们会介绍如何拖动物体,在画布上扔物体等。

6.1    选择与释放对象

        使用鼠标对物体的拖拽操作主要有三个步骤——鼠标进入物体范围并按下,鼠标移动及鼠标释放。这涉及到三个鼠标事件:mousedown,mousemove,mouseup。我们按此思路,仍旧以前面介绍的小球系统来实现。
        首先需要检测到鼠标是否进入到小球中,为了简化处理,我们把小球看成一个与其外接矩形等效的图形。先得到小球在画布中所占据的位置。如下代码:

ball.prototype.getBounds=function(){
    return { x: ball.x-ball.radius,  y: ball.y-ball.radius,
          width: 2*ball.radius,  height: 2*ball.radius };
}

 

    如上,得到了小球外接矩形的左上端点及长宽。接下来,我们就需要来查看鼠标是否进入小球,抽象出来就是点是否在当前的矩形中,在其我们使用集合思想,取其对立事件就很容易处理。如下代码:

utils.containsPoint = function (rect, x, y) {
        return !(x < rect.x || x > rect.x + rect.width ||
                     y < rect.y || y > rect.y + rect.height);
};
 

    很明白地看到,我们先取得点不在小球的四种情况,然后取其对立事件即为点在小球内。于是很容易就实现:

    window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
               
                var ball=new Ball();
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.draw(context);
               //鼠标按键按下事件
                canvas.addEventListener("mousedown",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("===[mousedown]===in ball");
                    }else{
                        console.log("===[mousedown]===out ball");
                    }
                },false);
               //鼠标按键释放事件
                canvas.addEventListener("mouseup",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("***[mouseup]===in ball");
                    }else{
                        console.log("***[mouseup]===out ball");
                    }
                },false);
               //鼠标移动事件
                canvas.addEventListener("mousemove",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("###[mousemove]###in ball");
                    }else{
                        console.log("###[mousemove]###out ball");
                    }
                })
            };
 

 

6.2    拖动对象

         有了上面的实践基础,实现拖动非常容易,只需要在鼠标移动时让小球的位置与鼠标位置相同即可。如下代码:

window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
               
                var ball=new Ball(40);
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.draw(context);
               //小球跳动偏差处理
                var offset_fix_x=0;
                var offset_fix_=0;
               //鼠标按下时检测是否位于小球内部,如果位于,则注册移动事件处理函数
                canvas.addEventListener("mousedown",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        offset_fix_x=mouse.x-ball.x;
                        offset_fix_y=mouse.y-ball.y;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUP,false);
                    }
                },false);
                //鼠标按键释放时的操作
                function onMouseUP(){
                    canvas.removeEventListener("mouseup",onMouseUP,false);
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                }
               //鼠标移动时小球跟随鼠标
                function onMouseMove(event){
                    ball.x=mouse.x-offset_fix_x;
                    ball.y=mouse.y-offset_fix_y;
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                   
                    ball.draw(context);
                })();
            };

 
    很容易就实现了小球移动的功能。注意,offset_x与offset_y是为了用来处理在小球内部我们快速点击小球边缘产生的小球跳动问题。通过记录鼠标按下时鼠标与小球中心的偏差距离,在鼠标移动时固定处理这个偏差,就能避免跳动。

6.3    拖动移动中的对象

      如果需要对正在移动中的对象进行拖拽动作,原理和前面介绍的静止的对象拖拽一样,但需要注意,我们必须处理小球在鼠标点击后的状态,将此时小球的速度置0,否则我们鼠标在点住小球后,小球会继续沿其之前的速度运动,这样很难进行拖拽操作。如下代码:

window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
                var left=0,top=0,right=canvas.width,bottom=canvas.height,isMouseDown=false;
                var ball=new Ball(40);
                //跳动偏差处理
                var fix_offset_jump_x=fix_offset_jump_y=0;
               //小球移动状态初始化
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.vx=Math.random()*10-5;
                ball.vy=-10;
                bounce=-0.7;
                gravity=0.2;
                //鼠标按下时检测是否位于小球内部,如果位于,则注册移动事件处理函数
                canvas.addEventListener("mousedown",function(){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        isMouseDown=true;
                        //如果鼠标在小球内部,则使得小球静止
                        ball.vx=0;
                        ball.vy=0;
                        fix_offset_jump_x=mouse.x-ball.x;
                        fix_offset_jump_y=mouse.y-ball.y;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUP,false);
                    }
                },false);
               
                function onMouseUP(){
                    isMouseDown=false;
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                    canvas.removeEventListener("mouseup",onMouseUP,false);
                }
               
                function onMouseMove(){
                    ball.x=mouse.x-fix_offset_jump_x;
                    ball.y=mouse.y-fix_offset_jump_y;
                }
               //边缘检测,碰撞处理
                function checkBoundary(){
                    ball.vy+=gravity;
                    ball.x+=ball.vx;
                    ball.y+=ball.vy;
                    if(ball.y-ball.radius<top){
                        ball.y=ball.radius+top;
                        ball.vy*=bounce;
                        console.log(ball.vy);
                    }else if(ball.y+ball.radius>bottom){
                        ball.y=bottom-ball.radius;
                        ball.vy*=bounce;
                    }
                    if(ball.x-ball.radius<left){
                        ball.x=ball.radius+left;
                        ball.vx*=bounce;
                    }else if(ball.x+ball.radius>right){
                        ball.x=right-ball.radius;
                        ball.vx*=bounce;
                    }       
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                   
                    if(!isMouseDown){
                        checkBoundary();
                    }   
                    ball.draw(context);
                })();
            };

 

6.4    投掷对象

         对于对象的投掷动作看似复杂,其实结合之前的拖拽动作,它的实现就非常简单。假设我们把一个静止的小球在一帧中从原始位置水平移动了10像素后松开鼠标,即实现了扔的动作,那么我们就认为此时小球被以10像素/ 帧的速度水平投掷出来。即

ball.vx=ball.x-lastX;
ball.vy=ball.y-lastY;

 

    于是,我们对移动中的小球进行投掷动作,代码如下:

window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
                //定义系统环境变量
                var top=0,left=0,right=canvas.width,left=0,bottom=canvas.height;
                var fix_mouse_drag_offset_x=0;
                var fix_mouse_drag_offset_y=0;
                var bounce=-0.7;
                var gravity=0.2;
                var isMouseDown=false;
                var oldX=oldY=0;

               //初始化小球
                var ball=new Ball(40);
               
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
               
                ball.vx=Math.random()*10-5;
                ball.vy=-10;
                //鼠标按下时检测鼠标是否位于小球内部
                canvas.addEventListener("mousedown",function(){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        isMouseDown=true; 
                        //小球跳动处理
                        fix_mouse_drag_offset_x=mouse.x-ball.x;
                        fix_mouse_drag_offset_y=mouse.y-ball.y;
                        //将小球置于静止状态
                        oldX=ball.x;
                        oldY=ball.y;
                        mouse.vx=mouse.vy=0;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUp,false);
                    }
                },false);
               
                function onMouseMove(){
                    ball.x=mouse.x-fix_mouse_drag_offset_x;
                    ball.y=mouse.y-fix_mouse_drag_offset_x;
                }
               
                function onMouseUp(){
                    isMouseDown=false;
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                    canvas.removeEventListener("mouseup",onMouseUp,false);
                }
               //计算小球被投掷后的速度
                function trackVelocity(){
                    ball.vx=ball.x-oldX;
                    ball.vy=ball.y-oldY;
                    oldX=ball.x;
                    oldY=ball.y;
                }
               //边缘检测,碰撞出理
                function checkBoundary(){
                    ball.vy+=gravity;
                    ball.x+=ball.vx;
                    ball.y+=ball.vy;
                   
                    if(ball.x-ball.radius<left){
                        ball.x=left+ball.radius;
                        ball.vx*=bounce;
                    }else if(ball.x+ball.radius>right){
                        ball.x=right-ball.radius;
                        ball.vx*=bounce;
                    }
                   
                    if(ball.y-ball.radius<top){
                        ball.y=top+ball.radius;
                        ball.vy*=bounce;
                    }else if(ball.y+ball.radius>bottom){
                        ball.y=bottom-ball.radius;
                        ball.vy*=bounce;
                    }
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                    //鼠标按下时,进行投掷处理,否则进行边缘检测及碰撞处理
                    if(!isMouseDown){
                        checkBoundary();   
                    }else{
                        trackVelocity();
                    }
                    ball.draw(context);
                })();
               
            };
 

 

2
2
分享到:
评论
4 楼 blessdyb 2014-02-13  
aikki_gogh 写道
最近正在研究canvas,求utils.js和arrow.js


代码都在当年系列的文章里面
3 楼 aikki_gogh 2014-01-22  
最近正在研究canvas,求utils.js和arrow.js
2 楼 blessdyb 2012-11-23  
scgy5555 写道
感谢楼主分享经验 这几篇每天让我研究到深夜
但是这篇错误好多。。 望改正。。
顺便问一下 想继续研究canvas做游戏 有推荐的书/教程么 中文优先。。

什么错误呀?代码都跑过的呀
1 楼 scgy5555 2012-11-21  
感谢楼主分享经验 这几篇每天让我研究到深夜
但是这篇错误好多。。 望改正。。
顺便问一下 想继续研究canvas做游戏 有推荐的书/教程么 中文优先。。

相关推荐

    HTML5 Canvas游戏开发实战

    9. **最佳实践**:分享HTML5 Canvas开发的最佳实践,包括代码组织、调试技巧以及如何确保兼容性。 10. **社区与资源**:可能还会介绍一些HTML5和Canvas的在线社区、工具、库和框架,帮助读者持续学习和提高。 总的...

    HTML5 Canvas核心技术图形、动画与游戏开发 PDF扫描版[71MB].rar

    在这个"HTML5 Canvas核心技术图形、动画与游戏开发"的PDF扫描版中,读者可以深入学习到Canvas的核心概念和实践技巧。 首先,Canvas的基本使用方法是通过JavaScript API来实现的。这个API提供了大量的绘图命令,如`...

    小程序canvasDemo

    在微信小程序中,Canvas是一个非常重要的组件,它允许开发者在...以上就是关于"小程序canvasDemo"项目中涉及的主要技术点,通过学习和实践,你可以掌握微信小程序中canvas的使用技巧,进一步提升你的小程序开发能力。

    canvas简单实例详解

    HTML5的Canvas是一个强大的绘图API,它允许开发者在网页上进行动态的、基于...随着对Canvas的深入理解和实践,你会发现它的潜力无穷无尽。在实际项目中,可以结合CSS3、WebGL等技术,构建更复杂的交互式Web应用。

    html5_canvas_塔防游戏

    HTML5 Canvas是Web开发中的一个强大工具,它允许开发者在网页上进行动态图形绘制,创造出丰富的交互式用户体验。在这个“html5_canvas_...这样的实现不仅方便分享,也为开发者提供了一个学习和实践Canvas API的好平台。

    canvas+js写的绘图小程序

    《canvas+js绘制图形的实践探索》 在Web开发领域,HTML5的canvas元素提供了一种强大的机制,允许开发者在浏览器上进行动态图形绘制。这篇博文将深入探讨如何结合JavaScript,利用canvas API来构建一个简单的绘图小...

    canvas截图.zip

    这个功能在很多场景下都非常有用,比如网页分享、游戏截图、在线编辑器保存草图等。 首先,我们要了解canvas的基本用法。canvas是一个矩形画布,通过JavaScript来控制它的内容。我们可以通过`&lt;canvas&gt;`标签在HTML中...

    html5 canvas核心技术

    HTML5 Canvas是Web开发中的一个关键技术,...通过学习和实践这些HTML5 Canvas的核心技术,开发者可以构建出交互性强、视觉效果丰富的Web应用程序,无论是数据可视化、游戏开发还是艺术创作,Canvas都能提供强大的支持。

    HTML5 Canvas实战pdf下载

    9. **保存和导出**:Canvas上的内容可以导出为图像,或者使用toDataURL方法生成数据URL,方便分享和存储。 10. **实际应用**:书中实例可能涵盖游戏开发、图表绘制、数据可视化、地图应用等多个实际场景,帮助...

    canvas画图测试

    这篇博客"canvas画图测试"可能涉及了使用Canvas进行图形绘制的基础知识和实践技巧。Canvas API的使用通常包括以下几个核心知识点: 1. **Canvas元素**:在HTML中,`&lt;canvas&gt;`标签定义了一个可编程的画布,通过...

    android游戏源码分享

    2. 用户界面(UI):Android游戏通常使用自定义View或SurfaceView来实现游戏画面,结合Canvas进行绘制。UI的设计也包括菜单、暂停、设置等交互元素。 3. 图形渲染:游戏可能使用OpenGL ES进行高性能的2D或3D图形...

    HTML5 Canvas学习笔记(6)拼图游戏(数字版)

    在“HTML5 Canvas学习笔记(6)拼图游戏(数字版)”这篇博文中,作者分享了如何利用Canvas构建一个数字拼图游戏。下面我们将详细探讨这个知识点。 1. **HTML5 Canvas基础**: - Canvas是一个基于矢量图形的画布元素...

    H5游戏源码分享-跑酷游戏熊出没

    1. Canvas绘图:H5游戏常用Canvas API进行动态绘图,实现游戏场景的渲染。通过JavaScript操作Canvas的绘图方法,可以绘制角色、障碍物并实现动画效果。 2. Event Handling:JavaScript的事件监听和处理机制在游戏中...

    html5 canvas 视频网站文字弹幕动画特效

    这个技术的引入极大地扩展了网页的交互性和动态性,尤其在创建复杂的动画效果和游戏场景时表现得尤为出色。在这个特定的场景中,我们讨论的是如何使用HTML5 Canvas实现视频网站的文字弹幕动画特效。 首先,我们要...

    H5游戏源码分享-跳得更高

    H5游戏源码的分享,对于学习者来说是一次宝贵的实践机会,可以了解游戏逻辑、动画效果、用户交互等核心元素的实现方法。 【标签】"游戏":游戏是软件的一种类型,它可以提供娱乐、挑战或教育功能。H5游戏作为游戏的...

    几十个微信H5小游戏完整源码

    这些H5小游戏的源码对于初学者来说是宝贵的参考资料,他们可以通过阅读和分析源码,学习游戏开发的技巧和最佳实践。 总之,"几十个微信H5小游戏完整源码"不仅提供了可以直接运行的游戏,也是一份学习和研究H5游戏...

    games:使用canvas api开发一堆HTML游戏以使其更好,并且仅使用HTMLCSSJS堆栈构建游戏

    HTML5 Canvas API是Web开发中的一个强大工具,它允许开发者在网页上绘制2D图形,创建动态、交互式的游戏和应用程序。在这个项目中,“games:使用canvas api...在实践中,不断探索和创新,制作出更丰富、更有趣的游戏。

    《HTML5 Canvas 开发详解(第2版)》PDF

    8. **性能优化**:分享关于Canvas性能的技巧,如批处理绘图操作、使用图像数据缓冲区和避免不必要的重绘。 9. **高级应用**:深入探讨更复杂的用例,如粒子系统、游戏开发、图表绘制和数据可视化。 10. **实践案例...

    H5自写的小游戏源码分享

    在“H5自写的小游戏源码分享”这...同时,这也是一个很好的学习实践机会,可以提升你的JavaScript编程水平,理解游戏开发中的逻辑思维和问题解决能力。不断练习和学习,你将能够创造出更多有趣、引人入胜的HTML5游戏。

    jquery html5微信分享游戏围住神经猫游戏源码下载

    【标题】:“jQuery HTML5微信分享游戏:围住神经猫游戏源码下载” 【描述】:这个资源提供了基于jQuery和HTML5技术开发的微信分享...对于希望从事移动互联网游戏开发的初学者来说,这是一个非常有价值的实践案例。

Global site tag (gtag.js) - Google Analytics