gpt4 book ai didi

python - 将滚动相机放在 pygame 的迷你窗口中

转载 作者:行者123 更新时间:2023-12-01 09:17:17 25 4
gpt4 key购买 nike

我正在尝试创建一个游戏,其中的 Action 显示在主屏幕对象内的一个小框中,从而为文本和菜单等释放周围的空间。由于 map 比分配的窗口大,我编写了一个基本的“摄像机”来跟踪玩家。它大部分都有效,但我在“修剪”该窗口之外的区域时遇到了麻烦。

这是相关的代码位(经过编辑以提供工作示例):

import pygame, os, sys
from pygame.locals import *
pygame.init()

RIGHT = 'RIGHT'
LEFT = 'LEFT'
UP = 'UP'
DOWN = 'DOWN'

class Camera():
def __init__(self, screen, x_ratio = 1, y_ratio = 1, x_offset = 0, y_offset = 0):
self.screen = screen.copy()
self.rec = self.screen.get_rect()
self.rec.width *= x_ratio
self.rec.height *= y_ratio
self.x_offset = x_offset
self.y_offset = y_offset
def get_pos(self):
return (self.x_offset - self.rec.x, self.y_offset - self.rec.y)
def get_window(self):
w = pygame.Rect(self.rec)
w.topleft = (0 - self.rec.x, 0 - self.rec.y)
return w
def move(self, x, y):
"""Move camera into new position"""
self.rec.x = x
self.rec.y = y
def track(self, obj):
while obj.rec.left < self.rec.left:
self.rec.x -= 1
while obj.rec.right > self.rec.right:
self.rec.x += 1
while obj.rec.top < self.rec.top:
self.rec.y -= 1
while obj.rec.bottom > self.rec.bottom:
self.rec.y += 1

class Map:
def __init__(self, width, height):
self.width = width
self.height = height
self.rec = pygame.Rect(0,0,self.width,self.height)

def draw(self, screen):
pygame.draw.rect(screen, (200,200,200), self.rec)

class Obj:
def __init__(self, char, x = 0, y = 0, width = 0, height = 0):
self.width = width
self.height = height
self.rec = pygame.Rect(x, y, width, height)
self.cur_map = None
self.timers = {}

#Dummying in chars for sprites
self.char = char

self.x_dir = 1
self.y_dir = 1
self.speed = 1
self.moving = False

def move(self):
if self.x_dir != 0 or self.y_dir != 0:
new_x = self.rec.x + (self.x_dir*self.speed)
new_y = self.rec.y + (self.y_dir*self.speed)
new_rec = pygame.Rect(new_x, new_y, self.width, self.height)

#Keep movement within bounds of map
while new_rec.left < self.cur_map.rec.left:
new_rec.x += 1
while new_rec.right > self.cur_map.rec.right:
new_rec.x -= 1
while new_rec.top < self.cur_map.rec.top:
new_rec.y += 1
while new_rec.bottom > self.cur_map.rec.bottom:
new_rec.y -= 1

self.rec = new_rec

def set_dir(self, d):
self.x_dir = 0
self.y_dir = 0
if d == LEFT:
self.x_dir = -1
elif d == RIGHT:
self.x_dir = 1
elif d == UP:
self.y_dir = -1
elif d == DOWN:
self.y_dir = 1

def set_moving(self, val = True):
self.moving = val

class Game:
def __init__(self):
self.screen_size = (800, 600)
self.screen = pygame.display.set_mode(self.screen_size)
self.map_screen = self.screen.copy()
self.title = 'RPG'
pygame.display.set_caption(self.title)

self.camera = Camera(self.screen, 0.75, 0.75)#, 10, 75)

self.fps = 80
self.clock = pygame.time.Clock()
self.debug = False
self.bg_color = (255,255,255)
self.text_size = 18
self.text_font = 'Arial'
self.text_style = pygame.font.SysFont(self.text_font, self.text_size)
self.key_binds = {LEFT : [K_LEFT, K_a], RIGHT : [K_RIGHT, K_d], UP : [K_UP, K_w], DOWN : [K_DOWN, K_s],
'interact' : [K_RETURN, K_z], 'inventory' : [K_i, K_SPACE], 'quit' : [K_ESCAPE]}

self.player = Obj('p', 0, 0, 10, self.text_size)

def draw(self, obj):
char = obj.char
self.draw_text(char, obj.rec.x, obj.rec.y, screen = self.map_screen)

def draw_text(self, text, x, y, color = (0,0,0), screen = None):
textobj = self.text_style.render(text, 1, color)
textrect = textobj.get_rect()
textrect.x = x
textrect.y = y
if screen == None:
"""Use default screen"""
self.screen.blit(textobj, textrect)
else:
screen.blit(textobj, textrect)

def play(self):
done = False
cur_map = Map(800, 800)
self.map_screen = pygame.Surface((cur_map.width, cur_map.height))
self.map_screen.fill(self.bg_color)

bg = pygame.Surface((cur_map.width, cur_map.height))
cur_map.draw(bg)

self.player.cur_map = cur_map

while not done:

for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key in self.key_binds[LEFT]:
self.player.set_dir(LEFT)
self.player.set_moving()
elif event.key in self.key_binds[RIGHT]:
self.player.set_dir(RIGHT)
self.player.set_moving()
elif event.key in self.key_binds[UP]:
self.player.set_dir(UP)
self.player.set_moving()
elif event.key in self.key_binds[DOWN]:
self.player.set_dir(DOWN)
self.player.set_moving()

elif event.type == KEYUP:
self.player.set_moving(False)


if self.player.moving:
self.player.move()

self.camera.track(self.player)
self.clock.tick()

self.screen.fill(self.bg_color)
self.map_screen.blit(bg, (0,0))
self.draw(self.player)

pygame.draw.rect(self.map_screen, (0,0,0), self.camera.rec, 1)
#self.screen.blit(self.map_screen, (0,0), [0 - self.camera.rec.x, 0 - self.camera.rec.y, self.camera.rec.width, self.camera.rec.height])
self.screen.blit(self.map_screen, self.camera.get_pos(), self.camera.get_window())
pygame.display.flip()

game = Game()
game.play()

将玩家移过相机窗口的边界会导致窗口完全卷起并消失。我尝试按照之前的建议调整位 block 传送坐标,但它似乎只改变了窗口滚动的方向。

最佳答案

根据更新后的代码,self.screen.blit(...) 的 blitting 坐标仍在更改:self.camera.get_window() 更改值,因为rec.xrec.y 是指 map 内玩家位置的值。因此,您应该定义一个恒定的小 map 坐标,这应该与相机偏移相同。

self.screen.blit(self.map_screen, (self.camera.x_offset,self.camera.y_offset), (*self.camera.get_pos(), self.camera.rec.width, self.camera.rec.height))

Camera().get_pos()更改为:

def get_pos(self):
return (self.rec.x, self.rec.y)

我相信我只更改了 self.screen.blit(...) 并停止使用或重写了您的相机函数,因为您对所有的记录变量感到困惑。

为了说明其工作原理,请将 Map().draw(screen) 修改为:

def draw(self, screen):
pygame.draw.rect(screen, (200,200,200), self.rec)
pygame.draw.circle(screen, (255, 255, 255), (50, 50), 20, 2)

还有一个提示,不要在每次循环时绘制整个 map ,只绘制可见的部分。

关于python - 将滚动相机放在 pygame 的迷你窗口中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51127095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com