2017-11-16 3 views
0

Ich versuche gerade, ein einfaches Plattformspiel auf Pygame zu programmieren, aber ich habe Probleme mit den Kollisionen, wenn ich versuche, die Kamerafunktionalität zum Spiel hinzuzufügen.Problem mit Kameraoffset und Kollisionen in Pygame

Hier ist mein Code:

Um nicht die Frage zu groß werde ich die Teile des Codes geschnitten, die die Bewegung enthalten, die Kollision und die Zeichnung.

Index.py

  • entfernte die init und setup_tiles Funktionen.

    import pygame 
    from settings import * 
    from tiles import * 
    from player import * 
    from camera import * 
    
    pygame.init() 
    
    
    class Window: 
    
        def game_loop(self): 
    
        while not self.crashed: 
    
         for event in pygame.event.get(): 
          if event.type == pygame.QUIT: 
           self.crashed = True 
    
         self.movement() 
    
         self.window.blit(self.background, (0, 0)) 
         self.all_sprites.clear(self.window, self.background) 
         self.player.update(self.all_sprites) 
         self.camera.update(self.player) 
         self.player.draw(self.window) 
         # self.all_sprites.draw(self.window) 
         for sprite in self.all_sprites: 
          self.window.blit(sprite.image, self.camera.apply(sprite)) 
    
         pygame.display.flip() 
    
         self.clock.tick(60) 
    
        quit() 
        pygame.quit() 
    
    def movement(self): 
        keys = pygame.key.get_pressed() 
    
        if keys[pygame.K_w]: 
         self.player.velocity_y = -3 
         self.player.rect.y += self.player.velocity_y 
         for sprite in self.all_sprites: 
          if self.player.collide_Y(sprite): 
           self.player.rect.y = self.player.rect.y - self.player.velocity_y 
    
        elif keys[pygame.K_s]: 
         self.player.velocity_y = 3 
         self.player.rect.y += self.player.velocity_y 
         for sprite in self.all_sprites: 
          if self.player.collide_Y(sprite): 
           self.player.rect.y = self.player.rect.y - self.player.velocity_y 
    
        if keys[pygame.K_a]: 
         self.player.velocity_x = -3 
         self.player.rect.x += self.player.velocity_x 
         for sprite in self.all_sprites: 
          if self.player.collide_X(sprite): 
           self.player.rect.x = self.player.rect.x - self.player.velocity_x 
    
        elif keys[pygame.K_d]: 
         self.player.velocity_x = 3 
         self.player.rect.x += self.player.velocity_x 
         for sprite in self.all_sprites: 
          if self.player.collide_X(sprite): 
           self.player.rect.x = self.player.rect.x - self.player.velocity_x 
    
    window = Window() 
    
    window.game_loop() 
    

Tiles.py

import pygame 
from settings import * 

class Tiles(pygame.sprite.Sprite): 

    def __init__(self, file, pos): 
     pygame.sprite.Sprite.__init__(self) 
     self.bitmap = pygame.image.load(file) 
     self.bitmap = pygame.transform.scale(self.bitmap, (TILE_SIZE, TILE_SIZE)) 
     self.image = pygame.Surface((TILE_SIZE, TILE_SIZE), pygame.HWSURFACE | pygame.SRCALPHA) 
     self.image.blit(self.bitmap, (0, 0)) 
     self.rect = self.image.get_rect() 
     self.rect.x, self.rect.y = pos 

