2

Я создал мягкий круг тела в затылке. И теперь я пытаюсь получить текстуру. Но у меня проблемы, и я не могу найти ответ. Вот почему я обращаюсь к вам, ребята.AS3 Softbody texture starling

Im пытается сделать то, что он делает в этой Objective C учебник:

http://www.uchidacoonga.com/2012/04/soft-body-physics-with-box2d-and-cocos2d-part-44/

любые идеи о том, как сделать это с скворца и Stage3D?

ответ

2

Вы должны написать пользовательский экранный объект (см. Starling manual). Вот простой пример: Пример

package 
{ 
    import com.adobe.utils.AGALMiniAssembler; 

    import flash.display3D.Context3D; 
    import flash.display3D.Context3DProgramType; 
    import flash.display3D.Context3DVertexBufferFormat; 
    import flash.display3D.IndexBuffer3D; 
    import flash.display3D.VertexBuffer3D; 
    import flash.geom.Point; 
    import flash.utils.ByteArray; 

    import starling.core.RenderSupport; 
    import starling.core.Starling; 
    import starling.display.DisplayObject; 
    import starling.errors.MissingContextError; 
    import starling.textures.Texture; 

    public class Ball extends DisplayObject 
    { 
     private static const PROGRAM_NAME:String = "ball"; 

     private var _texture:Texture; 

     private var _numSides:uint; 

     private static const data32PerVertex:uint = 4; 

     private var _vertices:Vector.<Number>; 
     private var _indices:Vector.<uint>; 

     private var _vertexBuffer:VertexBuffer3D; 
     private var _indexBuffer:IndexBuffer3D; 

     public function Ball(initialX:Number, initialY:Number, initialR:Number, texture:Texture, numSides:uint = 10) { 
      _texture = texture; 
      _numSides = numSides; 

      // if the texture is a SubTexture (i.e. a texture from an atlas), then you need 
      // to modify these values to match the sub-texture UV bounds. 
      var minU:Number = 0, minV:Number = 0, maxU:Number = 1, maxV:Number = 1; 

      setupGeometry(initialX, initialY, initialR, minU, minV, maxU, maxV); 

      createBuffers(); 
      registerPrograms(); 
     } 

     private function setupGeometry(initialX:Number, initialY:Number, initialR:Number, uMin:Number, vMin:Number, uMax:Number, vMax:Number):void { 
      const numVertices:uint = _numSides + 1, 
        numSideVertices:uint = _numSides, 
        txtCu:Number = (uMin + uMax)/2, // center of the circle in UV coords 
        txtCv:Number = (vMin + vMax)/2, 
        txtRu:Number = uMax - txtCu,  // radiuses of the circle in UV coords 
        txtRv:Number = vMax - txtCv; 

      _vertices = new Vector.<Number>(data32PerVertex * numVertices, true); 
      _indices = new Vector.<uint>(3 * _numSides, true); 

      var centerVectexIndex:uint = _numSides; 

      // side vertices 

      for (var sideVertexI:uint = 0; sideVertexI < numSideVertices; ++sideVertexI) { 
       var dataOffset:uint = sideVertexI * data32PerVertex, 
        angle:Number = 2 * Math.PI * sideVertexI/_numSides, 
        sinA:Number = Math.sin(angle), 
        cosA:Number = Math.cos(angle); 

       _vertices[dataOffset ] = initialX + initialR * cosA; // x 
       _vertices[dataOffset + 1] = initialY + initialR * sinA; // y 
       _vertices[dataOffset + 2] = txtCu + txtRu * cosA; // u 
       _vertices[dataOffset + 3] = txtCv + txtRv * sinA; // v 

       var indexOffset:uint = 3 * sideVertexI; 

       _indices[indexOffset ] = centerVectexIndex; 
       _indices[indexOffset + 1] = sideVertexI; 
       _indices[indexOffset + 2] = (sideVertexI + 1) % numSideVertices; 
      } 

      // center vertex 

      dataOffset = centerVectexIndex * data32PerVertex; 

      _vertices[dataOffset ] = initialX; // x 
      _vertices[dataOffset + 1] = initialY; // y 
      _vertices[dataOffset + 2] = txtCu; // u 
      _vertices[dataOffset + 3] = txtCv; // v 
     } 

     private function createBuffers():void { 
      var context:Context3D = Starling.context; 
      if (context == null) { 
       throw new MissingContextError(); 
      } 

      _vertexBuffer && _vertexBuffer.dispose(); 
      _indexBuffer && _indexBuffer.dispose(); 

      const verticesCount:uint = _numSides + 1; 

      _vertexBuffer = context.createVertexBuffer(verticesCount, 4); 
      _vertexBuffer.uploadFromVector(_vertices, 0, verticesCount); 

      const indicesCount:uint = 3 * _numSides; // _numSides triangles, 3 indices per each triangle 

      _indexBuffer = context.createIndexBuffer(indicesCount); 
      _indexBuffer.uploadFromVector(_indices, 0, indicesCount); 
     } 

     private function registerPrograms():void { 
      var starling:Starling = Starling.current; 
      if (starling.hasProgram(PROGRAM_NAME)) { 
       return; 
      } 

      // va0.xy - position 
      // va1.xy - UV coords 
      // vc0-vc3 - mvp matrix 

      var vertexAGAL:String = 
       "m44 op, va0, vc0 \n" + 
       "mov v0, va1"; 

      var fragmentAGAL:String = 
       "tex oc, v0, fs0 <2d, clamp, linear, mipnone> \n"; // just sample texture color 

      var asm:AGALMiniAssembler  = new AGALMiniAssembler(), 
       vertexBytecode:ByteArray = asm.assemble(Context3DProgramType.VERTEX, vertexAGAL), 
       fragmentBytecode:ByteArray = asm.assemble(Context3DProgramType.FRAGMENT, fragmentAGAL); 

      starling.registerProgram(PROGRAM_NAME, vertexBytecode, fragmentBytecode); 
     } 

     override public function render(support:RenderSupport, parentAlpha:Number):void { 
      var context:Context3D = Starling.context; 
      if (context == null) { 
       throw new MissingContextError(); 
      } 

      support.finishQuadBatch(); 

      // setup 

      support.applyBlendMode(_texture.premultipliedAlpha); 
      context.setProgram(Starling.current.getProgram(PROGRAM_NAME)); 

      context.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); // position, va0 
      context.setVertexBufferAt(1, _vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); // uv, va1 
      context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, support.mvpMatrix3D, true); // mvp matrix, vc0-vc3 

      context.setTextureAt(0, _texture.base); // texture, fs0 

      // draw 

      context.drawTriangles(_indexBuffer); 
      support.raiseDrawCount(); 

      // clean up 

      context.setVertexBufferAt(0, null); 
      context.setVertexBufferAt(1, null); 
      context.setTextureAt(0, null); 
     } 

     override public function hitTest(localPoint:Point, forTouch:Boolean = false):DisplayObject { 
      var isHit:Boolean = false; 

      // to achieve proper mouse handling, you need to place here the code 
      // that checks if localPoint is contained inside any of triangles and 
      // sets isHit flag accorgingly. 

      return isHit ? this : null; 
     } 
    } 
} 

