利用python做游戏——pygame_1
之前碰了Qt,winforms,wpf. 主要是想接触一下GUI
我都不知道该干啥了
这个项目是在《Python编程从入门到实践》上摘写的 个人推荐这本书还有同系列的蟒蛇书
后面想写写matplotlib和其他的python库,不过Python这个语言是真的舒服.
pygame介绍
1.创建界面
1 | import sys |
pygame.init() 初始化背景设置 让pygame正常工作
pygame.display.set_mode() 创建一个显示窗口,游戏的所有图形元素都将在其中绘制 (1200,800)是一个元组 宽1200像素 高800像素
赋给self.screen的对象是一个Surface.是屏幕的一部分,用于显示游戏元素
激活游戏的动画循环后,每经过一次循环都将自动重绘这个Surface 将用户输入触发的所有变化都反映出来
run_game()包含一个while循环 监视事件
pygame.event.get()返回一个列表 包含它在上一次被调用发生的所有事件
所有键盘和鼠标事件都将倒是这个for循环进行 如果检查到pygame.QUIT则退出pygame.display.flip()将不断更新屏幕,以显示元素的新位置,并且在原来的位置隐藏元素,从而营造平滑的移动效果1
2
3#设置屏幕背景颜色
self.bg_color = (230,230,230) #rgb三元组
self.screen.fill(self.bg_color)
fill处理Surface,填充颜色
2.创建设置类
1 | class Settings: |
创建setting.py文件 这些变量可用于其他文件访问
这样写从代码上便于分离1
2
3
4
5
6from settings import Settings
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width,self.settings.screen_height)
)
self.screen.fill(self.settings.bg_color)
3.创建飞船类
1 | import pygame |
我们将屏幕和飞船都当作矩形,因为这样处理比较简单
参数有self,ai_game 后者指向当前AlienInvasion实例引用 访问定义中的游戏资源
rect对象有属性x,y,center,centerx,centery,top,bottom等
blit方法将图像self.rect绘制到指定位置
飞船的移动
主要是利用self.ship.rect.x等属性
将run_game()分为两个部分1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32def run_game(self):
'''开始游戏的主循环'''
while True:
# 监视键盘和鼠标事件
self._check_events()
# 更新屏幕
self.ship.update()
self._update_screen()
'''辅助方法'''
def _check_events(self):
'''响应鼠标和键盘事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
# 向右移动飞船
# self.ship.rect.x += 10
self.ship.moving_right = True
# if event.type == pygame.K_LEFT:
# self.ship.rect.x -=10
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
def _update_screen(self):
self.screen.fill(self.settings.bg_color)
# self.screen.fill(self.bg_color)
self.ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
注意event.key这个东西,用来控制飞船的移动
要实现连续移动可以给一个moving_right的flag控制
只要按下就能连续移动
当然,要将这个东西加入while循环监视
加快飞船速度
将速度改为1.5像素 由于rect.x为int值
将改变后的值赋给self.x 再赋值给self.rect.x 只存储整数部分
但问题不大
限制飞船活动范围
主要利用rect.right等限制
rect.right返回距离飞船外接矩形右边缘的x坐标1
2
3
4
5
6
7
8
9def update(self):
'''根据移动标志调整飞船位置'''
if self.moving_right and self.rect.right<self.screen_rect.right:
self.x += self.settings.ship_speed
if self.moving_left and self.rect.left>0:
self.x -= self.settings.ship_speed
# 根据self.x更新rect对象
self.rect.x = self.x
重构事件
1 | def _check_keydown_events(self, event): |
1 | if event.type == pygame.QUIT: |
按Q键退出
1 | def _check_keydown_events(self, event): |
全屏
1 | self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) |
创建子弹类
1 | import pygame |
1 | def _fire_bullet(self): |
删除消失的子弹
子弹没有消除,所以会消耗内存1
2
3for bullet in self.bullets.copy():
if bullet.rect.bottom <=0:
self.bullets.remove(bullet)
使用copy是因为遍历的数组不能变化
限制子弹数量
settings.py设置1
self.bullet_allowed = 3
1
2
3
4
5
6def _fire_bullet(self):
'''创建一颗子弹 将其加入编组中'''
#限制数量 当子弹数量小于限制数量时
if len(self.bullets)<self.settings.bullet_allowed:
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
重构代码
1 | def _updata_bullets(self): |
1 | def run_game(self): |
创建外星人
1 | import pygame |
设置其图像与大小,位置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def _create_fleet(self):
'''创建外星人群'''
alien = Alien(self)
alien_width = alien.rect.width
available_space_x = self.settings.screen_width - (2 * alien_width)
number_aliens_x = available_space_x // (2 * alien_width)
# 创建一行外星人
for alien_number in range(number_aliens_x):
self._create_alien(alien_number)
def _create_alien(self, alien_number):
# 创建一个外星人
alien = Alien(self)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
self.aliens.add(alien)
在__init__中加入1
2self.aliens = pygame.sprite.Group()
self._create_fleet()
同时1
2
3
4
5
6
7
8
9def _update_screen(self):
# self.screen.fill(self.settings.bg_color)
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self.aliens.draw(self.screen)
# 让最近绘制的屏幕可见
pygame.display.flip()
使用sprits.draw方法
重构
1 | def _create_fleet(self): |
让外星人移动
1 | def update(self): |
检查边界 到达边界后向另一个方向走并向下走
1 | def _update_alien(self): |
1 | def update(self): |
射击外星人
设计碰撞
sprits.groupcollide()1
2
3
4
5
6
7
8
9def _updata_bullets(self):
'''更新子弹位置并删除消失子弹'''
self.bullets.update()
# 删除消失的子弹
for bullet in self.bullets.copy():
if bullet.rect.bottom <= 0:
self.bullets.remove(bullet)
self._check_bullet_alien_collisions()1
2
3
4
5
6
7
8
9def _check_bullet_alien_collisions(self):
'''相应子弹和外星人碰撞'''
collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
if not self.aliens:
# 删除现有的所有子弹 并创建外星人
self.bullets.empty()
self._create_fleet()
飞船与ufo相碰撞
1 | def _update_aliens(self): |
1 | class GameStats: |
1 | def center_ship(self): |
碰撞后飞船消失
检查外星人到屏幕底端
1 | def _check_aliens_bottom(self): |
1 | def _update_aliens(self): |
游戏结束
添加一个标志
当数量小于0时设为False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def _ship_hit(self):
'''响应飞船被外星人碰撞'''
# 将left-1
if self.stats.ships_left>0:
self.stats.ships_left -= 1
# 清空余下的外星人和子弹
self.aliens.empty()
self.bullets.empty()
# 创建一群新的外星人 并将飞船放到屏幕的底端
self._create_fleet()
self.ship.center_ship()
# 暂停
sleep(0.5)
else:
self.stats.game_active = False1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def run_game(self):
'''开始游戏的主循环'''
while True:
# 监视键盘和鼠标事件
self._check_events()
# 更新屏幕
if self.stats.game_active:
self.ship.update()
# self.bullets.update()
self._updata_bullets()
self._update_screen()
self._update_aliens()
# for bullet in self.bullets.copy():
# if bullet.rect.bottom <= 0:
# self.bullets.remove(bullet)
先写到这里,后面再补
https://github.com/drowning-in-codes/pygame.git
github地址