• Go Mobile 例子 audio 源码分析


    看这个源码分析前,建议先看更简单地例子 basic 的源码分析(http://www.cnblogs.com/ghj1976/p/5183199.html), 一些基础知识本篇将不再提及。

    audio 的源码比起 basic 最大的变化是使用了 golang.org/x/mobile/exp/sprite 这个对游戏精灵的封装包。

    有关 audio  的简单说明请看:https://godoc.org/golang.org/x/mobile/example/audio 

    它是一个跑来跑去的 Gopher ,当撞墙时会发出声音,并弹回来。

    这个游戏是使用的sprite 包做的, Sprite包 是一个 2D 场景下的渲染和动画封装包。
    Sprite包下面还有个glimage包 (目录在 golang.org/x/mobile/exp/sprite/portable)通过渲染引擎把 image包的图片以节点树的方式绘制出来。这个树的根节点就是要画的屏幕背景。上面的元素是根节点的子节点。

    有关 glimage 包的代码分析请看: http://www.cnblogs.com/ghj1976/p/5199789.html

    由于是树的数据结构,每个绘图元素都是一个自己的坐标系,这就涉及到坐标系的转换,相对父元素(父坐标系)的仿射变换关系矩阵 用下面 Engine 接口的 SetTransform函数来设定。

    SetTransform(n *Node, m f32.Affine) // sets transform relative to parent. 

    有关仿射变换矩阵的知识请看: http://www.cnblogs.com/ghj1976/p/5199086.html

    有关坐标系转换的知识请看: http://www.cnblogs.com/ghj1976/p/5215707.html

    下面是一些具体这个游戏实现的分析:

    背景的绘制

    关键代码

    image

    // ClearColor specifies the RGBA values used to clear color buffers.
    ClearColor(red, green, blue, alpha float32)

    该方法设置OpenGl ES"清屏"所用的颜色,四个参数分别设置红、绿、蓝、透明值:0为最小值,1为最大值。例如ClearColor(0, 0, 0, 0);就是用黑色“清屏”。

    // Clear clears the window.
    // The behavior of Clear is influenced by the pixel ownership test,
    // the scissor test, dithering, and the buffer writemasks.
    Clear(mask Enum)

    mask
    Bitwise OR of masks that indicate the buffers to be cleared. The three masks are GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, and GL_STENCIL_BUFFER_BIT.

    可以使用 | 运算符组合不同的缓冲标志位,表明需要清除的缓冲

    • GL_COLOR_BUFFER_BIT:    当前可写的颜色缓冲
    • GL_DEPTH_BUFFER_BIT:    深度缓冲
    • GL_STENCIL_BUFFER_BIT: 模板缓冲

    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    第一条语句表示清除颜色设为黑色,第二条语句表示实际完成了把整个窗口清除为黑色的任务,glClear()的唯一参数表示需要被清除的缓冲区。

    参考: http://www.xuebuyuan.com/1268040.html

    递归绘图

    接上面的onPaint方法, 这里面完成背景绘制后,就是做的绘图引擎的场景绘制,如下图代码入口, 这里是一个树节点的递归绘制。
    eng.Render(scene, now, sz) 里面我们可以看到是递归绘制每个有贴图的节点
    func (e *engine) render(n *sprite.Node, t clock.Time, sz size.Event) {
    这个树节点的层次关系如下图:
    有一个根节点,一个子节点:
    image
    注意, 子节点的 相对转换 relTransform 不是仿射变换矩阵, 而是三个点的坐标(或者叫一个点+2个向量)合成的矩阵,
    看起来像 仿射变换矩阵,但是实际不是。
    原因是,仿射变换矩阵需要跟具体点坐标相乘后,才是转换后的矩阵, 而我们在具体绘图时看到, 这个 relTransform 计算后的结果直接就当点来用了。
      
    引擎的绘制在 eng.Render(scene, now, sz) 函数里面,具体这个函数的实现在 glsprite 中,这里的绘制逻辑如下图:
    image
    abs 是 absolute 绝对的缩写 ;  rel 是 relatively 相对的缩写。

    具体的绘制函数用的是(对这个函数的分析请看:http://www.cnblogs.com/ghj1976/p/5199789.html

    func (img *Image) Draw(sz size.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle)

    这里传入的是三个点, 即平行四边形的  左上、右上、左下 这三个点。

    absTransforms 在所有 相对 relTransform 相乘完毕后, 算出的是 左上,  右上比左上的X、Y轴位移, 左下比左上的X、Y轴的位移值。

    所以在传入 Draw 的时候, 会有下面的写法:

    image

    从矩阵运算的角度来说,最后一个矩阵的列,只会影响,不会影响最终值的其他列,只会影响本列,如下图:

    image

    所以最后这个relTransform  用三个节点来作为这个矩阵的三列是可行的。

    image

    这个相对转换,最后是三个坐标点的可以用下图表示:

    image

    精灵的动画行为定义

    我们用下面方式实现对精灵的行为定义:

    image

    这个定义是遵循下面接口定义的:

    image

    为了在引擎处理时,调用这个行为逻辑:

    image

    我们这里有个小技巧实现了这个调用:

    把行为函数定义成一个类型,然后这个类型实现了 Arrange 接口, 如下代码。

    image

  • 相关阅读:
    WebView.简单使用_ZC代码
    WebView.简单使用_资料
    APK.错误解决_Theme.AppCompat.Light相关
    USB调试.红米Note4X
    Android_连接数据库_资料收集
    APK签名_ZC
    APK签名_资料
    ubuntu系统中代替windows系统中onenote软件--basket note pads
    firefox浏览器设置新页面后激活
    oracle 写declare例子
  • 原文地址:https://www.cnblogs.com/ghj1976/p/5216345.html
Copyright © 2020-2023  润新知