【Python项目】过马路游戏

零、序章

这是一个使用Python写的过马路游戏。

可以练习一些面向对象的知识。

由于全写注释CSND说我字太少,就统一写代码外面来


实现的功能有:

  • 汽车的随机刷新、汽车的整体移动、碰撞检测
  • 玩家的移动(只能向上移动。。。没有更多操作了)
  • 关卡显示以及根据关卡自动调整汽车移动速度

可以改进的地方有:

  • 暂停功能
  • 碰撞检测可以优化得更精准
  • 感觉有卡顿,不知道是单次循环的停顿时间根据level变化造成的错觉,还是运行到后面车太多了造成了实际的卡顿

一、游戏主程序

  • cal_limits函数:根据screen计算边界
  • quit_game函数:控制退出游戏
  • 实例化屏幕对象、玩家对象、汽车管理员对象、计分板对象
  • 每次循环停顿时间根据level决定,level越高,停顿时间越短,达到汽车运动越快的效果(也可以通过更改汽车单次移动常量来加速)
  • 每次循环汽车要刷新、移动、进行碰撞检测
import time
from turtle import Screen
from player import Player
from car_manager import CarManager
from scoreboard import ScoreBoard

screen = Screen()
screen.setup(width=600, height=600)
screen.tracer(0)


def cal_limits(screen):
    u_limit = screen.window_height() / 2
    d_limit = -screen.window_height() / 2
    l_limit = -screen.window_width() / 2
    r_limit = screen.window_width() / 2
    return u_limit, d_limit, l_limit, r_limit


def quit_game():
    global game_is_on
    game_is_on = False


limits = cal_limits(screen)

player = Player()
car_manager = CarManager(limits=limits)

screen.listen()
screen.onkey(key='Up', fun=player.move)
screen.onkey(key='q', fun=quit_game)

scoreboard = ScoreBoard(limits)

game_is_on = True
while game_is_on:

    time.sleep(0.11 - scoreboard.level * 0.015)
    screen.update()

    car_manager.add_car((limits[0] - 50, limits[1] + 100, limits[3], limits[3] + 300))

    car_manager.move(limits)

    if car_manager.collision_check(player):
        scoreboard.game_clear('Game Over!!!')
        player.respawn()
        scoreboard.refresh_level()

    if player.check_finish():
        scoreboard.refresh_level()

二、玩家类

  • 具有初始位置、单次移动距离、终点线等常量
  • 继承自Turtle类
  • 每次抵达终点线使用respawn函数回到起点
  • 使用check_finish函数检测是否抵达终点线
STARTING_POSITION = (0, -280)
MOVE_DISTANCE = 10
FINISH_LINE_Y = 280

from turtle import Turtle


class Player(Turtle):
    def __init__(self):
        super().__init__()
        self.penup()
        self.shape('turtle')
        self.goto(STARTING_POSITION)
        self.setheading(90)

    def move(self):
        self.forward(MOVE_DISTANCE)

    def respawn(self):
        self.goto(STARTING_POSITION)

    def check_finish(self):
        if self.pos()[1] >= FINISH_LINE_Y:
            self.respawn()
            return True

三、汽车管理员类

  • 具有颜色、刷新距离、单次移动距离、刷新率等常量
  • 本身是个列表,列表内放Turtle类
  • 一开始在给定范围(基本是整个屏幕内)刷新,之后就都在屏幕右边的范围刷新
  • add_car函数:根据刷新率在屏幕右侧随机刷新汽车,,每次都要遍历汽车检测刷新距离是否满足STARTING_MOVE_DISTANCE常量,满足就加入列表
  • move函数:遍历列表,每个车都向左移动
  • collision_check碰撞检测函数:有点难做,因为我不想简单地使用distance,感觉这个是不是不能用在方形物体的碰撞检测上?我的总体思路是将整个屏幕看作一个网格,每个格子边长为10,计算出汽车上下左右边界和玩家的上下边界(左右边界感觉不用算也能判断得很精准)在哪个格子后再进行碰撞检测。
COLORS = ["red", "orange", "yellow", "green", "blue", "purple"]
STARTING_MOVE_DISTANCE = 10
MOVE_INCREMENT = 10
REFRESH_RATE = 0.3

import random
from turtle import Turtle


class CarManager:
    def __init__(self, limits):
        self.cars = []
        spawn_range = (limits[0] - 20, limits[1] + 100, limits[2], limits[3] + 300)
        for i in range(25):
            self.add_car(spawn_range)

    def add_car(self, spawn_range):
        if random.random() < REFRESH_RATE:
            new_pos = (random.randint(spawn_range[2], spawn_range[3]) // 20) * 20, \
                      (random.randint(spawn_range[1], spawn_range[0]) // 20) * 20

            while self.cars:
                for old_car in self.cars:
                    if old_car.distance(new_pos) <= STARTING_MOVE_DISTANCE:
                        new_pos = (random.randint(spawn_range[2], spawn_range[3]) // 20) * 20, \
                                  (random.randint(spawn_range[1], spawn_range[0]) // 20) * 20
                        break
                else:
                    break

            new_car = Turtle(shape='square')
            new_car.shapesize(stretch_wid=1, stretch_len=2)
            new_car.penup()
            new_car.color(random.choice(COLORS))
            new_car.setheading(180)
            new_car.goto(new_pos)
            self.cars.append(new_car)

    def move(self, limits):
        for car in self.cars:
            car.forward(MOVE_INCREMENT)
            if car.pos()[0] < limits[2] - 20:
                car.ht()
                self.cars.remove(car)

    def collision_check(self, player):
        player_up_y_block = (player.pos()[1] + 10) // 10
        player_down_y_block = (player.pos()[1] - 10) // 10

        for car in self.cars:
            car_left_x_block = (car.pos()[0] - 20) // 10
            car_right_x_block = (car.pos()[0] + 20) // 10
            car_up_y_block = (car.pos()[1] + 10) // 10
            car_down_y_block = (car.pos()[1] - 10) // 10
            if car_left_x_block <= 0 <= car_right_x_block and \
                    (car_down_y_block < player_up_y_block < car_up_y_block or
                     car_down_y_block < player_down_y_block < car_up_y_block):
                return True

四、计分板类

  • 具有字体、最大关数等常量
  • 计分板类继承自Turtle类,具有额外的level属性
  • 其他功能和之前发的贪吃蛇、乒乓类似,就不赘述了,只多了个检测通关的功能
FONT = ("Courier", 24, "normal")
MAX_LEVEL = 7

import time
from turtle import Turtle


class ScoreBoard(Turtle):
    def __init__(self, limits):
        super().__init__()
        self.level = 1
        self.penup()
        self.ht()
        self.goto(limits[2] + 20, limits[0] - 50)
        self.write(f"Level:{self.level}", font=FONT)

    def refresh_level(self):
        if self.level >= MAX_LEVEL:
            self.game_clear('Game Clear!!!')
        self.clear()
        self.level += 1
        self.write(f"Level:{self.level}", font=FONT)

    def game_clear(self, info):
        self.level = 0
        pos = self.pos()
        self.goto(-100, 0)
        self.write(info, font=FONT)
        self.goto(pos)
        time.sleep(5)

五、效果展示

在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sprite.Nym

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值