欢迎

这是解释在flash,actionscript中如何使用 向量 的教程,你不需要懂太多的数学知识,当然懂得多更好。
请注意此教程只讨论2d 向量,如果你想了解 3D 向量恐怕你不得不寻找其他的教程了。

不是每个游戏都需要向量,在基于文字的冒险游戏(text-based adventure game)好象不是太需要向量计算,但是在大多数动作游戏中向量能给你巨大的帮助:例如 高尔夫球,弹球,迷宫游戏,赛车,射击的游戏,他们都得益于更好的物理学,这些都可以用向量来完成。

这个教程是基于actionscript和Macromedia Flash的,如果你从来没用flash做过游戏的话,他们
也许很难读懂,加上我的英语不是很好,也许会有很多错误,或有些部分没有解释清楚,对不起,
我已经尽力了,如果你发现漏洞或错误,请告诉我。

我是用Flash5来写这些代码的。主要因为用得比较顺手。这些代码和原文件在FlashMX(ver6)中也会运行的很好,不会出任何问题。在FlashMX2004(ver7)和新的AS2中可能不兼容这些旧的代码,所以这些代码可能会失败,也可能会工作的很好,但一般来讲如果你真的想用AS2,你应该自己重写这些代码。当然这些思想是依然可用的,所以无论如何这些教程都是值得看的。

例子代码和原文件在创作公用协议的约定下是免费使用的

我希望在这里你能找到些有用的东西:)

谢谢

Tony 2005

基础知识:

基础。向量从哪来?

如果你做过游戏,很可能你已经尝试过将movie clip 放到舞台上,并移动他们。那么你肯定知道

每个movie clip都有两个相关的属性,x 和 y。所以你可以在舞台上声名每个点像这样:

p={x:10, y:5};

好,这样我们创建一个点对象“p”,我们不只要创建它,还要管理他的两个属性“x”和“y”,现在你可以在任何时候访问他们,像这样:

p.x
p.y

把点p的x属性设为10,y属性设为5。现在你可以创建一个movie clip并把他放到舞台上使用这两个坐标了。当然你不需要创建一个movie clip,所有的数学计算仍然可以正常工作,我们只是用movie clip来演示,当然在一个真正的游戏中你仍然需要一些东西在舞台上四处移动,否则也许是非常好的代码,但却一定是非常另人讨厌的游戏。

记住,在Flash中使用相反的y坐标,在人们所知道的大多数领域中y坐标的正方向是朝上的,但在

Flash中是向下的。

这样,我们已经创建了一个点,并看到它在舞台上的位置了,哈,是时候增加些难度了。现在我们创建

2个点:

p0={x:10, y:5};
p1={x:12, y:6};

在你注意到你已经创建了你的第一个向量前,不要感到惭愧,它发生在每个人身上,人们创建向量

是非常正常的。向量,你看是由两个点组成的,点p0叫做“起点”点p1(屏住呼吸)叫做“终点”

。记住向量是有方向的是非常重要的,就像人类有知觉,p0->p1 和p1->p0是不同的,他们非常相

似,他们有相同的长度,相同的点,但他们是相反的方向。我们精确的声明,伴随着他的伟大而诞

生:

v={
p0:{x:10, y:5},
p1:{x:12, y:6}
};

好了,我们用这两点画出这个向量:

你也许会想这个太简单了,或者在想为什么这杯咖啡味道有些奇怪,不要着急我们还没完成呢。
向量也可以由“起点”和“方向”组成。但不要把我们可怜的p1扔了!我们一会儿还需要它呢。
恩。。。那怎么能不用终点来创造一个向量呢?简单:

v={
p0:{x:10, y:5},
vx:2,
vy:1
};

看起来很亲切?当然,这个跟我们之前的向量是完全相同的。我们有相同的起点(快看看!)我们还有相同的x增量2,y增量1。这个向量说(如果向量会说话 - -)“从起点x=10,y=5向右走两步,向下走一步”。如果你跟着做,哦,难以置信,你结束的这点正是点p1。事实上,每个向量的终点都可以由它的起点个x,y增量计算出来:

