How to prevent images overlapping each other in pygame? - python

When I run the code the target images overlap each other
so if we shoot the target images which are overlapped are also removed
this is a big issue in my game help me to solve this
Like this:
import pygame, sys
import os
import random
pygame.mixer.init()
pygame.init()
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load(os.path.join("files", 'crosshair.png'))
self.rect = self.image.get_rect()
self.shot_sound = pygame.mixer.Sound(os.path.join('files','shot.wav'))
def sound(self):
self.shot_sound.play()
pygame.sprite.spritecollide(crosshair,target_group, True)
def update(self):
self.rect.center = pygame.mouse.get_pos()
class Target(pygame.sprite.Sprite):
def __init__(self, target ,x,y):
super().__init__()
self.image = pygame.image.load(target)
self.rect = self.image.get_rect()
self.rect.center = [x,y]
# Screeen
width, height = 1000,700
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
bg = pygame.transform.scale2x(pygame.transform.scale2x(pygame.image.load(os.path.join('files','bg.png'))))
pygame.display.set_caption("Shotting Game")
pygame.mouse.set_visible(False)
# crosshair
crosshair = Crosshair()
crosshair_group = pygame.sprite.Group()
crosshair_group.add(crosshair)
# Target
target_group = pygame.sprite.Group()
for target in range(20):
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
target_group.add(draw_target)
# Main loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.sound()
screen.fill((255,255,255))
screen.blit(bg,(0,0))
target_group.draw(screen)
crosshair_group.draw(screen)
crosshair_group.update()
pygame.display.update()
clock.tick(50)

Use pygame.sprite.spritecollide to see if a new target intersects with another. Only add the target if it doesn't overlap:
target_group = pygame.sprite.Group()
while len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)
If you want to generate continuous targets, you can use the application loop:
# Target
target_group = pygame.sprite.Group()
# Main loop
while True:
if len(target_group) < 20:
draw_target = Target(os.path.join('files','target.png'),random.randint(0,width), random.randint(0,height))
if not pygame.sprite.spritecollide(draw_target, target_group, False):
target_group.add(draw_target)

Related

i want to change the location of my sprite when i click.... who to do that?

from numpy import place
import pygame, sys ,random as ran
start = True
ref_x = ran.randint(18,387)
ref_y = ran.randint(18,387)
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')
if mouse[0]+24 >= ref_x and ref_x+4 >= mouse[0] and mouse[1]+24 >= ref_y and ref_y+13 >= mouse[1]:
get_shot()
else :
print(ref_x,'here')
def update(self,speed):
self.image.set_colorkey('white')
mouse = pygame.mouse.get_pos()
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(mouse)
print('shot')
self.image = self.sprites_1[int(self.current_sprite)]
# self.image = self.sprites_1[int(self.current_sprite)]
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 = ref_x
enemy_y = ref_y
print(enemy_x,enemy_y)
enemy_ = enemy(enemy_x,enemy_y)
moving_sprites.add(enemy_,crosshair)
def get_shot():
moving_sprites.remove(enemy_)
moving_sprites.add(enemy_)
moving_sprites.remove(crosshair)
moving_sprites.add(crosshair)
pygame.display.flip()
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.06)
pygame.display.flip()
clock.tick(120)
on function get_shot i want to create my sp_1 at a new place i already tried to change the rect but it didn't work so what can I do to make it work and tell me it get_shot is the best method or not or do i have to create another sprite to make it work also i am a beggener to pygame so tr y to make it easy as possible ...
kill the enemy and spawn a new enemy in a new random position:
enemy_ = enemy(ref_x, ref_y)
moving_sprites.add(enemy_, crosshair)
def get_shot():
global enemy_, ref_x, ref_y
enemy_.kill()
ref_x = ran.randint(18,387)
ref_y = ran.randint(18,387)
enemy_ = enemy(ref_x, ref_y)
moving_sprites.add(enemy_)

how to animate the sprite?

