Pygame: Reset the Angle after Rotation - python

The helicopter flies from right to left. When a key is pressed it crashes. In the code excerpt, it flies to the bottom right corner.
Then another helicopter should come from the left and fly straight ahead to the right. That doesn't happen. He comes from the left and immediately falls again, although the angle has been reset.
breite,hoehe = 1200,800
screen = pygame.display.set_mode((breite,hoehe))
class Helikopter(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Bilder/heli1.png").convert_alpha()
self.img = pygame.transform.scale(self.image,(160,60))
self.rect = self.img.get_rect()
self.rect.x = - 20
self.rect.y = random.randrange(100,300)
self.speed = 10
self.absturz = False
self.angle = 0
def update(self):
self.rect.x += 2
self.rect.y += 0
if self.rect.x > breite or self.rect.y > hoehe:
self.rect.x = - 20
self.rect.y = random.randrange(100,300)
self.absturz == False
if self.absturz == True:
x = breite - self.rect.x
y = hoehe - self.rect.y
self.dist = math.sqrt(x ** 2 + y ** 2)
self.rect.x += self.speed *x / self.dist
self.rect.y += self.speed *y / self.dist
self.angle = math.degrees(-math.atan2(y, x))
else:
self.absturz = False
self.angle = 0
self.image = pygame.transform.rotozoom(self.img, self.angle,1)
heli_sprites = pygame.sprite.Group()
heli = Helikopter()
heli_sprites.add(heli)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
heli.absturz = True
screen.fill((250,0,0))
heli_sprites.draw(screen)
heli_sprites.update()
pygame.display.flip()

There are 2 problems:
self.absturz == False is a comparison, but not an assignement
self.absturz needs to be set True when self.rect hits the ground (self.absturz == True)
class Helikopter(pygame.sprite.Sprite):
# [...]
def update(self):
self.rect.x += 2
self.rect.y += 0
if self.rect.x > breite or self.rect.y > hoehe:
self.rect.x = - 20
self.rect.y = random.randrange(100,300)
self.absturz = True # <---
# [...]

Related

pygame detecting if drawn circle sprite is clicked failing

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?.

Im stuck on doing an explosion animation for my cement block sprites [duplicate]

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()

Make bullets fire off in the direction the player is facing

I was just getting some help to figure out how to get my player fire bullets when I realized that they only go (kinda expected this but however as only had y value for movement). I don't know how I'll make the bullets fire off in the direction the player is facing.
I have some idea of what to but I just don't know how to do it... I thought I could somehow use the cursor and player tracking that's in this game for the visuals but I don't know how to make that a one-time thing instead of a constant. For diagonal movement of the bullet, I have no clue.
Code below (split into two parts/file Main.py and PlayerSprite.py):
Main:
py.init()
py.mixer.init()
screen = py.display.set_mode((WIDTH, HEIGHT))
py.display.set_caption("Dimensional Drifter")
clock = py.time.Clock()
all_sprites = py.sprite.Group()
NPCs = py.sprite.Group()
bullets = py.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(14):
n = NPC(player)
all_sprites.add(n)
NPCs.add(n)
# Game loop
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
for event in py.event.get():
# check for closing window
if event.type == py.QUIT:
running = False
elif event.type == py.KEYDOWN:
if event.key == py.K_SPACE:
New_bullet = player.Shoot()
all_sprites.add(New_bullet)
bullets.add(New_bullet)
# Update
all_sprites.update()
# # check if there a collision between the bullet and NPC
hits = py.sprite.groupcollide(NPCs, bullets, True, True)
# check if there a collision between the player and NPC
hits = py.sprite.spritecollide(player, NPCs, True)
if hits:
running = False
# updates the position of of mouse and rotates it towards the mouse position
mouse_x, mouse_y = py.mouse.get_pos()
player.rotate(mouse_x, mouse_y)
# render
screen.fill(BLACK)
all_sprites.draw(screen)
# flip the display
py.display.flip()
py.quit()
PlayerSprite
import pygame as py
import math
import random
WIDTH = 800
HEIGHT = 600
FPS = 60
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
class Player(py.sprite.Sprite):
def __init__(self):
py.sprite.Sprite.__init__(self)
self.image = py.Surface((40, 40), py.SRCALPHA)
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT / 2
self.Yspeed = 0
self.rotatableimage = self.image
def update(self):
self.Xspeed = 0
self.Yspeed = 0
# line below allow for key press to equate to move of sprite
keypreesed = py.key.get_pressed()
if keypreesed[py.K_a]:
self.Xspeed = - 11
if keypreesed[py.K_d]:
self.Xspeed = 11
if keypreesed[py.K_w]:
self.Yspeed = - 11
if keypreesed[py.K_s]:
self.Yspeed = 11
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# line below allow the sprite to wrap around the screen
if self.rect.left > WIDTH:
self.rect.right = 0
if self.rect.right < 0:
self.rect.left = WIDTH
if self.rect.top > HEIGHT:
self.rect.top = 0
if self.rect.bottom < 0:
self.rect.bottom = HEIGHT
def rotate(self, mouse_x, mouse_y):
rel_x = mouse_x - self.rect.x
rel_y = mouse_y - self.rect.y
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
self.image = py.transform.rotate(self.rotatableimage, int(angle))
self.rect = self.image.get_rect(center=(self.rect.centerx, self.rect.centery))
return
def Shoot(self):
return Bullet(self.rect.centerx, self.rect.top)
class NPC(py.sprite.Sprite):
def __init__(self, player):
py.sprite.Sprite.__init__(self)
self.player = player
self.image = py.Surface((30, 30)).convert_alpha()
self.image.fill(RED)
self.originalimage = self.image
self.rect = self.image.get_rect()
self.spawn()
# allows of spawning from all four side of the screen and set the x, y speed and spawn position
def spawn(self):
self.direction = random.randrange(4)
if self.direction == 0:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.Xspeed = random.randrange(-2, 2)
self.Yspeed = random.randrange(4, 8)
elif self.direction == 1:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(HEIGHT, HEIGHT + 60)
self.Xspeed = random.randrange(-2, 2)
self.Yspeed = -random.randrange(4, 8)
elif self.direction == 2:
self.rect.x = random.randrange(-100, -40)
self.rect.y = random.randrange(HEIGHT - self.rect.height)
self.Xspeed = random.randrange(4, 8)
self.Yspeed = random.randrange(-2, 2)
elif self.direction == 3:
self.rect.x = random.randrange(WIDTH, WIDTH + 60)
self.rect.y = random.randrange(HEIGHT - self.rect.height)
self.Xspeed = -random.randrange(4, 8)
self.Yspeed = random.randrange(-2, 2)
def update(self):
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# makes it so that NPC point to wards the player as it passes from side to side
dir_x, dir_y = self.player.rect.x - self.rect.x, self.player.rect.y - self.rect.y
self.rot = (180 / math.pi) * math.atan2(-dir_x, -dir_y)
self.image = py.transform.rotate(self.originalimage, self.rot)
# Respawns the NPC when they hit an side
if self.direction == 0:
if self.rect.top > HEIGHT + 10:
self.spawn()
elif self.direction == 1:
if self.rect.bottom < -10:
self.spawn()
elif self.direction == 2:
if self.rect.left > WIDTH + 10:
self.spawn()
elif self.direction == 3:
if self.rect.right < -10:
self.spawn()
class Bullet(py.sprite.Sprite):
def __init__(self, x, y):
py.sprite.Sprite.__init__(self)
self.image = py.Surface((5, 5))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.Yspeed = -10
def update(self):
self.rect.y += self.Yspeed
# kill if moved of screen
if self.rect.bottom > HEIGHT or self.rect.top < 0:
self.kill()
if self.rect.right > WIDTH or self.rect.left < 0:
self.kill()
Add 2 attributes self.lastX and self.lastY to the class Player and change the attributes when the player changes the direction:
class Player(py.sprite.Sprite):
def __init__(self):
# [...]
self.lastX = 0
self.lastY = -10
def update(self):
# [...]
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
if self.Xspeed != 0 or self.Yspeed != 0:
self.lastX = self.Xspeed
self.lastY = self.Yspeed
Add an argument Xspeed ans Yspeed to the class Bullet
class Bullet(py.sprite.Sprite):
def __init__(self, x, y, Xspeed, Yspeed):
py.sprite.Sprite.__init__(self)
self.image = py.Surface((5, 5))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.Xspeed = Xspeed
self.Yspeed = Yspeed
def update(self):
self.rect.x += self.Xspeed
self.rect.y += self.Yspeed
# [...]
Set the attributes when the bullet spawns
class Player(py.sprite.Sprite):
# [...]
def Shoot(self):
return Bullet(self.rect.centerx, self.rect.centery, self.lastX, self.lastY)
Alternatively it is also possible to set the speed dependent on the direction to the mouse cursor.
Get the position of the player and the mouse cursor and compute the x and y distance (Vector ):
pos = self.rect.center
mpos = py.mouse.get_pos()
vx = mpos[0] - pos[0]
vy = mpos[1] - pos[1]
If the mouse position and the bullet position are equal, that does not make any sense, thus the bullet is skipped
if vx == 0 and vy == 0:
return None
Of course this vector is far to long, if you would use it for the direction (Xspeed, Yspeed) directly, then the bullet would step to the mouse cursor in one turn.
In the following I use pygame.math.Vector2, because it provides the handy method scale_to_length, that scales a vector to a specified Euclidean length:
direction = py.math.Vector2(vx, vy)
direction.scale_to_length(10)
Now the x and y component of the vector contain the x and y component of the speed. Since the components are floating point values, they are round to integral values:
return Bullet(pos[0], pos[1], round(direction.x), round(direction.y))
Method Shoot:
class Player(py.sprite.Sprite):
# [...]
def Shoot(self):
pos = self.rect.center
mpos = py.mouse.get_pos()
vx, vy = mpos[0] - pos[0], mpos[1] - pos[1]
if vx == 0 and vy == 0:
return None
direction = py.math.Vector2(vx, vy)
direction.scale_to_length(10)
return Bullet(pos[0], pos[1], round(direction.x), round(direction.y))
Note, if you set the bullet dependent on the direction to the mouse cursor, then it may be useful to spawn the bullet by a mouse click:
while running:
# [...]
for event in py.event.get():
if event.type == py.QUIT:
# [...]
elif event.type == py.MOUSEBUTTONDOWN:
if event.button == 1:
New_bullet = player.Shoot()
if New_bullet:
all_sprites.add(New_bullet)
bullets.add(New_bullet)
You can use pygames Vector2 to move in any direction. You calculate the angle of the player you can use that.
class Player(py.sprite.Sprite):
def __init__(self):
...
self.angle = 0
def rotate(self, mouse_x, mouse_y):
...
self.angle = -angle #make negative otherwise it will be going away from mouse
def Shoot(self):
return Bullet(self.rect.centerx, self.rect.top, py.math.Vector2(1,0).rotate(self.angle))
then in your bullet class, get the direction and add to its position
class Bullet(py.sprite.Sprite):
def __init__(self, x, y, Dir):
...
self.Dir = Dir
def update(self):
self.rect.y += self.Dir[1] * self.speed
self.rect.x += self.Dir[0] * self.speed
...

Can I get the rect.x from one class to use in another class?

So basically I want to my Road class to always know where my Car (Player1) class is so road knows whether to slow down as Car has left road (or be able to speed back up when Car gets back within road area.
As Car only moves left / right and it is the road that speeds up coming down screen, I figured a way to mimic the car using a "self.where_player" at same start position and then add / subtract x position and follow it with key's pressed (a, d), but after awhile it can lose Car placement as Car can either have x values added or subtracted while slipping left or right on ice or have it keys (a, d) temporarily disabled if spinning on oil, while the road does not know these things...
If I could figure out how the Road class could "always" know where the Car class rect.x was, well that would be fantastic!
import pygame
W = 1000
H = 800
pygame.init()
pygame.display.set_mode((W, H))
class Road1(pygame.sprite.Sprite):
def __init__(self, top, player):
pygame.sprite.Sprite.__init__(self)
bkgrnd = pygame.image.load("Images/Road.png").convert_alpha()
self.image = pygame.transform.scale(bkgrnd, (300, 100))
self.rect = self.image.get_rect(topleft = (120, top))
self.top = top
self.speedy = 0
self.player = player
self.out_of_bounds = False
def update(self):
self.top += self.speedy
if self.top >= 800:
self.top = self.top - 900
self.rect.top = self.top
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.speedy = min(20, self.speedy + 0.25)
if keys[pygame.K_s]:
self.speedy = max(0, self.speedy - 0.25)
if keys[pygame.K_a]:
self.player -= 5
if self.player <= 120:
self.player = 120
self.out_of_bounds = True
if self.out_of_bounds and self.speedy > 5:
self.speedy -= 0.35
else:
self.out_of_bounds = False
if keys[pygame.K_d]:
self.player += 5
if self.player >= 420:
self.player = 420
self.out_of_bounds = True
if self.out_of_bounds and self.speedy > 5:
self.speedy -= 0.35
else:
self.out_of_bounds = False
The following is a portion from the Main page enough to make Road work:
import pygame
import random
import sys
# from Ice_Patch import Ice1, Ice2
# from Oil_Slick import Oil1, Oil2
from Player1 import Player1, car1_image
# from Player2 import Player2, car2_image
from Roads import Road1, # Road2
W, H = 1000, 800
HW, HH = W / 2, H / 2
AREA = W * H
FPS = 30
GREEN = (0, 200, 0)
pygame.init()
CLOCK = pygame.time.Clock()
DS = pygame.display.set_mode((W, H))
pygame.display.set_caption("Racing Fury")
def events():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
player = Player1()
all_sprites = pygame.sprite.Group()
road = pygame.sprite.Group()
for i in range(9):
rd = Road1((i - 1) * 100, player)
all_sprites.add(rd)
road.add(rd)
while True:
CLOCK.tick(FPS)
events()
all_sprites.update()
DS.fill(GREEN)
all_sprites.draw(DS)
pygame.display.flip()
Player1 Class:
import pygame
W = 1000
H = 800
pygame.init()
pygame.display.set_mode((W, H))
car1_image = pygame.image.load("Images/GalardB.png").convert_alpha()
car1_image = pygame.transform.scale(car1_image, (40, 70))
GREY = (211, 211, 211)
ANIM_DELAY = 50
POWERUP_TIME = 5000
SPIN_TIME = 1950
class Player1(pygame.sprite.Sprite):
def __init__(self, car1_image, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = car1_image
self.image.set_colorkey(GREY)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.radius = 25
self.speedx = 0
self.rotations = [self.image]
self.spinning_since = 0
self.rotate()
self.damage = 100
self.shoot_delay = 250
self.last_shot = pygame.time.get_ticks()
self.lives = 3
self.hidden = False
self.hide_timer = pygame.time.get_ticks()
self.score = 0
self.crashx = 0
self.crashy = 0
self.power = 0
self.power_time = pygame.time.get_ticks()
self.not_spinning = True
def update(self):
if self.power >= 1 and pygame.time.get_ticks() - self.power_time > POWERUP_TIME:
self.power -= 1
self.power_time = pygame.time.get_ticks()
if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1500:
self.hidden = False
self.rect.center = (300, 700)
self.speedx = 0
keystate1 = pygame.key.get_pressed()
if keystate1[pygame.K_SPACE]:
self.shoot()
if self.not_spinning:
if keystate1[pygame.K_a]:
self.speedx = -5
if keystate1[pygame.K_d]:
self.speedx = 5
self.rect.x += self.speedx
if self.rect.right > 420:
self.rect.right = 420
if self.rect.left < 120:
self.rect.left = 120
if self.spinning_since > 0:
time_spinning = pygame.time.get_ticks() - self.spinning_since
if time_spinning >= SPIN_TIME:
self.spinning_since = 0
index = 0
self.not_spinning = True
else:
index = int(time_spinning / ANIM_DELAY)
index %= len(self.rotations)
self.not_spinning = False
cx, cy = self.rect.center
self.image = self.rotations[index]
self.rect = self.image.get_rect()
self.rect.centerx = cx
self.rect.centery = cy
def powerup(self):
self.power += 1
self.power_time = pygame.time.get_ticks()
def shoot(self):
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
if self.power == 0:
pass
if self.power >= 1:
bullet1 = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet1)
bullets1.add(bullet1)
def rotate(self):
ROT_FRAMES = 36
for i in range(ROT_FRAMES):
angle = i * (720 / ROT_FRAMES)
rotated_image = pygame.transform.rotozoom(self.image, angle, 1)
self.rotations.append(rotated_image)
def spin(self):
if self.spinning_since == 0:
self.spinning_since = pygame.time.get_ticks()
else:
pass
def slide(self):
keystate1 = pygame.key.get_pressed()
if keystate1[pygame.K_a]:
self.rect.x -= 2
self.rect.x -= 1.5
self.rect.x -= 1
self.rect.x -= 0.5
self.rect.x -= 0.25
if keystate1[pygame.K_d]:
self.rect.x += 2
self.rect.x += 1.5
self.rect.x += 1
self.rect.x += 0.5
self.rect.x += 0.25
def hide(self):
self.crashx = self.rect.x
self.crashy = self.rect.y
self.hidden = True
self.hide_timer = pygame.time.get_ticks()
self.rect.center = (W * 2, H * 2)
The easiest solution is to make the "road" knowing the player. Add an attribute player the class Road1:
class Road1(pygame.sprite.Sprite):
def __init__(self, top, player):
pygame.sprite.Sprite.__init__(self)
self.player = player
# [...]
Instead of self.where_player you can directly ask self.player for its position.
Pass the player to the road objects when they are constructed. e.g.:
player = Player1(?????)
all_sprites = pygame.sprite.Group()
road = pygame.sprite.Group()
for i in range(9):
rd = Road1((i - 1) * 100, player)
all_sprites.add(rd)
road.add(rd)
An other option would be to add an argument player to the method update:
class Road1(pygame.sprite.Sprite):
# [...]
def update(self, player):
# [...]
Of course you have to separate the update of road and player. e.g.:
player.update()
road.update(player)

what does "s for s in sprite_list if s.rect.collidepoint(pos)" meaning?

I was reading code about pygame.Down is the part of a little game of pygame.I cannot understand "clicked_smileys = [s for s in sprite_list if s.rect.collidepoint(pos)]" the code.It'sin the last eighth lines.Who can understand?
I thinked that it has error just now,but IDE can run it.It is the code of python3.
count_smileys = 0
count_popped = 0
class Smiley(pygame.sprite.Sprite):
pos =(0,0)
xvel = 1
yvel = 1
scale = 100
def __init__(self, pos, xvel, yvel):
pygame.sprite.Sprite.__init__(self)
self.image = pic
self.scale = random.randrange(10,100)
self.image = pygame.transform.scale(self.image, (self.scale,self.scale))
self.rect = self.image.get_rect()
self.pos = pos
self.rect.x = pos[0] - self.scale/2
self.rect.y = pos[1] - self.scale/2
self.xvel = xvel
self.yvel = yvel
def update(self):
self.rect.x += self.xvel
self.rect.y += self.yvel
if self.rect.x <= 0 or self.rect.x > screen.get_width()- self.scale:
self.xvel = -self.xvel
if self.rect.y <= 0 or self.rect.y > screen.get_height()- self.scale:
self.yvel = -self.yvel
while keep_going:
for event in pygame.event.get():
if event.type == pygame.QUIT:
keep_going = False
if event.type == pygame.MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed()[0]:  # Left mouse button, draw
mousedown = True
elif pygame.mouse.get_pressed()[2]: # Right mouse button, pop
pos = pygame.mouse.get_pos()
clicked_smileys = [s for s in sprite_list if s.rect.collidepoint(pos)]
sprite_list.remove(clicked_smileys)
if len(clicked_smileys)> 0:
pop.play()
count_popped += len(clicked_smileys)
if event.type == pygame.MOUSEBUTTONUP:
mousedown = False
screen.fill(BLACK)
clicked_smileys = [s for s in sprite_list if s.rect.collidepoint(pos)] is the list comprehension form of
clicked_smileys = []
for s in sprite_list:
if s.rect.collidepoint(pos):
clicked_smileys.append(s)

Categories

Resources