from numpy import place
import pygame, sys ,random as ran
start = True
class Player(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.attack_animation = False
self.sprites_1 = []
self.sprites_1.append(pygame.image.load('crossHair.png'))
self.sprites_1.append(pygame.image.load('crossHair_2.png'))
self.sprites_1.append(pygame.image.load('crossHair_3.png'))
self.sprites_1.append(pygame.image.load('crossHair_4.png'))
self.sprites_1.append(pygame.image.load('crossHair_5.png'))
self.sprites_1.append(pygame.image.load('FIRE.png'))
self.current_sprite = 0
self.image = self.sprites_1[self.current_sprite]
self.image.set_colorkey('white')
for items in self.sprites_1:
items.set_colorkey('white')
self.rect = self.image.get_rect()
self.rect.topleft = [pos_x,pos_y]
def attack(self):
self.attack_animation = True
self.image.set_colorkey('white')
def update(self,speed):
self.image.set_colorkey('white')
if self.attack_animation == True:
self.current_sprite += speed
if int(self.current_sprite) >= len(self.sprites_1):
self.current_sprite = 0
self.attack_animation = False
print('shot')
self.image = self.sprites_1[int(self.current_sprite)]
# self.image = self.sprites_1[int(self.current_sprite)]
mouse = pygame.mouse.get_pos()
self.rect = mouse
class enemy(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.image = pygame.image.load('sp_1.png')
self.rect = self.image.get_rect()
self.rect.center = [pos_x, pos_y]
self.image.set_colorkey((255,255,255))
# General setup
pygame.init()
pygame.mouse.set_visible(0)
clock = pygame.time.Clock()
# Game Screen
screen_width = 400
screen_height = 400
mouse = pygame.mouse.get_pos()
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("Sprite Animation")
# Creating the sprites and groups
moving_sprites = pygame.sprite.Group()
crosshair = Player(mouse[0],mouse[1])
enemy_x = ran.randint(18,387)
enemy_y = ran.randint(18,387)
print(enemy_x,enemy_y)
enemy_ = enemy(enemy_x,enemy_y)
moving_sprites.add(enemy_,crosshair)
while True:
# Player.set_pos(*pygame.mouse.get_pos())
globals()['mouse'] = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed()[0]:
crosshair.attack()
enemy.checkCollision(enemy,crosshair,enemy_)
# enemy.attack()
# pygame.sprite.spritecollide(Player,enemy,True)
screen.fill((120,220,150))
#this is causing the problem
get_hit = pygame.sprite.spritecollide(Player,enemy,True)
# Drawing
screen.set_colorkey('white')
moving_sprites.draw(screen)
moving_sprites.update(0.08)
pygame.display.flip()
clock.tick(120)
the movement i check for sprite collision it gives me error sayin' :
File "c:\Users\pc\VS_PYTHON_PY\pyGame.py", line 82, in
get_hit = pygame.sprite.spritecollide(Player,enemy,True)
File "C:\python-py\lib\site-packages\pygame\sprite.py", line 1682, in spritecollide
default_sprite_collide_func = sprite.rect.colliderect
AttributeError: type object 'Player' has no attribute 'rect'
why is that happening can you solve this pls
The arguments of pygame.sprite.spritecollide must be instance objects of Sprite and Group classes. Player and enemy are a classes, however crosshair and enemy_ are objects. Create a Group for the enemies and detect the collisions between the crosshair and the Group of enemies:
crosshair = Player(mouse[0],mouse[1])
enemyGroup = pygame.sprite.Group()
enemy_ = enemy(enemy_x,enemy_y)
enemyGroup.add(enemy_)
while True:
# [...]
get_hit = pygame.sprite.spritecollide(crosshair, enemyGroup, True)
See also How do you program collision in classes? and How do I detect collision in pygame?.
Also see Style Guide for Python Code: Class names should normally use the CapWords convention. The name of the class should be Enemy instead of enemy.
Related
import pygame, sys
start = True
class Player(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.attack_animation = False
self.sprites = []
self.sprites.append(pygame.image.load('crossHair.png'))
self.sprites.append(pygame.image.load('crossHair_2.png'))
self.sprites.append(pygame.image.load('crossHair_3.png'))
self.sprites.append(pygame.image.load('crossHair_4.png'))
self.current_sprite = 0
self.image = self.sprites[self.current_sprite]
self.image.set_colorkey('white')
for items in self.sprites:
items.set_colorkey('white')
self.rect = self.image.get_rect()
self.rect.topleft = [pos_x,pos_y]
def attack(self):
self.attack_animation = True
self.image.set_colorkey('white')
def update(self,speed):
self.image.set_colorkey('white')
self.current_sprite += speed
if int(self.current_sprite) >= len(self.sprites):
self.attack_animation = False
self.current_sprite = 0
self.image = self.sprites[int(self.current_sprite)]
# General setup
pygame.init()
clock = pygame.time.Clock()
# Game Screen
screen_width = 400
screen_height = 400
mouse = pygame.mouse.get_pos()
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("Sprite Animation")
# Creating the sprites and groups
moving_sprites = pygame.sprite.Group()
while True:
globals()['mouse'] = pygame.mo[![now this is the problem][1]][1]use.get_pos()
player = Player(mouse[0],mouse[1])
moving_sprites.add(player)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
player.attack()
# Drawing
screen.fill((0,0,0))
screen.set_colorkey('white')
moving_sprites.draw(screen)
moving_sprites.update(0.04)
pygame.display.flip()
clock.tick(120)
this is creatiing my player / crossHair every 120th of a second and it leaves behind it's last sprite
now the problem with that is it leaves behind my last sprite and if i put
moving_sprites = pygame.sprite.Group()
in while loop then it won't animate anybody can solve this pls answer my question...
This is not the way to animate sprites. Creating a new sprite every frame is bad practice and a waste of performance since all objects have to be recreated. Even more you load the images in the constructor of the Player class. If you do this every frame, then every frame the images have to be loaded from the volume and decoded.
Create the sprite once before the application loop and change the attributes of the sprite object in the loop. This will give you the best performance:
class Player(pygame.sprite.Sprite):
# [...]
def set_pos(self, pos_x, pos_y):
self.rect.topleft = (pos_x, pos_y)
moving_sprites = pygame.sprite.Group()
player = Player(0, 0)
moving_sprites.add(player)
while True:
player.set_pos(*pygame.mouse.get_pos())
# [...]
First excuse-mo for my english, I'm French. I have alittle problem : I am maiding a 2d rpg in pygame and I made my map with many little image of grass, tree... But when I put the real size of textures on the screen my hero sprite have a jerky walk so I try to reduce de size of the bloc :my sprite walk normaly but the texture were very ugly so I'll ask you this question : do you know how solve it ? My main code :
import pygame
from game import Game
from level import Level
pygame.init()
lvl = Level()
screen = pygame.display.set_mode((1080, 720))
pygame.display.set_caption("RPG")
game = Game()
running = True
lvl.generer()
print(game.player.rect)
while running:
lvl.afficher(screen, 0, 0)
if game.pressed.get(pygame.K_RIGHT) and game.player.rect.x + game.player.rect.width < 1080:
game.player.move_right()
#print(game.player.rect.x)
elif game.pressed.get(pygame.K_LEFT) and game.player.rect.x > 0:
game.player.move_left()
#print(game.player.rect.x)
elif game.pressed.get(pygame.K_DOWN):
game.player.move_down()
#screen.scroll(0, -game.player.velocity)
#print(game.player.rect.y)
elif game.pressed.get(pygame.K_UP):
game.player.move_up()
#screen.scroll(0, game.player.velocity)
#print(game.player.rect.y)
screen.blit(game.player.image, game.player.rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
elif event.type == pygame.KEYDOWN:
game.pressed[event.key] = True
elif event.type == pygame.KEYUP:
game.pressed[event.key] = False
And my player class (who inherited of game class but I d'ont put my game class on this post)
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, game):
super(Player, self).__init__()
self.game = game
self.health = 100
self.maxHealth = 100
self.attack = 10
self.velocity = 100
self.image = pygame.image.load("assets/player/player_face/player_face.png")
self.original_image = pygame.image.load("assets/player/player_face/player_face.png")
self.image = pygame.transform.scale(self.image, (300, 300))
self.rect = self.image.get_rect()
self.rect.x = 400
self.rect.y = 500
def move_right(self):
self.rect.x += self.velocity
self.image = pygame.image.load("assets/player/player_profileLeft/player_profile_left.png")
self.image = pygame.transform.scale(self.image, (300, 300))
def move_left(self):
self.rect.x -= self.velocity
self.image = pygame.image.load("assets/player/player_profileRight/player_profile_right.png")
self.image = pygame.transform.scale(self.image, (300, 300))
def move_down(self):
self.rect.y += self.velocity
self.image = pygame.image.load("assets/player/player_face/player_face.png")
self.image = pygame.transform.scale(self.image, (300, 300))
def move_up(self):
self.rect.y -= self.velocity
self.image = pygame.image.load("assets/player/player_back/player_dos.png")
self.image = pygame.transform.scale(self.image, (300, 300))
and my game class:
# -*- coding: utf-8 -*-
import pygame
from player import Player
class Game:
def __init__(self):
self.all_players = pygame.sprite.Group()
self.player = Player(self)
self.all_players.add(self.player)
self.pressed = {}
def check_collision(self, sprite, group):
return pygame.sprite.spritecollide(sprite, group, False, pygame.sprite.collide_mask)
If I see correctly, you aren't using [var] = pygame.time.Clock() and [var].tick([some number]), which limits the FPS. I think your issue is that the FPS is fluctuating and causing lag.
I'm trying to make a basic shooting game with sprites. I get an error on the line alien.rect.x in my for loop when I try to run. It says that my object Alien has no rect attribute. I thought self.rect = self.image.get_rect () in my Alien class takes care of that? What am I doing wrong? Do I need Sprite lists for this?
#Created by Mark Schaeffler 4/17/18
import pygame
import random
import sys
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
WINDOWWIDTH = 600
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 0)
FPS = 40
PLAYERMOVERATE = 5
# set up pygame, the window, and the mouse cursor
pygame.init()
clock = pygame.time.Clock()
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Alien Invasion')
pygame.mouse.set_visible(False)
# set up fonts
font = pygame.font.Font(None, 48)
# set up sounds
game_over_sound = pygame.mixer.Sound("gameover.wav")
background_music = pygame.mixer.Sound("Background_Music.ogg")
click_sound = pygame.mixer.Sound("laser5.ogg")
#Terminate
def terminate():
pygame.quit()
sys.exit()
#Class for player
class Player(pygame.sprite.Sprite):
def __init__(self):
# Call the parent class (Sprite) constructor
super().__init__()
#Load player image
self.image = pygame.image.load("Player1.png").convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
# Update the player's position
# Get the current mouse position.
pos = pygame.mouse.get_pos()
# Set the player x, y position
self.rect.x = pos[0]
self.rect.y = pos[0]
#Class for bullets
class Bullet(pygame.sprite.Sprite):
def __init__(self):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([4, 10])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
def update(self):
# Move the bullet
self.rect.y -= 3
#Class for aliens
class Aliens(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("Aliensprite1")
self.rect = self.image.get_rect()
def reset_pos(self):
self.rect.y = random.randrange(-300, -20)
self.rect.x = random.randrange(0, WINDOWWIDTH)
def update(self):
# Move alien down one pixel
self.rect.y += 1
# If alien is too far down, reset to top of screen.
if self.rect.y > 610:
self.reset_pos()
def waitForPlayerToPressKey():
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # pressing escape
quits
terminate()
return
# List of every sprite. All aliens, bullets, player
all_sprites_list = pygame.sprite.Group()
# List of each alien in the game
alien_list = pygame.sprite.Group()
# List of each bullet
bullet_list = pygame.sprite.Group()
for i in range(50):
# This represents an alien
alien = Aliens
# Set random location for the aliens
alien.rect.x = random.randrange(WINDOWWIDTH)
# Add aliens to the list of objects
alien_list.add(alien)
all_sprites_list.add(alien)
def drawText(text, font, surface, x, y):
textobj = font.render(text, 1, TEXTCOLOR)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
# "Start" screen
drawText('Alien Invasion', font, windowSurface, (WINDOWWIDTH / 3),
(WINDOWHEIGHT / 3))
drawText('Press any key to start.', font, windowSurface, (WINDOWWIDTH
/ 3) - 30, (WINDOWHEIGHT / 3) + 50)
pygame.display.update()
waitForPlayerToPressKey()
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
score = 0
topScore = 0
player.rect.y = 370
background_music.play()
# -------- Main Program Loop -----------
You need to create an instance of the Aliens class, you are missing the brackets:
alien = Aliens()
This invokes the class constructor and creates a new object of Aliens.
Replace alien = Aliens with alien = Aliens() :)
I've tried numerous things to let my bullets collide with my mob, but it doesn't work. The bullet just goes straight through the mob. I also tried spritecollide and groupcollide codes, but they all failed. Maybe i'm putting my code in the wrong line or the wrong place. I also want the bullet and mob to be removed from the list.
import pygame
import random
import math
GRAD = math.pi / 180
black = (0,0,0)
Bulleti = pygame.image.load('bullet.png')
Monster = pygame.image.load('Monster1re.png')
class Config(object):
fullscreen = True
width = 1366
height = 768
fps = 60
class Player(pygame.sprite.Sprite):
maxrotate = 180
down = (pygame.K_DOWN)
up = (pygame.K_UP)
def __init__(self, startpos=(102,579), angle=0):
super().__init__()
self.pos = list(startpos)
self.image = pygame.image.load('BigShagHoofdzzz.gif')
self.orig_image = self.image
self.rect = self.image.get_rect(center=startpos)
self.angle = angle
def update(self, seconds):
pressedkeys = pygame.key.get_pressed()
if pressedkeys[self.down]:
self.angle -= 2
self.rotate_image()
if pressedkeys[self.up]:
self.angle += 2
self.rotate_image()
def rotate_image(self):
self.image = pygame.transform.rotate(self.orig_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
class Mob(pygame.sprite.Sprite):
def __init__(self, image):
super().__init__()
self.image = image
self.rect = self.image.get_rect()
self.rect.x = 1400
self.rect.y = random.randrange(500,600)
self.speedy = random.randrange(-8, -1)
def update(self):
self.rect.x += self.speedy
if self.rect.x < -100 :
self.rect.x = 1400
self.speedy = random.randrange(-8, -1)
class Bullet(pygame.sprite.Sprite):
"""This class represents the bullet."""
def __init__(self, pos, angle, image):
super().__init__()
self.image = image
self.image = pygame.transform.rotate(self.image, angle)
self.rect = self.image.get_rect()
speed = 15
self.velocity_x = math.cos(math.radians(-angle)) * speed
self.velocity_y = math.sin(math.radians(-angle)) * speed
self.pos = list(pos)
def update(self):
""" Move the bullet. """
self.pos[0] += self.velocity_x
self.pos[1] += self.velocity_y
self.rect.center = self.pos
player = Player()
#this is the mob group
mobs = []
for x in range(0,10):
mob = Mob(Monster)
mobs.append(mob)
print(mobs)
#sprite lists
bullet_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
allgroup = pygame.sprite.LayeredUpdates()
allgroup.add(player)
for mob in mobs:
all_sprites_list.add(mob)
def main():
#game
pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.mixer.init()
pygame.init()
screen=pygame.display.set_mode((Config.width, Config.height),
pygame.FULLSCREEN)
background = pygame.image.load('BGGameBig.png')
sound = pygame.mixer.Sound("shoot2.wav")
clock = pygame.time.Clock()
FPS = Config.fps
mainloop = True
while mainloop:
millisecond = clock.tick(Config.fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False
if event.key == pygame.K_SPACE: #Bullet schiet knop op space
# Pass the position and angle of the player.
bullet = Bullet(player.rect.center, player.angle,
Bulleti)
all_sprites_list.add(bullet)
bullet_list.add(bullet)
sound.play()
if event.key == pygame.K_ESCAPE:
mailoop = False
pygame.display.set_caption("hi")
allgroup.update(millisecond)
all_sprites_list.update()
for bullet in bullet_list:
if bullet.rect.x > 1380:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
#this is the code for collission
hits = pygame.sprite.groupcollide(bullet_list, mobs, True, True)
screen.blit(background, (0,0))
allgroup.draw(screen)
all_sprites_list.draw(screen)
pygame.display.flip()
if __name__ == '__main__':
main()
pygame.quit()
if anyone could help me out on this one it would really be appreciated. I spent alot of time working on the solution but I haven't found any yet. Watched alot of youtubers and did the same thing but it just won't work.
I get a different error when I run the program, an AttributeError caused by this line hits = pygame.sprite.groupcollide(bullet_list, mobs, True, True). That happens because the mobs list should be a pygame.sprite.Group.
mobs = pygame.sprite.Group()
for x in range(0,10):
mob = Mob(Monster)
mobs.add(mob)
After I changed this part of the code, it worked correctly.
I am trying to display a group of Sprite to the screen, however, my code below displays a blank screen. I've been at this for a while and i dont know why this doesnt work at the logic seems correct. the main problem occurs in the sprite method where i am trying to add the sprites at a random position. The sprites are then drawn in the gameLoop method.
Any suggestions?
import pygame, sys, random
pygame.init()
troll = pygame.image.load("image.png")
black = (0, 0, 0)
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 400
sprite_width = 5
sprite_height = 5
spriteCount = 5
class Sprite(pygame.sprite.Sprite):
pygame.init()
sprite = pygame.sprite.Group()
clock = pygame.time.Clock()
def __init__(self):
pygame.sprite.Sprite.__init__(self)
def __init__(self, Image, pos):
pygame.sprite.Sprite.__init__(self)
self.image =pygame.Surface([0, 0])
self.rect = self.image.get_rect()
self.rect.topleft = pos
#classmethod
def sprite(self):
for i in range(spriteCount):
tmp_x = random.randrange(0, SCREEN_WIDTH)
tmp_y = random.randrange(0, SCREEN_HEIGHT)
# all you have to do is add new sprites to the sprite group
self.sprite.add(Sprite(troll, [tmp_x, tmp_y]))
def update(self):
self.rect.x += 1
self.rect.y += 2
if self.rect.y > SCREEN_HEIGHT:
self.rect.y = -1 * sprite_height
if self.rect.x > SCREEN_WIDTH:
self.rect.x = -1 * sprite_width
#classmethod
def setImage(self,Image):
self.image=pygame.image.load(Image)
#classmethod
def gameLoop(self):
screen = pygame.display.set_mode([640, 400])
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(black)
# to update or blitting just call the groups update or draw
# notice there is no for loop
# this will automatically call the individual sprites update method
self.actor.update()
self.actor.draw(screen)
pygame.display.update()
self.clock.tick(20)
Sprite.sprite()
Sprite.setImage("image.png")
Sprite.gameLoop()
#classmethod
def setImage(self,Image):
self.image=pygame.image.load(Image)
Here, you should name the first parameter cls, not self, since it's a class method, not an instance method. Also, parameter-names should be lowercase (image instead of Image).
#classmethod
def gameLoop(self):
screen = pygame.display.set_mode([640, 400])
while True:
...
Same here. Also, I don't know why your gameloop is part of your Sprite class. Also, you should not name your class Sprite in the first place, as it will just create confusion with pygame's Sprite class.
class Sprite(pygame.sprite.Sprite):
...
sprite = pygame.sprite.Group()
...
#classmethod
def sprite(self):
...
Here you have a field called sprite and a class level function sprite. This will not work, as the method will overwrite the field. So whenever you want to access the field sprite, you will access the function sprite instead.
#classmethod
def gameLoop(self):
...
self.actor.update()
Sprite.actor does not exit. You never created such a field.
def __init__(self, Image, pos):
pygame.sprite.Sprite.__init__(self)
self.image =pygame.Surface([0, 0])
self.rect = self.image.get_rect()
self.rect.topleft = pos
Here, you pass an argument called Image. However, you don't use it but an empty Surface .
Here's a running version of your code:
import pygame, sys, random
pygame.init()
troll = pygame.image.load("image.png")
black = pygame.color.Color('black')
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 400
spriteCount = 5
class Sprite(pygame.sprite.Sprite):
actors = pygame.sprite.Group()
clock = pygame.time.Clock()
def __init__(self):
pygame.sprite.Sprite.__init__(self)
def __init__(self, image, pos):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.rect.topleft = pos
#classmethod
def init(self):
for i in range(spriteCount):
tmp_x = random.randrange(0, SCREEN_WIDTH)
tmp_y = random.randrange(0, SCREEN_HEIGHT)
self.actors.add(Sprite(troll, [tmp_x, tmp_y]))
def update(self):
self.rect.x += 1
self.rect.y += 2
if self.rect.y > SCREEN_HEIGHT:
self.rect.y = -1 * self.rect.height
if self.rect.x > SCREEN_WIDTH:
self.rect.x = -1 * self.rect.width
#classmethod
def gameLoop(self):
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(black)
self.actors.update()
self.actors.draw(screen)
pygame.display.update()
self.clock.tick(20)
Sprite.init()
Sprite.gameLoop()