# 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("  ")
