Python Grafikkarte

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

Hallo,

hab ne Frage:
Wenn ich ein Programm in Python schreibe, was irgendwas mit Grafik macht - meinetwegen einfach ein Bild über den Bildschirm von Rechts nach Links laufen lässt - benutzt
Python dann zum Berechnen und Darstellen automatisch die Grafikkarte oder wird das alles über die CPU gerechnet ?
Ich hatte einen Text gezeichnet, der über den Bildschirm laufen sollte. Das macht er auch, aber es läuft total ungleichmäßig bzw ruckelt.
Mal läuft er schnell, mal langsam - total unterschiedlich, als ob irgendwas anderes den ab und zu ausbremst.
Liegt das daran, daß Phython eine Skriptsprache ist und andere Systemsachen das Berechnen ab und zu ausbremsen ?
Vor allem: je größer die Grafiken sind, umso ruckeliger und langsamer wird das.

Kann mir es jemand erklären ?

Ich hab z.B. auch mal ein einfaches Game geschrieben, wo man mit nem Flaschenöffner einfach paar Bierflaschen abschießen muß (war halt ne witzige Idee :-D ). Hier das selbe - sind die Flaschen
klein, läuft das recht flüssig. Nehme ich größere Grafiken, ruckelt es und ist auch viel langsamer.
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Ob die Graphik ruckelt oder nicht, hängt in erster Linie davon ab, wie Du es programmiert hast. Ohne Code kann man da nichts sagen.
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

Code: Alles auswählen


import pygame
import random
import math
from tkinter import *
from pygame import mixer


#Pygame initialisieren
pygame.init()

# Bildschirm festlegen
screen = pygame.display.set_mode((800, 800))

# Hintergrundbild
background = pygame.image.load("D:\_Programmieren\Python\_Downloaded\Bier_Background.png")






# Bildschirm-Titel und Icon
pygame.display.set_caption("Eckes-APPS: Stammtisch FVDR")
#icon = pygame.image.load("D:\_Programmieren\Python\_Downloaded\launch.png")  <- braucht man nicht, wenn man alles in eine Zeile schreibt
pygame.display.set_icon(pygame.image.load("D:\_Programmieren\Python\_Downloaded\launch.png"))

# Player
playerimg = pygame.image.load("D:\_Programmieren\Python\_Downloaded\Stammtisch-Mitglieder\Ebby_klein.png")
playerX = 370
playerY = 536
playerX_change = 0
playername = "Ebby"

# Level
level = 1


# Flasche Flens
Flascheimg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []

number_of_enemys = 6

# Flaschen
flensimg = "D:\_Programmieren\Python\_Downloaded\Flens_Pils_Flasche_klein.png"
becksimg = "pix/Becks_small.png"
karlsquellimg = "pix/Karlsquell_small.png"
oettingerimg = "pix/Karlsquell_small.png"



z = 1
for i in range (number_of_enemys):
    if z == 1:
        Flascheimg.append (pygame.image.load(karlsquellimg))
    if z == 2:
        Flascheimg.append(pygame.image.load(karlsquellimg))
    if z == 3:
        Flascheimg.append(pygame.image.load(oettingerimg))
    if z == 4:
        Flascheimg.append(pygame.image.load(flensimg))
    z += 1
    if z > 4:
        z = 1

    enemyX.append (random.randint(10, 700))
    enemyY.append (random.randint (0, 50))
    enemyX_change.append (-0.3)
    enemyY_change.append (0.02)

# Flschenöffner-Geschoß
bulletimg = pygame.image.load("D:\_Programmieren\Python\_Downloaded\Flaschenöffner_klein.png")
bulletX = 0
bulletY = 500
bulletX_change = 0
bulletY_change = 1.5
# bullet state ist für 'ready' gleich nicht abgefeuert, 'fire' ist gleich abgefeuert
bullet_state = "ready"

#score
score_value = 0
font = pygame.font.Font("freesansbold.ttf",32)

textX = 10
textY = 10

game_over_font = pygame.font.Font("freesansbold.ttf",64)

# Hintergrund-Sound
pygame.mixer.init()

#pygame.mixer.music.play(loops = 0)
pygame.mixer.music.load("Sound/Maiden_Loneliness_intro.mp3")
pygame.mixer.music.play(loops = -1)

def game_over_text():
    over = game_over_font.render("GAME OVER !!!", True, (0, 0, 0))
    screen.blit(over, (200, 250))

def show_score(x, y):
    score = font.render("Pullen gesoffen = " + str(score_value), True, (0, 0, 0))
    screen.blit(score, (x, y))

def player(x, y):
    screen.blit(playerimg, (x, y)) # blit stellt image auf dem screen dar

def enemy(x, y, i):
    screen.blit(Flascheimg[i], (x, y))

def fire_bullet(x, y):
    global bullet_state
    bullet_state = "fire"
    screen.blit(bulletimg, (x+15, y))
    #bullet_sound = pygame.mixer.Sound("D:\_Programmieren\Python\_Downloaded\Sound\FlensburgerBierPlop.mp3")
    #bullet_sound.play()

