93
社区成员
发帖
与我相关
我的任务
分享
20234108 2023-2024-2 《Python程序设计》综合实践
课程:《Python程序设计》
班级:2341
姓名:沈紫娴
学号:20234107
实验教师:王志强
实验日期:2024年5月27日
必修/选修: 专选课
1.实验内容
Python综合应用:
选择利用PyCharm编写游戏“飞机大战”。
2. 实验过程及结果
(1)安装pygame模块:
在file--settings--Project Interpreter中添加pygame package。
(2)素材准备
直接在项目下,将准备好的素材图片文件夹整个导入,命名为image。
(3)游戏原理
主要涉及图形界面、事件处理、游戏逻辑几部分。主要运用到初始化和退出(pygame.init、pygame.quit)、坐标系(pygame.Rect)、创建游戏窗口(pygame.display.set_mode)、绘制图像(pygame.image.load())、调用(build)、更新(update)、设置时钟对象(pygame.time.Clock())、监听事件(pygame.event.get())、精灵和精灵组等功能。综合运用了pygame的各个模块、面向对象的编程等知识。
那么,我们就要运用上述原理来搭建程序的框架。针对游戏初始化我们有三个功能要实现:1.设置游戏窗口2.创建游戏时钟3.创建精灵,精灵组;针对游戏循环我们有五个功能要实现:1.设置刷新频率2.事件监听3.碰撞检测4.更新绘制精灵组5.更新屏幕显示。
①背景图像的滑动
在游戏中我们让飞机在移动的时候能够实现背景图不断变换,就运用精灵组的功能,先在精灵组中新建背景精灵,再在主文件中调用,实现背景长图重复划过屏幕,实现移动的效果。一下分别为在精灵组和主代码中的操作:
class Background(GameSprite):
"""游戏背景精灵"""
def update(self):
super().update()
if self.rect.y >= SCREEN_RECT.height:
self.rect.y = -self.rect.height
def __create_sprites(self):
background1 = plane_sprites.Background("./飞机大战/images/background.png")
background2 = plane_sprites.Background("./飞机大战/images/background.png")
background2.rect.y = -background2.rect.height
self.back_group = pygame.sprite.Group(background1, background2)
最后再更新绘制精灵组
def __update_sprites(self):
self.back_group.update()
self.back_group.draw(self.screen)
②敌机的移动和判定。在游戏中设置定时器,每隔一秒出现一架敌机。然后再在精灵组中创建敌机类,再在主代码中调用。然后再运用random板块,随机敌机出现的位置。
def __init__(self):
super().__init__('./飞机大战/images/enemy1.png')
self.speed = random.randint(2, 4)
self.rect.bottom = 0
max_x = SCREEN_RECT.width - self.rect.width
self.rect.x = random.randint(0, max_x)
③销毁敌机
当敌机移出屏幕后一定要对敌机进行销毁,使用精灵类自带的kill()功能,判断飞出后直接使用kill()功能进行销毁。
④玩家飞机
首先我们先在主文件里创建一个英雄飞机的类,并设置它的位置和速度,由于飞机默认静止,所以设置它的速度为0。采用pygame自带的使用键盘提供的方法获取键盘按键,获取到按键元组,然后用元组索引进行判断是否满足左右键,然后进行相应的移动操作。然后在精灵组里创建英雄飞机的精灵和精灵组,这里需要单独把英雄设置成属性,为后面碰撞检测做准备,以及到时候直接调用发射子弹的方法,最后更新和绘制英雄飞机。
⑤子弹
让子弹每0.5秒发射一次,用定时器来实现这个功能。然后和创建敌机的方法一样,创建一个子弹类,来对子弹进行创建更新和绘制。之后再和敌机一样进行更新绘制到屏幕上,位置可以设置到英雄战机的头部偏上一点。
然后再用pygame提供的pygame.sprites.groupcollide()方法,设定敌机和子弹发生碰撞。
def __check_collide(self):
pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
⑥敌机碰撞玩家飞机
使用pygame.sprites.groupcollide()类型的pygame.sprite.spritecollide()方法,传入一个精灵和精灵组,返回一个敌机列表,然后判断是否销毁,判断返回列表里是否有值,如果有的话,表示英雄飞机和敌机发生碰撞,用kill()销毁英雄战机。
def __check_collide(self):
pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
if len(enemies) > 0:
self.hero.kill()
PlaneGame.__game_over()
下面是完整代码:
主代码:
import pygame
from plane_sprites import *
class PlaneGame(object):
"""飞机大战主游戏"""
def __init__(self):
print("游戏初始化")
self.screen = pygame.display.set_mode(SCREEN_RECT.size)
self.clock = pygame.time.Clock()
self.__creat_sprites()
pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
pygame.time.set_timer(HERO_FIRE_EVENT, 500)
def __creat_sprites(self):
bg1 = Background()
bg2 = Background(True)
self.back_group = pygame.sprite.Group(bg1, bg2)
self.enemy_group = pygame.sprite.Group()
self.hero = Hero()
self.hero_group = pygame.sprite.Group(self.hero)
self.enemy_hit_group = pygame.sprite.Group();
def start_game(self):
print("游戏开始.....")
while True:
self.clock.tick(FRAME_PER_SEC)
self.__event_handler()
self.__check_collide()
self.__update_sprites()
pygame.display.update()
def __event_handler(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
PlaneGame.__game_over()
elif event.type == CREATE_ENEMY_EVENT:
print("敌机出场")
enemy = Enemy()
self.enemy_group.add(enemy)
elif event.type == HERO_FIRE_EVENT:
self.hero.fire()
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_RIGHT]:
self.hero.speed = 3
elif keys_pressed[pygame.K_LEFT]:
self.hero.speed = -3
else:
self.hero.speed = 0
def __check_collide(self):
enemy_hit = pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
if len(enemies) > 0:
self.hero.kill()
PlaneGame.__game_over()
def __update_sprites(self):
self.back_group.update()
self.back_group.draw(self.screen)
self.enemy_group.update()
self.enemy_group.draw(self.screen)
self.hero_group.update()
self.hero_group.draw(self.screen)
self.hero.bullets.update()
self.hero.bullets.draw(self.screen)
@staticmethod
def __game_over():
print("游戏结束")
pygame.quit()
exit()
if __name__ == '__main__':
game = PlaneGame()
game.start_game()
精灵组代码:
import random
import pygame
SCREEN_RECT=pygame.Rect(0,0,480,700)
FRAME_PER_SEC=60
explode_index=0
CREATE_ENEMY_EVENT=pygame.USEREVENT
HERO_FIRE_EVENT=pygame.USEREVENT+1
class GameSprite(pygame.sprite.Sprite):
"""飞机大战游戏精灵"""
def __init__(self,image_name,speed=1):
super().__init__()
self.image=pygame.image.load(image_name)
self.rect=self.image.get_rect()
self.speed=speed
def update(self):
self.rect.y+=self.speed
class Background(GameSprite):
"""游戏背景精灵"""
def __init__(self,is_alt=False):
super().__init__("./images/background.png")
if is_alt:
self.rect.y = -self.rect.height
def update(self):
super().update()
if self.rect.y>=SCREEN_RECT.height:
self.rect.y= -self.rect.height
class Enemy(GameSprite):
"""敌机精灵"""
def __init__(self):
super().__init__("./images/enemy1.png")
self.speed=random.randint(1,3)
self.rect.bottom=0
max_x=SCREEN_RECT.width-self.rect.width
self.rect.x=random.randint(0,max_x)
self.explode_index=0
def update(self):
super().update()
if self.rect.y>=SCREEN_RECT.height:
self.kill()
#if self.explode_index==5:
#return
if self.explode_index!=0:
new_rect=self.rect
super.__init__("./images/enemy1_down1.png")
self.explode_index=self.explode_index+1
self.rect=new_rect
def __del__(self):
pass
class Hero(GameSprite):
"""英雄精灵"""
def __init__(self):
super().__init__("./images/me1.png",0)
self.rect.centerx=SCREEN_RECT.centerx
self.rect.bottom=SCREEN_RECT.bottom-120
self.bullets=pygame.sprite.Group()
def update(self):
self.rect.x+=self.speed
if self.rect.x<0:
self.rect.x=0
elif self.rect.right>SCREEN_RECT.right:
self.rect.right=SCREEN_RECT.right
def fire(self):
print("发射子弹...")
for i in (0,1,2):
bullet=Bullet()
bullet.rect.bottom=self.rect.y-i*20
bullet.rect.centerx=self.rect.centerx
self.bullets.add(bullet)
def explode(self,screen):
new_rect=self.rect
for i in (1,2,3,4):
super.__init__("./images/me_destroy_2.png")
self.rect.centerx=new_rect.centerx
self.rect.centery=new_rect.centery
screen.blit(self.image,(self.rect.x,self.rect.y))
pygame.display.update()
class Bullet(GameSprite):
"""子弹精灵"""
def __init__(self):
super().__init__("./images/bullet1.png",-2)
def update(self):
super().update()
if self.rect.bottom<0:
self.kill()
def __del__(self):
print("子弹被销毁")
程序运行视频:
-问题1:无法找到图片素材文件
-问题1解决方案:图片文件夹路径错误,不小心在文件夹中又多嵌套了一个文件夹,修改过后成功运行。
-问题2:运行结束后,报错“libpng warning: iCCP: known incorrect sRGB profile”(libpng 警告:iCCP:已知不正确的 sRGB 配置文件)
-问题2解决方案:原因是因为libpng 1.6太敏感,1.6及以上版本增强了ICC profiles检查,所以发出警告。把png格式的文件在Photoshop中重新保存一遍即可。
感想体会:在小游戏的编写中,飞机大战属于比较简单的程序,但是在这个全新的领域的探索中,我依然面临诸多问题和挑战。并且将人的思维转化为程序思维,并整合成整个游戏的逻辑框架,也是有难度的。但是,我因此对pygame板块产生了浓厚的兴趣,希望即使在结课后也对其继续探索,未来能不仅参考别人的代码,也开发出自己想玩的小游戏代码。
4.课程感想体会
在这一学期的python课中,主要学习了以下内容:
环境搭建:如何安装Python和配置开发环境。基本语法:变量、注释、输入输出等。数值类型:整数、浮点数、复数。序列类型:列表(list)、元组(tuple)、集合(set)和字典(dictionary)的使用。控制结构:条件语句:if、elif、else;循环语句:while循环和for循环;循环控制:break。函数的定义和调用:如何定义函数以及如何调用函数。面向对象编程:类和对象:类的定义和对象的创建;继承和封装。文件及目录操作。socket编程。网络爬虫开发等。在课上我们学习到了丰富的技术知识,老师的课件和ppt也十分清晰易懂。同时,也做了许多实践活动:比如猜数字、猜拳游戏、制作计算器、socket编程实践等等。在丰富的实践与理论学习中,我对这些知识也有了基本的掌握,对python的理解更进一步,也有助于我更智慧高效地运用编程知识来处理一些数据,有助于未来实现更高效的智慧办公,掌握一门专业技能,不落后于时代潮流。
同时,除了专业技能上的收获,python也极大地培养了我的逻辑思维和思考问题的方式,使我思考问题能够从更多方面展开,也拓宽了我解决问题的思路。在解决一些繁杂、人力耗费巨大的任务时,可以运用编程知识帮忙解决问题。同时,也培养了我的探索和实验的能力:在实验中,我遇到问题不再退缩放弃,而是充分运用一切学习资源,到社区论坛求解,将问题各个疏通,逐一击破,最后化解难题,克服了许多畏难情绪。即使一行代码出错,也会引发整个程序的错误,因此,编写python也使我更加认真仔细,减少出错。
最后,我也紧跟老师的教诲,不但在python这一门学科上,在其它学科上,也不断探索,不断求知,不使自己落后于时代的浪潮。
参考资料
-https://blog.csdn.net/q610098308/article/details/135407153?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-135407153-blog-121900456.235^v43^pc_blog_bottom_relevance_base8&spm=1001.2101.3001.4242.1&utm_relevant_index=3