如何在 pygame 中创建二维滚动平铺地图?
How can I create a 2-d scrolling tiled map in pygame?
我正在创建类似 RPG 的游戏,但是,我完全不知道如何滚动地图以使玩家位于中心。您可能有的任何其他建议也将不胜感激!感谢你的帮助!这是我的代码:
import pygame
from pytmx import load_pygame
pygame.init()
transparent = (0,0,0,0)
black = (0,0,0)
white = (255,255,255)
x,y = 0,0
moveSpeed = 5
#create window
screenSize = (800,600)
screen = pygame.display.set_mode(screenSize)
pygame.display.set_caption("Frozen")
gameMap = load_pygame("Frozen.tmx")
def getMap(layer):
#creates list of single tiles
images = []
for y in range(50):
for x in range(50):
image = gameMap.get_tile_image(x,y,layer)
images.append(image)
#displays tiles in locations
i = 0
for y in range(50):
for x in range(50):
screen.blit(images[i],(x*32,y*32))
i += 1
def getProperties():
#gets properties of tiles in map
properties = []
for y in range(50):
for x in range(50):
tileProperties = gameMap.get_tile_properties(x,y,3)
properties.append(tileProperties)
return properties
def createBoxes():
#creates collision rectangles for unpassable tiles
noWalkLocs = []
rects = []
i = 0
testSurf = pygame.Surface(screenSize).convert_alpha()
testSurf.fill(transparent)
for y in range(50):
for x in range(50):
tileProperties = properties[i]
walkable = tileProperties.get("walkable")
if walkable == "False":
rect = pygame.draw.rect(testSurf,(0,0,0, 0),(x*32,y*32,32,32))
rects.append(rect)
i += 1
return rects
def getCollisions():
global x
global y
collisionLoc = player.rect.collidelist(rects)
collision = rects[collisionLoc]
if player.rect.collidepoint(collision.bottomleft):
if x > 0 and y < 0:
player.rect.topright = collision.bottomleft
x,y = 0, 0
elif x > 0:
player.rect.right = collision.left
x =0
elif y < 0:
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.topleft):
if x > 0 and y > 0:
player.rect.bottomright = collision.topleft
x,y = 0, 0
elif x > 0:
player.rect.right = collision.left
x =0
elif y > 0:
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.bottomright):
if x < 0 and y <0:
player.rect.topleft = collision.bottomright
x,y = 0, 0
elif x < 0:
player.rect.left = collision.right
x =0
elif y < 0:
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.topright):
if x < 0 and y > 0:
player.rect.bottomleft = collision.topright
x,y = 0, 0
elif x < 0:
player.rect.left = collision.right
x =0
elif y > 0:
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.midbottom):
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.midtop):
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.midright):
player.rect.left = collision.right
x = 0
elif player.rect.collidepoint(collision.midleft):
player.rect.right = collision.left
x = 0
return player.rect.x, player.rect.y, x, y
class sprite(pygame.sprite.Sprite):
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
self.x,self.y = x,y
self.image = standFront
self.rect = self.image.get_rect()
self.frontImages = [standFront,walkFront1,walkFront2,walkFront3]
self.backImages = [standBack,walkBack1,walkBack2,walkBack3]
self.leftImages = [standLeft,walkLeft1,walkLeft2,walkLeft3]
self.rightImages = [standRight,walkRight1,walkRight2,walkRight3]
self.index = 0
def walkFront(self):
self.index += 1
if self.index >= len(self.frontImages):
self.index=0
self.image = self.frontImages[self.index]
def walkBack(self):
self.index += 1
if self.index >= len(self.backImages):
self.index=0
self.image = self.backImages[self.index]
def walkLeft(self):
self.index += 1
if self.index >= len(self.leftImages):
self.index=0
self.image = self.leftImages[self.index]
def walkRight(self):
self.index += 1
if self.index >= len(self.rightImages):
self.index=0
self.image = self.rightImages[self.index]
def render(self):
screen.blit(self.image,(self.x,self.y))
self.rect.x, self.rect.y = self.x, self.y
#loads images
standFront = pygame.image.load("Images/Elsa Sprite/WalkFront/StandFront.png").convert_alpha()
walkFront1 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront1.png").convert_alpha()
walkFront2 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront2.png").convert_alpha()
walkFront3 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront3.png").convert_alpha()
standBack = pygame.image.load("Images/Elsa Sprite/WalkBack/StandBack.png").convert_alpha()
walkBack1 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack1.png").convert_alpha()
walkBack2 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack2.png").convert_alpha()
walkBack3 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack3.png").convert_alpha()
standLeft = pygame.image.load("Images/Elsa Sprite/WalkLeft/StandLeft.png").convert_alpha()
walkLeft1 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft1.png").convert_alpha()
walkLeft2 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft2.png").convert_alpha()
walkLeft3 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft3.png").convert_alpha()
standRight = pygame.image.load("Images/Elsa Sprite/WalkRight/StandRight.png").convert_alpha()
walkRight1 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight1.png").convert_alpha()
walkRight2 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight2.png").convert_alpha()
walkRight3 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight3.png").convert_alpha()
#creates tick
clock = pygame.time.Clock()
#creates player
player = sprite(250, 300)
properties = getProperties()
rects = createBoxes()
#main loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#gets keypresses
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x, y = 0, 0
x -= moveSpeed
elif event.key == pygame.K_RIGHT:
x, y = 0, 0
x += moveSpeed
elif event.key == pygame.K_UP:
x, y = 0, 0
y -= moveSpeed
elif event.key == pygame.K_DOWN:
x, y = 0, 0
y += moveSpeed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x = 0
player.image = player.leftImages[0]
elif event.key == pygame.K_RIGHT:
x = 0
player.image = player.rightImages[0]
elif event.key == pygame.K_UP:
y = 0
player.image = player.backImages[0]
elif event.key == pygame.K_DOWN:
y = 0
player.image = player.frontImages[0]
player.x += x
player.y += y
if y > 0:
player.walkFront()
if y < 0:
player.walkBack()
if x > 0:
player.walkRight()
if x < 0:
player.walkLeft()
getMap(0)
getMap(1)
getMap(2)
player.render()
pygame.display.flip()
player.rect.x, player.rect.y, x, y = getCollisions()
player.x, player.y = player.rect.x, player.rect.y
clock.tick(10)
pygame.quit()
您可以使用 PyGames .scroll()
方法。不要更改 player
的 x
和 y
坐标,而是调用 tieldMap.scroll()
函数并将新的 x
和 y
传递给它(即mx
和 my
) 值。
为此你需要两个表面,主要screen
表面(你已经有),另一个你可以"scroll"(例如tieldMap
).
在 pygame.init()
函数调用后的某处添加此行:
mapSize = (120,120) #change this values
tieldMap = pygame.Surface(mapSize)
mx, my = 0, 0
并将您的 getMap()
函数中的代码(您将磁贴 blit 到主 screen
上)更改为:
#displays tiles in locations
i = 0
for y in range(50):
for x in range(50):
tieldMap.blit(images[i],(x*32,y*32))
i += 1
现在您可以 "scroll" 主游戏循环中的 tieldMap
表面:
更改此行
player.x += x
player.y += y
到
mx += x
my += y
添加这两行以创建一个名为 _tieldMap
的副本 tieldMap
表面 (.copy
) 并调用 .scroll
函数。
_tieldMap = tieldMap.copy()
_tieldMap.scroll(xm, ym)
最后在主游戏循环中将 tieldMap
表面 blit 到 (0,0)
的 screen
并更新它:
screen.blit(_tieldMap,(0,0))
pygame.display.flip()
重要提示:您必须检查 xm
或 ym
是否小于或大于图像的高度或宽度!
希望对您有所帮助:)
我正在创建类似 RPG 的游戏,但是,我完全不知道如何滚动地图以使玩家位于中心。您可能有的任何其他建议也将不胜感激!感谢你的帮助!这是我的代码:
import pygame
from pytmx import load_pygame
pygame.init()
transparent = (0,0,0,0)
black = (0,0,0)
white = (255,255,255)
x,y = 0,0
moveSpeed = 5
#create window
screenSize = (800,600)
screen = pygame.display.set_mode(screenSize)
pygame.display.set_caption("Frozen")
gameMap = load_pygame("Frozen.tmx")
def getMap(layer):
#creates list of single tiles
images = []
for y in range(50):
for x in range(50):
image = gameMap.get_tile_image(x,y,layer)
images.append(image)
#displays tiles in locations
i = 0
for y in range(50):
for x in range(50):
screen.blit(images[i],(x*32,y*32))
i += 1
def getProperties():
#gets properties of tiles in map
properties = []
for y in range(50):
for x in range(50):
tileProperties = gameMap.get_tile_properties(x,y,3)
properties.append(tileProperties)
return properties
def createBoxes():
#creates collision rectangles for unpassable tiles
noWalkLocs = []
rects = []
i = 0
testSurf = pygame.Surface(screenSize).convert_alpha()
testSurf.fill(transparent)
for y in range(50):
for x in range(50):
tileProperties = properties[i]
walkable = tileProperties.get("walkable")
if walkable == "False":
rect = pygame.draw.rect(testSurf,(0,0,0, 0),(x*32,y*32,32,32))
rects.append(rect)
i += 1
return rects
def getCollisions():
global x
global y
collisionLoc = player.rect.collidelist(rects)
collision = rects[collisionLoc]
if player.rect.collidepoint(collision.bottomleft):
if x > 0 and y < 0:
player.rect.topright = collision.bottomleft
x,y = 0, 0
elif x > 0:
player.rect.right = collision.left
x =0
elif y < 0:
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.topleft):
if x > 0 and y > 0:
player.rect.bottomright = collision.topleft
x,y = 0, 0
elif x > 0:
player.rect.right = collision.left
x =0
elif y > 0:
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.bottomright):
if x < 0 and y <0:
player.rect.topleft = collision.bottomright
x,y = 0, 0
elif x < 0:
player.rect.left = collision.right
x =0
elif y < 0:
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.topright):
if x < 0 and y > 0:
player.rect.bottomleft = collision.topright
x,y = 0, 0
elif x < 0:
player.rect.left = collision.right
x =0
elif y > 0:
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.midbottom):
player.rect.top = collision.bottom
y = 0
elif player.rect.collidepoint(collision.midtop):
player.rect.bottom = collision.top
y = 0
elif player.rect.collidepoint(collision.midright):
player.rect.left = collision.right
x = 0
elif player.rect.collidepoint(collision.midleft):
player.rect.right = collision.left
x = 0
return player.rect.x, player.rect.y, x, y
class sprite(pygame.sprite.Sprite):
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
self.x,self.y = x,y
self.image = standFront
self.rect = self.image.get_rect()
self.frontImages = [standFront,walkFront1,walkFront2,walkFront3]
self.backImages = [standBack,walkBack1,walkBack2,walkBack3]
self.leftImages = [standLeft,walkLeft1,walkLeft2,walkLeft3]
self.rightImages = [standRight,walkRight1,walkRight2,walkRight3]
self.index = 0
def walkFront(self):
self.index += 1
if self.index >= len(self.frontImages):
self.index=0
self.image = self.frontImages[self.index]
def walkBack(self):
self.index += 1
if self.index >= len(self.backImages):
self.index=0
self.image = self.backImages[self.index]
def walkLeft(self):
self.index += 1
if self.index >= len(self.leftImages):
self.index=0
self.image = self.leftImages[self.index]
def walkRight(self):
self.index += 1
if self.index >= len(self.rightImages):
self.index=0
self.image = self.rightImages[self.index]
def render(self):
screen.blit(self.image,(self.x,self.y))
self.rect.x, self.rect.y = self.x, self.y
#loads images
standFront = pygame.image.load("Images/Elsa Sprite/WalkFront/StandFront.png").convert_alpha()
walkFront1 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront1.png").convert_alpha()
walkFront2 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront2.png").convert_alpha()
walkFront3 = pygame.image.load("Images/Elsa Sprite/WalkFront/WalkFront3.png").convert_alpha()
standBack = pygame.image.load("Images/Elsa Sprite/WalkBack/StandBack.png").convert_alpha()
walkBack1 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack1.png").convert_alpha()
walkBack2 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack2.png").convert_alpha()
walkBack3 = pygame.image.load("Images/Elsa Sprite/WalkBack/WalkBack3.png").convert_alpha()
standLeft = pygame.image.load("Images/Elsa Sprite/WalkLeft/StandLeft.png").convert_alpha()
walkLeft1 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft1.png").convert_alpha()
walkLeft2 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft2.png").convert_alpha()
walkLeft3 = pygame.image.load("Images/Elsa Sprite/WalkLeft/WalkLeft3.png").convert_alpha()
standRight = pygame.image.load("Images/Elsa Sprite/WalkRight/StandRight.png").convert_alpha()
walkRight1 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight1.png").convert_alpha()
walkRight2 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight2.png").convert_alpha()
walkRight3 = pygame.image.load("Images/Elsa Sprite/WalkRight/WalkRight3.png").convert_alpha()
#creates tick
clock = pygame.time.Clock()
#creates player
player = sprite(250, 300)
properties = getProperties()
rects = createBoxes()
#main loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#gets keypresses
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x, y = 0, 0
x -= moveSpeed
elif event.key == pygame.K_RIGHT:
x, y = 0, 0
x += moveSpeed
elif event.key == pygame.K_UP:
x, y = 0, 0
y -= moveSpeed
elif event.key == pygame.K_DOWN:
x, y = 0, 0
y += moveSpeed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x = 0
player.image = player.leftImages[0]
elif event.key == pygame.K_RIGHT:
x = 0
player.image = player.rightImages[0]
elif event.key == pygame.K_UP:
y = 0
player.image = player.backImages[0]
elif event.key == pygame.K_DOWN:
y = 0
player.image = player.frontImages[0]
player.x += x
player.y += y
if y > 0:
player.walkFront()
if y < 0:
player.walkBack()
if x > 0:
player.walkRight()
if x < 0:
player.walkLeft()
getMap(0)
getMap(1)
getMap(2)
player.render()
pygame.display.flip()
player.rect.x, player.rect.y, x, y = getCollisions()
player.x, player.y = player.rect.x, player.rect.y
clock.tick(10)
pygame.quit()
您可以使用 PyGames .scroll()
方法。不要更改 player
的 x
和 y
坐标,而是调用 tieldMap.scroll()
函数并将新的 x
和 y
传递给它(即mx
和 my
) 值。
为此你需要两个表面,主要screen
表面(你已经有),另一个你可以"scroll"(例如tieldMap
).
在 pygame.init()
函数调用后的某处添加此行:
mapSize = (120,120) #change this values
tieldMap = pygame.Surface(mapSize)
mx, my = 0, 0
并将您的 getMap()
函数中的代码(您将磁贴 blit 到主 screen
上)更改为:
#displays tiles in locations
i = 0
for y in range(50):
for x in range(50):
tieldMap.blit(images[i],(x*32,y*32))
i += 1
现在您可以 "scroll" 主游戏循环中的 tieldMap
表面:
更改此行
player.x += x player.y += y
到
mx += x my += y
添加这两行以创建一个名为
_tieldMap
的副本tieldMap
表面 (.copy
) 并调用.scroll
函数。_tieldMap = tieldMap.copy() _tieldMap.scroll(xm, ym)
最后在主游戏循环中将 tieldMap
表面 blit 到 (0,0)
的 screen
并更新它:
screen.blit(_tieldMap,(0,0))
pygame.display.flip()
重要提示:您必须检查 xm
或 ym
是否小于或大于图像的高度或宽度!
希望对您有所帮助:)