I’m having trouble making the character move in python with pygame

Asked

Viewed 351 times

-2

import pygame

pygame.init()

tela = pygame.display.set_mode((800,600),0,32)

personagem = pygame.image.load('./você.png').convert_alpha()

def get_frame_by_gid(gid):
    global personagem
    columns = 4
    width = 100
    height = 100
    space_h = 0
    margin = 0
    top = 0
    space_v = 0
    linha = gid//columns
    coluna = gid % columns
    x = (coluna*(width+ space_h)) + margin
    y = (linha * (height+ space_v)) + top
    quadro = personagem.subsurface(pygame.Rect((x,y),(width,height)))
    return quadro

cima = [4,5,6,7]
baixo = [0,1,2,3]
esquerda = [8,9,10,11]
direita = [12,13,14,15]


parado_cima = [4]
parado_baixo = [0]
parado_esquerda = [8]
parado_direita = [12]
lista_quadro = esquerda

quadro = 0

clk = pygame.time.Clock()
while True:

    tela.fill((0,0,0))
    quadro = quadro + 1
    if quadro >= len(lista_quadro):
        quadro = 0
    gid = lista_quadro[quadro]
    frame = get_frame_by_gid(gid)

    tela.blit(frame,(400,300))
    pygame.display.update()
    clk.tick(8)

    for i in pygame.event.get():
        if i.type == pygame.QUIT:
            exit()

        elif i.type == pygame.KEYDOWN:
            if i.key == pygame. K_LEFT:
                lista_quadro = esquerda
                

            elif i.key == pygame. K_UP:
                lista_quadro = cima
            elif i.key == pygame. K_DOWN:
                lista_quadro = baixo

            elif i.key == pygame. K_RIGHT:
                lista_quadro = direita


        elif i.type == pygame.KEYUP:

            if i.key == pygame.K_LEFT:
                lista_quadro = parado_esquerda
            elif i.key == pygame.K_UP:
                lista_quadro = parado_cima
            elif i.key == pygame.K_DOWN:
                lista_quadro = parado_baixo

            elif i.key == pygame.K_RIGHT:
                lista_quadro = parado_direita
  • 2

    Hello - then take a tour of the site - your question is with negative votes because you missed adding some text - only with the code and the title of the question sometimes becomes a problem figure out how to answer.

1 answer

1


You’re taking the image dynamically, but you’re always putting the drawing in the same position (300,400) on the main screen -

You have to create variables (x and y, for example), to maintain the character’s position, and update these variables within the if that check the keys, and choose the image to draw.

You didn’t even tell if the rest is working well - with no error message - with a code of this size it is difficult to guess if everything is ok, although it seems. The code seems complete, but without the image we can’t test.