v.p1={};
v.p1.x=v.p0.x+v.vx;
v.p1.y=v.p0.y+v.vy;

恩,万一你的向量开始就由两个点构成,你也可以轻松的找到x,y增量:

v.vx=v.p1.x-v.p0.x;
v.vy=v.p1.y-v.p0.y;

从现在开始,无论何时我们提到某个向量,我们都知道它有两个点p0和p1,每个点都有x,y属性,
Vector本身含有x,y增量。

如果你利用起点和向量来移动某个物体,这个向量通常会有很多不同的名字但意义基本上相同:"speed", "velocity", "movement", "displacement". 不要为这些名字烦恼,这些只不过是在x,y方向移动物体罢了。

基础。向量有什么

有了两个点和x,y增量已经足够使每个向量感到很高兴了,他们还有更有用的刀具。每个向量都有长度。向量的长度是起点与终点之间的真实距离。
只要我们知道x,y增量就可以非常简单的求出它的长度:

v.len=Math.sqrt(v.vx*v.vx+v.vy*v.vy);

这实际上是来自古希腊数学家毕达哥拉斯的勾股定理,x增量的平方与y增量的平方之和再取平方根。

向量的好处在于你使用它时,因为你可以不必再面对角度,正弦和其他一些虎人的咚咚.但我知道很多人还是非常喜欢使用角度的。幸运的是转变成角度是非常简单的(目前为止,所有的都很简单):

angle=Math.atan2(v.vy, v.vx)

你可能知道Flash是多么的喜欢用弧度来量度角度,所以如果你想让你的movie clip正面一直朝着运动向量的方向,你需要把你的角度量度单位转成度:

angledeg=angle*180/Math.PI;

有时你知道角度和长度,你想用这些来创造一个向量却不知道怎么做。别急,这并不太复杂(嘿,偶这次没说“简单”)

v.vx=v.len*Math.cos(angle);
v.vy=v.len*Math.sin(angle);

哪个向量是标准的?

你也许会很奇怪,但并不是所有向量都是标准的。像人一样,有些人是比较正常有些人却喜欢隐居山林,不喜欢与人接触,不同的是每个向量都能被标准化,想标准化就要找到相同方向但长度为1的单位向量。

v.dx=v.vx/v.len;
v.dy=v.vy/v.len;

通过x,y增量和向量长度,我们找到了单位向量,跟一般的向量差不多,都有两个分量dx,dy。单位向量的长度为1,你可能想算一算,事实上就是在用我们的勾股定理朋友去求dx,dy向量的长度。

如果你确实懒得去算它,相信我就好。规格化了的向量只告诉了我们方向,并没有告诉我们距离。就像你在说“火车站在那边”你只交代了方向,并没有说具体离火车站多远。

区分的时候你一定要确定它不是零向量,向量的长度有可能是零,但它仍然是向量,如果你不事先检查向量长度,要标准化它会很麻烦。Flash会给它个“Infinity”值。

向量还有“法线”,他们完全垂直于偶们的向量。或者你非要粘着角度不放的话,它是偶们向量旋转90度得到的。每个向量都有两个法线,右法线,左法线。让我们想象一下你站起来(我知道你实际上是在坐着读这篇教程,或许你喜欢像这样坐在那读,但是偶尔站起来一下对你还是有好处的)然后面向着向量的方向。现在,如果你愿意将两臂从两边抬起远离你身体的话,你的手会告诉你左右法向量。

左右法向量是可以被计算出来的:

v.rx = -v.vy;
v.ry = v.vx;
v.lx = v.vy;
v.ly = -v.vx;

在最后,我做了个小影片,你可以在周围拖拽里边的点,看看向量是怎样变化的:

点这里 显示/隐藏 媒体

attachments/200510/14_004333_vect2.swf

