Pygame kollisionen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Dienstag 17. März 2020, 16:56

Hallo ich versuche ein spiel zu programmieren, aber scheitere bei der Kollision eines Stachels und dem Spieler. :roll:
Wenn ihr die Bilder dazu braucht kann ich einen 1️⃣ Drive Link schicken, aber ich hoffe dass ihr mir anhand des Codes helfen könnt.🙃
Liebe Grüsse Fire Spike :)

Code: Alles auswählen

import sys
import pygame
import random
import time

WINDOW_TITLE = "Game" #Title of window
WHITE = (255, 255, 255) #White in RGB

FPS = 60 #Frames per second

screenx = 800 #x coordinates of the window
screeny = 1600 #y coordinates of the window

spikex = 816
spikey = 1056
playerx = 700 #x coordinates of the player

icon_paths = {
    "small" : "./Images/Icons/Icon_small.png", #71x71
    "medium" : "./Images/Icons/Icon_medium", #107x107
    "large" : "./Images/Icons/Icon_large" #142x142
}

pygame.init()
screen = pygame.display.set_mode((screeny, screenx))
pygame.display.set_caption(WINDOW_TITLE)

screen.fill(WHITE)
clock = pygame.time.Clock()

spikes = [] # List of all Spikes
del_queue = [] #Queue for spikes to be deleted

last_time = time.time()

class Spike():
    def __init__(self):
        self.step = 20
        self.playerx = 0 #- spikex
        self.playery = random.randrange(0, 1600)

    def down(self):
        self.playerx += self.step
        pygame.draw.polygon(
            screen,
            (255, 0, 0),
            (
                (self.playery, self.playerx),
                (self.playery + 100, self.playerx),
                (self.playery + 50, self.playerx + 100)
            )
        )
        
class Cube():
    def __init__(self, playery):
        self.step = 10
        self.playery = playery
        self.playericon = pygame.image.load(icon_paths["small"])

    def left(self):
        self.playery -= self.step
        self.update()
        
    def right(self):
        self.playery += self.step
        self.update()
        
    def update(self):
        screen.blit(self.playericon, (self.playery, playerx))

player = Cube(650)

while True:
    screen.fill(WHITE)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
            
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit()

    if pygame.key.get_pressed()[pygame.K_RIGHT]:
        player.right()

    if pygame.key.get_pressed()[pygame.K_LEFT]:
        player.left()
    
    if time.time() - last_time > 0.1:
        spikes.append(Spike())
        last_time = time.time()
        
    for i in range(len(spikes)):
        spikes[i].down()            
        if spikes[i].playerx > 800:
            del_queue.append(i)
        
    counter = 0
    for i in del_queue:
        del spikes[i-counter]
        counter += 1
            
    del_queue = []
    
    player.update()
    pygame.display.flip()
    clock.tick(FPS)
__deets__
User
Beiträge: 8423
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dienstag 17. März 2020, 19:15

Um Kollisionen zu pruefen gibt es pygame.rect, und das sollest du auch benutzen. Und statt dieses wirklich umstaendlichen del_queue-Gefummels ist es viel einfacher, NICHT mit dem beruehmten anti-pattern for i in range(len(spikes)) zu arbeiten, sondern gleich ueber die Liste zu iterieren. Und einfach in einer zweiten Liste die Spikes aufsammeln, die du behalten willst. Last but not least gehoert die Pruefung ob ein Spike noch sichtbar ist in eine Methode des Spikes, und nicht in die main-Funktion - die sollte da agnostisch sein. Und wenn du eh jede Runde einmal player update aufrufst (was ja auch richtig ist), dann ist es aber ein Fehler, dass in left/right zu machen.
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 18. März 2020, 13:56

Code optimiert💪🏻
Die Doku redet bei pygame.Rect immer nur über Rechtecke⁉️
__deets__
User
Beiträge: 8423
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 18. März 2020, 14:11

Ja und? Das reicht üblicherweise aus. Pixelgenaue Kollision braucht man selten bis nie. Zur Not zb 2 Rechtecke.
Benutzeravatar
__blackjack__
User
Beiträge: 6576
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 18. März 2020, 16:11

Egal ob nun pixelgenau oder Rechteck, für beides (und mehr) hat `pygame.sprite` Lösungen.
long long ago; /* in a galaxy far far away */
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Sonntag 22. März 2020, 21:20

Danke für die Idee mit Sprites. :D
Ich versuchte das umzusetzen, die Kollision funktioniert auch aber nur sehr ungenau :? 😭
Es kam auch noch ein neues Problem :oops: und zwar dass das Surface vom Spike den Player überlappt, das sollte hinter dem Player sein und das Weiss sollte transparent sein.
Bilder der Fehler mit dem Code im Link
Könnt ihr mir helfen❔
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Montag 23. März 2020, 09:59

Das mit der Transparents habe ich gelöst könnt ihr mir bitte 🌸 noch bei der Kollision helfen?

Edit:
Link aktualisiert.
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Mittwoch 25. März 2020, 20:45

Voy a hacer un experimento

Code: Alles auswählen

import sys
import pygame
import random
import time

WINDOW_TITLE = "Game" # Title of window

WHITE = (255, 255, 255) # White in RGB
RED = (255, 0, 0) # Red in RGB

FPS = 60 # Frames per second

screenx = 800 # x coordinates of the window
screeny = 1600 # y coordinates of the window

playerx = 700 # x coordinates of the player

