当前位置: 首页 > 编程日记 > 正文

如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4

在第一篇《如何使用CCRenderTexture创建动态纹理》基础上,增加创建动态山丘,原文《How To Create A Game Like Tiny Wings with Cocos2D 2.X Part 1》,在这里继续以Cocos2d-x进行实现。有关源码、资源等在文章下面给出了地址。

步骤如下:
1.使用上一篇的工程;
2.添加地形类 Terrain,派生自 CCNode类。文件 Terrain.h代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once
#include  "cocos2d.h"

#define kMaxHillKeyPoints  1000

class Terrain :  public cocos2d::CCNode
{
public:
    Terrain( void);
    ~Terrain( void);

    CREATE_FUNC(Terrain);
    CC_SYNTHESIZE_RETAIN(cocos2d::CCSprite*, _stripes, Stripes);

private:
     int _offsetX;
    cocos2d::CCPoint _hillKeyPoints[kMaxHillKeyPoints];
};

这里声明了一个_hillKeyPoints数组,用来存储每个山丘顶峰的点,同时声明了一个_offsetX代表当前地形滚动的偏移量。文件Terrain.cpp代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
#include  "Terrain.h"
using  namespace cocos2d;

Terrain::Terrain( void)
{
    _stripes =  NULL;
    _offsetX = 0;
}

Terrain::~Terrain( void)
{
    CC_SAFE_RELEASE_NULL(_stripes);
}

增加如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
void Terrain::generateHills()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
     float x =  0;
     float y = winSize.height /  2;
     for ( int i =  0; i < kMaxHillKeyPoints; ++i)
    {
        _hillKeyPoints[i] = ccp(x, y);
        x += winSize.width /  2;
        y = rand() % ( int)winSize.height;
    }
}

这个方法用来生成随机的山丘顶峰的点。第一个点在屏幕的左侧中间,之后的每一个点,x轴方向移动半个屏幕宽度,y轴方向设置为0到屏幕高度之间的一个随机值。添加以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool Terrain::init()
{
     bool bRet =  false;
     do 
    {
        CC_BREAK_IF(!CCNode::init());

         this->generateHills();

        bRet =  true;
    }  while ( 0);

     return bRet;
}

void Terrain::draw()
{
    CCNode::draw();
     for ( int i =  1; i < kMaxHillKeyPoints; ++i)
    {
        ccDrawLine(_hillKeyPoints[i -  1], _hillKeyPoints[i]);
    }
}

init方法调用generateHills方法创建山丘,draw方法简单地绘制相邻点之间的线段,方便可视化调试。添加以下方法:

1
2
3
4
5
void Terrain::setOffsetX( float newOffsetX)
{
    _offsetX = newOffsetX;
     this->setPosition(ccp(-_offsetX *  this->getScale(),  0));
}

英雄沿着地形的x轴方法前进,地形向左滑动。因此,偏移量需要乘以-1,还有缩放比例。打开HelloWorldScene.h文件,添加头文件引用:

1
#include  "Terrain.h"

添加如下变量:

1
Terrain *_terrain;

打开HelloWorldScene.cpp文件,在onEnter方法里,调用genBackground方法之前,加入如下代码:

1
2
_terrain = Terrain::create();
this->addChild(_terrain,  1);

update方法里,最后面添加如下代码:

1
_terrain->setOffsetX(offset);

修改genBackground方法为如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void HelloWorld::genBackground()
{
     if (_background)
    {
        _background->removeFromParentAndCleanup( true);
    }

    ccColor4F bgColor =  this->randomBrightColor();
    _background =  this->spriteWithColor(bgColor,  512512); 

    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    _background->setPosition(ccp(winSize.width /  2, winSize.height /  2));
    ccTexParams tp = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
    _background->getTexture()->setTexParameters(&tp);

     this->addChild(_background);

    ccColor4F color3 =  this->randomBrightColor();
    ccColor4F color4 =  this->randomBrightColor();
    CCSprite *stripes =  this->spriteWithColor1(color3, color4,  5125124);
    ccTexParams tp2 = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_CLAMP_TO_EDGE};
    stripes->getTexture()->setTexParameters(&tp2);
    _terrain->setStripes(stripes);
}