黑线的是向量,蓝线的是单位向量,绿色的是右法向量还有红色的是左法向量。你也可以下载这个 源文件。

投影(projections )

有时候知道两个向量是怎样定向的是非常有用的。意思就是当两个相同或相反方向的向量同时作用一个物体时

dp = v1.vx*v2.vx + v1.vy*v2.vy;

我们将两个向量的x,y分量分别相乘,并将结果相加。得到的这个变量dp叫做“向量v1,v2的点乘”。dp不是一个向量,它只是一个数字,如果它是正数则两个向量指向相同的方向,如果是负数则他们的方向相对。

现在我们说有两个向量作用这个物体,我们想知道向量v1怎么向v2投影。能转变向量到任何坐标系统是非常有用的。(向量v2和它的法线构成了一个坐标系统)投影的两个分量会分别的改变。计算向量v1在v2上的投影:

proj.vx=dp*v2.dx;
proj.vy=dp*v2.dy

投影又是一个向量,我们求它用两个向量的点乘(dp)分别乘以v2的单位向量(dx/dy)。

这里我做了个向量投影的例子。你可以拖拽点来观察投影分量的改变:

点这里 显示/隐藏 媒体

attachments/200510/14_021942_vect3.swf

黑线是向量v1,蓝线是向量v2和它的法线,红线和绿线分别为v1在v2和v2法线上的投影。

你可以下载这个 源文件

用向量移动

希望你已经读了上边的基础章节,到现在你已经知道什么是点,什么是向量也知道了怎么计算向量相关的一些东西,为了真正把向量用在游戏中你已经付出了很大努力了,那么就开始看看到底怎么用向量来移动物体吧。

在这个例子里,红点就是我们要移动的物体。你可以用方向键改变他运动向量的x,y分量

点这里 显示/隐藏 媒体

attachments/200510/14_154035_vect4.swf

首先我们声明一下这个对象:

myOb={};
myOb.p0={x:100, y:150};
myOb.vx=3;
myOb.vy=1;

这个对象的起点为x=150,y=100,移动向量的两个分量vx=3,vy=1。新的位置应该是向量的终点(p1),这个是在updateVector函数中计算的。如果你不记得怎么找到向量的终点p1,那么就请回头看看前边关于点和向量的章节。 drawAll函数负责把movie clip放好到终点位置,并把终点p1设置为起点,以便下次使用。

无论什么时候按方向键,x或y分量都会增加或减少。这是getKeys和 releaseKeys函数干的。主函数runMe在每一帧都会执行,它调用updateVector函数去找到下一个新位置,并用drawAll函数将mc放到那里。在这个例子里我们还检查物体是否移出了舞台,如果那样,我们会让它从另一边出来。

记住,绝对不要在计算过程中使用movie clip的_x和_y属性,它一定要在所有的计算完成后的最后,用来把movie clip放到计算好后的正确位置。

帧还是时间

再看一遍updateVector函数,看看p1的新坐标是怎么找到的:

var thisTime=getTimer();
var time=(thisTime-v.lastTime)/100;
v.p1={};
v.p1.x=v.p0.x+v.vx*time;
v.p1.y=v.p0.y+v.vy*time;
v.lastTime=thisTime;

Flash是基于帧的程序,它会每秒按你设置的帧频努力的执行所有的动画和as代码。一般情况都是用enterFrame影片事件来处理所有的计算,但是实际上这不是一个好的方法。想象一下,你已经写了代码将物体每帧移动1。如果你设置帧频率为20,那么这个代码每秒会运行20次,结果就是这个物体每秒移动20个象素。

或许你认为这是对的,但实际上Flash没有精确的按照帧频运行。这个帧频只不过是个最大值,Flash Player也努力的去达到这个最大值,但通常都是失败的。影片糟到了浏览器的损害,因为浏览器需要一些cpu周期,有的电脑比其他的慢,或者同时有其他程序在运行,所有这些导致在一般情况下帧频都会下降20-25%。

