Kollisionen mit pygame

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Benutzeravatar
Benni1000
User
Beiträge: 9
Registriert: Mittwoch 27. Juni 2012, 13:51
Wohnort: Österreich
Kontaktdaten:

Hallo,
ich bin gerade dabei pygame auszutesten, und jetzt geht es an die kollision von vierecken.
In meinem Spiel lasse ich über alle aktiven Gegner sowie über die Schüsse des Spielers vierecke zeichnen,
das problem ist das sie irgentwie immer kollidieren, auch wenn sie nicht kollidieren dürften.
Ich wäre sehr froh wenn mir einer von euch sagen könnte warum das passiert.

Code: Alles auswählen

import sys
import pygame

#Init game
pygame.init()
pygame.display.set_caption("Space")
display = pygame.display.set_mode((1000,700))

#Coords
ship_x = 100
ship_y = 100

#Moving
moving_l = 0
moving_r = 0
moving_u = 0
moving_d = 0

#Misc
health = 3
shots = []
enemys = []
gen_enem = 700

#Load Images
sprite_ship = pygame.image.load("res/space.png")

#Objects

#Shot
class shot():
    def __init__(self,x_co,y_co,disp):
        self.sprite_shot = pygame.image.load("res/shot.png")  
        self.x = x_co
        self.y = y_co
        self.display = disp 
    def move(self):
        if self.y < 0:
            return 0
        self.y = self.y - 10
        self.display.blit(self.sprite_shot,(self.x,self.y))
        return 1
    def __del__(self):
        pass
    def getRect(self):
        return self.sprite_shot.get_rect()

#Enemy
class enemy():
    def __init__(self,x_co,y_co,disp):
        self.sprite_ship = pygame.image.load("res/enemy.png")
        self.x = x_co
        self.y = y_co
        self.display = disp
        self.shoot_delay = 0
    def move(self):
        if self.y > 1000:
            return 0
        self.y = self.y + 5
        self.display.blit(self.sprite_ship,(self.x,self.y))  
    def __del__(self):
        pass
    def getRect(self):
        return self.sprite_ship.get_rect()

#Main Loop
while 1:
    
    #Get Events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                moving_u = 1
            if event.key == pygame.K_a:
                moving_l = 1
            if event.key == pygame.K_s:
                moving_d = 1
            if event.key == pygame.K_d:
                moving_r = 1
            if event.key == pygame.K_SPACE:
                newsh = shot(ship_x - 59 / 2,ship_y - 62 - 1,display)
                shots.append(newsh)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w:
                moving_u = 0
            if event.key == pygame.K_a:
                moving_l = 0
            if event.key == pygame.K_s:
                moving_d = 0
            if event.key == pygame.K_d:
                moving_r = 0
    
    #Border
    if moving_u == 1 and ship_y < 2:
        moving_u = 0
    if moving_d == 1 and ship_y > 699 - 62:
        moving_d = 0
    if moving_l == 1 and ship_x < 2:
        moving_l = 0
    if moving_r == 1 and ship_x > 999 - 59:
        moving_r = 0
    
    #Move Ship
    if moving_l == 1:
        ship_x = ship_x - 10
    if moving_r == 1:
        ship_x = ship_x + 10
    if moving_u == 1:
        ship_y = ship_y - 10
    if moving_d == 1:
        ship_y = ship_y + 10
        
    #Clear Screen
    display.fill((0,0,0))
    
    #Render Shots
    i = 0
    while i < len(shots):
        ex = shots[i].move()
        if ex == 0:
            shots.remove(shots[i])
        i = i + 1
    
    #Generate enemies
    if gen_enem == 0:
        gen_enem = 700
        en = enemy(ship_x - 59 / 2,0,display)
        enemys.append(en)
    else:
        gen_enem = gen_enem - 10
        
    #Render Enemys
    i = 0
    while i < len(enemys):
        ex = enemys[i].move()
        if ex == 0:
            enemys.remove(enemys[i])
        i = i + 1
        
    #Render Ship
    display.blit(sprite_ship,(ship_x,ship_y))
    
    #Collisions enemy - bullet
    i = 0
    while i < len(enemys):
        rect_ene = enemys[i].getRect()
        i2 = 0
        while i2 < len(shots):
            if shots[i2].getRect().colliderect(rect_ene):
                enemys.remove(enemys[i])
                break
            i2 = i2 + 1
        i = i + 1
    
    #Flip
    pygame.display.flip()
    #Delay
    pygame.time.delay(20)