注意,每次触摸屏幕,地形上的条纹纹理都会随机生成一个新的条纹纹理,这方便于测试。此外,在Update方法里_background调用setTextureRect方法时,可以将offset乘以0.7,这样背景就会比地形滚动地慢一些。编译运行,可以看到一些线段,连接着山丘顶峰的点,如下图所示:

当看到山丘滚动,可以想象得到,这对于一个Tiny Wings游戏,并不能很好的工作。由于采用y轴随机值,有时候山丘太高,有时候山丘又太低,而且x轴也没有足够的差别。但是现在已经有了这些测试代码,是时候用更好的算法了。
3.更好的山丘算法。使用Sergey的算法来进行实现。打开Terrain.cpp文件,修改generateHills方法为如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void Terrain::generateHills()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

     float minDX =  160;
     float minDY =  60;
     int rangeDX =  80;
     int rangeDY =  40;

     float x = -minDX;
     float y = winSize.height /  2;

     float dy, ny;
     float sign =  1// +1 - going up, -1 - going  down
     float paddingTop =  20;
     float paddingBottom =  20;

     for ( int i =  0; i < kMaxHillKeyPoints; ++i)
    {
        _hillKeyPoints[i] = ccp(x, y);
         if (i ==  0)
        {
            x =  0;
            y = winSize.height /  2;
        } 
         else
        {
            x += rand() % rangeDX + minDX;
             while ( true)
            {
                dy = rand() % rangeDY + minDY;
                ny = y + dy * sign;
                 if (ny < winSize.height - paddingTop && ny > paddingBottom)
                {
                     break;
                }
            }
            y = ny;
        }
        sign *= - 1;
    }
}

这个算法执行的策略如下:

  • 在范围160加上0-80之间的随机数进行递增x轴。
  • 在范围60加上0-40之间的随机数进行递增y轴。
  • 每次都反转y轴偏移量。
  • 不要让y轴值过于接近顶部或底部(paddingTop, paddingBottom)。
  • 开始于屏幕外的左侧,硬编码第二个点为(0, winSize.height/2),所以左侧屏幕外有一个山丘。

编译运行,现在可以看到一个更好的山丘算法,如下图所示:

4.一次只绘制部分。在更进一步之前,需要做出一项重大的性能优化。现在,绘制出了山丘的1000个顶峰点,即使每次都只有少数在屏幕上看得到。所以,可以根据屏幕区域来计算哪些顶峰点会被显示出来,然后只显示那些点,如下图所示:

打开 Terrain.h文件,添加如下变量:

1
2
int _fromKeyPointI;
int _toKeyPointI;

打开Terrain.cpp文件,在构造函数里面添加如下代码:

1
2
_fromKeyPointI =  0;
_toKeyPointI =  0;

添加如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Terrain::resetHillVertices()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

     static  int prevFromKeyPointI = - 1;
     static  int prevToKeyPointI = - 1;

     // key points interval for drawing
     while (_hillKeyPoints[_fromKeyPointI +  1].x < _offsetX - winSize.width /  8 /  this->getScale())
    {
        _fromKeyPointI++;
    }
     while (_hillKeyPoints[_toKeyPointI].x < _offsetX + winSize.width * 9 /  8 /  this->getScale())
    {
        _toKeyPointI++;
    }
}

这里,遍历每一个顶峰点(从0开始),将它们的x轴值拿来做比较。无论当前对应到屏幕左边缘的偏移量设置为多少,只要将它减去winSize.width/8。如果顶峰点的x轴值小于结果值,那么就继续遍历,直到找到一个大于结果值的,这个顶峰点就是显示的起始点。对于toKeypoint也采用同样的过程。修改draw方法,代码如下:

