Rect argument is invalid [duplicate] - python

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Pygame Drawing a Rectangle
(6 answers)
Closed 5 months ago.
I'm building a game with Sprites, using almost exactly the same code for all the sprites. But when it comes to my ship its telling me I have no rect or colliderect is invalid etc etc etc.
I tried to put a box around my 'rect' to make sure it was loaded correctly but I just get this error.
My code for the ship is
class Spaceship(pygame.sprite.Sprite):
def __init__(self, x, y, scale):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("ship.png")
self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale)))
self.rect = self.image.get_rect() # isn't this correct to get a rect!?
self.rect.center = [x, y]
self.pos = pygame.mouse.get_pos()
self.alive = True
self.speed = 100
self.dx = 0
self.dy = 0
self.x = 0
self.y = 0
def update(self):
pygame.draw.rect(screen,(GREEN), self.rect, 2) # Trying to establish rect object
self.pos = pygame.mouse.get_pos()
self.dx = (self.pos[0])
self.dy = (self.pos[1])
if self.x +20 <= self.dx:
self.x += speed
if self.x +20 >= self.dx:
self.x -= speed
self.y = (self.pos[1])
if self.y +20 <= self.dy:
self.y += speed
if self.y +20 >= self.dy:
self.y -= speed
print(self.pos[0])
print(self.pos[1])
if self.x >= SW - 40:
self.x = SW - 40
if self.x <= 0:
self.x = 0
if self.y >= SH -40:
self.y = SH - 40
if self.y <= SH - 600:
self.y = SH - 600
self.blit = (self.x, self.y)
self.rect = (self.x, self.y)
If I can't get this rect right I can't check rect collisions.
Thanks for any thoughts.

Related

How do I change rect size in pygame with sprites to improve accuracy of turrets? [duplicate]

