(译)如何使用cocos2d制作基于tile地图的游戏教程:第一部分

  免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!

原文链接地址:http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d

教程截图:

  在这个2部分的教程中,我将会教大家如何使用cocos2d来做一个基于tile地图的游戏,当然还有Tiled地图编辑器。(我们小时候玩的小霸王小学机里面的游戏,大部分都是基于tile地图的游戏,如坦克大战、冒险岛、吞食天地等)我们将会创建一个忍者在沙漠中找西瓜吃的小游戏。-_-

  在第一部分教程中,我将教大家如何使用Tile来创建地图,怎样把地图加到游戏中,怎么让地图跟随玩家滚动,以及怎样使用对象层。

  在第二部分教程中,我将介绍如何在地图中创建可碰撞的区域,如何使用tile属性,如何制作可拾取的物体和动态修改地图,还有确保忍者不要吃撑了!

  如果你还没有准备好的话,你可能需要先从《如何使用cocos2d来制作简单的iphone游戏》系列教程开始学起,因为我们这个教程使用了大量的基本概念,而这些概念都可以从上面的教程中获取。

  好了,让我们玩一玩tile地图吧!

创建工程骨架

  让我们首先创建整个工程的骨架,这样可以确保今后我们需要的文件都包含进来了,并且能够跑起来。

  因此,启动XCode,点击“File\New Project...”,选择cocos2d Application template,并且把工程命名为TileGame。

  接下来,下载游戏资源文件。这个资源文件包里包含了以下内容:

  • 玩家sprite。这个图片和《如何使用cocos2d来制作简单的iphone游戏》差不多。
  • 我使用cxfr这个工具制作的一些音效。
  • 我使用Garage Band制作的一些背景音乐。(查看这篇博文获得更多的信息)
  • 我们将会使用的tile集合--它实际上会和tile地图编辑器一块儿使用,但是,我想把它放在这里,余下的事情会变得更容易。 
  • 一些额外的“特殊”的tile,我将会在后面加以说明。

  一旦你获得了这些资源,解压并把它拖到你的工程的“Resources”分组下面。确保复选中“Copy items into destination group’s folder (if needed)”,引用类型为“Relative to Project”,然后点击增加。

  如果一切顺利,所有的文件应该都在你的工程里了。是时候制作我们的地图了!

使用Tile来制作地图

  cocos2d支持使用开源的Tile地图编辑器创建的TMX格式的地图。

  (作者给出的网址现在打不开了,这是我在另一个地方找到的。我把它放到我的网盘里了,并且做了一个链接。如果有人下载不了,请留言。这个tile地图编辑器是java版的,其实还有一个at版的,但是java版的功能强大一些。但是,大家请注意,作者使用的是qt版本的,所以界面会有一些不一致,但这并不影响程序的使用。)

  下载完之后,直接双击运行。点击File\New,然后会出现以下对话框:

  在 orientation部分,你可以选择Orthogonal(参考:  Legend of Zelda)或者Isometric(参考:  Disgaea)。我们这里将选择Orthogonal。

  接下来,设置地图的大小。记住,这个大小是以tile为单位的,而不是以像素为单位。我们将创建一个尽量小的地图,因此选择50×50.

  最后,你指定每个tile的宽度和高度。你这里选择的宽度和高度要根据你的实际的tile图片的尺寸来做。这个教程使用的样例tile的尺寸是32×32,所以在上面的选项中选择32×32.

  接下来,我们把制作地图所需要的tile集合导入进来。点击菜单栏上面的“TileSets”菜单,“New Tileset...”,然后会出现下面的窗口:

  为了获得图片,点击Browse按钮,然后定位到你的TestGame文件夹,选择 tmw_desert_spacing.png文件,然后加到工程中去。它会基于文件名自动填充Name。然后把TileSet name命名为“tmw_desert_spacing.png”.同时,设置下面的Tile spacing和Margin都为1.

  你可以保留宽度和高度为32×32,因为tile的实际大小也是这么多。至于margin和spacing,我还没找到任何好的文档解释如何设置这两个值,下面是我的个人看法:

  • Margin就是当前的tile计算自身的像素的时候,它需要减去多少个像素(宽度和高度都包含在内)。(类比word、css的margin)
  • Spacing 就是相邻两个tile之间的间隔(同时考虑宽度和高度)(类比word、css的spacing)

  如果你看看 tmw_desert_spacing.png,你将会看见每一个tile都有一个像素的空白边界围绕着,这意味着我们需要把margin和spacing设置为1.

  一旦你选择ok,你将会看到Tilesets窗口中显示了一些tiles。现在,你可以制作地图了!点击工具栏上的“Stamp”按钮。点击Tile palette中的tile map,然后选择一个tile,然后再在地图上的任意位置单击,你就会看到你选中的tile出现在点中的地方了。

  因此,继续制作地图吧---充分发挥你的聪明才智!确保增加至少一对建筑物在地图上,因为后面我们需要一些东西来做碰撞。

