I am currently making a battleships type game and I have created a user-friendly interface that highlights spaces on a grid in order to finish my hit system in this game I need to find the position of my sprite at a certain instance(for example when the player presses enter).
So what you can do to find the position of a sprite in pygame is you can use the get_rect() to find the Rect of the sprite, and then using the .x and .y. I'm assuming that you're sprites are pygame.Surfaces.
find_loc(surface):
loc = (surface.get_rect().x, surface.get_rect().y)
return loc
# First, I get the Rect of your surface
# With the Rect, I get the variables of the x and y
# I assign the .get_rect().x and .get_rect().y to a tuple which is assigned to variable 'loc'
# I return 'loc'
I hope this helps.
Related
This is just a quick question regarding sprites in PyGame, I have my image loaded as in the code below, and I'm just wondering how to display the sprite in PyGame like drawing a rectangle or circle. I don't want to have it behave in anyway. I think I use a blit command, but I'm not sure and I'm not finding much online.
Here's my image code for loading it.
Star = pygame.image.load('WhiteStar.png').convert_alpha()
You could just provide an outline for loading a sprite. I simply want to display it.
Use blit to draw an image. Actually blit draws one Surface onto another. Hence you need to blit the image onto the Surface associated to the display.
You need to specify the position where the image is blit on the target. The position can be specified by a pair of coordinates that define the top left position. Or it can be specified by a rectangle, only taking into account the top left point of the rectangle:
screen = pygame.dispaly.set_mode((width, height))
star = pygame.image.load('WhiteStar.png').convert_alpha()
# [...]
while run:
# [...]
screen.blit(star, (x, y))
# [...]
Use a pygame.Rect when you want to place the center of a surface at a specific point. pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument. For example, the center of the rectangle can be specified with the keyword argument center. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments):
screen.blit(star, star.get_rect(center = (x, y)))
I have a single ball sprite and I don't really have a need for a group. I want to set that sprite to be deleted (or killed) when it reaches the end of the screen, also so it generates another one. I am trying to do this without a group and wanted to know if this is possible. Thank you for your expertise.
I tried self.kill() and kill.self in an update method for the sprite class. That didn't work. I tried to do a kill in the screen update loop for the application. That didn't work. I have done extensive research and all the answer are only when using groups. I also tried to do "if not pygame.surface.rect.contains(Ball())" and that didn't work. (It is something like that, I tried several variations of that expression.)
def update(self):
"""Move the ball down"""
self.y = self.y + 1
self.rect.y = self.y
#print("Screen is: " + str(pygame.surface.rect()))
print("Object is: " + str(self.rect))
if (self.rect.y >= 800):
self.kill()
def update_screen(screen, ball, lamp):
#Show on the screen
screen.fill((135,206,250))
lamp.blitme()
ball.blitme()
ballgen(screen)
ball.update()
lamp.update()
pygame.display.flip()
I expected the results to stop counting the rect of the ball, but it keeps counting up, thus making me think that it is not being removed.
If you don't use the Group class, there's no point in calling the Sprite.kill method. All it does is to remove the Sprite from all of its groups. Calling kill does not magically remove the Sprite from your game.
If you want to have a Sprite removed, just stop using it: either stop calling ball.blitme() and ball.update() in your update_screen function, or replace ball with a new instance of your Sprite's class.
But consider starting to actually use the Group class. It'll make your life easier.
To check if the ball is inside the screen, instead of
if not pygame.surface.rect.contains(Ball())
use
if not pygame.display.get_surface().get_rect().contains(self.rect):
self.rect.center = (whatever_new_position, ....)
in Ball's update method. pygame.display.get_surface() will get you the screen surface, get_rect() will get you the Rect of that Surface, and contains() will check if the Rect of the Ball is still inside the screen.
Then we just set a new position for the ball.
Also note that there's usually no need for an x and y attribute in a sprite class since the position is already stored in the rect attribute.
I am making a game, with pygame, and i want it to be that when the mouse hovers over my text, the box gets shaded.
here is what I have so far:
in the event-handling loop:
(tuples in CheckToUnshadeBoxes are pairs of text-surfaces and their boxes (from get_rect method))
elif event.type == MOUSEMOTION:
CheckToShadeBoxes(event, LERect, LoadRect, PlayRect)
CheckToUnshadeBoxes(event, (LERect, LESurf),
(LoadRect, LoadSurf), (PlayRect, PlaySurf))
here is CheckToShadeBoxes:
def CheckToShadeBoxes(event, *args):
'''
shade the box the mouse is over
'''
for rect in args:
s = pg.Surface((rect.width, rect.height))
s.set_alpha(50)
print(rect.x, rect.y)
s.fill(COLOURS['gray'])
x, y = event.pos
if rect.collidepoint(x, y):
SURFACE.blit(s, (rect.x, rect.y))
and CheckToUnshadeBoxes:
def CheckToUnshadeBoxes(event, *args):
''' if the mouse moves out of the box, the box will become unshaded.'''
for (rect, TextSurf) in args:
x, y = event.pos
if not rect.collidepoint(x, y):
SURFACE.blit(TextSurf, (rect.x, rect.y))
This works fine! except that when I move the mouse inside of the box, the box will continue to get darker and darker until you cant even see the text! I know it is a small detail, but it has been bugging me for a long time and I don't know how to fix it.
by the way, if it is not evident enough, COLOURS is a dictionary with string keys and RGB tuple values, and SURFACE is my main drawing surface.
If you have any questions about my code, or anything I have done just comment!
If the rects you are passing are your own derived class, then I recommend making a .is_shaded class variable and checking to make sure the variable is false before shading it.
If these rects aren't your own class extending another, then I recommend you make one, as it would make it much simpler
The problem with your code is that you keep adding in dark rectangles when the mouse is hovered over. No wonder it gets darker and darker.
All that is needed is for your code to be shuffled around a little.
Inside your event handling, you should call a function to check if it should shade the text. This should return a Boolean value. Store this in a variable. Most of the code from the CheckToShadeBoxes function will do the trick.
In your render section, you should render just one surface on top of your text, based on whether the Boolean value is true or not. The code that creates a gray surface in the CheckToShadeBoxes function will work but make sure it is only one surface. Don't create a new surface in every iteration. Define it outside once and blit it to the screen inside the loop.
This should fix your problem!
I hope this answer helps you! If you have any further questions please feel free to post a comment below!
I am using python 2.7, and im using pygame to make a basic game.
(code can be found here: http://github.com/ProgrammerKid/snake)
(snake.py is my main file)
My game was initially supposed to mock the snake game, but it turned out to be more like pacman... so my problem is that since in pygame, the position of an image is always set to the top left corner of the image.... is there was i can make it the center of the image...
because the position of the killer/alien is at the top left, and same with the pacman/snake... so the two objects would literally have to be overlapping for the alien to kill the pacman.... i want it so that they only overlap a little....:
check out this picture:
http://i.stack.imgur.com/N88GX.png
see: Pygame Rect Reference
you probably already know:
imageObject = pygame.image.load(filename)
rect = imageObject.get_rect()
Now try:
rect.center = (newX, newY)
Or, better:
rect.move(xDistance, yDistance)
Good Luck!
Yep, I'm asking another question about this program :D
Anyway, I currently a program that creates two lines on the screen with a gap in between them that can scroll. From here, I obviously need to see if the two objects are colliding. Since I only have one sprite and one rectangle I thought it was slightly pointless and overkill to make two classes for them. However, I can only find tutorials relating to classes which I obviously don't need. So, my question really is:
Is it possible to test for collision between a standard image and a Pygame rect? If it is not, how can I convert either the image, rectangle or both the sprites to do this. (All preferably without using classes.)
Note: the image and rectangle are created in the following ways (if it makes a difference)
bird = pygame.image.load("bird.png").convert_alpha()
pipeTop = pygame.draw.rect(screen, (0,200,30), Rect((scrollx,0),(30,height)))
pipeBottom = pygame.draw.rect(screen, (0,200,30), Rect((scrollx,900),(30,-bheight)))
An image by itself does not have a position. You cannot test collision between a rect and something that is not placed in the world. I would recommend to create a class Bird along with a class Pipe that will both subclass pygame.Sprite.
Pygame already has collision detection built in.
A short example
bird = Bird()
pipes = pygame.Group()
pipes.add(pipeTop)
pipes.add(pipeBottom)
while True:
if pygame.sprite.spritecollide(bird,pipes):
print "Game Over"
EDIT:
Don't be afraid of classes, you will have to use them anyways sooner or later.
If you really don't want to use sprites, you can use the birds rect and the pipe and call collide_rect to check if they overlap.
EDIT2:
an example Bird class modified from pygame docs
class Bird(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bird.png").convert_alpha()
# Fetch the rectangle object that has the dimensions of the image
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()
You could then add methods such as move, which will move the bird down with the force of gravity.
The same would apply for the Pipe but instead of loading an image, you can create an empty Surface, and fill it with a color.
image = pygame.Surface(width,height)
image.fill((0,200,30)
You can just get the x and y values and compare them:
if pipe.x < bird.x < pipe.x+pipe.width:
#collision code
pass