Spielfigur mit Leertaste hüpfen lassen

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.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Hi, bin gerade dabei Python zu lernen und ein Parkour-Spiel zu programmieren. Allerdings scheitere ich daran, einen Sprung zu programmieren. Der Spieler soll mit einem Druck der Leertaste über die Mauer springen können. Könnte mir bitte jemand den Code für einen Sprung erklären?

Code: Alles auswählen

import pgzrun
from random import randint

WIDTH = 800
HEIGHT = 600

stickman = Actor("stickman")
stickman.pos = 50, 527

wall = Actor("wall")
wall.pos = randint(800, 1600), 527

game_over = False
score = 0

scores = []

def update_high_scores():
    global score, scores
    filename = r"/Users/stieb/Desktop/Programmer/FartRun/highscores.txt"
    scores = []
    with open(filename, "r") as file:
        line = file.readline()
        high_scores = line.split()
        for high_score in high_scores:
            if(score > int(high_score)):
                scores.append(str(score) + " ")
                score = int(high_score)
            else:
                scores.append(str(high_score) + " ")
    with open(filename, "w") as file:
        for high_score in scores:
            file.write(high_score)

def display_high_scores():
    screen.draw.text("HIGHSCORES", (350, 150), color="black")
    y = 175
    position = 1
    for high_score in scores:
        screen.draw.text(str(position) + ".   " + high_score, (350, y), color="black")
        y += 25
        position += 1

def draw():
    screen.blit("background", (0, 0))
    if not game_over:
        stickman.draw()
        wall.draw()
        screen.draw.text("Punkte: " + str(score), (700, 5), color = "black")
    else:
        display_high_scores()
		
def update():
    global game_over, score, run
    if not game_over:
        if wall.right > 0:
            wall.x -= 2
        else:
            wall.x = randint(1600, 3200)
            score += 1

    if stickman.collidepoint(wall.x, wall.y):
        game_over = True
        update_high_scores()

pgzrun.go()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es gibt verschiedene Möglichkeiten, aber für den Anfang das einfachste: wenn in update die Leertaste gedrückt ist, verringerst du die y-Koordinate des stickman. Wenn nicht, erhöhst du sie, wobei du aufpasst, das sie nicht unter den Boden fällt.

Wenn das steht, kann man Verbesserungen einbauen. Zb einen festen Sprung, der nicht unterbrochen werden kann, indem man eine bestimmte Anzahl von Auf- und Abbewegungen macht.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Vielen Dank, für die schnelle Antwort.
Allerdings kann die Figur doch dann unendlich hoch fliegen, solange die Leertaste gedrückt ist, oder :?:
Könntest du mir bitte einen groben Code von dem Sprung schicken? Da ich noch Anfänger bin und nicht exakt weiß, wie ich alles zu schreiben habe...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, ich sage ja, das ist nur der erste Schritt.

Und Programmieren lernt man durch Programmieren. Nicht dadurch, das andere das für einen erledigen. Ich habe das Problem extra so beschrieben, dass es ein einfaches Verhalten für den Anfang ist. Versuch dich daran, und zeig, was du machst, und wo es hakt. Dann sehen wir weiter.

Aber einfach auf Bestellung programmieren kostet bei mir zumindest Geld.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Ok, ich hab eine Lösung. Allerdings habe ich innerhalb des Fensters, in dem sich das Spiel startet nur einen Black-Screen und mein Python ab, wenn ich den Code ausführe. Warum?

Code: Alles auswählen

import pgzrun
from random import randint
import keyboard

WIDTH = 800
HEIGHT = 600

stickman = Actor("stickman")
stickman.pos = 50, 527

wall = Actor("wall")
wall.pos = randint(800, 1600), 527

game_over = False
score = 0

scores = []

def update_high_scores():
    global score, scores
    filename = r"/Users/stieb/Desktop/Programmer/FartRun/highscores.txt"
    scores = []
    with open(filename, "r") as file:
        line = file.readline()
        high_scores = line.split()
        for high_score in high_scores:
            if(score > int(high_score)):
                scores.append(str(score) + " ")
                score = int(high_score)
            else:
                scores.append(str(high_score) + " ")
    with open(filename, "w") as file:
        for high_score in scores:
            file.write(high_score)

def display_high_scores():
    screen.draw.text("HIGHSCORES", (350, 150), color="black")
    y = 175
    position = 1
    for high_score in scores:
        screen.draw.text(str(position) + ".   " + high_score, (350, y), color="black")
        y += 25
        position += 1

def draw():
    screen.blit("background", (0, 0))
    if not game_over:
        stickman.draw()
        wall.draw()
        screen.draw.text("Punkte: " + str(score), (700, 5), color = "black")
    else:
        display_high_scores()    
		
def update():
    global game_over, score, run
    if not game_over:
        if wall.right > 0:
            wall.x -= 2
        else:
            wall.x = randint(1600, 3200)
            score += 1

    while True:
        try:
            if keyboard.is_pressed("space"):
                stickman.y -= 2
            else:
                if stickman.y >= 527:
                    stickman.y += 2
        except:
            break

    if stickman.collidepoint(wall.x, wall.y):
        game_over = True
        update_high_scores()