记住一些方便的快捷方式:

  • 你可以在Tileset拾取器中拖出一个方框,一次选取多个tile。
  • 你可以使用工具栏上的paint按钮来基于一个基准tile绘制整个地图。
  • 你可以使用“View\Zoom In...”和“View\Zoom out...”来放大和缩小地图。

  一旦你完成了地图的绘制工作,在Layers选项卡的层上面双击(现在可以说是“Layer1”),然后重命名为“Background”。然后点击“File\Save”并且保存文件到你的工程的资源文件夹中,并且命名为“TileMap.tmx”。

  后面我们将会使用这个tmx来做一些有趣的事情,好了,让我们把地图加载到游戏中去吧!

把tile地图添加到cocos2d的场景中

  首先,第一件事情,右键点击Resources,选择“ Add\Existing Files…”,然后添加TileMap.tmx文件。

  打开HelloWorldScene.h,然后添加一些成员变量,并且申明一声属性:

// Inside the HelloWorld class declaration
CCTMXTiledMap *_tileMap;
CCTMXLayer
*_background;

// After the class declaration
@property (nonatomic, retain) CCTMXTiledMap *tileMap;
@property (nonatomic, retain) CCTMXLayer
*background;

 

然后在HelloWorldScene.m文件中做如下修改:

// Right after the implementation section
@synthesize tileMap = _tileMap;
@synthesize background
= _background;

// In dealloc
self.tileMap = nil;
self.background
= nil;

// Replace the init method with the following
-(id) init
{
if( (self=[super init] )) {

self.tileMap
= [CCTMXTiledMap tiledMapWithTMXFile:@"TileMap.tmx"];
self.background
= [_tileMap layerNamed:@"Background"];

[self addChild:_tileMap z:
-1];

}
return self;
}

  这里,我们调用CCTMXTiledMap类的一些方法,把我们刚刚创建的地图文件加载进去。

  一些简明的CCTMXTiledMap的背景知识。它是一个CCNode,你可以设置它的位置和比例等。这个地图的孩子是一些层,而且提供了一个帮助函数可以让你通过层的名字得到层对象--我们上面就是通过这种方面获得地图背景的。每一个层都是一个CCSpriteSheet的子类,这里考虑了性能的原因--但是这也意味着每一个层只能有一个tile集。

  因此,我们这里做的所有这些,就是指向一个tile地图,然后保存背景层的引用,并且把tile地图加到HelloWorld层中。

  好了,就这么多!编译并运行工程,你将会看到地图的左下角出现在模拟器中。

  还不错!但是,这还不是一个游戏!我们还需要三个东西:a)游戏主角,b)主角初使位置和c)能够移动视图,这样就好像是第一视角了。

  好了,接下来让我们来解决这些问题。

tiled对象层和设置tile地图位置

  tiled支持两类层--tile层(就是我们目前使用的层),还有对象层。

  对象层允许你在地图上圈出一些区域,来指定一些事件的发生。比如,你可能想制作一个区域,在那里怪物将会跳出来,或者是一个区域,只要进入就会死掉。这我们这个例子中,我们将创建一个区域来显示我们的游戏主角。

  因此,找到Tiled的菜单,点击”  Layer\Add Object Group…”,命名为“Objects”,然后选择Ok。如果你绘制了地图,你将会注意到,它并没有绘制一个tile,而是画了一个很难看的灰色矩形,这个矩形我们之后可以扩展,使之能够包含多个tiles或者移动它。

  我们只想要选择一个tile来让主角显示。因此,在你的地图上选择一个tile。这个区域的大小实际上并没有关系,因为我们仅仅使用x、y坐标。

  然后,上面的黄色对象上面点右键, 取名为“SpawnPoint",然后选择Ok:

(添加对象方法很简单,看到左边的+号和-号了吗?一个是增加对象,一个是删除对象。点中加号以后,用鼠标可以拖出一个矩阵区域。)

(下面给出一些技巧。如何把一个对象准确放置到Background的空白区域,只需要调整背景的opacity就可以了)

  假设,你可以做一些奇思妙想。你把对象的类型命名为cocos2d里面的class的名字,然后它会为你创建那个类型(比如CCSprite),但是,我在cocos2d自带的源代码里面代不到这样的例子。更新:来自GeekAndDad.com的Tyler提供了之前版本的cocos2d里面使用这种“妙想”的方法,但是,由于背景有白色,所以被移除了。

  不管怎么说--我们仅仅把这个类型设置为空就行了,最后cocos2d会为我们创建NSMutableDictionary,我们可以从中获得对象的各种属性,包含x,y坐标。

  保存地图,然后返回XCode。在HelloWorldScene.h中做如下修改:

// Inside the HelloWorld class declaration
CCSprite *_player;

// After the class declaration
@property (nonatomic, retain) CCSprite *player;

 

同样,修改HelloWorldScene.m,代码如下:

// Right after the implementation section
@synthesize player = _player;

// In dealloc
self.player = nil;

// Inside the init method, after setting self.background
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:@"Objects"];
NSAssert(objects
!= nil, @"'Objects' object group not found");
NSMutableDictionary
*spawnPoint = [objects objectNamed:@"SpawnPoint"];
NSAssert(spawnPoint
!= nil, @"SpawnPoint object not found");
int x = [[spawnPoint valueForKey:@"x"] intValue];
int y = [[spawnPoint valueForKey:@"y"] intValue];

self.player
= [CCSprite spriteWithFile:@"Player.png"];
_player.position
= ccp(x, y);
[self addChild:_player];

[self setViewpointCenter:_player.position];

 

  好了,让我们先歇会儿,来解释一下对象层和对象组。首先,注意你通过CCTMXTiledMap对象的objectGroupNamed方法来获得对象层(而不是layerNamed方法)。它返回一个特殊的CCTMXObjectGroup对象。

  我们然后调用CCTMXObjectGroup类的objectNamed方法来获得一个NSMutableDictionary,这个字典包含了关于对象的大量信息,包括x和y坐标值,宽度和高度。在这个例子中,我们只关心x和y坐标,因此,我们提取出这两个信息,并且设置player的位置。

  最后,我想设置这个视图为玩家所在的位置。因此,添加下面一个新方法到文件中:

-(void)setViewpointCenter:(CGPoint) position {

CGSize winSize
= [[CCDirector sharedDirector] winSize];

int x = MAX(position.x, winSize.width /2);
int y = MAX(position.y, winSize.height /2);
x
= MIN(x, (_tileMap.mapSize.width * _tileMap.tileSize.width)
- winSize.width /2);
y
= MIN(y, (_tileMap.mapSize.height * _tileMap.tileSize.height)
- winSize.height/2);
CGPoint actualPosition
= ccp(x, y);

CGPoint centerOfView
= ccp(winSize.width/2, winSize.height/2);
CGPoint viewPoint
= ccpSub(centerOfView, actualPosition);
self.position
= viewPoint;

}

  好了,让我解释一下。假设这个函数是设置camera的中心。我们允许用户传入地图上任何x、y坐标值--但是如果你仔细想一下,有些东西我们并不想让它显示出来--比如,我们不想让屏幕超过地图的边界(那些区域仅仅是一个空白区域!)

  比如,看看下面这幅图:

  看一下,什么时候camera的中心会小于winSize.width/2或者winSize.height/2,部分视图将会在屏幕之外?类似的,我们需要检查上面的界限区间,也和我们这里的情形一样。

  因此,我们把这个函数看作是设置camera的视角中心点。然而。。。那不完全是我们想要的。在cocos2d里面有一种方式可以直接操作一个CCNode的camera,但是那会使事情变得更复杂。我们需要另一种替代方法,那就是移动整个层。

  看看下面的图:

  想像一个大的地图,我们查看从0到winSize.height/width的坐标。我们的视图的中心点是centerOfView,而且我们知道我们要把这个中心设置到哪里(actualPositon)。因此,为了使实际的位置和视图中心相吻合,我们只需要把地图往左下角移动即可!

  这个可以通过使实际的位置减去视图的中心位置来实现,然后设置HelloWorld层到那个点。

  唉!太多理论了--让我们看点实际的吧!编译并运行项目,如果一切顺利,你将会看到忍者在场景当中,然而视角也移过来了。

