Python二维游戏(极限飞驰)

读万卷书,行万里路——木子成

基于Python中pygame模块的二维游戏

a:向左移动

d:向右移动

空格:暂停

游戏速度会根据游戏得分加速

extreme_speed.py

import pygame
import function as fun
from settings import Settings
from pygame.sprite import Group
from car import Car
from impact_effects import ImpactEffects
from autodrome import Line
from game_button import GameButton
from score import ScoreCard


def run_game():
    """游戏主干部分"""
    pygame.init()   # 初始化游戏并且创建一个游戏界面
    pygame.display.set_caption("极限飞驰")  # 显示在游戏界面左上角

    game_settings = Settings()  # 设置类,包含绝大部分参数
    # 生成主屏幕
    screen = pygame.display.set_mode((game_settings.screen_width, game_settings.screen_height))
    car = Car(screen, game_settings)    # 飞车类
    impact_effects = ImpactEffects(screen, game_settings)    # 撞车效果类
    active_line = Line(screen, game_settings)    # 赛道实线类
    button = GameButton(game_settings, screen)    # 游戏开始、结束类
    score = ScoreCard(screen, game_settings)    # 游戏得分类
    dotted_lines = Group()    # 虚线编组
    obstacles = Group()    # 障碍物编组

    fun.track_init(screen, game_settings, dotted_lines, obstacles, car)    # 开始游戏主循环
    while True:
        # 监控键盘和鼠标响应
        fun.check_events(game_settings, button, obstacles, screen, car, dotted_lines)
        # 游戏点击开始或者继续并且游戏非暂停
        if game_settings.game_start and game_settings.game_pause is False:
            car.update()    # 更新赛车
            dotted_lines.update(car, dotted_lines)    # 更新虚线(模拟赛车前进)
            obstacles.update(obstacles)    # 更新障碍物
            # 检测是否撞车
            fun.check_crash(game_settings, car, obstacles, impact_effects)
        # 绘制屏幕
        fun.draw_screen(screen, game_settings, active_line, car, dotted_lines,
                        impact_effects, obstacles, button, score)
        pygame.display.flip()    # 让最近绘制的屏幕可见


run_game()    # 运行游戏

function.py

import pygame
import sys
import random
from autodrome import DottedLine
from car import Obstacles


def dl_make(screen, game_settings, dotted_lines):
    """"生成虚线"""
    for dl_x in game_settings.dl_xs:
        new_dl = DottedLine(screen, game_settings)
        new_dl.rect.left = dl_x
        dotted_lines.add(new_dl)


def obs_make(screen, game_settings, obstacles):
    """生成障碍物"""
    obs_make_number = 0    # 记录每次生成个数,确保小于4个大于1个
    for obs_x in game_settings.obs_xs:
        if random.randint(0, 10) < game_settings.obs_number_ratio:    # 随机生成个数
            obs_make_number += 1
            if obs_make_number <= game_settings.way_num:    # 确保小于4个
                new_obs = Obstacles(screen, game_settings, obs_x)
                obstacles.add(new_obs)
        if obs_x == game_settings.obs_xs[-1] and obs_make_number == 0:    # 确保大于1个
            new_obs = Obstacles(screen, game_settings, obs_x)
            obstacles.add(new_obs)


def track_init(screen, game_settings, dotted_lines, obstacles, car):
    """游戏初始化"""
    obstacles.empty()    # 清空所有障碍物
    dotted_lines.empty()    # 清空所有虚线
    dl_make(screen, game_settings, dotted_lines)    # 重新生成虚线
    obs_make(screen, game_settings, obstacles)    # 重新生成障碍物

    game_settings.impact = False    # 关闭撞车效果显示开关
    car.rect.centerx = game_settings.way_width / 2    # 重新定位赛车位置

    # 初始化游戏速度
    game_settings.game_speed = 0.7
    game_settings.dl_moving_speed = game_settings.game_speed
    game_settings.obs_up_speed = game_settings.game_speed - 0.4
    game_settings.obs_down_speed = game_settings.game_speed + 0.2

    game_settings.score = 0    # 初始化分数


def count_top_score(game_settings):
    """计算历史最高得分"""
    with open("score/score.txt", 'r+') as file:    # 打开最高得分储存文件
        top_score = file.read()
        if int(top_score) < game_settings.score:
            file.seek(0)    # 文件读取指针指到文件开头
            file.truncate()    # 清空文件内容(若无上一步将无法清空)
            file.write(str(game_settings.score))    # 写入最高得分