pgzrun.go()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil du eine Endlosschleife gebaut hast. Das darf nicht sein. Ich have geschrieben: wenn Taste gedrückt, dann Bewegung hoch. Sonst Bewegung runter. Beides muss limitiert werden. Das sind if-Anweisungen, keine schleifen.
dirk009
User
Beiträge: 27
Registriert: Donnerstag 3. Juni 2021, 21:49

Hallo @V-Max,

manchmal hilft auch ein Tutorial: https://www.techwithtim.net/tutorials/g ... l/jumping/

Cheers,
Dirk
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Vielen Danke, euch beiden!
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Jetzt sieht mein Code schonmal so aus, aber ich kriege es nicht hin, es zu verbieten, dass man die Leertaste gedrückt hält. Könnt ihr mir dazu bitte noch einen Ratschlag geben, weil im Video, ist das zu kompliziert, um es auf meinen Code anzuwenden.

Code: Alles auswählen

import pgzrun
from random import randint
import keyboard

WIDTH = 800
HEIGHT = 600

stickman = Actor("stickman")
stickman.pos = 50, 527

wall = Actor("wall")
wall.pos = randint(800, 1600), 527

game_over = False
score = 0

scores = []

def update_high_scores():
    global score, scores
    filename = r"/Users/stieb/Desktop/Programmer/FartRun/highscores.txt"
    scores = []
    with open(filename, "r") as file:
        line = file.readline()
        high_scores = line.split()
        for high_score in high_scores:
            if(score > int(high_score)):
                scores.append(str(score) + " ")
                score = int(high_score)
            else:
                scores.append(str(high_score) + " ")
    with open(filename, "w") as file:
        for high_score in scores:
            file.write(high_score)

def display_high_scores():
    screen.draw.text("HIGHSCORES", (350, 150), color="black")
    y = 175
    position = 1
    for high_score in scores:
        screen.draw.text(str(position) + ".   " + high_score, (350, y), color="black")
        y += 25
        position += 1

def draw():
    screen.blit("background", (0, 0))
    if not game_over:
        stickman.draw()
        wall.draw()
        screen.draw.text("Punkte: " + str(score), (700, 5), color = "black")
    else:
        display_high_scores()    
		
def update():
    global game_over, score
    if keyboard.is_pressed("space"):
        if stickman.y >= 430:
            stickman.y -= 25
    else:
        if stickman.y <= 525:
            stickman.y += 3
    
    if not game_over:
        if wall.right > 0:
            wall.x -= 6
        else:
            wall.x = randint(1600, 3200)
            score += 1

    if stickman.collidepoint(wall.x, wall.y):
        game_over = True
        update_high_scores()

pgzrun.go()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der nächste Schritt ist dann die Zeit zu begrenzen. Du musst einen Zähler einführen, der hochgezählt wird, solange man die Leertaste drückt. Und wenn der größer zb 4 ist (weil du 25 Pixel springst, und etwa 100 hoch erlaubte), dann wird der Druck der Leertaste eben ignoriert.

Sobald der Spieler wieder auf dem Boden aufkommt, setzt man den Zähler auf 0, und der Spieler kann wieder springen.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Und mit welchem Befehl kann man die Leertaste ignorieren?
dirk009
User
Beiträge: 27
Registriert: Donnerstag 3. Juni 2021, 21:49

Indem man den Zähler von deets ebenfalls prüft:

Code: Alles auswählen

 if keyboard.is_pressed("space") and counter == 0 
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Jetzt habe ich diesen Code, aber ich kann nur ein mal springen, danach nicht mehr. Und wenn ich

Code: Alles auswählen

jumpTime = 0
an eine andere Stelle setze, kann ich wieder fliegen.

Code: Alles auswählen

    if keyboard.is_pressed("space") and jumpTime == 0:
        jumpTime += 1
        if stickman.y >= 430:
            stickman.y -= 27
            jumpTime = 0
    else:
        if stickman.y <= 525:
            stickman.y += 3
    
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ja auch die falsche Stelle. Wenn du runter gehst auf den Boden, muss der Zähler resettet werden.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Und wo ist die Stelle, wo ich auf den Boden gehe? Ich habe etwas probiert, aber es ging nie...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wozu ist denn die Abfrage mit 525?
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Das er wieder nach unten kommt und bei dieser Höhe stoppt
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja eben. Und das ist doch der Moment, ab dem du es wieder erlauben kannst, das der User springt. Also machst du an der Stelle das Rücksetzen.
V-Max
User
Beiträge: 10
Registriert: Sonntag 18. Juli 2021, 17:35

Jetzt teleportiere ich mich stückweise nach oben und kann immer noch fliegen?!

Code: Alles auswählen

    if keyboard.is_pressed("space") and jumpTime == 0:
        jumpTime += 1
        if stickman.y >= 430:
            stickman.y -= 27
    else:
        if stickman.y <= 525:
            stickman.y += 2
            jumpTime = 0
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich würde während des Sprungs einfach eine "Schwerkraft" basteln unter Beachtung der Bodenhöhe, sofern diese nicht immer 0 ist. Ein Beispiel:

Code: Alles auswählen

height = max(height - 5, ground_height)
Die wirkt dann in jedem Intervall (zb 200 ms) als Gegengewicht zur erreichten Höhe durch die Leertaste. Die Operation käme dann als Schritt vor der Tasten-Abfrage.
Antworten