Pygame是一个利用SDL库的写的游戏库,SDL呢,全名Simple DirectMedia Layer,是一位叫做Sam Lantinga的大牛写的 SDL是用C写的,不过它也可以使用C++进行开发,当然还有很多其它的语言,Pygame就是Python中使用它的一个库
具体教程可参考官网:https://www.pygame.org/docs/
1、pygame安装
安装命令:pip install pygame
提示:如果有多个版本,同时装有python 2.7 和 python3.6时
可以使用 pip3 install pygame
查看已安装的第三方库:pip list 或 pip3 list
(1)本地安装
(2) PyCharm安装
FAQ:PyCharm中安装遇到版本兼容问题:
在安装pygame模块的时候尤其要注意一下:
如果在pychram中安装不成功 如下错误:
EOFError: EOF when reading a line
Command "python setup.py egg_info" failed with error code 1 in C:\Users\Administrator\AppData\Local\Temp\pip-install-392v1at0\pygame\
此时我们就可以换种思路:
1:确保在系统层面的python环境里面 已经安装了pygame[pip install pygame] 一般都可以安装成功
2: 我们就可以把 已经安装好的 pygame 模块的 文件夹拷贝到 pycharm 所创建项目中的venv虚拟环境里面【D:\SoftTools\Python313\Lib\site-packages】
soure path:C:\Users\Administrator\AppData\Local\Programs\Python\Python38-32\Lib\site-packages
dst path: 你的项目路径/venv\Lib\site-packages
1、查找本地安装路径
pip show pygame 命令查看安装路径;本地和PyCharm上都可以操作
2、将本地下载的库直接copy到PyCharm项目中.venv下的Lib文件夹下
一、飞机大战
步骤:
1、创建一个窗口
2、创建一个我方飞机 根据方向键左右的移动
3、给我方飞机添加发射子弹的功能【按下空格键去发送】
4、创建一个敌人飞机
5、敌人飞机可以自由的移动
6、敌人飞机可以自动的发射子弹
1、控制玩具飞机-面向过程
实现控制飞机的步骤如下:
1、载入一张飞机图片并初始飞机图片位置(即设置图片的X、Y坐标)
2、当按键盘的左右键或A、D键时修改X、Y坐标值
3、根据新的坐标值,更新飞机图片的位置
import pygame #引用第三方的模块
import random #随机产生数据的对象
import time
from pygame.locals import *
'''
1: 实现飞机的显示 并且可以控制飞机的移动【面向对象】
'''
class HeroPlane(object):def __init__(self,screen):'''初始化函数:param screen: 主窗体对象'''# 飞机的默认位置self.x=150self.y=450# 设置要显示内容的窗口self.screen=screen# 生成飞机的图片对象self.imageName='./feiji/hero.png'self.image=pygame.image.load(self.imageName)# 用来存放子弹的列表self.bulletList=[]passdef moveleft(self):'''左移动:return:'''if self.x>0:self.x-=10passdef moveright(self):'''右移动:return:'''if self.x<350-40:self.x+=10passdef display(self):'''在主窗口中显示飞机:return:'''self.screen.blit(self.image,(self.x,self.y))# 完善子弹的展示逻辑needDelItemList=[]for item in self.bulletList:if item.judge():needDelItemList.append(item)passpass# 重新遍历一下for i in needDelItemList:self.bulletList.remove(i)passfor bullet in self.bulletList:bullet.display() # 显示子弹的位置bullet.move()#让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置pass# 发射子弹def sheBullet(self):# 创建一个新的子弹对象newBullet=Bullet(self.x,self.y,self.screen)self.bulletList.append(newBullet)passpass'''创建子弹类
'''
class Bullet(object):def __init__(self,x,y,screen):''':param x::param y::param screen:'''self.x=x+13self.y=y-20self.screen=screenself.imgage=pygame.image.load('./feiji/bullet.png')passdef display(self):self.screen.blit(self.imgage,(self.x,self.y))passdef move(self):self.y-=2passdef judge(self):'''判断子弹是否越界:return:'''if self.y<0:return Trueelse:return Falsepasspass# 创建敌机类
class EnemyPlane:def __init__(self,screen):# 默认设置一个方向self.direction='right'# 飞机的默认位置self.x = 0self.y = 0# 设置要显示内容的窗口self.screen = screenself.bulletList=[]# 生成飞机的图片对象self.imageName = './feiji/enemy0.png'self.image = pygame.image.load(self.imageName)passdef display(self):'''显示敌机以及位置子弹的信息:return:'''self.screen.blit(self.image,(self.x,self.y))# 完善子弹的展示逻辑needDelItemList = []for item in self.bulletList:if item.judge():needDelItemList.append(item)passpass# 重新遍历一下for i in needDelItemList:self.bulletList.remove(i)passfor bullet in self.bulletList:bullet.display() # 显示子弹的位置bullet.move() # 让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置passpassdef sheBullet(self):'''敌机随机的发射子弹:return:'''num=random.randint(1,50)if num==3:newBullet=EnemyBullet(self.x,self.y,self.screen)self.bulletList.append(newBullet)passdef move(self):'''敌机移动 随机进行的:return:'''if self.direction=='right':self.x+=2passelif self.direction=='left':self.x-=2passif self.x>350-20:self.direction='left'passelif self.x<0:self.direction='right'passpass#敌机的子弹类
class EnemyBullet(object):def __init__(self,x,y,screen):''':param x::param y::param screen:'''self.x=xself.y=y+10self.screen=screenself.imgage=pygame.image.load('./feiji/bullet1.png')passdef display(self):self.screen.blit(self.imgage,(self.x,self.y))passdef move(self):self.y+=2passdef judge(self):'''判断子弹是否越界:return:'''if self.y>500:return Trueelse:return Falsepasspassdef key_control(HeroObj):'''定义普通的函数 用来实现键盘的检测:param HeroObj: 可控制检测的对象:return:'''eventList = pygame.event.get()for event in eventList:if event.type == QUIT:print('退出')exit()passelif event.type == KEYDOWN:if event.type == K_a or event.key == K_LEFT:print('left')HeroObj.moveleft() #调用函数实现左移动passelif event.type == K_d or event.key == K_RIGHT:print('right')HeroObj.moveright() #调用函数实现右移动passelif event.key == K_SPACE:print('按下了空格键 space 发射子弹')HeroObj.sheBullet()passdef main():#首先创建一个窗口 用来显示内容screen=pygame.display.set_mode((350,500),depth=32)# 创建一个背景图片对象background=pygame.image.load('./feiji/background.png')# 设置一个titlepygame.display.set_caption('飞机大战')# 添加背景音乐pygame.mixer.init()pygame.mixer.music.load('./feiji/background.mp3')pygame.mixer.music.set_volume(0.2)pygame.mixer.music.play(-1) #循环次数 -1表示无限循环# 创建一个飞机对象了hero=HeroPlane(screen)# 创建一个敌人飞机的对象enemyplane=EnemyPlane(screen)# 设定要显示的内容while True:screen.blit(background,(0,0))# 显示玩家飞机的图片hero.display()enemyplane.display() #显示敌机enemyplane.move() #敌机移动enemyplane.sheBullet()#敌机随机发送子弹# 获取键盘事件key_control(hero)# 更新显示内容pygame.display.update()# time.sleep(1) #休眠一秒钟pygame.time.Clock().tick(15)passif __name__=='__main__':main()
2、控制玩具飞机-面向对象
实现步骤原理跟面向过程是一样的,不同的时,代码的组织方式不一样:
1、创建一个飞机类,实现左移、右移、显示三个功能
2、创建一个键盘控制函数,实现键盘的左、右、空格键的功能
3、创建主函数,实现创建窗口、背景图片、背景音乐、并实现所有的逻辑
3、玩家飞机发射子弹
1、每次按回车就会有一颗子弹射出,起始位置就是从飞机的停靠位置
2、子弹超出窗口就消失,并且删除掉子弹(否则子弹越来越多,界面会越来越卡)
3、每一颗子弹就代表着一张图片
4、子弹会从发射开始,慢慢的往上移动,直到消失
优化版:
import pygame #引用第三方的模块
import random #随机产生数据的对象
import time
from pygame.locals import *
'''
1: 实现飞机的显示 并且可以控制飞机的移动【面向对象】
'''
#抽象出来一个飞机的基类
class BasePlane(object):def __init__(self,screen,imagePath):'''初始化基类函数:param screen: z主窗体对象:param imageName:加载的图片'''self.screen=screenself.image=pygame.image.load(imagePath)self.bulletList=[] #存储所有的子弹passdef display(self):self.screen.blit(self.image, (self.x, self.y))# 完善子弹的展示逻辑needDelItemList = []for item in self.bulletList:if item.judge():needDelItemList.append(item)passpass# 重新遍历一下for i in needDelItemList:self.bulletList.remove(i)passfor bullet in self.bulletList:bullet.display() # 显示子弹的位置bullet.move() # 让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置passpassclass CommonBullet(object):'''公共的子弹类'''def __init__(self,x,y,screen,bulletType):self.type=bulletTypeself.screen=screenif self.type=='hero':self.x=x+13self.y=y-20self.imagePath='./feiji/bullet.png'elif self.type == 'enemy':self.x = xself.y =y+10self.imagePath = './feiji/bullet1.png'passself.image=pygame.image.load(self.imagePath)passdef move(self):'''子弹的移动:return:'''if self.type=='hero':self.y-=2elif self.type=='enemy':self.y+=2passdef display(self):self.screen.blit(self.image,(self.x,self.y))passdef judge(self):'''判断子弹是否越界:return:'''if self.y>500 or self.y<0:return Trueelse:return Falsepasspassclass HeroPlane(BasePlane):def __init__(self,screen):'''初始化函数:param screen: 主窗体对象'''super().__init__(screen,'./feiji/hero.png') #调用父类的构造方法# 飞机的默认位置self.x=150self.y=450passdef moveleft(self):'''左移动:return:'''if self.x>0:self.x-=10passdef moveright(self):'''右移动:return:'''if self.x<350-40:self.x+=10pass# 发射子弹def sheBullet(self):# 创建一个新的子弹对象newBullet=CommonBullet(self.x,self.y,self.screen,'hero')self.bulletList.append(newBullet)passpass# 创建敌机类
class EnemyPlane(BasePlane):def __init__(self,screen):super().__init__(screen,'./feiji/enemy0.png')# 默认设置一个方向self.direction='right'# 飞机的默认位置self.x = 0self.y = 0passdef sheBullet(self):'''敌机随机的发射子弹:return:'''num=random.randint(1,50)if num==3:newBullet=CommonBullet(self.x,self.y,self.screen,'enemy')self.bulletList.append(newBullet)passdef move(self):'''敌机移动 随机进行的:return:'''if self.direction=='right':self.x+=2passelif self.direction=='left':self.x-=2passif self.x>350-20:self.direction='left'passelif self.x<0:self.direction='right'passpassdef key_control(HeroObj):'''定义普通的函数 用来实现键盘的检测:param HeroObj: 可控制检测的对象:return:'''eventList = pygame.event.get()for event in eventList:if event.type == QUIT:print('退出')exit()passelif event.type == KEYDOWN:if event.type == K_a or event.key == K_LEFT:print('left')HeroObj.moveleft() #调用函数实现左移动passelif event.type == K_d or event.key == K_RIGHT:print('right')HeroObj.moveright() #调用函数实现右移动passelif event.key == K_SPACE:print('按下了空格键 space 发射子弹')HeroObj.sheBullet()passdef main():#首先创建一个窗口 用来显示内容screen=pygame.display.set_mode((350,500),depth=32)# 创建一个背景图片对象background=pygame.image.load('./feiji/background.png')# 设置一个titlepygame.display.set_caption('飞机大战')# 添加背景音乐pygame.mixer.init()pygame.mixer.music.load('./feiji/background.mp3')pygame.mixer.music.set_volume(0.2)pygame.mixer.music.play(-1) #循环次数 -1表示无限循环# 创建一个飞机对象了hero=HeroPlane(screen)# 创建一个敌人飞机的对象enemyplane=EnemyPlane(screen)# 设定要显示的内容while True:screen.blit(background,(0,0))# 显示玩家飞机的图片hero.display()enemyplane.display() #显示敌机enemyplane.move() #敌机移动enemyplane.sheBullet()#敌机随机发送子弹# 获取键盘事件key_control(hero)# 更新显示内容pygame.display.update()# time.sleep(1) #休眠一秒钟pygame.time.Clock().tick(15)passif __name__=='__main__':main()
运行结果:
二、数字华容道
以 Python 语言为例,如果我们想用通义灵码开发“数字华容道”这个小游戏,你可以对它说:
帮我用pygame创建一个数字华容道小游戏,控制面板上显示正方形棋盘格。
每局游戏开始通过“游戏开始”的按钮显示,当用户点击该按钮时,游戏才会开始。
每局游戏限时3分钟,面板上显示倒计时,时间到未通过显示“游戏失败”提示。
数字移动通过键盘控制,使用上下左右箭头键分别控制数字向上、向下、向左、向右移动。
代码如下:
import pygame
import random
import time'''
首先确保你已经安装了 pygame 库。如果没有安装,可以使用以下命令进行安装:
pip install pygame
''''''
代码说明
初始化:初始化 pygame 并设置窗口大小。
颜色和字体:定义了一些常用的颜色和字体。
棋盘生成:生成一个随机的初始棋盘。
查找空白位置:找到棋盘上的空白位置。
移动数字:根据键盘输入移动数字。
检查胜利条件:检查当前棋盘是否符合胜利条件。
绘制棋盘:绘制棋盘和数字。
绘制按钮:绘制“游戏开始”按钮。
开始游戏:设置游戏开始状态并生成新的棋盘。
主循环:处理事件、更新游戏状态和绘制界面。
'''# 初始化pygame
pygame.init()# 设置窗口大小
WIDTH, HEIGHT = 400, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("数字华容道")# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)# 字体设置
font = pygame.font.SysFont(None, 48)# 棋盘大小
BOARD_SIZE = 4
TILE_SIZE = WIDTH // BOARD_SIZE# 游戏状态
GAME_STARTED = False
GAME_OVER = False
TIME_LIMIT = 180 # 3分钟# 生成初始棋盘
def generate_board():board = list(range(1, BOARD_SIZE * BOARD_SIZE)) + [0]random.shuffle(board)return [board[i:i+BOARD_SIZE] for i in range(0, len(board), BOARD_SIZE)]# 查找空白位置
def find_blank(board):for i in range(BOARD_SIZE):for j in range(BOARD_SIZE):if board[i][j] == 0:return i, j# 移动数字
def move(board, direction):x, y = find_blank(board)if direction == 'UP' and x > 0:board[x][y], board[x-1][y] = board[x-1][y], board[x][y]elif direction == 'DOWN' and x < BOARD_SIZE - 1:board[x][y], board[x+1][y] = board[x+1][y], board[x][y]elif direction == 'LEFT' and y > 0:board[x][y], board[x][y-1] = board[x][y-1], board[x][y]elif direction == 'RIGHT' and y < BOARD_SIZE - 1:board[x][y], board[x][y+1] = board[x][y+1], board[x][y]# 检查游戏是否胜利
def is_win(board):flat_board = [num for row in board for num in row]return flat_board[:-1] == list(range(1, BOARD_SIZE * BOARD_SIZE))# 绘制棋盘
def draw_board(board):screen.fill(WHITE)for i in range(BOARD_SIZE):for j in range(BOARD_SIZE):if board[i][j] != 0:pygame.draw.rect(screen, BLUE, (j * TILE_SIZE, i * TILE_SIZE, TILE_SIZE, TILE_SIZE))text = font.render(str(board[i][j]), True, WHITE)screen.blit(text, (j * TILE_SIZE + TILE_SIZE // 2 - text.get_width() // 2, i * TILE_SIZE + TILE_SIZE // 2 - text.get_height() // 2))else:pygame.draw.rect(screen, BLACK, (j * TILE_SIZE, i * TILE_SIZE, TILE_SIZE, TILE_SIZE))# 绘制按钮
def draw_button(text, x, y, w, h, color, hover_color, action=None):mouse = pygame.mouse.get_pos()click = pygame.mouse.get_pressed()if x + w > mouse[0] > x and y + h > mouse[1] > y:pygame.draw.rect(screen, hover_color, (x, y, w, h))if click[0] == 1 and action is not None:action()else:pygame.draw.rect(screen, color, (x, y, w, h))text_surf = font.render(text, True, WHITE)screen.blit(text_surf, (x + w // 2 - text_surf.get_width() // 2, y + h // 2 - text_surf.get_height() // 2))# 开始游戏
def start_game():global GAME_STARTED, GAME_OVER, start_time, boardGAME_STARTED = TrueGAME_OVER = Falsestart_time = time.time()board = generate_board()# 主循环
def main():global GAME_STARTED, GAME_OVER, start_time, boardclock = pygame.time.Clock()start_time = 0board = []while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()returnelif event.type == pygame.KEYDOWN and GAME_STARTED and not GAME_OVER:if event.key == pygame.K_UP:move(board, 'UP')elif event.key == pygame.K_DOWN:move(board, 'DOWN')elif event.key == pygame.K_LEFT:move(board, 'LEFT')elif event.key == pygame.K_RIGHT:move(board, 'RIGHT')if GAME_STARTED and not GAME_OVER:current_time = time.time()elapsed_time = int(current_time - start_time)remaining_time = max(TIME_LIMIT - elapsed_time, 0)if remaining_time <= 0:GAME_OVER = TrueGAME_STARTED = Falseif is_win(board):GAME_OVER = TrueGAME_STARTED = Falsescreen.fill(WHITE)if not GAME_STARTED:draw_button("游戏开始", WIDTH // 2 - 100, HEIGHT // 2 - 25, 200, 50, GREEN, RED, start_game)else:draw_board(board)time_text = font.render(f"剩余时间: {remaining_time}秒", True, BLACK)screen.blit(time_text, (10, HEIGHT - 50))if GAME_OVER:if is_win(board):game_over_text = font.render("恭喜你,游戏胜利!", True, GREEN)else:game_over_text = font.render("时间到,游戏失败!", True, RED)screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - game_over_text.get_height() // 2))pygame.display.flip()clock.tick(60)if __name__ == "__main__":main()
运行结果如下:
可参考:
就3步,用通义灵码写一个数字华容道小游戏