1
2
3
4
5
6
7
8
9
void Terrain::draw()
{
    CCNode::draw();
     for ( int i = MAX(_fromKeyPointI,  1); i <= _toKeyPointI; ++i)
    {
        ccDrawColor4F( 1. 0001. 0);
        ccDrawLine(_hillKeyPoints[i -  1], _hillKeyPoints[i]);
    }
}

现在,不是绘制所有点,而是只绘制当前可见的点,这些点是前面计算得到的。另外,也把线的颜色改成红色,这样更易于分辨。接着,在init方法里面,最后面添加如下代码:

1
this->resetHillVertices();

setOffsetX方法里面,最后面添加如下代码:

1
this->resetHillVertices();

为了更容易看到,打开HelloWorldScene.cpp文件,在onEnter方法,最后面添加如下代码:

1
this->setScale( 0. 25);

编译运行,可以看到线段出现时才进行绘制,如下图所示:

5.制作平滑的斜坡。山丘是有斜坡的,而不是这样直上直下的直线。一个办法是使用余弦函数让山丘弯曲。回想一下,余弦曲线就如下图所示:

因此,它是从1开始,每隔PI长度,曲线下降到-1。但怎么利用这个函数来创建一个漂亮的曲线连接顶峰点呢?先只考虑两个点的情况,如下图所示:

首先,需要分段绘制线,因此,需要每10个点创建一个区段。同样的,想要一个完整的余弦曲线,因此,可以将PI除以区段的数量,得到每个点的角度。然后,让cos(0)对应p0的y轴值,而cos(PI)对应p1的y轴值。要做到这一点,将调用cos(angle),乘以p1和p0之间距离的一半(图上的ampl)。由于cos(0)=1,而cos(PI)=-1,所以,ampl在p0,而-ampl在p1。将它加上中点坐标,就可以得到想要的y轴值。打开Terrain.h文件,添加区段长度定义,如下代码:

1
#define kHillSegmentWidth  10

然后,打开Terrain.cpp文件,在draw方法里面,ccDrawLine之后,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ccDrawColor4F( 1. 01. 01. 01. 0);
CCPoint p0 = _hillKeyPoints[i -  1];
CCPoint p1 = _hillKeyPoints[i];
int hSegments = floorf((p1.x - p0.x) / kHillSegmentWidth);
float dx = (p1.x - p0.x) / hSegments;
float da = M_PI / hSegments;
float ymid = (p0.y + p1.y) /  2;
float ampl = (p0.y - p1.y) /  2;

CCPoint pt0, pt1;
pt0 = p0;
for ( int j =  0; j < hSegments +  1; ++j)
{
    pt1.x = p0.x + j * dx;
    pt1.y = ymid + ampl * cosf(da * j);

    ccDrawLine(pt0, pt1);

    pt0 = pt1;
}

打开HelloWorldScene.cpp文件,在onEnter方法,设置scale为1.0,如下代码:

1
this->setScale( 1. 0);

编译运行,现在可以看到一条曲线连接着山丘,如下图所示:

6.绘制山丘。用上一篇文章生成的条纹纹理来绘制山丘。计划是对山丘的每个区段,计算出两个三角形来渲染山丘,如下图所示:

还将设置每个点的纹理坐标。对于x坐标,简单地除以纹理的宽度(因为纹理重复)。对于y坐标,将山丘的底部映射为0,顶部映射为1,沿着条带的方向分发纹理高度。打开Terrain.h文件,添加如下代码:

1
2
#define kMaxHillVertices  4000
#define kMaxBorderVertices  800

添加类变量,代码如下:

1
2
3
4
5
int _nHillVertices;
cocos2d::CCPoint _hillVertices[kMaxHillVertices];
cocos2d::CCPoint _hillTexCoords[kMaxHillVertices];
int _nBorderVertices;
cocos2d::CCPoint _borderVertices[kMaxBorderVertices];

