[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[pygame] Collision Issues
- To: pygame-users@xxxxxxxx
- Subject: [pygame] Collision Issues
- From: Scott Miller <miller.scott.j@xxxxxxxxx>
- Date: Mon, 24 Aug 2009 19:11:55 +0300
- Delivered-to: archiver@xxxxxxxx
- Delivered-to: pygame-users-outgoing@xxxxxxxx
- Delivered-to: pygame-users@xxxxxxxx
- Delivery-date: Mon, 24 Aug 2009 12:18:28 -0400
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type; bh=8wegXFaq5h3BQifV/zM7vQnqhy5AcH6K6GUzH7cYkW8=; b=t2JeS1JoqQtI/Jomgf62ymyIGUNDBNwOAIPA5ezsyrDFIFawLBO74lIR3Z3qOdVBbC /AC0n4l90/+CCEtIKhrGUX5bb3IVj8btnVOGUY45Rr0l3oyxmAxAcKb3lNOXfsX7v6ui EZf/m9iZuZlx2D20eiW3Ncf0S4qTD2w33W5/c=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=SgNek/ODnagKlo7QmqB0bH03UFfxCxWOjQ+wuXBUvhWC3JthaIjnF3Q/NZD1wrMsIo riQGGK6QRjITeZaOx04OiFegd5Qj+fneGU/sPrEF9y3N2enthpgvQ0jgBx4vaaMbCxDs k1KzJYb4EMWv/T9jo1tIAJMeQAsNHThoP6a2Y=
- Reply-to: pygame-users@xxxxxxxx
- Sender: owner-pygame-users@xxxxxxxx
I've been messing around with a sample from the L Line's book on game programming, and I've tried to further develop their space.py example that demonstrates a ship without friction. I've tried my hardest to properly enter collision detection on a set of 40,40 rects that are placed throughout the 800,600 screen, but it is proving to be a bit harder than first imagined. The issues that I am noticing is that sometimes the sprite will catch the collisions, sometimes they won't. Another is the rotate() method. If I rotated, the sprite's rect will expand and throw off the collision detection as well, sending the sprite all throughout the screen and eventually off into the great unknown. May I ask for assistance in pointing me to what I am doing wrong with this? I would greatly appreciate any help provided! Thank you very very much!
""" space.py
simulate a spacecraft with
no traction at all
"""
import pygame, math
pygame.init()
class Ship(pygame.sprite.Sprite):
# Sprite containing the main ship that the user will control in the game.
# Methods:
# update()
# checkKeys()
# rotate()
# calcVector()
# setPos()
# checkCollision()
def __init__(self, screen, walls, map):
pygame.sprite.Sprite.__init__(self)
self.walls = walls #import the wall sprite group for collision detection
self.imageThrust = pygame.image.load("shipThrust.png") #image for the sprite while applying thrust
self.imageThrust = self.imageThrust.convert()
self.imageCruise = pygame.image.load("shipCruise.png") #image for the sprite when idle
self.imageCruise = self.imageCruise.convert()
self.imageLeft = pygame.image.load("shipLeft.png") #image for the sprite when rotating left
self.imageLeft = self.imageLeft.convert()
self.imageRight = pygame.image.load("shipRight.png") #image for the sprite when rotating right
self.imageRight = self.imageRight.convert()
#designate the initial master image and get the rect for it
self.imageMaster = self.imageCruise
self.image = self.imageMaster
self.rect = self.image.get_rect()
#some initial properties, including initial position, difference in x/y, direction, turn rate,
#and thrust of the Ship sprite
self.x = 100
self.y = 100
self.dx = 0
self.dy = 0
self.dir = 0
self.turnRate = 5
self.thrust = 0
def update(self):
#The default update method that is called in the main loop.
#all further methods are properly encapsulated in order
#to keep stuff tidy!
self.checkKeys()
self.rotate()
self.calcVector()
self.checkCollision()
self.setPos()
#after all the methods get their chance, we finish up this frame by
#placing the sprite in the proper x and y position
self.rect.center = (self.x, self.y)
def checkKeys(self):
#we store the pressed key in the variable "keys" so that we may flip through
#all the posibilities. Note that we are doing individual if statements
#so that we may apply multiple keys at once, instead of one at a time with
#the elif approach
keys = pygame.key.get_pressed()
self.imageMaster = self.imageCruise #start with the cruising sprite image
if keys[pygame.K_RIGHT]:
self.dir -= self.turnRate #rotate clockwise
if self.dir < 0:
self.dir = 360 - self.turnRate
self.imageMaster = self.imageRight
self.checkCollision()
if keys[pygame.K_LEFT]:
self.dir += self.turnRate #rotate counter-clockwise
if self.dir > 360:
self.dir = self.turnRate
self.imageMaster = self.imageLeft
self.checkCollision()
if keys[pygame.K_UP]:
self.thrust = .1 #apply thrust
self.imageMaster = self.imageThrust
else:
self.thrust = 0 #nothing was pressed, speed will remain constant
def rotate(self):
oldCenter = self.rect.center #get the old center so that we may recenter after rotating
self.image = pygame.transform.rotate(self.imageMaster, self.dir)
self.rect = self.image.get_rect() #get the rect for the newly rotated sprite
self.rect.center = oldCenter #and center it back on it's old x,y coord's
def calcVector(self):
radians = self.dir * math.pi / 180
thrustDx = self.thrust * math.cos(radians)
thrustDy = self.thrust * math.sin(radians)
thrustDy *= -1
self.dx += thrustDx
self.dy += thrustDy
self.speed = math.sqrt((self.dx * self.dx) + (self.dy * self.dy))
def setPos(self):
#The final piece before the x/y coords are placed on the sprite
self.x += self.dx
self.y += self.dy
def checkCollision(self):
#
# !!BROKEN!!
#
# Currently I have this set to detect for each rect in the walls sprite group
# If it collides with any of them, it will determine based off of the difference
# in x/y to see what direction it collided from. Once it determines the direction,
# it will clear the dx/dy (based on how it hit) so that the ship sprite will not
# move once it goes to the setPos() method, and it will also move it so that it
# is 15 pixels from the center of the direction it hit the wall. I chose 15px
# in this hopes that it will move it 1px extra away from the wall.
for wall in self.walls:
if self.rect.colliderect(wall.rect):
if self.dx > 0:
self.dx = 0
self.x = wall.rect.left-15
if self.dx < 0:
self.dx = 0
self.x = wall.rect.right+15
if self.dy > 0:
self.dy = 0
self.y = wall.rect.top-15
if self.dy < 0:
self.dy = 0
self.y = wall.rect.bottom+15
class Map(object):
# Sprite containing the boundaries and walls
def __init__(self,walls,screen):
self.walls = walls
self.screen = screen
self.grid = [
"++++++++++++++++++++",
"+ + +",
"+ + +",
"+ + +",
"+ + +",
"+ + +",
"+ ++++++",
"+ +",
"++++++ +",
"+ + +",
"+ + +",
"+ + +",
"+ + +",
"+ + +",
"++++++++++++++++++++"
]
self.x = self.y = 0
for row in self.grid:
for col in row:
if col == "+":
self.walls.add(Walls(self.x, self.y, self.walls, self.screen))
self.x += 40
self.y += 40
self.x = 0
class Walls(pygame.sprite.Sprite):
def __init__(self, x, y, walls, screen):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((40,40))
self.image.fill((0,0,0))
self.rect = self.image.get_rect()
self.rect.topleft = x,y
def main():
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Space craft")
background = ""> background.fill((200, 200, 200))
screen.blit(background, (0, 0))
walls = pygame.sprite.Group()
map = Map(walls, screen)
ship = Ship(screen, walls, map)
allSprites = pygame.sprite.Group(ship, walls)
clock = pygame.time.Clock()
keepGoing = True
while keepGoing:
clock.tick(50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
allSprites.clear(screen, background)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
if __name__ == "__main__":
main()
Again, thank you very much for the help!