def keydown_events(game_settings, event):
    """响应按下按键"""
    if event.key == pygame.K_a:
        game_settings.moving_left = True    # 按下a按键打开左移开关
    elif event.key == pygame.K_d:
        game_settings.moving_right = True    # 按下d按键打开右移开关
    elif event.key == pygame.K_SPACE:    # 按下空格按键暂停
        game_settings.game_pause = bool(1 - game_settings.game_pause)    # 对布尔达参数取反


def keyup_events(game_settings, event):
    """响应松开按键"""
    if event.key == pygame.K_a:
        game_settings.moving_left = False    # 松开a按键关闭左移开关
    elif event.key == pygame.K_d:
        game_settings.moving_right = False    # 松开d按键关闭右移开关


def mouse_down(mouse_x, mouse_y, button, game_settings, obstacles, screen, car, dotted_lines):
    """响应点击鼠标"""
    if button.rect.collidepoint(mouse_x, mouse_y):    # 检测鼠标点击位置是否为按钮
        game_settings.game_start = True    # 游戏开始
        if game_settings.game_first:
            button.continuation()    # 制作“继续”按钮
            game_settings.game_first = False    # 游戏第一次运行开关关闭
        else:
            track_init(screen, game_settings, dotted_lines, obstacles, car)    # 游戏初始化