Player.py

  • die init entfernt Funktion

    import pygame 
    from settings import * 
    
    
    class Player(pygame.sprite.Sprite): 
    
    def draw(self, window): 
        window.blit(self.image, (self.rect.x, self.rect.y)) 
    
    def collide_X(self, sprite): 
        if (self.rect.x + self.width >= sprite.rect.x >= self.rect.x and self.rect.y + self.height >= sprite.rect.y + TILE_SIZE >= 
         self.rect.y) or (self.rect.x + self.width >= sprite.rect.x + TILE_SIZE >= self.rect.x 
         and self.rect.y + self.height >= sprite.rect.y + TILE_SIZE >= self.rect.y) or (self.rect.x + self.width >= sprite.rect.x >= self.rect.x and 
         sprite.rect.y + TILE_SIZE >= self.rect.y + self.height >= sprite.rect.y >= self.rect.y): 
         print 'True' 
         return True 
        else: 
         return False 
    
    def collide_Y(self, sprite): 
        if (self.rect.y + self.height + self.velocity_y >= sprite.rect.y >= self.rect.y and self.rect.x + self.width >= 
         sprite.rect.x >= self.rect.x) or (self.rect.y + self.height >= sprite.rect.y + TILE_SIZE >= self.rect.y + self.velocity_y 
         and self.rect.x + self.width >= sprite.rect.x >= self.rect.x): 
         return True 
        else: 
         return False 
    

Camera.py

import pygame 
from settings import * 


class Camera: 
    def __init__(self, width, height): 
     self.camera = pygame.Rect(0, 0, width, height) 
     self.width = width 
     self.height = height 

    def apply(self, target): 
     return target.rect.move(self.camera.topleft) 

    def update(self, target): 
     x = - target.rect.x + int(WIDTH/2) 
     y = - target.rect.y + int(HEIGHT/2) 
     self.camera = pygame.Rect(x, y, self.width, self.height) 

Settings.py

WIDTH = 800 
HEIGHT = 600 

TILE_SIZE = 32 

LEVEL_1 = [ 
    'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'TTTTTTTTTB     V      V', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'B        V      V', 
    'B              V', 
    'B              V', 
    'B              V', 
    'B    VTTTTTTTTTTTTTTTTTTTTTTTTB    V', 
    'B        V      V', 
    'B        V      V', 
    'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT' 
] 

LEVEL_1_WIDTH = len(LEVEL_1[0])*TILE_SIZE 
LEVEL_1_HEIGHT = len(LEVEL_1)*TILE_SIZE 

Kollision ohne Kamera

enter image description here

Dies ist die Kollision ohne die Kamera, wie Sie es sehen können funktioniert gut.

Kollision mit Kamera

enter image description here

Wenn ich die Kamera-Funktionalität hinzufügen, ist es das, was

passiert, wenn Sie es entfernen Sie das # vom game_loop und kommentieren Sie die Zeichnung mit der Kamera testen möchten anwenden .

# self.all_sprites.draw(self.window) 
    for sprite in self.all_sprites: 
     self.window.blit(sprite.image, self.camera.apply(sprite)) 

Ich benutze Python 2.7 in einem Fenster 10 X 64-Maschine.

+0

verwenden Sie 'camera.apply()' mit allen Sprites aber nicht mit 'player' - es kann ein Problem sein. – furas

+1

BTW: Es könnte einfacher sein, wenn Sie kompletten Code mit Bildern auf GitHub oder einem anderen Portal erstellen - wir könnten es ausführen und testen. – furas

+0

Es funktioniert jetzt, danke @furas. Ich kann nicht glauben, dass etwas einfach das Problem verursacht hat. –

Antwort

1

Sie wenden die Transformation der Kamera einfach nicht auf Ihre player Instanz an: Sie wird in absoluten Spielkoordinaten gezeichnet, während alles andere in Kamerakoordinaten gezeichnet wird.

Die Kollisionsprüfungen hingegen werden immer in absoluten Koordinaten des Spiels durchgeführt.

Sie müssen die Kamera auf Ihren Player anwenden, bevor Sie sie ebenfalls zeichnen. Wie Ihr Code aussieht, müssen Sie den Player einfach zur Gruppe all_sprites hinzufügen und die Player.draw-Methode vollständig entfernen.Und dann, wenn Sie möchten, korrigieren Sie etwas auf der Methode, so dass, wenn am Rand der Karte, der Spieler nicht immer auf dem Bildschirm zentriert ist.