zoukankan      html  css  js  c++  java
  • BOX2d绘制曲线

    来自天地会的wkyjoey同学问道如何做一个重力大师游戏(如下图)。这里要特意表示一下歉意,最近一直忙于工作,没有及时更新教程。


    对于重力大师游戏,试玩之后,不难发现,我们在运行时可以创建的刚体有两种,线条刚体和多边形刚体。今天我们来一起研究一下线条刚体的创建。多边形刚体会在下次教程中讨论。
    这里我们要绘制的线条不是直线而是曲线,所以简单的矩形刚体无法实现这个效果。在圆形边界教程中,我们同样接触到了曲线。解决方法是用多个线段组合起来模拟一个圆圈。庆幸的是这个方法同样适用于本例中的曲线。下面我们详细讨论一下。
    线条是由无数个点组成的,把点放大一些就成了线段,所以一个线条可以变成多个线段的组合。

    如上图,我们假设每个先断掉长度为segmentLength,线段的长度越短,segmentLength越小,线条模拟就越逼真。

    在线条绘制过程中,持续检测鼠标坐标curPoint与前一个点prePoint之间的距离distance,当distance大于线段长度时,创建一个新的线段,并将curPoint赋值给prePoint。

    好吧,下面我介绍一下具体的步骤:

    • 定义线段的长度segmentLength
    • 在鼠标点下后,卡是绘制线条,并记录之前的鼠标坐标位置为prePoint
    • 在绘制过程中。如果鼠标坐标与prePoint之间的距离distance大于segmentLength,则将鼠标坐标赋值给prePoint,创建新的线段,并添加到segmentList中
    • 鼠标弹起后,遍历所有的线段,并利用多边形组合法,创建对于的线段刚体,然后组合成一个完整的线条。


    效果如下,点击并拖动鼠标开始绘制,其中的红点是线段的坐标位置。另外这里我没有限制线段的交叉,所以在绘制时尽量避免交叉,防止意外的错误,后续我们再讨论如何防止绘制线段时交叉。

    源码中用到了LDEasyBox2D来简化代码。完整的代码及注释如下:

    1. package
    2. {
    3.     import Box2D.Collision.b2AABB;
    4.     import Box2D.Collision.Shapes.b2PolygonShape;
    5.     import Box2D.Common.Math.b2Vec2;
    6.     import Box2D.Dynamics.b2Body;
    7.     import Box2D.Dynamics.b2BodyDef;
    8.     import Box2D.Dynamics.b2DebugDraw;
    9.     import Box2D.Dynamics.b2FixtureDef;
    10.     import Box2D.Dynamics.b2World;
    11.     import flash.display.Sprite;
    12.     import flash.events.Event;
    13.     import flash.events.MouseEvent;
    14.     import flash.geom.Point;
    15.     /**
    16.      * http://www.ladeng6666.com
    17.      * @author ladeng6666
    18.      */
    19.     public class Main extends Sprite
    20.     {
    21.         private var world:b2World;
    22.         private var spriteCanvas:Sprite;
    23.         private var tipCanvas:Sprite;
    24.         //前一个point
    25.         private var prePoint:Point = new Point();
    26.         //当前的point
    27.         private var curPoint:Point = new Point();
    28.         //1.设置线段长度segmentLength
    29.         private var segmentLength:Number = 20;
    30.         private var segmentsList:Array=new Array();
    31.         private var isDrawing:Boolean = false;
    32.         public function Main()
    33.         {
    34.             //创建box2D世界
    35.             world = LDEasyBox2D.createWorld();
    36.             //创建box2D调试图
    37.             addChild(LDEasyBox2D.createDebug(world));
    38.             //创建地面
    39.             LDEasyBox2D.createWrapWall(world,stage);
    40.             spriteCanvas = new Sprite();
    41.             addChild(spriteCanvas);
    42.             tipCanvas = new Sprite();
    43.             addChild(tipCanvas);
    44.             //侦听事件
    45.             addEventListener(Event.ENTER_FRAME, loop);
    46.             stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
    47.             stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
    48.             stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
    49.         }
    50.         private function onStageMouseDown(e:MouseEvent):void
    51.         {
    52.             //2.开始绘制线条,并定义prePoint
    53.             isDrawing = true;
    54.             spriteCanvas.graphics.lineStyle(2);
    55.             spriteCanvas.graphics.moveTo(mouseX, mouseY);
    56.             curPoint = new Point(mouseX, mouseY);
    57.             prePoint = curPoint.clone();
    58.         }
    59.         private function onStageMouseMove(e:MouseEvent):void
    60.         {
    61.             if(!isDrawing) return;
    62.             spriteCanvas.graphics.lineTo(mouseX, mouseY);
    63.             curPoint = new Point(mouseX, mouseY);
    64.             var distance:Number = Point.distance(prePoint, curPoint);
    65.             if (distance >= segmentLength) {
    66.                 //3.创建线段,并添加到segmentsList中
    67.                 segmentsList.push( new Segment(prePoint, curPoint));
    68.                 prePoint = curPoint.clone();
    69.             }
    70.         }
    71.         private function onStageMouseUp(e:MouseEvent):void
    72.         {
    73.             isDrawing = false;
    74.             spriteCanvas.graphics.clear();
    75.             //在鼠标位置随机创建一个圆形或矩形刚体
    76.             createSegment(segmentsList);
    77.             //清楚segmengsList里的内容
    78.             segmentsList = new Array();
    79.         }
    80.         private function loop(e:Event):void
    81.         {
    82.             world.Step(1 / 30, 10, 10);
    83.             world.ClearForces();
    84.             world.DrawDebugData();
    85.             drawTip(segmentsList);
    86.         }
    87.         private function createSegment(segmentsArray:Array):void
    88.         {
    89.             //1.创建刚体需求b2BodyDef
    90.             var bodyRequest:b2BodyDef = new b2BodyDef();
    91.             bodyRequest.type = b2Body.b2_dynamicBody;
    92.             bodyRequest.position.Set(0 ,0);//记得米和像素的转换关系
    93.             //2.Box2D世界工厂更具需求创建createBody()生产刚体
    94.             var body:b2Body=world.CreateBody(bodyRequest);
    95.             //3.创建敢提形状需求b2ShapeDef的子类
    96.                 //创建矩形刚体形状需求
    97.             var fixtureRequest:b2FixtureDef = new b2FixtureDef();
    98.             fixtureRequest.density = 3;
    99.             fixtureRequest.friction = 0.3;
    100.             fixtureRequest.restitution = 0.2;
    101.             for each(var segment:Segment in segmentsArray) {
    102.                 var shapeBoxRequest:b2PolygonShape = new b2PolygonShape();
    103.                 shapeBoxRequest.SetAsOrientedBox(segment.length /2/ 30, 2 / 30, new b2Vec2(segment.centerX/30, segment.centerY/30), segment.rotation);
    104.                 fixtureRequest.shape = shapeBoxRequest;
    105.                 body.CreateFixture(fixtureRequest);
    106.             }
    107.         }
    108.         private function drawTip(segmengtsArray:Array):void {
    109.             tipCanvas.graphics.clear();
    110.             for each( var segment:Segment in segmengtsArray) {
    111.                 tipCanvas.graphics.beginFill(0xFF0000, 0.5);
    112.                 tipCanvas.graphics.drawCircle(segment.centerX, segment.centerY,3);
    113.             }
    114.         }
    115.     }
    116. }
    复制代码

    <ignore_js_op style="font: 16px/28px Tahoma, Helvetica, SimSun, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 0px; letter-spacing: normal; word-spacing: 0px; white-space: normal; word-wrap: break-word; orphans: 2; widows: 2; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-size-adjust: auto; -webkit-text-stroke- 0px;"> 2012-07-08 实时绘制线条刚体2.1a.rar (336.7 KB, 下载次数: 307) 

  • 相关阅读:
    用UILocalNotification实现一个闹钟(Swift)
    Swift
    iOS判断一些权限是否被禁止
    ofbiz学习笔记
    POJ1062 昂贵的聘礼 【DFS】
    echarts 应用数个样例
    java 中缀转后缀(逆波兰)
    开放是否能让苹果成为智能家居的标准制定者?
    2015阿里校招前端在线题目
    hql中不能写count(1)能够写count(a.id)
  • 原文地址:https://www.cnblogs.com/cooka/p/3559610.html
Copyright © 2011-2022 走看看