阿里云建立网站,贤邦网站建设app开发,企业信息系统查询,甘肃百度推广电话谷歌流量器中有个很有名的彩蛋#xff1a;当你网络出现问题时#xff0c;就会出现一个“小恐龙游戏”。(如果想要直接进行游戏#xff0c;可以在地址栏输入#xff1a;chrome://dino)今天我们就来给大家演示下#xff0c;用Python来自己做一个仿制的“小恐龙游戏”#x…谷歌流量器中有个很有名的彩蛋当你网络出现问题时就会出现一个“小恐龙游戏”。(如果想要直接进行游戏可以在地址栏输入chrome://dino)今天我们就来给大家演示下用Python来自己做一个仿制的“小恐龙游戏”废话不多说让我们愉快地开始吧~开发工具Python版本3.6.4相关模块pygame模块以及一些python自带的模块。环境搭建安装Python并添加到环境变量pip安装需要的相关模块即可。先睹为快在终端运行如下命令即可python Game7.py效果如下代码介绍这里介绍一下游戏的实现原理。首先我们对游戏进行一些必要的初始化工作# 游戏初始化pygame.init()screen pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption(T-Rex Rush —— Charles的皮卡丘)# 导入所有声音文件sounds {}for key, value in cfg.AUDIO_PATHS.items():sounds[key] pygame.mixer.Sound(value)接着我们来考虑一下游戏中有哪些游戏元素小恐龙由玩家控制以躲避路上的障碍物路面游戏的背景云游戏的背景飞龙路上的障碍物之一小恐龙碰上就会死掉仙人掌路上的障碍物之一小恐龙碰上就会死掉记分板记录当前的分数和历史最高分。让我们来依次定义一下这些游戏元素类。对于云路面以及仙人掌来说定义起来很简单我们只需要加载对应的游戏元素图片然后写两个类内部方法update和draw就ok了。两个方法分别用于将场景不断向左移动以实现小恐龙不断向前移动的动画效果和将场景显示在游戏界面的对应位置上。具体而言代码实现如下地板class Ground(pygame.sprite.Sprite):def __init__(self, imagepath, position, **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.image_0 pygame.image.load(imagepath)self.rect_0 self.image_0.get_rect()self.rect_0.left, self.rect_0.bottom positionself.image_1 pygame.image.load(imagepath)self.rect_1 self.image_1.get_rect()self.rect_1.left, self.rect_1.bottom self.rect_0.right, self.rect_0.bottom# 定义一些必要的参数self.speed -10更新地板def update(self):self.rect_0.left self.speedself.rect_1.left self.speedif self.rect_0.right 0:self.rect_0.left self.rect_1.rightif self.rect_1.right 0:self.rect_1.left self.rect_0.right将地板画到屏幕def draw(self, screen):screen.blit(self.image_0, self.rect_0)screen.blit(self.image_1, self.rect_1)云class Cloud(pygame.sprite.Sprite):def __init__(self, imagepath, position, **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.image pygame.image.load(imagepath)self.rect self.image.get_rect()self.rect.left, self.rect.top position# 定义一些必要的参数self.speed -1将云画到屏幕上def draw(self, screen):screen.blit(self.image, self.rect)更新云def update(self):self.rect self.rect.move([self.speed, 0])if self.rect.right 0:self.kill()仙人掌class Cactus(pygame.sprite.Sprite):def __init__(self, imagepaths, position(600, 147), sizes[(40, 40), (40, 40)], **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.images []image pygame.image.load(imagepaths[0])for i in range(3):self.images.append(pygame.transform.scale(image.subsurface((i*101, 0), (101, 101)), sizes[0]))image pygame.image.load(imagepaths[1])for i in range(3):self.images.append(pygame.transform.scale(image.subsurface((i*68, 0), (68, 70)), sizes[1]))self.image random.choice(self.images)self.rect self.image.get_rect()self.rect.left, self.rect.bottom positionself.mask pygame.mask.from_surface(self.image)# 定义一些必要的变量self.speed -10画到屏幕上def draw(self, screen):screen.blit(self.image, self.rect)更新def update(self):self.rect self.rect.move([self.speed, 0])if self.rect.right 0:self.kill()记分板的定义也类似只不过它不需要移动但是需要实时地更新当前 的分数记分板class Scoreboard(pygame.sprite.Sprite):def __init__(self, imagepath, position, size(11, 13), is_highestFalse, bg_colorNone, **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.images []image pygame.image.load(imagepath)for i in range(12):self.images.append(pygame.transform.scale(image.subsurface((i*20, 0), (20, 24)), size))if is_highest:self.image pygame.Surface((size[0]*8, size[1]))else:self.image pygame.Surface((size[0]*5, size[1]))self.rect self.image.get_rect()self.rect.left, self.rect.top position# 一些必要的变量self.is_highest is_highestself.bg_color bg_colorself.score 00000设置得分def set(self, score):self.score str(score).zfill(5)画到屏幕上def draw(self, screen):self.image.fill(self.bg_color)for idx, digital in enumerate(list(self.score)):digital_image self.images[int(digital)]if self.is_highest:self.image.blit(digital_image, ((idx3)*digital_image.get_rect().width, 0))else:self.image.blit(digital_image, (idx*digital_image.get_rect().width, 0))if self.is_highest:self.image.blit(self.images[-2], (0, 0))self.image.blit(self.images[-1], (digital_image.get_rect().width, 0))screen.blit(self.image, self.rect)上面代码用is_highest变量来区分该记分板是否用于记录游戏最高分还是只是记录当前的分数做该区分的原因是游戏最高分前面有HI标识所以占的空间更大飞龙的定义就稍微复杂一些了因为它不仅需要向左移动还需要做出不停扇动翅膀的效果。具体而言飞龙有两张图你需要做的就是每隔一段时间就切换一次当前的飞龙图片以实现飞龙扇动翅膀的效果飞龙class Ptera(pygame.sprite.Sprite):def __init__(self, imagepath, position, size(46, 40), **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.images []image pygame.image.load(imagepath)for i in range(2):self.images.append(pygame.transform.scale(image.subsurface((i*92, 0), (92, 81)), size))self.image_idx 0self.image self.images[self.image_idx]self.rect self.image.get_rect()self.rect.left, self.rect.centery positionself.mask pygame.mask.from_surface(self.image)# 定义一些必要的变量self.speed -10self.refresh_rate 10self.refresh_counter 0画到屏幕上def draw(self, screen):screen.blit(self.image, self.rect)更新def update(self):if self.refresh_counter % self.refresh_rate 0:self.refresh_counter 0self.image_idx (self.image_idx 1) % len(self.images)self.loadImage()self.rect self.rect.move([self.speed, 0])if self.rect.right 0:self.kill()self.refresh_counter 1载入当前状态的图片def loadImage(self):self.image self.images[self.image_idx]rect self.image.get_rect()rect.left, rect.top self.rect.left, self.rect.topself.rect rectself.mask pygame.mask.from_surface(self.image)最后我们需要定义一下小恐龙类也就是最复杂的一个游戏精灵类。它有低头跳跃普通前进三种状态。对于低头来说你只需要和飞龙扇动翅膀一样不断切换两张低头的图片以实现小恐龙跑动的效果就可以了。对于普通状态也是类似的对于跳跃状态我们则可以通过初中学的上抛和自由落体运动公式来建模从而计算小恐龙在竖直方向上的位置。具体而言代码实现如下小恐龙class Dinosaur(pygame.sprite.Sprite):def __init__(self, imagepaths, position(40, 147), size[(44, 47), (59, 47)], **kwargs):pygame.sprite.Sprite.__init__(self)# 导入所有图片self.images []image pygame.image.load(imagepaths[0])for i in range(5):self.images.append(pygame.transform.scale(image.subsurface((i*88, 0), (88, 95)), size[0]))image pygame.image.load(imagepaths[1])for i in range(2):self.images.append(pygame.transform.scale(image.subsurface((i*118, 0), (118, 95)), size[1]))self.image_idx 0self.image self.images[self.image_idx]self.rect self.image.get_rect()self.rect.left, self.rect.bottom positionself.mask pygame.mask.from_surface(self.image)# 定义一些必要的变量self.init_position positionself.refresh_rate 5self.refresh_counter 0self.speed 11.5self.gravity 0.6self.is_jumping Falseself.is_ducking Falseself.is_dead Falseself.movement [0, 0]跳跃def jump(self, sounds):if self.is_dead or self.is_jumping:returnsounds[jump].play()self.is_jumping Trueself.movement[1] -1 * self.speed低头def duck(self):if self.is_jumping or self.is_dead:returnself.is_ducking True不低头def unduck(self):self.is_ducking False死掉了def die(self, sounds):if self.is_dead:returnsounds[die].play()self.is_dead True将恐龙画到屏幕def draw(self, screen):screen.blit(self.image, self.rect)载入当前状态的图片def loadImage(self):self.image self.images[self.image_idx]rect self.image.get_rect()rect.left, rect.top self.rect.left, self.rect.topself.rect rectself.mask pygame.mask.from_surface(self.image)更新小恐龙def update(self):if self.is_dead:self.image_idx 4self.loadImage()returnif self.is_jumping:self.movement[1] self.gravityself.image_idx 0self.loadImage()self.rect self.rect.move(self.movement)if self.rect.bottom self.init_position[1]:self.rect.bottom self.init_position[1]self.is_jumping Falseelif self.is_ducking:if self.refresh_counter % self.refresh_rate 0:self.refresh_counter 0self.image_idx 5 if self.image_idx 6 else 6self.loadImage()else:if self.refresh_counter % self.refresh_rate 0:self.refresh_counter 0if self.image_idx 1:self.image_idx 2elif self.image_idx 2:self.image_idx 3else:self.image_idx 1self.loadImage()self.refresh_counter 1定义完游戏精灵类我们就可以实例化他们# 定义一些游戏中必要的元素和变量score 0score_board Scoreboard(cfg.IMAGE_PATHS[numbers], position(534, 15), bg_colorcfg.BACKGROUND_COLOR)highest_score highest_scorehighest_score_board Scoreboard(cfg.IMAGE_PATHS[numbers], position(435, 15), bg_colorcfg.BACKGROUND_COLOR, is_highestTrue)dino Dinosaur(cfg.IMAGE_PATHS[dino])ground Ground(cfg.IMAGE_PATHS[ground], position(0, cfg.SCREENSIZE[1]))cloud_sprites_group pygame.sprite.Group()cactus_sprites_group pygame.sprite.Group()ptera_sprites_group pygame.sprite.Group()add_obstacle_timer 0score_timer 0然后写游戏主循环啦# 游戏主循环clock pygame.time.Clock()while True:for event in pygame.event.get():if event.type pygame.QUIT:pygame.quit()sys.exit()elif event.type pygame.KEYDOWN:if event.key pygame.K_SPACE or event.key pygame.K_UP:dino.jump(sounds)elif event.key pygame.K_DOWN:dino.duck()elif event.type pygame.KEYUP and event.key pygame.K_DOWN:dino.unduck()screen.fill(cfg.BACKGROUND_COLOR)# --随机添加云if len(cloud_sprites_group) 5 and random.randrange(0, 300) 10:cloud_sprites_group.add(Cloud(cfg.IMAGE_PATHS[cloud], position(cfg.SCREENSIZE[0], random.randrange(30, 75))))# --随机添加仙人掌/飞龙add_obstacle_timer 1if add_obstacle_timer random.randrange(50, 150):add_obstacle_timer 0random_value random.randrange(0, 10)if random_value 5 and random_value 7:cactus_sprites_group.add(Cactus(cfg.IMAGE_PATHS[cacti]))else:position_ys [cfg.SCREENSIZE[1]*0.82, cfg.SCREENSIZE[1]*0.75, cfg.SCREENSIZE[1]*0.60, cfg.SCREENSIZE[1]*0.20]ptera_sprites_group.add(Ptera(cfg.IMAGE_PATHS[ptera], position(600, random.choice(position_ys))))# --更新游戏元素dino.update()ground.update()cloud_sprites_group.update()cactus_sprites_group.update()ptera_sprites_group.update()score_timer 1if score_timer (cfg.FPS//12):score_timer 0score 1score min(score, 99999)if score highest_score:highest_score scoreif score % 100 0:sounds[point].play()if score % 1000 0:ground.speed - 1for item in cloud_sprites_group:item.speed - 1for item in cactus_sprites_group:item.speed - 1for item in ptera_sprites_group:item.speed - 1# --碰撞检测for item in cactus_sprites_group:if pygame.sprite.collide_mask(dino, item):dino.die(sounds)for item in ptera_sprites_group:if pygame.sprite.collide_mask(dino, item):dino.die(sounds)# --将游戏元素画到屏幕上dino.draw(screen)ground.draw(screen)cloud_sprites_group.draw(screen)cactus_sprites_group.draw(screen)ptera_sprites_group.draw(screen)score_board.set(score)highest_score_board.set(highest_score)score_board.draw(screen)highest_score_board.draw(screen)# --更新屏幕pygame.display.update()clock.tick(cfg.FPS)# --游戏是否结束if dino.is_dead:break游戏主循环的逻辑很简单即每帧游戏画面我们都需要检测一下玩家的操作如果玩家按下了空格键或者↑键则小恐龙跳跃如果玩家按下了↓键则小恐龙低头否则小恐龙正常向前冲。然后在游戏中我们随机产生云飞龙和仙人掌这些游戏场景和障碍物并且和路面一起以相同的速度向左移动从而实现小恐龙向右移动的视觉效果。在移动的过程中我们需要对小恐龙和仙人掌小恐龙和飞龙进行碰撞检测当小恐龙碰到这些障碍物时小恐龙就死掉了本局游戏也随之结束。需要注意的是我们应该使用collide_mask函数来进行更为精确的碰撞检测而不是之前的collide_rect函数即当两个目标的最小外接矩形有重叠时collide_rect就会判定两个目标有碰撞这显然是不合理的会给玩家带来较差的游戏体验。另外当分数每提高一千分我们就和原版的游戏一样增加一点场景和障碍物向左移动的速度(也就是增加小恐龙向右移动的速度)。最后把当前所有的游戏元素绑定到屏幕上并更新当前的屏幕就ok了。