pygame 入门实例

mac2022-06-30  81

本文基于win7(64) + py3.5(64)环境。

本文是这里的一篇学习笔记。加入了自己的理解。

本文最终目的是实现一个飞机躲避导弹的游戏。

1、核心概念

pygame 的核心概念有:

Surface 对象(一个容器,一个载体,可以是空白的矩形区域,亦可是图片)Surface 对象的矩形区域(用 Surface 实例的get_rect()方法获得)屏幕对象的blit()方法用于放置 Surface 对象display 模块的flip()方法用于重绘游戏界面窗口主循环 import pygame, sys from pygame.locals import * # 全局常量 # 初始化 pygame.init() # 屏幕对象 screen = pygame.display.set_mode((400,270)) # 尺寸 # Surface对象 surf = pygame.Surface((50,50)) # 长、宽 surf.fill((255,255,255)) # 颜色 # Surface对象的矩形区域 rect = surf.get_rect() # 窗口主循环 while True: # 遍历事件队列 for event in pygame.event.get(): if event.type == QUIT: # 点击右上角的'X',终止主循环 pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: # 按下'ESC'键,终止主循环 pygame.quit() sys.exit() # 放置Surface对象 screen.blit(surf, ((400-50)//2, (270-50)//2)) # 窗口正中 #screen.blit(surf, rect) # surf的左上角 # 重绘界面 pygame.display.flip()

效果图

2、引入精灵

上面的代码很能体现pygame的核心概念,但不利于规模比较大的游戏开发。

为此,就需要继承 Sprite 类,并且设置属性surf为Surface对象。同时设置rect属性。

调用屏幕对象的blit方法时,以精灵实例的surf属性和rect属性为参数。

import pygame, sys from pygame.locals import * import random '''玩家随着方向键运动''' # 玩家 class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.surf = pygame.Surface((75,25)) self.surf.fill((255,255,255)) self.rect = self.surf.get_rect() def update(self, key): # 随着方向键运动 if key[K_UP]: self.rect.move_ip(0,-5) if key[K_DOWN]: self.rect.move_ip(0,5) if key[K_LEFT]: self.rect.move_ip(-5,0) if key[K_RIGHT]: self.rect.move_ip(5,0) # 限定player在屏幕中 if self.rect.left < 0: self.rect.left = 0 elif self.rect.right > 800: self.rect.right = 800 if self.rect.top <= 0: self.rect.top = 0 elif self.rect.bottom >= 600: self.rect.bottom = 600 # 初始化 pygame.init() # 屏幕对象 screen = pygame.display.set_mode((800,600)) # 尺寸 # 玩家精灵对象 player = Player() # 窗口主循环 while True: # 遍历事件队列 for event in pygame.event.get(): if event.type == QUIT: # 点击右上角的'X',终止主循环 pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: # 按下'ESC'键,终止主循环 pygame.quit() sys.exit() # 更新屏幕 screen.fill((0,0,0)) # 获得按键 key = pygame.key.get_pressed() # 更新玩家 player.update(key) # 放置玩家 screen.blit(player.surf, player.rect) # 更新界面 pygame.display.flip()

效果图

3、引入敌人

由于敌人很多,最好的方式是用Group来管理那么多的精灵。

import pygame, sys from pygame.locals import * import random # 玩家 class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.surf = pygame.Surface((75,25)) self.surf.fill((255,255,255)) self.rect = self.surf.get_rect() def update(self, key): if key[K_UP]: self.rect.move_ip(0,-5) if key[K_DOWN]: self.rect.move_ip(0,5) if key[K_LEFT]: self.rect.move_ip(-5,0) if key[K_RIGHT]: self.rect.move_ip(5,0) # 限定player在屏幕中 if self.rect.left < 0: self.rect.left = 0 elif self.rect.right > 800: self.rect.right = 800 if self.rect.top <= 0: self.rect.top = 0 elif self.rect.bottom >= 600: self.rect.bottom = 600 # 敌人 class Enemy(pygame.sprite.Sprite): def __init__(self): super().__init__() self.surf = pygame.Surface((20, 10)) self.surf.fill((255, 255, 255)) self.rect = self.surf.get_rect(center=(820, random.randint(0, 600))) self.speed = random.randint(5, 20) def update(self): self.rect.move_ip(-self.speed, 0) # 从右向左 if self.rect.right < 0: self.kill() # Sprite 的内建方法 # 初始化 pygame.init() # 屏幕对象 screen = pygame.display.set_mode((800,600)) # 尺寸 # 自定义事件 ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都要比 USEREVENT 大 pygame.time.set_timer(ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发 # 玩家 player = Player() # 两个精灵组 enemies = pygame.sprite.Group() all_sprites = pygame.sprite.Group() all_sprites.add(player) # 窗口主循环 while True: # 遍历事件队列 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: pygame.quit() sys.exit() elif event.type == ADDENEMY: # 自定义事件 new_enemy = Enemy() enemies.add(new_enemy) all_sprites.add(new_enemy) # 更新屏幕 screen.fill((0,0,0)) # 更新玩家 key = pygame.key.get_pressed() player.update(key) screen.blit(player.surf, player.rect) # 更新敌人 for enemy in enemies: enemy.update() screen.blit(enemy.surf, enemy.rect) # 碰撞检测(灵魂所在) if pygame.sprite.spritecollideany(player, enemies): player.kill() print('发生碰撞!') # 重绘界面 pygame.display.flip()