This question already has answers here:
Can't figure out how to check mask collision between two sprites
(1 answer)
How to get the correct dimensions for a pygame rectangle created from an image
(2 answers)
Closed 3 days ago.
I am trying to make a game in pygame. I want to make a turret that will fire at the player. I have the formula to make this happen, but for some reason, it isn't completely accurate. I am running into the same problem with the player shooting as well. I am trying to use the mouse to aim, and it is off by a little bit.
Here is an image to help with understanding.
The cross is the turret and the ghost is the player. The rest is the bullets that should be hitting the player but it is hitting the rect top left it seems.
It is a bit of a mess but here is the code I am trying to test this with.
import pygame, math, random
pygame.init()
height,width = 1050,1000
clock = pygame.time.Clock()
screen = pygame.display.set_mode((height, width,))
pygame.display.set_caption("Vampires Suck")
pygame.display.flip()
running = True
class Crucifix2(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.sprite = pygame.image.load("image")
self.image = self.sprite
self.rect = self.image.get_rect()
self.rect.x =(450)
self.rect.y = (150)
self.mask = pygame.mask.from_surface(self.image)
def update(self):
pass
class MagicBullet2(pygame.sprite.Sprite):
def __init__(self, speed,x,y, targetx, targety):
super().__init__()
self.sprite = pygame.image.load("Image")
self.image = self.sprite
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
angle = math.atan2(targety - y, targetx - x)
self.dx = math.cos(angle) * speed
self.dy = math.sin(angle) * speed
self.x = x
self.y = y
def update(self):
self.x = self.x + self.dx
self.y = self.y + self.dy
self.rect.x = int(self.x)
self.rect.y = int(self.y)
if self.rect.x < -50 or self.rect.x > width + 50 or self.rect.y < -50 or self.rect.y > height + 50:
self.kill()
def collide(self, spriteGroup):
if pygame.sprite.spritecollide(self, spriteGroup, True, pygame.sprite.collide_mask):
pass
class OurHero(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.sprite = pygame.image.load('image')
self.size = (400,400)
self.current_sprite = 0
self.image =pygame.transform.scale(self.sprite, self.size)
self.rect = self.image.get_rect(topleft = (580, 630))
self.rect.x = (430)
self.rect.y = (380)
self.mask = pygame.mask.from_surface(self.image)
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.rect.x -= 3
if keys[pygame.K_RIGHT]:
self.rect.x += 3
if keys[pygame.K_UP]:
self.rect.y -= 3
if keys[pygame.K_DOWN]:
self.rect.y += 3
if self.rect.x > 793:
self.rect.x -= 3
if self.rect.x < 75:
self.rect.x += 3
if self.rect.y < 87:
self.rect.y += 3
if self.rect.y > 789:
self.rect.y -=3
self.current_sprite += 0.027
class aim(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.sprite = pygame.image.load("image")
self.image = self.sprite
self.rect = self.image.get_rect(center = (300,300))
self.rect.inflate(-500,-500)
def update(self):
self.rect.center = pygame.mouse.get_pos()
class MagicBullet(pygame.sprite.Sprite):
def __init__(self, speed,x,y, targetx, targety):
super().__init__()
self.sprite = pygame.image.load("image")
self.image = self.sprite
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
angle = math.atan2(targety - y, targetx - x)
self.dx = math.cos(angle) * speed
self.dy = math.sin(angle) * speed
self.x = x
self.y = y
def update(self):
self.x = self.x + self.dx
self.y = self.y + self.dy
self.rect.x = int(self.x)
self.rect.y = int(self.y)
if self.rect.x < -50 or self.rect.x > width + 50 or self.rect.y < -50 or self.rect.y > height + 50:
self.kill()
mouse_x, mouse_y = pygame.mouse.get_pos()
pygame.mouse.set_visible(False)
mouse = aim()
player = OurHero()
dude_sprite = pygame.sprite.Group()
dude_sprite.add(player)
dude_sprite.add(mouse)
bad = pygame.sprite.Group()
bad3 = pygame.sprite.Group()
bad2 = Crucifix2()
bad.add(bad2)
player_bullets = MagicBullet2(8, bad2.rect.x , bad2.rect.y+90 , player.rect.x, player.rect.y)
bullet_group = pygame.sprite.Group()
bad3.add(player_bullets)
distance_x = player.rect.x - bad2.rect.x
distance_y = player.rect.y - bad2.rect.y
angle = math.atan2(distance_y, distance_x)
dude2 = MagicBullet(5, player.rect.x, player.rect.y, mouse_x, mouse_y)
while running:
mouse_x, mouse_y = pygame.mouse.get_pos()
pygame.display.update()
player_bullets = MagicBullet2(8, bad2.rect.x , bad2.rect.y+90 , player.rect.x + 30, player.rect.y + 30)
bad3.add(player_bullets)
screen.fill('white')
bad3.update()
bad3.draw(screen)
dude_sprite.update()
dude_sprite.draw(screen)
bullet_group.draw(screen)
bad.update()
bad.draw(screen)
bullet_group.update()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
#bullet_group.add(player.creat_bullet())
dude2 = MagicBullet(8, player.rect.x , player.rect.y , mouse_x, mouse_y)
bullet_group.add(dude2)
if event.type == pygame.QUIT:
running = False
clock.tick(120)
I have been searching everywhere for an answer. I am not exactly sure what I am looking for. I am very new to game dev and I am still pretty new with python and pygame. I tried transform.scale() but that seemed to push the character off the screen when I put it into update().

how to move a rectangle in a pygame program [duplicate]

This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
Closed last month.
Good day, I am writing a pygame program that uses sockets. Right now I am just trying to get the rectangles to move in the x-axis and I keep getting this error
self.rect.x += self.dx
AttributeError: 'tuple' object has no attribute 'x' ".
My goal is just to move the rect left and right. using the move method below.
import pygame
class Player():
def __init__(self, x, y, width, height, color):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
self.rect = pygame.Rect((x, y, width, height))
self.vel = 3
self.dx = 0
self.dy = 0
self.jump = False
def draw(self, win):
pygame.draw.rect(win, self.color, self.rect)
def move(self, screen_width, screen_height):
SPEED = 10
dx = 0
dy = 0
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.dx = -SPEED
if keys[pygame.K_RIGHT]:
self.dx = SPEED
self.update()
def update(self):
# update player position
self.rect.x += self.dx
self.rect.y += self.dy
self.rect = (self.x, self.y, self.width, self.height)
self.dx = 0
self.dy = 0
I see that you already created a pygame.Rect object and updated it correct, why recreate that object?
Change this:
def update(self):
# update player position
self.rect.x += self.dx
self.rect.y += self.dy
self.rect = (self.x, self.y, self.width, self.height)
self.dx = 0
self.dy = 0
To:
def update(self):
# update player position
self.rect.x += self.dx
self.rect.y += self.dy
self.dx = 0
self.dy = 0
Also you might want to remove this as it doesn't do anything:
self.x = x
self.y = y
Unless you need the position where it was first created

'ball' object has no attribute 'top'

I am trying to make a pong game but for some reason i am getting a error
'ball' object has no attribute 'top'
ball1.x -= ball1.speed
ball1.y += ball1.speed
if ball1.top <= 0 or ball1.bottom >= 500:
ball1.speed *= -1
if ball1.left <= 0 or ball1.right >= 500:
ball1.speed *= -1
the ball class
# this is the moving ball
class ball:
def __init__(self,x,y,height,width,color):
self.x =x
self.y = y
self.height = height
self.width = width
self.color = color
self.speed = 5
self.rect = pygame.Rect(x,y,height,width)
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.circle(window, self.color, self.rect.center,10)
ball1 = ball(290,200,20,20,white)
You just need to add top, bottom, left and right to your class. Something like this:
class ball:
def __init__(self,x,y,height,width,color):
self.x =x
self.y = y
self.height = height
self.width = width
self.color = color
self.speed = 5
self.rect = pygame.Rect(x,y,height,width)
self.top = self.y
self.bottom = self.y + height
self.left = self.x
self.right = self.x + width
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.circle(window, self.color, self.rect.center,10)

Can Someone Tell Me Why My Projectiles Arent Showing Up On My Screen Test Shows The Projectiles are firing doesnt display on my screen?

on my output idle its printing that the bullets are firing but they arent showing up on my screen
if len(bulls):
bull = Bullet(round(smallice1.x+dir_x), round(smallice1.y+dir_y))
bulls.append(bull)
if round(pygame.time.get_ticks()/1000) % 3 == 0:
print("shooting")
if bulls != []: #Firing bullets
for bull in bulls:
bulls.append(bull)
if bull.y < 400: #Bullet movement
bull.x += bull.v
else:
bulls.pop(bulls.index(bull)) #Poping bullets from list
keys = pygame.key.get_pressed()
the bullets class
# enemys bullets
class Bullet:
def __init__(self, x, y, bull_x, bull_y, color):
self.x = x
self.y = y
self.dirx = bull_x
self.diry = bull_y
self.slash = pygame.image.load("heart.png")
self.rect = self.slash.get_rect()
self.rect.topleft = ( self.x, self.y )
self.speed = 10
self.color = color
def move(self):
self.x += self.bull_x * self.speed
self.y += self.bull_y * self.speed
def draw(self, window):
self.rect.topleft = (round(self.x), round(self.y))
window.blit(self.slash,self.rect)
even tho i rain this function below
for bull in bulls:
bull.draw(window)
full code
https://pastebin.com/EN6pU7bR
I redone my bullet class
class Bullet(object):
def __init__(self, x, y,color):
self.x = x
self.y = y
self.slash = pygame.image.load("littleboy.png")
self.rect = self.slash.get_rect()
self.rect.topleft = ( self.x, self.y )
self.speed = 10
self.color = color
def draw(self, window):
self.rect.topleft = ( self.x,self.y )
window.blit(slash, self.rect)
and shorten the firing part for the player added a variable list outside of my main loop called bulls = [] then used that I am bad at explainging things the
code is simple I can you can read it
for bull in bulls:
if bull.x < 500 and bull.x > 0:
bull.x += bull.speed
else:
bulls.pop(bulls.index(bull))
if len(bulls) < 2:
bulls.append(Bullet(round(smallice1.x+smallice1.width//2),round(smallice1.y + smallice1.height-60),(0,0,0)))

How to animate scale and rotate in pygame using rotozoom [duplicate]

This question already has answers here:
How to rotate an image around its center while its scale is getting larger(in Pygame)
(2 answers)
Closed 2 years ago.
Okay so Im just trying to get it working with rotations first before scaling then once I nail that the rotozoom should be easy. For the life of me I cant seem to get it working. Heres a simple class that I want the object to rotate over time as well a transform in the x direction. The transform is working fine but i just cant get it to rotate.
class Puff(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.screen = screen
try:
self.imagePuff = pygame.image.load(os.path.join("Images","puff.tga")).convert()
except:
raise UserWarning, "Unable to find Puff image"
self.imagePuff.set_colorkey((0,0,255))
self.image = self.imagePuff
self.rect = self.image.get_rect()
self.x = self.screen.get_width()/3
self.y = self.screen.get_height()/3+10
self.rect.center = (self.x, self.y)
self.lifespan = 60
self.speed = 1
self.count = 0
self.angle = 0
def update(self):
self.calcPos()
self.rect.center = self.x, self.y
self.transform()
if self.count > self.lifespan:
self.kill()
def calcPos(self):
self.x -= 5
self.y = self.y
def transform(self):
self.count += 1.1
self.angle += self.count*25
self.newTrans = pygame.transform.scale(self.copyImage, (400,400))
self.newRect = self.newTrans.get_rect()
self.newRect.center = self.rect.center
This is how I've made it so you can rotate your puff class:
import pygame
class Puff(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.screen = screen
try:
self.imagePuff = pygame.image.load("puff.jpg").convert()
except:
raise UserWarning, "Unable to find Puff image"
self.image = self.imagePuff
self.imagePuff.set_colorkey((0,0,255))
self.rect = self.image.get_rect()
self.x = self.screen.get_width()/3
self.y = self.screen.get_height()/3+10
self.rect.center = (self.x, self.y)
self.lifespan = 60
self.speed = 1
self.count = 0
self.angle = 0
def update(self):
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imagePuff, self.angle)
self.rect = self.image.get_rect()
self.rect.center = oldCenter
def calcPos(self):
self.x -= 5
self.y = self.y
def turnLeft(self):
self.angle = (self.angle + 45) % 360
def turnRight(self):
self.angle = (self.angle - 45) % 360
if __name__ == "__main__":
pygame.init()
screen = pygame.display.set_mode((400,300))
clock = pygame.time.Clock()
background = pygame.Surface(screen.get_size())
background.fill((0, 0, 0))
pygame.display.set_caption("Spinning sprite!!!")
ball = Puff(screen)
sprites = pygame.sprite.Group()
sprites.add(ball)
keepGoing = True
while keepGoing:
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
ball.turnRight()
sprites.clear(screen, background)
sprites.update()
sprites.draw(screen)
pygame.display.flip()
clock.tick(30)
Essentially the key points are:
self.image = pygame.transform.rotate(self.imagePuff, self.angle)
In the update method, and the two methods for changing the angle:
def turnLeft(self):
self.angle = (self.angle + 45) % 360
def turnRight(self):
self.angle = (self.angle - 45) % 360
In the code above every clock tick the sprite is rotated to the right:
ball.turnRight()
As you omitted your transform method, I had to edit the code to show how to do just rotations.
Hope this helps and if you need any more help please leave a comment.
Edit:
if you want to rotate and move to the left then you only really need to add this:
def update(self):
self.calcPos() # This moves the position - 5 in the x direction
self.rect.center = self.x, self.y
self.rotate() # This calls the bit to change the angle
if self.count > self.lifespan:
self.kill()
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imagePuff, self.angle) # This rotates
self.rect = self.image.get_rect()
self.rect.center = oldCenter
def calcPos(self):
self.x -= 5
def rotate(self):
self.angle = (self.angle + 45) % 360
You should check out:
http://www.gamedev.net/topic/444490-pygame-easy-as-py/
If you search for "rotate.py" you'll see the a section of code on rotating sprites
EDIT:
Try changing you transform method to:
def transform(self):
self.count += 1.1
self.angle += (self.count*25) % 360
self.copyImage = pygame.transform.rotate(self.imagePuff, self.angle)
self.newTrans = pygame.transform.scale(self.copyImage, (400,400))
self.image = self.newTrans

Categories