我正在尝试实现一个相机功能,其工作原理是图像移动 - 但是:
1)后续图像(例如新菜单)将在如果我没有移动相机的话本应创建的位置创建。因此,如果我将相机向右移动 30 像素,则原本在 (0,0) 处创建的后续图像现在将在 (30,0) 处创建。 这也适用于与按钮的交互;在上面的示例中,要使用在 (0,0) 创建的按钮,我需要将鼠标放在 (0,0) 上,即使该按钮现在显示在 (30,0)
因此,如果我移动相机,我会得到类似 https://i.sstatic.net/yfiRH.png 的结果(看看我如何在鼠标位于新游戏上方时选择新游戏?我的鼠标在哪里,就是在哪里)该按钮是在我移动相机之前)或https://i.sstatic.net/VjOoe.png(游戏会记住我在上一个菜单中移动相机,现在在相同的位置创建下一个菜单)原来的菜单是,在我移动相机之前
2)如果我创建一个大于屏幕宽度或屏幕高度的图像,然后移动相机,我实际上看不到图像的其余部分。相反,我看到这样的东西:https://i.sstatic.net/JwtQs.png
因此,游戏不会显示地图的其余部分,而是仅移动快照(尺寸为屏幕宽度乘屏幕高度):https://i.sstatic.net/S64q2.png - 但如果我放大菜单,你可以看到地图实际上应该大得多,而且我显然希望在移动相机时看到地图的其余部分:https://i.sstatic.net/YSN7s.png
相关变量在Controller类中声明:
windowWidth = 800 #1792
windowHeight = 600 #896
windowResize = False
cameraactive = False
camera = pygame.display.set_mode((windowWidth, windowHeight))
screen = pygame.Surface((windowWidth, windowHeight))
mouse = pygame.mouse.get_pos()
camerax = 0
cameray = 0
sprites = pygame.sprite.Group()
# All the other sprite.Group()s, such as spritesciv, are created just like this one
spriteslist = [sprites , spritesciv , tiles , cities , texttiles , textcities , textcitiesselected , buttonscitiesselected , textbuttonscitiesselected , buttons , buttonsselectciv , buttonsrandomciv , textinputs]
buttonslist = [tiles , cities , buttonscitiesselected , buttons , buttonsselectciv , buttonsrandomciv , textinputs]
相关功能,全部在Controller内
def on_event(self):
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
self._running = False
if keys[K_ESCAPE]:
self._running = False
if event.type == MOUSEMOTION:
Controller.mouse = pygame.mouse.get_pos()
if event.type == pygame.VIDEORESIZE: #Controller.windowResize
screensize = event.size
Controller.windowWidth = event.w
Controller.windowHeight = event.h
screen = pygame.display.set_mode(screensize,RESIZABLE)
if self.cameraactive:
if Controller.mouse[0]<50:
self.camerax += 8
if (self.windowWidth - Controller.mouse[0])<50:
self.camerax -= 8
if Controller.mouse[1]<50:
self.cameray += 8
if (self.windowHeight - Controller.mouse[1])<50:
self.cameray -= 8
if keys[K_SPACE] and event.type == pygame.KEYUP:
self.nextturn()
if keys[K_TAB] and event.type == pygame.KEYUP:
i = Controller.civilisationsactive.index(Controller.civilisation)
if i < (len(Controller.civilisationsactive)-1):
Controller.civilisation = Controller.civilisationsactive[i + 1]
else:
Controller.civilisation = Controller.civilisationsactive[0]
for i in Controller.buttonslist:
for button in i:
button._create_event(event)
def empty_draw(self):
for i in Controller.spriteslist:
i.empty()
def on_draw(self):
self.screen.fill((255, 255, 255))
for i in Controller.spriteslist:
i.draw(self.screen)
self.camera.blit(self.screen, (self.camerax, self.cameray))
pygame.display.flip()
pygame.display.update()
非常感谢您的帮助。 :)
您可以使用完整地图创建表面并在屏幕上复制该地图的部分内容
screen.blit(fullmap, (0,0), camera)
但我会使用不同的名称:
screen
(最终 window
)- 使用 set_mode((800,600))
创建的曲面
fullmap
- 使用 Surface((2000, 1000))
创建的曲面来绘制所有元素
camera
- Rect
,而不是 Surface
与相机的位置/偏移
最少的工作代码。
我使用箭头更改
camera
(Rect
) 的位置 (x,y) 并检查该矩形是否没有留下完整地图。
后来我使用这个矩形
camera
将地图的一部分复制到屏幕上。
我还添加了“图标”,它是单独传输的 - 总是在同一个位置 - 所以它永远不会随着箭头移动。
import pygame
import random # to draw random rectangles on map
# --- constants ---
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
COLORS = (RED, GREEN, BLUE)
TILE_SIZE = 50
# --- main ---
pygame.init()
# - window -
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()
# - map - (with random rectangles)
fullmap = pygame.Surface((2000, 1000))
#for y in range(TILE_SIZE, 1000-TILE_SIZE, TILE_SIZE):
# for x in range(TILE_SIZE, 2000-TILE_SIZE, TILE_SIZE):
for y in range(0, 1000, TILE_SIZE):
for x in range(0, 2000, TILE_SIZE):
pygame.draw.rect(fullmap, random.choice(COLORS), (x, y, TILE_SIZE, TILE_SIZE))
fullmap_rect = fullmap.get_rect()
# - icon(s) which not move -
icon = pygame.Surface((100, 100))
icon.fill((255,255,255))
icon_rect = icon.get_rect()
icon_rect.right = screen_rect.right - 10
icon_rect.bottom = screen_rect.bottom - 10
# - camera -
# `camera` is not `Surface` but only `Rect` with value/offset which I uses to cut map
camera = screen.get_rect()
# --- loop ---
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
# - updates (without draws) -
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
camera.x -= 5
if camera.left < fullmap_rect.left:
camera.left = fullmap_rect.left
if keys[pygame.K_RIGHT]:
camera.x += 5
if camera.right > fullmap_rect.right:
camera.right = fullmap_rect.right
if keys[pygame.K_UP]:
camera.y -= 5
if camera.top < fullmap_rect.top:
camera.top = fullmap_rect.top
if keys[pygame.K_DOWN]:
camera.y += 5
if camera.bottom > fullmap_rect.bottom:
camera.bottom = fullmap_rect.bottom
# - draws (without updates) -
# moving map - using `camera` to copy part of `fullmap` to `screen`
screen.blit(fullmap, (0,0), camera)
# static icon(s)
screen.blit(icon, icon_rect)
pygame.display.update()
# --- end ---
pygame.quit()