1.首选对于游戏的设计,需要安装pygame模块,至于怎么去安装点击这里这里会有具体的安装教程,实在不会,再自行百度,总能找到办法。
2.其次这个游戏还要用到random的随机函数,便于设置游戏里的障碍物出现的时机就是随机的,对于图片的选取,自己到网上找,然后调好分辨率,才能在画面中找到。
3.pygame模块
image.load()加载图片
display.set_mode()创建窗口
pygame.event.get()获取单击事件
pygame.MOUSEBUTTONUP鼠标事件
pygame.sprite.collide_rect()判断矩形的碰撞
pygame.mixer.Sound()加载音乐
pygame.mouse.get_pos()获取鼠标坐标
pygame.Rect()创建矩形
4.具体代码
import pygame
from pygame.locals import *
import sys
from itertools import cycle
import random
SCREENWIDTH = 822
SCREENHEIGHT = 199
FPS=30
# 定义一个地图类
class MyMap():
def __init__(self, x, y):
self.bg = pygame.image.load("marie_adventure/image/bg.png").convert_alpha()
self.x = x
self.y = y
def map_rolling(self):
if self.x<-790:
self.x=800
else:
self.x-=5
def map_update(self):
SCREEN.blit(self.bg, (self.x, self.y))
# 玛丽类
class Marie():
def __init__(self):
# 初始化玛丽矩阵
self.rect = pygame.Rect(0, 0, 0, 0)
self.jumpState = False # 跳跃的状态
self.jumpHeight = 130 # 跳跃的高度
self.lowest_y = 140 # 最低坐标
self.jumpValue = 0 # 跳跃增变量
# 加载动图索引
self.marieIndex = 0
self.marieIndexGen = cycle([0, 1, 2])
# 增加玛丽照片
self.adventure_img = (
pygame.image.load("marie_adventure/image/adventure2.png").convert_alpha(),
pygame.image.load("marie_adventure/image/adventure2.png").convert_alpha(),
pygame.image.load("marie_adventure/image/adventure2.png").convert_alpha(),
)
# self.jump_audio = pygame.mixer.Sound("") # 跳音效
self.rect.size = self.adventure_img[0].get_size()
self.x = 50
self.y = self.lowest_y
self.rect.topleft = (self.x, self.y)
def jump(self):
self.jumpState = True
# 小玛丽移动的方法
def move(self):
if self.jumpState: # 当起跳的时候
if self.rect.y >= self.lowest_y:
self.jumpValue = -5
if self.rect.y <= self.lowest_y-self.jumpHeight:
self.jumpValue = 5
self.rect.y += self.jumpValue
if self.rect.y >=self.lowest_y:
self.jumpState = False
# 绘制小玛丽
def draw_marie(self):
# 匹配小玛丽动图
marieIndex = next(self.marieIndexGen)
# 绘制小玛丽
SCREEN.blit(self.adventure_img[marieIndex],
(self.x, self.rect.y))
# 障碍物类
class Obstacle():
score = 1 # 分数
move = 5 # 移动距离
obstacle_y = 150 # 障碍物的y坐标
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.missile = pygame.image.load('marie_adventure/image/missile.png').convert_alpha()
self.pipe = pygame.image.load('marie_adventure/image/pipe.png').convert_alpha()
# 加载分数图片
self.numbers = (pygame.image.load('marie_adventure/image/0.png').convert_alpha(),
pygame.image.load('marie_adventure/image/1.png').convert_alpha(),
pygame.image.load('marie_adventure/image/2.png').convert_alpha(),
pygame.image.load('marie_adventure/image/3.png').convert_alpha(),
pygame.image.load('marie_adventure/image/4.png').convert_alpha(),
pygame.image.load('marie_adventure/image/5.png').convert_alpha(),
pygame.image.load('marie_adventure/image/6.png').convert_alpha(),
pygame.image.load('marie_adventure/image/7.png').convert_alpha(),
pygame.image.load('marie_adventure/image/8.png').convert_alpha(),
pygame.image.load('marie_adventure/image/9.png').convert_alpha()
)
# 加载加分音效
self.score_audio = pygame.mixer.Sound('marie_adventure/audio/score.wav') # 加分
# 0和1随机数
r = random.randint(0, 1)
if r == 0: # 如果随机数为0显示导弹障碍物,相反显示管道
self.image = self.missile # 显示导弹障碍
self.move = 15 # 移动速度加快
self.obstacle_y = 100 # 导弹坐标在天上
else:
self.image = self.pipe # 显示管道障碍
# 根据障碍物位图的宽、高来设置矩形
self.rect.size = self.image.get_size()
# 获取位图宽高
self.width, self.height = self.rect.size
# 障碍物绘制坐标
self.x = 800
self.y = self.obstacle_y
self.rect.center = (self.x, self.y)
# 障碍物移动
def obstacle_move(self):
self.rect.x -= self.move
# 绘制障碍物
def draw_obstacle(self):
SCREEN.blit(self.image, (self.rect.x, self.rect.y))
# 获取分数
def getScore(self):
self.score
tmp = self.score;
if tmp == 1:
self.score_audio.play() # 播放加分音乐
self.score = 0;
return tmp;
# 显示分数
def showScore(self, score):
# 获取得分数字
self.scoreDigits = [int(x) for x in list(str(score))]
totalWidth = 0 # 要显示的所有数字的总宽度
for digit in self.scoreDigits:
# 获取积分图片的宽度
totalWidth +=self.numbers[digit].get_width()
# 分数横向位置
Xoffset = (SCREENWIDTH - (totalWidth+30))
for digit in self.scoreDigits:
# 绘制分数
SCREEN.blit(self.numbers[digit], (Xoffset, SCREENHEIGHT * 0.1))
# 随着数字增加改变位置
Xoffset += self.numbers[digit].get_width()
# 背景音乐按钮
class Music_Botton():
is_open = True # 背景音乐的标记
def __init__(self):
self.open_img = pygame.image.load('marie_adventure/image/btn_open.png').convert_alpha()
self.close_img = pygame.image.load('marie_adventure/image/btn_close.png').convert_alpha()
self.bg_music = pygame.mixer.Sound('marie_adventure/audio/bg_music.wav') # 加载背景音乐
# 判断鼠标是否在按钮的范围
def is_select(self):
# 获取鼠标坐标
point_x, point_y = pygame.mouse.get_pos()
w, h = self.open_img.get_size() # 获取按钮图片的大小
# 判断鼠标是否在按钮范围内
in_x = point_x > 20 and point_x < 20 + w
in_y = point_y >20 and point_y < 20 + h
return in_x and in_y
# 游戏结束的函数
def game_over():
bump_audio = pygame.mixer.Sound('') # 撞击
bump_audio.play() # 播放撞击音效
# 获取窗体宽、高
screen_w = pygame.display.Info().current_w
screen_h = pygame.display.Info().current_h
# 加载游戏结束图片
over_img = pygame.image.load('marie_adventure/image/gameover.png').convert_alpha()
# 将游戏结束的图片绘制在窗体的中间位置
SCREEN.blit(over_img, ((screen_w - over_img.get_width())/2, (screen_h - over_img.get_height())/2))
def mainGame():
score = 0
over = False
global SCREEN, FPSCLOCK
pygame.init()
FPSCLOCK=pygame.time.Clock()
SCREEN=pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
pygame.display.set_caption('玛丽冒险')
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(800, 0)
# 创建小玛丽对象
marie = Marie()
addObstacleTimer = 0 # 添加障碍物的时间
list = [] # 障碍物对象列表
music_button = Music_Botton() # 创建背景音乐按钮对象
btn_img = music_button.open_img # 设置背景音乐按钮的默认图片
music_button.bg_music.play(-1) # 循环播放背景音乐
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# 单击键盘空格键,开启跳的状态
if event.type == KEYDOWN and event.key == K_SPACE:
if marie.rect.y >=marie.lowest_y: # 如果小玛丽在地面上
# marie.jump_audio.play() # 播放小马里跳跃音效
marie.jump() # 开启小玛丽跳跃状态
if over == True:
mainGame()
if event.type == pygame.MOUSEBUTTONUP: # 判断鼠标事件
if music_button.is_select(): # 判断鼠标是否在静音按钮范围内
if music_button.is_open: # 判断背景音乐状态
btn_img = music_button.close_img # 单击后显示关闭状态的图片
music_button.is_open = False # 关闭背景音乐状态
music_button.bg_music.stop() # 停止背景音乐的播放
else:
btn_img = music_button.open_img
music_button.is_open = True
music_button.bg_music.play(-1)
# 判断没有结束的情况下
if over == False:
# 绘制地图起到更新作用
bg1.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_update()
bg2.map_rolling()
# 小玛丽的移动
marie.move()
# 绘制小玛丽
marie.draw_marie()
# 计算障碍物的间隔时间
if addObstacleTimer >= 1300:
r = random.randint(0, 100)
if r > 40:
# 创建障碍物对象
obstacle = Obstacle()
# 将障碍物对象添加到列表中
list.append(obstacle)
# 重置添加障碍物时间
addObstacleTimer = 0
# 循环遍历障碍物
for i in range(len(list)):
# 障碍物移动
list[i].obstacle_move()
# 绘制障碍物
list[i].draw_obstacle()
# 判断小玛丽与障碍物是否碰撞
if pygame.sprite.collide_rect(marie, list[i]):
over = True # 碰撞后开启结束开关
game_over() # 调用游戏结束的方法
music_button.bg_music.stop() # 停止播放背景音乐
else:
# 判断小玛丽是否越过了障碍物
if(list[i].rect.x + list[i].rect.width) < marie.rect.x:
# 加分
score += list[i].getScore()
# 显示分数
list[i].showScore(score)
addObstacleTimer += 20
SCREEN.blit(btn_img, (20, 20)) # 绘制背景音乐按钮
pygame.display.update() # 更新整个窗体
FPSCLOCK.tick(FPS) # 循环应该多长时间运行一次
if __name__=='__main__':
mainGame()
代码就在上面有点小长,一个小小的游戏代码就有这么多,对于里面还有碰撞的音效我没有加上去,是在不想找那个音效了,太难了。。。。
5.具体步骤
(1)首先是游戏窗体的实现,利用的是pygame模块中的init()方法,实现初始化功能,接下来要实现创建循环update()函数不断更新窗体,最后需要判断用户是否单击关闭了窗体的按钮,如果单击“关闭”按钮,将关闭窗体,否则继续循环显示窗体。当中会有个Global
(2)对于地图的加载,实现图片的无限循环,无限滚动,听起来就很神奇。对于人物的跳跃状态,判断是否按了《space》(空格)键,如果按下了就开启玛丽的跳跃开关,如果按下了就开启玛丽的跳跃开关,让玛丽以5个像素的距离向上移动,当玛丽到达窗体顶部的边缘时,再让玛丽以5个像素的距离向下移动,回到地面后关闭跳跃的开关。创建个jump()的方法,通过该方法实现跳跃的开关。
(3)随机出现的障碍
导入随机数,创建一个名称为Obstacle的障碍物类,在该类中定义一个分数,然后在初始化方法中加载障碍物图片、分数图片以及加分音效。创建0~1的随机数字,根据 该数字抽选障碍物是管道还是飞行的导弹,最后根据图片的高宽创建障碍物矩形大小并设置障碍物的绘制坐标。然后在障碍物类里创建移动障碍物的方法,用于实现绘制障碍物。
在主函数中绘制计算障碍物出现的间隔时间,同时计算循环遍历障碍物,并进行障碍物的绘制,然后更新整个窗体代码上面,增加障碍物的时间。
(4)然后对背景音乐的播放与停止
我们的方法是具体实现一个按钮,通过点击按钮来实现音乐的播放与停止,这就涉及到一个鼠标的时间,当用鼠标点击这个事件,来判断这个是否发生,在根据这个判断来执行下一步操作。
(5)碰撞和积分的实现
首先要判断两个对象是否发生了碰撞,首先获取两个图片的高宽,当高宽有重合的时候,就说明发生了碰撞,同时要设置,如果发生了碰撞,就要设置一个结束标语,来结束这个程序,不然就只能死循环,卡在这个界面,俗话说的好:有始就有终,所以不能光开着不关着,浪费资源。