[Pygame] Merkwürdiges Verhalten eines Bildes beim Bewegen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
BLU3L30PARD
User
Beiträge: 26
Registriert: Freitag 20. August 2010, 19:31

Hey Leute!
Ich habe mir mal vorgenommen, etwas mit Pygame zu machen,
und da habe ich mir gedacht, dass ein Spaceshooter ähnliches
Spiel ein guter Anfang wäre. Doch beim Bewegen des Player-Bildes
treten kleine "Bugs" auf...
Wenn man den Spieler nach Oben oder nach Links bewegt, dann aber
wieder die Bewegungstaste loslässt, bewegt sich das Bild trotzdem weiter
bis an den Bildschirmrand. Aber etwas derartiges steht nicht in meinem Code :K

Hier mal die Game - Classe:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
import pygame
from Utils import *
from Player import *
from Zombie import *
from Bullet import *
from pygame.locals import *


class Game():
    def __init__(self):
        # Init Game Window
        pygame.init()
        self.screen = pygame.display.set_mode((800, 600))
        pygame.display.set_caption("PyZombie Invasion - by blue leopard")
        pygame.display.set_icon(getImage("Thumbnail.png"))
        # ---
        self.clock = pygame.time.Clock()
        self.isRunning = True
        # ---
        self.isKeyPressed_Up = False
        self.isKeyPressed_Down = False
        self.isKeyPressed_Left = False
        self.isKeyPressed_Right = False
        # ---
        self.loadComponents()
        
    def loadComponents(self):
        self.background = getImage("Background.png")
        self.player = Player()
        
    def update(self):
        if self.isKeyPressed_Up:
            self.player.go(1)
        if self.isKeyPressed_Down:
            self.player.go(2)
        if self.isKeyPressed_Left:
            self.player.go(3)
        if self.isKeyPressed_Right:
            self.player.go(4)
        self.player.update()
    
    def draw(self):
        self.screen.blit(self.background, self.background.get_rect())
        self.player.draw(self.screen)
    
    def launch(self):
        while self.isRunning:
            self.clock.tick(60)
            self.screen.fill((0, 0, 0))
            for event in pygame.event.get():
                if event.type == QUIT:
                    self.isRunning = False
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.isRunning = False
                        sys.exit()
                    if event.key == K_UP:
                        self.isKeyPressed_Up = True
                    if event.key == K_DOWN:
                        self.isKeyPressed_Down = True
                    if event.key == K_LEFT:
                        self.isKeyPressed_Left = True
                    if event.key == K_RIGHT:
                        self.isKeyPressed_Right = True
                if event.type == KEYUP:
                    if event.key == K_UP:
                        self.isKeyPressed_Up = False
                    if event.key == K_DOWN:
                        self.isKeyPressed_Down = False
                    if event.key == K_LEFT:
                        self.isKeyPressed_Left = False
                    if event.key == K_RIGHT:
                        self.isKeyPressed_Right = False
            self.update()
            self.draw()
            pygame.display.flip()
    
    
if __name__ == "__main__":
    game = Game()
    game.launch()
Und hier die Player-Klasse:

Code: Alles auswählen

#-*- coding:utf-8 -*-

import pygame
from Utils import *
from pygame.locals import *


class Player():
    def __init__(self):
        self.image = getImage("Player.png")
        self.position = self.image.get_rect()
        # ---
        self.velocityX = 0.0
        self.velocityY = 0.0
        
    def update(self):
        self.position.x += self.velocityX
        self.position.y += self.velocityY
        self.velocityX *= 0.95
        self.velocityY *= 0.95
    
    def draw(self, screen):
        screen.blit(self.image, self.position)
        
    def go(self, direction):
        if direction == "up" or direction == 1:
            self.velocityY -= 0.8
        if direction == "down" or direction == 2:
            self.velocityY += 0.8
        if direction == "left" or direction == 3:
            self.velocityX -= 0.8
        if direction == "right" or direction == 4:
            self.velocityX += 0.8
Habe das Selbe schon in einer anderen Programmiersprache mit einem SDL - Wrapper
gemacht, und da hat das auf genau die gleiche weise funktioniert. Und naja, bewegt
man den Spieler nach Unten oder Rechts, dann bleibt er auch nach kurzer Zeit wieder stehen...
Hat jemand eine Idee, woran das liegen könnte?

