Python飞机大战小游戏
#!/usr/bin/env python
# @Time : 2018/3/31 15:21
# @Author : KiritoLiu
# @Contact : [email protected]
# @Site :
# @File : 《飞机大战》游戏.py
# @Software: PyCharm
import pygame
from pygame.locals import *
import time
import random
import sys
import threading
bg_image = "./images/bg2.png"
hero_image = "./images/me.png"
enemy_images = ("./images/e0.png", "./images/e1.png", "./images/e2.png")
bullet_image = "./images/pd.png"
explosion_images = ("./images/exp0.png", "./images/exp1.png", "./images/exp2.png")
gameover_image = "./images/gameover.png"
quit_image = "./images/quit.png"
restart_image = "./images/restart.png"
############################################
class MoveObject:
'''
移动物体的父类
1.位置 2.速度 3.图像 4.子弹列表 5.位置刷新 6.存活状态
'''
def __init__(self, screen_temp, x, y):
self.x = x
self.y = y
self.screen = screen_temp
self.bullet_list = []
self.aliving = True
def itimage(self, image):
self.image = pygame.image.load(image)
def speed_x(self, speedx):
self.speedx = speedx
def speed_y(self, speedy):
self.speedy = speedy
def display(self):
if self.aliving:
self.screen.blit(self.image, (self.x, self.y))
def move_x(self):
if self.aliving:
self.x += self.speedx
def move_y(self):
if self.aliving:
self.y += self.speedy
def fire(self, bullet):
if self.aliving:
self.bullet_list.append(bullet)
def setaliving(self, aliving):
self.aliving = aliving
class Bullet(MoveObject):
'''
子弹,只能纵向移动,且敌我皆可发射子弹
'''
def __init__(self, screen_temp, x, y, speedy):
MoveObject.__init__(self, screen_temp, x, y)
self.speed_y(speedy)
self.itimage("./images/pd.png")
def move_y(self):
MoveObject.move_y(self)
if self.y < -10 or self.y > 570:
return True
class HeroPlane(MoveObject):
'''
玩家飞机
移动方向:前 后 左 右
子弹:设置开火
'''
def __init__(self, screen_temp):
MoveObject.__init__(self, screen_temp, 200, 400)
self.itimage(hero_image)
def display(self):
MoveObject.display(self)
for b in self.bullet_list:
b.display()
if b.move_y():
self.bullet_list.remove(b)
def moveleft(self):
self.speed_x(-8)
self.move_x()
if self.x <= 0:
self.x = 0
def moveright(self):
self.speed_x(8)
self.move_x()
if self.x >= 406:
self.x = 406
def moveup(self):
self.speed_y(-8)
self.move_y()
if self.y <= 0:
self.y =0
def movedown(self):
self.speed_y(8)
self.move_y()
if self.y >= 492:
self.y = 492
def fire(self):
MoveObject.fire(self, Bullet(self.screen, self.x+53, self.y-9, -10))
def restart(self):
self.x = 200
self.y = 400
self.setaliving(True)
self.bullet_list.clear()
class Enemy(MoveObject):
'''
敌机 三种 只能向下 间断性开火(发射子弹的时间间隔)
判断英雄子弹与敌机撞击
判断敌我飞机碰撞
'''
def __init__(self, screen_temp):
MoveObject.__init__(self, screen_temp, random.randint(0, 396), -75)
self.itimage(enemy_images[random.randint(0, 2)])
self.speed_y(random.randint(4, 6))
def display(self):
MoveObject.display(self)
for b in self.bullet_list:
b.display()
if b.move_y():
self.bullet_list.remove(b)
def move_y(self, hero):
try:
MoveObject.move_y(self)
except:
pass
#玩家飞机碰撞热区的判定
heroleft = hero.x + 10
heroright = hero.x + hero.image.get_width() - 10
herotop = hero.y + 10
herobottom = hero.y + hero.image.get_height() - 30
#敌机碰撞热区的判定
enemyleft = self.x + 5
enemyright = self.x + self.image.get_width() - 5
enemytop = self.y + 5
enemybottom = self.y + self.image.get_height() - 25
if enemytop > 570:
return 1
for bo in hero.bullet_list:
if bo.x > enemyleft and bo.x < enemyright and bo.y > self.y + 20 and bo.y < self.y + 60:
hero.bullet_list.remove(bo)
return 2
if hero.aliving:
for bo in self.bullet_list:
if bo.x > heroleft + 12 and bo.x < heroright - 12 and bo.y > herotop + 20 and bo.y < herobottom + 60:
self.bullet_list.remove(bo)
return 3
if (heroleft <= enemyleft <= heroright or heroleft <= enemyright <= heroright) and (herotop <= enemytop <= herobottom or herotop <= enemybottom <= herobottom):
return 4
def fire(self):
MoveObject.fire(self, Bullet(self.screen, self.x + self.image.get_width() / 2, self.y + self.image.get_height(), 10))
def setfire(self, hasbullet, interval):
self.hasbullet = hasbullet
self.interval = interval
def run(enemy):
'''
敌机各自开火的线程
'''
while True:
try:
enemy.fire()
time.sleep(enemy.interval)
except Exception:
print(Exception)
def explosion(MoveObject, screen):
'''
显示击中或撞击之后的爆炸效果
'''
centrex = MoveObject.x + MoveObject.image.get_width() / 2
centrey = MoveObject.y + MoveObject.image.get_height() / 2
for i in [0] * 50 + [1] * 50 + [2] * 50:
image = pygame.image.load(explosion_images[i])
screen.blit(image, (centrex, centrey))
pygame.display.update()
def key_control(hero_temp):
'''键盘控制方法'''
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
quit()
if not hero_temp.aliving:
# 玩家已经被击毁则不响应键盘按键
return False
pressed_keys = pygame.key.get_pressed()
if pressed_keys[K_LEFT] or pressed_keys[K_a]:
hero_temp.moveleft()
elif pressed_keys[K_RIGHT] or pressed_keys[K_d]:
hero_temp.moveright()
if pressed_keys[K_UP] or pressed_keys[K_w]:
hero_temp.moveup()
elif pressed_keys[K_DOWN] or pressed_keys[K_s]:
hero_temp.movedown()
if pressed_keys[K_SPACE]:
hero_temp.fire()
return True
class Button(object):
'''
按钮类,用来做结束游戏和重新开始按钮
'''
def __init__(self, image, position):
self.image = pygame.image.load(image).convert_alpha()
self.position = position
def isover(self):
point_x, point_y = pygame.mouse.get_pos()
x, y = self.position
w, h = self.image.get_size()
x -= w / 2
y -= h / 2
in_x = x < point_x < x + w
in_y = y < point_y < y + h
return in_x and in_y
def render(self, surface):
x, y = self.position
w, h = self.image.get_size()
x -= w / 2
y -= h / 2
surface.blit(self.image, (x, y))
#############################################
def main():
'''
游戏主程序
'''
pygame.init()
# 初始化pygame
pygame.mixer.init()
# 初始化misxer
screen = pygame.display.set_mode((512, 568), 0, 0)
# 创建游戏窗口
background = pygame.image.load(bg_image)
game_over = False
font = pygame.font.SysFont('arial', 40)
gameover = Button(gameover_image, (250, 200))
quitbutton = Button(quit_image, (180, 300))
restartbutton = Button(restart_image, (300, 300))
enemy_list = []
myscore = 0
hero = HeroPlane(screen)
m = -968
while True:
screen.blit(background, (0, m))
m += 2
if m >= -200:
m = -968
# 背景循环滚动
if game_over:
# 显示game over,quit,restart
gameover.render(screen)
quitbutton.render(screen)
restartbutton.render(screen)
pygame.mouse.set_visible(True)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
quit()
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
if quitbutton.isover():
pygame.quit()
quit()
elif restartbutton.isover():
game_over = False
myscore = 0
hero.restart()
else:
hero.display()
if key_control(hero):
pass
if len(enemy_list) < 15:
r = random.randint(1, min(100, 25 * (len(enemy_list) + 1)))
if r == 12:
newenemy = Enemy(screen)
newenemy.setfire(random.choice([0, 1]), random.choice([0.5, 1, 2]))
enemy_list.append(newenemy)
if newenemy.hasbullet:
t = threading.Thread(target=run, args=(newenemy,))
t.start()
for e in enemy_list:
e.display()
result = e.move_y(hero)
if result == 1:
enemy_list.remove(e)
elif result == 2:
explosion(e, screen)
enemy_list.remove(e)
myscore += 100
elif result == 3:
hero.setaliving(False)
hero.display()
game_over = True
explosion(hero, screen)
elif result == 4:
explosion(e, screen)
enemy_list.remove(e)
myscore += 50
hero.setaliving(False)
hero.display()
game_over = True
explosion(hero, screen)
score = font.render(str(myscore), 1, (237, 140, 21))
screen.blit(score, (400, 20))
pygame.display.update()
time.sleep(0.03)
#判断当前否是主程序,并调用主程序
if __name__ == '__main__':
main()