Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am making a tile based game in pygame, and I would like to have a smooth walking animation between tiles with the player class. I have made it so that the player will face in the correct direction.
I tried to have a small delay between switching animations, but it didn't work very well. It just froze for a split second.
class Player(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites
self._layer = PLAYER_LAYER
pygame.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.image = self.game.spritesheet.get_image(0,32,32,32)
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.x = x
self.y = y
self.dir = 'UP'
def move(self, x_change, y_change):
if x_change > 0:
self.dir = 'RIGHT'
if x_change < 0:
self.dir = 'LEFT'
if y_change > 0:
self.dir = 'DOWN'
if y_change < 0:
self.dir = 'UP'
if not self.collide(x_change, y_change):
self.x += x_change
self.y += y_change
if self.dir == 'UP':
self.image = self.game.spritesheet.get_image(64,96,32,32)
self.image.set_colorkey(BLACK)
time.sleep(1)
self.image = self.game.spritesheet.get_image(32,96,32,32)
self.image.set_colorkey(BLACK)
if self.dir == 'LEFT':
self.image = self.game.spritesheet.get_image(96,32,32,32)
self.image.set_colorkey(BLACK)
if self.dir == 'RIGHT':
self.image = self.game.spritesheet.get_image(64,64,32,32)
self.image.set_colorkey(BLACK)
if self.dir == 'DOWN':
self.image = self.game.spritesheet.get_image(0,32,32,32)
self.image.set_colorkey(BLACK)
def collide(self, x_change, y_change):
for block in self.game.blocks:
if block.x == self.x + x_change and block.y == self.y + y_change and block.collidable:
return True
return False
def update(self):
self.rect.x = self.x * SCALE
self.rect.y = self.y * SCALE
Thanks
Create a list of the sprites for animation in a certain direction:
self.image_up = [self.game.spritesheet.get_image(64,96,32,32),
self.game.spritesheet.get_image(32,96,32,32)]
Add an attribute walkcount:
self.walkcount = 0
Increment walkcount in move and get an image from self.image_up, indexed by self.walkcount:
if self.walkcount >= len(self.image_up)
self.walkcount = 0
self.image = self.image_up[self.walkcount]
self.walkcount += 1
Class Player:
class Player(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites
self._layer = PLAYER_LAYER
pygame.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.image = self.game.spritesheet.get_image(0,32,32,32)
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.x = x
self.y = y
self.dir = 'UP'
self.image_up = [self.game.spritesheet.get_image(64,96,32,32),
self.game.spritesheet.get_image(32,96,32,32)]
self.image_left = [self.game.spritesheet.get_image(96,32,32,32)]
self.image_right = [self.game.spritesheet.get_image(64,64,32,32)]
self.image_down = [self.game.spritesheet.get_image(0,32,32,32)]
self.walkcount = 0
def move(self, x_change, y_change):
if x_change > 0:
self.dir = 'RIGHT'
if x_change < 0:
self.dir = 'LEFT'
if y_change > 0:
self.dir = 'DOWN'
if y_change < 0:
self.dir = 'UP'
if not self.collide(x_change, y_change):
self.x += x_change
self.y += y_change
image_list = None
if self.dir == 'UP':
image_list = self.image_up
elif self.dir == 'LEFT':
image_list = self.image_left
elif self.dir == 'RIGHT':
image_list = self.image_right
elif self.dir == 'DOWN':
image_list = self.image_down
if image_list:
if self.walkcount >= len(image_list)
self.walkcount = 0
self.image = image_list[self.walkcount]
self.walkcount += 1
self.image.set_colorkey(BLACK)
def collide(self, x_change, y_change):
for block in self.game.blocks:
if block.x == self.x + x_change and block.y == self.y + y_change and block.collidable:
return True
return False
def update(self):
self.rect.x = self.x * SCALE
self.rect.y = self.y * SCALE
Related
I am working on a small game where if you click a circle it makes a pop sound and goes back to the bottom my problem is when I switched to using a class and sprite to allow multiple circles it no longer will detect if one is clicked what am I doing wrong?
class Bubble(pygame.sprite.Sprite):
def __init__(self):
self.radius = random.randint(50,100)
self.image = pygame.Surface([self.radius/2,self.radius/2])
self.image.fill(blue)
self.image = pygame.image.load(bPath+"Images\\Bubble.png")
self.rect = self.image.get_rect()
self.bx = random.randint(70, 1466)
self.x = self.bx
self.y = 930
self.way = 0
self.rect.x = self.x
self.rect.y = self.y
def move(self):
pygame.draw.circle(tv,blue,(self.x,self.y),self.radius)
self.y -= 2
if self.x == self.bx+20:
self.way = 1
elif self.x == self.bx-20:
self.way = 0
else:
pass
if self.way == 0:
self.x += 1
else:
self.x -= 1
if self.y <= 0:
self.bx = random.randint(70, 1466)
self.x = self.bx
self.y = 930
self.radius=random.randint(50,100)
else:
pass
bubbleList = []
nBubble = 0
while True:
tv.fill(white)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
for b in bubbleList:
if b.rect.collidepoint(pygame.mouse.get_pos()):
print("hi")
pygame.mixer.music.play()
if pygame.time.get_ticks() > nBubble:
nBubble += 5000
if len(bubbleList) < 10:
bubbleList.append(Bubble())
else:
pass
for b in bubbleList:
b.move()
pygame.display.update()
FramePerSec.tick(fps)
I have looked at a couple other similar posts on here and have implemented them as you can probably see. It throws no errors on my computer it just does nothing when clicked.
What are self.x and self.y for? You don't need these attributes. You have self.rect.x and self.rect.y. The collision detection depends on the position stored in the rect attribute.
if b.rect.collidepoint(pygame.mouse.get_pos()):
However, self.rect.x and self.rect.y do not magically change when you change self.x and self.y. The position stored in the rect attribute is not tied to self.x and self.y. Get rid of self.x and self.y:
class Bubble(pygame.sprite.Sprite):
def __init__(self):
self.radius = random.randint(50,100)
self.image = pygame.Surface([self.radius/2,self.radius/2])
self.image.fill(blue)
self.image = pygame.image.load(bPath+"Images\\Bubble.png")
self.rect = self.image.get_rect()
self.bx = random.randint(70, 1466)
self.way = 0
self.rect.x = self.bx
self.rect.y = 930
def move(self):
pygame.draw.circle(tv, blue, self.rect.center, self.radius)
self.rect.y -= 2
if self.rect.x == self.bx+20:
self.way = 1
elif self.rect.x == self.bx-20:
self.way = 0
else:
pass
if self.way == 0:
self.rect.x += 1
else:
self.rect.x -= 1
if self.rect.y <= 0:
self.bx = random.randint(70, 1466)
self.rect.x = self.bx
self.rect.y = 930
self.radius=random.randint(50,100)
else:
pass
See also How do I detect collision in pygame?.
There is a "player" (sprite) and a group of walls (other_group), also sprites. When creating a wall with NOT the same x/y coordinates, the sprite.spritecollide method does not work correctly. Horizontally everything is ok, vertically the player just falls into the wall.
fullcode
class Tile(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__(other_group)
self.image = wall_images
self.rect = self.image.get_rect().move(x, y)
# player
class Player(pygame.sprite.Sprite):
def __init__(self, speed, x, y):
super().__init__(player_group)
self.speed = speed
self.frames = []
self.cur_frame = 0
self.image = animation_down[0]
self.rect = self.image.get_rect().move(x, y)
self.rect.x = x
self.rect.y = y
def possibility_of_movement(self, directory_of_movement):
if directory_of_movement == 'right':
tester = Player(self.speed, self.rect.x + self.speed, self.rect.y)
elif directory_of_movement == 'left':
tester = Player(self.speed, self.rect.x - self.speed, self.rect.y)
elif directory_of_movement == 'up':
tester = Player(self.speed, self.rect.y - self.speed, self.rect.x)
else:
tester = Player(self.speed, self.rect.y + self.speed, self.rect.x)
if pygame.sprite.spritecollide(tester, other_group, dokill=False, collided=pygame.sprite.collide_rect_ratio(0.7)):
tester.kill()
return False
else:
return True
tile2 = Tile(264, 264)
tile3 = Tile(264+64, 264)
tile4 = Tile(446, 446)
tile4 = Tile(382, 382)
while running:
if keys[pygame.K_LEFT] and pos_x > 5 and player.possibility_of_movement('left'):
pos_x -= player.speed
left = True
right = False
down = False
up = False
I can't test it but I think all problem is because you set values in wrong order when you create tester - and it checks collision with wrong place (with place which doesn't have any wall) and it doesn't stop.
For up (and similar for down) you set y-speed,x but you have to set x, y-speed
Correct oder of values in Player()
elif directory_of_movement == 'up':
tester = Player(self.speed, self.rect.x, self.rect.y - self.speed)
else:
tester = Player(self.speed, self.rect.x, self.rect.y + self.speed)
This question already exists:
I want to do an explosion animation. I have 4 png files number 0 - 3. In my debris class I loaded them into an image list using a for loop [duplicate]
Closed 1 year ago.
I want to do an explosion animation. I have 4 png files number 0 - 3. In my debris class I loaded them into an image list using a for loop. Then I made an explosion function but when I load my pygame windows and start shooting my cement block sprites, my cement block sprites disappear which is fine but they don't do the exploding animation I want. How can I fix this problem. Would appreciate the help.
My code:
import random
import pygame
import pygame.freetype
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
self.score = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#check collision
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1
debris.kill()
#player stats
def stats(self):
myfont = pygame.font.SysFont('comicsans', 30)
scoretext = myfont.render("Score: " + str(self.score), 1, (0,0,0))
screen.blit(scoretext, (100,10))
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.centery < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self,scale,speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = random.randrange(100,800)
self.speed_y = 10
self.y = 15
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
self.velocity = random.randrange(1,2)
self.speed_x = random.randrange(-3,3)
self.moving_down = True
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.rect.center = (self.x,self.y)
#load explosion
self.images = []
for i in range(4):
self.images.append(pygame.image.load(f'explosion/{i}.png'))
self.index = 0
self.img = self.images[self.index]
#spawn new debris
def spawn_new_debris(self):
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.velocity = random.randrange(1, 2)
self.speed_x = random.randrange(-3, 3)
#respawn debris when they go of the screen
def boundaries(self):
if self.rect.left > WIDTH + 10 or self.rect.right < -10 or self.rect.top > HEIGHT + 10:
self.spawn_new_debris()
#update image
def update(self):
self.rect.y += self.velocity
self.rect.x += self.speed_x
self.boundaries()
#make debris fall down
def falldown(self):
self.rect.centery += self.velocity
if self.moving_down and self.rect.y > 350:
self.kill()
#explosion
def explode(self):
if self.max_health <= 0:
self.index += 1
if self.index >= len(self.images):
self.index = 0
self.img = self.images[self.index]
######################CAR/DEBRIS##########################
player = Player(1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
for i in range(50):
d = Debris(1,5)
debris_group.add(d)
all_sprites.add(d)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 1 year ago.
import libraries and define variables
import pygame, sys
import math
#variables globales
pygame.init()
size = width, height = 1000,700
screen = pygame.display.set_mode(size)
white = 255,255,255
reloj = pygame.time.Clock()
x = 100
y = 550
canjump = False
level = 3
this is my player class
class Player:
x = 100
y = 550
jump = 0
change_x = 0
change_y = 0
ha_saltado = False
top = 550
plataformaTop = False
def __init__(self):
super().__init__()
square_size = 50,50
self.image = pygame.Surface((square_size))
self.image.fill(white)
#establecer referencia de la imagen
self.rect = self.image.get_rect()
self.impulso_salto = 10
draw my player with x and y coordinates
def dibujar(self):
self.x += self.change_x
self.rect.x = self.x + self.change_x
self.rect.y = self.y
screen.blit(self.image, (self.x,self.y))
#movimiento horizontal
change player coordinates
def derecha (self):
self.change_x = 5
def izquierda (self):
self.change_x = -5
def stop (self):
self.change_x = 0
gravity function
#gravedad
def grav(self):
if self.ha_saltado:
if self.impulso_salto>= -10:
if self.impulso_salto < 0:
self.y += (self.impulso_salto ** 2)*0.5
else:
self.y -= (self.impulso_salto ** 2)*0.5
self.impulso_salto -= 1
else:
self.ha_saltado = False
canjump = False
self.impulso_salto = 10
def salto(self):
Player.grav(self)
def colisiones(self):
self.y += 2
if self.rect.colliderect(plataforma.rect):
self.plataformaTop = True
else:
self.plataformaTop = False
self.y -= 2
if self.plataformaTop:
print(plataforma.rect.top, self.y)
self.y -= 6
this is my stage class, here i make a white rectangle and i want my player can collide with the rectangle
class Escenario:
def __init__(self):
super().__init__()
here i create the rectangle
self.image = pygame.Surface([300,100])
self.image.fill(white)
self.rect = self.image.get_rect()
def dibujar(self, x, y):
screen.blit(self.image, (x, y))
self.rect.x = x
self.rect.y = y
here I create the events and initialize the objects
plataforma = Escenario()
player = Player()
texto = Texto()
pygame.mixer.music.load("C:/Users/Mati/Desktop/game/ost.mp3")
pygame.mixer.music.play()
while 1:
screen.fill((0,0,0))
player.colisiones()
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.derecha()
if event.key == pygame.K_LEFT:
player.izquierda()
if event.key == pygame.K_x:
player.stop()
if event.key == pygame.K_UP:
canjump = True
player.ha_saltado = True
gravity control
if canjump == True and player.ha_saltado == True:
player.salto()
else:
player.ha_saltado = False
if player.y < 550:
player.y += 10
level control(when the player x coordinate is greater than the screen width, the level increases)
if player.x >= width:
level += 1
player.x = 100
if level == 1:
texto.write("welcome to monochromatic adventure", 43, 200)
if level == 3:
plataforma.dibujar(800,500)
player.colisiones()
if level == 2:
texto.write("stage 1: Anguish", 43, 200)
update the game frames and draw the objects
#dibujar escenario
player.dibujar()
pygame.draw.line(screen, white, [1000, 600], [0, 600], 2)
reloj.tick(60)
pygame.display.flip()
There is a bug in the dibujar method. It must be self.rect.x = self.x instead of self.rect.x = self.x + self.change_x:
class Player:
# [...]
def dibujar(self):
self.x += self.change_x
self.rect.x = self.x
self.rect.y = self.y
screen.blit(self.image, self.rect)
I am building a top down shooter in the style of Raiden 2. I need to know how to get access to the enemy object when I detect collision using 'spritecollide'.
The reason I need the enemy object is so that I can lower their energy level for every bullet that hits them.
This is the dictionary that I have to work with:
enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)
Here's my Bullet class:
class Bullet(Entity):
def __init__(self, ship, angle):
Entity.__init__(self)
self.speed = 8
self.level = 0
self.image = pygame.Surface((BULLET_DIMENSIONS, BULLET_DIMENSIONS)).convert()
self.rect = self.image.get_rect()
self.rect.x = ship.rect.centerx
self.rect.y = ship.rect.top
self.angle = angle
def update(self, enemyGroup):
if self.rect.bottom < 0:
self.kill()
else:
self.rect.y -= self.speed
Here's my unfinished Enemy class:
class Enemy_1(Entity):
def __init__(self):
Entity.__init__(self)
self.speed = (1, 1)
self.energy = 10
self.begin = False
self.run = False
self.image = pygame.Surface((WIN_W/5, WIN_H/15)).convert()
self.image.fill((70, 70, 70))
self.rect = self.image.get_rect()
self.rect.centerx = WIN_W/1.333
self.rect.y = -WIN_H/15
def shoot(self):
bullet_1 = Bullet(self, 270)
bullet_2 = Bullet(self, 225)
bullet_3 = Bullet(self, 315)
def update(self, enemyGroup, timer):
if timer == 300:
self.begin = True
elif timer == 900:
self.run = True
elif timer > 900 and self.rect.x > WIN_W:
self.remove(enemyGroup)
if self.run:
self.rect.x += self.speed[0]
self.rect.y += self.speed[1]
elif self.begin:
self.rect.y += self.speed[1]
if self.rect.y > WIN_H/4:
self.rect.y = WIN_H/4
if self.energy == 0:
self.kill()
Here's the complete program:
import sys, pygame, os, random, math
from ast import literal_eval
# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'
# Constants
LEFT = 'left'
RIGHT = 'right'
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PILL_WIDTH = 5
PILL_HEIGHT = 20
WIN_W = 500
WIN_H = 800
SHIP_WIDTH = WIN_W/15
SHIP_HEIGHT = WIN_H/15
BULLET_DIMENSIONS = 5
TIMER = 0
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class Text(Entity):
def __init__(self, text, size, color, position, font=None):
Entity.__init__(self)
self.color = color
self.font = pygame.font.Font(font, size)
self.text = text
self.set(text, position)
def set(self, text, position):
self.image = self.font.render(str(text), 1, self.color)
self.rect = self.image.get_rect()
self.rect.move_ip(position[0]-self.rect.width/2, (position[1]-self.rect.height)/2)
class Ship(Entity):
def __init__(self, container):
Entity.__init__(self)
self.speed = 5
self.score = 0
self.image = pygame.Surface((SHIP_WIDTH, SHIP_HEIGHT)).convert()
self.rect = self.image.get_rect()
self.rect.centerx = container.centerx
self.rect.y = container.centery
def update(self, bulletGroup):
key = pygame.key.get_pressed()
if key[pygame.K_w]:
self.rect.centery -= self.speed
if key[pygame.K_s]:
self.rect.centery += self.speed
if key[pygame.K_d]:
self.rect.centerx += self.speed
if key[pygame.K_a]:
self.rect.centerx -= self.speed
if key[pygame.K_SPACE]:
if TIMER % 7 == 0:
bullet = Bullet(self, 90, 'friend')
bulletGroup.add(bullet)
# Ship Movement Boundaries
if self.rect.y < WIN_H/25:
self.rect.y = WIN_H/25
if self.rect.y > WIN_H - SHIP_HEIGHT:
self.rect.y = WIN_H - SHIP_HEIGHT
if self.rect.x < 0:
self.rect.x = 0
if self.rect.x > WIN_W - SHIP_WIDTH:
self.rect.x = WIN_W - SHIP_WIDTH
class Bullet(Entity):
def __init__(self, ship, angle, type):
Entity.__init__(self)
self.speed = 8
self.level = 0
self.image = pygame.Surface((BULLET_DIMENSIONS, BULLET_DIMENSIONS)).convert()
self.rect = self.image.get_rect()
self.dx = math.cos(math.radians(angle)) * self.speed
self.dy = math.sin(math.radians(angle)) * self.speed
self.setXY(ship, type)
def setXY(self, ship, type):
self.rect.x = ship.rect.centerx
if type == 'friend':
self.rect.y = ship.rect.top
elif type == 'enemy':
self.rect.y = ship.rect.bottom
def update(self):
if self.rect.bottom < 0:
self.kill()
else:
self.rect.x -= self.dx
self.rect.y -= self.dy
if type == 'friend':
self.rect.y = -self.rect.y
self.rect.x = -self.rect.x
class Powerup(Entity):
def __init__(self, xden, pillCount):
Entity.__init__(self)
self.speed = 3
self.density = xden
self.image = pygame.Surface((PILL_WIDTH, PILL_HEIGHT)).convert()
self.rect = self.image.get_rect()
self.rect = self.rect.move(100,100)
def restart(self):
pass
def update(self):
if self.rect.y > WIN_H:
del self
else:
self.rect = self.rect.move((0, self.speed))
class Enemy(Entity):
def __init__(self):
Entity.__init__(self)
self.begin = False
self.run = False
self.color = (153, 0, 76)
class Planes(Enemy):
def __init__(self, speed, energy, size, location):
Enemy.__init__(self)
self.speed = speed
self.energy = energy
self.image = pygame.Surface(size).convert()
self.image.fill(self.color)
self.rect = self.image.get_rect()
self.rect.centerx = location[0]
self.rect.y = location[1]
def shoot(self, enemyBulletGroup):
bullet_1 = Bullet(self, 240, 'enemy')
bullet_2 = Bullet(self, 270, 'enemy')
bullet_3 = Bullet(self, 300, 'enemy')
enemyBulletGroup.add(bullet_1, bullet_2, bullet_3)
def update(self, enemyGroup, enemyBulletGroup):
if TIMER == 300:
self.begin = True
elif TIMER == 900:
self.run = True
elif self.rect.x > WIN_W or self.energy == 0:
self.kill()
if self.run:
self.rect.x += self.speed[0]
self.rect.y += self.speed[1]
if TIMER % 100 == 0:
self.shoot(enemyBulletGroup)
elif self.begin:
self.rect.y += self.speed[1]
if self.rect.y > WIN_H/4:
self.rect.y = WIN_H/4
if TIMER % 100 == 0:
self.shoot(enemyBulletGroup)
def main():
# Initialize Everything
pygame.init()
global TIMER
fps = 60
lLeft = lRight = lUp = lDown = shoot = False
clock = pygame.time.Clock()
play = True
pygame.display.set_caption('Pong')
screen = pygame.display.set_mode((WIN_W, WIN_H), pygame.SRCALPHA)
# Create Game Objects
ship = Ship(pygame.rect.Rect(0, 0, WIN_W, WIN_H))
score1 = Text("Score: " + str(ship.score), 40, BLACK, (WIN_W/2, (WIN_H/25)))
enemy_1 = Planes((1, 1), 10, (WIN_W/5, WIN_H/15), (WIN_W/1.4, -WIN_H/15))
# Create Groups
powerupGroup = pygame.sprite.Group()
shipGroup = pygame.sprite.Group()
shipGroup.add(ship)
textGroup = pygame.sprite.Group()
textGroup.add(score1)
shipBulletGroup = pygame.sprite.Group()
enemyBulletGroup = pygame.sprite.Group()
enemyGroup = pygame.sprite.Group()
enemyGroup.add(enemy_1)
# Gameplay
while play:
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
# Update
powerupGroup.update()
ship.update(shipBulletGroup)
shipBulletGroup.update()
textGroup.update()
enemyGroup.update(enemyGroup, enemyBulletGroup)
enemyBulletGroup.update()
enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)
for key in enemyCollisions:
print enemyCollisions[key].energy
# Print Background/Sprites
screen.fill(WHITE)
powerupGroup.draw(screen)
shipGroup.draw(screen)
shipBulletGroup.draw(screen)
textGroup.draw(screen)
enemyGroup.draw(screen)
enemyBulletGroup.draw(screen)
# Print Score Bar
hori_partition = pygame.Surface((WIN_W, 1))
screen.blit(hori_partition, (0, WIN_H/25))
TIMER += 1
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
if __name__ == "__main__":
main()
The pygame.sprite.groupcollide() function returns a dictionary which values are list objects:
Every Sprite inside group1 is added to the return dictionary. The value for each item is the list of Sprites in group2 that intersect.
Thats the reason why calling print enemyCollisions[key].energy when iterating over the return dict fails, since a list object -- the value of enemyCollisions[key] -- does not have an energy() method.
To access all values of a dictionary in Python 2.X you could use the .itervalues() method of a dict instance. To get each colliding sprite, iterate again over these values:
enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)
#iterate over all values of the enemyCollisions dict
for enemyCollisions in enemyCollisions.itervalues():
#access all enemies which collided with an shipBullet
for enemy in enemyCollisions:
print enemy.energy
The syntax for accessing the collided sprite's property is as follows:
collisions = pygame.sprite.spritecollide(self, pillGroup, True)
for key in collisions:
self.density += key.density