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

海洋层生成异常及游戏卡顿问题技术求助

问题修复与性能优化方案

一、海洋覆盖岛屿问题修复

问题根源

当前代码使用独立的海洋噪声和海拔噪声,且海洋判断优先级高于海拔:只要海洋噪声低于阈值,不管该区域海拔有多高,都会被强制设为海洋颜色,直接覆盖了原本应该是岛屿的高海拔地形。

修复方案

取消独立的海洋噪声层,将海洋定义为低于水位线的低海拔区域,用统一的海拔噪声控制地形,确保高海拔区域始终保留为陆地生物群系:

  1. 删除单独的noise_ocean变量,复用海拔噪声判断海洋
  2. 调整海洋判定逻辑:当海拔低于70(对应biomes中water的海拔范围下限)时,直接设为海洋
  3. 调整生物群系匹配顺序,优先匹配海洋,再处理陆地生物群系

二、游戏卡顿性能优化

卡顿根源

  1. 每帧重复生成Chunk:游戏循环每帧都重新计算整个Chunk的Perlin噪声,噪声计算属于高开销操作
  2. 逐块绘制矩形:每帧需要绘制10000个独立矩形,大量的绘图API调用严重拖慢渲染速度
  3. 无Chunk缓存:玩家移动时重复生成已访问过的Chunk,浪费计算资源

优化方案

  1. 添加Chunk缓存字典:存储已生成的Chunk数据和预渲染的Surface,避免重复计算
  2. 预渲染Chunk Surface:每个Chunk生成后,一次性渲染到Surface上,后续只需将Surface blit到屏幕
  3. 按需生成Chunk:仅当玩家移动跨越Chunk边界时,才加载新的Chunk,而非每帧生成
  4. 统一噪声种子:为noise库设置固定种子,确保世界生成的一致性

修改后的完整代码

import pygame
import random
import noise

# Initialize Pygame
pygame.init()

# Screen settings
screen_width = 900
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Infinite Scrollable World")

# Color palette
colors = {
    "land": (134, 168, 83),   # Light green
    "water": (30, 144, 255),  # Deep blue
    "desert": (244, 164, 96), # Sandy color
    "mountains": (139, 137, 137),  # Gray
    "snow": (255, 250, 250),  # Snow white
    "forest": (34, 139, 34),  # Forest green
    "swamp": (105, 139, 34),  # Swampy green
    "beach": (238, 214, 175),  # Light beige
    "tundra": (192, 192, 192)  # Light gray
}

# Biome definitions
biomes = {
    "water": {"elevation": (0, 70), "temperature": (0.0, 1.0), "moisture": (0.0, 1.0), "color": colors["water"]},
    "beach": {"elevation": (71, 100), "temperature": (0.2, 0.8), "moisture": (0.2, 0.8), "color": colors["beach"]},
    "desert": {"temperature": (0.4, 1.0), "moisture": (0.0, 0.3), "elevation": (101, 200), "color": colors["desert"]},
    "grassland": {"temperature": (0.2, 0.8), "moisture": (0.2, 0.6), "elevation": (101, 200), "color": colors["land"]},
    "forest": {"temperature": (0.0, 0.7), "moisture": (0.5, 1.0), "elevation": (101, 200), "color": colors["forest"]},
    "mountains": {"elevation": (201, 255), "temperature": (0.0, 0.5), "moisture": (0.2, 0.8), "color": colors["mountains"]},
    "snow": {"temperature": (-1.0, 0.0), "moisture": (0.5, 1.0), "elevation": (256, 300), "color": colors["snow"]},
    "swamp": {"temperature": (0.0, 0.7), "moisture": (0.8, 1.0), "elevation": (101, 200), "color": colors["swamp"]},
    "tundra": {"temperature": (-1.0, 0.5), "moisture": (0.3, 0.6), "elevation": (201, 255), "color": colors["tundra"]}
}

# Chunk cache: key is (chunk_x, chunk_y), value is (surface, data)
chunk_cache = {}
tile_size = 10

