parent
d6bd02c18f
commit
e6eed22b17
@ -0,0 +1,318 @@
|
|||||||
|
import pygame, time, random
|
||||||
|
from pygame.sprite import Sprite
|
||||||
|
|
||||||
|
SCREEN_WIDTH = 750
|
||||||
|
SCREEN_HEIGHT = 500
|
||||||
|
BG_COLOR = pygame.Color(0, 0, 0)
|
||||||
|
TEXT_COLOR = pygame.Color(255, 0, 0)
|
||||||
|
|
||||||
|
class BaseItem(Sprite):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MainGame():
|
||||||
|
window = None
|
||||||
|
myTank = None
|
||||||
|
enemyCount = 5
|
||||||
|
enemyList = []
|
||||||
|
myBulletList = [] # 我方子弹列表
|
||||||
|
enemyBulletList = [] # 敌方子弹列表
|
||||||
|
explodeList = [] # 爆炸效果列表
|
||||||
|
wallList = [] # 墙壁列表
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def createEnemyTank(self): # 创建敌方坦克
|
||||||
|
top = 100
|
||||||
|
for i in range(MainGame.enemyCount):
|
||||||
|
left = random.randint(0, 600)
|
||||||
|
speed = random.randint(1, 4)
|
||||||
|
enemyTank = EnemyTank(left, top, speed)
|
||||||
|
MainGame.enemyList.append(enemyTank)
|
||||||
|
|
||||||
|
def displayEnemyTank(self): # 显示敌方坦克
|
||||||
|
for enemyTank in MainGame.enemyList:
|
||||||
|
if enemyTank.live:
|
||||||
|
enemyTank.displayTank()
|
||||||
|
enemyTank.randMove()
|
||||||
|
enemyTank.tank_hit_wall() # 检测与墙壁碰撞
|
||||||
|
if MainGame.myTank and MainGame.myTank.live:
|
||||||
|
enemyTank.enemyTank_hit_myTank() # 检测与我方坦克碰撞
|
||||||
|
enemyBullet = enemyTank.shot()
|
||||||
|
if enemyBullet:
|
||||||
|
MainGame.enemyBulletList.append(enemyBullet)
|
||||||
|
else:
|
||||||
|
MainGame.enemyList.remove(enemyTank)
|
||||||
|
|
||||||
|
def displayMyBullet(self): # 显示我方子弹
|
||||||
|
for myBullet in MainGame.myBulletList:
|
||||||
|
if myBullet.live:
|
||||||
|
myBullet.displayBullet()
|
||||||
|
myBullet.move()
|
||||||
|
myBullet.myBullet_hit_enemyTank() # 碰撞敌方坦克
|
||||||
|
myBullet.bullet_hit_wall() # 碰撞墙壁
|
||||||
|
else:
|
||||||
|
MainGame.myBulletList.remove(myBullet)
|
||||||
|
|
||||||
|
def displayEnemyBullet(self): # 显示敌方子弹
|
||||||
|
for enemyBullet in MainGame.enemyBulletList:
|
||||||
|
if enemyBullet.live:
|
||||||
|
enemyBullet.displayBullet()
|
||||||
|
enemyBullet.move()
|
||||||
|
enemyBullet.enemyBullet_hit_myTank() # 碰撞我方坦克
|
||||||
|
enemyBullet.bullet_hit_wall() # 碰撞墙壁
|
||||||
|
else:
|
||||||
|
MainGame.enemyBulletList.remove(enemyBullet)
|
||||||
|
|
||||||
|
def displayExplodeList(self): # 显示爆炸效果
|
||||||
|
for explode in MainGame.explodeList:
|
||||||
|
if explode.live:
|
||||||
|
explode.displayExplode()
|
||||||
|
else:
|
||||||
|
MainGame.explodeList.remove(explode)
|
||||||
|
|
||||||
|
def createMyTank(self): # 创建我方坦克
|
||||||
|
MainGame.myTank = MyTank(350, 300)
|
||||||
|
|
||||||
|
def createWall(self): # 创建墙壁
|
||||||
|
top = 220
|
||||||
|
for i in range(6):
|
||||||
|
wall = Wall(i * 130, top)
|
||||||
|
MainGame.wallList.append(wall)
|
||||||
|
|
||||||
|
def displayWallList(self): # 显示墙壁
|
||||||
|
for wall in MainGame.wallList:
|
||||||
|
if wall.live:
|
||||||
|
wall.displayWall()
|
||||||
|
else:
|
||||||
|
MainGame.wallList.remove(wall)
|
||||||
|
|
||||||
|
def startGame(self): # 启动游戏
|
||||||
|
pygame.display.init()
|
||||||
|
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||||
|
pygame.display.set_caption('坦克大战1.05') # 设置窗口标题
|
||||||
|
self.createMyTank()
|
||||||
|
self.createEnemyTank()
|
||||||
|
self.createWall()
|
||||||
|
while True:
|
||||||
|
time.sleep(0.02)
|
||||||
|
MainGame.window.fill(BG_COLOR)
|
||||||
|
textSurface = self.getTextSurface('敌方坦克剩余数量%d' % len(MainGame.enemyList))
|
||||||
|
MainGame.window.blit(textSurface, (10, 10))
|
||||||
|
self.getEvent()
|
||||||
|
|
||||||
|
if MainGame.myTank and MainGame.myTank.live:
|
||||||
|
MainGame.myTank.displayTank()
|
||||||
|
if not MainGame.myTank.stop:
|
||||||
|
MainGame.myTank.move()
|
||||||
|
MainGame.myTank.tank_hit_wall() # 检测与墙壁碰撞
|
||||||
|
MainGame.myTank.myTank_hit_enemyTank() # 检测与敌方坦克碰撞
|
||||||
|
else:
|
||||||
|
del MainGame.myTank
|
||||||
|
MainGame.myTank = None
|
||||||
|
|
||||||
|
self.displayEnemyTank()
|
||||||
|
self.displayMyBullet()
|
||||||
|
self.displayEnemyBullet()
|
||||||
|
self.displayExplodeList()
|
||||||
|
self.displayWallList()
|
||||||
|
pygame.display.update()
|
||||||
|
|
||||||
|
def endGame(self): # 结束游戏
|
||||||
|
print('谢谢使用,欢迎再次使用')
|
||||||
|
exit()
|
||||||
|
|
||||||
|
def getTextSurface(self, text): # 获取文字表面
|
||||||
|
pygame.font.init()
|
||||||
|
font = pygame.font.SysFont('kaiti', 18)
|
||||||
|
return font.render(text, True, TEXT_COLOR)
|
||||||
|
|
||||||
|
def getEvent(self): # 获取事件
|
||||||
|
eventList = pygame.event.get()
|
||||||
|
for event in eventList:
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
self.endGame()
|
||||||
|
if event.type == pygame.KEYDOWN:
|
||||||
|
if not MainGame.myTank:
|
||||||
|
if event.key == pygame.K_ESCAPE:
|
||||||
|
self.createMyTank()
|
||||||
|
if MainGame.myTank and MainGame.myTank.live:
|
||||||
|
if event.key == pygame.K_LEFT:
|
||||||
|
MainGame.myTank.direction = 'L'
|
||||||
|
MainGame.myTank.stop = False
|
||||||
|
elif event.key == pygame.K_RIGHT:
|
||||||
|
MainGame.myTank.direction = 'R'
|
||||||
|
MainGame.myTank.stop = False
|
||||||
|
elif event.key == pygame.K_UP:
|
||||||
|
MainGame.myTank.direction = 'U'
|
||||||
|
MainGame.myTank.stop = False
|
||||||
|
elif event.key == pygame.K_DOWN:
|
||||||
|
MainGame.myTank.direction = 'D'
|
||||||
|
MainGame.myTank.stop = False
|
||||||
|
elif event.key == pygame.K_SPACE and len(MainGame.myBulletList) < 3:
|
||||||
|
MainGame.myBulletList.append(Bullet(MainGame.myTank))
|
||||||
|
if event.type == pygame.KEYUP:
|
||||||
|
if event.key in (pygame.K_LEFT, pygame.K_UP, pygame.K_RIGHT, pygame.K_DOWN):
|
||||||
|
if MainGame.myTank and MainGame.myTank.live:
|
||||||
|
MainGame.myTank.stop = True
|
||||||
|
|
||||||
|
class Tank(BaseItem):
|
||||||
|
def __init__(self, left, top) -> None:
|
||||||
|
self.images = { # 坦克四个方向图片
|
||||||
|
'U': pygame.image.load('./img/p1tankU.gif'),
|
||||||
|
'D': pygame.image.load('./img/p1tankD.gif'),
|
||||||
|
'L': pygame.image.load('./img/p1tankL.gif'),
|
||||||
|
'R': pygame.image.load('./img/p1tankR.gif'),
|
||||||
|
}
|
||||||
|
self.direction = 'D'
|
||||||
|
self.image = self.images[self.direction]
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
self.rect.left, self.rect.top = left, top
|
||||||
|
self.speed = 5
|
||||||
|
self.stop = True
|
||||||
|
self.live = True
|
||||||
|
self.oldleft, self.oldtop = left, top
|
||||||
|
|
||||||
|
def displayTank(self): # 显示坦克
|
||||||
|
MainGame.window.blit(self.images[self.direction], self.rect)
|
||||||
|
|
||||||
|
def move(self): # 移动坦克
|
||||||
|
self.oldleft, self.oldtop = self.rect.left, self.rect.top
|
||||||
|
if self.direction == 'L' and self.rect.left > 0:
|
||||||
|
self.rect.left -= self.speed
|
||||||
|
elif self.direction == 'R' and self.rect.left + self.rect.height < SCREEN_WIDTH:
|
||||||
|
self.rect.left += self.speed
|
||||||
|
elif self.direction == 'U' and self.rect.top > 0:
|
||||||
|
self.rect.top -= self.speed
|
||||||
|
elif self.direction == 'D' and self.rect.top + self.rect.height < SCREEN_HEIGHT:
|
||||||
|
self.rect.top += self.speed
|
||||||
|
|
||||||
|
def shot(self): # 发射子弹
|
||||||
|
return Bullet(self)
|
||||||
|
|
||||||
|
def stay(self): # 保持原位
|
||||||
|
self.rect.left, self.rect.top = self.oldleft, self.oldtop
|
||||||
|
|
||||||
|
def tank_hit_wall(self): # 坦克碰撞墙壁检测
|
||||||
|
for wall in MainGame.wallList:
|
||||||
|
if pygame.sprite.collide_rect(self, wall):
|
||||||
|
self.stay()
|
||||||
|
|
||||||
|
class MyTank(Tank):
|
||||||
|
def __init__(self, left, top) -> None:
|
||||||
|
super().__init__(left, top)
|
||||||
|
|
||||||
|
def myTank_hit_enemyTank(self): # 我方坦克碰撞检测
|
||||||
|
for enemyTank in MainGame.enemyList:
|
||||||
|
if pygame.sprite.collide_rect(self, enemyTank):
|
||||||
|
self.stay()
|
||||||
|
|
||||||
|
class EnemyTank(Tank):
|
||||||
|
def __init__(self, left, top, speed) -> None:
|
||||||
|
super().__init__(left, top)
|
||||||
|
self.images = { # 敌方坦克图片
|
||||||
|
'U': pygame.image.load('./img/enemy1U.gif'),
|
||||||
|
'D': pygame.image.load('./img/enemy1D.gif'),
|
||||||
|
'L': pygame.image.load('./img/enemy1L.gif'),
|
||||||
|
'R': pygame.image.load('./img/enemy1R.gif'),
|
||||||
|
}
|
||||||
|
self.direction = self.randDirection()
|
||||||
|
self.image = self.images[self.direction]
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
self.rect.left, self.rect.top = left, top
|
||||||
|
self.speed, self.step = speed, 60
|
||||||
|
|
||||||
|
def randDirection(self): # 随机生成方向
|
||||||
|
return ['U', 'D', 'L', 'R'][random.randint(0, 3)]
|
||||||
|
|
||||||
|
def randMove(self): # 随机移动
|
||||||
|
if self.step <= 0:
|
||||||
|
self.direction, self.step = self.randDirection(), 60
|
||||||
|
else:
|
||||||
|
self.move()
|
||||||
|
self.step -= 1
|
||||||
|
|
||||||
|
def shot(self): # 敌方射击
|
||||||
|
return Bullet(self) if random.randint(0, 100) < 10 else None
|
||||||
|
|
||||||
|
def enemyTank_hit_myTank(self): # 碰撞我方坦克检测
|
||||||
|
if pygame.sprite.collide_rect(self, MainGame.myTank):
|
||||||
|
self.stay()
|
||||||
|
|
||||||
|
class Bullet(BaseItem):
|
||||||
|
def __init__(self, tank) -> None:
|
||||||
|
self.image = pygame.image.load('./img/enemymissile.gif')
|
||||||
|
self.direction = tank.direction
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
if self.direction == 'U': # 根据方向计算初始位置
|
||||||
|
self.rect.left = tank.rect.left + tank.rect.width/2 - self.rect.width/2
|
||||||
|
self.rect.top = tank.rect.top - self.rect.height
|
||||||
|
elif self.direction == 'D':
|
||||||
|
self.rect.left = tank.rect.left + tank.rect.width/2 - self.rect.width/2
|
||||||
|
self.rect.top = tank.rect.top + tank.rect.height
|
||||||
|
elif self.direction == 'L':
|
||||||
|
self.rect.left = tank.rect.left - self.rect.width/2
|
||||||
|
self.rect.top = tank.rect.top + tank.rect.width/2 - self.rect.width/2
|
||||||
|
elif self.direction == 'R':
|
||||||
|
self.rect.left = tank.rect.left + tank.rect.width
|
||||||
|
self.rect.top = tank.rect.top + tank.rect.width/2 - self.rect.width/2
|
||||||
|
self.speed, self.live = 6, True
|
||||||
|
|
||||||
|
def displayBullet(self): # 显示子弹
|
||||||
|
MainGame.window.blit(self.image, self.rect)
|
||||||
|
|
||||||
|
def move(self): # 子弹移动
|
||||||
|
if self.direction == 'U' and self.rect.top > 0:
|
||||||
|
self.rect.top -= self.speed
|
||||||
|
elif self.direction == 'D' and self.rect.top + self.rect.height < SCREEN_HEIGHT:
|
||||||
|
self.rect.top += self.speed
|
||||||
|
elif self.direction == 'L' and self.rect.left > 0:
|
||||||
|
self.rect.left -= self.speed
|
||||||
|
elif self.direction == 'R' and self.rect.left + self.rect.width < SCREEN_WIDTH:
|
||||||
|
self.rect.left += self.speed
|
||||||
|
else:
|
||||||
|
self.live = False # 超出边界时销毁
|
||||||
|
|
||||||
|
def myBullet_hit_enemyTank(self): # 我方子弹命中检测
|
||||||
|
for enemyTank in MainGame.enemyList:
|
||||||
|
if pygame.sprite.collide_rect(self, enemyTank):
|
||||||
|
enemyTank.live, self.live = False, False
|
||||||
|
MainGame.explodeList.append(Explode(enemyTank))
|
||||||
|
|
||||||
|
def enemyBullet_hit_myTank(self): # 敌方子弹命中检测
|
||||||
|
if MainGame.myTank and MainGame.myTank.live and pygame.sprite.collide_rect(self, MainGame.myTank):
|
||||||
|
self.live, MainGame.myTank.live = False, False
|
||||||
|
MainGame.explodeList.append(Explode(MainGame.myTank))
|
||||||
|
|
||||||
|
def bullet_hit_wall(self): # 子弹碰撞墙壁检测
|
||||||
|
for wall in MainGame.wallList:
|
||||||
|
if pygame.sprite.collide_rect(self, wall):
|
||||||
|
self.live, wall.hp = False, wall.hp-1
|
||||||
|
if wall.hp <= 0:
|
||||||
|
wall.live = False
|
||||||
|
|
||||||
|
class Wall(): # 墙壁类
|
||||||
|
def __init__(self, left, top) -> None:
|
||||||
|
self.image = pygame.image.load('./img/steels.gif')
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
self.rect.left, self.rect.top = left, top
|
||||||
|
self.live, self.hp = True, 3
|
||||||
|
|
||||||
|
def displayWall(self): # 显示墙壁
|
||||||
|
MainGame.window.blit(self.image, self.rect)
|
||||||
|
|
||||||
|
class Explode(): # 爆炸效果类
|
||||||
|
def __init__(self, tank) -> None:
|
||||||
|
self.rect = tank.rect
|
||||||
|
self.images = [pygame.image.load(f'./img/blast{i}.gif') for i in range(5)]
|
||||||
|
self.step, self.live = 0, True
|
||||||
|
|
||||||
|
def displayExplode(self): # 显示爆炸动画
|
||||||
|
if self.step < len(self.images):
|
||||||
|
MainGame.window.blit(self.images[self.step], self.rect)
|
||||||
|
self.step += 1
|
||||||
|
else:
|
||||||
|
self.live = False
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
MainGame().startGame()
|
Loading…
Reference in new issue