效果图

4、使用图片

上面的例子是丑陋的黑白界面,需要进行美化。好的方式是使用图片来代替。可以去网上找素材,也可以自己画。

为了让游戏更好看,增添了云朵精灵。

注意:下面的surf属性用image来代替了。

为方便朋友们测试,下面给出代码中用到的三张图片素材:

import pygame, sys from pygame.locals import * import random '''飞机躲避导弹''' # 玩家 class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load('jet.png').convert() # load函数,返回一个 Surface 对象 self.image.set_colorkey((255,255,255), RLEACCEL) self.rect = self.image.get_rect() def update(self, key): if key[K_UP]: self.rect.move_ip(0,-5) if key[K_DOWN]: self.rect.move_ip(0,5) if key[K_LEFT]: self.rect.move_ip(-5,0) if key[K_RIGHT]: self.rect.move_ip(5,0) # 限定player在屏幕中 if self.rect.left < 0: self.rect.left = 0 elif self.rect.right > 800: self.rect.right = 800 if self.rect.top <= 0: self.rect.top = 0 elif self.rect.bottom >= 600: self.rect.bottom = 600 # 敌人 class Enemy(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load('missile.png').convert() self.image.set_colorkey((255, 255, 255), RLEACCEL) self.rect = self.image.get_rect(center=(820, random.randint(0, 600))) self.speed = random.randint(5, 20) def update(self): self.rect.move_ip(-self.speed, 0) # 从右向左 if self.rect.right < 0: self.kill() # Sprite 的内建方法 # 白云 class Cloud(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load('cloud.png').convert() self.image.set_colorkey((0,0,0),RLEACCEL) self.rect = self.image.get_rect( center = (random.randint(820,900),random.randint(0,600)) ) def update(self): self.rect.move_ip(-5,0) if self.rect.right < 0: self.kill() # 游戏初始化 pygame.init() # 屏幕对象 screen = pygame.display.set_mode((800,600)) # 尺寸 # 背景Surface background = pygame.Surface(screen.get_size()) background.fill((135, 206, 250)) # 浅蓝色 # 两个自定义事件 ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大) pygame.time.set_timer(ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发 ADDCLOUD = pygame.USEREVENT + 2 pygame.time.set_timer(ADDCLOUD, 1000) # 玩家精灵对象 player = Player() # 三个精灵组 enemies = pygame.sprite.Group() clouds = pygame.sprite.Group() all_sprites = pygame.sprite.Group() all_sprites.add(player) # 窗口主循环 while True: # 遍历事件队列 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: pygame.quit() sys.exit() elif event.type == ADDENEMY: # 自定义事件 new_enemy = Enemy() enemies.add(new_enemy) all_sprites.add(new_enemy) elif event.type == ADDCLOUD: # 自定义事件 new_cloud = Cloud() clouds.add(new_cloud) all_sprites.add(new_cloud) # 背景 screen.blit(background, (0, 0)) # 获取按键 key = pygame.key.get_pressed() # 更新精灵(组) player.update(key) enemies.update() clouds.update() # 放置精灵 for sprite in all_sprites: screen.blit(sprite.image, sprite.rect) # 碰撞检测(灵魂所在) if pygame.sprite.spritecollideany(player, enemies): player.kill() #print('发生碰撞!') # 重绘界面 pygame.display.flip()

效果图

全都是类

所有的东西都放到类里面!难道这就是传说中的面向对象编程???