你可能会感到惊讶“那又怎样?”。它仍然会工作,坐标也没错,movie clip也仍然会被放到正确的位置,是的,但是这游戏已经不再你的控制之下了。在经过一段时间后,你就不能知道movie clip到底在哪,也不会知道它的实际移动速度是多少。如果你的游戏是用来考验人们反映能力的话。当它的帧频下降50%后再玩,肯定会比在正常(几乎正常)帧频玩的人要有优势。在Flash游戏中这是个普遍的作弊方法,你可以很容易的降低影片速度,去做任何通关需要的事情。

解决方案是在计算中不要靠你的帧,而需要真正的时间。在基于帧的游戏(frame-based game)中声明一个物体的速度vx=3的意思是Flash Player每次更新,这个movie clip将移动3个象素。在基于时间的游戏(time-based game )中声明速度vx=3的意思是每秒移动3个象素。在基于时间的游戏中不会使你找不到结果,你仍然知道这个movie clip 1秒后,10秒后,甚至1小时后在哪。在基于时间的游戏中,降低帧频能影响运动的平滑程度,物体每秒将出现更少次,移动可能变得有些“神经质”,但是每次物体都会被放到完全正确的位置。

我们使用getTimer函数找出时间:

var thisTime=getTimer();
var time=(thisTime-v.lastTime)/100;

getTimer返回从影片开始到现在的豪秒数。在移动计算中我们需要从上次到现在经过的这段时间,所以我们从当前时间减去上次的时间。因为时间是豪秒,我们需要把它除以100得到秒。你当然也可以用豪秒做单位,但这样的值显得太小了。

利用时间的经过计算出新的终点坐标:

v.p1.x=v.p0.x+v.vx*time;

我们看看是否正确,想象我们的movie clip在x=150,y=100,vx=1。如果帧频设置为20, 在这种情况下time变量有可能为5到50豪秒之间。当time变量为5豪秒,会得到v.p1.x=v.p0.x+0.05,1秒中移动20次后,物体移动了20*0.05=1象素。这正好是我们的速度vx。现在,如果time为50,计算新的坐标,虽然movieclip只在舞台上出现了两次,但它仍然是2*0.5=1象素。

你可以下载 原文件。

加速度

就像速度向量可以随着时间的流逝改变物体的位置一样,加速度向量可以随着时间的流逝改变物体的速度。

点这里 显示/隐藏 媒体

attachments/200510/17_223936_vect4a.swf

所以我们在开始我们把物体的加速度向量设为 0:

myOb.ax=0;
myOb.ay=0;

现在我们检查是否方向键被pressed,如果被pressed我们改变加速度的x,y分量。在update函数中我们将加速度向量与速度向量相加,小心使用你的加速度,如果你不限制你的速度接着你的速度会不断的增加增加再增加(= =b)。

v.vx=v.vx+v.ax;
v.vy=v.vy+v.ay;

同样注意到,要完全停止物体移动单把速度向量设置为0是不够的,你同样需要将加速度向量设为0,否则物体会继续保持移动状态。

你可以下载 原文件。

交点

现在你知道如何移动物体,就像生命被证实一样,每个移动中的物体迟早会碰到其他东东。例如这个移动物体是你,你很走运也许只碰到一些软的东西,比如床,但是你也会碰到硬的材料。砖墙。水泥地板。关着的门。自然界有很多不令人高兴的硬物在等着与你或其他物体相撞。所以知道在未来与哪个物体相撞是对你身体有好处的,也是明智的。

我们知道物体的移动向量。我们还知道虚构墙的向量(ok,这墙看起来像条细线,但你仍然需要小心)。我们想知道,是否,什么时候,在哪里,这个物体会跟墙碰撞。或者可以这么说“两个向量在哪相交?”

首先我们看看什么时候向量不会相交。向量在平行的时候不会相交。而当向量的单位向量相等(不需要相同的方向,相反也可以)时,他们平行:

(v1.dx==v2.dx and v1.dy==v2.dy) or
(v1.dx==-v2.dx and v1.dy==-v2.dy)