打开Terrain.cpp文件,在resetHillVertices方法里面,最后面添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
if (prevFromKeyPointI != _fromKeyPointI || prevToKeyPointI != _toKeyPointI)
{
     // vertices for visible area
    _nHillVertices =  0;
    _nBorderVertices =  0;
    CCPoint p0, p1, pt0, pt1;
    p0 = _hillKeyPoints[_fromKeyPointI];
     for ( int i = _fromKeyPointI +  1; i < _toKeyPointI +  1; ++i)
    {
        p1 = _hillKeyPoints[i];

         // triangle strip between p0 and p1
         int hSegments = floorf((p1.x - p0.x) / kHillSegmentWidth);
         float dx = (p1.x - p0.x) / hSegments;
         float da = M_PI / hSegments;
         float ymid = (p0.y + p1.y) /  2;
         float ampl = (p0.y - p1.y) /  2;
        pt0 = p0;
        _borderVertices[_nBorderVertices++] = pt0;
         for ( int j =  1; j < hSegments +  1; ++j)
        {
            pt1.x = p0.x + j * dx;
            pt1.y = ymid + ampl * cosf(da * j);
            _borderVertices[_nBorderVertices++] = pt1;

            _hillVertices[_nHillVertices] = ccp(pt0.x,  0);
            _hillTexCoords[_nHillVertices++] = ccp(pt0.x /  5121.0f);
            _hillVertices[_nHillVertices] = ccp(pt1.x,  0);
            _hillTexCoords[_nHillVertices++] = ccp(pt1.x /  5121.0f);

            _hillVertices[_nHillVertices] = ccp(pt0.x, pt0.y);
            _hillTexCoords[_nHillVertices++] = ccp(pt0.x /  5120);
            _hillVertices[_nHillVertices] = ccp(pt1.x, pt1.y);
            _hillTexCoords[_nHillVertices++] = ccp(pt1.x /  5120);

            pt0 = pt1;
        }

        p0 = p1;
    }

    prevFromKeyPointI = _fromKeyPointI;
    prevToKeyPointI = _toKeyPointI;
}

这里的大部分代码,跟上面的使用余弦绘制山丘曲线一样。新的部分,是将山丘每个区段的顶点用来填充数组,每个条纹需要4个顶点和4个纹理坐标。在draw方法里面,最上面添加如下代码:

1
2
3
4
5
6
7
8
9
10
CC_NODE_DRAW_SETUP();

ccGLBindTexture2D(_stripes->getTexture()->getName());
ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords);

ccDrawColor4F( 1.0f,  1.0f,  1.0f,  1.0f);
glVertexAttribPointer(kCCVertexAttrib_Position,  2, GL_FLOAT, GL_FALSE,  0, _hillVertices);
glVertexAttribPointer(kCCVertexAttrib_TexCoords,  2, GL_FLOAT, GL_FALSE,  0, _hillTexCoords);

glDrawArrays(GL_TRIANGLE_STRIP,  0, (GLsizei)_nHillVertices);

这里绑定条纹纹理作为渲染纹理来使用,传入之前计算好的顶点数组和纹理坐标数组,然后以GL_TRIANGLE_STRIP来绘制这些数组。此外,注释掉绘制山丘直线和曲线的代码。在init方法里面,调用generateHills方法之前,添加如下代码:

1
this->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTexture));

打开HelloWorldScene.cpp文件,在spriteWithColor1方法里面,注释// Layer 4: Noise里,更改混合方式,代码如下:

1
ccBlendFunc blendFunc = {GL_DST_COLOR, CC_BLEND_DST};

编译运行,可以看到不错的山丘了,如下图所示:

7.还不完善?仔细看山丘,可能会注意到一些不完善的地方,如下图所示:

增加水平区段数量,可以提高一些质量。打开Terrain.h文件,修改kHillSegmentWidth为如下:

1
#define kHillSegmentWidth  5

通过减少每个区段的宽度,强制代码生成更多的区段来填充空间。编译运行,可以看到山丘看起来更好了。当然,代价是处理时间。效果如下图所示:

