目录
导包
首先,我们需要导入所需的模块。这包括time、pygame和random模块。time模块用于控制游戏中的时间,pygame是用于游戏开发的主模块,random用于生成随机数,例如随机生成敌机子弹。
import time
import pygame
import random
界面设置
窗口
创建一个有戏窗口大小按自己喜好来定义
# 显示窗口
screen = pygame.display.set_mode((480,650))
背景
把准备好的背景图片加载在python中,并将其放置到窗口中,其中(0,0)对应背景放置位置,以背景左上角为主,将左上角放置到坐标(0,0)位置,坐标(0,0)也对应窗口的左上角
# 加载背景
bg_img = pygame.image.load("../飞机大战/img/background.png")
# 显示背景
screen.blit(bg_img, (0, 0))
绘制飞机
这里我们需要加载两个飞机图片,是两个飞机图片循环切换来实现飞机的动态效果,定义一个变量作为飞机切换的条件
-
首先,它检查战机的当前状态
self.a
是否为"小喷"。 -
如果
self.a
为"小喷",那么它使用self.hero_img1
作为战机图像,并将该图像绘制到游戏窗口的(self.x, self.y)位置。同时,它将战机的当前状态更新为"大喷",以便在下一次绘制时使用self.hero_img2
。 -
如果
self.a
不为"小喷",那么它使用self.hero_img2
作为战机图像,并将该图像绘制到游戏窗口的(self.x, self.y)位置。同时,它将战机的当前状态更新为"小喷",以便在下一次绘制时使用self.hero_img1
。
通过这种方式,英雄战机的图像会在"小喷"和"大喷"之间循环切换,从而在游戏窗口上显示两种不同状态下的战机图像。这种状态切换的实现增加了游戏的趣味性和视觉效果。
self.a = "小喷"
self.hero_img1 = pygame.image.load("../飞机大战/img/me1.png")
self.hero_img2 = pygame.image.load("../飞机大战/img/me2.png")
if self.a == "小喷":
screen.blit(self.hero_img1, (self.x,self.y))
self.a = "大喷"
else:
screen.blit(self.hero_img2, (self.x,self.y))
self.a = "小喷"
绘制敌机
和飞机一样我们也是加载两个敌机图片实现敌机切换
self.hit == 1
self.enemy_img = pygame.image.load("../飞机大战/img/enemy2.png")
self.enemy1_img = pygame.image.load("../飞机大战/img/enemy2_hit.png")
if self.hit == 0:
screen.blit(self.enemy_img, (self.x,self.y))
self.hit = 1
else:
screen.blit(self.enemy1_img, (self.x,self.y))
self.hit = 0
子弹类
用来定义飞机和敌机子弹的类
战机子弹类
这段代码定义了一个名为HeroBullet
的类,用于表示英雄战机的子弹。在这个类中,__init__
方法用于初始化子弹的属性,而draw
和move
方法分别用于在屏幕上绘制子弹和更新子弹的位置。
让我们详细解释这段代码:
-
__init__
方法:self.x = x
:这行代码将传入的x
值赋给子弹对象的x
属性,表示子弹的初始水平位置。self.y = y
:这行代码将传入的y
值赋给子弹对象的y
属性,表示子弹的初始垂直位置。self.show = screen
:这行代码将传入的screen
对象赋给子弹对象的show
属性,这个属性是用于在游戏窗口上绘制图像的屏幕对象。self.pic = pygame.image.load("../飞机大战/img/bullet1.png")
:这行代码使用Pygame的image.load
函数加载了一张图片,这张图片是子弹的图像,并将其存储在子弹对象的pic
属性中。
-
draw
方法:self.show.blit(self.pic,(self.x,self.y))
:这行代码使用blit
方法将子弹的图像绘制到游戏窗口上,其中self.pic
是子弹的图像,而(self.x, self.y)
是子弹的当前位置。self.move()
:这行代码调用move
方法,这个方法用于更新子弹的位置。
-
move
方法:self.y -= 5
:这行代码将子弹的y
坐标减少5,使其向上移动。由于y
坐标是垂直方向的,这表示子弹从英雄战机的位置向上发射,并逐渐消失在屏幕上方。
总的来说,这个HeroBullet
类定义了一个简单的子弹对象,它具有初始位置、屏幕显示和移动能力。通过这个类,我们可以创建多个子弹对象,并在游戏过程中发射它们。
class HeroBullet:
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
self.pic = pygame.image.load("../飞机大战/img/bullet1.png")
# 画子弹
def draw(self):
self.show.blit(self.pic,(self.x,self.y))
self.move()
# 子弹移动
def move(self):
self.y -= 5
敌机子弹类
这段代码定义了一个名为EnemyBullet
的类,用于表示敌机发射的子弹。在这个类中,__init__
方法用于初始化子弹的属性,而draw
和move
方法分别用于在屏幕上绘制子弹和更新子弹的位置。
让我们详细解释这段代码:
-
__init__
方法:self.x = x
:这行代码将传入的x
值赋给子弹对象的x
属性,表示子弹的初始水平位置。self.y = y
:这行代码将传入的y
值赋给子弹对象的y
属性,表示子弹的初始垂直位置。self.show = screen
:这行代码将传入的screen
对象赋给子弹对象的show
属性,这个属性是用于在游戏窗口上绘制图像的屏幕对象。self.pic = pygame.image.load("../飞机大战/img/bullet2.png")
:这行代码使用Pygame的image.load
函数加载了一张图片,这张图片是敌机子弹的图像,并将其存储在子弹对象的pic
属性中。
-
draw
方法:self.show.blit(self.pic,(self.x,self.y))
:这行代码使用blit
方法将子弹的图像绘制到游戏窗口上,其中self.pic
是子弹的图像,而(self.x, self.y)
是子弹的当前位置。self.move()
:这行代码调用move
方法,这个方法用于更新子弹的位置。
-
move
方法:self.y += 5
:这行代码将子弹的y
坐标增加5,使其向下移动。由于y
坐标是垂直方向的,这表示子弹从敌机的位置向下发射,并逐渐消失在屏幕下方。
总的来说,这个EnemyBullet
类定义了一个简单的子弹对象,它具有初始位置、屏幕显示和移动能力。通过这个类,我们可以创建多个子弹对象,并在游戏过程中由敌机发射它们。
class EnemyBullet:
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
self.pic = pygame.image.load("../飞机大战/img/bullet2.png")
# 画子弹
def draw(self):
self.show.blit(self.pic,(self.x,self.y))
self.move()
# 子弹移动
def move(self):
self.y += 5
按键设置
飞机按键设置
这里我们实现飞机跟随你的按键移动和攻击。
-
检测
pygame.QUIT
事件,这是当用户关闭游戏窗口时触发的事件。如果检测到这个事件,游戏会打印出“游戏结束了”,然后调用pygame.quit()
卸载Pygame模块,并使用exit(0)
退出游戏。 -
检测
pygame.KEYDOWN
事件,这是当用户按下键盘按键时触发的事件。在这个事件中,我们通过event.key
来检查按下的具体键,并做出相应的动作:- 如果按下的是左箭头键(
pygame.K_LEFT
),战机向左移动10个像素,但前提是战机的x坐标大于或等于5,以防止战机移出屏幕左侧。 - 如果按下的是右箭头键(
pygame.K_RIGHT
),战机向右移动10个像素,但前提是战机的x坐标小于或等于370,以防止战机移出屏幕右侧。 - 如果按下的是上箭头键(
pygame.K_UP
),战机向上移动10个像素,但前提是战机的y坐标大于或等于5,以防止战机移出屏幕上方。 - 如果按下的是下箭头键(
pygame.K_DOWN
),战机向下移动20个像素,但前提是战机的y坐标小于或等于521,以防止战机移出屏幕下方。 - 如果按下的是空格键(
pygame.K_SPACE
),战机发射子弹。这里创建了一个新的HeroBullet
对象,其x坐标是战机x坐标加上40和10(调整子弹发射位置),y坐标是战机y坐标减去11(调整子弹发射位置),并将新子弹添加到战机子弹列表self.bullet_list
中。
- 如果按下的是左箭头键(
通过这些代码,我们实现了战机的基本移动和射击功能,这些是飞机大战游戏的核心交互部分
for event in event_list:
if event.type == pygame.QUIT:
print("游戏结束了")
# 卸载模块
pygame.quit()
exit(0)
# 战机移动
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.x = self.x - 10 if self.x >= 5 else 0
elif event.key == pygame.K_RIGHT:
self.x = self.x + 10 if self.x <= 370 else 380
elif event.key == pygame.K_UP:
self.y = self.y - 10 if self.y >= 5 else 0
elif event.key == pygame.K_DOWN:
self.y = self.y + 20 if self.y <= 521 else 526
elif event.key == pygame.K_SPACE:
hero_bullet = HeroBullet(self.x + 40 + 10, self.y - 11, screen)
self.bullet_list.append(hero_bullet)
敌机的移动
我们只需要敌机在屏幕上方左右移动即可
-
首先,它检查敌机的当前移动方向
self.b
是否为"left"。 -
如果
self.b
为"left",那么它将敌机的x坐标减少3个像素,使其向左移动。同时,它检查敌机的x坐标是否小于或等于0,即是否已经到达屏幕左侧。如果已经到达,它将敌机的移动方向更新为"right",以便在下一次移动时向右移动。 -
如果
self.b
不为"left",那么它将敌机的x坐标增加3个像素,使其向右移动。同时,它检查敌机的x坐标是否大于或等于480 - 60,即是否已经到达屏幕右侧。如果已经到达,它将敌机的移动方向更新为"left",以便在下一次移动时向左移动。
通过这种方式,敌机会在屏幕的左右两侧之间来回移动,从而增加游戏的挑战性和趣味性。这种移动模式的实现使得敌机在游戏窗口上的位置不断变化,增加了玩家的射击难度。
def move(self):
if self.b == 'left':
self.x = self.x - 3
if self.x <= 0:
self.b = 'right'
elif self.b == 'right':
self.x = self.x + 3
if self.x >= 480 - 60:
self.b = 'left'
敌机子弹
敌机子弹我们设置其随机发射
-
首先,它使用
random.randint(1, 100)
生成一个1到100之间的随机数x
。这个随机数用来决定敌机是否发射子弹。 -
然后,它检查
x
是否等于5或者78。如果x
等于这两个数中的任何一个,敌机就会发射子弹。这里设置了一个非常低的概率,使得敌机不会频繁发射子弹,从而增加游戏的难度和挑战性。 -
如果
x
等于5或者78,敌机创建一个新的EnemyBullet
对象。这个新对象的x
坐标是敌机x
坐标加上69和5(69是敌机图片的宽度,5是调整子弹发射位置),y
坐标是敌机y
坐标加上99(99是敌机图片的高度,调整子弹发射位置)。 -
最后,它将新创建的子弹对象添加到敌机的子弹列表
self.bullet_list
中。这样,敌机发射的子弹就会被存储在这个列表中,并且可以在游戏窗口上绘制。
通过这种方式,敌机会在游戏过程中随机发射子弹,增加了游戏的挑战性和趣味性。这种发射模式的实现使得敌机在游戏窗口上的行为更加多样化和不可预测。
def fire(self):
x = random.randint(1, 100)
if x == 5 or x == 78:
enemybullet = EnemyBullet(self.x + (69 + 5) / 2, self.y + 99, screen)
self.bullet_list.append(enemybullet)
for bullet1 in self.bullet_list:
bullet1.draw()
碰撞事件
用来实现子弹碰撞到飞机显示击毁的效果并加载击毁效果的图片
加载飞机击毁图片
self.hero_bomb_list = ["img/me_destroy_1.png",
"img/me_destroy_2.png",
"img/me_destroy_3.png",
"img/me_destroy_4.png"]
self.enemy_bomb_list = ["img/enemy2_down1.png",
"img/enemy2_down2.png",
"img/enemy2_down3.png",
"img/enemy2_down4.png"]
碰撞实现
-
首先,它使用
pygame.rect.Rect
创建了一个英雄战机的矩形对象hero_rect
。这个矩形对象的x
和y
坐标分别是英雄战机的x
和y
坐标,而宽度和高度分别是英雄战机的宽度和高度。 -
然后,它遍历敌机子弹列表
bullet_list
中的每个子弹。对于每个子弹,它使用pygame.rect.Rect
创建了一个子弹的矩形对象enemy_bullet_rect
。这个矩形对象的x
和y
坐标分别是子弹的x
和y
坐标,而宽度和高度分别是子弹的宽度和高度。 -
接着,它使用
colliderect
方法检查hero_rect
和enemy_bullet_rect
是否发生了碰撞。如果发生了碰撞,flag
变量将被设置为True
。 -
如果发生了碰撞,游戏会打印出“被对面打爆了”,并将英雄战机的
hero_bomb
属性设置为True
,表示英雄战机被击中。同时,它从子弹列表bullet_list
中移除击中英雄战机的子弹。
通过这种方式,英雄战机能够检测到是否被敌机子弹击中,并在被击中时结束游戏。这种碰撞检测机制增加了游戏的挑战性和趣味性,使得玩家必须时刻注意敌机子弹的威胁。
def check_collision(self,bullet_list):
hero_rect = pygame.rect.Rect(self.x,self.y,102,126)
for bullet in bullet_list:
enemy_bullet_rect = pygame.rect.Rect(bullet.x,bullet.y,5,12)
flag = enemy_bullet_rect.colliderect(hero_rect)
if flag:
print("被对面打爆了")
self.hero_bomb = True
bullet_list.remove(bullet)
需要创建两个,一个飞机一个敌机
def check_collision(self, bullet_list):
enemy_rect = pygame.rect.Rect(self.x, self.y, 50, 56)
for bullet in bullet_list:
hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 5, 12)
falg = hero_bullet_rect.colliderect(enemy_rect)
if falg:
print("把对面打爆了")
self.enemy_bomb = True
bullet_list.remove(bullet)
封装
封装代码的意义在于提高代码的可读性、可维护性和可重用性。它是一种面向对象编程(OOP)的实践,通过将相关的数据和函数组合在一起,形成一个具有明确功能的模块或类,从而实现代码的模块化。以下是封装代码的一些主要优点
-
模块化:封装允许将代码组织成更小的、可管理的部分,每个部分负责一个特定的功能。这使得代码更容易理解和维护。
-
隐藏内部细节:通过封装,类的内部实现细节对外部代码是隐藏的,这有助于减少外部代码对内部代码的依赖,从而提高代码的独立性和灵活性。
-
提高可重用性:封装后的代码可以被多次使用,只需将它们作为独立的模块或类导入到其他项目中。
-
提高安全性:封装可以防止外部代码直接访问或修改类的内部状态,从而提高了代码的安全性。
-
简化编程:通过封装,开发者可以专注于解决特定问题,而不需要关心其他部分如何实现。这有助于简化编程过程,提高开发效率。
-
促进协作:封装允许不同开发者专注于不同的模块或类,然后将它们组合在一起,形成一个完整的系统。这有助于促进团队合作和代码共享。
-
提高代码的扩展性:当需要添加新功能或修改现有功能时,封装可以帮助开发者在不影响其他部分的情况下进行操作。
封装后的代码展示
# 导包
import time
import pygame
import random
# 定义英雄子弹
class HeroBullet:
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
self.pic = pygame.image.load("../飞机大战/img/bullet1.png")
# 画子弹
def draw(self):
self.show.blit(self.pic,(self.x,self.y))
self.move()
# 子弹移动
def move(self):
self.y -= 5
# 敌机子弹
class EnemyBullet:
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
self.pic = pygame.image.load("../飞机大战/img/bullet2.png")
# 画子弹
def draw(self):
self.show.blit(self.pic,(self.x,self.y))
self.move()
# 子弹移动
def move(self):
self.y += 5
# 英雄战机类
class HeroPlane():
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
# 战机切换
self.a = "小喷"
# 战机图片
self.hero_img1 = pygame.image.load("../飞机大战/img/me1.png")
self.hero_img2 = pygame.image.load("../飞机大战/img/me2.png")
# 战机爆炸
self.hero_bomb_index = 0
# 战机爆炸图片
self.hero_bomb_list = ["img/me_destroy_1.png",
"img/me_destroy_2.png",
"img/me_destroy_3.png",
"img/me_destroy_4.png"]
# 战机爆炸条件
self.hero_bomb = False
# 子弹列表
self.bullet_list = []
# 显示
def draw(self):
if self.hero_bomb == False:
# 显示战机
if self.a == "小喷":
screen.blit(self.hero_img1, (self.x,self.y))
self.a = "大喷"
else:
screen.blit(self.hero_img2, (self.x,self.y))
self.a = "小喷"
else:
if self.hero_bomb_index == len(self.hero_bomb_list):
time.sleep(0.3)
exit()
hero_bomb_img = pygame.image.load(self.hero_bomb_list[self.hero_bomb_index])
screen.blit(hero_bomb_img, (self.x,self.y))
self.hero_bomb_index += 1
time.sleep(0.2)
# 战机移动
def deal_event(self,event_list):
for event in event_list:
if event.type == pygame.QUIT:
print("游戏结束了")
# 卸载模块
pygame.quit()
exit(0)
# 战机移动
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.x = self.x - 10 if self.x >= 5 else 0
elif event.key == pygame.K_RIGHT:
self.x = self.x + 10 if self.x <= 370 else 380
elif event.key == pygame.K_UP:
self.y = self.y - 10 if self.y >= 5 else 0
elif event.key == pygame.K_DOWN:
self.y = self.y + 20 if self.y <= 521 else 526
elif event.key == pygame.K_SPACE:
hero_bullet = HeroBullet(self.x + 40 + 10, self.y - 11, screen)
self.bullet_list.append(hero_bullet)
# 调用函数画出战机子弹
for bullet in self.bullet_list:
bullet.draw()
# 碰撞事件
def check_collision(self,bullet_list):
hero_rect = pygame.rect.Rect(self.x,self.y,102,126)
for bullet in bullet_list:
enemy_bullet_rect = pygame.rect.Rect(bullet.x,bullet.y,5,12)
flag = enemy_bullet_rect.colliderect(hero_rect)
if flag:
print("被对面打爆了")
self.hero_bomb = True
bullet_list.remove(bullet)
# 敌机类
class EnemyPlane():
def __init__(self,x,y,screen):
self.x = x
self.y = y
self.show = screen
self.enemy_img = pygame.image.load("../飞机大战/img/enemy2.png")
self.enemy1_img = pygame.image.load("../飞机大战/img/enemy2_hit.png")
self.hit = 0
self.enemy_bomb_list = ["img/enemy2_down1.png",
"img/enemy2_down2.png",
"img/enemy2_down3.png",
"img/enemy2_down4.png"]
self.enemy_bomb_index = 0
self.enemy_bomb = False
self.bullet_list = []
self.b = 'left'
# 画敌机
def draw(self):
if self.enemy_bomb == False:
if self.hit == 0:
screen.blit(self.enemy_img, (self.x,self.y))
self.hit = 1
else:
screen.blit(self.enemy1_img, (self.x,self.y))
self.hit = 0
else:
if self.enemy_bomb_index == len(self.enemy_bomb_list):
time.sleep(0.2)
exit(0)
enemy_bomb_img = pygame.image.load(self.enemy_bomb_list[self.enemy_bomb_index])
screen.blit(enemy_bomb_img,(self.x,self.y))
self.enemy_bomb_index += 1
time.sleep(0.2)
self.move()
self.fire()
def move(self):
if self.b == 'left':
self.x = self.x - 3
if self.x <= 0:
self.b = 'right'
elif self.b == 'right':
self.x = self.x + 3
if self.x >= 480 - 60:
self.b = 'left'
def fire(self):
x = random.randint(1, 100)
if x == 5 or x == 78:
enemybullet = EnemyBullet(self.x + (69 + 5) / 2, self.y + 99, screen)
self.bullet_list.append(enemybullet)
for bullet1 in self.bullet_list:
bullet1.draw()
def check_collision(self, bullet_list):
enemy_rect = pygame.rect.Rect(self.x, self.y, 50, 56)
for bullet in bullet_list:
hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 5, 12)
falg = hero_bullet_rect.colliderect(enemy_rect)
if falg:
print("把对面打爆了")
self.enemy_bomb = True
bullet_list.remove(bullet)
# 初始化游戏
pygame.init()
# 显示窗口
screen = pygame.display.set_mode((480,650))
# 修改游戏图标
icon = pygame.image.load("../飞机大战/img/icon.png")
pygame.display.set_icon(icon)
# 加载背景
bg_img = pygame.image.load("../飞机大战/img/background.png")
# 加载战机
hero_plane = HeroPlane(480 // 2 - 102 // 2, 650 - 126,screen)
# 加载敌机
enemy_plane = EnemyPlane(480 // 2 - 69 // 2, 0,screen)
# 按键灵敏度
pygame.key.set_repeat(20, 30)
# 时钟
clock = pygame.time.Clock()
while True:
# 设置时钟
clock.tick(60)
# 显示背景
screen.blit(bg_img, (0, 0))
# 敌机调用方法
enemy_plane.check_collision(hero_plane.bullet_list)
enemy_plane.draw()
# 战机调用方法
hero_plane.check_collision(enemy_plane.bullet_list)
hero_plane.draw()
hero_plane.deal_event(pygame.event.get())
# 刷新窗口
pygame.display.update()