如果他们不平行,则迟早会相交。

绿线是以v1.p0为起点的移动向量,红线是以v2.p0为起点的墙,蓝线是v1,v2的起点之间的向量:

交点坐标可以像这样计算出来:

v3={vx:v2.p0.x-v1.p0.x, vy:v2.p0.y-v1.p0.y};
var t=perP(v3, v2)/perP(v1, v2);
ip={};
ip.x=v1.p0.x+v1.vx*t;
ip.y=v1.p0.y+v1.vy*t;
function perP(va, vb){
  pp = va.vx*vb.vy - va.vy*vb.vx;
  return pp;
}

首先我们找到起点间的向量v3。函数用这个去计算两个向量的perp product(nshen注:不会翻译 - -b)。Perp product跟点乘(dot product)有些相似只是把第一个向量换成了它的法向量。点乘是这样计算的:

dp = v1.vx*v2.vx + v1.vy*v2.vy;

法向量是:

v.rx = -v.vy;
v.ry = v.vx;

我们将v1换成它的法向量,我们得到:

pp = -v1.vy*v2.vx + v1.vx*v2.vy;

这正是perP函数中求的。

2个perp products 的比率“t”正好是1时,交点就是运动向量v1的终点。如果“t”是在0和1之间,那么交点就在这向量上。然而如果“t”是负数那么这个向量在过去曾有过交点,如果t大于1,那么在将来的某时会有交点。(nshen注:这段介绍的不太清楚,最好在原文件118行var t = perP(v3, v2)/perP(v1, v2);后加trace(t)自己观察下结果)

当然如果你想知道是否焦点在任何一个向量上,你不得不为v2找到t:

v3={vx:v1.p0.x-v2.p0.x, vy:v1.p0.y-v2.p0.y};
var t=perP(v3, v1)/perP(v2, v1);

在这个例子中尝试拖动点,看看向量在哪相交:

点这里 显示/隐藏 媒体

attachments/200510/18_020351_vect5.swf

如果你对交点的运算法则是如何发现的感兴趣,请看这里:
http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm

你可以下载 原文件

反弹

一旦碰撞发生,通常物体会从障碍物弹开。你的头撞墙也许不太明显(我不推荐你去尝试,那样只能让你头疼),但是观察像球一样的东西就很容易发现它极少穿过障碍物或者停在障碍物附近。

让我们看看如何找到碰撞后的新移动向量。

在图片中红线是移动向量,绿的是墙(向量),黑的是墙的法线,蓝的是碰撞后得到的新移动向量。粗线是运动向量在墙与墙的法线上的投影。
很明显的看到原向量和碰撞后得到的新向量不一致。没看到?好,那看他们的投影。在墙上的投影完全相同,但是在墙的法线上的投影却方向相反。到这里我们可以很容易的创建出移动物体撞墙后反弹的系统:

*找到交点
*找到移动向量的投影
*反转法线上的投影
*将投影相加

如果你忘记了投影或怎么找到投影,回头看看前边的章节。

v1是我们的移动向量。v2是墙(障碍物)向量。v2的左法向量:

v2.lx=v2.vy
v2.ly=-v2.vx

v1与v2的点乘:

dp1 = v1.vx*v2.vx + v1.vy*v2.vy;

在v2上的投影:

proj1.vx=dp1*v2.dx;
proj1.vy=dp1*v2.dy;

v1与v2法向量的点乘:

dp2 = v1.vx*v2.lx + v1.vy*v2.ly;

在v2上的投影:

proj1.vx=dp1*v2.dx;
proj1.vy=dp1*v2.dy;

v1与v2法向量的点乘:

dp2 = v1.vx*v2.lx + v1.vy*v2.ly;

移动向量在v2左法向量上的投影(注意怎么求的左法线单位向量):

proj2.vx=dp*(v2.lx/v2.len);
proj2.vy=dp*(v2.ly/v2.len);

法线上的投影取反:

