新增功能: 
1、q键直接退出游戏  -》  进行结算然后返回模式选择界面
2、 新增全屏按钮u ,并且切换的时候会造成3s的冻结效果
3、静音键m
4、暂停键p
5、无敌模式,进入下一关条件是只能打败20个坦克
6、代码注释完整
7、z键打印当前坦克的情况
8、可自定义地图
9、可自定义起始关卡

#!/usr/bin/python
# coding=utf-8
import datetime
import os, pygame, time, random, uuid, sys, psutil
from datetime import date
from time import ctime, sleep# 矩阵的 长宽高
class myRect(pygame.Rect):""" 添加类型属性 """def __init__(self, left, top, width, height, type):# 矩阵位置pygame.Rect.__init__(self, left, top, width, height)self.type = type# 获得一个唯一的随机的uid
class Timer(object):def __init__(self):self.timers = []# 获得一个唯一的随机的uiddef add(self, interval, f, repeat=-1):options = {"interval": interval, "callback": f, "repeat": repeat, "times": 0, "time": 0, "uuid": uuid.uuid4()# 生成一个随机的UUID}self.timers.append(options)return options["uuid"]#  销毁指定的uid(uuid_nr)def destroy(self, uuid_nr):for timer in self.timers:if timer["uuid"] == uuid_nr:self.timers.remove(timer)return# 定时器def update(self, time_passed):for timer in self.timers:timer["time"] += time_passedif timer["time"] > timer["interval"]:timer["time"] -= timer["interval"]timer["times"] += 1if timer["repeat"] > -1 and timer["times"] == timer["repeat"]:self.timers.remove(timer)try:timer["callback"]()except:try:self.timers.remove(timer)except:pass# 堡垒类
class Castle():""" Player's castle/fortress 堡垒的位置"""(STATE_STANDING, STATE_DESTROYED, STATE_EXPLODING) = range(3)def __init__(self):global sprites# images ,subsurface()从父表面创建一个新表面self.img_undamaged = sprites.subsurface(0, 15 * 2, 16 * 2, 16 * 2)self.img_destroyed = sprites.subsurface(16 * 2, 15 * 2, 16 * 2, 16 * 2)# init position 初始化位置self.rect = pygame.Rect(12 * 16, 24 * 16, 32, 32)# start w/ undamaged and shiny castle从未损坏和闪亮的城堡开始self.rebuild()def draw(self):""" Draw castle 画一个城堡"""global screen# blit()对图片进行操作,将一个平面的一部分或全部图象整块从这个平面复制到另一个平面screen.blit(self.image, self.rect.topleft)# 判断城堡是否被扎破if self.state == self.STATE_EXPLODING:if not self.explosion.active:self.state = self.STATE_DESTROYEDdel self.explosionelse:self.explosion.draw()def rebuild(self):""" Reset castle重置城堡 """self.state = self.STATE_STANDINGself.image = self.img_undamaged  # 城堡完整的图片self.active = Truedef destroy(self):""" Destroy castle 销毁城堡"""self.state = self.STATE_EXPLODINGself.explosion = Explosion(self.rect.topleft)  # 图片的左上被销毁self.image = self.img_destroyed  # 城堡被销毁的图片if god == False:self.active = False# 道具
class Bonus():""" Various power-ups 各种道具When bonus is spawned, it begins flashing and after some time dissapears当奖励产生时,它开始闪烁,一段时间后消失Available bonusses:  可用奖励列表手雷grenade   : Picking up the grenade power up instantly wipes out ever enemy presently on the screen, including Armor Tanks regardless of how many times you've hit them. You do not, however, get credit for destroying them during the end-stage bonus points.头盔helmet   : The helmet power up grants you a temporary force field that makes you invulnerable to enemy shots, just like the one you begin every stage with.铲子shovel  : The shovel power up turns the walls around your fortress from brick to stone. This makes it impossible for the enemy to penetrate the wall and destroy your fortress, ending the game prematurely. The effect, however, is only temporary, and will wear off eventually.星星star        : The star power up grants your tank with new offensive power each time you pick one up, up to three times. The first star allows you to fire your bullets as fast as the power tanks can. The second star allows you to fire up to two bullets on the screen at one time. And the third star allows your bullets to destroy the otherwise unbreakable steel walls. You carry this power with you to each new stage until you lose a life.坦克tank        : The tank power up grants you one extra life. The only other way to get an extra life is to score 20000 points.定时器timer        : The timer power up temporarily freezes time, allowing you to harmlessly approach every tank and destroy them until the time freeze wears off.
手雷:拿起手雷的电源,立即清除屏幕上的任何敌人,包括装甲坦克,无论你击中他们多少次。但是,你不会因为在最后阶段摧毁它们而得到积分。头盔:头盔能量提升给你一个临时力场,使你对敌人的射击无坚不摧,就像你在每个阶段开始的时候一样。铲子:铲子的力量把堡垒周围的墙从砖变成石头。这使得敌人不可能穿透墙壁并摧毁你的堡垒,从而提前结束游戏。然而,这种影响只是暂时的,最终会逐渐消失。星型:每次你拿起一辆星型坦克,它就会给你的坦克提供新的进攻能力,最多三次。第一颗星可以让你发射子弹的速度与动力坦克一样快。
第二颗星允许你在屏幕上同时发射两颗子弹。第三颗星可以让你的子弹摧毁原本坚不可摧的钢铁墙。你带着这种力量进入每一个新的阶段,直到你失去一条生命。坦克:坦克的能量增加可以让你多活一次。获得额外生命的唯一方法是获得20000分。定时器:定时器暂时冻结时间,允许你无害地接近每一辆坦克并摧毁它们,直到冻结时间消失。"""# bonus types 道具类型(BONUS_GRENADE, BONUS_HELMET, BONUS_SHOVEL, BONUS_STAR, BONUS_TANK, BONUS_TIMER) = range(6)def __init__(self, level):global sprites# to know where to place 在哪个地图(关卡)self.level = level# bonus lives only for a limited period of time 奖励只在有限的一段时间内有效self.active = True# blinking state 闪烁状态self.visible = True# 道具随机出现的地点self.rect = pygame.Rect(random.randint(0, 416 - 32), random.randint(0, 416 - 32), 32, 32)# 随机选一个道具self.bonus = random.choice([self.BONUS_GRENADE, self.BONUS_HELMET, self.BONUS_SHOVEL, self.BONUS_STAR, self.BONUS_TANK,self.BONUS_TIMER])self.image = sprites.subsurface(16 * 2 * self.bonus, 32 * 2, 16 * 2, 15 * 2)def draw(self):""" draw bonus 画道具"""global screenif self.visible:screen.blit(self.image, self.rect.topleft)def toggleVisibility(self):""" Toggle bonus visibility 道具开关可见??"""self.visible = not self.visible  # self.visible = self.visible# 子弹
class Bullet():# direction constants 子弹的方向的常量(DIR_UP, DIR_RIGHT, DIR_DOWN, DIR_LEFT) = range(4)# bullet's stated 声明子弹(STATE_REMOVED, STATE_ACTIVE, STATE_EXPLODING) = range(3)(OWNER_PLAYER, OWNER_ENEMY) = range(2)# 子弹初始化是:damage = 100, speed = 5def __init__(self, level, position, direction, damage=100, speed=5):global spritesself.level = levelself.direction = directionself.damage = damageself.owner = Noneself.owner_class = None# 1-regular everyday normal bullet常规子弹# 2-can destroy steel能摧毁钢铁的子弹self.power = 1  # 1/2self.image = sprites.subsurface(75 * 2, 74 * 2, 3 * 2, 4 * 2)# position is player's top left corner, so we'll need to子弹位置在坦克的左上角# recalculate a bit. also rotate image itself.旋转图像本身if direction == self.DIR_UP:self.rect = pygame.Rect(position[0] + 11, position[1] - 8, 6, 8)elif direction == self.DIR_RIGHT:self.image = pygame.transform.rotate(self.image, 270)self.rect = pygame.Rect(position[0] + 26, position[1] + 11, 8, 6)elif direction == self.DIR_DOWN:self.image = pygame.transform.rotate(self.image, 180)self.rect = pygame.Rect(position[0] + 11, position[1] + 26, 6, 8)elif direction == self.DIR_LEFT:self.image = pygame.transform.rotate(self.image, 90)self.rect = pygame.Rect(position[0] - 8, position[1] + 11, 8, 6)self.explosion_images = [  # 子弹爆炸图片sprites.subsurface(0, 80 * 2, 32 * 2, 32 * 2), sprites.subsurface(32 * 2, 80 * 2, 32 * 2, 32 * 2), ]self.speed = speedself.state = self.STATE_ACTIVEdef find(self):print "玩家射出的子弹移伤害为:" + str(self.damage) +",子弹飞行速度为:" + str(self.speed)def draw(self):""" draw bullet 画子弹"""global screenif self.state == self.STATE_ACTIVE:  # 子弹射出的时候的样子screen.blit(self.image, self.rect.topleft)elif self.state == self.STATE_EXPLODING:  # 子弹爆炸时候的样子self.explosion.draw()def update(self):global castle, players, enemies, bullets  # 城堡,玩家,敌人,子弹if self.state == self.STATE_EXPLODING:if not self.explosion.active:self.destroy()del self.explosionif self.state != self.STATE_ACTIVE:return""" move bullet 子弹移动"""if self.direction == self.DIR_UP:self.rect.topleft = [self.rect.left, self.rect.top - self.speed]if self.rect.top < 0:if play_sounds and self.owner == self.OWNER_PLAYER:try:sounds["steel"].play()# time.sleep(1)except:print "无法播放子弹击中屏幕顶端墙边bgm"print "子弹从顶端到底部花了"self.explode()returnelif self.direction == self.DIR_RIGHT:self.rect.topleft = [self.rect.left + self.speed, self.rect.top]if self.rect.left > (416 - self.rect.width):if play_sounds and self.owner == self.OWNER_PLAYER:try:sounds["steel"].play()except:print "无法播放子弹击中屏幕右边墙边bgm"self.explode()returnelif self.direction == self.DIR_DOWN:self.rect.topleft = [self.rect.left, self.rect.top + self.speed]if self.rect.top > (416 - self.rect.height):if play_sounds and self.owner == self.OWNER_PLAYER:try:sounds["steel"].play()except:print "无法播放子弹击中屏幕下面墙边bgm"self.explode()returnelif self.direction == self.DIR_LEFT:self.rect.topleft = [self.rect.left - self.speed, self.rect.top]if self.rect.left < 0:if play_sounds and self.owner == self.OWNER_PLAYER:try:sounds["steel"].play()except:print "无法播放子弹击中屏幕左边墙边bgm"self.explode()return# 是否冲突has_collided = False# check for collisions with walls. one bullet can destroy several (1 or 2) 检查是否与墙壁碰撞。一颗子弹可以摧毁数颗(1颗或2颗)# tiles but explosion remains 1   打到瓷砖,但依然显示爆炸特效rects = self.level.obstacle_rectscollisions = self.rect.collidelistall(rects)  # collidelistall 冲突(爆炸)列表if collisions != []:for i in collisions:if self.level.hitTile(rects[i].topleft, self.power, self.owner == self.OWNER_PLAYER):has_collided = Trueif has_collided:self.explode()return# check for collisions with other bullets 检查是否与其他子弹发生碰撞for bullet in bullets:if self.state == self.STATE_ACTIVE and bullet.owner != self.owner and bullet != self and self.rect.colliderect(bullet.rect):self.explode()return# check for collisions with players 检查是否与玩家发生碰撞for player in players:if player.state == player.STATE_ALIVE and self.rect.colliderect(player.rect):if player.bulletImpact(self.owner == self.OWNER_PLAYER, self.damage, self.owner_class):self.destroy()return# check for collisions with enemies检查与敌人的碰撞for enemy in enemies:if enemy.state == enemy.STATE_ALIVE and self.rect.colliderect(enemy.rect):if enemy.bulletImpact(self.owner == self.OWNER_ENEMY, self.damage, self.owner_class):self.destroy()return# check for collision with castle 检查是否与城堡发生碰撞if castle.active and self.rect.colliderect(castle.rect):castle.destroy()self.destroy()returndef explode(self):""" start bullets's explosion 开始子弹爆炸"""global screenif self.state != self.STATE_REMOVED:self.state = self.STATE_EXPLODINGself.explosion = Explosion([self.rect.left - 13, self.rect.top - 13], None, self.explosion_images)def destroy(self):self.state = self.STATE_REMOVED# 标签类(游戏画面的右边)
class Label():def __init__(self, position, text="", duration=None):self.position = positionself.active = Trueself.text = textself.font = pygame.font.SysFont("Arial", 13)  # 字体if duration != None:  # durationgtimer.add(duration, lambda: self.destroy(), 1)def draw(self):""" draw label 画标签"""global screenscreen.blit(self.font.render(self.text, False, (200, 200, 200)), [self.position[0] + 20, self.position[1] + 8])def destroy(self):self.active = False# 爆炸类
class Explosion():def __init__(self, position, interval=None, images=None):global spritesself.position = [position[0] - 16, position[1] - 16]self.active = Trueif interval == None:interval = 100if images == None:images = [sprites.subsurface(0, 80 * 2, 32 * 2, 32 * 2), sprites.subsurface(32 * 2, 80 * 2, 32 * 2, 32 * 2),sprites.subsurface(64 * 2, 80 * 2, 32 * 2, 32 * 2)]images.reverse()self.images = [] + imagesself.image = self.images.pop()gtimer.add(interval, lambda: self.update(), len(self.images) + 1)def draw(self):global screen""" draw current explosion frame """screen.blit(self.image, self.position)def update(self):""" Advace to the next image """if len(self.images) > 0:self.image = self.images.pop()else:self.active = False# 瓷砖
class Level():# tile constants(TILE_EMPTY, TILE_BRICK, TILE_STEEL, TILE_WATER, TILE_GRASS, TILE_FROZE) = range(6)# tile width/height in px平铺宽度/高度 16个像素(px)TILE_SIZE = 16def __init__(self, level_nr=None):""" There are total 35 different levels. If level_nr is larger than 35, loop overto next according level so, for example, if level_nr ir 37, then load level 2总共有35个不同的等级。如果level_nr大于35,循环;例如,如果level_nr ir 37,则加载level 2"""global sprites# max number of enemies simultaneously  being on map 最大数量的敌人同时在地图上是4self.max_active_enemies = 4tile_images = [pygame.Surface((8 * 2, 8 * 2)), sprites.subsurface(48 * 2, 64 * 2, 8 * 2, 8 * 2),sprites.subsurface(48 * 2, 72 * 2, 8 * 2, 8 * 2),sprites.subsurface(56 * 2, 72 * 2, 8 * 2, 8 * 2),sprites.subsurface(64 * 2, 64 * 2, 8 * 2, 8 * 2),sprites.subsurface(64 * 2, 64 * 2, 8 * 2, 8 * 2),sprites.subsurface(72 * 2, 64 * 2, 8 * 2, 8 * 2),sprites.subsurface(64 * 2, 72 * 2, 8 * 2, 8 * 2)]self.tile_empty = tile_images[0]self.tile_brick = tile_images[1]self.tile_steel = tile_images[2]self.tile_grass = tile_images[3]self.tile_water = tile_images[4]self.tile_water1 = tile_images[4]self.tile_water2 = tile_images[5]self.tile_froze = tile_images[6]self.obstacle_rects = []# 关卡等级level_nr = 1 if level_nr == None else level_nr % 35if level_nr == 0:level_nr = 35self.loadLevel(level_nr)# tiles' rects on map, tanks cannot move over 瓷砖在地图上的rects,坦克不能移动self.obstacle_rects = []# update these tiles 更新障碍物列表self.updateObstacleRects()gtimer.add(400, lambda: self.toggleWaves())# 根据子弹是1还是2来更新子弹打的显示效果def hitTile(self, pos, power=1, sound=False):"""Hit the tile@param pos Tile's x, y in px@return True if bullet was stopped, False otherwise 如果子弹被停止,返回True,否则返回False"""global play_sounds, soundsfor tile in self.mapr:if tile.topleft == pos:if tile.type == self.TILE_BRICK:if play_sounds and sound:try:sounds["brick"].play()except:print "无法播放子弹击中墙砖时bgm"self.mapr.remove(tile)self.updateObstacleRects()return Trueelif tile.type == self.TILE_STEEL:if play_sounds and sound:try:sounds["steel"].play()except:print "无法播放子弹击中墙砖时bgm"if power == 2:  # 能摧毁钢铁的子弹为2self.mapr.remove(tile)self.updateObstacleRects()return Trueelse:return Falsedef toggleWaves(self):""" Toggle water image 切换图片"""if self.tile_water == self.tile_water1:self.tile_water = self.tile_water2else:self.tile_water = self.tile_water1def loadLevel(self, level_nr=1):""" Load specified level 加载指定关卡等级@return boolean Whether level was loaded 返回的是布尔值,是-加载 , 否-没有加载"""filename = "levels/" + str(level_nr)  # 读取关卡文件if (not os.path.isfile(filename)):return Falselevel = []f = open(filename, "r")data = f.read().split("\n")self.mapr = []x, y = 0, 0for row in data:  # 把文件的符号翻译成对应的瓷砖类型for ch in row:if ch == "#":self.mapr.append(myRect(x, y, self.TILE_SIZE, self.TILE_SIZE, self.TILE_BRICK))elif ch == "@":self.mapr.append(myRect(x, y, self.TILE_SIZE, self.TILE_SIZE, self.TILE_STEEL))elif ch == "~":self.mapr.append(myRect(x, y, self.TILE_SIZE, self.TILE_SIZE, self.TILE_WATER))elif ch == "%":self.mapr.append(myRect(x, y, self.TILE_SIZE, self.TILE_SIZE, self.TILE_GRASS))elif ch == "-":self.mapr.append(myRect(x, y, self.TILE_SIZE, self.TILE_SIZE, self.TILE_FROZE))x += self.TILE_SIZEx = 0y += self.TILE_SIZEreturn Truedef draw(self, tiles=None):""" Draw specified map on top of existing surface 在现有表面上绘制指定的地图"""global screenif tiles == None:tiles = [TILE_BRICK, TILE_STEEL, TILE_WATER, TILE_GRASS, TILE_FROZE]for tile in self.mapr:  # 开始画图if tile.type in tiles:if tile.type == self.TILE_BRICK:screen.blit(self.tile_brick, tile.topleft)elif tile.type == self.TILE_STEEL:screen.blit(self.tile_steel, tile.topleft)elif tile.type == self.TILE_WATER:screen.blit(self.tile_water, tile.topleft)elif tile.type == self.TILE_FROZE:screen.blit(self.tile_froze, tile.topleft)elif tile.type == self.TILE_GRASS:screen.blit(self.tile_grass, tile.topleft)def updateObstacleRects(self):""" Set self.obstacle_rects to all tiles' rects that players can destroywith bullets 设定可以摧毁瓷砖的子弹"""global castleself.obstacle_rects = [castle.rect]for tile in self.mapr:if tile.type in (self.TILE_BRICK, self.TILE_STEEL, self.TILE_WATER):self.obstacle_rects.append(tile)def buildFortress(self, tile):""" Build walls around castle made from tile 用瓷砖在城堡周围筑墙"""positions = [(11 * self.TILE_SIZE, 23 * self.TILE_SIZE), (11 * self.TILE_SIZE, 24 * self.TILE_SIZE),(11 * self.TILE_SIZE, 25 * self.TILE_SIZE), (14 * self.TILE_SIZE, 23 * self.TILE_SIZE),(14 * self.TILE_SIZE, 24 * self.TILE_SIZE), (14 * self.TILE_SIZE, 25 * self.TILE_SIZE),(12 * self.TILE_SIZE, 23 * self.TILE_SIZE), (13 * self.TILE_SIZE, 23 * self.TILE_SIZE)]obsolete = []for i, rect in enumerate(self.mapr):if rect.topleft in positions:obsolete.append(rect)for rect in obsolete:self.mapr.remove(rect)for pos in positions:self.mapr.append(myRect(pos[0], pos[1], self.TILE_SIZE, self.TILE_SIZE, tile))self.updateObstacleRects()#  坦克类
class Tank():# possible directions 可能会出现的位置(DIR_UP, DIR_RIGHT, DIR_DOWN, DIR_LEFT) = range(4)# states 坦克的状态(STATE_SPAWNING, STATE_DEAD, STATE_ALIVE, STATE_EXPLODING) = range(4)# sides  坦克类型:玩家\机器人(SIDE_PLAYER, SIDE_ENEMY) = range(2)def __init__(self, level, side, position=None, direction=None, filename=None):global sprites# health. 0 health means dead,健康。0健康意味着死亡/坦克默认是100血self.health = 100# tank can't move but can rotate and shoot 坦克不能移动,但可以旋转和射击self.paralised = False# tank can't do anything 坦克什么也做不了self.paused = False# tank is protected from bullets 坦克不受子弹的伤害self.shielded = Falseself.speed = 2# how many bullets can tank fire simultaneously 坦克能同时发射多少子弹self.max_active_bullets = 1self.side = side# flashing state. 0-off, 1-on  坦克闪烁状态 0 不闪烁, 1 闪烁self.flash = 0# 0 - no superpowers# 1 - faster bullets# 2 - can fire 2 bullets# 3 - can destroy steel"""0 -没有超能力1-更快的子弹2 -可以发射2颗子弹3-能摧毁钢铁"""self.superpowers = 0# each tank can pick up 1 bonus 每个坦克可以获得1加值self.bonus = None# navigation keys: fire, up, right, down, left 坦克移动键:火,上,右,下,左self.controls = [pygame.K_SPACE, pygame.K_UP, pygame.K_RIGHT, pygame.K_DOWN, pygame.K_LEFT]# currently pressed buttons (navigation only)当前按下的按钮(仅供导航)  坦克有4个键位self.pressed = [False] * 4self.shield_images = [  # 坦克的盾sprites.subsurface(0, 48 * 2, 16 * 2, 16 * 2), sprites.subsurface(16 * 2, 48 * 2, 16 * 2, 16 * 2)]self.shield_image = self.shield_images[0]self.shield_index = 0self.spawn_images = [  # 坦克刚下来的样子?sprites.subsurface(32 * 2, 48 * 2, 16 * 2, 16 * 2), sprites.subsurface(48 * 2, 48 * 2, 16 * 2, 16 * 2)]self.spawn_image = self.spawn_images[0]self.spawn_index = 0self.level = levelif position != None:self.rect = pygame.Rect(position, (26, 26))else:self.rect = pygame.Rect(0, 0, 26, 26)if direction == None:self.direction = random.choice([self.DIR_RIGHT, self.DIR_DOWN, self.DIR_LEFT])else:self.direction = directionself.state = self.STATE_SPAWNING# spawning animation 坦克生成的动画?self.timer_uuid_spawn = gtimer.add(100, lambda: self.toggleSpawnImage())# duration of spawning 坦克生成的时间?self.timer_uuid_spawn_end = gtimer.add(1000, lambda: self.endSpawning())def endSpawning(self):""" End spawning Player becomes operational 从生产状态转变为玩家操控状态"""self.state = self.STATE_ALIVEgtimer.destroy(self.timer_uuid_spawn_end)def toggleSpawnImage(self):""" advance to the next spawn image 推进到下一个衍生图像"""if self.state != self.STATE_SPAWNING:gtimer.destroy(self.timer_uuid_spawn)returnself.spawn_index += 1if self.spawn_index >= len(self.spawn_images):self.spawn_index = 0self.spawn_image = self.spawn_images[self.spawn_index]# 护盾图像def toggleShieldImage(self):""" advance to the next shield image进入下一个盾牌图像 """if self.state != self.STATE_ALIVE:gtimer.destroy(self.timer_uuid_shield)returnif self.shielded:self.shield_index += 1if self.shield_index >= len(self.shield_images):self.shield_index = 0self.shield_image = self.shield_images[self.shield_index]def draw(self):""" draw tank 画坦克"""global screenif self.state == self.STATE_ALIVE:screen.blit(self.image, self.rect.topleft)if self.shielded:screen.blit(self.shield_image, [self.rect.left - 3, self.rect.top - 3])elif self.state == self.STATE_EXPLODING:self.explosion.draw()elif self.state == self.STATE_SPAWNING:screen.blit(self.spawn_image, self.rect.topleft)def explode(self):""" start tanks's explosion 开始坦克的爆炸"""if self.state != self.STATE_DEAD:self.state = self.STATE_EXPLODINGself.explosion = Explosion(self.rect.topleft)if self.bonus:self.spawnBonus()# 坦克发射子弹def fire(self, forced=False):""" Shoot a bullet 坦克射出一个子弹@param boolean forced. If false, check whether tank has exceeded his bullet quota. Default: True 如果错误,检查坦克是否超过子弹限额。默认值:真正的@return boolean True if bullet was fired, false otherwise 如果子弹被发射,为真,否则为假"""global bullets, labelsif self.state != self.STATE_ALIVE:gtimer.destroy(self.timer_uuid_fire)return Falseif self.paused:return Falseif not forced:active_bullets = 0for bullet in bullets:if bullet.owner_class == self and bullet.state == bullet.STATE_ACTIVE:active_bullets += 1if active_bullets >= self.max_active_bullets:return Falsebullet = Bullet(self.level, self.rect.topleft, self.direction)# 坦克超能力# if superpower level is at least 1 如果子弹速度超能力级别至少为1if self.superpowers > 0:bullet.speed = 8  # 子弹速度是8# if superpower level is at least 3 如果超能力等级至少为3if self.superpowers > 2:  # 子弹为2bullet.power = 2if self.side == self.SIDE_PLAYER:bullet.owner = self.SIDE_PLAYERelse:bullet.owner = self.SIDE_ENEMYself.bullet_queued = Falsebullet.owner_class = selfbullets.append(bullet)return True# 坦克根据方向键旋转def rotate(self, direction, fix_position=True):""" Rotate tankrotate, update image and correct position 旋转槽旋转,更新图像和正确的位置"""self.direction = directionif direction == self.DIR_UP:self.image = self.image_upelif direction == self.DIR_RIGHT:self.image = self.image_rightelif direction == self.DIR_DOWN:self.image = self.image_downelif direction == self.DIR_LEFT:self.image = self.image_leftif fix_position:new_x = self.nearest(self.rect.left, 8) + 3new_y = self.nearest(self.rect.top, 8) + 3if (abs(self.rect.left - new_x) < 5):self.rect.left = new_xif (abs(self.rect.top - new_y) < 5):self.rect.top = new_y# 把坦克转向相反的方向def turnAround(self):""" Turn tank into opposite direction 把坦克转向相反的方向"""if self.direction in (self.DIR_UP, self.DIR_RIGHT):self.rotate(self.direction + 2, False)else:self.rotate(self.direction - 2, False)# 更新计时器和爆炸def update(self, time_passed):""" Update timer and explosion (if any) 更新计时器和爆炸(如果有的话)"""if self.state == self.STATE_EXPLODING:if not self.explosion.active:self.state = self.STATE_DEADdel self.explosion# 整数到最能整除的数def nearest(self, num, base):""" Round number to nearest divisible ??整数到最能整除的数"""return int(round(num / (base * 1.0)) * base)# 如果子弹在撞击时被摧毁,返回True , 只有敌人交火才是Falsedef bulletImpact(self, friendly_fire=False, damage=100, tank=None):""" Bullet impactReturn True if bullet should be destroyed on impact. Only enemy friendly-fire 如果子弹在撞击时被摧毁,返回True。只有敌人交火doesn't trigger bullet explosion不会引起子弹爆炸"""#  子弹声音global play_sounds, soundsif self.shielded:return Trueif not friendly_fire:self.health -= damageif self.health < 1:if self.side == self.SIDE_ENEMY:tank.trophies["enemy" + str(self.type)] += 1points = (self.type + 1) * 100tank.score += pointsif play_sounds:try:sounds["explosion"].play()except:print "无法播放爆炸bgm"labels.append(Label(self.rect.topleft, str(points), 500))self.explode()return Trueif self.side == self.SIDE_ENEMY:return Falseelif self.side == self.SIDE_PLAYER:if not self.paralised:self.setParalised(True)self.timer_uuid_paralise = gtimer.add(10000, lambda: self.setParalised(False), 1)  # 玩家之间互殴后停留10秒return Truedef setParalised(self, paralised=True):""" set tank paralise state 双人模式坦克互殴,设置坦克状态@param boolean paralised@return None"""if self.state != self.STATE_ALIVE:gtimer.destroy(self.timer_uuid_paralise)returnself.paralised = paralised"""实例化坦克对象"""
#  敌人坦克
class Enemy(Tank):(TYPE_BASIC, TYPE_FAST, TYPE_POWER, TYPE_ARMOR) = range(4)def __init__(self, level, type, position=None, direction=None, filename=None):Tank.__init__(self, level, type, position=None, direction=None, filename=None)global enemies, sprites# if true, do not fire 为真则不开火self.bullet_queued = False# chose type on random 随机选择类型if len(level.enemies_left) > 0:self.type = level.enemies_left.pop()else:self.state = self.STATE_DEADreturnif self.type == self.TYPE_BASIC:self.speed = 1elif self.type == self.TYPE_FAST:self.speed = 3elif self.type == self.TYPE_POWER:self.superpowers = 1elif self.type == self.TYPE_ARMOR:self.health = 400# 1 in 5 chance this will be bonus carrier, but only if no other tank is 五分之一的机会,这将是奖励载体,但只有当没有其他坦克# 地图当前只能出现一个奖励载体坦克(修改这里可以刷出更多的道具坦克)if random.randint(1, 5) == 1:self.bonus = Truefor enemy in enemies:if enemy.bonus:self.bonus = Falsebreakimages = [sprites.subsurface(32 * 2, 0, 13 * 2, 15 * 2), sprites.subsurface(48 * 2, 0, 13 * 2, 15 * 2),sprites.subsurface(64 * 2, 0, 13 * 2, 15 * 2), sprites.subsurface(80 * 2, 0, 13 * 2, 15 * 2),sprites.subsurface(32 * 2, 16 * 2, 13 * 2, 15 * 2),sprites.subsurface(48 * 2, 16 * 2, 13 * 2, 15 * 2),sprites.subsurface(64 * 2, 16 * 2, 13 * 2, 15 * 2),sprites.subsurface(80 * 2, 16 * 2, 13 * 2, 15 * 2)]self.image = images[self.type + 0]self.image_up = self.image;self.image_left = pygame.transform.rotate(self.image, 90)self.image_down = pygame.transform.rotate(self.image, 180)self.image_right = pygame.transform.rotate(self.image, 270)if self.bonus:self.image1_up = self.image_up;self.image1_left = self.image_leftself.image1_down = self.image_downself.image1_right = self.image_rightself.image2 = images[self.type + 4]self.image2_up = self.image2;self.image2_left = pygame.transform.rotate(self.image2, 90)self.image2_down = pygame.transform.rotate(self.image2, 180)self.image2_right = pygame.transform.rotate(self.image2, 270)self.rotate(self.direction, False)if position == None:self.rect.topleft = self.getFreeSpawningPosition()if not self.rect.topleft:self.state = self.STATE_DEADreturn# list of map coords where tank should go next坦克下一步应该去的地图坐标列表self.path = self.generatePath(self.direction)# 1000 is duration between shots 1000毫秒=10秒是设计的持续时间??self.timer_uuid_fire = gtimer.add(1000, lambda: self.fire())# turn on flashing 开始闪光if self.bonus:self.timer_uuid_flash = gtimer.add(200, lambda: self.toggleFlash())def find(self): # 自定义一个方法去查询坦克实例的属性if self.type == self.TYPE_BASIC:if self.bonus:print "存在普通坦克,它是道具坦克,移速为: " + str(self.speed) + ", 血量为: " +str(self.health) + ",它的能力等级为: " + str(self.superpowers)else:print "存在普通坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)elif self.type == self.TYPE_FAST:if self.bonus:print "存在移速坦克,它是道具坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)else:print "存在移速坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)elif self.type == self.TYPE_POWER:if self.bonus:print "存在力量坦克,它是道具坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)else:print "存在力量坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)elif self.type == self.TYPE_ARMOR:if self.bonus:print "存在护甲坦克,它是道具坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)else:print "存在护甲坦克,移速为: " + str(self.speed) + ", 血量为: " + str(self.health) + ",它的能力等级为: " + str(self.superpowers)# print self.type , self.speed, self.bonus# 道具坦克的发光状态def toggleFlash(self):""" Toggle flash state 发光状态"""if self.state not in (self.STATE_ALIVE, self.STATE_SPAWNING):gtimer.destroy(self.timer_uuid_flash)returnself.flash = not self.flashif self.flash:self.image_up = self.image2_upself.image_right = self.image2_rightself.image_down = self.image2_downself.image_left = self.image2_leftelse:self.image_up = self.image1_upself.image_right = self.image1_rightself.image_down = self.image1_downself.image_left = self.image1_leftself.rotate(self.direction, False)# 道具闪烁频率和存在时长def spawnBonus(self):""" Create new bonus if needed """global bonusesif len(bonuses) > 0:returnbonus = Bonus(self.level)bonuses.append(bonus)gtimer.add(500, lambda: bonus.toggleVisibility())  # 道具闪烁频率gtimer.add(10000, lambda: bonuses.remove(bonus), 1)  # 道具存在时长# 坦克的三个出生点def getFreeSpawningPosition(self):global players, enemies# 坦克的三个出生点available_positions = [[(self.level.TILE_SIZE * 2 - self.rect.width) / 2, (self.level.TILE_SIZE * 2 - self.rect.height) / 2],[12 * self.level.TILE_SIZE + (self.level.TILE_SIZE * 2 - self.rect.width) / 2,(self.level.TILE_SIZE * 2 - self.rect.height) / 2],[24 * self.level.TILE_SIZE + (self.level.TILE_SIZE * 2 - self.rect.width) / 2,(self.level.TILE_SIZE * 2 - self.rect.height) / 2]]# 随机打乱出生点的顺序random.shuffle(available_positions)for pos in available_positions:enemy_rect = pygame.Rect(pos, [26, 26])# collisions with other enemies 与其他敌人的冲突collision = Falsefor enemy in enemies:if enemy_rect.colliderect(enemy.rect):collision = Truecontinueif collision:continue# collisions with players 与玩家冲突collision = Falsefor player in players:if enemy_rect.colliderect(player.rect):collision = Truecontinueif collision:continuereturn posreturn Falsedef move(self):""" move enemy if possible 尽可能移动敌人"""global players, enemies, bonusesif self.state != self.STATE_ALIVE or self.paused or self.paralised:returnif self.path == []:self.path = self.generatePath(None, True)new_position = self.path.pop(0)# move enemy 敌人移动if self.direction == self.DIR_UP:if new_position[1] < 0:self.path = self.generatePath(self.direction, True)returnelif self.direction == self.DIR_RIGHT:if new_position[0] > (416 - 26):self.path = self.generatePath(self.direction, True)returnelif self.direction == self.DIR_DOWN:if new_position[1] > (416 - 26):self.path = self.generatePath(self.direction, True)returnelif self.direction == self.DIR_LEFT:if new_position[0] < 0:self.path = self.generatePath(self.direction, True)returnnew_rect = pygame.Rect(new_position, [26, 26])# collisions with tiles 与瓷砖的碰撞if new_rect.collidelist(self.level.obstacle_rects) != -1:self.path = self.generatePath(self.direction, True)return# collisions with other enemies 与其他敌人的冲突 , 敌人之间不会发生碰撞# for enemy in enemies:#     if enemy != self and new_rect.colliderect(enemy.rect):#         self.turnAround()#         self.path = self.generatePath(self.direction)#         return# collisions with players 玩家之间的碰撞for player in players:if new_rect.colliderect(player.rect):self.turnAround()self.path = self.generatePath(self.direction)return# collisions with bonuses 碰撞带着道具for bonus in bonuses:if new_rect.colliderect(bonus.rect):bonuses.remove(bonus)# if no collision, move enemy 如果没有碰撞,移动敌人self.rect.topleft = new_rect.topleftdef update(self, time_passed):Tank.update(self, time_passed)if self.state == self.STATE_ALIVE and not self.paused:self.move()def generatePath(self, direction=None, fix_direction=False):""" If direction is specified, try continue that way, otherwise choose at random 如果指定了方向,继续尝试,否则随机选择"""all_directions = [self.DIR_UP, self.DIR_RIGHT, self.DIR_DOWN, self.DIR_LEFT]if direction == None:if self.direction in [self.DIR_UP, self.DIR_RIGHT]:opposite_direction = self.direction + 2else:opposite_direction = self.direction - 2directions = all_directionsrandom.shuffle(directions)directions.remove(opposite_direction)directions.append(opposite_direction)else:if direction in [self.DIR_UP, self.DIR_RIGHT]:opposite_direction = direction + 2else:opposite_direction = direction - 2if direction in [self.DIR_UP, self.DIR_RIGHT]:opposite_direction = direction + 2else:opposite_direction = direction - 2directions = all_directionsrandom.shuffle(directions)directions.remove(opposite_direction)directions.remove(direction)directions.insert(0, direction)directions.append(opposite_direction)# at first, work with general units (steps) not px 首先,使用一般单位(步骤)而不是pxx = int(round(self.rect.left / 16))y = int(round(self.rect.top / 16))new_direction = Nonefor direction in directions:if direction == self.DIR_UP and y > 1:new_pos_rect = self.rect.move(0, -8)if new_pos_rect.collidelist(self.level.obstacle_rects) == -1:new_direction = directionbreakelif direction == self.DIR_RIGHT and x < 24:new_pos_rect = self.rect.move(8, 0)if new_pos_rect.collidelist(self.level.obstacle_rects) == -1:new_direction = directionbreakelif direction == self.DIR_DOWN and y < 24:new_pos_rect = self.rect.move(0, 8)if new_pos_rect.collidelist(self.level.obstacle_rects) == -1:new_direction = directionbreakelif direction == self.DIR_LEFT and x > 1:new_pos_rect = self.rect.move(-8, 0)if new_pos_rect.collidelist(self.level.obstacle_rects) == -1:new_direction = directionbreak# if we can go anywhere else, turn around 如果我们能去别的地方,就掉头吧if new_direction == None:new_direction = opposite_directionprint "nav izejas. griezhamies"# fix tanks position 修复坦克的位置if fix_direction and new_direction == self.direction:fix_direction = Falseself.rotate(new_direction, fix_direction)positions = []x = self.rect.lefty = self.rect.topif new_direction in (self.DIR_RIGHT, self.DIR_LEFT):axis_fix = self.nearest(y, 16) - yelse:axis_fix = self.nearest(x, 16) - xaxis_fix = 0pixels = self.nearest(random.randint(1, 12) * 32, 32) + axis_fix + 3if new_direction == self.DIR_UP:for px in range(0, pixels, self.speed):positions.append([x, y - px])elif new_direction == self.DIR_RIGHT:for px in range(0, pixels, self.speed):positions.append([x + px, y])elif new_direction == self.DIR_DOWN:for px in range(0, pixels, self.speed):positions.append([x, y + px])elif new_direction == self.DIR_LEFT:for px in range(0, pixels, self.speed):positions.append([x - px, y])return positions# 玩家
class Player(Tank):def __init__(self, level, type, position=None, direction=None, filename=None):Tank.__init__(self, level, type, position=None, direction=None, filename=None)global spritesif filename == None:filename = (0, 0, 16 * 2, 16 * 2)self.start_position = positionself.start_direction = directionself.lives = 3  # 初始生命条数 , 生命数# total score初始总分是0self.score = 0# 储存这个玩家在这关的战绩self.trophies = {"bonus": 0, "enemy0": 0, "enemy1": 0, "enemy2": 0, "enemy3": 0}self.image = sprites.subsurface(filename)self.image_up = self.image;self.image_left = pygame.transform.rotate(self.image, 90)self.image_down = pygame.transform.rotate(self.image, 180)self.image_right = pygame.transform.rotate(self.image, 270)if direction == None:self.rotate(self.DIR_UP, False)else:self.rotate(direction, False)def move(self, direction):""" move player if possible 玩家移动"""global players, enemies, bonusesif self.state == self.STATE_EXPLODING:if not self.explosion.active:self.state = self.STATE_DEADdel self.explosionif self.state != self.STATE_ALIVE:return# rotate player 旋转玩家if self.direction != direction:self.rotate(direction)if self.paralised:return# move player 移动玩家if direction == self.DIR_UP:new_position = [self.rect.left, self.rect.top - self.speed]if new_position[1] < 0:returnelif direction == self.DIR_RIGHT:new_position = [self.rect.left + self.speed, self.rect.top]if new_position[0] > (416 - 26):returnelif direction == self.DIR_DOWN:new_position = [self.rect.left, self.rect.top + self.speed]if new_position[1] > (416 - 26):returnelif direction == self.DIR_LEFT:new_position = [self.rect.left - self.speed, self.rect.top]if new_position[0] < 0:returnplayer_rect = pygame.Rect(new_position, [26, 26])# collisions with tiles 与瓷砖碰撞if player_rect.collidelist(self.level.obstacle_rects) != -1:return# collisions with other players 与其他玩家碰撞for player in players:if player != self and player.state == player.STATE_ALIVE and player_rect.colliderect(player.rect) == True:return# collisions with enemies 与敌人碰撞for enemy in enemies:if player_rect.colliderect(enemy.rect) == True:return# collisions with bonuses 碰撞道具坦克for bonus in bonuses:if player_rect.colliderect(bonus.rect) == True:self.bonus = bonus# if no collision, move player如果没有碰撞,移动玩家self.rect.topleft = (new_position[0], new_position[1])def reset(self):""" reset player 重置玩家"""self.rotate(self.start_direction, False)self.rect.topleft = self.start_positionif god == False:self.superpowers = 0self.max_active_bullets = 1else:# 修改无敌模式的数值self.superpowers = 3self.max_active_bullets = 2self.speed = 5self.health = 100self.paralised = Falseself.paused = Falseself.pressed = [False] * 4self.state = self.STATE_ALIVE# 开始游戏
class Game():# direction constants(DIR_UP, DIR_RIGHT, DIR_DOWN, DIR_LEFT) = range(4)TILE_SIZE = 16  # 瓷砖大小是16def __init__(self):global screen, sprites, play_sounds, sounds, Fullscreen,textList,bullets# center windowos.environ['SDL_VIDEO_WINDOW_POS'] = 'center'if play_sounds:pygame.mixer.pre_init(44100, -16, 1, 512)pygame.init()pygame.display.set_caption("Battle City")global sizesize = width, height = 480, 416#  玩家输入-f可以获得全屏if "-f" in sys.argv[1:]:screen = pygame.display.set_mode(size, pygame.FULLSCREEN)else:screen = pygame.display.set_mode(size)self.clock = pygame.time.Clock()# load sprites (funky version)# sprites = pygame.transform.scale2x(pygame.image.load("images/sprites.gif"))# load sprites (pixely version)sprites = pygame.transform.scale(pygame.image.load("images/sprites.gif"), [192, 224])# screen.set_colorkey((0,138,104))pygame.display.set_icon(sprites.subsurface(0, 0, 13 * 2, 13 * 2))# load soundstry:if play_sounds:pygame.mixer.init(44100, -16, 1, 512)sounds["start"] = pygame.mixer.Sound("sounds/gamestart.ogg")sounds["end"] = pygame.mixer.Sound("sounds/gameover.ogg")sounds["score"] = pygame.mixer.Sound("sounds/score.ogg")sounds["bg"] = pygame.mixer.Sound("sounds/background.ogg")sounds["fire"] = pygame.mixer.Sound("sounds/fire.ogg")sounds["bonus"] = pygame.mixer.Sound("sounds/bonus.ogg")sounds["explosion"] = pygame.mixer.Sound("sounds/explosion.ogg")sounds["brick"] = pygame.mixer.Sound("sounds/brick.ogg")sounds["steel"] = pygame.mixer.Sound("sounds/steel.ogg")except:print "没有插耳机"  # 不插耳机报错# finally:#     pygame.mixer.init(44100, -16, 1, 512)#     sounds["start"] = pygame.mixer.Sound("sounds/gamestart.ogg")#     sounds["end"] = pygame.mixer.Sound("sounds/gameover.ogg")#     sounds["score"] = pygame.mixer.Sound("sounds/score.ogg")#     sounds["bg"] = pygame.mixer.Sound("sounds/background.ogg")#     sounds["fire"] = pygame.mixer.Sound("sounds/fire.ogg")#     sounds["bonus"] = pygame.mixer.Sound("sounds/bonus.ogg")#     sounds["explosion"] = pygame.mixer.Sound("sounds/explosion.ogg")#     sounds["brick"] = pygame.mixer.Sound("sounds/brick.ogg")#     sounds["steel"] = pygame.mixer.Sound("sounds/steel.ogg")self.enemy_life_image = sprites.subsurface(81 * 2, 57 * 2, 7 * 2, 7 * 2)self.player_life_image = sprites.subsurface(89 * 2, 56 * 2, 7 * 2, 8 * 2)self.flag_image = sprites.subsurface(64 * 2, 49 * 2, 16 * 2, 15 * 2)# this is used in intro screen这在介绍屏幕中使用self.player_image = pygame.transform.rotate(sprites.subsurface(0, 0, 13 * 2, 13 * 2), 270)# if true, no new enemies will be spawn during this time 如果是这样,在此期间不会产生新的敌人self.timefreeze = False# load custom font加载自定义字体self.font = pygame.font.Font("fonts/prstart.ttf", 16)# pre-render game over text预先渲染游戏的文字self.im_game_over = pygame.Surface((64, 40))self.im_game_over.set_colorkey((0, 0, 0))self.im_game_over.blit(self.font.render("GAME", False, (127, 64, 64)), [0, 0])self.im_game_over.blit(self.font.render("OVER", False, (127, 64, 64)), [0, 20])self.game_over_y = 416 + 40# number of players. here is defined preselected menu value 默认的玩家数量是1(菜单默认1开始,)self.nr_of_players = 1del players[:]del bullets[:]del enemies[:]del bonuses[:]def gameLoop(self, flag):while flag:if flag == False:break# 触发道具def triggerBonus(self, bonus, player):""" Execute bonus powers 执行额外的权力"""global enemies, labels, play_sounds, soundsif play_sounds:try:sounds["bonus"].play()except:print "无法播放获得道具时bgm"player.trophies["bonus"] += 1player.score += 500  # 触发道具+500分if bonus.bonus == bonus.BONUS_GRENADE:for enemy in enemies:enemy.explode()elif bonus.bonus == bonus.BONUS_HELMET:if god == False:self.shieldPlayer(player, True, 10000)  # 护盾持续10000毫秒=10秒elif bonus.bonus == bonus.BONUS_SHOVEL:self.level.buildFortress(self.level.TILE_STEEL)gtimer.add(10000, lambda: self.level.buildFortress(self.level.TILE_BRICK), 1)elif bonus.bonus == bonus.BONUS_STAR:player.superpowers += 1if player.superpowers == 2:player.max_active_bullets = 2  # 坦克最多同时发射的子弹elif bonus.bonus == bonus.BONUS_TANK:player.lives += 1  # 生命+1elif bonus.bonus == bonus.BONUS_TIMER:self.toggleEnemyFreeze(True)  # 敌人被冻住10秒gtimer.add(10000, lambda: self.toggleEnemyFreeze(False), 1)bonuses.remove(bonus)labels.append(Label(bonus.rect.topleft, "500", 500))def shieldPlayer(self, player, shield=True, duration=None):""" 添加/移除护盾玩家: 玩家 (非敌人)护盾: 真/假(布尔型)持续时间: 在(持续时间)毫秒内. 如果没有, 不要自动移除护盾"""player.shielded = shieldif shield:player.timer_uuid_shield = gtimer.add(100, lambda: player.toggleShieldImage())  # 任务定时器else:gtimer.destroy(player.timer_uuid_shield)if shield and duration != None:  # 如果有护盾,持续时间不为空gtimer.add(duration, lambda: self.shieldPlayer(player, False), 1)# 生成坦克def spawnEnemy(self):""" Spawn new enemy if needed 如果有需要就产生新的坦克Only add enemy if:- there are at least one in queue至少有一个在排队- map capacity hasn't exceeded its quota地图容量没有超过限额- now isn't timefreeze现在不是时间冻结"""global enemiesif len(enemies) >= self.level.max_active_enemies:returnif len(self.level.enemies_left) < 1 or self.timefreeze:returnenemy = Enemy(self.level, 1)enemies.append(enemy)# 玩家重生def respawnPlayer(self, player, clear_scores=False):""" 玩家重生 """player.reset()if clear_scores:player.trophies = {"bonus": 0, "enemy0": 0, "enemy1": 0, "enemy2": 0, "enemy3": 0}if god == False:self.shieldPlayer(player, True, 4000)else:# 无敌模式self.shieldPlayer(player, True, 99999999999)print "进入无敌模式"# 设定self.game_over = Truedef gameOver(self):""" 结束游戏 返回到菜单 """global play_sounds, soundsprint "Game Over"if play_sounds:try:for sound in sounds:sounds[sound].stop()sounds["end"].play()except:print "无法播放游戏结束bgm"self.game_over_y = 416 + 40self.game_over = Truegtimer.add(3000, lambda: self.showScores(), 1)  # 展示分数def gameOverScreen(self):#  游戏结束时界面global screen, FullscreenFullscreen = False# 停止游戏主循环self.running = Falsescreen.fill([0, 0, 0])  # 游戏结束时背景颜色self.writeInBricks("game", [125, 140])  # [x,y] x为横坐标,y为纵坐标,意思是字体显示位置self.writeInBricks("over", [125, 220])pygame.display.flip()  # 更新整个待显示的 Surface 对象到屏幕上while 1:  # 循环time_passed = self.clock.tick(50)for event in pygame.event.get():  # 监听用户事件if event.type == pygame.QUIT:  # 判断用户是否点击了关闭按钮print "quit()3"quit()  # 关闭所有相关联的窗口elif event.type == pygame.KEYDOWN:  # 判断用户是否按下键盘if event.key == pygame.K_p :  # 游戏结算界面暂停Flag = Trueprint "结算界面暂停"while Flag:for event in pygame.event.get():if event.type == pygame.KEYDOWN:#sleep(1)if event.key == pygame.K_p:# self.writeInBricks("stopping", [65, 80])# print "开始"Flag = Falseelse:continueif event.key == pygame.K_u:  # u键切换窗口为全屏或窗口Fullscreen = not Fullscreenif Fullscreen:print "菜单进入全屏"screen = pygame.display.set_mode(size, pygame.FULLSCREEN)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(3000, lambda: self.FreezeAll(False), 1)else:print "菜单进入窗口"screen = pygame.display.set_mode(size)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(3000, lambda: self.FreezeAll(False), 1)# elif event.key == pygame.K_RETURN:  # 判断按键输入为Enter时self.showMenu()  # 调用showMenu回到主菜单returndef showMenu(self):# 显示游戏菜单# 仅当按下向上或向下键时重新绘制屏幕。# 当按下回车键时,退出这个屏幕,跳转到主界面中进行玩家人数选择global players, screen# stop game main loop (if any)停止游戏主循环(如果有的话)self.running = False# clear all timers 清除所有计时器del gtimer.timers[:]# 设置当前阶段为0 ,等于1时,是第2关,所以是从0开始才对,初始关卡(设置关卡)# self.stage = 1self.stage = 0self.animateIntroScreen()main_loop = TrueFullscreen = Falserunning = 0flag = Falsewhile main_loop:time_passed = self.clock.tick(50)# 各种事件for event in pygame.event.get():if event.type == pygame.QUIT:quit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_u:  # f键切换窗口为全屏或窗口Fullscreen = not Fullscreenif Fullscreen:print "菜单进入全屏"screen = pygame.display.set_mode(size, pygame.FULLSCREEN)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(30000, lambda: self.FreezeAll(False), 1)else:print "菜单进入窗口"screen = pygame.display.set_mode(size)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(30000, lambda: self.FreezeAll(False), 1)elif event.key == pygame.K_p :  # 菜单暂停Flag = Trueprint "菜单界面停"while Flag:for event in pygame.event.get():if event.type == pygame.KEYDOWN:#sleep(1)if event.key == pygame.K_p:# self.writeInBricks("stopping", [65, 80])# print "开始"Flag = Falseelse:continueelif event.key == pygame.K_q:quit()elif event.key == pygame.K_UP:if self.nr_of_players == 2:self.nr_of_players = 1self.drawIntroScreen()elif self.nr_of_players == 3:self.nr_of_players = 2self.drawIntroScreen()elif event.key == pygame.K_DOWN:if self.nr_of_players == 1:self.nr_of_players = 2self.drawIntroScreen()elif self.nr_of_players == 2:self.nr_of_players = 3self.drawIntroScreen()elif event.key == pygame.K_RETURN:main_loop = Falsedel players[:]self.nextLevel()# 重新载入玩家,包括玩家出生点def reloadPlayers(self):"""初始化玩家如果玩家已经存在,只需重置他们"""global players, textListif len(players) == 0:# first player 第一个玩家x = 8 * self.TILE_SIZE + (self.TILE_SIZE * 2 - 26) / 2y = 24 * self.TILE_SIZE + (self.TILE_SIZE * 2 - 26) / 2player = Player(self.level, 0, [x, y], self.DIR_UP, (0, 0, 13 * 2, 13 * 2))players.append(player)# second player 第二个玩家if self.nr_of_players == 2:x = 16 * self.TILE_SIZE + (self.TILE_SIZE * 2 - 26) / 2y = 24 * self.TILE_SIZE + (self.TILE_SIZE * 2 - 26) / 2player = Player(self.level, 0, [x, y], self.DIR_UP, (16 * 2, 0, 13 * 2, 13 * 2))player.controls = [102, 119, 100, 115, 97]players.append(player)for player in players:player.level = self.levelif player.lives == 0:player.lives += 1self.respawnPlayer(player, True)else:self.respawnPlayer(player, True)# 展示关卡分数def showScores(self):""" 展示关卡分数 """global screen, sprites, players, play_sounds, sounds# 停止游戏主循环self.running = False# 清除所有计时器del gtimer.timers[:]if play_sounds:for sound in sounds:sounds[sound].stop()hiscore = self.loadHiscore()# 如果需要更新最高分if players[0].score > hiscore:hiscore = players[0].scoreself.saveHiscore(hiscore)if self.nr_of_players == 2 and players[1].score > hiscore:hiscore = players[1].scoreself.saveHiscore(hiscore)img_tanks = [  # 敌方坦克图片加载sprites.subsurface(32 * 2, 0, 13 * 2, 15 * 2), sprites.subsurface(48 * 2, 0, 13 * 2, 15 * 2),sprites.subsurface(64 * 2, 0, 13 * 2, 15 * 2), sprites.subsurface(80 * 2, 0, 13 * 2, 15 * 2)]img_arrows = [  # 箭头加载sprites.subsurface(81 * 2, 48 * 2, 7 * 2, 7 * 2), sprites.subsurface(88 * 2, 48 * 2, 7 * 2, 7 * 2)]screen.fill([0, 0, 0])# 颜色black = pygame.Color("black")white = pygame.Color("white")purple = pygame.Color(127, 64, 64)pink = pygame.Color(191, 160, 128)screen.blit(self.font.render("HI-SCORE", False, purple), [105, 35])screen.blit(self.font.render(str(hiscore), False, pink), [295, 35])screen.blit(self.font.render("STAGE" + str(self.stage).rjust(3), False, white), [170, 65])screen.blit(self.font.render("I-PLAYER", False, purple), [25, 95])# 玩家一的分数screen.blit(self.font.render(str(players[0].score).rjust(8), False, pink), [25, 125])print players[0].scoreif self.nr_of_players == 2:screen.blit(self.font.render("II-PLAYER", False, purple), [310, 95])# 玩家二的分数screen.blit(self.font.render(str(players[1].score).rjust(8), False, pink), [325, 125])# 坦克和箭头for i in range(4):screen.blit(img_tanks[i], [226, 160 + (i * 45)])screen.blit(img_arrows[0], [206, 168 + (i * 45)])if self.nr_of_players == 2:screen.blit(img_arrows[1], [258, 168 + (i * 45)])screen.blit(self.font.render("TOTAL", False, white), [70, 335])# 总计 下划线pygame.draw.line(screen, white, [170, 330], [307, 330], 4)pygame.display.flip()self.clock.tick(2)interval = 5# 分数和击杀数for i in range(4):# 特定坦克总数tanks = players[0].trophies["enemy" + str(i)]for n in range(tanks + 1):if n > 0 and play_sounds:try:sounds["score"].play()except:print "无法播放结算bgm"# 删除之前的文本screen.blit(self.font.render(str(n - 1).rjust(2), False, black), [170, 168 + (i * 45)])# 打印新的敌人数量screen.blit(self.font.render(str(n).rjust(2), False, white), [170, 168 + (i * 45)])# 删除之前的文本screen.blit(self.font.render(str((n - 1) * (i + 1) * 100).rjust(4) + " PTS", False, black),[25, 168 + (i * 45)])# 打印每个敌人的总分数screen.blit(self.font.render(str(n * (i + 1) * 100).rjust(4) + " PTS", False, white),[25, 168 + (i * 45)])pygame.display.flip()self.clock.tick(interval+5)if self.nr_of_players == 2:tanks = players[1].trophies["enemy" + str(i)]for n in range(tanks + 1):if n > 0 and play_sounds:try:sounds["score"].play()except:print "无法播放结算bgm"screen.blit(self.font.render(str(n - 1).rjust(2), False, black), [277, 168 + (i * 45)])screen.blit(self.font.render(str(n).rjust(2), False, white), [277, 168 + (i * 45)])screen.blit(self.font.render(str((n - 1) * (i + 1) * 100).rjust(4) + " PTS", False, black),[325, 168 + (i * 45)])screen.blit(self.font.render(str(n * (i + 1) * 100).rjust(4) + " PTS", False, white),[325, 168 + (i * 45)])pygame.display.flip()self.clock.tick(interval)self.clock.tick(interval)# 坦克总数tanks = sum([i for i in players[0].trophies.values()]) - players[0].trophies["bonus"]screen.blit(self.font.render(str(tanks).rjust(2), False, white), [170, 335])if self.nr_of_players == 2:tanks = sum([i for i in players[1].trophies.values()]) - players[1].trophies["bonus"]screen.blit(self.font.render(str(tanks).rjust(2), False, white), [277, 335])pygame.display.flip()# 什么都不做两秒钟self.clock.tick(1)self.clock.tick(1)if self.game_over:self.gameOverScreen()#self.nextLevel()     无敌模式else:self.nextLevel()# 画游戏界面的图def draw(self):global screen, castle, players, enemies, bullets, bonusesscreen.fill([0, 0, 0])self.level.draw([self.level.TILE_EMPTY, self.level.TILE_BRICK, self.level.TILE_STEEL, self.level.TILE_FROZE,self.level.TILE_WATER])castle.draw()for enemy in enemies:enemy.draw()for label in labels:label.draw()for player in players:player.draw()for bullet in bullets:bullet.draw()for bonus in bonuses:bonus.draw()self.level.draw([self.level.TILE_GRASS])if self.game_over:if self.game_over_y > 188:self.game_over_y -= 4screen.blit(self.im_game_over, [176, self.game_over_y])  # 176=(416-64)/2self.drawSidebar()pygame.display.flip()# 画右边的标签栏def drawSidebar(self):global screen, players, enemiesx = 416y = 0screen.fill([100, 100, 100], pygame.Rect([416, 0], [64, 416]))xpos = x + 16ypos = y + 16# 敌方坦克数量显示for n in range(len(self.level.enemies_left) + len(enemies)):screen.blit(self.enemy_life_image, [xpos, ypos])if n % 2 == 1:xpos = x + 16ypos += 17else:xpos += 17# 玩家生命数if pygame.font.get_init():text_color = pygame.Color('black')for n in range(len(players)):if n == 0:screen.blit(self.font.render(str(n + 1) + "P", False, text_color), [x + 16, y + 200])screen.blit(self.font.render(str(players[n].lives), False, text_color), [x + 31, y + 215])screen.blit(self.player_life_image, [x + 17, y + 215])else:screen.blit(self.font.render(str(n + 1) + "P", False, text_color), [x + 16, y + 240])screen.blit(self.font.render(str(players[n].lives), False, text_color), [x + 31, y + 255])screen.blit(self.player_life_image, [x + 17, y + 255])screen.blit(self.flag_image, [x + 17, y + 280])screen.blit(self.font.render(str(self.stage), False, text_color), [x + 17, y + 312])# 画模式选择界面def drawIntroScreen(self, put_on_surface=True):""" 游戏主界面菜单@param boolean put_on_surface If True, flip display after drawing  put_on_surface如果为真,在绘制后翻转显示@return None"""global screenglobal godgod = Falsescreen.fill([0, 0, 0])if pygame.font.get_init():# hiscore是最高分hiscore = self.loadHiscore()screen.blit(self.font.render("HI- " + str(hiscore), True, pygame.Color('white')), [170, 35])screen.blit(self.font.render("1 PLAYER", True, pygame.Color('white')), [165, 250])screen.blit(self.font.render("2 PLAYERS", True, pygame.Color('white')), [165, 275])screen.blit(self.font.render("GOD MODE", True, pygame.Color('white')), [165, 300])screen.blit(self.font.render("(c) 1980 1985 NAMCO LTD.", True, pygame.Color('white')), [50, 350])screen.blit(self.font.render("ALL RIGHTS RESERVED", True, pygame.Color('white')), [85, 380])if self.nr_of_players == 1:screen.blit(self.player_image, [125, 245])elif self.nr_of_players == 2:screen.blit(self.player_image, [125, 270])elif self.nr_of_players == 3:screen.blit(self.player_image, [125, 300])god = Trueself.writeInBricks("battle", [65, 80])self.writeInBricks("city", [129, 160])if put_on_surface:pygame.display.flip()# 按下Enter键,立即完成模式选择界面的动画def animateIntroScreen(self):""" 从下到上滑动介绍(菜单)屏幕如果按下Enter键,立即完成动画@return None"""global screenself.drawIntroScreen(False)screen_cp = screen.copy()screen.fill([0, 0, 0])y = 416while (y > 0):time_passed = self.clock.tick(50)for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:y = 0breakscreen.blit(screen_cp, [0, y])pygame.display.flip()y -= 5screen.blit(screen_cp, [0, 0])pygame.display.flip()# 将文本字符串分割成指定大小的块def chunks(self, l, n):""" 将文本字符串分割成指定大小的块@param string l Input string@param int n Size (number of characters) of each chunk@return list"""return [l[i:i + n] for i in range(0, len(l), n)]# 以“砖块字体”写入指定文本,组成单词“Battle City”和“Game Over”def writeInBricks(self, text, pos):""" 以“砖块字体”写入指定文本
只有这些字母可以组成单词“Battle City”和“Game Over”
小写和大写都是有效的输入,但是输出总是大写的
每个字母由7x7块砖块组成,砖块被转换成49个字符的字符串
然后将其转换为十六进制以节省一些字节@return None"""global screen, spritesbricks = sprites.subsurface(56 * 2, 64 * 2, 8 * 2, 8 * 2)brick1 = bricks.subsurface((0, 0, 8, 8))brick2 = bricks.subsurface((8, 0, 8, 8))brick3 = bricks.subsurface((8, 8, 8, 8))brick4 = bricks.subsurface((0, 8, 8, 8))#  字母表alphabetalphabet = {"a": "0071b63c7ff1e3", "b": "01fb1e3fd8f1fe", "c": "00799e0c18199e", "e": "01fb060f98307e","g": "007d860cf8d99f", "i": "01f8c183060c7e", "l": "0183060c18307e", "m": "018fbffffaf1e3","o": "00fb1e3c78f1be", "r": "01fb1e3cff3767", "t": "01f8c183060c18", "v": "018f1e3eef8e08","y": "019b3667860c18"}abs_x, abs_y = posfor letter in text.lower():binstr = ""for h in self.chunks(alphabet[letter], 2):binstr += str(bin(int(h, 16)))[2:].rjust(8, "0")binstr = binstr[7:]x, y = 0, 0letter_w = 0surf_letter = pygame.Surface((56, 56))for j, row in enumerate(self.chunks(binstr, 7)):for i, bit in enumerate(row):if bit == "1":if i % 2 == 0 and j % 2 == 0:surf_letter.blit(brick1, [x, y])elif i % 2 == 1 and j % 2 == 0:surf_letter.blit(brick2, [x, y])elif i % 2 == 1 and j % 2 == 1:surf_letter.blit(brick3, [x, y])elif i % 2 == 0 and j % 2 == 1:surf_letter.blit(brick4, [x, y])if x > letter_w:letter_w = xx += 8x = 0y += 8screen.blit(surf_letter, [abs_x, abs_y])abs_x += letter_w + 16# 道具冻结敌人def toggleEnemyFreeze(self, freeze=True):""" 冻结/解冻所有敌人 """global enemiesfor enemy in enemies:enemy.paused = freezeself.timefreeze = freeze# 卡过图的时候冻结敌人和玩家def FreezeAll(self, freeze=True):"""冻结所有坦克,相对暂停"""global enemies,playersfor e in enemies:e.paused = freezefor p in players:p.paused = freezeself.timefreeze = freeze# 加载最高分,查看本地是否有.hiscore文件def loadHiscore(self):""" 加载最高分,查看本地是否有.hiscore文件如果某种原因不能加载最高分,返回20000返回值为int型"""filename = ".hiscore"if (not os.path.isfile(filename)):return 20000f = open(filename, "r")hiscore = int(f.read())if hiscore > 19999 and hiscore < 1000000:  # 最高分在19999<hiscore<1000000时返回最高分return hiscoreelse:  # 其他情况最高分20000print "cheater =["return 20000# 把最高分写入文件里def saveHiscore(self, hiscore):""" 保存最高分@返回 布尔型"""try:f = open(".hiscore", "w")except:print "产生错误,不能写入最高分"return Falsef.write(str(hiscore))f.close()return True# 完成当前关卡,保存当前成绩,晋级下一关def finishLevel(self):""" Finish current level 完成当前关卡Show earned scores and advance to the next stage 保存当前成绩,晋级下一关"""global play_sounds, sounds# ,bullets ,playersif play_sounds:try:sounds["bg"].stop()except:print "无法播放界面bgm"self.active = Falsegtimer.add(3000, lambda: self.showScores(), 1)print "Stage " + str(self.stage) + " completed"# 开始下一关的内容里:包括不同坦克类型的数量,def nextLevel(self):""" 开始下一关 """global castle, players, bullets, bonuses, play_sounds, sounds, Fullscreen, fire, sound1del bullets[:]del enemies[:]del bonuses[:]  # 清除奖励castle.rebuild()del gtimer.timers[:]# 加载下一关self.stage += 1self.level = Level(self.stage)self.timefreeze = False# 根据等级设置不同类型(基础,快速,力量,护甲)的敌人坦克数量levels_enemies = ((5, 5, 5, 5), (14, 4, 0, 2), (14, 4, 0, 2), (2, 5, 10, 3), (8, 5, 5, 2), (9, 2, 7, 2), (7, 4, 6, 3),(7, 4, 7, 2), (6, 4, 7, 3), (12, 2, 4, 2), (5, 5, 4, 6), (0, 6, 8, 6), (0, 8, 8, 4), (0, 4, 10, 6),(0, 2, 10, 8), (16, 2, 0, 2), (8, 2, 8, 2), (2, 8, 6, 4), (4, 4, 4, 8), (2, 8, 2, 8), (6, 2, 8, 4),(6, 8, 2, 4), (0, 10, 4, 6), (10, 4, 4, 2), (0, 8, 2, 10), (4, 6, 4, 6), (2, 8, 2, 8), (15, 2, 2, 1),(0, 4, 10, 6), (4, 8, 4, 4), (3, 8, 3, 6), (6, 4, 2, 8), (4, 4, 4, 8), (0, 10, 4, 6), (0, 6, 4, 10))if self.stage <= 35:enemies_l = levels_enemies[self.stage - 1]else:enemies_l = levels_enemies[34]self.level.enemies_left = [0] * enemies_l[0] + [1] * enemies_l[1] + [2] * enemies_l[2] + [3] * enemies_l[3]random.shuffle(self.level.enemies_left)  # 到达36级开始增加额外难度try:#if play_sounds:sounds["start"].play()gtimer.add(30, lambda: sounds["bg"].play(-1), 1)except:print "无法播放界面bgm  "# 载入重生的玩家,这里有个Bug是玩家会被npc坦克卡住self.reloadPlayers()gtimer.add(3000, lambda: self.spawnEnemy())# if True, start "game over" animation 如果为真,启动“游戏结束”动画self.game_over = False# if False, game will end w/o "game over" bussiness如果错误,游戏将结束,没有“游戏结束”业务self.running = True# if False, players won't be able to do anything 如果为False,玩家将不能做任何事情self.active = Trueself.draw()while self.running:time_passed = self.clock.tick(50)#  事件的具体内容for event in pygame.event.get():  # 鼠标按键无反应if event.type == pygame.MOUSEBUTTONDOWN:passelif event.type == pygame.QUIT:print "菜单的q"quit()elif event.type == pygame.KEYDOWN and not self.game_over and self.active:if event.key == pygame.K_p :  # 菜单暂停Flag = Trueprint "菜单界面停"while Flag:for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_p:Flag = Falseelse:continueif event.key == pygame.K_q and self.nr_of_players == 3:print "无敌模式的q"god = Falseself.gameOver()if event.key == pygame.K_q and self.nr_of_players != 3:print "单人和双人模式的按q"self.gameOver()# quit()# toggle soundselif event.key == pygame.K_m:  # m键切换为静音或有声音try:play_sounds = not play_soundsif not play_sounds:pygame.mixer.stop()else:sounds["bg"].play(-1)except:print "无法切换音效"elif event.key == pygame.K_u:  # f键切换窗口为全屏或窗口Fullscreen = not Fullscreenif Fullscreen:print "游戏中进入全屏"screen = pygame.display.set_mode(size, pygame.FULLSCREEN)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(3000, lambda: self.FreezeAll(False), 1)else:print "游戏中进入窗口"screen = pygame.display.set_mode(size)self.FreezeAll(True)  # 冻结3秒,让程序卡过图gtimer.add(3000, lambda: self.FreezeAll(False), 1)# 获取后台的数值elif event.key == pygame.K_z:print "====npc坦克情况====="print "当前场上有" + str(len(enemies)) + "个npc坦克"for e1 in enemies:e1.find()print "====玩家坦克状态====="# if len(players) == 1:#     print "1、当前玩家的移动速度是"+ str(player.speed)#     for bullet in bullets:#         bullet.find()# elif len(players) == 2:for player in players:print "玩家坦克的移动速度是" + str(player.speed)for bullet in bullets:bullet.find()for player in players:if player.state == player.STATE_ALIVE:  # 玩家存活时,可以进行射击且射击时可上下左右行动try:index = player.controls.index(event.key)except:passelse:if index == 0:if player.fire() and play_sounds:try:sounds["fire"].play()except:print "无法播放开火bgm"elif index == 1:player.pressed[0] = Trueelif index == 2:player.pressed[1] = Trueelif index == 3:player.pressed[2] = Trueelif index == 4:player.pressed[3] = Trueelif event.type == pygame.KEYUP and not self.game_over and self.active:  # 玩家松开按键时,默认无法进行上下左右操作for player in players:if player.state == player.STATE_ALIVE:try:index = player.controls.index(event.key)except:passelse:if index == 1:player.pressed[0] = Falseelif index == 2:player.pressed[1] = Falseelif index == 3:player.pressed[2] = Falseelif index == 4:player.pressed[3] = Falsefor player in players:if player.state == player.STATE_ALIVE and not self.game_over and self.active:  #if player.pressed[0] == True:player.move(self.DIR_UP);elif player.pressed[1] == True:player.move(self.DIR_RIGHT);elif player.pressed[2] == True:player.move(self.DIR_DOWN);elif player.pressed[3] == True:player.move(self.DIR_LEFT);player.update(time_passed)for enemy in enemies:if enemy.state == enemy.STATE_DEAD and not self.game_over and self.active:enemies.remove(enemy)  # 敌人死亡时,从敌人队列中移除#print len(self.level.enemies_left),len(enemies)if len(self.level.enemies_left) == 0 and len(enemies) == 0:  #self.finishLevel()else:enemy.update(time_passed)Deadnums = 0  # 无法复活的玩家次数if not self.game_over and self.active:for player in players:if player.state == player.STATE_ALIVE:if player.bonus != None and player.side == player.SIDE_PLAYER:self.triggerBonus(bonus, player)player.bonus = Noneelif player.state == player.STATE_DEAD:self.superpowers = 0if player.lives !=0:player.lives -= 1if player.lives > 0:self.respawnPlayer(player)if player.lives == 0:Deadnums += 1if Deadnums ==2:self.gameOver()for bullet in bullets:if bullet.state == bullet.STATE_REMOVED:bullets.remove(bullet)else:bullet.update()for bonus in bonuses:if bonus.active == False:bonuses.remove(bonus)for label in labels:if not label.active:labels.remove(label)if not self.game_over:if not castle.active:self.gameOver()gtimer.update(time_passed)self.draw()if __name__ == "__main__":gtimer = Timer()god = Falsesprites = Nonescreen = Noneplayers = []enemies = []bullets = []bonuses = []labels = []Fullscreen = Falseplay_sounds = Truesounds = {}textList = []game = Game()castle = Castle()game.showMenu()

Python编写坦克大战(新增无敌模式)相关推荐

  1. Python编写坦克大战(新增无敌模式)-附赠源码

    新增功能: 1.q键直接退出游戏  ->  进行结算然后返回模式选择界面 2. 新增全屏按钮u ,并且切换的时候会造成3s的冻结效果 3.静音键m 4.暂停键p 5.无敌模式,进入下一关条件是只 ...

  2. python编写坦克大战过程

    目录 一.首先明白编写坦克大战有哪些需求 二.细节编写 1.完成游戏的主要逻辑 2.完成坦克 1)完成我方坦克 2)完成敌方坦克 3.完成子弹 1)我方坦克射击 2)敌方坦克 3)我方子弹和敌方坦克碰 ...

  3. python坦克大战_Life is short,you need Python——Python实现坦克大战(一)

    先展示一下效果 搓搓小手手,坦克大战即将开始--https://www.zhihu.com/video/1140743290784817152 一.游戏引擎的安装 安装方式有两种:1.pip安装 wi ...

  4. 微信5.0 Android版飞机大战破解无敌模式手记

    微信5.0 Android版飞机大战破解无敌模式手记 转载: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html 微信5.0 ...

  5. Python实现坦克大战源码

    Python实现坦克大战小游戏源码,可实现单人及双人模式. import sysimport pygameimport sceneimport bulletimport foodimport tank ...

  6. python 游戏开发框架_Python开发 基于python实现坦克大战游戏

    这篇文章主要为大家详细介绍了基于python实现坦克大战游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了python实现坦克大战游戏的具体代码, ...

  7. c语言编写坦克大战设计报告,c语言编写坦克大战源代码

    <c语言编写坦克大战源代码>由会员分享,可在线阅读,更多相关<c语言编写坦克大战源代码(10页珍藏版)>请在人人文库网上搜索. 1.include tank.h#include ...

  8. Python pygame 坦克大战

    Python pygame 坦克大战 import pygame, time, random from pygame.sprite import SpriteSCREEN_WIDTH = 750 SC ...

  9. python版坦克大战

    Python版坦克大战 Python一千行代码搞定坦克大战游戏. 在开发坦克大战游戏项目中,我们使用的是pygame模块来完成的,所以得先装好pygame模块.本游戏一共封装了11个类和两个模块(py ...

最新文章

  1. torch标记维度最大
  2. Spring MVC入门示例教程--静态页面跳转
  3. boost::multiprecision模块测试 cpp_dec_float_50 是否符合我们的 概念要求
  4. 唐骏《我的成功也可以复制》1,盖婚房
  5. 不属于python标准库的是_《Python Cookbook(第2版)中文版》——1.10 过滤字符串中不属于指定集合的字符-阿里云开发者社区...
  6. Alter index coalesce VS shrink space
  7. Day_05 显示字符串
  8. AJAX,PHP,前端简单交互制作输入框效果
  9. 平面设计(板式设计与构图篇)
  10. 【POJ】1321-棋盘问题 n皇后、dfs
  11. 【学习笔记】移动无线信道理论
  12. QT应用之透明背景_嵌入式freambuffer_QWS背景淡绿色问题
  13. 30天自制操作系统——第四天使用C语言制作操作系统进度条
  14. 使用smtp协议发送邮件
  15. 一款可以帮助你处理文字、编写内容等办公软件-Word 2013 提供下载
  16. 四核处理器_戴尔这款笔记本彪悍,配置四核处理器,双内存插槽,不足4000元...
  17. react修改webpack配置,添加别名
  18. Python实现布林带策略
  19. npcap loopback adapter是什么意思_阜阳为什么叫阜阳,阜阳古时候叫什么,阜阳历史的由来...
  20. 基于matlab的股票投资,基于matlab的股票估价模型系统.doc

热门文章

  1. bugku-简单加密 writeup
  2. UE4 常用函数使用方法
  3. vs2013 clr20r3怎么解决
  4. 【金猿案例展】某国家级研究所——组学大数据分析平台建设
  5. Apache启动命令
  6. 电台转型与计算机相关的问题,数字化电台自动化播出系统中时间一致性问题研究...
  7. 紫薇盘反推出生年月时
  8. N76E003,C51开发不编译
  9. iOS开发的跳槽之路的心路历程分享(iOS进阶路线路)
  10. AndroidStudio-图片的上传以及存进mysql数据库里