使忍者移动

  我们已经有一个好的开端了,但是我们的忍者只是站在那儿不动!这可不像真正的忍者!

  让我们使忍者动起来吧,只需要让忍者移动到用户点击的地方就行了。在HelloWorldScene.m中增加以下代码:

// Inside init method
self.isTouchEnabled = YES;

-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:
0 swallowsTouches:YES];
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
return YES;
}

-(void)setPlayerPosition:(CGPoint)position {
_player.position
= position;
}

-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{

CGPoint touchLocation
= [touch locationInView: [touch view]];
touchLocation
= [[CCDirector sharedDirector] convertToGL: touchLocation];
touchLocation
= [self convertToNodeSpace:touchLocation];

CGPoint playerPos
= _player.position;
CGPoint diff
= ccpSub(touchLocation, playerPos);
if (abs(diff.x) > abs(diff.y)) {
if (diff.x >0) {
playerPos.x
+= _tileMap.tileSize.width;
}
else {
playerPos.x
-= _tileMap.tileSize.width;
}
}
else {
if (diff.y >0) {
playerPos.y
+= _tileMap.tileSize.height;
}
else {
playerPos.y
-= _tileMap.tileSize.height;
}
}

if (playerPos.x <= (_tileMap.mapSize.width * _tileMap.tileSize.width) &&
playerPos.y
<= (_tileMap.mapSize.height * _tileMap.tileSize.height) &&
playerPos.y
>=0&&
playerPos.x
>=0 )
{
[self setPlayerPosition:playerPos];
}

[self setViewpointCenter:_player.position];

}

 

  首先,在init方法中设置层能够接收touch事件。如果我们覆盖registerWithTouchDispatcher方法,来使这个层能够处理目标touch事件。这样会导致ccTouchBegan和ccTouchEnded方法被调用(注意是单数形式,而不是复数形式的ccTouchesBegan和ccTouchesEnded方法)

  你可能会问,为什么我要讲这个,因为我们在 《如何使用cocos2d来制作简单的iphone游戏》里面使用的是ccTouchesBegan和ccTouchesEnded方法。那两个方法可以,在这个教程里用两种方法都可以。但是,我想向大家介绍一个新方法,因为它有两个优点:

  • “你不需要处理NSSet,划分UITouch集合并调度的工作全部由cocos2d框架来完成。每一次方法调用,你只获得了一个UITouch。“
  • “你可以在ccTouchBegan中返回yes,这样当前的层就可以接收touch事件回调。而且,只有当你返回yes的时候,才会响应move/ended/cancelled回调. 这个就使你从一些复杂的多触摸判断中解放出来了。

  不管怎么说,在我们的ccTouchEnded里面,我们转换屏幕touch坐标为局部view坐标,然后再转换成GL的坐标。这两个步骤,在新的cocos2d版本中,只需要一步完成,即调用 [self convertToNodeSpace:touchLocation].就可以了。

  这是因为,touch位置只是告诉我们屏幕视口的坐标(比如100,100)。但是,我们我们滚动了地图,这个位置实际可能对应地图的(800,800)。因此,调用这个方法基于我们当前层的位置来决定touch的偏移。

  接下来,计算出touch点和player的位置之差。我们必须基于touch位置选择一个方向,因此,首先,我们需要计算出是上下移动还是左右移动。然后,我们比较正负值,决定具体的方向。

  相应的,我们再调整player的位置,并且设置player的位置为视口的中心位置,这个在上一节中已经用到了。

  更新:注意,我们不得不添加一个安全检查,来确保我们的player不会移到地图之外!这一点,是Geek&Dad指出来的,谢谢你!

  编译并运行!你现在可以点击鼠标,想让尽者移到哪,它就移到哪儿!

何去何从?

  这只是这个教程的一部分。此时,你应该了解一些创建tile地图的基础了,而且知道如何把它导入到游戏当中。

  这里有我们目前为止用的完整源代码。

  接下,期待第二部分教程吧!在那里,我将教大家如何在地图中添加碰撞检测,如果使我们的忍者沿着墙壁快乐的奔跑!

 

著作权声明:本文由http://www.cnblogs.com/andyque翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