import pygame, sys from pygame.locals import * import random '''飞机躲避导弹''' # 根据概率随机选取 def choice(seq, prob): p = random.random() for i in range(len(seq)): if sum(prob[:i]) < p < sum(prob[:i+1]): return seq[i] # 玩家 class PlayerSprite(pygame.sprite.Sprite): speed = 5 def __init__(self): super().__init__() self.image = pygame.image.load('jet.png').convert() # load函数,返回一个 Surface 对象 self.image.set_colorkey((255,255,255), RLEACCEL) self.rect = self.image.get_rect() def update(self, key): if key[K_UP]: self.rect.move_ip(0, -self.speed) if key[K_DOWN]: self.rect.move_ip(0, self.speed) if key[K_LEFT]: self.rect.move_ip(-self.speed, 0) if key[K_RIGHT]: self.rect.move_ip(self.speed, 0) # 限定player在屏幕中 if self.rect.left < 0: self.rect.left = 0 elif self.rect.right > 800: self.rect.right = 800 if self.rect.top <= 0: self.rect.top = 0 elif self.rect.bottom >= 600: self.rect.bottom = 600 # 敌人 class EnemySprite(pygame.sprite.Sprite): speed = choice([1,3,5], [0.5, 0.4, 0.1]) def __init__(self): super().__init__() self.image = pygame.image.load('missile.png').convert() self.image.set_colorkey((255, 255, 255), RLEACCEL) self.rect = self.image.get_rect(center=(820, random.randint(0, 600))) #self.speed = random.randint(5, 20) def update(self): self.rect.move_ip(-self.speed, 0) # 从右向左 if self.rect.right < 0: self.kill() # Sprite 的内建方法 # 白云 class CloudSprite(pygame.sprite.Sprite): speed = choice([1,2], [0.8, 0.2]) def __init__(self): super().__init__() self.image = pygame.image.load('cloud.png').convert() self.image.set_colorkey((0,0,0),RLEACCEL) self.rect = self.image.get_rect( center = (random.randint(820,900),random.randint(0,600)) ) def update(self): self.rect.move_ip(-self.speed,0) if self.rect.right < 0: self.kill() # 背景 class BackgroundSprite(pygame.sprite.Sprite): def __init__(self, size): super().__init__() self.image = pygame.Surface(size) # 实际上是surf,为了统一写成image self.image.fill((135, 206, 250)) # 浅蓝色 self.rect = pygame.Rect(0, 0, *size) def update(self): pass class Game(): def __init__(self): # 游戏初始化 pygame.init() # 屏幕大小及屏幕对象 self.size = self.width, self.height = 800, 600 self.screen = pygame.display.set_mode(self.size) pygame.display.set_caption("Pygame 2D RPG !") # 两个自定义事件 self.ADDENEMY = pygame.USEREVENT + 1 # 事件本质上就是整数常量。比 USEREVENT 小的数值已经对应内置事件,因此任何自定义事件都必须比 USEREVENT 大) pygame.time.set_timer(self.ADDENEMY, 250) # 每隔 250 毫秒(四分之一秒) 触发 self.ADDCLOUD = pygame.USEREVENT + 2 pygame.time.set_timer(self.ADDCLOUD, 1000) # 两个精灵对象 self.background = BackgroundSprite(self.size) self.player = PlayerSprite() # 三个精灵组 self.enemies = pygame.sprite.Group() self.clouds = pygame.sprite.Group() self.all_sprites = pygame.sprite.Group() self.all_sprites.add(self.player) def run(self): # 窗口主循环 while True: # 遍历事件队列 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: pygame.quit() sys.exit() elif event.type == self.ADDENEMY: # 自定义事件 new_enemy = EnemySprite() self.enemies.add(new_enemy) self.all_sprites.add(new_enemy) elif event.type == self.ADDCLOUD: # 自定义事件 new_cloud = CloudSprite() self.clouds.add(new_cloud) self.all_sprites.add(new_cloud) # 背景 self.screen.blit(self.background.image, self.background.rect) # 获取按键 key = pygame.key.get_pressed() # 更新精灵(组) self.player.update(key) self.enemies.update() self.clouds.update() # 放置精灵 for sprite in self.all_sprites: self.screen.blit(sprite.image, sprite.rect) # 碰撞检测(灵魂所在) if pygame.sprite.spritecollideany(self.player, self.enemies): self.player.kill() print('发生碰撞!') # 重绘界面 pygame.display.flip() if __name__ == '__main__': Game().run()

转载于:https://www.cnblogs.com/hhh5460/p/7029217.html

相关资源:pygame示例代码
最新回复(0)