Das hat mich seit Tagen beschäftigt. Ich versuche, ein Spiel mit einem in der Mitte fixierten Spieler zu erstellen, und einen Kachel-basierten Hintergrund, der sich flüssig hinter dem Spieler bewegt und zusätzliche Kachelbilder erzeugt, wenn der Spieler sich bewegt. Der Hintergrund funktioniert soweit perfekt.Python (Pygame) - Objektinstanzen bewegen sich mit unterschiedlicher Geschwindigkeit zum Hintergrund
Das Problem tritt auf, wenn ich Objekte zum Hintergrund (z. B. einen Baum) hinzufügen möchte. Ich möchte, dass dieses Objekt an einem bestimmten Hintergrundort fixiert bleibt, aber wenn sich der Spieler bewegt, bewegt sich das Objekt allmählich in Relation zum Hintergrund. Das heißt, das Objekt bewegt sich, wenn sich der Spieler bewegt (wie es sein sollte), aber es bewegt sich auch viel .
Ich habe die Ursache auf die World.update-Methode, den Abschnitt self.tileShift, isoliert. Wenn Sie diesen gesamten if/elif-Abschnitt entfernen, sieht das Verhalten gut aus (außer natürlich, dass der Hintergrund nicht richtig aktualisiert wird, daher brauchen wir diesen Abschnitt). Irgendwie, wenn der tileShift überspringt, überspringt jedes Objekt auf dem Bildschirm auch ein paar Pixel. Nachdem ich über eine Woche lang geforscht und experimentiert habe, kann ich es immer noch nicht beheben. Ich habe versucht, das Bild zu ändern, den tileShift Cutoff-Punkt zu ändern, die Reihenfolge des Aufrufs von update/draw-Methoden usw. zu ändern.
Siehe unten (massiv abgespeckte, aber eigenständige) Code unten. Beachten Sie, dass wir ein Hintergrundkachelbild mit Mustern benötigen (siehe Weltklasse init), sonst können Sie das beschriebene Verhalten nicht sehen, da die fehlerhafte Bewegung so graduell ist. Verwenden Sie für eine optimale Leistung ein 70 x 70 PNG-Bild.
Hoffentlich macht diese Erklärung Sinn, bitte lassen Sie mich wissen, wenn zusätzliche Informationen erforderlich sind. Jede Hilfe würde sehr geschätzt werden !!
import pygame
# Initialisation
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 850
pygame.init() # Initialise pygame
window = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # Set the window surface (the main screen of the game)
pygame.display.set_caption("Game") # Game window caption
window_rect = window.get_rect()
# GLOBAL VARIABLES
WorldMove = dict(x=0, y=0) # List for the direction and amount the background moves as the player moves
PlayerMoveSpeed = 5
# CLASSES
class World(pygame.sprite.Sprite):
def __init__(self):
self.tileShift = dict(x=0, y=0) # Tracker for when the player has passed from one map tile to another
# Load and set up the tile images
self.tiles = pygame.image.load("Images\Tiles\Tile.png")
self.tileSize = self.tiles.get_rect().size[0] # Assumes a square size
self.map = pygame.Surface((self.tileSize*14,self.tileSize*15)) # Visible area surface size, based on tile size
self.rect = self.map.get_rect() # Create a rect attribute for the World, so it can be blitted to the window
self.rect.x, self.rect.y = -self.tileSize,-self.tileSize # The map is blitted starting one tile size above left of the screen (so we see no whitespace)
def update(self):
# Move the map around the player based on WorldMove, which is set in the player_move function
self.rect.x += WorldMove["x"]
self.rect.y += WorldMove["y"]
# Update the tileShift based on player movement so we know when they've moved onto another tile
if WorldMove["x"] != 0: self.tileShift["x"] -= WorldMove["x"]
if WorldMove["y"] != 0: self.tileShift["y"] -= WorldMove["y"]
# Once the self.tileShift has passed the size of one of the tile images, reset it and move self.matrix by 1
if self.tileShift["x"] < -self.tileSize:
self.tileShift["x"] = 0 # Reset the tileShift variable
self.rect.x = -self.tileSize # Reset the point from which the map is blitted to window to top left of visible screen
elif self.tileShift["x"] > self.tileSize:
self.tileShift["x"] = 0
self.rect.x = -self.tileSize
if self.tileShift["y"] > self.tileSize:
self.tileShift["y"] = 0
self.rect.y = -self.tileSize
elif self.tileShift["y"] < -self.tileSize:
self.tileShift["y"] = 0
self.rect.y = -self.tileSize
def draw(self):
# Draw the tiles in a grid in the visible area
for y in range(15): # Visible number of tiles on y axis
for x in range(14): # Visible number of tiles on x axis
self.map.blit(self.tiles, (self.tileSize*x, self.tileSize*y)) # Blit each tile onto self.map
window.blit(self.map, self.rect) # Blit self.map onto the window
class Player(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.Surface((35, 35))
self.image.fill((0, 0, 0))
self.rect = (SCREEN_WIDTH/2, SCREEN_HEIGHT/2) # Player is always in middle of screen
def player_move(self):
global WorldMove # Make sure that we're referring to and updating the global variable for the world movement
key = pygame.key.get_pressed()
x, y = 0, 0
if key[pygame.K_w] or key[pygame.K_UP]: y = PlayerMoveSpeed
if key[pygame.K_d] or key[pygame.K_RIGHT]: x = -PlayerMoveSpeed
if key[pygame.K_a] or key[pygame.K_LEFT]: x = PlayerMoveSpeed
if key[pygame.K_s] or key[pygame.K_DOWN]: y = -PlayerMoveSpeed
if x != 0 and y != 0: # If more than one key pressed, move diagonally
WorldMove["x"] = int(x/1.5)
WorldMove["y"] = int(y/1.5)
else:
WorldMove["x"] = x
WorldMove["y"] = y
def draw(self):
window.blit(self.image, self.rect)
class Object(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.Surface((50,100))
self.image.fill((50,50,250))
self.rect = self.image.get_rect()
self.rect.center = window_rect.center
self.rect.x, self.rect.y = 100, 100 # Spawn location of the object
def update(self): # Move the object as the world moves around the player
self.rect.x += WorldMove["x"]
self.rect.y += WorldMove["y"]
def draw(self): # Blit the object onto the screen at its location
window.blit(self.image, self.rect)
# Set Objects
world = World()
object = Object()
player = Player()
# Main Loop
gameRunning = True
while gameRunning:
# Player events
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
gameRunning = False
player.player_move() # Move player based on movement key(s) pressed (if any)
# Class updates and drawing to the screen
window.fill((255, 255, 255)) # Fill the window with background white
world.update()
world.draw()
object.update()
object.draw()
player.draw()
pygame.display.update() # Refresh the display
# End - only reaches this point if gameRunning = False
pygame.quit()
Falls es hilft Ihnen, mehr Forschung zu tun, das ist genannt * Parallax * Scrollen. – jwg