Pygame spritecollide error - python

I have a few questions about pygame. I am completely new to python/pygame and curious if for one, I am doing this properly, or if I am writing this sloppy.
And for my other question, when I use spritecollide, object seems to still be there even after the image disappears. Let me share the code
import pygame, time, random, sys, player, creep, weapon
from pygame.locals import *
pygame.init()
#Variables for the game
width = 700
height = 500
clock = pygame.time.Clock()
screen = pygame.display.set_mode((width, height), 0, 32)
pygame.display.set_caption('Creep')
#Create Characters of the game
player1 = player.Player()
player1.rect.x = 0
player1.rect.y = 0
comp = creep.Creep()
comp.rect.x = random.randrange(width)
comp.rect.y = random.randrange(height)
bullet = weapon.Weapon()
bullet.rect.x = -1
bullet.rect.y = -1
#Make Character Groups
good = pygame.sprite.Group(player1)
bad = pygame.sprite.Group(comp)
weap = pygame.sprite.Group(bullet)
while True:
clock.tick(60)
screen.fill((0,0,0))
#set up for game to get input
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
sys.exit()
if event.type == KEYDOWN and event.key == K_c:
bullet.rect.x = player1.rect.x + 25
bullet.rect.y = player1.rect.y
#main controls
key = pygame.key.get_pressed()
if key[K_RIGHT]:
player1.rect.x = player1.moveRight(player1.rect.x)
if key[K_LEFT]:
player1.rect.x = player1.moveLeft(player1.rect.x)
if key[K_DOWN]:
player1.rect.y = player1.moveDown(player1.rect.y)
if key[K_UP]:
player1.rect.y = player1.moveUp(player1.rect.y)
if bullet.rect.x > -1:
weap.draw(screen)
bullet.rect.x = bullet.rect.x +5
pygame.sprite.spritecollide(bullet, bad, True)
pygame.sprite.spritecollide(comp, good, True)
#game functions
good.draw(screen)
bad.draw(screen)
pygame.display.flip()
So I have an image of a gun (player1, 'good' group), an image for the computer (comp, 'bad' group), and an image for a "bullet" when LCTRL is hit (bullet, 'weap' group).. when the bullet hits the image from the bad group, it disappears, which is what I want. But then when I move the player1 image in that direction, it will disappear as if the 'bad group' was still there. I hope this makes sense.
An example code of the classes I am calling on look like this:
import pygame
class Creep(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('creep.jpg')
self.rect = self.image.get_rect()
Any idea? and if there is a better way of going at this please let me know, I only started learning a week ago, and don't know if I am going in the proper direction, or not. Thanks!

I wasn't sure what some of your variables were. Note: If you put a sprite in multiple groups, then kill it, it will kill it in all groups automatically.
I started cleaning up the code.
#import time, sys, # not longer required
import player, creep, weapon
import random
import pygame
from pygame.locals import *
pygame.init()
#Variables for the game
width = 700
height = 500
clock = pygame.time.Clock()
screen = pygame.display.set_mode((width, height), 0, 32)
pygame.display.set_caption('Creep')
#Create Characters of the game
player1 = player.Player()
player1.rect.x = 0
player1.rect.y = 0
comp = creep.Creep()
comp.rect.topleft = random.randrange(width), random.randrange(height)
bullet = pygame.sprite.Sprite()# weapon.Weapon()
bullet.rect.topleft = (-1, -1)
#Make Character Groups
good = pygame.sprite.Group(player1)
bad = pygame.sprite.Group(comp)
weap = pygame.sprite.Group(bullet)
done = False
while not done:
clock.tick(60)
#set up for game to get input
for event in pygame.event.get():
if event.type == pygame.QUIT: done = True
if event.type == KEYDOWN:
if event.key == K_ESCAPE: done = True
elif event.key == K_c:
bullet.rect.x = player1.rect.x + 25
bullet.rect.y = player1.rect.y
#main controls
key = pygame.key.get_pressed()
if key[K_RIGHT]:
player.rect.x += 10
if key[K_LEFT]:
player1.rect.x -= 10
if key[K_DOWN]:
player.rect.y += 10
if key[K_UP]:
player.rect.y -= 10
# movement, collisions
pygame.sprite.spritecollide(bullet, bad, True)
pygame.sprite.spritecollide(comp, good, True)
# not sure what this was for? If you meant 'onscreen' or?
# You can kill it if it goes offscreen. Otherwise draw works if offscreen.
if bullet.rect.x > -1:
bullet.rect.x += 5
screen.fill(Color("black"))
weap.draw(screen)
#game functions
good.draw(screen)
bad.draw(screen)
pygame.display.flip()

Related

Player sprite ignoring my colliderect() with the ground surface and clipping right through and going down very fast

import pygame, time
from sys import exit
pygame.init()
pygame.font.init()
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
def update_fps():
fps = str(int(clock.get_fps()))
fps_text = font.render(fps, 1, pygame.Color("coral"))
return fps_text
# Game Variables / Functions
screen_width = 1068
screen_height = 628
screen = pygame.display.set_mode((screen_width, screen_height))
original_player_pos = (50, 500)
original_player_size = (40, 60)
FPS = 69
gravity = 0
jump_force = 15
player_speed_right = 10
player_speed_left = 10
ground_grip = True
can_jump = True
# Player
class player():
player_surf = pygame.image.load("Graphics\player_idle.png").convert_alpha()
player = player_surf.get_rect(topleft=(original_player_pos))
class background():
sky_surf = pygame.image.load("Graphics\Sky.png")
sky_surf = pygame.transform.scale(sky_surf, (screen_width * 2, screen_height * 2))
sky = sky_surf.get_rect(topleft=(0, -screen_height))
class surfaces():
main_platform_surf = pygame.image.load("Graphics\main_ground.png")
main_platform = main_platform_surf.get_rect(topleft=(0, screen_height - main_platform_surf.get_height() + (main_platform_surf.get_height()) / 2))
# Game Engine Functions
def y_movement():
global gravity, ground_grip,can_jump
gravity += 1
player().player.y += gravity
if ground_grip == True:
if player().player.colliderect(surfaces().main_platform):
player().player.y = surfaces().main_platform.y - original_player_size[1]
if not player().player.colliderect(surfaces().main_platform) and player().player.y < surfaces().main_platform.y - original_player_size[1]:
can_jump = False
else:
can_jump = True
def x_movement():
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
player().player.x += player_speed_right
return "Right"
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
player().player.x -= player_speed_left
return "Left"
def draw(surface, rect):
screen.blit(surface, rect)
def jump():
global gravity
gravity = -jump_force
# Game Engine
while True:
update_fps()
screen.fill("black")
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and can_jump == True:
ground_grip = False
if ground_grip == False:
jump()
ground_grip = True
x_movement()
y_movement()
draw(background().sky_surf, background().sky)
draw(surfaces().main_platform_surf, surfaces().main_platform)
draw(player().player_surf, player().player)
draw(update_fps(), (10,0))
clock.tick(FPS)
pygame.display.update()
Please try the code above out yourself, if you don't mind add some graphics to replace the pygame.image.load() or just replace it with a blank surface. When you run the program you see the main character and stuff, you can move around using WASD or arrow keys. Feel free to move around some stuff. Till now there is not a problem right? Now what I want you to do is stand still for 10 seconds (might happen sooner or later than that, should be around 10 seconds tho). When you stand still you will see the player sprite that you were moving around earlier literally just disappear. Now exit the program and add
print(player().player.y)
you will see the current player y location. Wait till the player dissapeares, and once it does, look at the y location that's gonna be printed out in your terminal. It will rapidly increase.
I tried 2 things. I added a variable that tries to grip the player into the ground if the player.y is over 0. It did not help and the player goes down anyways. I tried adding a variable that decides when the player can jump (because the y movement is linked directly to gravity and jumping) to decide when the player can jump. I was expecting the player sprite to just stay where it is.
When the player hits the platform, they must set the bottom of the player to the top of the platform.
player().player.bottom = surfaces().main_platform.top
Also set gravity = 0. If you do not reset gravity, gravity will increase until the player falls through the platform.
def y_movement():
global gravity, ground_grip,can_jump
gravity += 1
player().player.y += gravity
if ground_grip == True:
if player().player.colliderect(surfaces().main_platform):
player().player.bottom = surfaces().main_platform.top
gravity = 0
can_jump = True

Enemy Object wont move in Pygame

I'm trying to make a character move across the screen from the top to the bottom, where it will disappear. However, the code I have doesn't return any errors, but it won't move the character either. Here is my code:
import pygame
import sys
import random
pygame.init()
width , height = 600 , 500
display = pygame.display.set_mode((width, height ) )
pygame.display.set_caption("Class Test")
primoimage = pygame.image.load("/home/pi/Downloads/PRIMO/primo_0.png").convert()
class Enemy:
def __init__(self, name, shoot, speed, image):
self.name = name
self.shoot = shoot
self.speed = speed
self.image = image
def move(self):
enemyRack = []
if len(enemyRack) == 0:
enemyRack.append([width/2, 0])
for enemy in enemyRack:
display.blit(self.image, pygame.Rect(enemy[0], enemy[1], 0,0))
for e in range(len(enemyRack)):
enemyRack[e][1]+=2
for enemy in enemyRack:
if enemy[1] > height:
enemyRack.remove(enemy)
primo = Enemy("primo", 2, False, primoimage)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pass
primo.move()
pygame.display.update()
pygame.quit()
sys.exit()
The problem is in the move() function.
If you could figure it out that would be great! Thanks.
I added some indentation so things work again. (I'm assuming you just broke the indentation when posting your code). Your error was re-initializing enemyRack = [] every time move is called. That way you'll always have [300, 0] in the enemyRack.
import pygame
import sys
import random
pygame.init()
width , height = 600 , 500
display = pygame.display.set_mode((width, height ) )
pygame.display.set_caption("Class Test")
primoimage = pygame.image.load("player.png").convert()
class Enemy:
def __init__(self, name, shoot, speed, image):
self.name = name
self.shoot = shoot
self.speed = speed
self.image = image
self.enemyRack = [] # let's make this a class variable so we don't lose the contents
def move(self):
if len(self.enemyRack) == 0:
self.enemyRack.append([width/2, 0])
for enemy in self.enemyRack:
display.blit(self.image, pygame.Rect(enemy[0], enemy[1], 0,0))
for e in range(len(self.enemyRack)):
self.enemyRack[e][1]+=2
for enemy in self.enemyRack:
if enemy[1] > height:
self.enemyRack.remove(enemy)
primo = Enemy("primo", 2, False, primoimage)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pass
primo.move()
pygame.display.update()
pygame.quit()
sys.exit()

How do you add collision and make my foes to go slower in Pygame?

I made a game where the player has to dodge things called foes. I have tried doing the collision but have had no luck with it and I am not sure how to get the foes to go slower. The following is what I have so far:
import pygame,random, sys
from pygame.locals import *
from Player import *
from Person import *
from Badies import *
def terminate():
pygame.quit()
sys.exit()
def writeText(window, written, cenX, cenY):
font = pygame.font.Font(None, 48)
text = font.render(written, 1, TEXTCOLOR)
textpos = text.get_rect()
textpos.centerx = cenX
textpos.centery = cenY
window.blit(text, textpos)
return (textpos)
def waitForPlayerToPressKey():
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE: # pressing escape quits
terminate()
return
def playerHitFoes(playerRect, foes):
for f in foes:
if guy.getRect(f['rect']):
return True
return False
pygame.init()
screen = pygame.display.set_mode((800,600))
pygame.key.set_repeat(1, 1)
font = pygame.font.SysFont(None, 48)
WINDOWWIDTH = 800
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
FPS = 40
BADDIEMAXSIZE = 35
BADDIEMINSIZE = 35
BADDIEMAXSPEED = 10
BADDIEMINSPEED = 10
ADDNEWFOESRATE = 6
PLAYERMOVERATE = 5
changedRecs=[]
BACKGROUNDCOLOR = (255, 255, 255)
gameWin = False
win=False
score = 0
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
guy = Player(400, 525)
foes = Badies()
playerRect = getRec(guy)
foess = pygame.image.load('Bad.png')
writeText(screen,"How to Play?" , 400,100)
writeText(screen,"*Help Mario dodge the squares", 400,150)
writeText(screen,"*Controls: Up, Down, Left, Right.", 400,200)
writeText(screen,"(Press Any Key to Start.)", 400,250)
pygame.display.update()
waitForPlayerToPressKey()
gameEnd = foes.drawAndCollision(screen, guy)
pygame.display.update()
gameEnd = foes.drawAndCollision(screen, guy)
WHITE = (255,255,255)
screen.fill(WHITE)
pygame.display.update()
while True:
# set up the start of the game
foes= []
score = 0
moveLeft = moveRight = moveUp = moveDown = False
r = s = False
foesAddCounter = 0
while True: # the game loop runs while the game part is playing
score += 1 # increase score
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_LEFT:
guy.moveLeft()
if event.key == K_RIGHT:
guy.moveRight()
if event.key == K_UP:
guy.moveUp()
if event.key == K_DOWN:
guy.moveDown()
if not r and not s:
foesAddCounter += 1
if foesAddCounter == ADDNEWFOESRATE:
foesAddCounter = 0
baddieSize = BADDIEMAXSIZE
newFoes = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-baddieSize), 0 - baddieSize, baddieSize, baddieSize),
'speed': BADDIEMAXSPEED,
'surface':pygame.transform.scale(foess, (baddieSize, baddieSize)),
}
foes.append(newFoes)
for f in foes:
if not r and not s:
f['rect'].move_ip(0, f['speed'])
elif reverseCheat:
f['rect'].move_ip(0, -5)
elif slowCheat:
f['rect'].move_ip(0, 1)
for f in foes[:]:
if f['rect'].top > WINDOWHEIGHT:
foes.remove(f)
screen.fill(BACKGROUNDCOLOR)
writeText(screen,"Score: %s" % (score), 10, 0)
guy.draw(screen)
for f in foes:
windowSurface.blit(f['surface'], f['rect'])
pygame.display.update()
if playerHasHitBaddie(playerRect, baddies):
writeText(screen, "Game Over!", 400,300)
break
pygame.display.update()
This next part is the Player File:
import pygame
from pygame.locals import *
class Player:
# set all class variables in the constructor
def __init__(self, newX, newY):
self.x = newX
self.y = newY
# Add images to the list of images
self.images = [ "Player.gif", "PlayerR.gif","PlayerR.gif", "Player.gif"]
# Use this to keep track of which image to use
self.cos = 0
# draw your person with the correct image
def draw(self, window):
window.blit( pygame.image.load( self.images[ self.cos ] ),
(self.x,self.y))
# move person left and set the costume facing left.
def moveLeft(self):
self.x -= 1
self.cos = 3
# move person right and set the costume facing right
def moveRight(self):
self.x += 1
self.cos = 2
# move person up and set the costume facing up
def moveUp(self):
self.y -= 1
self.cos = 1
# move person down and set the costume facing down
def moveDown(self):
self.y += 1
self.cos = 0
def playerHitFoes(playerRect, foes):
for f in foes:
if playerRect.colliderect(f['rect']):
return True
def playerHasHitHeart(playerRect, foes):
for h in heart:
if playerRect.colliderect(h['rect']):
return True
def collide(self, other):
myRec = self.getRec
otherRec = other.getRec()
oRight = otherRec[0] + otherRec[2]
oBottom = otherRec[1] + otherRec[3]
right = myRec[0] + myRec[2]
bottom = myRec[1] + myRec[3]
if (otherRec[0] <= right) and (oRight >= self.x) and (otherRec[1] <= bottom) and (oBottom >= self.y):
return True
return False
def getRec(self):
myRec = pygame.image.load( self.images[ self.cos ] ).get_rect()
return (self.x, self.y, myRec[2], myRec[3])
Without having access to the gif's and being able to run this code, I'm going to assume your problem lies within how you check for collisions.
Namely, the colliderect() function takes one parameter, and it should be a pygame.Rect() object.
Meaning when you do your playerHitFoes you should pass the .rect object of your f['rect'] objects like so:
def playerHitFoes(playerRect, foes):
for f in foes:
if playerRect.colliderect(f['rect'].rect):
return True
def playerHasHitHeart(playerRect, foes):
for h in heart:
if playerRect.colliderect(h['rect'].rect):
return True
This might or might not solve your issue.
But I'll touch on some other things I found that is most likely not crucial to this problem, but might give you problems down the line.
def playerHitFoes(playerRect, foes):
for f in foes:
if guy.getRect(f['rect']):
return True
return False
In the code above, playerRect is never used, guy is not defined (all tho it will most likely pull the guy = Player() just fine, but this might cause issues for you.
playerHitFoes() is also defined twice, once out in the wild and once in the player function. But it's never used in your code examples.
playerHitFoes, playerHasHitHeart and collide? is never called upon anywhere in your code.
playerHasHitBaddie is used to check if game is over, but playerHasHitBaddie is never defined.
This code would give a lot of exceptions even if i had the gifs.
So I'll assume this is just a minor part of your code and you left out a lot of things.. So either the above solves the problem - or you need to give at least me more detail.. For instance what code do you use to do the actual collision detection?
List of things not defined or not used
Badies() - We don't know what it looks like
foes.drawAndCollision
playerHasHitBaddie
playerHitFoes
playerHasHitHeart
collide
gameWin
changedRecs
PLAYERMOVERATE
BADDIEMINSPEED
BADDIEMINSIZE
FPS
win
guy, TEXTCOLOR (Local variables in functions assuming global presence)
This was just to name a few.
One important one is what Badies() look like and how check/call for the collision detection.

Pygame seems to "avoid" loop

I am just getting started with Pygame and I am currently trying out some basic movement functions.
I ran into a problem when trying to code my movement conditions into my object class rather than in the game loop.
My first attempt which works is as follow:
classes.py:
import pygame, sys
from pygame.locals import *
class GameObject:
def __init__(self, image, height, speed):
self.speed = speed
self.image = image
self.pos = image.get_rect().move(0, height) #initial placement
def move_south(self):
self.pos = self.pos.move(0, self.speed)
if self.pos.right > 600:
self.pos.left = 0
def move_east(self):
self.pos = self.pos.move(self.speed , 0)
if self.pos.right > 600:
self.pos.left = 0
main.py:
import pygame, sys
from pygame.locals import *
from classes import *
screen = pygame.display.set_mode((640, 480))
#Importing Chars
player = pygame.image.load('green_hunter_small.png').convert()
#player.set_alpha(100) #makes whole player transparent
player.set_colorkey((0,0,0)) #sets background colour to transparent
ennemi = pygame.image.load('red_hunter_small.png').convert()
ennemi.set_colorkey((0,0,0))
background = pygame.image.load('grass_map_640x640.png').convert()
screen.blit(background, (0, 0))
objects = []
objects.append(GameObject(player, 80, 0))
for x in range(2): #create 2 objects
o = GameObject(ennemi, x*40, 0)
objects.append(o)
while True:
for event in pygame.event.get(): #setting up quit
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_DOWN:
for o in objects:
screen.blit(background, o.pos, o.pos) #erases players by bliting bg
for o in objects:
o.speed = 4
o.move_south() #moves player
o.speed = 0
screen.blit(o.image, o.pos) #draws player
if event.key == K_RIGHT:
for o in objects:
screen.blit(background, o.pos, o.pos) #erases players by bliting bg
for o in objects:
o.speed = 4
o.move_east() #moves player
o.speed = 0
screen.blit(o.image, o.pos) #draws player
pygame.display.update()
pygame.time.delay(50)
My second attempt which didn't work was to dp:
classes.py:
import pygame, sys
from pygame.locals import *
class GameObject:
def __init__(self, image, height, speed):
self.speed = speed
self.image = image
self.pos = image.get_rect().move(0, height) #initial placement
def move_south(self):
self.pos = self.pos.move(0, self.speed)
if self.pos.right > 600:
self.pos.left = 0
def move_east(self):
self.pos = self.pos.move(self.speed , 0)
if self.pos.right > 600:
self.pos.left = 0
def move(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_DOWN:
screen.blit(background, self.pos, self.pos) #erases players by bliting bg
self.speed = 4
self.move_south() #moves player
self.speed = 0
if event.key == K_RIGHT:
screen.blit(background, self.pos, self.pos) #erases players by bliting bg
self.speed = 4
self.move_east() #moves player
self.speed = 0
screen.blit(self.image, self.pos) #draws player
main.py:
import pygame, sys
from pygame.locals import *
from classes import *
screen = pygame.display.set_mode((640, 480))
#Importing Chars
player = pygame.image.load('green_hunter_small.png').convert()
#player.set_alpha(100) #makes whole player transparent
player.set_colorkey((0,0,0)) #sets background colour to transparent
ennemi = pygame.image.load('red_hunter_small.png').convert()
ennemi.set_colorkey((0,0,0))
background = pygame.image.load('grass_map_640x640.png').convert()
screen.blit(background, (0, 0))
objects = []
objects.append(GameObject(player, 80, 0))
for x in range(2): #create 2 objects
o = GameObject(ennemi, x*40, 0)
objects.append(o)
while True:
for event in pygame.event.get(): #setting up quit
if event.type == QUIT:
pygame.quit()
sys.exit()
for o in objects:
o.move()
pygame.display.update()
pygame.time.delay(50)
So it seems that the code struggles to go and check the event loop from the instance. The reason I wanted to code the movement as a method rather than straight in main was to save space and make it easier to add characters later on.
Your code has a race condition (to use the term really loosely).
The reason that your characters are not moving is that the first pygame.event.get call (when you are checking for a QUIT event) consumes all the KEYDOWN events that are on the queue. Then (unless you manage to press a key while the first loop is running), there are no KEYDOWN events in the queue when the first GameObject checks for events. Diddo for all other GameObjects.
You need to handler all pygame events in one loop. Example code:
class GameObject():
#rest of class
def move(self,event):
if event.key == K_DOWN:
screen.blit(background, self.pos, self.pos) #erases players by bliting bg
self.speed = 4
self.move_south() #moves player
self.speed = 0
#repeat for all other directions
screen.blit(self.image, self.pos) #draws player
#initialize objects
while True:
for event in pygame.event.get():
if event.type == QUIT: #handle quit event
elif event.type == KEYDOWN:
for o in objects:
o.move(event)
#do non-eventhandling tasks.

Pygame sprite assistance

I've basically just started developing with PyGame and I am having trouble with the whole Sprite concept. I have been looking every where for guides on how to use it, I just can't seem to find any. I would like to know the basic concept of how it all works. This is the code I have been working on:
#!/usr/bin/python
import pygame, sys
from pygame.locals import *
size = width, height = 320, 320
clock = pygame.time.Clock()
xDirection = 0
yDirection = 0
xPosition = 32
yPosition = 256
blockAmount = width/32
pygame.init()
screen = pygame.display.set_mode(size)
screen.fill([0, 155, 255])
pygame.display.set_caption("Mario Test")
background = pygame.Surface(screen.get_size())
mainCharacter = pygame.sprite.Sprite()
mainCharacter.image = pygame.image.load("data/character.png").convert()
mainCharacter.rect = mainCharacter.image.get_rect()
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image, mainCharacter.rect)
grass = pygame.sprite.Sprite()
grass.image = pygame.image.load("data/grass.png").convert()
grass.rect = grass.image.get_rect()
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 256]
screen.blit(grass.image, grass.rect.topleft )
running = False
jumping = False
falling = False
standing = True
jumpvel = 22
gravity = -1
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
running = True
xRun = -5
elif event.key == K_RIGHT:
running = True
xRun = 5
elif event.key == K_UP or event.key == K_SPACE:
jumping = True
elif event.type == KEYUP:
if event.key == K_LEFT or event.key == K_RIGHT:
running = False
if running == True:
xPosition += xRun
if mainCharacter.rect.right >= width:
xPosition = xPosition - 10
print "hit"
running = False
elif mainCharacter.rect.left <= 0:
xPosition = xPosition + 10
print "hit"
running = False
screen.fill([0, 155, 255])
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 64]
screen.blit(grass.image, grass.rect.topleft )
if jumping:
yPosition -= jumpvel
print jumpvel
jumpvel += gravity
if jumpvel < -22:
jumping = False
if mainCharacter.rect.bottom == grass.rect.top:
jumping = False
if not jumping:
jumpvel = 22
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image,mainCharacter.rect)
clock.tick(60)
pygame.display.update()
basically I just want to know how to make these grass blocks into sprites in a group, so that when I add my player (also a sprite) I can determine whether or not he is in the air or not through the collision system. Can someone please explain to me how I would do this. All I am looking for is basically a kick starter because some of the documentation is quite bad in my opinion as it doesn't completely tell you how to use it. Any help is greatly appreciated :)
In Pygame, sprites are very minimal. They consist of two main parts: an image and a rect. The image is what is displayed on the screen and the rect is used for positioning and collision detection. Here's an example of how your grass image could be made into a Sprite:
grass = pygame.image.load("grass.png")
grass = grass.convert_alpha()
grassSprite = new pygame.sprite.Sprite()
grassSprite.image = grass
#This automatically sets the rect to be the same size as your image.
grassSprite.rect = grass.get_rect()
Sprites are pretty pointless on their own, since you can always keep track of images and positions yourself. The advantage is in using groups. Here's an example of how a group might be used:
myGroup = pygame.sprite.Group()
myGroup.add([sprite1,sprite2,sprite3])
myGroup.update()
myGroup.draw()
if myGroup.has(sprite2):
myGroup.remove(sprite2)
This code creates a group, adds three sprites to the group, updates the sprites, draws them, checks to see if sprite2 is in the group, then removes the sprite. It is mostly straight forward, but there are some things to note:
1) Group.add() can take either a single sprite or any iterable collection of sprites, such as a list or a tuple.
2) Group.update() calls the update methods of all the Sprites it contains. Pygame's Sprite doesn't do anything when its update method is called; however, if you make a subclass of Sprite, you can override the update method to make it do something.
3) Group.draw() blits the images of all the Group's Sprites to the screen at the x and y positions of their rects. If you want to move a sprite, you change its rect's x and y positions like so: mySprite.rect.x = 4 or mySprite.rect.y -= 7
One way to use Groups is to create a different group for each level. Then call the update and draw method of whichever group represents the current level. Since nothing will happen or be displayed unless those methods are called, all other levels will remain "paused" until you switch back to them. Here's an example:
levels = [pygame.sprite.Group(),pygame.sprite.Group(),pygame.sprite.Group()]
levels[0].add(listOfLevel0Sprites)
levels[1].add(listOfLevel1Sprites)
levels[2].add(listOfLevel2Sprites)
currentLevel = 0
while(True):
levels[currentLevel].update()
levels[currentLevel].draw()
I know this question is somewhat old, but I hope you still find it helpful!

Categories

Resources