Mfg Benni1000
Lust auf Russisches Roulette?
[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo "You live"

Besucht doch mal meine Website und hinterlasst Kommentare zu meinen Programmen.
Alle Programme sind OpenSource und mit einer CreativeCommons Lizenz geschützt.
http://benni1000.eu
deets

Ok, zu dem Code gaeb's so manches zu sagen. Aber dein eigentliches Problem besteht darin, dass du dein rect immer vom image laedst. Das ist natuerlich fuer alle Schuesse gleich - (0,0, <breite>, <hoehe>) - und kollidiert.

Stattdessen

- setze ein Schuss/Schiff-Rect beim initialisieren in __init__
- verschiebe es mit seinem Ursprung an die Position des Schusses
- verzichte am besten auf die Koordinaten selbst, sondern pass einfach immer die Posittion des Rechtecks an
- mal das Sprite eben an genau diese Position
Benutzeravatar
Benni1000
User
Beiträge: 9
Registriert: Mittwoch 27. Juni 2012, 13:51
Wohnort: Österreich
Kontaktdaten:

Hallo,
ich habe jetzt angefangen das ganze Projekt neu zu schreiben, da wie du es gesagt hast, der Programmierstil nicht gut war.
Hast du vielleicht eine Idee was ich falsch mache?
Wenn ich mich in eine Richtung bewegen Möchte bewegt sich das Schiff mit einer sehr hohen geschwindikeit nach rechts unten.
Die Abfragen ob sich das Objekt bewegen soll stimmen soweit.

Code: Alles auswählen

import sys
import pygame

#Init game
pygame.init()
pygame.display.set_caption("Space")
display = pygame.display.set_mode((1000,700))

#Objects
class PlayerShip():
    def __init__(self,disp):
        self.x = 100
        self.y = 100
        self.moving = [0,0,0,0] #0-up 1-down 2-left 3-right
        self.health = 10
        self.image = pygame.image.load("res/ship.png")
        self.rect = self.image.get_rect()
        self.display = disp
    def setMoving(self,direction,value):
        self.moving[direction] = value
    def getMoving(self,direction):
        return self.moving[direction]
    def move(self,x,y):
        self.rect = self.rect.move(self.x,self.y)
    def getX(self):
        return self.x
    def getY(self):
        return self.y
    def getHealth(self):
        return self.health
    def setHealth(self,amount):
        self.health = amount
    def render(self):
        self.display.blit(self.image,self.rect)

#Create Objects
player = PlayerShip(display)

#Main Loop
while 1:
    
    #Get Events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                player.setMoving(0,1)
            if event.key == pygame.K_a:
                player.setMoving(2,1)
            if event.key == pygame.K_s:
                player.setMoving(1,1)
            if event.key == pygame.K_d:
                player.setMoving(3,1)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w:
                player.setMoving(0,0)
            if event.key == pygame.K_a:
                player.setMoving(2,0)
            if event.key == pygame.K_s:
                player.setMoving(1,0)
            if event.key == pygame.K_d:
                player.setMoving(3,0)
                
    #Check Moving
    if player.getMoving(0) == 1:
        player.move(player.getX(),player.getY()-1)
    if player.getMoving(1) == 1:
        player.move(player.getX(),player.getY()+1)
    if player.getMoving(2) == 1:
        player.move(player.getX()-1,player.getY())
    if player.getMoving(3) == 1:
        player.move(player.getX()+1,player.getY())
    
    #Rendering
    display.fill((0,0,0))
    player.render()
    
    #Flip
    pygame.display.flip()
    #Delay
    pygame.time.delay(20)
Mfg Benni1000
Lust auf Russisches Roulette?
[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo "You live"

Besucht doch mal meine Website und hinterlasst Kommentare zu meinen Programmen.
Alle Programme sind OpenSource und mit einer CreativeCommons Lizenz geschützt.
http://benni1000.eu
deets

Also es faengt schonmal damit an, dass man in Python keine getter/setter verwendet. Dann hast du die unnoetigen x/y im PlayerShip. Und wenn die weg sind, dann faellt dir auch gleich dein Programmierfehler auf - naemlich in move() self.x und self.y zu benutzen, statt nur relative Koordinaten ala 0, 1 oder -1, 1.

Und das ist dann noch das finale: Rect.move bewegt *RELATIV* zur bestehenden Position. Nicht absolut. Also kannst du dir das ganze player.move(playger.getX...) gehumse sparen.
Benutzeravatar
Benni1000
User
Beiträge: 9
Registriert: Mittwoch 27. Juni 2012, 13:51
Wohnort: Österreich
Kontaktdaten:

Vielen Dank, es funktioniert jetzt.
Ich arbeite jetzt komplett ohne Getter und Setter. Ich war das von Java so gewöhnt, mir was garnicht klar das man die in Python weglassen kann.
Lust auf Russisches Roulette?
[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo "You live"

Besucht doch mal meine Website und hinterlasst Kommentare zu meinen Programmen.
Alle Programme sind OpenSource und mit einer CreativeCommons Lizenz geschützt.
http://benni1000.eu
Antworten