icon_paths = {
    "small" : "./Images/Icons/Icon_small.png", # small icon
    "medium" : "./Images/Icons/Icon_medium", # medium icon
    "large" : "./Images/Icons/Icon_large" # large icon
}

icon_sizes = {
    "small" : 71,
    "medium" : 107,
    "large" : 142
}

pygame.init()
screen = pygame.display.set_mode((screeny, screenx)) # set window size
pygame.display.set_caption(WINDOW_TITLE) # set window title

screen.fill(WHITE)
clock = pygame.time.Clock()

all_spikes = [] # List of all Spikes
visible_spikes = []# List of all visible spikes

last_time = time.time()

life = True

class Spike():
    def __init__(self):
        self.step = 20
        self.spikex = -100
        self.spikey = random.randrange(0, 1600)
        self.image = pygame.Surface((100,100), pygame.SRCALPHA)
        self.rect = self.image.get_rect(center=(self.spikey, self.spikex))
        self.mask = None
        
    def down(self):
        """
        move the spike down
        """
        self.spikex += self.step
        pygame.draw.polygon(
            self.image,
            RED,
            (
                (0, 0),
                (100, 0),
                (50, 100)
            )
        )
        self.rect = self.image.get_rect(center=(self.spikey, self.spikex))
        self.mask = pygame.mask.from_surface(self.image)
        screen.blit(self.image.convert_alpha(), self.rect)
        
    def is_visible(self):
        if self.spikex > 800:
            return True
        
        else:
            False
            
class Cube(pygame.sprite.Sprite):
    def __init__(self, playery):
        self.icon_size = "small" # size of icon
        self.step = 10
        self.playery = playery
        self.image = pygame.image.load(icon_paths[self.icon_size]).convert_alpha() # load the icon of the player
        self.rect = self.image.get_rect(center=(self.playery, playerx))
        self.mask = pygame.mask.from_surface(self.image)
        
    def left(self):
        """
        move the player to the left
        """
        if not self.playery < 0:
            self.playery -= self.step
            
        self.rect = self.image.get_rect(center=(self.playery, playerx))
        self.mask = pygame.mask.from_surface(self.image)
        
    def right(self):
        """
        move the player to the right
        """
        if not self.playery > screeny - icon_sizes[self.icon_size]:
            self.playery += self.step
            
        self.rect = self.image.get_rect(center=(self.playery, playerx))
        self.mask = pygame.mask.from_surface(self.image)
        
    def update(self):
        """
        update position of player
        """
        screen.blit(self.image, (self.playery, playerx))

player = Cube(650)

pygame.mixer.music.load("./Sounds/Death-Moon.mp3")
pygame.mixer.music.play()

while life:
    screen.fill(WHITE)
    all_spikes = visible_spikes
    visible_spikes = []
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
            
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit()

    if pygame.key.get_pressed()[pygame.K_RIGHT]:
        player.right()

    if pygame.key.get_pressed()[pygame.K_LEFT]:
        player.left()
    
    player.update()
    
    if time.time() - last_time > 0.1:
        visible_spikes.append(Spike())
        last_time = time.time()
        
    for spike in all_spikes:
        spike.down()
        
    pygame.display.flip()
    for spike in all_spikes:
        if pygame.sprite.collide_mask(spike, player) != None:
            life = False
            pygame.mixer.music.stop()
            
        if not spike.is_visible():
            visible_spikes.append(spike)
            
    clock.tick(FPS)
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Freitag 27. März 2020, 17:48

Es ist kein Problem wenn ihr nicht hilft, ABER ich würde gerne wissen wieso nicht😐
__deets__
User
Beiträge: 8423
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 27. März 2020, 18:17

Das hat keinen besonderen Grund, man hat halt fuer bestimmte Dinge manchal keine Zeit. Dein Programm da oben zB kann ich nicht einfach nehmen und laufen lassen, weil die Bilder fehlen. Ich muss also anfangen, das umzuschreiben, oder Test-Bildchen machen. Und damit kostet das nicht 2 Minuten lesen, sondern 20, und dann muss man ja auch noch das Problem loesen. Manchmal hat man dazu Lust. Manchmal nicht. Glaub mir, du bist nicht der einzige.
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Freitag 27. März 2020, 20:28

Ich habe ja einen Link mit allem gepostet, du kannst ja einfach den ganzen Ordner herunterladen🙃
https://1drv.ms/u/s!AhT7GNW97XSLogBGFYL ... T?e=LMKwod
__deets__
User
Beiträge: 8423
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 27. März 2020, 20:31

Du hast einen Link gepostet, da steht was von "Bildern der Fehler". Nicht von "fehlenden Bildern".
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Freitag 27. März 2020, 20:48

Hatte mich verschrieben. Im Link ist das vollständige Programm mit allen Dateien die es braucht, auch die Bilder in Images. Und auch das Bild das den Fehler zeigt das ich zu früh sterbe (Bug1.png).
Das ⬇️
Bild
Zuletzt geändert von Fire Spike am Freitag 27. März 2020, 20:50, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 8423
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 27. März 2020, 20:50

Fire Spike hat geschrieben:
Sonntag 22. März 2020, 21:20
Bilder der Fehler mit dem Code im Link
Das heisst fuer mich, da sind Bilder drin, die den Fehler im Code zeigen. NICHT, dass da der Code drin ist, geschweige denn die Bilder, die man zum laufen lassen des Codes benoetigt.
Fire Spike
User
Beiträge: 239
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Freitag 27. März 2020, 20:52

Hatte mich verschrieben🤯
Antworten