20193221 徐炟 2019-2020《Python程序设计》 实验四 报告

20193221 2019-2020-2 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 1932
姓名: 徐炟
学号:20193221
实验教师:王志强
实验日期:2020年6月14日
必修/选修: 公选课

1.实验内容

此次实验我参照python教材做了一个《外星人入侵》的游戏。
实现的功能有:
飞船可以左右移动,并用空格键射击;
外星人群从左移动到屏幕右端然后下移一定距离,接着往反方向移动;
飞船射杀外星人,也就是子弹与外星人碰撞时,子弹与外星人消失,外星人消灭完后又新创建一群;
当外星人撞到飞船,玩家就损失一艘飞船,满3次游戏结束;
记录得分,最高得分,等级,余下的飞船数。

2.实验过程及其结果

1.添加并安装pygame。
2.过程和代码如下:

3.1 主循环的构建

创建一个空的pygame窗口,游戏的基本结构如下:

    alien_invasion.py

    import sys
    import pygame

    def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()
    screen = pygame.display.set_mode((1200, 800))
    pygame.display.set_caption("Alien Invasion")

    # 开始游戏的主循环
    while True:
    # 监视键盘和鼠标事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    # 让最近绘制的屏幕可见
    pygame.display.flip()
    run_game()

3.2 存储所有设置的类

将所有的设置存储到一个类中,命名为Settings。

    settings.py

    class Settings():
"""存储所有设置的类"""
def __init__(self):
	"""初始化游戏的静态设置"""
	# 屏幕设置
	self.screen_width = 1200
	self.screen_height = 700
	self.bg_color = (230, 230, 230)
	# 飞船的设置
	self.ship_limit = 3

	# 子弹设置
	self.bullet_width = 3
	self.bullet_height = 15
	self.bullet_color = 60, 60, 60
	self.bullets_allowed = 3

	# 外星人设置
	self.fleet_drop_speed = 10

在alieninvasion.py中导入Settings类,创建settings的实例ai_settings,在主循环中重绘屏幕.

            alien_invasion.py

            def run_game():
'''初始化游戏并定义一个屏幕对象'''
        pygame.init()
        ai_settings = Settings()
        screen = pygame.display.set_mode(
	(ai_settings.screen_width, ai_settings.screen_height))
        pygame.display.set_caption('Alien Invasion')

3.3 飞船Ship类

选择表示飞船的图像,导入到Ship类中,再在alien_invasion.py中写入显示到屏幕的代码段。

            ship.py

            import pygame
            from pygame.sprite import Sprite

            class Ship(Sprite):
"""一个飞船类,方便创建飞船编组"""
        def __init__(self, ai_settings, screen):
	"""初始化飞船设置初始位置"""
	super().__init__()
	self.screen = screen # 加self的可以供类中所有方法使用
	self.ai_settings = ai_settings

	# 加载飞船图像并获取外接矩形
	self.image = pygame.image.load('images/ship.bmp')
	self.rect = self.image.get_rect()
	self.screen_rect = screen.get_rect()

	# 将每艘新飞船放在屏幕底部中央
	self.rect.centerx = self.screen_rect.centerx
	self.rect.bottom = self.screen_rect.bottom

在alien_invasion.py中导入Ship类,创建飞船的实例,在主循环中重绘屏幕。

3.4 游戏函数