在第二部分,将会实现海豹飞翔。
参考资料:
1.How To Create A Game Like Tiny Wings with Cocos2D 2.X Part 1 http://www.raywenderlich.com/32954/how-to-create-a-game-like-tiny-wings-with-cocos2d-2-x-part-1
2.(译)如何制作一个类似tiny wings的游戏:第一部分 http://www.cnblogs.com/zilongshanren/archive/2011/07/01/2095489.html
非常感谢以上资料,本例子源代码附加资源下载地址:http://download.csdn.net/detail/akof1314/5733037
如文章存在错误之处,欢迎指出,以便改正。

相关文章:

腾讯优图开源业界首个3D医疗影像大数据预训练模型

整理 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;近日&#xff0c;腾讯优图首个医疗AI深度学习预训练模型 MedicalNet 正式对外开源。这也是全球第一个提供多种 3D 医疗影像专用预训练模型的项目&#xff0c;将为全球医疗AI发展提供基础。许多研…

接口冲突的一种解决方法

问题描述&#xff1a;在一个大的项目中往往会包括很多模块&#xff0c;会有不同的部门或公司来负责实现某个模块&#xff0c;也有可能有第三方或客户的参与。假如他们都用到了某个开源软件&#xff0c;底层模块根据自身的需求对这个开源软件进行了修改或裁减。上层也用到了此开…

程序员:请你不要对业务「置之不理」

成长是条孤独的路&#xff0c;一个人会走得更快&#xff1b;有志同道合者同行&#xff0c;会走得更远。本篇内容整理自 21 天鲲鹏新青年计划线上分享内容。鲲鹏新青年计划是由 TGO 鲲鹏会组织的线上分享活动&#xff0c;希望能帮助更多同学一起学习、成长。12 月 28 日&#xf…

史上最简单的人脸识别项目登上GitHub趋势榜

来源 | GitHub Trending整理 | Freesia译者 | TommyZihao出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;导读&#xff1a;近日&#xff0c;一个名为 face_recognition 的人脸识别项目登上了 GitHub Trending 趋势榜&#xff0c;赚足了眼球。自开源至截稿&#xff0…

Centos 64位 Install certificate on apache 即走https协议

2019独角兽企业重金招聘Python工程师标准>>> 一: 先要apache 请求ssl证书的csr 一下是步骤&#xff1a; 重要注意事项 An Important Note Before You Start 在生成CSR文件时同时生成您的私钥&#xff0c;如果您丢了私钥或忘了私钥密码&#xff0c;则颁发 证书给您…

C/C++中“#”和“##”的作用和用法

在C/C的宏中&#xff0c;”#”的功能是将其后面的宏参数进行字符串化操作(Stringfication)&#xff0c;简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。而”##”被称为连接符(concatenator)&#xff0c;用来将两个子串Token连接为一个Token。注意这里连接…

国贫县山西永和:“一揽子”保险“保”脱贫

永和是吕梁山特困连片地区的深度贫困县&#xff0c;生产生活条件极差。 范丽芳 摄 永和是吕梁山特困连片地区的深度贫困县&#xff0c;生产生活条件极差。 范丽芳 摄 中新网太原1月16日电 题&#xff1a;国贫县山西永和&#xff1a;“一揽子”保险“保”脱贫 作者范丽芳 李海金…

内存泄漏检测工具VLD在VS2010中的使用举例

Visual LeakDetector(VLD)是一款用于Visual C的免费的内存泄露检测工具。它的特点有&#xff1a;(1)、它是免费开源的&#xff0c;采用LGPL协议&#xff1b;(2)、它可以得到内存泄露点的调用堆栈&#xff0c;可以获取到所在文件及行号&#xff1b;(3)、它可以得到泄露内存的完整…

天下武功,唯快不破,论推荐系统的“实时性”

作者 | 王喆转载自知乎王喆的机器学习笔记导读&#xff1a;周星驰著名的电影《功夫》里面有一句著名的台词——“天下武功&#xff0c;无坚不摧&#xff0c;唯快不破”。如果说推荐系统的架构是那把“无坚不摧”的“玄铁重剑”&#xff0c;那么推荐系统的实时性就是“唯快不破”…

