新增了刚体这种类型的方块
rigid继承精灵,brick(能动)继承rigid,fixed(不能动)继承精灵
刚体类也有一些bug,可能很难修复
之后可以有water类,有TNT类
`
import pygame
import sys
import time
import random
BACK = (200,200,250)
SCREEN_X = 1400
SCREEN_Y = 750
class Tank(pygame.sprite.Sprite):
my_all_bullet = pygame.sprite.Group()
enemy_all_bullet = pygame.sprite.Group()
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:/图片/heroW.png'),
's': pygame.image.load('E:/图片/heroS.png'),
'a': pygame.image.load('E:/图片/heroA.png'),
'd': pygame.image.load('E:/图片/heroD.png')
}
else:
self.imgs = {
'w': pygame.image.load('E:/图片/eW.png'),
's': pygame.image.load('E:/图片/eS.png'),
'a': pygame.image.load('E:/图片/eA.png'),
'd': pygame.image.load('E:/图片/eD.png')
}
self.team = team
self.direction = 'w'
self.img = self.imgs[self.direction]
# tank初始化位置
self.rect = self.img.get_rect()
self.ran = [0, 4, 0]
if team == 0:
self.speed = 5
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 rrr == 3:
b = Bullet(self.direction, self.rect)
self.all_bullet.add(b)
Tank.my_all_bullet.add(b)
if key_pressed[pygame.K_h]:
# 加速
self.ran[2] += random.randint(1,10)
def ai(self,player):
if abs(self.rect.top - player.rect.top) < 40:
bb1 = Bullet(self.direction, self.rect)
self.all_bullet.add(bb1)
Tank.enemy_all_bullet.add(bb1)
self.__boundary()
self.ran[0] += 1
if self.ran[0] % 30 == 0:
bb = Bullet(self.direction, self.rect)
self.all_bullet.add(bb)
Tank.enemy_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()
self.all_bullet.draw(self.screen)
@classmethod
# 清空子弹
def clear(cls):
cls.my_all_bullet.empty()
cls.enemy_all_bullet.empty()
`
`
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 = 10
self.distance = random.randint(300,500)
def move(self):
# 子弹距离坦克的位置太远则会消失
if (abs(self.rect.top - self.r.top) > self.distance
or abs(self.rect.left - self.r.left) > self.distance):
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 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 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)
`
Sound类 省略,因为比较简单
`
class Manager:
#计时器的id(id是什么数字不重要),好像id值不能重复
id = 0
id2 = 1
#计算一局游戏的得分,打掉1个坦克得1分
score = 0
#计算一局游戏的存活时间,单位为秒
timer = 0
#计算游戏是第几局/回合
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']
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()
Tank.clear()#清除子弹
self.players.empty()#清除我方坦克
self.enemys.empty()#清除敌方坦克
self.maps.clear()#清除砖块
mmmm = Manager()
mmmm.main()
def main(self):
pygame.init()
self.title = pygame.display.set_caption("坦克大战--开始界面")
self.start()
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 True:
self.screen.fill(BACK)
for i in self.players:
i.control()
i.display()
for j in self.enemys:
j.ai(self.players.sprites()[0])
j.display()
self.maps.display_all()
time.sleep(0.07)#防止坦克跑得太快
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:
Manager.timer += 1
self.title = pygame.display.set_caption \
('这是第'+ str(Manager.j)+'局,开局'+str(Manager.timer)+'秒,'+str(Manager.score)+'杀')
#我方坦克与敌方坦克的碰撞
tanks_pump = pygame.sprite.groupcollide(self.players, self.enemys, True, True)
# 敌方子弹打玩家坦克
e_hit_i = pygame.sprite.groupcollide(self.players, Tank.enemy_all_bullet,True, True)
# 我方坦克撞墙
i_hit_wall = pygame.sprite.groupcollide(self.maps.hard_block, self.players,False, True)
i_hit_brick = pygame.sprite.groupcollide(self.maps.brick_block, self.players,True, True)
if tanks_pump or e_hit_i or i_hit_wall or i_hit_brick:
self.sound.boost()
self.restart()
# 敌方坦克撞墙
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 e_hit_wall or e_hit_brick:self.sound.boost()
#玩家子弹打敌方坦克
i_hit_e = pygame.sprite.groupcollide(Tank.my_all_bullet, self.enemys,True, True)
if i_hit_e:
Manager.score += 1
self.sound.boost()
#我方子弹碰到敌方子弹
bullet_pump = pygame.sprite.groupcollide(Tank.my_all_bullet,Tank.enemy_all_bullet,True,True)
if bullet_pump:self.sound.hit()
#坦克推墙
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)
#子弹撞墙
i_bullet_wall = pygame.sprite.groupcollide(self.maps.hard_block,Tank.my_all_bullet,False, True)
i_bullet_wool = pygame.sprite.groupcollide(self.maps.wool,Tank.my_all_bullet,False,True)
i_bullet_brick = pygame.sprite.groupcollide(self.maps.brick_block, Tank.my_all_bullet, False, True)
i_bullet_stone = pygame.sprite.groupcollide(self.maps.stone, Tank.my_all_bullet, False, True)
e_bullet_wall = pygame.sprite.groupcollide(self.maps.hard_block, Tank.enemy_all_bullet, False, True)
e_bullet_wool = pygame.sprite.groupcollide(self.maps.wool, Tank.enemy_all_bullet, False, True)
e_bullet_brick = pygame.sprite.groupcollide(self.maps.brick_block, Tank.enemy_all_bullet, False, True)
e_bullet_stone = pygame.sprite.groupcollide(self.maps.stone, Tank.enemy_all_bullet, False, True)
if i_bullet_wall or i_bullet_wool or e_bullet_wall or e_bullet_wool:self.sound.hit()
if i_bullet_stone or i_bullet_brick or e_bullet_brick or e_bullet_stone:
self.sound.hit()
for i in i_bullet_stone.keys():
i.shoot()
for j in i_bullet_brick.keys():
j.shoot()
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)
`