|
|
# coding: utf-8
|
|
|
# 滑雪小游戏
|
|
|
import sys
|
|
|
import pygame
|
|
|
import random
|
|
|
from pygame.locals import *
|
|
|
|
|
|
|
|
|
# 滑雪者类
|
|
|
class SkierClass(pygame.sprite.Sprite):
|
|
|
def __init__(self): import pygame, sys, random
|
|
|
|
|
|
|
|
|
skier_images = ["skier_down.png", "skier_right1.png", "skier_right2.png",
|
|
|
"skier_left2.png", "skier_left1.png"]
|
|
|
|
|
|
|
|
|
class SkierClass(pygame.sprite.Sprite): # 创建滑雪者
|
|
|
def __init__(self):
|
|
|
pygame.sprite.Sprite.__init__(self) # 基类的init方法
|
|
|
self.image = pygame.image.load("skier_crash.png") # 这个是滑雪者的美照。
|
|
|
self.rect = self.image.get_rect() # 用于获得Image的矩形大小
|
|
|
self.rect.center = [320, 100] # 指定矩形的中心位置
|
|
|
self.angle = 0
|
|
|
|
|
|
def turn(self, direction): # 滑雪者 转向函数 其中的direction参数是指定滑雪者移动的方向和程度(点击两次右键比一次右键滑动的幅度要大,一会自己试着运行一下试试。)
|
|
|
self.angle = self.angle + direction # 滑雪者当前的移动速度
|
|
|
if self.angle < -2: self.angle = -2 # 用于将滑雪者的移动方式固定到这五个方式当中
|
|
|
if self.angle > 2: self.angle = 2
|
|
|
center = self.rect.center
|
|
|
self.image = pygame.image.load(skier_images[self.angle]) # 这个时候滑雪者应该有的姿态图片。
|
|
|
self.rect = self.image.get_rect()
|
|
|
self.rect.center = center
|
|
|
speed = [self.angle, 6 - abs(self.angle) * 2] # 滑雪者的速度。
|
|
|
return speed
|
|
|
|
|
|
def move(self, speed): # 滑雪者左右移动
|
|
|
self.rect.centerx = self.rect.centerx + speed[0] # 滑雪者所在位置
|
|
|
if self.rect.centerx < 20: self.rect.centerx = 20 # 滑雪者所在位置不应该超过的最大最小值。
|
|
|
if self.rect.centerx > 620: self.rect.centerx = 620
|
|
|
|
|
|
|
|
|
class ObstacleClass(pygame.sprite.Sprite): # 创建树和小旗
|
|
|
def __init__(self, image_file, location, type):
|
|
|
pygame.sprite.Sprite.__init__(self)
|
|
|
self.image_file = image_file # image_file可能是树或者小旗
|
|
|
self.image = pygame.image.load(image_file) # 载入当前的图片
|
|
|
self.location = location
|
|
|
self.rect = self.image.get_rect()
|
|
|
self.rect.center = location
|
|
|
self.type = type
|
|
|
self.passed = False
|
|
|
|
|
|
def scroll(self, terrainPos): # 场景上滚,造成下滑假象。
|
|
|
self.rect.centery = self.location[1] - terrainPos
|
|
|
|
|
|
|
|
|
def create_map(start, end): # 创建一个窗口,包含随机的树和小旗
|
|
|
obstacles = pygame.sprite.Group() # 创建独立运动的组织
|
|
|
locations = []
|
|
|
gates = pygame.sprite.Group()
|
|
|
for i in range(10):
|
|
|
row = random.randint(start, end) # 获得随机数在 start-end之间
|
|
|
col = random.randint(0, 9)
|
|
|
location = [col * 64 + 20, row * 64 + 20] # 确定所在位置
|
|
|
if not (location in locations): # 如果上面定义的物体不在已经确定属性(位置等参数)的物体里面。
|
|
|
locations.append(location)
|
|
|
type = random.choice(["tree", "flag"]) # 随机选择是树还是小旗
|
|
|
if type == "tree":
|
|
|
img = "skier_tree.png" # 选择相应的图片
|
|
|
elif type == "flag":
|
|
|
img = "skier_flag.png"
|
|
|
obstacle = ObstacleClass(img, location, type) # 将上面的形成的物体添加到游戏
|
|
|
obstacles.add(obstacle)
|
|
|
return obstacles
|
|
|
|
|
|
|
|
|
def animate(): # 如果发生移动就重新绘制屏幕
|
|
|
screen.fill([255, 255, 255]) # 指定背景颜色 (RGB)
|
|
|
pygame.display.update(obstacles.draw(screen))
|
|
|
screen.blit(skier.image, skier.rect) # 用于绘制位图 在屏幕的skier.rect位置绘制skier.image
|
|
|
screen.blit(score_text, [10, 10])
|
|
|
pygame.display.flip()
|
|
|
|
|
|
|
|
|
def updateObstacleGroup(map0, map1): # 切换到场景的下一屏
|
|
|
obstacles = pygame.sprite.Group()
|
|
|
for ob in map0: obstacles.add(ob)
|
|
|
for ob in map1: obstacles.add(ob)
|
|
|
return obstacles
|
|
|
|
|
|
pygame.init() # 初始化pygame的所有模块
|
|
|
def Show_Start_Interface(Demo, width, height,con1,con2):
|
|
|
Demo.fill((255, 255, 255))
|
|
|
tfont = pygame.font.Font('./font.ttf', 100)
|
|
|
cfont = pygame.font.Font('./font.ttf',50 )
|
|
|
title = tfont.render(con1, True, (255, 0, 0))
|
|
|
content = cfont.render(con2, True, (0, 0, 255))
|
|
|
trect = title.get_rect()
|
|
|
trect.midtop = (width / 2, height / 10)
|
|
|
crect = content.get_rect()
|
|
|
crect.midtop = (width / 3, height / 2.2)
|
|
|
Demo.blit(title, trect)
|
|
|
Demo.blit(content, crect)
|
|
|
pygame.display.update()
|
|
|
while True:
|
|
|
for event in pygame.event.get():
|
|
|
if event.type == pygame.QUIT:
|
|
|
sys.exit()
|
|
|
elif event.type == pygame.KEYDOWN:
|
|
|
return
|
|
|
|
|
|
|
|
|
Demo = pygame.display.set_mode((900, 900))
|
|
|
|
|
|
Show_Start_Interface(Demo, 900, 900,"滑雪游戏",'按任意键开始')
|
|
|
|
|
|
|
|
|
screen = pygame.display.set_mode([900, 900]) # 用于初始化窗口,其中的参数就是分辨率
|
|
|
clock = pygame.time.Clock() # 载入监听时间的模块 clock在下面还可以看到 clock.tick等方法
|
|
|
skier = SkierClass() # 初始化SkierClass对象
|
|
|
speed = [0, 6]
|
|
|
map_position = 0
|
|
|
points = 0
|
|
|
map0 = create_map(20, 29)
|
|
|
map1 = create_map(10, 19)
|
|
|
activeMap = 0
|
|
|
|
|
|
obstacles = updateObstacleGroup(map0, map1)
|
|
|
|
|
|
font = pygame.font.Font(None, 50)
|
|
|
|
|
|
while True:
|
|
|
clock.tick(100) # 每秒更新30次图形 ---这就是帧率。
|
|
|
for event in pygame.event.get(): # 检查按键或者窗口是否关闭
|
|
|
if event.type == pygame.QUIT: sys.exit()
|
|
|
if event.type == pygame.KEYDOWN:
|
|
|
if event.key == pygame.K_LEFT:
|
|
|
speed = skier.turn(-1)
|
|
|
elif event.key == pygame.K_RIGHT:
|
|
|
speed = skier.turn(1)
|
|
|
skier.move(speed) # 移动滑雪者
|
|
|
map_position += speed[1] # 滚动场景
|
|
|
|
|
|
if map_position >= 640 and activeMap == 0: # 从场景的一个窗口切换到下一个窗口
|
|
|
activeMap = 1
|
|
|
map0 = create_map(20, 29)
|
|
|
obstacles = updateObstacleGroup(map0, map1)
|
|
|
if map_position >= 1280 and activeMap == 1:
|
|
|
activeMap = 0
|
|
|
for ob in map0:
|
|
|
ob.location[1] = ob.location[1] - 1280
|
|
|
map_position = map_position - 1280
|
|
|
map1 = create_map(10, 19)
|
|
|
obstacles = updateObstacleGroup(map0, map1)
|
|
|
|
|
|
for obstacle in obstacles:
|
|
|
obstacle.scroll(map_position)
|
|
|
|
|
|
hit = pygame.sprite.spritecollide( skier,obstacles, False) # 检查是否碰到树或者小旗。
|
|
|
if hit:
|
|
|
if hit[0].type == "tree" and not hit[0].passed:
|
|
|
points = points - 10
|
|
|
skier.image = pygame.image.load("skier_crash.png")
|
|
|
animate()
|
|
|
pygame.time.delay(400)
|
|
|
skier.image = pygame.image.load("skier_down.png")
|
|
|
skier.angle = 0
|
|
|
speed = [0, 6]
|
|
|
hit[0].passed = True
|
|
|
if points<0:
|
|
|
Show_Start_Interface(Demo, 900, 900,"游戏结束",'按任意键重新开始')
|
|
|
points=0
|
|
|
elif hit[0].type == "flag" and not hit[0].passed:
|
|
|
points += 10
|
|
|
obstacles.remove(hit[0])
|
|
|
# 显示得分
|
|
|
score_text = font.render("Score: " + str(points), 1, (0, 0, 0))
|
|
|
animate()
|
|
|
|
|
|
pygame.sprite.Sprite.__init__(self)
|
|
|
# 滑雪者的朝向(-2到2)
|
|
|
self.direction = 0
|
|
|
self.imgs = ["skier_crash.png", "skier_right1.png", "skier_right2.png", "skier_left2.png", "skier_left1.png"]
|
|
|
self.person = pygame.image.load(self.imgs[self.direction])
|
|
|
self.rect = self.person.get_rect()
|
|
|
self.rect.center = [320, 100]
|
|
|
self.speed = [self.direction, 6 - abs(self.direction) * 2]
|
|
|
|
|
|
|
|
|
# 改变滑雪者的朝向
|
|
|
# 负数为向左,正数为向右,0为向前
|
|
|
def turn(self, num):
|
|
|
self.direction += num
|
|
|
self.direction = max(-2, self.direction)
|
|
|
self.direction = min(2, self.direction)
|
|
|
center = self.rect.center
|
|
|
self.person = pygame.image.load(self.imgs[self.direction])
|
|
|
self.rect = self.person.get_rect()
|
|
|
self.rect.center = center
|
|
|
self.speed = [self.direction, 6 - abs(self.direction) * 2]
|
|
|
return self.speed
|
|
|
# 移动滑雪者
|
|
|
|
|
|
|
|
|
def move(self):
|
|
|
self.rect.centerx += self.speed[0]
|
|
|
self.rect.centerx = max(20, self.rect.centerx)
|
|
|
self.rect.centerx = min(620, self.rect.centerx)
|
|
|
|
|
|
# 障碍物类
|
|
|
# Input:
|
|
|
# -img_path: 障碍物图片路径
|
|
|
# -location: 障碍物位置
|
|
|
# -attribute: 障碍物类别属性
|
|
|
class ObstacleClass(pygame.sprite.Sprite):
|
|
|
def __init__(self, img_path, location, attribute):
|
|
|
pygame.sprite.Sprite.__init__(self)
|
|
|
|
|
|
|
|
|
self.img_path = img_path
|
|
|
self.image = pygame.image.load(self.img_path)
|
|
|
self.location = location
|
|
|
self.rect = self.image.get_rect()
|
|
|
self.rect.center = self.location
|
|
|
self.attribute = attribute
|
|
|
self.passed = False
|
|
|
|
|
|
|
|
|
# 移动
|
|
|
def move(self, num):
|
|
|
self.rect.centery = self.location[1] - num
|
|
|
|
|
|
|
|
|
# 创建障碍物
|
|
|
def create_obstacles(s, e, num=10):
|
|
|
obstacles = pygame.sprite.Group()
|
|
|
locations = []
|
|
|
for i in range(num): row = random.randint(s, e)
|
|
|
col = random.randint(0, 9)
|
|
|
location = [col * 64 + 20, row * 64 + 20]
|
|
|
if location not in locations: locations.append(location)
|
|
|
attribute = random.choice(["tree", "flag"])
|
|
|
img_path = './images/tree.png' if attribute == "tree" else './images/flag.png'
|
|
|
obstacle = ObstacleClass(img_path, location, attribute)
|
|
|
obstacles.add(obstacle)
|
|
|
return obstacles
|
|
|
|
|
|
|
|
|
# 合并障碍物
|
|
|
def AddObstacles(obstacles0, obstacles1):
|
|
|
obstacles = pygame.sprite.Group()
|
|
|
for obstacle in obstacles0: obstacles.add(obstacle)
|
|
|
for obstacle in obstacles1: obstacles.add(obstacle)
|
|
|
return obstacles
|
|
|
|
|
|
|
|
|
# 显示游戏开始界面
|
|
|
|
|
|
# 主程序
|
|
|
def main():
|
|
|
'''
|
|
|
初始化
|
|
|
'''
|
|
|
pygame.init()
|
|
|
# 屏幕
|
|
|
screen = pygame.display.set_mode([900, 900])
|
|
|
# 主频
|
|
|
clock = pygame.time.Clock()
|
|
|
# 滑雪者
|
|
|
skier = SkierClass()
|
|
|
# 记录滑雪的距离
|
|
|
distance = 0
|
|
|
# 创建障碍物
|
|
|
obstacles0 = create_obstacles(20, 29)
|
|
|
obstacles1 = create_obstacles(10, 19)
|
|
|
obstaclesflag = 0
|
|
|
obstacles = AddObstacles(obstacles0, obstacles1)
|
|
|
# 分数
|
|
|
font = pygame.font.Font(None, 50)
|
|
|
score = 0
|
|
|
score_text = font.render("Score: " + str(score), 1, (0, 0, 0))
|
|
|
# 速度
|
|
|
speed = [0, 6]
|
|
|
Show_Start_Interface(screen, 640, 640)
|
|
|
'''
|
|
|
主循环
|
|
|
'''
|
|
|
|
|
|
# 更新屏幕
|
|
|
def update():
|
|
|
screen.fill([255, 255, 255])
|
|
|
|
|
|
pygame.display.update(obstacles.draw(screen))
|
|
|
screen.blit(skier.person, skier.rect)
|
|
|
screen.blit(score_text, [10, 10])
|
|
|
pygame.display.flip()
|
|
|
|
|
|
while True:
|
|
|
for event in pygame.event.get():
|
|
|
if event.type == pygame.QUIT: sys.exit()
|
|
|
if event.type == pygame.KEYDOWN:
|
|
|
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
|
|
|
speed = skier.turn(-1)
|
|
|
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
|
|
|
speed = skier.turn(1)
|
|
|
skier.move()
|
|
|
distance += speed[1]
|
|
|
if distance >= 640 and obstaclesflag == 0:
|
|
|
obstaclesflag = 1
|
|
|
obstacles0 = create_obstacles(20, 29)
|
|
|
obstacles = AddObstacles(obstacles0, obstacles1)
|
|
|
if distance >= 1280 and obstaclesflag == 1:
|
|
|
obstaclesflag = 0
|
|
|
distance -= 1280
|
|
|
for obstacle in obstacles0:
|
|
|
obstacle.location[1] = obstacle.location[1] - 1280
|
|
|
obstacles1 = create_obstacles(10, 19)
|
|
|
obstacles = AddObstacles(obstacles0, obstacles1)
|
|
|
# 用于碰撞检测
|
|
|
for obstacle in obstacles:
|
|
|
obstacle.move(distance)
|
|
|
# 碰撞检测
|
|
|
is_hit = pygame.sprite.spritecollide(skier, obstacles, False)
|
|
|
if is_hit:
|
|
|
if is_hit[0].attribute == "tree" and not is_hit[0].passed: score -= 50
|
|
|
skier.person = pygame.image.load("./images/skier_fall.png")
|
|
|
update()
|
|
|
# 摔倒后暂停一会再站起来
|
|
|
pygame.time.delay(1000)
|
|
|
skier.person = pygame.image.load("./images/skier_forward.png")
|
|
|
skier.direction = 0
|
|
|
speed = [0, 6]
|
|
|
is_hit[0].passed = True
|
|
|
if is_hit[0].attribute == "flag" and not is_hit[0].passed:
|
|
|
score += 10
|
|
|
obstacles.remove(is_hit[0])
|
|
|
score_text = font.render("Score: " + str(score), 1, (0, 0, 0))
|
|
|
update()
|
|
|
clock.tick(40)
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
print(" ")
|