Hier ist nochmal das ganze bisherige "Spiel" inklusive aktuell benötigte Grafiken:
:arrow: http://dl.dropbox.com/u/7887259/pyzombi ... em-001.zip
Zum ausführen wird Python 2.7.1+ und natürlich Pygame benötigt.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ebend etwas der artiges steht nicht in deinem Programm :D Du solltest mal überlegen wie dein Spieler reagiert wenn er keine Änderung seiner Richtung bekommt. Am Anfang läuft er nur nicht weil seine Geschwindigkeit 0 ist, aber du setzt diese im Programm nie wieder auf 0, so kann er nur in 4 Richtungen laufen doch stehen bleiben gibt es bei ihm nicht.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BLU3L30PARD
User
Beiträge: 26
Registriert: Freitag 20. August 2010, 19:31

Das ist eigentlich auch garnicht nötig...
WIe gesagt, hier habe ich das mit D programmiert:
http://blueleopard.de/?download=DgameSa ... ownShooter

Und das funktioniert das ja auch :D
deets

Ich denke dein Player ist falsch programmiert. Neben aestethischen Aspekten (statt direkt aus dem key die Richtung zu machen, bastelst du grosse if-Kaskaden) wird bei fortgesetztem Tastendruck andauern 0.8 auf die Velocity addiert. Also bei 60 Frames 60 * .8 = 48. Und dann multiplizierst du das mit 0.95 wenn man loslaest - aber das geht asymptotisch gegen 0, und braucht mindestens solange wie du gedrueckt hast, bis es so halbwegs langsam genug ist. Aber eigentlich noch viel laenger, etwa nach 80 Frames ist die Geschwindigkeit so bei einem Pixel/Frame angekommen, bewegt sich also immer noch.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Wie deets schon sagte liegt dort das Problem, in D hattest du einfach das Glück das abgerundet wurde und nahe Null ebend als gleich Null gewertet wurde. In pygame wird aber auch 4.92e-179 als 1 Pixel gewertet und so bewegt er sich halt weiter. Setz dir einfach einen Epsilon und wenn der Wert unterschritten wird setzt du seine Geschwindigkeit auf 0.0
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BLU3L30PARD
User
Beiträge: 26
Registriert: Freitag 20. August 2010, 19:31

deets hat geschrieben:statt direkt aus dem key die Richtung zu machen, bastelst du grosse if-Kaskaden
Das mache ich, weil, würde ich das so machen:

Code: Alles auswählen

if event.type == K_UP:
    player.go(1)
, müsste der Spieler ganz schnell hintereinander die <UP> Taste drücken.
Es gibt ja kein KEYPRESSED - Event in Pygame bzw. SDL. Aber genau das brauche ich.
Habe vorher nur mit SFML und C++ bzw. C# gearbeitet und da geht das ;)
So ist halt ein zwischenweg gefunden :D
Xynon1 hat geschrieben:Setz dir einfach einen Epsilon und wenn der Wert unterschritten wird setzt du seine Geschwindigkeit auf 0.0
Danke, ich denke, so werde ich das machen ;D

Danke für eure Hilfe! :)
deets

BLU3L30PARD hat geschrieben:
deets hat geschrieben:statt direkt aus dem key die Richtung zu machen, bastelst du grosse if-Kaskaden
Das mache ich, weil, würde ich das so machen:

Code: Alles auswählen

if event.type == K_UP:
    player.go(1)
, müsste der Spieler ganz schnell hintereinander die <UP> Taste drücken.
Es gibt ja kein KEYPRESSED - Event in Pygame bzw. SDL. Aber genau das brauche ich.
Habe vorher nur mit SFML und C++ bzw. C# gearbeitet und da geht das ;)
Das ist ja nicht wirklich ein Grund, oder? Denn mit DOWN und UP hast du doch alles, was du brauchst - du musst nur eine Menge der DOWN-keys verwalten, und generierst daraus PRESSED-events.

Einmal gebaut, immer wieder verwendbar ;)
Antworten