1.怪物大战1.0基本上使用了坦克大战10.0版本的代码

学习元气骑士

游戏中的图片都应该是俯视图,可以画一些虫子,🐞,蜻蜓,车辆,箭头,刷子,✉作为怪物!

2.这个1.0版本暂时分了三个文件,以后还会分更多文件
目前三个文件:Manager类,Sound类,和剩余代码

之后可以再分几个文件:怪物的类,子弹的类,方块的类
若代码超过2000行,则可以分的更加细致一点

3.目前关于回旋镖的代码很不成熟,还有一些别的代码也需要改进
怪物类,子弹类,方块类可能都需要分开来写,可以继承抽象类,或者把一些相似的特性写在一个类里

要降低耦合度,增加可拓展性和清楚易读性,同时完善注释

`
class Tank(pygame.sprite.Sprite):
def init(self,screen,team=0):
pygame.sprite.Sprite.init(self)
self.screen = screen
self.all_bullet = pygame.sprite.Group()
if team == 0:
self.imgs = {
'w': pygame.image.load('E:/图片/player-w.png'),
's': pygame.image.load('E:/图片/player-s.png'),
'a': pygame.image.load('E:/图片/player-a.png'),
'd': pygame.image.load('E:/图片/player-d.png')
}
else:
self.imgs = {
'w': pygame.image.load('E:/图片/dir-w.png'),
's': pygame.image.load('E:/图片/dir-s.png'),
'a': pygame.image.load('E:/图片/dir-a.png'),
'd': pygame.image.load('E:/图片/dir-d.png')
}
self.team = team
self.direction = 'w'
self.img = self.imgs[self.direction]
self.rect = self.img.get_rect()
self.ran = [0, 4, 0]
if team == 0:
self.speed = 5
self.weapon = 1
self.rect.topleft = [random.randrange(30,SCREEN_X,80),
random.randrange(30,SCREEN_Y,20)]
else:
self.speed = random.randint(1, 5)
self.rect.topleft = [random.random()SCREEN_X, random.random()SCREEN_Y]

def __boundary(self):
    # 地图是上下左右贯通的
    # up
    if self.rect.top <= 0-20:
        self.rect.top = SCREEN_Y + 10
    # down
    if self.rect.top >= SCREEN_Y + 20:
        self.rect.top = 0 - 20
    # left
    if self.rect.left <= 0-20:
        self.rect.left = SCREEN_X + 10
    # right
    if self.rect.left >= SCREEN_X + 20:
        self.rect.left = 0 - 20

def control(self):
    self.__boundary()
    # 按键控制(键盘连续监听)
    key_pressed = pygame.key.get_pressed()
    if key_pressed[pygame.K_w]:
        self.direction = 'w'
        self.rect.top -= self.speed + self.ran[2]
        self.ran[2] = 0

    if key_pressed[pygame.K_s]:
        self.direction = 's'
        self.rect.top += self.speed + self.ran[2]
        self.ran[2] = 0

    if key_pressed[pygame.K_a]:
        self.direction = 'a'
        self.rect.left -= self.speed+ self.ran[2]
        self.ran[2] = 0

    if key_pressed[pygame.K_d]:
        self.direction = 'd'
        self.rect.left += self.speed + self.ran[2]
        self.ran[2] = 0

    if key_pressed[pygame.K_j]:
        #控制子弹发射的频率
        rrr = random.randint(1, 5)
        if self.weapon == 1:
            if rrr == 3:
                b = Bullet(self.direction, self.rect)
                self.all_bullet.add(b)
        elif self.weapon == 2:
            if rrr == 2:
                b = Biao(self.direction, self.rect)
                self.all_bullet.add(b)

    if key_pressed[pygame.K_h]:
        # 加速
        self.ran[2] += random.randint(1,10)
        if self.ran[2] >= 35:self.ran[2] = 35

    if key_pressed[pygame.K_1]:
        self.weapon = 1
    elif key_pressed[pygame.K_2]:
        self.weapon = 2
    elif key_pressed[pygame.K_3]:
        self.weapon = 3
    elif key_pressed[pygame.K_4]:
        self.weapon = 4

def ai(self):
    self.__boundary()
    self.ran[0] += 1
    if self.ran[0] % 30 == 0:
        bb = Bullet(self.direction, self.rect)
        self.all_bullet.add(bb)
    if self.ran[1] % 4 == 0:
        self.direction = 'w'
        self.rect.top -= self.speed
        if self.ran[0] % 20 == 0:
            self.ran[1] = random.randint(4,7)
    elif self.ran[1] % 4 == 1:
        self.direction = 's'
        self.rect.top += self.speed
        if self.ran[0] % 20 == 0:
            self.ran[1] = random.randint(4,7)
    elif self.ran[1] % 4 == 2:
        self.direction = 'a'
        self.rect.left -= self.speed
        if self.ran[0] % 20 == 0:
            self.ran[1] = random.randint(4,7)
    elif self.ran[1] % 4 == 3:
        self.direction = 'd'
        self.rect.left += self.speed
        if self.ran[0] % 20 == 0:
            self.ran[1] = random.randint(4,7)

def display(self):
    self.img = self.imgs[self.direction]
    self.screen.blit(self.img, self.rect)
    for i in self.all_bullet:
        i.move_straight_forward()
    self.all_bullet.draw(self.screen)

class Bullet(pygame.sprite.Sprite):
def init(self,dir,rect):
pygame.sprite.Sprite.init(self)
self.image = pygame.image.load('E:/图片/bullet.png')
self.direction = dir
self.r = rect
self.rect = self.image.get_rect()
if self.direction == 'w':
self.rect.left = rect.left + rect.width/2 - self.rect.width/2
self.rect.top = rect.top - self.rect.top
elif self.direction == 's':
self.rect.left = rect.left + rect.width / 2 - self.rect.width / 2
self.rect.top = rect.top + rect.height
elif self.direction == 'a':
self.rect.left = rect.left - rect.width / 2 - self.rect.width / 2
self.rect.top = rect.top + rect.width/2 - self.rect.width/2
elif self.direction == 'd':
self.rect.left = rect.left + rect.width
self.rect.top = rect.top + rect.width/2 - self.rect.width/2
self.speed = 18
self.distance = [random.randint(300,500),random.randint(300,400)]

def move_straight_forward(self):
    # 子弹离monster太远,则消失
    if abs(self.rect.top - self.r.top) > self.distance[0] or abs(self.rect.left - self.r.left) > self.distance[0]:
        self.kill()
    if self.direction == 'w':
        self.rect.top -= self.speed
    elif self.direction == 's':
        self.rect.top += self.speed
    elif self.direction == 'a':
        self.rect.left -= self.speed
    elif self.direction == 'd':
        self.rect.left += self.speed

class Biao(Bullet):
def init(self,dir,rect):
Bullet.init(self,dir,rect)
self.image = pygame.image.load('E:/图片/bullet1.png')

def move_straight_back(self):
    if self.direction == 'w':
        self.rect.top += self.speed
    elif self.direction == 's':
        self.rect.top -= self.speed
    elif self.direction == 'a':
        self.rect.left += self.speed
    elif self.direction == 'd':
        self.rect.left -= self.speed

def move_straight_forward(self):
    if abs(self.rect.top - self.r.top) > self.distance[1] or abs(self.rect.left - self.r.left) > self.distance[1]:
        self.move_straight_back()
    if self.direction == 'w':
        self.rect.top -= self.speed
    elif self.direction == 's':
        self.rect.top += self.speed
    elif self.direction == 'a':
        self.rect.left -= self.speed
    elif self.direction == 'd':
        self.rect.left += self.speed

class Rigid(pygame.sprite.Sprite):
def init(self):
# 刚体不能与任何东西发生重合,坦克/刚体可以给刚体一个速度
# 坦克/刚体与刚体发生碰撞,则它们之间的边缘会重合
# 刚体可以有多个速度,遵守矢量相加的规律
pygame.sprite.Sprite.init(self)
self.img = pygame.image.load('E:/图片/0.png')
self.rect = self.img.get_rect()
self.rect.topleft = [random.random() * SCREEN_X,random.random() * SCREEN_Y]
self.sp1 = [] #记录上下方向及速度,下方向为正速度
self.sp2 = [] #记录左右方向及速度,右方向为正速度
self.speed1 = 0
self.speed2 = 0
self.dir1 = ''
self.dir2 = ''

def pump(self,dir,speed,rect):
    #坦克碰刚体/刚体碰刚体
    if dir == 'w':
        self.rect.top = rect.top - self.rect.height
        self.sp1.append(-speed)
    elif dir == 's':
        self.rect.top = rect.top + rect.height
        self.sp1.append(speed)
    elif dir == 'a':
        self.rect.left = rect.left - self.rect.width
        self.sp2.append(-speed)
    elif dir == 'd':
        self.rect.left = rect.left + rect.width
        self.sp2.append(speed)
    self.speed1 = sum(self.sp1)
    self.speed2 = sum(self.sp2)
    if self.speed1 > 0:
        self.dir1 = 's'
    else:
        self.dir1 = 'w'
    if self.speed2 > 0:
        self.dir2 = 'd'
    else:
        self.dir2 = 'a'

class Brick(Rigid):
def init(self,attack=-1,type='wool'):
Rigid.init(self)
if type == 'wool':
#羊毛--wool:不能消失,所有坦克可以推开
self.attack = -1
self.img = pygame.image.load('E:/图片/6.png')
elif type == 'stone':
#石头--stone:可以打掉,所有坦克可以推开
self.attack = attack
if self.attack <= 1:self.attack = 1
self.img = pygame.image.load('E:/图片/2.png')

def shoot(self):
    # 子弹碰brick
    if self.attack >= 1:
        self.attack -= 1
        if self.attack == 0:
            self.kill()

class Fixed(pygame.sprite.Sprite):
def init(self,attack=-1, type='hard_block'):
pygame.sprite.Sprite.init(self)
if type == 'hard_block':
# 基岩--hard_block:不能消失,所有坦克不能推开
self.attack = -1
self.img = pygame.image.load('E:/图片/0.png')
elif type == 'brick_block':
# 砖块--brick_block:可以打掉,所有坦克不能推开
self.attack = attack
if self.attack <= 1:self.attack = 1
self.img = pygame.image.load('E:/图片/1.png')
self.rect = self.img.get_rect()
self.rect.topleft = [random.random() * SCREEN_X, random.random() * SCREEN_Y]

def shoot(self):
    # 子弹碰fixed(固定方块)
    if self.attack >= 1:
        self.attack -= 1
        if self.attack == 0:
            self.kill()

class Thing(pygame.sprite.Sprite):
def init(self):
pygame.sprite.Sprite.init(self)
self.img = pygame.image.load('E:/图片/h.jpg')
self.rect = self.img.get_rect()
self.rect.topleft = [random.random() * SCREEN_X, random.random() * SCREEN_Y]

class Map:
def init(self,screen):
self.brick_block = pygame.sprite.Group()
self.hard_block = pygame.sprite.Group()
self.wool = pygame.sprite.Group()
self.stone = pygame.sprite.Group()
self.screen = screen

def clear(self):
    self.hard_block.empty()
    self.brick_block.empty()
    self.wool.empty()
    self.stone.empty()

def ww(self,a,style,mm):
    for i in range(a):
        if style == 0:#横着的方块
            mm[0].rect.topleft = [random.randint(0,SCREEN_X),random.randrange(int(SCREEN_Y/4)
                                                                              ,int(3*SCREEN_Y/4),10)]
            mm[i].rect.top = mm[i-1].rect.top
            mm[i].rect.left = mm[i-1].rect.left + 55
        elif style == 1:#竖着的方块
            mm[0].rect.topleft = [random.randrange(int(SCREEN_X/5),int(5*SCREEN_X/6),15)
                                                                ,random.randint(0,SCREEN_Y)]
            mm[i].rect.top = mm[i - 1].rect.top + 55
            mm[i].rect.left = mm[i - 1].rect.left
        elif style == 2:#斜着的方块
            mm[0].rect.topleft = [random.randrange(int(SCREEN_X/3),int(5*SCREEN_X/6),20),
                                  random.randrange(int(SCREEN_Y/5),int(2*SCREEN_Y/5),10)]
            mm[i].rect.top = mm[i - 1].rect.top + 55
            mm[i].rect.left = mm[i - 1].rect.left + 55

def map1(self, a, style=-1, attack=1, type='stone'):
    if type == 'wool' or type == 'stone':
        mm = [Brick(attack,type) for _ in range(a)]
        self.ww(a,style,mm)
        if type == 'wool':
            self.wool.add(mm)
        elif type == 'stone':
            self.stone.add(mm)
    else:
        nn = [Fixed(attack,type) for _ in range(a)]
        self.ww(a,style,nn)
        if type == 'hard_block':
            self.hard_block.add(nn)
        elif type == 'brick_block':
            self.brick_block.add(nn)

def display_all(self):
    for i in self.hard_block:
        self.screen.blit(i.img, i.rect)
    for j in self.brick_block:
        self.screen.blit(j.img, j.rect)
    for k in self.wool:
        self.screen.blit(k.img,k.rect)
    for l in self.stone:
        self.screen.blit(l.img,l.rect)

Thing是我新增加的一个类,一般是游戏的道具:比如捡起生命值,捡起经验 Thing和方块类有许多相似的地方,可以提取共性成为一个类
class Manager:
#计时器的id(id是什么数字不重要),好像id值不能重复
id = 0
id2 = 1
#计算游戏是第几局/回合
j = 1

def __init__(self):
    self.screen = pygame.display.set_mode((SCREEN_X,SCREEN_Y))
    self.players = pygame.sprite.Group()
    self.enemys = pygame.sprite.Group()
    self.maps = Map(self.screen)
    self.sound = Sound()
    self.ran = [random.random()*10]
    self.rann = ['hard_block','brick_block','wool','stone']
    # 己方坦克有几条命
    self.life = 6
    # 计算一局游戏的存活时间,单位为秒
    self.timer = 0
    # 计算一局游戏的打怪数
    self.kill = 0

def player(self):
    #生成1辆我方坦克
    p = Tank(self.screen)
    self.players.add(p)

def enemy(self,x=1):
    #生成x辆敌方坦克
    e = [Tank(self.screen, 1) for _ in range(x)]
    self.enemys.add(e)

def restart(self):
    Manager.j += 1
    Manager.timer,Manager.score = 0, 0
    self.sound.horry()
    #清除所有子弹
    for i in self.players:
        i.all_bullet.empty()
    for j in self.enemys:
        j.all_bullet.empty()
    self.players.empty()#清除我方坦克
    self.enemys.empty()#清除敌方坦克
    self.maps.clear()#清除砖块
    mmmm = Manager()
    mmmm.main()#不能用self.main()

def write(self, t, x, y):
    font = pygame.font.SysFont(['方正粗黑宋简体', 'microsoftsansserif'], 40)
    text = font.render(t, True, (255, 0, 0), None)
    r = text.get_rect()
    r.topleft = (x, y)
    self.screen.blit(text, r)

def main(self):
    pygame.init()
    self.sound.back()
    pygame.display.set_caption("坦克大战--开始界面")
    self.screen.fill((150, 250, 200))
    self.write("1p", 280, 50)
    self.write("2p", 280, 150)
    while 1:
        pygame.display.update()
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if e.type == pygame.MOUSEBUTTONUP:
                click = pygame.mouse.get_pos()  # 获取鼠标位置
                if 240 <= click[0] <= 320 and 20 <= click[1] <= 80:
                    self.start()
                    #mmm = Manager() mmm.start()

def minus_life(self,x=1):
    self.sound.boost()
    self.life -= x
    if self.life <= 0:
        self.restart()

def ppp(self):
    # 我方坦克与敌方坦克碰撞
    tanks_pump = pygame.sprite.groupcollide(self.players, self.enemys, False, True)
    if tanks_pump: self.minus_life(3)
    # 子弹打坦克
    for a in self.enemys:
        e_hit_i = pygame.sprite.groupcollide(self.players, a.all_bullet, False, True)
        if e_hit_i: self.minus_life(1)
    for b in self.players:
        i_hit_e = pygame.sprite.groupcollide(b.all_bullet, self.enemys, True, True)
        if i_hit_e:
            self.kill += 1
            self.sound.boost()
    # 我方子弹碰到敌方子弹
    for c in self.players:
        for d in self.enemys:
            bullet_pump = pygame.sprite.groupcollide(c.all_bullet, d.all_bullet, True, True)
            if bullet_pump: self.sound.hit()
    # 坦克撞墙
    i_hit_wall = pygame.sprite.groupcollide(self.maps.hard_block, self.players, False, False)
    i_hit_brick = pygame.sprite.groupcollide(self.maps.brick_block, self.players, True, False)
    e_hit_wall = pygame.sprite.groupcollide(self.maps.hard_block, self.enemys, False, True)
    e_hit_brick = pygame.sprite.groupcollide(self.maps.brick_block, self.enemys, True, True)
    if i_hit_wall: self.minus_life(4)
    if i_hit_brick: self.minus_life(2)
    if e_hit_wall or e_hit_brick: self.sound.boost()
    # 坦克推墙
    i_hit_wool = pygame.sprite.groupcollide(self.maps.wool, self.players, False, False)
    i_hit_stone = pygame.sprite.groupcollide(self.maps.stone, self.players, False, False)
    e_hit_wool = pygame.sprite.groupcollide(self.maps.wool, self.enemys, False, False)
    e_hit_stone = pygame.sprite.groupcollide(self.maps.stone, self.enemys, False, False)
    if i_hit_wool or i_hit_stone or e_hit_wool or e_hit_stone:
        for i in i_hit_wool.keys():
            for ii in list(i_hit_wool.values())[0]:
                i.pump(ii.direction, ii.speed, ii.rect)
        for j in i_hit_stone.keys():
            for jj in list(i_hit_stone.values())[0]:
                j.pump(jj.direction, jj.speed, jj.rect)
        for k in e_hit_wool.keys():
            for kk in list(e_hit_wool.values()):
                for kkk in kk:
                    k.pump(kkk.direction, kkk.speed, kkk.rect)
        for l in e_hit_stone.keys():
            for ll in list(e_hit_stone.values()):
                for lll in ll:
                    l.pump(lll.direction, lll.speed, lll.rect)
    # 墙推墙
    for i in list(self.maps.stone) + list(self.maps.wool):
        for j in list(self.maps.stone) + list(self.maps.wool):
            if i != j:
                p = pygame.sprite.collide_rect(i, j)
                if p: i.pump(j.dir2, j.speed2, j.rect)
    # 子弹撞墙
    for e in self.players:
        i_bullet_wall = pygame.sprite.groupcollide(self.maps.hard_block, e.all_bullet, False, True)
        i_bullet_wool = pygame.sprite.groupcollide(self.maps.wool, e.all_bullet, False, True)
        i_bullet_brick = pygame.sprite.groupcollide(self.maps.brick_block, e.all_bullet, False, True)
        i_bullet_stone = pygame.sprite.groupcollide(self.maps.stone, e.all_bullet, False, True)
        if i_bullet_wall or i_bullet_wool or i_bullet_stone or i_bullet_brick:
            self.sound.hit()
        for i in i_bullet_stone.keys():
            i.shoot()
        for j in i_bullet_brick.keys():
            j.shoot()
    for f in self.enemys:
        e_bullet_wall = pygame.sprite.groupcollide(self.maps.hard_block, f.all_bullet, False, True)
        e_bullet_wool = pygame.sprite.groupcollide(self.maps.wool, f.all_bullet, False, True)
        e_bullet_brick = pygame.sprite.groupcollide(self.maps.brick_block, f.all_bullet, False, True)
        e_bullet_stone = pygame.sprite.groupcollide(self.maps.stone, f.all_bullet, False, True)
        if e_bullet_wall or e_bullet_wool or e_bullet_brick or e_bullet_stone:
            self.sound.hit()
        for k in e_bullet_brick.keys():
            k.shoot()
        for l in e_bullet_stone.keys():
            l.shoot()
    # 检测墙体之间的碰撞(保证墙体不会重合,除了hard_block可以与自身重合)
    for i in self.maps.brick_block:
            for j in self.maps.brick_block:
                if i != j:
                    walls_pump = pygame.sprite.collide_rect(i, j)
                    if walls_pump: self.maps.brick_block.remove(i)
    pygame.sprite.groupcollide(self.maps.hard_block, self.maps.brick_block, False, True)
    pygame.sprite.groupcollide(self.maps.hard_block, self.maps.wool, False, True)
    pygame.sprite.groupcollide(self.maps.brick_block, self.maps.wool, True, True)
    pygame.sprite.groupcollide(self.maps.stone, self.maps.hard_block, True, False)
    pygame.sprite.groupcollide(self.maps.stone, self.maps.brick_block, True, True)

def start(self):
    self.sound.back()
    self.player()
    self.maps.map1(random.randint(2,10),random.randint(0,2),-1,'hard_block')
    pygame.time.set_timer(Manager.id,random.randrange(3500,8500,100))
    pygame.time.set_timer(Manager.id2, 1000)
    while 1:
        self.screen.fill(BACK)
        for i in self.players:
            i.control()
            i.display()
        for j in self.enemys:
            j.ai()
            j.display()
        self.maps.display_all()
        time.sleep(0.07)  # 防止monster跑得太快
        pygame.display.update()
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif e.type == Manager.id:
                self.enemy()
                self.maps.map1(2, -1, random.randint(1,9), self.rann[random.randint(0, 3)])
            elif e.type == Manager.id2:
                self.timer += 1
                pygame.display.set_caption \
                    ('这是第' + str(Manager.j) + '局,开局' + str(self.timer) + '秒,'
                     + str(self.kill) + '杀,生命值' + str(self.life))
        self.ppp()

`