# Generate a single chunk and pre-render its surface
def generate_chunk(chunk_coord_x, chunk_coord_y, chunk_size):
    # Calculate world coordinates for the chunk
    world_x_start = chunk_coord_x * chunk_size
    world_y_start = chunk_coord_y * chunk_size
    
    # Create surface for the chunk
    chunk_surface = pygame.Surface((chunk_size * tile_size, chunk_size * tile_size))
    chunk_data = []
    
    for y in range(chunk_size):
        row = []
        world_y = world_y_start + y
        for x in range(chunk_size):
            world_x = world_x_start + x
            
            # Combine multiple Perlin noise layers
            noise_elevation = noise.snoise2(world_x * 0.005, world_y * 0.005, octaves=4)
            noise_temperature = noise.snoise2(world_x * 0.01, world_y * 0.01, octaves=4)
            noise_moisture = noise.snoise2(world_x * 0.015, world_y * 0.015, octaves=4)

            elevation = int((noise_elevation + 1) * 128)
            temperature = min(max(noise_temperature, -1.0), 1.0)
            moisture = min(max(noise_moisture, -1.0), 1.0)

            # Assign biome based on elevation, temperature, and moisture
            color = colors["water"]  # Default to water
            if elevation > biomes["water"]["elevation"][1]:
                # Match land biomes
                for biome_name, info in biomes.items():
                    if biome_name == "water":
                        continue
                    if (elevation >= info["elevation"][0] and elevation <= info["elevation"][1]
                        and temperature >= info["temperature"][0] and temperature <= info["temperature"][1]
                        and moisture >= info["moisture"][0] and moisture <= info["moisture"][1]):
                        color = info["color"]
                        break
            
            row.append((elevation, color))
            # Draw tile to chunk surface
            pygame.draw.rect(chunk_surface, color, pygame.Rect(x*tile_size, y*tile_size, tile_size, tile_size))
        
        chunk_data.append(row)
    
    return chunk_surface, chunk_data

# Function to generate a new random seed for world generation
def generate_new_seed():
    return random.randint(0, 1000000)

# Player movement variables
player_x = screen_width // 2
player_y = screen_height // 2
scroll_speed = 5

# World generation parameters
chunk_size = 100
# Current visible chunk coordinates
current_chunks = set()

# Set initial random seed for world generation
random_seed = generate_new_seed()
random.seed(random_seed)
noise.seed(random_seed)  # Set seed for noise library too

# Game loop
running = True
clock = pygame.time.Clock()

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_n:  # Press "N" key to generate a new world
                random_seed = generate_new_seed()
                random.seed(random_seed)
                noise.seed(random_seed)
                chunk_cache.clear()  # Clear old chunks
                print(f"Generating new world with seed: {random_seed}")

    # Player movement
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player_x -= scroll_speed
    if keys[pygame.K_RIGHT]:
        player_x += scroll_speed
    if keys[pygame.K_UP]:
        player_y -= scroll_speed
    if keys[pygame.K_DOWN]:
        player_y += scroll_speed

    # Calculate which chunks are visible
    visible_chunk_x_min = (player_x - screen_width//2) // (chunk_size * tile_size)
    visible_chunk_x_max = (player_x + screen_width//2) // (chunk_size * tile_size)
    visible_chunk_y_min = (player_y - screen_height//2) // (chunk_size * tile_size)
    visible_chunk_y_max = (player_y + screen_height//2) // (chunk_size * tile_size)

    # Load visible chunks
    new_current_chunks = set()
    for chunk_x in range(visible_chunk_x_min - 1, visible_chunk_x_max + 2):
        for chunk_y in range(visible_chunk_y_min - 1, visible_chunk_y_max + 2):
            chunk_key = (chunk_x, chunk_y)
            new_current_chunks.add(chunk_key)
            if chunk_key not in chunk_cache:
                # Generate new chunk if not in cache
                chunk_surface, chunk_data = generate_chunk(chunk_x, chunk_y, chunk_size)
                chunk_cache[chunk_key] = (chunk_surface, chunk_data)
    
    current_chunks = new_current_chunks

    # Clear screen and draw visible chunks
    screen.fill((0, 0, 0))
    for chunk_x, chunk_y in current_chunks:
        chunk_surface, _ = chunk_cache[(chunk_x, chunk_y)]
        # Calculate position on screen
        screen_x = chunk_x * chunk_size * tile_size - (player_x - screen_width//2)
        screen_y = chunk_y * chunk_size * tile_size - (player_y - screen_height//2)
        screen.blit(chunk_surface, (screen_x, screen_y))

    # Update display
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

内容的提问来源于stack exchange,提问作者Nery Lemus Salguero - Student

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:37:05