转载于:https://www.cnblogs.com/zilongshanren/archive/2011/04/11/2012852.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298467.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

devexpress 中的checkboxlist怎么设置间距_HTML中怎么设置h1的字体样式你知道吗?关于设置h1标签的样式详解

本篇文章主要为大家讲解了html中的h1标签的样式解析&#xff0c;但是如果不用css样式来做的话&#xff0c;那就只能在html4.01中显示了&#xff0c;所以我们还是尽快学习css层叠样式表吧&#xff0c;好了&#xff0c;现在让我们来说说这篇文章吧。HTML中的H标签(H1&#xff0c;…

终端如何粘贴快捷键_11 个“原来可以这样”的 Linux 终端命令

1. 命令行日常系快捷键如下的快捷方式非常有用&#xff0c;能够极大的提升你的工作效率&#xff1a;CTRL U - 剪切光标前的内容CTRL K - 剪切光标至行末的内容CTRL Y - 粘贴CTRL E - 移动光标到行末CTRL A - 移动光标到行首ALT F - 跳向下一个空格ALT B - 跳回上一个空格…

2020应届生「求职图鉴」,扎心了!

一场疫情&#xff0c;开启了2020应届生求职的地狱模式&#xff1a;实习&#xff0c;辞了考研&#xff0c;凉了论文&#xff0c;废了春招&#xff0c;歇了......别说拿高薪&#xff0c;有份工作都难&#xff01;当「想象」遇上「现实」&#xff0c;现在的你&#xff0c;还挺得住…

WCF发布到IIS7问题的解决方案

今天用VS2010开发了一个WCF服务进行一个简单测试&#xff0c;没想到这点小事竟然折腾了我2个小时。 为避免其他兄弟遇到相同的问题少走弯路做一下总结。 操作系统:Windows7 旗舰版 开发环境:VS2010 .NET Framework4.0 ASP.NET4.0 第一步&#xff1a;检查Windows7中IIS是否安装了…

flex布局_Flex布局,真香

作者: EcbJS https://blog.csdn.net/EcbJS/article/details/106466757?utm_sourceapp1.基本原理Flex 英文意思为&#xff0c;弯曲&#xff0c;屈伸&#xff0c;可以伸缩的布局&#xff0c;天生就是为了适配不同的分辨率。而且用法也很简单&#xff0c;首先只要告诉浏览器&…

字体编辑器_FontLab 7 ——字体编辑器

FontLab VI是一款专为Mac用户设计的字体编辑器。无论您是专家还是初学者&#xff0c;使用FontLab突破性的绘图工具和响应式轮廓操作都能够轻松设计&#xff0c;编辑和转换字体&#xff0c;让您的设计过程将更快&#xff0c;更高效&#xff01;功能介绍一、画画 下一代绘图神器&…

分享一个理工男必学的撩妹姿势

随着气温越来越高&#xff0c;空气中恋爱的酸臭味也越来越浓。。。是的&#xff0c;这意味着一个由谐音演变而来的“传统佳节”&#xff0c;也终于迎来了它的高光时刻。520可以说是每个直男都要经历的考验&#xff0c;说是“我爱你”的谐音&#xff0c;过得好是520&#xff0c;…

Docker小白到实战之Dockerfile解析及实战演示,果然顺手

前言使用第三方镜像肯定不是学习Docker的最终目的&#xff0c;最想要的还是自己构建镜像&#xff1b;将自己的程序、文件、环境等构建成自己想要的应用镜像&#xff0c;方便后续部署、启动和维护&#xff1b;而Dockerfile就是专门做这个事的&#xff0c;通过类似简单编码的形式…

转换实体类_利用Java反射机制进行Map和JavaBean间转换

Java中利用反射进行Map和JavaBean间转换在日常工作中&#xff0c;有时候我们可能会遇到以下这样的情况发生。例如&#xff1a;(1)后端接受一个参数Map param(可能是前端form维护的一个对象...)。(2)将一个对象个别属性(key)和对应值(value)存放到Map对象中。(3).......针对上面…

python模拟键盘输入_这件神器,每个 Python入门学习者都值得一试

灰常实用的一篇文章&#xff0c;看完你会来点赞滴。 不论你是刚开始学 Python&#xff0c;还是正在啃数据分析的骨头&#xff0c;对你来说&#xff0c;不断在各种命令行窗口和编辑器里切来切去&#xff0c;或者不断打开各种窗口查看 matplotlib 的输出之类的繁琐操作&#xff0…