Использования:

package 
{ 
    import flash.display.BitmapData; 
    import flash.display.GradientType; 
    import flash.display.Graphics; 
    import flash.display.Sprite; 
    import flash.geom.Matrix; 

    import starling.display.Sprite; 
    import starling.textures.Texture; 

    public class BallExperiment extends starling.display.Sprite 
    { 
     public function BallExperiment() { 
     } 

     public function start():void { 
      const numSides:uint = 7; 

      var txt:Texture = createBallTxt(numSides, true); 
      var ball:Ball = new Ball(200, 200, 50, txt, numSides); 

      addChild(ball); 
     } 

     private function createBallTxt(numSides:uint, debugFillBcgr:Boolean = false):Texture { 
      var canvas:flash.display.Sprite = new flash.display.Sprite(), 
       g:Graphics = canvas.graphics; 

      // as we don't want to use sub-textures in this simple example, we need this 
      // number to be a power of two: otherwise Starling will internally create 
      // a power-of-two-sized texture and return a sub-texture of this bigger texture. 
      const size:Number = 512; 

      // we need to make the radius of a ball texture to be smaller than size/2 in order 
      // to prevent the texture from extending beyond our triangles. 
      var rScale:Number = Math.cos(Math.PI/numSides), 
       r:Number = rScale * (size/2); 

      g.lineStyle(0, 0, 0); 

      // draw uniform background to show actual triangulation 

      if (debugFillBcgr) { 
       g.beginFill(0xBB4400, 0.2); 
       g.drawRect(0, 0, size, size); 
       g.endFill(); 
      } 

      // draw the ball 

      g.beginFill(0x0000DD); 
      g.drawCircle(size/2, size/2, r); 

      var m:Matrix = new Matrix(); 
       m.createGradientBox(size, size); 

      g.beginGradientFill(GradientType.LINEAR, [0x00DD00, 0x00DD00], [0, 1], [0, 255], m); 
      g.drawCircle(size/2, size/2, r); 
      g.endFill(); 

      const smallCircleR:Number = r/10, 
        smallCircleCR:Number = r - 2 * smallCircleR; 

      g.beginFill(0xBB0000); 

      for (var i:uint = 0; i < numSides; ++i) { 
       var angle:Number = 2 * Math.PI * i/numSides, 
        cx:Number = size/2 + smallCircleCR * Math.cos(angle), 
        cy:Number = size/2 + smallCircleCR * Math.sin(angle); 
       g.drawCircle(cx, cy, smallCircleR); 
      } 

      g.drawCircle(size/2, size/2, smallCircleR); 
      g.endFill(); 

      // create and return the texture 

      var bmd:BitmapData = new BitmapData(size, size, true, 0); 
       bmd.draw(canvas); 

      return Texture.fromBitmapData(bmd); 
     } 
    } 
} 