新疆兵团开展迎新春“送文化下基层”慰问演出活动

演员表演舞蹈。 戚亚平 摄 演员表演舞蹈。 戚亚平 摄演员表演豫剧《花木兰》选段。 戚亚平 摄为物业公司员工送春联。 戚亚平 摄公安民警收到春联后留影。 戚亚平 摄走进退休职工家中表演节目。 戚亚平 摄为退休职工送春联。 戚亚平 摄 1月16日&#xff0c;2019年迎新春新疆生产…

Python爬取B站5000条视频,揭秘为何千万人为它流泪

作者 | Yura编辑 | 胡巍巍来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;导语&#xff1a;我们特邀作者Yura爬取B站5000条视频&#xff0c;为你揭秘电影《哪吒》的更多“优秀梗”&#xff0c;看完还能Get新技能&#xff0c;赶快往下滑吧。这个夏天&#xff0c;《哪…

父域与子域之的信任关系

搭了一个测试环境&#xff0c;做一个父、子域间信任关系的测试&#xff0c;过程如下&#xff1a;两台测试服务器&#xff0c;主域为primary.com&#xff0c;子域为child.primary.com客户机Clientpri加入父域&#xff0c;客户机Clientcli加入子域&#xff0c;父域中有一个用户为…

Ubantu安装maven

2019独角兽企业重金招聘Python工程师标准>>> 一、下载maven http://maven.apache.org/download.cgi 二、解压到指定目录 tar -xvf apache-maven-3.6.0-bin.tar.gz 三、添加环境变量 cd /etc vi profile 向其中添加 export M2_HOMEmaven所在目录 export M2$M2_HOME/b…

Leptonica在VS2010中的编译及简单使用举例

在tesseract-ocr中会用到leptonica库&#xff0c;这里对leptonica简单介绍下。Leptonica是一个开源的图像处理和图像分析库&#xff0c;它的license是BSD 2-clause。它主要包括的操作有&#xff1a;位图操作、仿射变换、形态学操作、连通区域填充、图像变换及像素掩模、融合、增…

IJCAI 2019精选论文一览,从底层到应用都有了

作者 | 神经小姐姐来源 | HyperAI超神经&#xff08;ID: HyperAI&#xff09;导语&#xff1a;为期一周的 IJCAI 第一天议程已经圆满结束。在前三天的工作坊上&#xff0c;全球各地人工智能行业人士&#xff0c;在此讨论 AI 在各个领域与方向的最新研究成果与未来动向。超神经特…

UITableView 添加长按手势UILongPressGestureRecognizer

2019独角兽企业重金招聘Python工程师标准>>> 给UITableView 添加长按手势&#xff0c;识别长按哪一行。 长按手势类UILongPressGestureRecognizer&#xff0c; 属性minimumPressDuration表示最短长按的时间 添加手势代码&#xff1a; UILongPressGestureRecogniz…

像我这种垃圾学校出来的人...【原话,不是我编的】

今天这标题&#xff0c;是咱们先行者课程的学生的原话&#xff0c;不是我编的&#xff0c;咱有截图为证&#xff0c;我这没别的意思&#xff0c;就是想说一下我自己的想法&#xff0c; 这种情况怎么办呢&#xff1f;也得生活啊&#xff0c;对吧&#xff0c;也不能人人都上清华北…

二维码Data Matrix简介及在VS2010中的编译

Data Matrix 二维条码原名Datacode&#xff0c;由美国国际资料公司(International Data Matrix, 简称ID Matrix)于1989年发明。Data-Matrix二维条码是一种矩阵式二维条码。Data Matrix符号由规则排列的深浅色正方形模块构成&#xff0c;每个正方形模块就是一个基本单元&#x…

一、数据库设计与性能优化--概述