proj2.vx*=-1;
proj2.vy*=-1;

合并投影,求出新的移动向量:

v1.vx=proj1.vx+proj2.vx;
v1.vy=proj1.vy+proj2.vy;

在这个例子中尝试拖动点,看看移动向量是如何改变的:

点这里 显示/隐藏 媒体

attachments/200510/19_231616_vect6.swf

你可以下载这个 原文件

真实的弹力和摩擦

真实生活中因为阻力和能量损耗没有物体可以永远移动,当然弹力也不是完美的。完美的弹力是碰撞后移动向量的长度跟碰撞前一样。我们认为在弹性中的能量损耗是两个变量作用在物体上:“bounciness”和“friction”

ob.b=0.99;
ob.f=0.99;

我们已经找到了新的移动向量,现在我们可以将每个投影乘以两个对象的b和f。Bounciness影响墙的法向量,friction影响墙方向向量。

v1.vx=v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
v1.vy=v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;

如果各个对象的b和f等于1怎么样呢?那么我们会得到完美的弹性--碰撞后没有任何能量损失,所受的力完全相同。如果移动的物体或者墙没有弹力(b=0)那么碰撞后移动向量平行于墙,物体贴住墙,想象一下,球飞到柏油或胶水上。

当然你的弹性参数也可以大于1,什么情况下碰撞后会使速度加快呢。有个好的例子就是弹球游戏中的缓冲器,一旦碰到他们,这个球就会得到额外的速度。

在这个例子中,有一个受到重力影响的点和许多面墙。你可以移动墙的终点。

点这里 显示/隐藏 媒体

attachments/200510/21_011032_vect6a.swf

Moving point loops through all the walls and checks if it will hit any of them in time that was passed since last check. If it would hit multiple walls, then the wall with closest intersection point is picked. Then the end point of object is set to intersection point and new movement vector is calculated. End point is then moved from intersection point to the direction of new vector substracting the value it took to get from original starting point to intersection point.

You can improve the system further with at least two ways:
1. Because object is drawn last time on screen at starting point p0 and next time at ending point p1 then human eye doesnt see it never go near the wall at intersection point ip. It might result to see object moving straight from p0 to p1. While not correct, sometimes the object is placed at the intersection point and whole screen is updated so the eye can see it hitting the wall.
2. It is possible for object to hit another wall after first wall. Currently only closest wall is bounced from. To be sure, you could start checking of collision with every wall over after new vector is found. Then you should only check for new vector from intersection point to p1 (blue in the picture).

You can download the source fla.

原文:http://www.nshen.net/blog/article.asp?id=368

http://www.tonypa.pri.ee/vectors/start.html

