#!/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):
""" 添加类型属性 """
# 道具
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分。
定时器:定时器暂时冻结时间,允许你无害地接近每一辆坦克并摧毁它们,直到冻结时间消失。
"""
def update(self):
global castle, players, enemies, bullets # 城堡,玩家,敌人,子弹
if self.state == self.STATE_EXPLODING:
if not self.explosion.active:
self.destroy()
del self.explosion
if 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()
return
elif 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()
return
elif 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()
return
elif 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_rects
collisions = 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 = True
if 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()
return
# tile width/height in px平铺宽度/高度 16个像素(px)
TILE_SIZE = 16
def __init__(self, level_nr=None):
""" There are total 35 different levels. If level_nr is larger than 35, loop over
to 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 最大数量的敌人同时在地图上是4
self.max_active_enemies = 4
# 关卡等级
level_nr = 1 if level_nr == None else level_nr % 35
if level_nr == 0:
level_nr = 35
self.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, sounds
for 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 True
elif tile.type == self.TILE_STEEL:
if play_sounds and sound:
try:
sounds["steel"].play()
except:
print "无法播放子弹击中墙砖时bgm"
if power == 2: # 能摧毁钢铁的子弹为2
self.mapr.remove(tile)
self.updateObstacleRects()
return True
else:
return False
def toggleWaves(self):
""" Toggle water image 切换图片"""
if self.tile_water == self.tile_water1:
self.tile_water = self.tile_water2
else:
self.tile_water = self.tile_water1
# 坦克发射子弹
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, labels
if self.state != self.STATE_ALIVE:
gtimer.destroy(self.timer_uuid_fire)
return False
if self.paused:
return False
if not forced:
active_bullets = 0
for bullet in bullets:
if bullet.owner_class == self and bullet.state == bullet.STATE_ACTIVE:
active_bullets += 1
if active_bullets >= self.max_active_bullets:
return False
# 坦克根据方向键旋转
def rotate(self, direction, fix_position=True):
""" Rotate tank
rotate, update image and correct position 旋转槽旋转,更新图像和正确的位置
"""
self.direction = direction
if direction == self.DIR_UP:
self.image = self.image_up
elif direction == self.DIR_RIGHT:
self.image = self.image_right
elif direction == self.DIR_DOWN:
self.image = self.image_down
elif direction == self.DIR_LEFT:
self.image = self.image_left
if (abs(self.rect.left - new_x) < 5):
self.rect.left = new_x
if (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_DEAD
del self.explosion
# 1 in 5 chance this will be bonus carrier, but only if no other tank is 五分之一的机会,这将是奖励载体,但只有当没有其他坦克
# 地图当前只能出现一个奖励载体坦克(修改这里可以刷出更多的道具坦克)
if random.randint(1, 5) == 1:
self.bonus = True
for enemy in enemies:
if enemy.bonus:
self.bonus = False
break
# 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.topleft
def 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 如果指定了方向,继续尝试,否则随机选择
"""
if direction == None:
if self.direction in [self.DIR_UP, self.DIR_RIGHT]:
opposite_direction = self.direction + 2
else:
opposite_direction = self.direction - 2
directions = all_directions
random.shuffle(directions)
directions.remove(opposite_direction)
directions.append(opposite_direction)
else:
if direction in [self.DIR_UP, self.DIR_RIGHT]:
opposite_direction = direction + 2
else:
opposite_direction = direction - 2
if direction in [self.DIR_UP, self.DIR_RIGHT]:
opposite_direction = direction + 2
else:
opposite_direction = direction - 2
directions = all_directions
random.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 首先,使用一般单位(步骤)而不是px
x = int(round(self.rect.left / 16))
y = int(round(self.rect.top / 16))
new_direction = None
for 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 = direction
break
elif 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 = direction
break
elif 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 = direction
break
elif 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 = direction
break
# if we can go anywhere else, turn around 如果我们能去别的地方,就掉头吧
if new_direction == None:
new_direction = opposite_direction
print "nav izejas. griezhamies"
# fix tanks position 修复坦克的位置
if fix_direction and new_direction == self.direction:
fix_direction = False