前言我1998年第一次接触SQL Server 6.5 for Windows NT 4.0&#xff0c;当时的感觉就认为SQL Server只是一个功能强大的Excel文件。现在回想起来&#xff0c;当年抱着这样一种态度&#xff0c;我开发的那些应用程序应该是非常幼稚的&#xff0c;其性能可想而知。记得那时候随便…

第四范式戴文渊:AI落地,为什么不能照搬教科书?

“年少成名”、“天才”&#xff0c;在中国 AI 行业里用这两个词同时形容一个人的牛人不多&#xff0c;第四范式创始人戴文渊位列其中。在上海交通大学就读本科期间&#xff0c;戴文渊就带领三人团队夺得了 2005 年 ACM 的世界冠军和三个亚洲冠军&#xff0c;并担任ACM竞赛教练…

Kong Api 网关使用 docker 部署

Kong 镜像: https://hub.docker.com/_/kong 官网给定的用户安装手册上并没有设置 PG 的密码&#xff0c;导致如下问题无法启动 nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/kong/init.lua:277: [PostgreSQL error] failed to >retrieve server_version_num…

Windows7中搭建Android x86_64及armv8-a操作步骤

1. 从https://developer.android.com/tools/sdk/ndk/index.html 下载android-ndk-r10d-windows-x86_64.exe 和 android-ndk-r10d-linux-x86_64.bin&#xff1b; 2. 在Ubuntu1404 64位中通过终端安装ndkr10d&#xff1a;./android-ndk-r10d-linux-x86_64.bin ; 3.…

ContentResolver.query()—buildQueryString()

Cursor cursor context.getContentResolver().query(Sms.CONTENT_URI, new String[]{"thread_id from sms where type 3 group by thread_id—"}, // 可以这样使用。 null, null, null); 07-17 10:55:17.084: E/AndroidRuntime(30157): FATAL EX…

Room Database完全使用手册

前言 Android数据持久层直接使用SQLite很麻烦&#xff0c;Google官方推出了Room&#xff0c; Google对Room的定义&#xff1a; The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of …

wiki的使用

Wiki一词来源于夏威夷语的”weekee wee kee”&#xff0c;被译为”维基”或”维客”。Wiki是一种多人协作的写作编辑平台。在Wiki网站上&#xff0c;访问者可以修改、完善已经存在的页面&#xff0c;或者创建新内容。 可以利用”维基百科&#xff1a;沙盒”来练习如何编辑&…

GAMIT安装备忘

2019独角兽企业重金招聘Python工程师标准>>> 系统环境&#xff1a; VMware Workstation9 ubuntu 10.04 操作 1.安装VMware Workstation 参考&#xff1a; VMware Workstation下载&#xff1a;http://pan.baidu.com/share/link?shareid407480&uk258569718…

FreeType简介及在vs2010的编译使用

FreeType库是一个开源、高质量、可扩展、可定制、可移植的字体引擎&#xff0c;它提供统一的接口来访问多种字体格式文件&#xff0c;包括点阵字、TrueType、OpenType、Type1、CID、CFF、Windows FON/FNT、X11 PCF等。 FreeType有两个License&#xff0c;一个是BSD-stype&…

firefox下的调试工具

2019独角兽企业重金招聘Python工程师标准>>> vue-devtools https://addons.mozilla.org/en-US/firefox/user/13100848/ 转载于:https://my.oschina.net/u/3371661/blog/3003299

NLP为RPA带来了什么价值?

什么是 RPA&#xff08;Robotic Process Automation&#xff09;&#xff1f;机器人流程自动化&#xff08;RPA&#xff09;是一种自动化工具&#xff0c;用于创建软件机器人的虚拟劳动力&#xff0c;从而优化和降低企业中端到端业务流程的成本。RPA 可以翻译成机器人流程自动化…

从原理到代码,轻松深入逻辑回归模型!

整理 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;【导语】学习逻辑回归模型&#xff0c;今天的内容轻松带你从0到100&#xff01;阿里巴巴达摩院算法专家、阿里巴巴技术发展专家、阿里巴巴数据架构师联合撰写&#xff0c;从技术原理、算法和工程…