基于向量的flash开发相关推荐

  1. html5做动画视频教程,基于HTML5的Flash动画开发视频教程

    (xuehui@TLF) Lynda.com 出品的时长3小时16分的基于HTML5的Flash动画开发视频教程.由Lee Brimelow演示了Flash开发人员在浏览器中利用HTML5,CSS或其 ...

  2. [转]基于Starling移动项目开发准备工作

    最近自己趁业余时间做的flash小游戏已经开发得差不多了,准备再完善下ui及数值后,投放到国外flash游戏站.期间也萌生想法,想把游戏拓展到手机平台.这两天尝试了下,除去要接入ane接口的工作,小游 ...

  3. Flash开发的基本概念

    有好几年没有接触过Flash了,MM公司被Adobe收购后,Flash应该来说发展的是非常好的. Adobe的策略好像与微软有点类似,提供一个免费甚至开源(微软的Windows SDK暂时是不可能开源 ...

  4. 基于Starling移动项目开发准备工作

    转自: Starling中文站 -  Starling移动开发教程 作者: 郭少瑞(NeoGuo) 现在移动开发可谓热火朝天,如果您是一位Flash开发者,或许您所在的团队,已经开始基于Flash内容 ...

  5. 基于STM32的Flash擦除方式

    基于STM32的Flash擦除方式 前言 介绍 STM32 FLASH 闪存的编程和擦除 Flash擦除的标准库函数 软件设计 直接使用固件库函数擦除当前地址所在的内容 擦除对应地址和大小的Flash ...

  6. SpringBoot 基于向量搜索引擎及虹软人脸识别SDK的大规模人脸搜索

    SpringBoot 基于向量搜索引擎及虹软人脸识别SDK的大规模向量数据搜索 文章目录 SpringBoot 基于向量搜索引擎及虹软人脸识别SDK的大规模向量数据搜索 在线环境demo 在线环境说明 ...

  7. 2021物联网开发学习——基于小熊派IoT开发板Bear-Pi-IOT、E53_IA1_智慧农业拓展板与小熊派-鸿蒙·季Bear-Pi-HM Nano并接入Hi-Link

    2021物联网开发学习--基于小熊派IoT开发板Bear-Pi-IOT.E53_IA1_智慧农业拓展板与小熊派-鸿蒙·季Bear-Pi-HM Nano并接入Hi-Link 目录 作者介绍 目的 用到的 ...

  8. Flash开发环境简介

    目前的Flash制作中,除了基于时间轴的动画外,使用AS脚本开发的应用越来越多.开发基于时间轴的flash的理想工具当然是Adobe的Flash系列,包括Flash 8,Flash MX2004,Fl ...

  9. 30多个最受用的基于XML的Flash相册教程 -- Part I

    我们一直热衷于收录出色的作品来做成专题,今天就要向大家介绍一些 非常受用的基于XML的Flash相册教程(XML是一种网络脚本,大多数flash开发者都用它来存取数据). 下面列出的 教程不仅能帮助您 ...

最新文章

  1. Alibaba代码规范插件、FindBugs插件安装及详解,IDEA插件安装,代码规范,代码查错,代码格式规范
  2. c语言中external,static关键字用法
  3. 使用jquery在新窗口中打开外部链接
  4. 什么是光纤以太网交换机?
  5. 从L1 loss到EIoU loss,目标检测边框回归的损失函数一览
  6. shell 删除simatic_安装西门子软件时提示重启电脑的解决办法
  7. 设备描述符请求失败_如果用户发出过多请求 苹果将取消Apple ID帐户恢复
  8. 项目应用EasyUI_Tab控件全部关闭
  9. mysql max_pac_如何解决 MySQL max
  10. Kafka负载均衡、Kafka自定义Partition、Kafk文件存储机制
  11. java匿名内部类 内部类_java中的匿名内部类详细总结
  12. java-php-python-ssm在线购书商城系统计算机毕业设计
  13. 业务系统+电子签章开放平台,快速构建个性化的电子签署应用
  14. Android平台压缩纹理ETC2 VS ASTC
  15. 知识图谱指南:从理论到应用
  16. 高通平台android 8.1基线某款usb camera打开dev/video1出错
  17. OpenCV图像基本操作——图像合成
  18. 小云路由器mysql地址_小云OS3.0,极简操作,让小白玩转离线下载和NAS(转发)
  19. 四旋翼无人机学习第4节--STM32、MPU9250等器件的绘制
  20. 用photoshop更换照片背景步骤

热门文章

  1. java如何给密码加密_Java如何实现密码加密
  2. 01背包问题(动态规划解决)
  3. 未来教育1级计算机基础及ms,未来教育·全国计算机等级考试教程:一级计算机基础及MS Office应用...
  4. 猪齿鱼(Choerodon UI )的通用提交的封装 —— 两种方案,A.使用dataSet的自身的submit,B.使用axios.post来提交
  5. vrep导入urdf
  6. 解决在ubuntu的firefox浏览器下不能看b站视频的问题
  7. 点阵屏32x64/32x128单片机驱动及HUB08说明
  8. Android 11.0 SystemUI导航栏固定在底部显示的修改
  9. 热门光学软件之初体验网络课程系列大纲2
  10. 热门光学软件之初体验网络课程系列大纲8