Mehrere SpriteGroups ausgeben mit wenig Aufwand

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Hallo bin Neu hier und Grüße Alle recht herzlich.

Ich wurschtel mich so durch und vieles in Python verstehe ich halt noch nicht, von Klassen habe ich bislang Abstand gehalten aber muss halt sein.

Hier verstehe ich nicht ganz wie ich praktisch dasselbe Sprite bzw. Group mehrfach auf dem Bildschirm ausgeben kann ohne immer neue Zuweisungen anzulegen.

Code: Alles auswählen

import pygame
import random
from pygame.locals import *

# GLOBAL VARIABLES
COLOR = (255, 100, 98)
SURFACE_COLOR = (50, 50, 50)
WIDTH = 500
HEIGHT = 500

# Object class
class Sprite(pygame.sprite.Sprite):
	def __init__(self, color, height, width):
		super().__init__()

		self.image = pygame.Surface([width, height])
		self.image.fill(SURFACE_COLOR)
		self.image.set_colorkey(COLOR)
		pygame.draw.rect(self.image,color,pygame.Rect(0, 0, width, height))
		self.rect = self.image.get_rect()


pygame.init()

RED = (255, 0, 0)
x_move = 0
size = (WIDTH, HEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Creating Sprite")

all_sprites_list = pygame.sprite.Group()
object_ = Sprite(RED, 20, 30)
object_.rect.x = 200 
object_.rect.y = 300
all_sprites_list.add(object_)

exit = True
clock = pygame.time.Clock()

while exit:
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			exit = False
		if event.type == pygame.KEYDOWN:
			if event.key == ord('q'):
				pygame.quit()
			if event.key == pygame.K_LEFT or event.key == ord('d'):
				object_.rect.x += 4
		if event.type == pygame.KEYUP:
			if event.key == pygame.K_LEFT or event.key == ord('d'):
				object_.rect.x += 0
	all_sprites_list.update()
	screen.fill(SURFACE_COLOR)
	all_sprites_list.draw(screen)

	pygame.display.flip()
	clock.tick(60)

pygame.quit()

Wenn ich jetzt ein Duplikat ausgeben möchte, dann fällt mir nur dies ein:

Code: Alles auswählen

all_sprites_list2 = pygame.sprite.Group()
object_2 = Sprite(RED, 20, 30)
object_2.rect.x = 250 
object_2.rect.y = 350
all_sprites_list.add2(object_2)
Klar geht das aber wenn man dann 10 davon, 5 hier von und 26 jene ausgeben möchte kommt mir das etwas zu kompliziert vor
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Warum? Wenn die Sprites verschiendene Koordinaten haben, dann muessen die nunmal auch getrennt vorgehalten werden. Hast du Angst, deine diversen Gigabyte RAM werden alle?
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Nö aber das ist sehr viel Schreibarbeit, vor allem wenn ich im Aufruf dann noch jeweils object_.rect.x und object_.rect.y eintragen muss.

Wenn ich das mit einem normalen Quadrat machen würde, würde ich einfach

Code: Alles auswählen

class Rect:
    def __init__(self, x, y, width, height):
        self.rect = pygame.Rect(x, y, width, height)

    def render(self, display, color):
        pygame.draw.rect(display, color, self.rect)

Quadrat1 = Rect(0, 0, 80, 160)
Quadrat2 = Rect(80, 0, 160, 160)

Und fertig.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wo ist denn bei deinem Recht der Gewinn? Das du die Koordinaten zusätzlich im Konstruktor übergibst? Das kannst du durch Ableitung von Sprite ja sehr simpel selber machen.

Und wenn du x unterschiedliche Sprites hast, musst das ja irgendwie hingeschrieben werden. Weniger wird es nur, wenn du eine Systematik ausnutzen kannst, die hier aber niemand kennt. Also zb eine Welle von Angreifern, die alle auf einer Linie sind zb.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei hier wohl auch eine Schleife erwähnt werden sollte, wenn man anfängt Namen zu nummerieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Ja da habe ich schon dran gedacht viewtopic.php?t=813
Muss ich mal experimentieren.

Was mich einfach stört ist das ich halt bei dem einfachen Beispiel praktisch die Blaupause nehme und so viele machen kann wie ich möchte während ich bei der SpriteGroup für jedes Andere 3 neue Variablen deklarieren muss.

Sollte man das irgendwie verkürzt schreiben können, würde mich auch interessieren.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Schreib halt einfach eine Funktion:

Code: Alles auswählen

def new_sprite(color, height, width, x, y):
    sprite = Sprite(RED, 20, 30)
    sprite.rect.x = 250 
    sprite.rect.y = 350
    return sprite

...

other_sprites = pygame.sprite.Group()
other_sprites.add(new_sprite(color=RED, height=20, width=30, x=250, y=350))
other_sprites.add(new_sprite(color=BLUE, height=40, width=50, x=450, y=550))
...
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Naja, oder man packt die Position halt einfach gleich mit in die `__init__()`. Kann man ja mit Defaultwerten (0, 0) belegen, dann kann man es auch weiterhin ohne aufrufen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

pillmuncher hat geschrieben: Montag 18. Oktober 2021, 20:32 Schreib halt einfach eine Funktion:

Code: Alles auswählen

def new_sprite(color, height, width, x, y):
    sprite = Sprite(RED, 20, 30)
    sprite.rect.x = 250 
    sprite.rect.y = 350
    return sprite

...

other_sprites = pygame.sprite.Group()
other_sprites.add(new_sprite(color=RED, height=20, width=30, x=250, y=350))
other_sprites.add(new_sprite(color=BLUE, height=40, width=50, x=450, y=550))
...
Das sieht so aus als könnte es die Lösung sein aber ich schaffe es nicht das alles zusammenzukloppen so das es funktioniert.

Könnte man damit dann beliebig viele Sprites so ausgeben?
other_sprites.draw((screen), RED, 50, 50, 200, 300)
other_sprites.draw((screen), BLUE, 150, 150, 200, 300)

Bzw. die Spritegrösse wäre in dem Fall Einheitlich und könnte man sich sparen.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Josh Bosh: Nein, wie kommst Du darauf? Die `Group.draw()`-Methode nimmt *ein* Argument entgegen. Das `Surface` auf dem gezeichnet wird. Das steht so in der Dokumentation. Warum würdest Du an *der* Stelle denn noch mal Daten für Sprites angeben wollen, die doch bereits in der Gruppe sind‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

__blackjack__ hat geschrieben: Dienstag 19. Oktober 2021, 13:46 @Josh Bosh: Nein, wie kommst Du darauf? Die `Group.draw()`-Methode nimmt *ein* Argument entgegen. Das `Surface` auf dem gezeichnet wird. Das steht so in der Dokumentation. Warum würdest Du an *der* Stelle denn noch mal Daten für Sprites angeben wollen, die doch bereits in der Gruppe sind‽
Weil ich Python generell nicht so durchschaue wie ich es gerne tun würde und mich auch dieses recht einfache Beispiel ziemlich durcheinander bringt eben weil permanent hin und her Verweise stattfinden.

Sorry, ich meinte
new_sprite((screen), RED, 50, 50, 200, 300)
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Code: Alles auswählen

import pygame
import random
from pygame.locals import *

# GLOBAL VARIABLES
COLOR = (255, 100, 98)
SURFACE_COLOR = (50, 50, 50)
WIDTH = 800
HEIGHT = 800
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

# Object class
class Sprite(pygame.sprite.Sprite):
	def __init__(self, color, width, height):
		super().__init__()

		self.image = pygame.Surface([width, height])
		self.image.fill(SURFACE_COLOR)
		self.image.set_colorkey(COLOR)
		pygame.draw.rect(self.image,color,pygame.Rect(0, 0, width, height))
		self.rect = self.image.get_rect()

# Func
def new_sprite(color, width, height, x, y):
    sprite = Sprite(color, 50, 50)
    sprite.rect.x = 250 
    sprite.rect.y = 350
    return sprite

all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(new_sprite(color=RED, width=50 ,height= 50, x=100, y=150))
all_sprites_list.add(new_sprite(color=BLUE, height=50, width=50, x=450, y=550))
all_sprites_list.add(new_sprite(color=GREEN, height=50, width=50, x=450, y=650))
pygame.init()

x_move = 0
size = (WIDTH, HEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Creating Sprite")

exit = True
clock = pygame.time.Clock()

while exit:
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			exit = False
		if event.type == pygame.KEYDOWN:
			if event.key == ord('q'):
				pygame.quit()
			if event.key == pygame.K_LEFT or event.key == ord('d'):
				object_.rect.x += 4
		if event.type == pygame.KEYUP:
			if event.key == pygame.K_LEFT or event.key == ord('d'):
				object_.rect.x += 0
                
	all_sprites_list.update()
	screen.fill(SURFACE_COLOR)
	all_sprites_list.draw(screen)
	pygame.display.flip()
	clock.tick(60)

pygame.quit()
Habe jetzt versucht die Funktion von Pillmuncher einzubinden aber ich habe entweder etwas Falsch gemacht oder vergessen - oder Falsch interpretiert.

Sollten hier jetzt 3 Quadrate erscheinen, dann klappt die Koordinatenzuweisung nicht
Zuletzt geändert von Josh Bosh am Dienstag 19. Oktober 2021, 15:07, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

pillmuncher hat einen trivialen Fehler gemacht. Wo in der new_sprite Funktion werden die Koordinaten gesetzt, und auf was? Und auf was sollten sie stattdessen gesetzt werden?
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

*oops*
In specifications, Murphy's Law supersedes Ohm's.
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Ja die sprite.rect innerhalb der Funktion gibt die vererbten Werte an, klammert man die aus, hängen die Quadrate 0,0.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, das ist nicht was ich meine. Du übergibst Parameter für x und y. Werden die benutzt?
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Nein.
Ich denke man muss erst x und y zusätzlich in der Funktion "anmelden"
Wenn ich das mache, frisst ers aber nicht. width und height überschreiben klappt, aber ich weiss nicht weiter

Code: Alles auswählen

# Func
def new_sprite(color, width, height, x, y):
    sprite = Sprite(color, 50, 50, 10, 10)
    # sprite.x = 0 
    # sprite.y = 0
    return sprite

all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(new_sprite(color=RED, width=50 ,height= 50, x= 100, y=100))
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Josh Bosh hat geschrieben: Dienstag 19. Oktober 2021, 15:46 Ja die sprite.rect innerhalb der Funktion gibt die vererbten Werte an, klammert man die aus, hängen die Quadrate 0,0.
Nein. Meine Funktion hätte so aussehen sollen:

Code: Alles auswählen

def new_sprite(color, height, width, x, y):
    sprite = Sprite(color, height, width)
    sprite.rect.x = x
    sprite.rect.y = y
    return sprite
Das hätte mir auffallen müssen. Dir aber auch. Programmieren funktioniert nicht so, dass man einfach irgendwas aus dem Internet zusammenkopiert, sondern man muss schon verstehen, was man tut. Das kann dir keiner abnehmen. Es wäre vermutlich auch sinnvoll, wenn du das offizielle Tutorial durcharbeitest, damit du verstehst, was Funktionen sind und wie und wo und warum man sie verwendet.
In specifications, Murphy's Law supersedes Ohm's.
Josh Bosh
User
Beiträge: 11
Registriert: Montag 18. Oktober 2021, 17:07

Ja Danke, natürlich hast du recht. Aber ist ja nicht so das ich mir die Codeschnipsel rauskopiere um sie nicht zu verändern, sondern um davon zu lernen, weil egal ob man Tutorials durcharbeitet oder nicht, man legt ja auch vieles was man durcharbeitet wieder zur Seite.

Dann mal vielen Dank an Alle für die Hilfe, damit komme ich wirklich schonmal mit meinem Projekt weiter.
Antworten