So, if everything else is ok, what can we do: (1) put the main body of the program into a function. Although it works like this, with the while True: loose in the middle of the module, this is not recommended - it is impossible to reuse this code - (for example, when this game evolves and you want to show a message when the character changes screen, and back in this while True: there is no way like this. If you are in a function, just call the function again.

And then, as all the rest of the "if" is right, just add the variables of location "x" and "y" and use these in place of the fixed numbers - the character should walk.

Well, I put some kind of image here and ran the program - yes, it’s in fact without any other problem.

So, in addition to the minimal changes I suggested, I put a few more things already anticipating three or four other steps - that you would face next.

The first of them - in addition to putting the game logic within a function, I did this also with the boot function, and put some values game critics within variables. With the name in capital letters of these variables, by the style convention they should be treated as constants - that is, I do not change their value after giving the initial value. I did this with the screen size, and the character size: So at other points in the code where I needed reference to these values, I didn’t have to copy the number - and then, if I want to change then just change the value once in the code.

The other things comment after the code:



import pygame

LARG, ALT = 800, 600
TAM_PERSONAGEM = 100

def init():
    global tela, personagem
    pygame.init()

    tela = pygame.display.set_mode((LARG, ALT),0,32)
    personagem = pygame.image.load('./você.png').convert_alpha()


def get_frame_by_gid(gid):
    global personagem
    columns = 4
    width = TAM_PERSONAGEM
    height = TAM_PERSONAGEM
    space_h = 0
    margin = 0
    top = 0
    space_v = 0
    linha = gid//columns
    coluna = gid % columns
    x = (coluna*(width+ space_h)) + margin
    y = (linha * (height+ space_v)) + top
    quadro = personagem.subsurface(pygame.Rect((x,y),(width,height)))
    return quadro


cima = [4,5,6,7]
baixo = [0,1,2,3]
esquerda = [8,9,10,11]
direita = [12,13,14,15]


parado_cima = [4]
parado_baixo = [0]
parado_esquerda = [8]
parado_direita = [12]

passo = 20

def principal():
    lista_quadro = parado_esquerda
    quadro = 0
    clk = pygame.time.Clock()

    x_anterior = x = LARG // 2
    y_anterior = y = ALT // 2

    vel_x = vel_y = 0

    while True:

        tela.fill((0,0,0))
        quadro = quadro + 1
        if quadro >= len(lista_quadro):
            quadro = 0
        gid = lista_quadro[quadro]
        frame = get_frame_by_gid(gid)

        pygame.draw.rect(tela, (0, 0, 0),(x_anterior, y_anterior, 100, 100))
        tela.blit(frame,(x, y))
        pygame.display.update()
        clk.tick(8)

        for i in pygame.event.get():
            if i.type == pygame.QUIT:
                return

            elif i.type == pygame.KEYDOWN:
                if i.key == pygame. K_LEFT:
                    lista_quadro = esquerda
                    vel_x = - passo
                elif i.key == pygame. K_UP:
                    lista_quadro = cima
                    vel_y = - passo
                elif i.key == pygame. K_DOWN:
                    lista_quadro = baixo
                    vel_y = passo
                elif i.key == pygame. K_RIGHT:
                    lista_quadro = direita
                    vel_x = passo

            elif i.type == pygame.KEYUP:

                if i.key == pygame.K_LEFT:
                    lista_quadro = parado_esquerda
                    vel_x = 0
                elif i.key == pygame.K_UP:
                    lista_quadro = parado_cima
                    vel_y = 0
                elif i.key == pygame.K_DOWN:
                    lista_quadro = parado_baixo
                    vel_y = 0
                elif i.key == pygame.K_RIGHT:
                    lista_quadro = parado_direita
                    vel_x = 0

        x_anterior = x
        y_anterior = y

        if 0 <= x + vel_x < LARG - TAM_PERSONAGEM :
            x += vel_x
        if 0 <= y + vel_y < LARG - TAM_PERSONAGEM :
            y += vel_y

init()
principal()
pygame.quit()

First thing - besides entering "x" and "y", I entered "vel_x" and "vel_y" - to indicate how many pixels to walk on each axis - and update everything at the end. I could do it alone

...
   if i.key == pygame. K_LEFT:
      lista_quadro = esquerda
       x -= passo
...

That is - add my step variable directly on x and y - but having a "speed x" variable I gain two things: first - the Pcs do send several 'KEYDOWN' events when a key is pressed - but the amount of events depends on OS key repetition parameters-you could get less than a 'KEYDOWN' (or more than one) in each frame of the game - and then the move on the x axis would get uneven. With speed, I talk that he is walking left in the first keydown event - and ready, only will stop when there is a "KEYUP" of the corresponding arrow key, and the speed goes to zero.

The second advantage has to do with one of the advances I made in the game - at the end of the function, before updating x and y in each frame, I check if the persongaem will continue on the screen limits. (use the shape 0 < x < max which is characteristic of Python, works like notation we learn in mathematics. Python internally does the same thing as 0 < x and x < max) - If I didn’t have a vel_x - I would have to do this check on the left key and the right key: a lot more lines of program, and a mix of concepts - take the event, with "check if the person can" . With the separate verification code, it becomes easy when the project grows to pass this to a part function as well.

Well, and besides the vel_x and vel_y I picked up a x_anterior and y_anterior - because if the program simply drew the character in the new position, the previous position would be marked and he would leave "trace". Hmm . but only now have I noticed that a call is also made to tela.fill - this clears the screen between one frame and another - only it uses much more machine processing - with the previous x and y and drawing the black rectangle in the previous position, it is not necessary to fill the whole screen .

The recommendation is that you experiment there - until you understand all these points - experiemnte take the call to "tela.Fill" and also comment on the pygame.draw.rect - and you’ll see the trail left - it’s important to understand the operation of the game and the program, at a level where whoever programs into a ready game engine, just doesn’t understand - these concepts are missing.

Good project there - in the next questions, do not forget to give a little context, otherwise the staff closes the question before someone can answer. (I got here with 4 votes to close - in the 5th vote it is closed)

  • Thank you so much for your help, the college asks every semester as work of integration of all the subjects that we gather in groups and create games, usually I concentrate only on taking care of the animations, but the teacher demanded that everyone in the group would have to have a good sense of programming, so I’m trying to run behind that.

  • cool - I hope I helped. It would be nice for me if you showed this answer to the other integrates of the group as well - I think it added a lot of value to it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.