对于飞船的移动,就需要响应按键和鼠标事件,将管理事件的代码放到新函数check_events中,新创建一个game_functions.py用于存储游戏过程中需要用到的函数。由于允许飞船不断移动,所以按键与松开按键需要单独定义。

            game_functions.py

            def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""响应按键"""
        if event.key == pygame.K_RIGHT:
	# 向右移动飞船
	ship.moving_right =True
        elif event.key == pygame.K_LEFT:
	# 向左移动飞船
	ship.moving_left =True
        elif event.key == pygame.K_SPACE:
	fire_bullet(ai_settings, screen, ship, bullets)
        elif event.key == pygame.K_q:
	sys.exit()
            def check_keyup_events(event, ship):
"""响应松开"""
        if event.key == pygame.K_RIGHT:
	ship.moving_right =False
        elif event.key == pygame.K_LEFT:
	ship.moving_left =False

            def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens, 
	bullets):
"""响应键盘和鼠标事件"""
for event in pygame.event.get():
		if event.type == pygame.QUIT:
			sys.exit()
		elif event.type == pygame.KEYDOWN:
			check_keydown_events(event, ai_settings, screen, ship, bullets)
		elif event.type == pygame.KEYUP:
			check_keyup_events(event, ship)
		elif event.type == pygame.MOUSEBUTTONDOWN:
			mouse_x,mouse_y = pygame.mouse.get_pos()
			check_play_button(ai_settings, screen, stats, sb, play_button, ship, 
				aliens, bullets, mouse_x, mouse_y)

接着在主循环中调用这些函数,及时更新屏幕上的图像。

3.4 子弹bullet类

创建子弹类,将子弹存储到编组Group中,在gamefunctions.py中,加入玩家按空格键时发射子弹。还需修改update_screen(),确保在调用flip()前在屏幕上重绘每颗子弹,删除已消失的子弹(在屏幕外面的)。

            bullet.py

            class Bullet(Sprite):
"""飞船发射的子弹的类"""
        def __init__(self, ai_settings, screen, ship):
	"""在飞船所处位置创建一个子弹对象"""
	# 初始化父类Sprite的属性	
	super().__init__()
	self.screen = screen
	
	# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
	self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
		ai_settings.bullet_height)
	self.rect.centerx = ship.rect.centerx
	self.rect.top = ship.rect.top

3.5 外星人Alien类

选择表示外星人的图像,导入到Alien类中,再在alien_invasion.py中创建Alien的实例,写入显示到屏幕的代码段。接着根据计算创建外星人群,把它们放到编组中,并向右向下移动。

            alien.py

            import pygame
            from pygame.sprite import Sprite

            class Alien(Sprite):
"""一个外星人类"""
        def __init__(self, ai_settings, screen):
	"""初始化外星人设置初始位置"""
	super().__init__()
	self.screen = screen # 加self的可以供类中所有方法使用
	self.ai_settings = ai_settings

	# 加载外星人图像并获取外接矩形
	self.image = pygame.image.load('images/alien.bmp')
	self.rect = self.image.get_rect()

	# 每个新外星人最初在左上角
	self.rect.x = self.rect.width
	self.rect.y = self.rect.height
	# 存储外星人的准确位置
	self.x = float(self.rect.x)

4 外星人与飞船的战争

4.1 检测子弹与外星人的碰撞

当子弹击中外星人时,子弹与外星人都消失,方法sprite.groupcollide()将每颗子弹的rect与每个外星人的rect,相比较,返回一个字典,包含发生碰撞的子弹和外星人,每个键时一个子弹,相应的值为被击中的外星人。

            game_functions.py

            def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, 
	aliens, bullets):
# 检查是否有子弹击中了外星人,删除相应子弹外星人,两个true表示删除,两个组之间的
        collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

4.2 响应外星人和飞船碰撞

当外星人与飞船相撞时,通过跟踪游戏的统计信息来记录飞船被撞了几次,满三次就游戏结束。相对应的编写新类GameStats放入game_stats.py,在alien_invasion.py中创建GameStats的实例。

            game_stats.py

            class GameStats():
"""跟踪游戏的统计信息"""
        def __init__(self, ai_settings):
	"""初始化统计信息"""
	self.ai_settings = ai_settings
	self.reset_stats()
	# 游戏启动时处于非活动状态
	self.game_active = False
	self.hign_score = 0

        def reset_stats(self):
	"""初始化在游戏运行期间可能变化的统计信息"""
	self.ships_left = self.ai_settings.ship_limit
	self.score = 0
	self.level = 1

飞船数量减1,清空外星人与子弹列表,接着创建一群新外星人,将飞船放在屏幕的底部中央。

            # 清空外星人列表和子弹列表
            aliens.empty()
            bullets.empty()
            # 创建一群新外星人,飞船放到屏幕低端中央
            create_fleet(ai_settings, screen, ship, aliens)
            ship.center_ship()
            sleep(0.5)

5 添加记分牌

5.1 添加play按钮

当玩家点击屏幕中央的play按钮时,开始游戏。创建Button类,实例化按钮,并在屏幕上绘制。

            button.py

            import pygame.font

            class Button():
"""开始游戏结束游戏的按钮"""
def __init__(self, ai_settings, screen, msg):
	"""初始化按钮属性"""
	self.screen = screen
	self.screen_rect = screen.get_rect()
	
	# 设置按钮的尺寸和其它属性
	self.width, self.height = 200, 50
	self.button_color = (0, 255, 0)
	self.text_color = (255, 255, 255)
	self.font = pygame.font.SysFont(None, 48)

5.2 创建记分牌

为在屏幕上显示得分,创建新类Scoreboard,用来显示当前得分,最高得分,玩家等级,余下的飞船数。

            scoreboard.py

            class Scoreboard():
"""显示得分信息的类"""
        def __init__(self, ai_settings, screen, stats):
	"""初始化显示得分信息涉及的属性"""
	self.screen = screen
	self.screen_rect = screen.get_rect()
	self.ai_settings = ai_settings
	self.stats = stats

	# 显示得分信息时的字体设置
	self.text_color = (30, 30, 30)
	self.font = pygame.font.SysFont(None, 48)

在外星人被消灭时更新得分,更新stats.score的值,再更新得分图像。

检查是否产生了最高得分,显示最高分,并将得分圆整为10的倍数。

            scoreboard.py

            def prep_hign_score(self):
"""将最高得分转换为一幅渲染的图像"""
# 将得分圆整,为10的倍数,round()让小数精确到小数点后几位
        hign_score = int(round(self.stats.hign_score, -1)) # python3可不要int
        hign_score_str = "{:,}".format(hign_score)
        self.hign_score_img = self.font.render(hign_score_str, True, 
	self.text_color, self.ai_settings.bg_color)

显示余下的飞船数需要先创建一艘新飞船,再创建一个新编组,每艘飞船左边距为10像素,将剩余的飞船显示在左下角。

            scoreboard.py

            def prep_ships(self):
"""显示还剩下多少飞船"""
        self.ships = Group()
        for ship_number in range(self.stats.ships_left):
	ship = Ship(self.ai_settings, self.screen)
	ship.rect.x = 10 + ship_number * ship.rect.width
	ship.rect.y = 10
	self.ships.add(ship)

运行结果如下:

3.其他(感悟、思考等)

首先很庆幸自己选到了这门个性化选修课,可能是我个人比较认为这门课程所用的语言很特别很奇妙,老师也很有趣,能让我们更好的了解Python这门课程真正的用途。在学习Python这门课程的这段时间以来,并且自己也能认识并且学习到很多知识,最大的特点就是其简单,容易上手.学完后感觉确实如此,相比于其他更为复杂的c,c++,Java等其语言板块更加清晰明了,简明扼要要编写一个程序,首先要确定目标是什么,然后分几个步骤去编写,编写代码要完整,一个语句有有始有终,嵌套编辑,然后编写一段检查一段,这样可以最大限度的保证,最小的最少的出问题。不管学什么,还是要脚踏实地,老老实实的去践行,学了以后就要训练,这样印象才会深刻,不至于眼高手低。现在发现确实是这样,自己原本以为已经理解了,已经会了,已经能够做好了,但是当自己真正去编写的时候,发现还是会出错,有时候根本不知道自己错在哪里了,所以练习还是非常重要的。突然想到一句话,原本我们以为不存在的。但是它确确实实就在那里;原本我们以为是真正有的,但是却不存在,比如说爱情。
找一个对的人怎么都不累,怎么都合适,不对的人,怎么都是问题。学习编程是个人爱好,也许在某一天,自己的这个爱好能够给自己带来很大的帮助。

posted on 2020-06-14 21:44  炟炟  阅读(131)  评论(0编辑  收藏

导航