python – Coordinates of a PyGame image

Question:

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()

Answer:

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 pygame.Sprite class.

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)

Scroll to Top