How can I get the x and y coordinates of an image in PyGame? I need this for a game where I have to make the shot go right below an enemy. This is the code:
# -*- coding: cp1252 -*- import sys import random import pygame print pygame.init() #inicia todo o módulo pygame (pygame.init() retorna algo, não faz a inicialização completa por isso so print x_player, y_player = 650, 440 screen = pygame.display.set_mode((700, 500)) # screen's size width and height pygame.display.set_caption("Space Invaders v1.0.0") # name of the screen pygame.display.flip() invaders = pygame.image.load( "C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\space-invaders.jpeg").convert() player = pygame.image.load( "C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\28006.png").convert() # loads the image # of the player and put it on a variable mother_ship = pygame.image.load( "C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\mother_ship.png").convert() lifes = pygame.image.load( "C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\28007.png").convert() shots = pygame.image.load( "C:\\Users\\bernardo\\Documents\\IFC\\Programação\\SpaceInvaders-my_own\\shots_and_bombs2.png").convert() pygame.font.init() clock = pygame.time.Clock() player_size = player.get_size() move_x = 0 x_invaders, y_invaders = 60, 60 lifes_list = [lifes, lifes, lifes] x_mother = 0 invaders_matrix = [[invaders] * 11] * 5 existe_nave = False start = True while len(lifes_list) != 0: screen.fill([0, 0, 0]) # color of the screen (rgb) screen.blit(player, [(x_player / 2), y_player]) # initial position of player clock.tick(35) # are going to happen just movements on 23 frames per second screen.blit(shots, (invaders_matrix[random.randint(0, 4)][random.randint(0, 10)].get_rect().centerx, invaders_matrix[random.randint(0, 4)][random.randint(0, 10)].get_rect().centery)) x_invaders, y_invaders = 105, 125 for invader in range(len(invaders_matrix)): for invad in range(len(invaders_matrix[invader])): screen.blit(invaders_matrix[invader][invad], [x_invaders, y_invaders]) x_invaders += 45 x_invaders = 105 y_invaders += 30 if existe_nave and (x_mother < 700): screen.blit(mother_ship, [x_mother, 35]) x_mother += 4.5 screen.blit(mother_ship, [x_mother, 35]) elif random.randint(0, 800) == 0: existe_nave = True x_mother = 0 width_for_lifes = 680 for icon_lifes in lifes_list: width_for_lifes -= 50 screen.blit(icon_lifes, (width_for_lifes, 15)) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() start = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: move_x -= 10 start = False if event.key == pygame.K_RIGHT: move_x += 10 start = False if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: move_x = 0 start = False if x_player >= 1280: x_player = 1280 if x_player <= 25: x_player = 25 font = pygame.font.Font(None, 36) text = font.render("Lifes", 1, (0, 255, 85)) screen.blit(text, (450, 15)) font = pygame.font.Font(None, 36) text = font.render("Score", 1, (0, 255, 85)) screen.blit(text, (20, 15)) x_player += move_x pygame.display.update()
After you place an image on the main image (screen) using a call to the "blit" method like this code does, the image becomes part of the main image:
Blit is like hitting a stamp on a sheet of paper: what you know is where you ordered the stamp to hit – if you move the stamp in place, just using your eyes to "see" where the image is. But when we program games in this style, "seeing" is an expensive operation – in this case, almost impossible. (It's possible, but you would have to use image recognition and a series of programming techniques almost a hundred times more sophisticated than the game itself)
To know where each invading ship is and to place the shot there, you must store the coordinates of each ship in data structures in memory –
In your case, the lines
x_invaders += 45 x_invaders = 105 y_invaders += 30
position the aliens, in a "handcrafted" fashion – and the data about each alien is discarded and recalculated in real time in the next frame.
This was a necessary technique in video games with a few KB of memory where this type of game was first created. Nowadays, what pays off is creating a memory object for each invading ship (and other elements in game), and associating the data of each element with itself. So any alien in the matrix will have the information on where he is.
Pygame provides a really cool class, which interacts with the game's
Group classes, to serve as the basis for its objects: the
When you sweat your enemies derived from pygame.Sprite, for example, they will usually have an associated
pygame.Rect object – which contains all of the enemy's coordinates, at any given time (your program that updates those coordinates). But by doing this, you can have the coordinate of the center horizontally, of the underside of each invader simply by doing:
x, y = invader.rect.centerx, invader.rect.bottom
Please feel free to write to me privately if you would like further guidance on this game – I am working on a similar project with my students. (my contact is on profile)