You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何实现俯视视角赛车游戏背景随车辆反向移动

实现俯视赛车游戏的赛道跟随移动效果

嘿,作为Python新手能搭建出这样的游戏框架真的很不错!咱们来搞定赛道随玩家移动反向滚动的效果,核心思路是让相机始终聚焦在玩家车辆中心,背景和其他物体根据玩家的移动量反向偏移,这样就会营造出玩家沿赛道前进的视觉感。

核心原理

所有物体(玩家、AI车、赛道)都在「世界坐标」里存在,我们通过一个camera向量来记录相机的偏移量:

  • 相机的位置 = 玩家的世界位置 - 屏幕中心坐标(确保玩家始终在屏幕正中央)
  • 绘制时,每个物体的屏幕坐标 = 物体的世界坐标 - 相机坐标
  • 赛道背景的世界坐标是(0,0),所以它的屏幕坐标就是-camera,玩家移动时,背景会自动向相反方向移动

修改后的完整代码

import math
import random
import pygame

pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()

screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()

# 音乐设置
pygame.mixer.music.load("Wice.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)

WHITE = pygame.Color('white')

# 加载车辆图片(移除不必要的Surface创建和提前blit)
VEHICLE1 = pygame.image.load("YellowLambo.png").convert_alpha()
VEHICLE2 = pygame.image.load("RedLambo.png").convert_alpha()

# 加载赛道背景
BACKGROUND = pygame.image.load("track.png").convert()

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class VehicleSprite(Entity):
    MAX_FORWARD_SPEED = 10
    MAX_REVERSE_SPEED = 2
    ACCELERATION = 0.05
    TURN_SPEED = 0.5  # 原来的数值太小,几乎转不动,调大一点

    def __init__(self, image, position):
        Entity.__init__(self)
        self.src_image = image
        self.image = image
        self.rect = self.image.get_rect(center=position)
        self.position = pygame.math.Vector2(position)
        self.velocity = pygame.math.Vector2(0, 0)
        self.speed = self.direction = 0
        self.k_left = self.k_right = self.k_down = self.k_up = 0

    def update(self, time):
        # 速度更新
        self.speed += self.k_up + self.k_down
        # 限制速度范围
        self.speed = max(-self.MAX_REVERSE_SPEED, min(self.speed, self.MAX_FORWARD_SPEED))
        
        # 转向更新
        self.direction += (self.k_right + self.k_left)
        rad = math.radians(self.direction)
        
        # 计算速度向量
        self.velocity.x = -self.speed * math.sin(rad)
        self.velocity.y = -self.speed * math.cos(rad)
        
        # 更新世界坐标位置
        self.position += self.velocity
        
        # 旋转车辆图片
        self.image = pygame.transform.rotate(self.src_image, self.direction)
        self.rect = self.image.get_rect(center=self.position)

class Background(pygame.sprite.Sprite):
    def __init__(self, image, location):
        pygame.sprite.Sprite.__init__(self)
        self.image = image
        self.rect = self.image.get_rect(topleft=location)

def game_loop():
    background = Background(BACKGROUND, [0, 0])
    # 初始时玩家在世界坐标的屏幕中心位置
    bike = VehicleSprite(VEHICLE1, rect.center)
    ball = VehicleSprite(VEHICLE2, (rect.centerx + 200, rect.centery))  # 把AI车移开一点,避免重叠
    bike_group = pygame.sprite.Group(bike)
    ball_group = pygame.sprite.Group(ball)
    all_sprites = pygame.sprite.Group(bike_group, ball_group)

    done = False
    while not done:
        time = clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.KEYDOWN:
                # 玩家车辆控制
                if event.key == pygame.K_d:
                    bike.k_right = -2  # 调大转向幅度,更容易控制
                elif event.key == pygame.K_a:
                    bike.k_left = 2
                elif event.key == pygame.K_w:
                    bike.k_up = 0.2  # 调小加速度,避免速度暴增
                elif event.key == pygame.K_s:
                    bike.k_down = -0.2
                elif event.key == pygame.K_ESCAPE:
                    done = True
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_d:
                    bike.k_right = 0
                elif event.key == pygame.K_a:
                    bike.k_left = 0
                elif event.key == pygame.K_w:
                    bike.k_up = 0
                elif event.key == pygame.K_s:
                    bike.k_down = 0

        # 更新所有物体的世界坐标
        all_sprites.update(time)
        
        # 计算相机偏移:让玩家始终在屏幕中心
        camera = bike.position - pygame.math.Vector2(rect.center)
        
        # 绘制背景(反向偏移相机,实现赛道滚动)
        screen.fill(WHITE)
        screen.blit(background.image, -camera)
        
        # 绘制所有车辆(基于相机偏移计算屏幕坐标)
        for sprite in all_sprites:
            screen_pos = sprite.position - camera
            screen.blit(sprite.image, screen_pos - pygame.math.Vector2(sprite.rect.width//2, sprite.rect.height//2))
        
        pygame.display.flip()

game_loop()
pygame.quit()

关键修改点说明

  1. 修复车辆控制参数:原来的转向速度和加速度数值不合理,调整后更容易操控车辆
  2. 相机偏移计算:通过camera = bike.position - pygame.math.Vector2(rect.center)确保玩家始终在屏幕中心
  3. 背景绘制逻辑:用-camera作为背景的绘制坐标,实现赛道随玩家移动反向滚动
  4. 物体绘制修正:所有车辆的屏幕坐标通过「世界坐标 - 相机坐标」计算,确保它们在赛道上的位置正确
  5. 移除冗余代码:删除了加载图片时不必要的Surface创建和提前blit操作,让代码更简洁

现在运行代码,你会发现玩家车辆始终在屏幕中心,赛道会随着你的移动反向滚动,完美营造出沿赛道前进的视觉效果!

内容的提问来源于stack exchange,提问作者Y2J

火山引擎 最新活动