Table of contents
(1) The main structure of the code
1. Reference the required modules
3. Define the main() function: the main program
The best way to learn is to learn other people's codes, and I used to like the game Raiden, so I started with Airplane Wars, downloaded the source code and picture materials from the Internet, and uploaded the source code first, and the ownership of the code belongs to the original author .
1. Source code
import pygame
from pygame.locals import *
from sys import exit
import time
import random
#创建子弹类,把子弹的图片转化为图像对象,设定固定的移动速度
class Bullet():
def __init__(self,bulletfilename,bulletpos): #定义初始化,参数是图的文件名和位置
self.bulletimg = pygame.image.load(bulletfilename) #图像
self.bullet_rect = self.bulletimg.get_rect()#获得rect
self.bullet_image = self.bulletimg.subsurface(self.bullet_rect) #生成subsurface对象
self.bullet_rect.midbottom = bulletpos #设置rect位置
self.speed = 2 #设置子弹速度
def move(self):
self.bullet_rect.top -= self.speed #子弹的运动是不断的以速度值大小减小
# 创建玩家飞机类,用面向对象的思想来对待
class play_plane_fly():
def __init__(self,play_image_filename,play_pos):
self.image = pygame.image.load(play_image_filename)
self.plane_rect = self.image.get_rect()
self.play_image = self.image.subsurface(self.plane_rect)
self.plane_rect.midtop = play_pos
self.speed = 2
#子弹是由玩家飞机发射的,所以创建列表,存储子弹对象,使该列表变为该类的属性
self.bullets = [] #子弹空列表
self.is_hitted = False #是否被击中
#生成函数,完成发射子弹动作,同时将每个子弹对象存在列表中
def shoot(self,bullet_filename):
bulletobj = Bullet(bullet_filename,self.plane_rect.midtop) #利用Bullet生产
self.bullets.append(bulletobj) #加入子弹列表
#定义向上移动方法,当飞机移动到边框位置时,无法移动
def moveup(self):
if self.plane_rect.top <= 0:
self.plane_rect.top = 0
else:
self.plane_rect.top -= self.speed
# 定义向下移动方法,当飞机移动到边框位置时,无法移动
def movedown(self):
if self.plane_rect.top >= 700 - self.plane_rect.height:
self.plane_rect.top = 700 - self.plane_rect.height
else:
self.plane_rect.top += self.speed
# 向右移动,当飞机移动到边框位置时,无法移动
def moveleft(self):
if self.plane_rect.left <= -40:
self.plane_rect.left = -40
else:
self.plane_rect.left -= self.speed
# 向左移动,当飞机移动到边框位置时,无法移动
def moveright(self):
if self.plane_rect.left >= 700 - self.plane_rect.width:
self.plane_rect.left = 700 - self.plane_rect.width
else:
self.plane_rect.left += self.speed
# 生成敌机类,设定固定的移动速度
class Enemy():
def __init__(self,enemyfilename,enemypos):
self.img = pygame.image.load(enemyfilename)
self.enemy_rect = self.img.get_rect()
self.enemy_image = self.img.subsurface(self.enemy_rect)
self.enemy_rect.midbottom = enemypos
self.speed = 1
def move(self):
self.enemy_rect.bottom += self.speed #敌机向下运动
clock = pygame.time.Clock()
def main():
# 初始化文字屏幕
pygame.font.init()
# 初始化图像屏幕
pygame.init()
# 设定游戏帧
clock.tick(50)
# 设定游戏屏幕大小
screen = pygame.display.set_mode((660, 700))
# 设定游戏名称
pygame.display.set_caption('飞机大战')
# 加载背景图片,生成图像对象
background = pygame.image.load('image/background.png').convert()
backgroundsurface = pygame.transform.scale(background, (660, 700))
# 加载游戏结束图片,生成图像对象
gameover = pygame.image.load('image/gameover.png').convert()
gameoversurface = pygame.transform.scale(gameover,(660, 700))
playplanefilename = 'image/hero1.png'
planepos = [330,600]
player = play_plane_fly(playplanefilename,planepos) #定义play实例
bulletfilename = 'image/bullet.png'
# 按频率生成子弹,初始化数字为0
bullet_frequency = 0
enemyfilename = 'image/enemy0.png'
# 按频率生成敌机,初始化数字为0
enemy_frequency = 0
# 定义enemys空列表
enemys = []
myfont = pygame.font.SysFont("font/Marker Felt.ttf", 40)
textImage = myfont.render("Score ", True, (0,0,0))
# 初始化得分为0
Score = 0
# 敌机被子弹击中时的动画,将每张图片的图像对象存在列表中
enenys_down = []
enemy0_down = pygame.image.load('image/enemy0_down1.png')
enemy0_down_rect = enemy0_down.get_rect()
enemydown0 = enemy0_down.subsurface(enemy0_down_rect)
enenys_down.append(enemydown0)
enemy1_down = pygame.image.load('image/enemy0_down2.png')
enemy1_down_rect = enemy1_down.get_rect()
enemydown1 = enemy1_down.subsurface(enemy1_down_rect)
enenys_down.append(enemydown1)
enemy2_down = pygame.image.load('image/enemy0_down3.png')
enemy2_down_rect = enemy2_down.get_rect()
enemydown2 = enemy2_down.subsurface(enemy2_down_rect)
enenys_down.append(enemydown2)
enemy3_down = pygame.image.load('image/enemy0_down4.png')
enemy3_down_rect = enemy3_down.get_rect()
enemydown3 = enemy3_down.subsurface(enemy3_down_rect)
enenys_down.append(enemydown3)
#以上存了四组击中后的图片,实现击中后的飞机爆炸
while True:
# 动态显示得分
score = str(Score)
myscore = pygame.font.SysFont("font/Marker Felt.ttf", 40)
scoreImage = myscore.render(score, True, (0, 0, 0))
# 判断事件,防止卡顿或者意外退出
for event in pygame.event.get():
if event.type == pygame.QUIT: #退出事件
pygame.quit()
exit()
key_pressed = pygame.key.get_pressed() #接收输入键
if key_pressed[K_UP] or key_pressed[K_w]:
player.moveup()
if key_pressed[K_DOWN] or key_pressed[K_s]:
player.movedown()
if key_pressed[K_LEFT] or key_pressed[K_a]:
player.moveleft()
if key_pressed[K_RIGHT] or key_pressed[K_d]:
player.moveright()
screen.blit(backgroundsurface, (0, 0)) #绑定背景图
if not player.is_hitted: #如果游戏对象没有被击中
# 按频率生成子弹
# 通过控制30这个数,来控制发射子弹的间隔,循环30次后发射一个子弹
if bullet_frequency % 30 == 0:
player.shoot(bulletfilename)
bullet_frequency += 1
if bullet_frequency >= 30:
bullet_frequency = 0
# print("bullet_frequency is {0}".format(bullet_frequency)) #试验用的,没有实际意义
# 让子弹动起来
for i in player.bullets:
i.move()
screen.blit(i.bullet_image,i.bullet_rect)
# 当子弹飞出屏幕,删除子弹对象
if i.bullet_rect.bottom <= 0:
player.bullets.remove(i) #从列表中删除数据
# 按频率生成敌机
#原理同子弹频率一样
if enemy_frequency % 100 == 0:
enemypos = [random.randint(30, 630), 0]
enemyplane = Enemy(enemyfilename, enemypos)
#将敌机对象添加到列表中
enemys.append(enemyplane)
enemy_frequency += 1
if enemy_frequency >= 100:
enemy_frequency = 0
# 让敌机动起来
for i in enemys:
i.move()
screen.blit(i.enemy_image,i.enemy_rect)
# 当敌机飞出屏幕,删除敌机对象
if i.enemy_rect.bottom >= 700:
enemys.remove(i)
# 遍历子弹对象,判断子弹是否击中敌机
for j in player.bullets:
# 如果击中,分数增加,同时移除该子弹和敌机对象
if pygame.Rect.colliderect(j.bullet_rect,i.enemy_rect): #运用的是rect对象的检测,测试两个矩形是否重叠
Score += 100
enemys.remove(i)
player.bullets.remove(j)
for k in enenys_down:
screen.blit(k,i.enemy_rect)
# 遍历敌机对象,判断玩家是否和敌机相撞
if pygame.Rect.colliderect(player.plane_rect,i.enemy_rect):
# 修改is_hitted的值,跳出该层循环
player.is_hitted = True
break
screen.blit(player.play_image,player.plane_rect)
screen.blit(textImage, (0,0))
screen.blit(scoreImage, (110, 0))
pygame.display.update()
# 玩家退出时显示分数和游戏结束
else:
screen.blit(gameoversurface,(0,0))
screen.blit(textImage, (0, 0))
screen.blit(scoreImage, (110, 0))
pygame.display.update()
time.sleep(2)
break
main()
2. Source code analysis:
(1) The main structure of the code
1. Reference the required modules
import pygame from pygame.locals import * from sys import exit import time import random
2. Defined classes
(1) Bullet()-bullet class
The bullet image and position need to be initialized
Define class method move
(2) play_plane_fly(): Player aircraft class
Need to initialize the aircraft image and position
Define the class method shoot and four aspects of movement
(3) Enemy(): Enemy aircraft
The image and position of the enemy aircraft need to be initialized
Define class method move
3. Define the main() function: the main program
(1) Initialization and settings
# Initialize text screen pygame.font.init() # Initialize image screen pygame.init() # Set the game frame clock.tick(50) # Set the game screen size screen = pygame.display.set_mode((660, 700)) # Set the game name pygame.display.set_caption('Airplane War') # Load the background image and generate an image object background = pygame.image.load('image/background.png').convert() backgroundsurface = pygame.transform.scale(background, (660, 700)) # Load the game over image and generate an image object gameover = pygame.image.load('image/gameover.png').convert() gameoversurface = pygame.transform.scale(gameover,(660, 700)) #Set aircraft parameters playplanefilename = 'image/hero1.png' planepos = [330,600] #define aircraft instance player = play_plane_fly(playplanefilename,planepos) #Define play instance #Set bullet parameters bulletfilename = 'image/bullet.png' # Generate bullets according to the frequency, the initialization number is 0 bullet_frequency = 0 #Set enemy plane parameters enemyfilename = 'image/enemy0.png' # Generate enemy planes according to the frequency, the initialization number is 0 enemy_frequency = 0 # define an empty list of enemies enemys = [] # generate font object myfont = pygame.font.SysFont("font/Marker Felt.ttf", 40) # Generate Surface textImage = myfont.render("Score ", True, (0,0,0)) # Initialize score to 0 Score = 0 # The animation when the enemy plane is hit by a bullet, save the image object of each picture in the list enenys_down = [] enemy0_down = pygame.image.load('image/enemy0_down1.png') enemy0_down_rect = enemy0_down.get_rect() enemydown0 = enemy0_down.subsurface(enemy0_down_rect) enenys_down.append(enemydown0) enemy1_down = pygame.image.load('image/enemy0_down2.png') enemy1_down_rect = enemy1_down.get_rect() enemydown1 = enemy1_down.subsurface(enemy1_down_rect) enenys_down.append(enemydown1) enemy2_down = pygame.image.load('image/enemy0_down3.png') enemy2_down_rect = enemy2_down.get_rect() enemydown2 = enemy2_down.subsurface(enemy2_down_rect) enenys_down.append(enemydown2) enemy3_down = pygame.image.load('image/enemy0_down4.png') enemy3_down_rect = enemy3_down.get_rect() enemydown3 = enemy3_down.subsurface(enemy3_down_rect) enenys_down.append(enemydown3) #The above four groups of pictures after hitting are saved to realize the explosion of the plane after hitting
(2) Get events and respond one by one
while True: # Dynamically display the score score = str(Score) myscore = pygame.font.SysFont("font/Marker Felt.ttf", 40) scoreImage = myscore.render(score, True, (0, 0, 0)) # Judge events to prevent stuck or unexpected exit for event in pygame.event.get(): if event.type == pygame.QUIT: #Quit event pygame.quit() exit() key_pressed = pygame.key.get_pressed() #Receive input key if key_pressed[K_UP] or key_pressed[K_w]: player.moveup() if key_pressed[K_DOWN] or key_pressed[K_s]: player.movedown() if key_pressed[K_LEFT] or key_pressed[K_a]: player.moveleft() if key_pressed[K_RIGHT] or key_pressed[K_d]: player.moveright() screen.blit(backgroundsurface, (0, 0)) #Binding background image if not player.is_hitted: #If the game object is not hit # Generate bullets by frequency # Control the interval of firing bullets by controlling the number 30, and fire a bullet after 30 cycles if bullet_frequency % 30 == 0: player.shoot(bulletfilename) bullet_frequency += 1 if bullet_frequency >= 30: bullet_frequency = 0 # make the bullet move for i in player.bullets: i.move() screen.blit(i.bullet_image,i.bullet_rect) # When the bullet flies off the screen, delete the bullet object if i.bullet_rect.bottom <= 0: player.bullets.remove(i) #Remove data from the list # Generate enemy planes by frequency #The principle is the same as bullet frequency if enemy_frequency % 100 == 0: enemypos = [random.randint(30, 630), 0] enemyplane = Enemy(enemyfilename, enemypos) #Add the enemy object to the list enemys.append(enemyplane) enemy_frequency += 1 if enemy_frequency >= 100: enemy_frequency = 0 # Make the enemy move for i in enemys: i.move() screen.blit(i.enemy_image,i.enemy_rect) # When the enemy plane flies out of the screen, delete the enemy plane object if i.enemy_rect.bottom >= 700: enemys.remove(i) # Traverse the bullet object to determine whether the bullet hits the enemy plane for j in player.bullets: # If it hits, the score is increased, and both the bullet and the enemy object are removed if pygame.Rect.colliderect(j.bullet_rect,i.enemy_rect): #Use the detection of the rect object to test whether the two rectangles overlap Score += 100 enemys.remove(i) player.bullets.remove(j) for k in enenys_down: screen.blit(k,i.enemy_rect) # Traversing the enemy plane object to determine whether the player has collided with the enemy plane if pygame.Rect.colliderect(player.plane_rect,i.enemy_rect): # Modify the value of is_hitted to jump out of the layer loop player.is_hitted = True break screen.blit(player.play_image,player.plane_rect) screen.blit(textImage, (0,0)) screen.blit(scoreImage, (110, 0)) pygame.display.update() # Show score and game over when player exits else: screen.blit(gameoversurface,(0,0)) screen.blit(textImage, (0, 0)) screen.blit(scoreImage, (110, 0)) pygame.display.update() time.sleep(2) break
illustrate:
① Receive keyboard input
key_pressed = pygame.key.get_pressed() #Receive input key
② Control the firing frequency of bullets and enemy planes
# Control the interval of firing bullets by controlling the number 30, and fire a bullet after 30 cycles if bullet_frequency % 30 == 0: player.shoot(bulletfilename) bullet_frequency += 1 if bullet_frequency >= 30: bullet_frequency = 0
Increase the number by 1 each time the transmission frequency reaches the requirement every 30 times, shoot once
The frequency method of the enemy aircraft is the same
③Collision detection
Realized by collision detection between rects
For example:
if pygame.Rect.colliderect(player.plane_rect,i.enemy_rect):
# Modify the value of is_hitted to jump out of the layer loop
player.is_hitted = True
break
(3) Update and Refresh
..... screen.blit(player.play_image,player.plane_rect) screen.blit(textImage, (0,0)) screen.blit(scoreImage, (110, 0)) pygame.display.update()
(2) Code analysis harvest
1. The code makes full use of classes and class methods, which greatly reduces the amount of code and has good reusability.
2. The idea of transmitting frequency control can be used in other occasions.
3. Using the collision detection of the Rect object to realize the collision between the plane, the bullet and the enemy plane, the realization is better
4. Realize the effect of enemy aircraft explosion by switching the enenys_down list, which can be used for reference.