from numpy import size
import pygame
import sys
# --- constants --- # PEP8: `UPPER_CASE_NAMES` for constants
WHITE = (255, 255, 255) # PE8: space after `,`
SIZE = (700, 500)
FPS = 120 # there is no need to use `500` because Python can't run so fast,
# and monitors runs with 60Hz (eventually 120Hz) which can display 60 FPS (120 FPS)
# --- classes --- # PEP8: `CamelCaseNames` for classes
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y, picture, colorkey):
super().__init__()
# you need one of them
# load image
self.image = pygame.image.load(picture)
# OR
# create surface
# self.image = pygame.Surface((10, 10))
# self.image.fill((255, 0, 0))
# ----
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.image.set_colorkey(colorkey)
def update(self):
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = pygame.mouse.get_pos()
print(mouse[:])
# --- main ---
pygame.init()
window_game = pygame.display.set_mode(SIZE)
backGround = pygame.image.load('bg.jpg').convert_alpha(window_game)
backGround = pygame.transform.smoothscale(backGround,SIZE)
backGround.set_colorkey(WHITE)
#placeSP_group = pygame.sprite.Group()
placeSP_group = pygame.sprite.OrderedUpdates() # Group which keep order
sprite1 = [MySprite(0, 0, 'crossHair.png', WHITE),MySprite(0, 0, 'crossHair_2.png', WHITE)]
placeSP_group.add([sprite1[0],sprite1[1]])
pygame.mouse.set_visible(False)
clock = pygame.time.Clock() # PEP8: `lower_case_names` for variables
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
#running = False
pygame.quit()
exit()
# create new Sprite
global x,y
x, y = pygame.mouse.get_pos()
new_sprite = sprite1[:]
# add new Sprite at the end of OrderedUpdates()
placeSP_group.add([new_sprite])
# remove Sprite at the beginning of OrderedUpdates()
placeSP_group.sprites()[0].kill()
placeSP_group.update()
# ---
pygame.display.flip()
window_game.fill('white')
window_game.blit(backGround,(0,0)).size
placeSP_group.draw(window_game)
clock.tick(FPS)
when i assignee new_sprite to all the assigned sprites in placeSP
it dosen't show any thing can you help me with that i am not sure why is that happening but can you fix it ... this an edited question. And i didn't got any answer .... but i have the concept in my head can and i also don't wan't to modify my code that much can you help me with that...
Create a sprite class with a list of images. Add an attribute that counts the frames. Get image from image list in the update method based on number of frames:
class MySprite(pygame.sprite.Sprite):
def __init__(self, x, y, image_list):
super().__init__()
self.frame = 0
self.image_list = image_list
self.image = self.image_list[0]
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def update(self, event_list):
animation_interval = 20
self.frame += 1
if self.frame // animation_interval >= len(self.image_list):
self.frame = 0
self.image = self.image_list[self.frame // animation_interval]
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = event.pos
print(mouse[:])
However, instead of constantly creating and killing the sprite every frame, you need to create the sprite once before the application loop. Change the position of the sprite and update the sprite in the application loop:
file_list = ['crossHair.png', 'crossHair_2.png', 'crossHair_3.png']
image_list = []
for name in file_list:
image = pygame.image.load(name)
image.set_colorkey(WHITE)
image_list.append(image)
# create sprite
sprite1 = MySprite(0, 0, image_list)
placeSP_group = pygame.sprite.OrderedUpdates()
placeSP_group.add([sprite1])
clock = pygame.time.Clock()
running = True
while running:
# handle events
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
running = False
# update sprite
x, y = pygame.mouse.get_pos()
placeSP_group.sprites()[0].rect.center = (x, y)
placeSP_group.update(event_list)
# draw scene
window_game.fill('white')
window_game.blit(backGround,(0,0)).size
placeSP_group.draw(window_game)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
exit()
See also:
how to create an illusion of animations in pygame
Animated sprite from few images
How do I create animated sprites using Sprite Sheets in Pygame?

Sprite has no attribute image

So I have a player class setup with pygame. Everytime I run my code however it gives me a "type object 'playnode' has no attribute 'image'" error. Any help would be great.
Player Class:
import pygame,random
class playnode(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = pygame.image.load("amogus png.png")
self.image = pygame.transform.smoothscale(self.image, (15,15))
self.rect = self.image.get_rect()
self.rect.center = pos
self.speed = pygame.math.Vector2(0, 5)
self.speed.rotate_ip(random.randint(0, 360))
self.time = 0
def update(self,x_speed,y_speed):
self.rect.move_ip(x_speed, y_speed)
Main:
import pygame
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
on = True
from Level import *
size = (width, height) = 850, 480
import Player
players = pygame.sprite.Group()
color = (54, 96, 230)
screen = pygame.display.set_mode(size, RESIZABLE)
p_v_x = 0
p_v_y = 0
posTuple = tuple((p_v_x, p_v_y))
enemyNum = 10
def innit():
players = pygame.sprite.Group
Enemies = pygame.sprite.Group
players.add(playnode)
def event_processor():
global on, success
for event in pygame.event.get():
if event.type == QUIT:
on = False
def main():
global on
innit()
while on == True:
clock.tick(60)
event_processor()
# screen.fill(color)
screen.blit(Player.playnode.image, Player.playnode.rect)
pygame.display.flip()
if __name__ == '__main__':
main()
Random crap so I can post this ajsodijaoikdjaoijdoisajoidjioajdoisajoidjaosijdiosjasidojoiasdjiodjpiodfjiopjsjfoij;aokjkofjdiaojfopiajiopafjiopajdoipfjdoiojpsjfpoiajfdopijaopidfjopidsajfiopj9uipwhfgioujnwiouonbhgoiunowjnvoiejqwownoivnwe
You are referencing the class variables of the player instead of the instance variables, so you first need to create a instance of the player before referencing it
example:
player = Player(...)
...
screen.blit(player .playnode.image, player .playnode.rect)

How can a object detect the mouse in pygame

import pygame
from pygame.constants import( QUIT, KEYDOWN, KEYUP, K_LEFT, K_RIGHT, K_ESCAPE, K_SPACE,
MOUSEBUTTONDOWN)
import os
from random import randint
class Settings:
w_width = 800
w_height = 600
w_border = 50
file_path = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(file_path, "pictures")
class Background(object):
def __init__(self, filename):
self.imageo = pygame.image.load(os.path.join(Settings.image_path, filename))
self.image = pygame.transform.scale(self.imageo, (Settings.w_width, Settings.w_height)).convert()
self.rect = self.image.get_rect()
def draw(self, screen):
screen.blit(self.image, self.rect)
I have here the bubbles class and i want to do it that when you click a bubble it despawns but i dont know how the bubbles detect the mouse cursor and how the bubbles despawn.
I already tried to add the mouse position function but I dont know hot to use it.
And I searched on the Internet but I found nothing about that.
class Bubble(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.width = 50
self.height = 300
self.image = pygame.image.load(os.path.join(Settings.image_path, "Blase.png ")).convert_alpha()
self.image = pygame.transform.scale(self.image, (25, 25))
self.rect_br = (Settings.w_width//2) + 100, (Settings.w_height//2) + 100
self.rect = self.image.get_rect()
self.mousex, self.mousey = pygame.mouse.get_pos()
self.cx = self.width - 25
self.cy = self.height - 25
self.rect.left = randint(Settings.w_border, Settings.w_width - Settings.w_border)
self.rect.top = randint(Settings.w_border, Settings.w_height - (Settings.w_border * 2))
def update(self):
pass
def scale_up(self):
self.scale["width"] += 2
self.scale["height"] += 2
def scale_down(self):
self.scale["width"] -= 2
self.scale["height"] -= 2
def events(self):
pass
def draw(self, screen):
screen.blit(self.image,self.rect )
Here is where everythings run from the code
class Game(object):
def __init__(self):
self.screen = pygame.display.set_mode((Settings.w_width, Settings.w_height))
self.clock = pygame.time.Clock()
self.runn = False
self.background = Background("Hintergrund.png")
self.bubble = pygame.sprite.Group()
def run(self):
self.runn = True
while self.runn:
self.clock.tick(60)
self.watch_for_events()
self.draw()
self.events()
def events(self):
if len(self.bubble)< 100:
self.bubble.add(Bubble())
time.sleep(0.2)
def draw(self):
self.background.draw(self.screen)
self.bubble.draw(self.screen)
pygame.display.flip()
def watch_for_events(self):
for event in pygame.event.get():
if event.type == QUIT:
self.runn = False
if __name__ == '__main__':
os.environ['SDL_VIDEO_WINDOWS_POS'] = "50, 1100"
pygame.init()
game = Game()
game.run()
pygame.quit()
Thanks for Helping
"Despawn" a bubble by calling pygame.sprite.Sprite.kill. kill remove the Sprite from all Groups. Use the MOUSEBUTTONDOWN event and pygame.Rect.collidepoint to determine if a bubble is clicked:
class Game(object):
# [...]
def watch_for_events(self):
for event in pygame.event.get():
if event.type == QUIT:
self.runn = False
if event.type == MOUSEBUTTONDOWN:
for bubble in self.bubble:
if bubble.rect.collidepoint(event.pos):
bubble.kill()

How to spawn multiple enemies in pygame

So im trying to make a game where the character should dodge enemies which are randomly spawned from above. The problem is, I dont know how to make the Random values different without instanciating another class, which I dont want to do. Also, with Screen.fill(), the enemies wont show up since they're being overlapped by the colour every frame, and if I dont use Screen.fill(), my character would leave a trail everytime it moves. Any Suggestions?
import random
pygame.init()
Running = True
Screen = pygame.display.set_mode((800, 600))
player_img = pygame.image.load('/Users/kevinhadinata/Downloads/ufo.png')
player_updated = pygame.transform.scale(player_img,(60,60))
enemy_list = []
enemy_img = pygame.image.load('/Users/kevinhadinata/Downloads/alien.png')
SPAWNENEMY = pygame.USEREVENT
pygame.time.set_timer(SPAWNENEMY,1000)
class Player:
def __init__(self):
self.ypos = 540
self.xpos = 325
self.height = 60
self.width = 60
self.playerUpdated = player_updated
def create_player(self):
Playerss = pygame.Rect(self.xpos,self.ypos,self.height,self.width)
pygame.draw.ellipse(Screen, (0, 0, 0), Playerss)
Screen.blit(player_updated, (Playerss.x, Playerss.y))
sizee = random.randint(10,40)
randomX = random.randint(0,700)
class Enemy:
def __init__(self):
self.xval = random.randint(0,700)
self.size = random.randint(10,40)
def create_enemy(self):
Enemy = pygame.Rect(self.xval, 0, self.size,self.size)
#enemy_updated = pygame.transform.scale(enemy_img,(self.size,self.size))
enemy_list.append(Enemy)
pygame.draw.ellipse(Screen,(255,255,0),Enemy)
Player = Player()
Enemys = Enemy()
while Running:
Screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
Player.xpos -= 20
if event.key == pygame.K_RIGHT:
Player.xpos += 20
if event.type == SPAWNENEMY:
Enemys.create_enemy()
Player.create_player()
pygame.display.update()
It's a good idea to not instantiate a new enemy, because just recycling it back to the top of the screen is enough. This amounts to simply changing the size & x,y.
Some of your code is occluding the Enemy class name with an Enemy variable name. I've changed this variable name to new_enemy.
class Enemy:
def __init__(self):
self.recycle() # set the position & size initially
def recycle( self ):
# start or re-start an enemy position
self.size = random.randint(10,40)
self.xval = random.randint(0,700)
self.yval = -self.size # off the screen-top
self.rect = pygame.Rect( self.xval, self.yval, self.size, self.size )
def draw( self, screen ):
pygame.draw.ellipse( screen, (255,255,0), self.rect )
def create_enemy(self):
global enemy_list
new_enemy = Enemy() # create a new Enemy
enemy_list.append( new_enemy ) # add it to the list
Then in your main loop, you can recycle() any Enemy that goes off-screen.
[...] # in main loop
# draw all the enemies, and re-position any enemies that moved off the screen
for enemy in enemy_list:
enemy.draw( screen )
if ( enemy.ypos > 600 ): # TODO - don't use a fixed size
enemy.recycle() # move back to top
The drawing an spawning code was mixed-up, I have re-arranged this into a separate .draw() function. Using this solves the problem with clearing the screen too. Each frame, the code clears the screen, then repaints all the items.
You need to create a list of enemies and iterate the list in the main loop to draw each enemy. Use randint to randomly place the enemies.
Try this code:
import random, pygame
pygame.init()
Running = True
Screen = pygame.display.set_mode((800, 600))
player_img = pygame.image.load('/Users/kevinhadinata/Downloads/ufo.png')
player_updated = pygame.transform.scale(player_img,(60,60))
enemy_list = []
enemy_img = pygame.image.load('/Users/kevinhadinata/Downloads/alien.png')
SPAWNENEMY = pygame.USEREVENT
pygame.time.set_timer(SPAWNENEMY,1000)
class Player:
def __init__(self):
self.ypos = 540
self.xpos = 325
self.height = 60
self.width = 60
self.playerUpdated = player_updated
def create_player(self):
self.Playerss = pygame.Rect(self.xpos,self.ypos,self.height,self.width)
pygame.draw.ellipse(Screen, (0, 0, 0), self.Playerss)
Screen.blit(player_updated, (self.Playerss.x, self.Playerss.y))
def draw(self): # draw player
Screen.blit(player_updated, (self.xpos,self.ypos))
sizee = random.randint(10,40)
randomX = random.randint(0,700)
class Enemys:
def __init__(self):
#self.xval = random.randint(0,700)
self.size = random.randint(10,40)
def create_enemy(self):
Enemy = pygame.Rect(random.randint(100,700), 0, self.size,self.size)
#enemy_updated = pygame.transform.scale(enemy_img,(self.size,self.size))
enemy_list.append(Enemy)
pygame.draw.ellipse(Screen,(255,255,0),Enemy)
def draw(self): # draw all enemies
for e in enemy_list:
pygame.draw.ellipse(Screen,(255,255,0),e)
Player = Player() # player object
Enemys = Enemys() # collection of enemies
Player.create_player()
while Running:
Screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
Player.xpos -= 20
if event.key == pygame.K_RIGHT:
Player.xpos += 20
if event.type == SPAWNENEMY:
Enemys.create_enemy()
Player.draw() # draw player
Enemys.draw() # draw all enemies
pygame.display.update()

Categories

Resources