早上起床时需要的重力

1 我这一波操作怎么样&#xff1f;2 要趁垃圾桶不注意3 主人在厕所&#xff0c;我要守护她4 好歹给你留了一张&#xff0c;知足吧5 怎么吃这么小的榴莲6 不存在的7 早上起床时需要的重力8 求解你点的每个赞&#xff0c;我都认真当成了喜欢

一年几百亿的电费 中国移动再提5G功耗问题

最近&#xff0c;中移动高管表示&#xff0c;在5G网络建设中&#xff0c;中国移动将贯彻绿色发展的理念&#xff0c;利用节能技术&#xff0c;使功耗尽可能能够减少。之所以如此&#xff0c;原因之一是中国移动的网络功耗上受到一定程度的压力。在中国移动招股书中也反映出了5G…

拆弹部队火了,种***的笑了

第82届奥斯卡颁奖落幕&#xff0c;美国战争片《拆弹部队》一举战胜票房第一的《阿凡达》获得6项大奖&#xff0c;而 《拆弹部队》这部电影并未进入电影院线&#xff0c;众多影迷们只能求助于互联网&#xff0c;《拆弹部队》立即成为搜索热词。只能在网上看大片&#xff0c;将面…

海外服务器搭建网站访问很慢,海外服务器访问速度变慢了怎么办

但随着越来越多的站长选择在海外服务器上搭建网站&#xff0c;也有许多使用者开始抱怨服务器速度怎么越变越慢了&#xff1f;所以我们在这里讲解下如何解决服务器访问速度变慢的问题。海外服务器访问速度变慢了怎么办首先我们需要找到是什么原因降低了服务器速度&#xff0c;其…

别 再 给 我 打 拼 音 缩 写 了

全世界只有3.14 % 的人关注了爆炸吧知识今天给大家介绍个朋友——姜哥&#xff01;他和所有即将步入中年的雄性一样&#xff0c;最爱在会议室上呼风唤雨&#xff0c;精神上俯视后辈。口头禅是“年轻人&#xff0c;这才哪到哪啊”。对新周猫“姜哥”来说&#xff0c;走出猫窝就是…

json 格式化工具_如何在命令行中优雅地处理JSON

当年刚出道的时候&#xff0c;整天使用 grep/cut/awk 处理各种纯文本日志。那时候的日志都是一行一条&#xff0c;内容使用特定分割符。使用各种 unix 命令配合管道真可谓得心应手。然而&#xff0c;到了 9102 年&#xff0c;好多数据都以 json 形式传输和存储。awk 这类工具在…

云计算参考架构几例

云计算参考架构: 上图阐释如何创建私有和混合云&#xff0c;最终用户可以自行提供计算、 存储和网络。许多大型组织开始创建内部的私有云&#xff0c;来增强其数据中心战略。 58同城的云架构: 百度社区的云架构 结合对弹性服务的理解&#xff0c;第一个是弹性伸缩&#xff0c;你…

C#开源类库推荐:拼多多开放平台SDK,开源免费,支持.NET Core!

今天推荐一个拼多多开放平台DotNet SDK!开源地址&#xff1a;https://github.com/niltor/open-pdd-net-sdk作者&#xff1a;niltor背景介绍来源原文链接&#xff1a;https://www.cnblogs.com/msdeveloper/p/open-pdd-net-sdk.html环境支持支持基于 NETStandardv2.0 的项目&…

道理我都懂,但你到底为什么偏偏喜欢咬我??

▲ 点击查看眼看着天气一天天热起来&#xff0c;我这春困还没醒呢&#xff0c;蚊子们倒是醒过来了。每天晚上一关灯&#xff0c;就能听到它在我周围“嗡嗡嗡”地叫&#xff0c;可一开灯&#xff0c;又找不到它在哪儿&#xff0c;心里真是恨得直痒痒。才刚进四月&#xff0c;我就…

python爬虫登录有验证码_大神教你用Python爬虫模拟登录带验证码网站

爬取网站时经常会遇到需要登录的问题&#xff0c;这是就需要用到模拟登录的相关方法。python提供了强大的url库&#xff0c;想做到这个并不难。这里以登录学校教务系统为例&#xff0c;做一个简单的例子。 首先得明白cookie的作用&#xff0c;cookie是某些网站为了辨别用户身份…