Пример бегун:

package 
{ 
    import flash.display.Sprite; 
    import flash.display.StageAlign; 
    import flash.display.StageScaleMode; 

    import starling.core.Starling; 
    import starling.events.Event; 

    [SWF(width = 600, height = 500, frameRate = 60)] 

    public class StarlingTestRunner extends Sprite 
    { 

     public function StarlingTestRunner() { 
      stage.scaleMode = StageScaleMode.NO_SCALE; 
      stage.align = StageAlign.TOP_LEFT; 

      Starling.multitouchEnabled = false; 
      Starling.handleLostContext = false; 

      var starling:Starling = new Starling(BallExperiment, stage); 
      starling.showStats = true; 
      starling.simulateMultitouch = true; 
      starling.enableErrorChecking = true; 
      starling.addEventListener(Event.ROOT_CREATED, onTestCreated); 
      starling.start(); 
     } 

     private function onTestCreated(e:Event, test:BallExperiment):void { 
      test.start(); 
     } 
    } 
} 

Результат:

enter image description here

искажать б все, просто измените те элементы вектора _vertices, которые соответствуют x и y координатам (т. элементы с индексами 4n и 4n + 1, где n = 0 .. numSides), а затем повторно загружают массив _vertices в буфер вершин.

В качестве альтернативы, вы можете использовать геометрию шара с помощью вспомогательного класса VertexData, как показано в руководстве по скриню.

+0

Большое вам спасибо за ваш ответ! Это очень помогло. Я изучу пользовательский экранный экран при скрининге: http://wiki.starling-framework.org/manual/custom_display_objects –

+0

Добро пожаловать :) – skozin

Смежные вопросы