本文作为开发过程记录用。
目前游戏画面:
下一个添加的功能:敌机可以进行射击。
弹幕类
from pygame.sprite import Sprite from pygame import transform import mathclass Barrage(Sprite):def __init__(self,raiden_settings,screen,ship,enemy,angle=0):self.barrage_type = enemy.barrage_typeself.screen = screenself.raiden_settings = raiden_settingsself.ship = shipself.image = pygame.image.load(raiden_settings. \barrage_image[barrage_type-1])self.rect = self.image.get_rect()self.rect.x = enemy.rect.xself.rect.y = enemy.rect.yself.x = float(self.rect.x)self.y = float(self.rect.y)self.angle = angleif self.barrage_type == 1:self.image = pygame.transform.rotate(self.image, raiden_settings.direction_angle)def update(self):if self.barrage_type == 1 or self.barrage_type == 2:self.x += self.raiden_settings.barrage_speed_factor * \math.sin(self.angle)self.y += self.raiden_settings.barrage_speed_factor * \math.cos(self.angle)if self.barrage_type == 3:tmp = ((self.x - self.ship.x) ** 2 + (self.y -self.ship.y) \** 2) ** 0.5self.x += self.raiden_settings.barrage_speed_factor * \(self.ship.x - self.x)/tmpself.y += self.raiden_settings.barrage_speed_factor * \(self.y - self.ship.y)/tmpself.rect.x = self.xself.rect.y = self.y
子弹类
import pygame from pygame.sprite import Sprite import math from pygame import transformclass Bullet(Sprite):def __init__(self,raiden_settings,screen,ship,angle):super().__init__()self.screen = screenself.image = pygame.image.load(raiden_settings.bullet_image)self.image = pygame.transform.rotate(self.image,angle)self.rect = self.image.get_rect()self.rect.centerx = ship.rect.centerxself.rect.top = ship.rect.topself.y = float(self.rect.y) self.x = float(self.rect.x)self.angle = angleself.speed_factor = raiden_settings.bullet_speed_factordef update(self):self.y -=self.speed_factor * math.cos(self.angle)self.x +=self.speed_factor * math.sin(self.angle)self.rect.y = self.yself.rect.x = self.xdef draw_bullet(self):pygame.draw.rect(self.screen,self.color,self.rect)
按钮类
import pygame.fontclass Button():def __init__(self,raiden_settings,screen,msg):self.screen = screenself.screen_rect = screen.get_rect()self.width = raiden_settings.button_widthself.height = raiden_settings.button_heightself.button_color = raiden_settings.button_colorself.text_color = raiden_settings.button_text_colorself.font = pygame.font.SysFont(None,raiden_settings.button_font_size)self.rect = pygame.Rect(0,0,self.width,self.height)self.rect.center = self.screen_rect.centerself.prep_msg(msg)def prep_msg(self,msg):self.msg_image = self.font.render(msg,True,self.text_color,self.button_color)self.msg_image_rect = self.msg_image.get_rect()self.msg_image_rect.center = self.rect.centerdef draw_button(self):self.screen.fill(self.button_color,self.rect)self.screen.blit(self.msg_image,self.msg_image_rect)
掉落物类
import pygame from pygame.sprite import Spriteclass DropItem(Sprite):def __init__(self,raiden_settings,screen,enemy,ship):super().__init__()self.screen = screenself.raiden_settings = raiden_settingsself.image = pygame.image.load( \raiden_settings.dropitem_image[ship.arms_level - 1]). \convert_alpha()self.rect = self.image.get_rect()self.rect.centerx = enemy.rect.centerxself.rect.top = enemy.rect.bottomself.y = self.rect.yself.speed_factor = raiden_settings.dropitem_speed_factorself.level = ship.arms_level + 1def update(self):self.y +=self.speed_factorself.rect.y = self.ydef draw_dropitem(self):self.screen.blit(self.image,self.rect)
敌机类
import pygame from pygame.sprite import Sprite from pygame import transform from random import randintclass Enemy(Sprite):def __init__(self,raiden_settings,screen):super().__init__()self.screen = screenself.raiden_settings = raiden_settingsself.enemy_type = randint(1,3)self.image = pygame.image.load(raiden_settings. \enemy_image[self.enemy_type - 1]).convert_alpha()self.image = transform.smoothscale(self.image,raiden_settings.enemy_image_rect)self.image = pygame.transform.rotate(self.image, raiden_settings.direction_angle)self.rect = self.image.get_rect()self.x = float(self.rect.x)self.y = float(self.rect.y)self.barrage_type = self.enemy_typeself.set_enemy_rect()def blitme(self):self.screen.blit(self.image,self.rect)def update(self):# ~ self.x += (self.raiden_settings.enemy_speed_factor *# ~ self.raiden_settings.fleet_direction)# ~ self.rect.x = self.xif self.enemy_type == 1:self.y += self.raiden_settings.enemy_speed_factor if self.enemy_type == 2:if self.x < 100 :self.x += self.raiden_settings.enemy_speed_factorelif self.x >self.screen.get_rect().right - 100:self.x -= self.raiden_settings.enemy_speed_factorif self.enemy_type == 3:if self.x <= self.screen.get_rect().right:self.x += self.raiden_settings.enemy_speed_factorelse:self.x -= self.raiden_settings.enemy_speed_factorself.y += self.raiden_settings.enemy_speed_factorself.rect.x = self.xself.rect.y = self.ydef check_edges(self):screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <= 0:return Truedef set_enemy_rect(self):if self.enemy_type == 1:self.x = randint(0,self.screen.get_rect().width)self.y = 0elif self.enemy_type == 2:self.y = 200if randint(1,2) == 1:self.x = 0else:self.x = self.screen.get_rect().rightelif self.enemy_type == 3:self.y = randint(0,300)if randint(1,2) == 1:self.x = 0else:self.x = self.screen.get_rect().rightself.rect.x = self.xself.rect.y = self.y
游戏内功能函数类
import sys import pygamefrom Bullet import Bullet from Enemy import Enemy from time import sleep from dropitem import DropItem from random import random from barrage import Barrage#检查输入 def check_events(raiden_settings,screen,stats,ship,enemys,bullets,play_button,sprites):for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()elif event.type == pygame.KEYDOWN:check_keydown_event(event,raiden_settings,screen,ship,bullets,sprites)elif event.type == pygame.KEYUP:check_keyup_event(event,ship)elif event.type == pygame.MOUSEBUTTONDOWN:mouse_x,mouse_y = pygame.mouse.get_pos()check_play_button(raiden_settings,stats,screen,play_button,mouse_x,mouse_y)elif event.type == pygame.USEREVENT:create_enemy(raiden_settings,screen,enemys,sprites)#更新屏幕 def update_screen(screen,stats,play_button,sprites):if not stats.game_active:play_button.draw_button()else:updates = sprites.draw(screen)pygame.display.update(updates)pygame.display.flip()#检查按下输入 def check_keydown_event(event,raiden_settings,screen,ship,bullets,sprites):if event.key == pygame.K_d:ship.moving_right = Trueelif event.key == pygame.K_a:ship.moving_left = Trueelif event.key == pygame.K_SPACE:fire_bullet(raiden_settings,screen,ship,bullets,sprites)elif event.key == pygame.K_w:ship.moving_up = Trueelif event.key == pygame.K_s:ship.moving_down = Trueelif event.key == pygame.K_q:sys.exit()#检查放开输入 def check_keyup_event(event,ship):if event.key == pygame.K_d:ship.moving_right = Falseelif event.key == pygame.K_a:ship.moving_left = Falseelif event.key == pygame.K_w:ship.moving_up = Falseelif event.key == pygame.K_s:ship.moving_down = False#更新子弹 def update_bullets(raiden_settings,screen,stats,ship,enemys,bullets,dropitems,scoreboard,sprites):for bullet in bullets.copy():if bullet.rect.bottom <=0 or bullet.rect.x <= 0 or \bullet.rect.x >= raiden_settings.screen_width:bullets.remove(bullet)collisions = pygame.sprite.groupcollide(bullets,enemys,True,True)if collisions:enemy_hit(raiden_settings,screen,stats,ship,enemys,dropitems,scoreboard,collisions,sprites)#敌人被击中 def enemy_hit(raiden_settings,screen,stats,ship,enemys,dropitems,scoreboard,collisions,sprites):for bullet,enemy_list in collisions.items():stats.score += raiden_settings.score_up_factorscoreboard.prep_score()scoreboard.show_score()if check_drop(raiden_settings):for enemy in enemy_list:new_dropitem = DropItem(raiden_settings,screen,enemy,ship)dropitems.add(new_dropitem)sprites.add(new_dropitem)#更新掉落物 def update_dropitems(raiden_settings,screen,stats,ship,dropitems,sprites):for dropitem in dropitems.copy():if dropitem.rect.bottom <= 0:sprites.remove(dropitem)dropitems.remove(dropitem)collision = pygame.sprite.spritecollideany(ship,dropitems)if collision:sprites.remove(collision)dropitems.remove(collision)if collision.level == ship.arms_level + 1:ship.update_arms()#开火 def fire_bullet(raiden_settings,screen,ship,bullets,sprites):bullet_list = []if ship.arms_level == raiden_settings.arms_1_level:bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.vertical_angle))elif ship.arms_level == raiden_settings.arms_2_level:bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.left_deflectical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.right_deflectical_angle))elif ship.arms_level == raiden_settings.arms_3_level:bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.vertical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.left_deflectical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.right_deflectical_angle))elif ship.arms_level == raiden_settings.arms_4_level:bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.vertical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.left_deflectical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.right_deflectical_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.left_horizontal_angle))bullet_list.append(Bullet(raiden_settings,screen,ship,raiden_settings.right_horizontal_angle))for bullet in bullet_list:bullets.add(bullet)sprites.add(bullet)#创建敌人 def create_enemy(raiden_settings,screen,enemys,sprites):enemy = Enemy(raiden_settings,screen)enemys.add(enemy)sprites.add(enemy)def update_enemys(raiden_settings,stats,lifeboard,screen,ship,enemys,bullets,sprites):if pygame.sprite.spritecollideany(ship,enemys):ship_hit(raiden_settings,stats,lifeboard,screen,ship,enemys,bullets,sprites)#玩家被击中 def ship_hit(raiden_settings,stats,lifeboard,screen,ship,enemys,bullets,sprites):if stats.ships_left > 0:stats.ships_left -= 1ship.reset_ship()lifeboard.dead(stats,sprites)reset_game(raiden_settings,screen,ship,enemys,bullets,sprites)sleep(1)else:stats.game_active = Falsepygame.mouse.set_visible(False)stats.ship_left = raiden_settings.ship_init_lifestats.score = 0stats.reset_stats()ship.reset_ship()reset_game(raiden_settings,screen,ship,enemys,bullets,sprites)pygame.mouse.set_visible(True)lifeboard.dead(stats,sprites)#重置游戏 def reset_game(raiden_settings,screen,ship,enemys,bullets,sprites):for enemy in enemys:sprites.remove(enemy)enemys.empty()for bullet in bullets:sprites.remove(bullet)bullets.empty()sprites.clear(screen,clear_callback)ship.center_ship()#检查玩家是否点击play按钮 def check_play_button(raiden_settings,stats,screen,play_button,mouse_x,mouse_y):if play_button.rect.collidepoint(mouse_x,mouse_y) and not \stats.game_active:stats.game_active = Truepygame.mouse.set_visible(False)screen.fill(raiden_settings.bg_color)#是否掉落物品 def check_drop(raiden_settings):if random() < raiden_settings.chance:return Trueelse:return False#检查掉落物是否到达屏幕底 def check_dropitem_bottom(raiden_settings,stats,screen,dropitems):screen_rect = screen.get_rect()for dropitem in dropitems.sprite():if dropitem.rect.bottom >= screen_rect.bottom:dropitems.remove(dropitem)#清除子图形 def clear_callback(surf, rect):bg = 255,255,255surf.fill(bg, rect)
生命值记录板类
from pygame.sprite import Sprite from pygame.sprite import Group from Ship import Ship from pygame import transformclass Lifeboard(Sprite):def __init__(self,raiden_settings,screen,stats,sprites):super().__init__()self.stats = statsself.screen = screenself.rect = screen.get_rect()self.raiden_settings = raiden_settingsself.ships = Group()self.ship_list = []self.prep_ships()for ship in self.ships:sprites.add(ship)ship.image = transform.smoothscale(ship.image,raiden_settings.lifeboard_image_rect)def prep_ships(self):for ship_number in range(self.stats.ships_left):ship = Ship(self.raiden_settings,self.screen)ship.center = self.raiden_settings.lifeboard_ship_center + \ship_number * self.raiden_settings. \lifeboard_ship_center_growthship.bottom = self.raiden_settings.lifeboard_ship_bottomself.ships.add(ship)self.ship_list.append(ship)def dead(self,stats,sprites):self.ships.remove(self.ship_list[-1])sprites.remove(self.ship_list[-1])del self.ship_list[-1]
游戏类(主程序)
import sys import pygamefrom Settings import Settings from Ship import Ship import game_functions as gf from pygame.sprite import Group from Enemy import Enemy from GameStats import GameStats from Button import Button from Scoreboard import Scoreboard from Lifeboard import Lifeboarddef run_game():pygame.init()raiden_settings = Settings()screen = pygame.display.set_mode((raiden_settings.screen_width,raiden_settings.screen_height))EVENT_CREATE_ENEMY = pygame.USEREVENT pygame.time.set_timer(EVENT_CREATE_ENEMY,300)pygame.display.set_caption("Raiden")play_button = Button(raiden_settings,screen,"Play!")ship = Ship(raiden_settings,screen)bullets = Group()enemys = Group()dropitems = Group()sprites = pygame.sprite.RenderUpdates()stats = GameStats(raiden_settings)scoreboard = Scoreboard(raiden_settings,screen,stats)lifeboard = Lifeboard(raiden_settings,screen,stats,sprites)screen.fill(raiden_settings.bg_color)sprites.add(ship)sprites.add(scoreboard)while True:gf.check_events(raiden_settings,screen,stats,ship,enemys,bullets,play_button,sprites)if stats.game_active:sprites.clear(screen,gf.clear_callback)sprites.update()gf.update_bullets(raiden_settings,screen,stats,ship,enemys,bullets,dropitems,scoreboard,sprites)gf.update_dropitems(raiden_settings,screen,stats,ship,dropitems,sprites)gf.update_enemys(raiden_settings,stats,lifeboard,screen,ship,enemys,bullets,sprites)gf.update_screen(screen,stats,play_button,sprites)run_game()
计分板类
import pygame.font from pygame.sprite import Sprite from pygame.sprite import Groupfrom Ship import Shipclass Scoreboard(Sprite):def __init__(self,raiden_settings,screen,stats):super().__init__()self.screen = screenself.screen_rect = screen.get_rect()self.raiden_settings = raiden_settingsself.stats = statsself.text_color = raiden_settings.scoreboard_text_colorself.font = pygame.font.SysFont(None,raiden_settings.scoreboard_font_size)self.prep_score()def prep_score(self):score_str = str(self.stats.score)self.image = self.font.render(score_str,True,self.text_color,self.raiden_settings.bg_color)self.rect = self.image.get_rect()self.rect.right = self.screen_rect.right self.rect.top = 0def show_score(self):self.screen.blit(self.image,self.rect)
常数类
import mathclass Settings():def __init__(self):#屏幕设置self.screen_width = 300self.screen_height = 600self.bg_color = (255,255,255)#飞行速度设置self.ship_speed_factor = 0.3self.enemy_speed_factor = 0.3self.fleet_drop_speed = 8self.enemy_speed_up_factor = 0.1self.bullet_speed_factor = 0.7self.barrage_speed_factor = 0.7#飞行方向设置self.fleet_direction = 1#生命值self.ship_init_life = 3#分数设置self.score_up_factor = 10#掉落物设置self.dropitem_speed_factor = 0.1#掉落指数设置self.chance = 0.5#武器等级设置self.init_arms_level = 1self.max_arms_level = 4self.arms_1_level = 1self.arms_2_level = 2self.arms_3_level = 3self.arms_4_level = 4#角度self.vertical_angle = 0self.right_deflectical_angle = math.pi/6self.left_deflectical_angle = -math.pi/6self.left_horizontal_angle = -math.pi/2self.right_horizontal_angle = math.pi/2self.direction_angle = 180self.angle_left_10 = -10self.angle_right_10 = 10#图片位置self.enemy_image = ['image/enemy1.png','image/enemy2.png','image/enemy3.png',]self.ship_image = 'image/9.png'self.bullet_image = 'image/bullet.png'self.dropitem_image = ['image/dropitem1.png','image/dropitem2.png','image/dropitem3.png','image/dropitem4.png',]self.barrage_image = ['image\barrage1.png','image\barrage2.png','image\barrage3.png',]#enemy图片大小self.enemy_image_rect = (30,30)#lifeboard图片大小self.lifeboard_image_rect = (30,30)#ship图片大小self.ship_image_rect = (50,50)#计分板字体颜色self.scoreboard_text_color = (30,30,30)#计分板字体大小self.scoreboard_font_size = 48#计分板位置self.lifeboard_ship_center = 25self.lifeboard_ship_bottom = 50self.lifeboard_ship_center_growth = 15#button设置self.button_text_color = (255,255,255)self.button_color = (0,255,0)self.button_width = 200self.button_height = 50self.button_font_size = 48
飞船类
import pygame from Settings import Settings from pygame.sprite import Sprite from pygame import transformclass Ship(Sprite):def __init__(self,raiden_settings,screen):super().__init__()self.screen = screenself.raiden_settings = raiden_settingsself.image = pygame.image.load(raiden_settings.ship_image). \convert_alpha()self.image = transform.smoothscale(self.image,raiden_settings.ship_image_rect)self.rect = self.image.get_rect()self.screen_rect = screen.get_rect()self.rect.centerx = self.screen_rect.centerxself.rect.bottom = self.screen_rect.bottomself.arms_level = raiden_settings.init_arms_levelself.center = float(self.rect.centerx)self.bottom = float(self.rect.bottom)self.moving_right = Falseself.moving_left = Falseself.moving_up = Falseself.moving_down = Falsedef update(self):if self.moving_right and self.rect.right < \self.screen_rect.right:self.center += self.raiden_settings.ship_speed_factorif self.moving_left and self.rect.left > 0:self.center -= self.raiden_settings.ship_speed_factorif self.moving_up and self.rect.top > 0:self.bottom -=self.raiden_settings.ship_speed_factorif self.moving_down and self.rect.bottom < \self.screen_rect.bottom:self.bottom +=self.raiden_settings.ship_speed_factorself.rect.centerx = self.centerself.rect.bottom = self.bottomdef blitme(self):self.screen.blit(self.image,self.rect)def center_ship(self):self.center = self.screen_rect.centerxdef update_arms(self):if self.arms_level < self.raiden_settings.max_arms_level:self.arms_level += 1def reset_ship(self):self.rect.centerx = self.screen_rect.centerxself.rect.bottom = self.screen_rect.bottomself.center = self.screen_rect.centerxself.bottom = self.screen_rect.bottomself.arms_level = self.raiden_settings.init_arms_level
游戏内部记录类
class GameStats():def __init__(self,raiden_settings):self.raiden_settings = raiden_settingsself.reset_stats()self.game_active = Falseself.score = 0def reset_stats(self):self.ships_left = self.raiden_settings.ship_init_life