def isCollission(enemyX, enemyY, bulletX, bulletY):
    distance = math.sqrt(math.pow(enemyX - bulletX,2) + math.pow(enemyY - bulletY,2))
    if distance < 42:
        return True
    else:
        return False



# Hauptprogramm-Schleife
running = True
while running:
    screen.fill((0, 0, 0))
    screen.blit(background, (0,0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                playerX_change = -0.5
            if event.key == pygame.K_RIGHT:
                playerX_change = 0.5
            if event.key == pygame.K_SPACE:
                if bullet_state == "ready": # schießen geht nur, wenn gerade keine Kugel fliegt
                    bulletX = playerX
                    fire_bullet(bulletX, bulletY)

        if event.type == pygame.KEYUP:
            playerX_change = 0

    playerX += playerX_change
    if playerX <= 0:
        playerX = 0
    elif playerX >= 736:
        playerX = 736
    # enemy movement
    for i in range (number_of_enemys):
        # Game over
        if enemyY[i] >400:
            for j in range (number_of_enemys):
                enemyY[j] = 2000
                game_over_text()
                break
        enemyX[i] += enemyX_change[i]
        enemyY[i] += enemyY_change[i]
        if enemyX[i] <= 0:
            enemyX_change[i] = 0.3
        elif enemyX[i] >= 736:
            enemyX_change[i] = -0.3

            # bullet collission
        collission = isCollission(enemyX[i], enemyY[i], bulletX, bulletY)
        if collission:
            bullet_state = "ready"
            bulletY = 500
            score_value += 1
            bullet_sound = mixer.Sound("Sound\FlensburgerBierPlop.mp3")
            bullet_sound.play()
            enemyX[i] = random.randint(10, 730)
            enemyY[i] = random.randint(0, 50)
        enemy(enemyX[i], enemyY[i], i)

# bullet movement
    if bulletY <= -12:
        bullet_state = "ready"
        bulletY = 500
    if bullet_state == "fire":
        fire_bullet(bulletX, bulletY)
        bulletY -= bulletY_change



    player(playerX, playerY)
    show_score(textX, textY)
    pygame.display.update()
    
Zuletzt geändert von Eckes am Mittwoch 15. Dezember 2021, 14:07, insgesamt 1-mal geändert.
narpfel
User
Beiträge: 691
Registriert: Freitag 20. Oktober 2017, 16:10

@Eckes: Bitte den Code in einen Codeblock setzen, sonst kann man den nicht lesen.
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

jetz aber

ich ändere ja nur die images von kleinen in größere und dann ruckelt es. Kann also ja eigentlich nicht am code liegen ...
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dir fehlt vor allem eine Beschränkung der Frame-Rate auf zb 30. Das kannst du in pygame mit der Clock Klasse erreichen. Das erklärt mindestens einen Teil der Ruckeligkeit.
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

an welcher Stelle mach ich die Clock am besten rein ?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na in deiner Schleife. Die soll ja warten, um die Gramerate anzupassen.
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

okay - hab ich gemacht, aber es macht von 60 auf 100 Framerate zwar einen Unterschied, aber ab 100 wird es nicht mehr schneller. Daher ja die Frage, wo das berechnet wird CPU ? GPU ?
Und wenn ich ne größere Grafik nehme, wird es auch wieder langsamer.

Deshalb hab ich ja jetzt auch mal angefangen bisschen c++ zu lernen, um zu sehen ob das da schneller ist.

Python wäre mir natürlich lieber, weil es einfacher zu lernen ist.
Eckes
User
Beiträge: 18
Registriert: Mittwoch 17. Februar 2021, 17:27

Ich habe einen Core i7 und ne Gforce RTX3060 - damit müsste das doch rasend schnell sein eigentlich....
Ich meine, wenn da so Games wie Farcry usw fließend laufen, wo ja nu wirklich hammerviel Grafik bewegt wird, warum läuft das in python so langsam ?
Ich bewege da ja nun wirklich nicht viel - gerade mal paar objekte.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst auch rasend schnell ruckeln, das hat ja nichts mit Geschwindigkeit an sich zu tun. Sondern mit Synchronisation und wechselnden Lasten des Systems, und schlechter Programmierung.

Um die Frage zu beantworten: das meisste wird wohl auf der CPU sein. Aber du machst ja nicht so viel, das sollte reichen. Es sind allerdings einige Fehler drin, zb laedst du jedes mal einen Sound, wenn du ihn abspielt. Das kann also beliebig lange warten, bis die Platte den liefert. Auch beim Font-Rendering kann man denke ich optimieren, indem man da vorberechnet und damit dann nur noch blittet, statt das jedes mal neu zu machen.

Ob das wirklich was bringt, kann man nur durch profiling rausbekommen. Oder durch gezieltes suchen, indem du bestimmte Dinge abklemmst/vereinfachst.
Antworten