You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止Pygame中.blit()像素跨屏环绕及地形交互实现

问题解决方案

一、修复滚动与地形生成问题

原代码的滚动逻辑是直接复制屏幕内容偏移,导致旧地形在屏幕另一侧重复出现。正确的做法是维护独立的地形数据,只绘制当前可见区域的地形:

  • 用列表存储所有地形列的Y坐标(每列宽度16px,和方块尺寸一致)
  • 滚动时不直接操作屏幕,而是调整偏移量scroll_offset_x
  • 当偏移量超过一个方块宽度时,移除最左侧的旧地形,生成新的右侧地形,同时重置偏移量

二、玩家碰撞检测方案

不推荐用像素颜色检测(效率低、易出错),直接维护地形数据列表更可靠:

  • 记录玩家的坐标(player_x, player_y)
  • 移动时计算玩家即将进入的位置对应的地形列,检查该列的地形Y坐标是否和玩家位置重叠
  • 如果重叠则阻止移动,否则允许移动

修改后的完整代码

import pygame as py
import random as r

py.init()

# 基础设置
SCREEN_WIDTH = 512
SCREEN_HEIGHT = 512
BLOCK_SIZE = 16
FPS = 4  # 和原代码0.25秒间隔对应

# 地形与滚动相关
terrain_columns = []
scroll_offset_x = 0
# 初始化屏幕可见的所有地形列(32列,512/16=32)
for _ in range(SCREEN_WIDTH // BLOCK_SIZE):
    terrain_columns.append(r.randint(0, 15))

# 玩家设置
player_x = BLOCK_SIZE * 5  # 初始在屏幕左侧
player_y = BLOCK_SIZE * 8
player_size = BLOCK_SIZE  # 用16px方块代表玩家,方便检测

screen = py.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = py.time.Clock()

def generate_new_terrain():
    # 生成新地形列,延续之前的趋势避免突变
    last_y = terrain_columns[-1]
    change = round(r.randint(0,5) ** (1/4))
    if r.randint(0,1) == 0:
        change = -change
    new_y = last_y + change
    new_y = max(0, min(15, new_y))  # 限制在0-15之间
    return new_y

running = True
while running:
    clock.tick(FPS)
    screen.fill((175, 215, 225))

    # 处理事件
    for event in py.event.get():
        if event.type == py.QUIT:
            running = False
        # 玩家移动控制
        if event.type == py.KEYDOWN:
            if event.key == py.K_LEFT:
                target_x = player_x - BLOCK_SIZE
                col_idx = (target_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE)
                if col_idx >= 0:
                    terrain_y = terrain_columns[col_idx] * BLOCK_SIZE
                    if not (player_y + player_size > terrain_y and player_y < terrain_y + BLOCK_SIZE):
                        player_x = target_x
            if event.key == py.K_RIGHT:
                target_x = player_x + BLOCK_SIZE
                col_idx = (target_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE)
                if col_idx < len(terrain_columns):
                    terrain_y = terrain_columns[col_idx] * BLOCK_SIZE
                    if not (player_y + player_size > terrain_y and player_y < terrain_y + BLOCK_SIZE):
                        player_x = target_x
            if event.key == py.K_UP:
                target_y = player_y - BLOCK_SIZE
                if target_y >= 0:
                    player_y = target_y
            if event.key == py.K_DOWN:
                target_y = player_y + BLOCK_SIZE
                col_idx = (player_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE)
                terrain_y = terrain_columns[col_idx] * BLOCK_SIZE
                if target_y + player_size <= SCREEN_HEIGHT and not (target_y + player_size > terrain_y and target_y < terrain_y + BLOCK_SIZE):
                    player_y = target_y

    # 自动向右滚动
    scroll_offset_x += BLOCK_SIZE
    # 偏移量超过方块宽度时更新地形列表
    if scroll_offset_x >= BLOCK_SIZE:
        scroll_offset_x -= BLOCK_SIZE
        terrain_columns.pop(0)
        terrain_columns.append(generate_new_terrain())

    # 绘制所有可见地形
    for idx, y in enumerate(terrain_columns):
        block_x = idx * BLOCK_SIZE - scroll_offset_x
        block_y = y * BLOCK_SIZE
        py.draw.rect(screen, (0, 100, 20), py.Rect(block_x, block_y, BLOCK_SIZE, BLOCK_SIZE))

    # 绘制玩家
    py.draw.rect(screen, (255, 0, 0), py.Rect(player_x, player_y, player_size, player_size))

    py.display.flip()

py.quit()

代码说明

  1. 地形维护:用terrain_columns列表存储每列地形的Y坐标,滚动时只更新列表首尾,保证地形无限延伸且不重复
  2. 滚动逻辑:通过scroll_offset_x控制地形绘制偏移,每次滚动一个方块宽度后,移除旧列添加新列,实现无缝滚动
  3. 碰撞检测:移动玩家时计算目标位置对应的地形列,直接对比坐标判断是否重叠,高效准确
  4. 玩家控制:添加方向键控制,移动时检查地形阻挡,避免穿过地形

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:53:22