def check_events(game_settings, button, obstacles, screen, car, dotted_lines):
    """监控键盘和鼠标响应"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:    # 强制退出
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            keydown_events(game_settings, event)
        elif event.type == pygame.KEYUP:
            keyup_events(game_settings, event)
        # 响应点击鼠标并且游戏在结束或者未开始界面
        elif event.type == pygame.MOUSEBUTTONDOWN and game_settings.game_start is False:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            mouse_down(mouse_x, mouse_y, button, game_settings, obstacles, screen,
                       car, dotted_lines)


def draw_screen(screen, game_settings, active_line, car, dotted_lines, impact_effects,
                obstacles, button, score):
    """绘制屏幕"""
    screen.fill(game_settings.bg_color)    # 绘制屏幕
    if game_settings.game_first is False:    # 游戏第一次开始不显示游戏各部分
        active_line.draw()
        for dotted_line in dotted_lines.sprites():
            dotted_line.draw()
        car.draw()
        obstacles.draw(screen)
        score.draw()
    if game_settings.game_start is False:    # 游戏结束打印“继续”按钮
        button.draw()
    if game_settings.impact:    # 撞车后显示撞车效果
        impact_effects.draw()


def check_crash(game_settings, car, obstacles, impact_effects):
    """检测撞车、定位撞车位置"""
    if pygame.sprite.spritecollideany(car, obstacles):    # 检测撞车
        obs = pygame.sprite.spritecollide(car, obstacles, False)[0]    # 返回碰撞车辆精灵
        if car.rect.left + 1 == obs.rect.right or car.rect.right - 1 == obs.rect.left:
            if car.rect.bottom <= obs.rect.bottom:
                impact_effects.rect.centery = (car.rect.bottom + obs.rect.top) / 2
                if car.rect.left + 1 == obs.rect.right:
                    impact_effects.rect.centerx = car.rect.left
                else:
                    impact_effects.rect.centerx = car.rect.right
            else:
                impact_effects.rect.centery = (car.rect.top + obs.rect.bottom) / 2
                if car.rect.left + 1 == obs.rect.right:
                    impact_effects.rect.centerx = car.rect.left
                else:
                    impact_effects.rect.centerx = car.rect.right
        elif car.rect.top + 1 == obs.rect.bottom:
            if car.rect.left > obs.rect.left:
                impact_effects.rect.centerx = (car.rect.left + obs.rect.right) / 2
            else:
                impact_effects.rect.centerx = (car.rect.right + obs.rect.left) / 2
            impact_effects.rect.centery = car.rect.top

        game_settings.impact = True
        game_settings.game_start = False
        count_top_score(game_settings)


def count_score(game_settings):
    """计算得分、游戏加速"""
    game_settings.score += 1
    if game_settings.score % game_settings.add_speed_blanking == 0 and \
            game_settings.game_speed < game_settings.max_speed:
        game_settings.game_speed += game_settings.speed_increment
        game_settings.dl_moving_speed = game_settings.game_speed
        game_settings.obs_up_speed = game_settings.game_speed - 0.4
        game_settings.obs_down_speed = game_settings.game_speed + 0.2






impact_effects.py

import pygame


class ImpactEffects:
    """撞车效果"""
    def __init__(self, screen, game_settings):
        self.screen = screen
        self.game_settings = game_settings

        self.image = pygame.image.load('images/impact_effects.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = self.screen.get_rect()

    def draw(self):
        self.screen.blit(self.image, self.rect)

game_button.py

import pygame


class GameButton:
    """游戏开始、继续按钮"""
    def __init__(self, game_settings, screen):
        self.screen = screen
        self.game_settings = game_settings
        self.screen_rect = self.screen.get_rect()

        self.width = self.game_settings.g_button_width
        self.height = self.game_settings.g_button_height

        self.button_color = self.game_settings.button_color
        self.text_color = self.game_settings.text_color

        self.font = pygame.font.SysFont(None, 48)

        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        self.image = self.font.render("Play", True, self.text_color, self.button_color)
        self.image_rect = self.image.get_rect()
        self.image_rect.center = self.rect.center

    def draw(self):
        self.screen.fill(self.button_color, self.rect)
        self.screen.blit(self.image, self.image_rect)

    def continuation(self):
        self.image = self.font.render("Continue", True, self.text_color, self.button_color)
        self.image_rect = self.image.get_rect()
        self.image_rect.center = self.rect.center


car.py

import pygame
from pygame.sprite import Sprite
import function as fun


class Car:
    """赛车类"""
    def __init__(self, screen, game_settings):
        self.screen = screen
        self.game_settings = game_settings

        self.image = pygame.image.load('images/car_up.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = self.screen.get_rect()

        self.rect.centerx = self.game_settings.way_width / 2
        self.rect.bottom = self.game_settings.screen_height

    def draw(self):
        self.screen.blit(self.image, self.rect)

    def update(self):
        # 左右移动不能超出界限
        if self.game_settings.moving_left and self.rect.left > 0:
            self.rect.x -= self.game_settings.car_moving_speed
        elif self.game_settings.moving_right and self.rect.right < \
                self.game_settings.screen_width:
            self.rect.x += self.game_settings.car_moving_speed


class Obstacles(Sprite):
    """障碍物"""
    def __init__(self, screen, game_settings, obs_x):
        super(Obstacles, self).__init__()
        self.screen = screen
        self.game_settings = game_settings
        self.obs_x = obs_x

        # 分车道设置障碍物
        if self.obs_x < self.game_settings.screen_width / 2:
            self.image = pygame.image.load('images/car_down.bmp')
        else:
            self.image = pygame.image.load('images/car_up.bmp')

        self.rect = self.image.get_rect()

        self.rect.centerx = self.obs_x
        self.rect.bottom = self.game_settings.score_height
        self.y = float(self.rect.y)    # 浮点化坐标,方便调节速度
        self.rect.y = self.y

    def update(self, obstacles):
        if self.rect.x < self.game_settings.screen_width / 2:
            self.y += self.game_settings.obs_down_speed
            self.rect.y = self.y
        else:
            self.y += self.game_settings.obs_up_speed
            self.rect.y = self.y

        # 循环后保存最后一个障碍物,防止多个坐标符合新建障碍物
        obstacle = Obstacles(self.screen, self.game_settings, 0)
        for obs in obstacles.sprites():
            obstacle = obs
            if obs.rect.top >= self.game_settings.screen_height:
                obstacles.remove(obs)
                fun.count_score(self.game_settings)       # 计算分数
        if obstacle.rect.top >= self.game_settings.obs_distance + \
                self.game_settings.g_button_height:
            fun.obs_make(self.screen, self.game_settings, obstacles)    # 生成新的障碍物




score.py

import pygame


class ScoreCard:
    """得分类"""
    def __init__(self, screen, game_settings):
        self.screen = screen
        self.game_settings = game_settings
        self.screen_rect = self.screen.get_rect()

        self.width = self.game_settings.score_width
        self.height = self.game_settings.score_height

        self.bg_color = self.game_settings.score_bg_color
        self.text_color = self.game_settings.score_text_color

        self.name_font = pygame.font.SysFont(None, 30)    # 分数名字字体大小
        self.score_font = pygame.font.SysFont(None, 40)    # 分数字体大小

        self.rect = pygame.Rect(0, 0, self.width, self.height)    # 分数显示栏背景
        self.rect.top = 0

    def draw_current_score(self):
        """绘制当前得分"""
        self.cs = "CurrentScore"
        self.cs_surface = self.name_font.render(self.cs, True, self.text_color, self.bg_color)
        self.cs_rect = self.cs_surface.get_rect()
        self.cs_rect.centerx = self.width / 4
        self.cs_rect.top = self.rect.top

        self.current_score = str(self.game_settings.score)
        self.current_score_surface = self.score_font.render(self.current_score, True, self.text_color, self.bg_color)
        self.current_score_rect = self.current_score_surface.get_rect()
        self.current_score_rect.centerx = self.width / 4
        self.current_score_rect.bottom = self.rect.bottom

        self.screen.blit(self.cs_surface, self.cs_rect)
        self.screen.blit(self.current_score_surface, self.current_score_rect)

    def draw_highest_score(self):
        """绘制最高得分"""
        self.hs = "HighestScore"
        self.hs_surface = self.name_font.render(self.hs, True, self.text_color, self.bg_color)
        self.hs_rect = self.hs_surface.get_rect()
        self.hs_rect.centerx = self.width * 3 / 4
        self.hs_rect.top = self.rect.top

        with open('score/score.txt') as file:
            self.highest_score = file.read()
        self.highest_score_surface = self.score_font.render(self.highest_score, True, self.text_color, self.bg_color)
        self.highest_score_rect = self.highest_score_surface.get_rect()
        self.highest_score_rect.centerx = self.width * 3 / 4
        self.highest_score_rect.bottom = self.rect.bottom

        self.screen.blit(self.hs_surface, self.hs_rect)
        self.screen.blit(self.highest_score_surface, self.highest_score_rect)

    def draw(self):
        """绘制得分"""
        self.screen.fill(self.bg_color, self.rect)
        self.draw_highest_score()
        self.draw_current_score()






autodromr.py

import pygame
from pygame.sprite import Sprite
import function as fun


class Line:
    """实线类"""
    def __init__(self, screen, game_settings):

        self.screen = screen
        self.game_settings = game_settings
        self.screen_rect = self.screen.get_rect()

        self.width = game_settings.active_line_width
        self.height = game_settings.active_line_height

        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.centerx = self.screen_rect.centerx
        self.rect.bottom = self.game_settings.screen_height

        self.color = self.game_settings.al_color

    def draw(self):
        pygame.draw.rect(self.screen, self.color, self.rect)


class DottedLine(Sprite):
    """虚线类"""
    def __init__(self, screen, game_settings):
        super(DottedLine, self).__init__()

        self.screen = screen
        self.game_settings = game_settings

        self.width = game_settings.dotted_line_width
        self.height = game_settings.dotted_line_height

        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.bottom = self.game_settings.score_height

        self.color = self.game_settings.dotted_line_color
        self.y = float(self.rect.y)    # 浮点化坐标,方便调节速度

    def draw(self):
        pygame.draw.rect(self.screen, self.color, self.rect)

    def update(self, car, dotted_lines):
        self.y += self.game_settings.dl_moving_speed
        self.rect.y = self.y

        # 循环后保存最后一个障碍物,防止多个坐标符合新建虚线
        dl = DottedLine(self.screen, self.game_settings)
        for dotted_line in dotted_lines.sprites():
            dl = dotted_line
            if dl.rect.top >= self.game_settings.screen_height:
                dotted_lines.remove(dl)
        if dl.rect.top > self.height + self.game_settings.g_button_height:
            fun.dl_make(self.screen, self.game_settings, dotted_lines)








settings.py

class Settings:
    """设置类"""
    def __init__(self):
        # 屏幕参数
        self.screen_height = 750
        self.screen_width = 440
        self.bg_color = (195, 195, 195)

        # 得分背景参数
        self.g_button_width = 150
        self.g_button_height = 50
        self.button_color = (255, 235, 0)
        self.text_color = (0, 0, 0)

        # 得分参数
        self.score_height = 60
        self.score_width = self.screen_width
        self.score_bg_color = (255, 235, 0)
        self.score_text_color = (0, 0, 0)

        # 实线参数
        self.active_line_height = self.screen_height - self.score_height
        self.active_line_width = 20
        self.al_color = (255, 235, 0)

        # 虚线参数
        self.dotted_line_height = 150
        self.dotted_line_width = self.active_line_width
        self.dotted_line_color = self.al_color

        # 生成虚线x轴坐标、障碍物x轴坐标
        self.way_num = 4
        self.way_width = (self.screen_width - 3 * self.active_line_width) / self.way_num
        self.obs_xs = [0, 0, 0, 0]
        for num in range(len(self.obs_xs)):
            self.obs_xs[num] = num * (self.active_line_width + self.way_width) + self.way_width / 2
        self.dl_xs = [0, 0]
        for num in range(len(self.dl_xs)):
            self.dl_xs[num] = 2 * num * (self.way_width + self.active_line_width) + self.way_width

        # 游戏开关
        self.moving_left = False
        self.moving_right = False
        self.game_first = True
        self.game_start = False
        self.impact = False
        self.game_pause = False
        self.score = 0

        # 随机生成障碍物几率
        self.obs_number_ratio = 5
        # 障碍物生成初始间隔距离
        self.obs_distance = 500

        # 游戏速度
        self.car_moving_speed = 1
        self.game_speed = 0.7
        self.dl_moving_speed = self.game_speed
        self.obs_up_speed = self.game_speed - 0.4
        self.obs_down_speed = self.game_speed + 0.2
        self.max_speed = 2.0
        self.speed_increment = 0.05
        self.add_speed_blanking = 5



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值