1
\$\begingroup\$

So far I've loaded the images and can move the sprite around. When I hit the spacebar to cycle through the attack sprites within the attack_front list. The image becomes compressed, because the sword is now extending outwards. How would I go about keeping the image in the same location and only extending the surface I print it on for these images? I've tried just adjusting the surface in my get_image method, but the image skips around on the screen when you move.

I've made a gist and uploaded the spritesheet I'm utilizing to imgur and the links are below.

#!/usr/bin/python
import pygame as pg
from settings import *

class Spritesheet:

def __init__(self, filename):
    self.spritesheet = pg.image.load(filename).convert()

def get_image(self, x, y, width, height):
    image = pg.Surface((width, height)) #tried resizing this to specifc w & h, but made image skip around
    image.blit(self.spritesheet, (0,0), (x, y, width, height))

    image = pg.transform.scale(image, (150,150))
    return image

class Player(pg.sprite.Sprite):

    def __init__(self, game):
        pg.sprite.Sprite.__init__(self)
        self.game = game
        self.walking = False
        self.standing = False
        self.current_frame = 0
        self.last_update = 0
        self.image = self.game.spritesheet.get_image(9, 108, 18, 23)
        self.load_images()
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)
        self.x = 0
        self.y = 0

    def update(self):
        self.animate()
        self.x = 0
        self.y = 0
        keys = pg.key.get_pressed()
        if keys[pg.K_LEFT]:
            self.x = -3
        if keys[pg.K_RIGHT]:
            self.x = 3
        if keys[pg.K_UP]:
            self.y = -3
        if keys[pg.K_DOWN]:
            self.y = 3

        self.rect.x += self.x
        self.rect.y += self.y

    def load_images(self):
        self.standing = {'front': self.game.spritesheet.get_image(9, 108, 18, 23),
                         'back': self.game.spritesheet.get_image(79, 10, 17, 21),
                         'right': self.game.spritesheet.get_image(8, 190, 18, 21)}

        self.standing_left = []


        self.walking_bck = [self.game.spritesheet.get_image(106, 108, 18, 23),
                            self.game.spritesheet.get_image(138, 109, 18, 22),
                            self.game.spritesheet.get_image(170, 107, 18, 24),
                            self.game.spritesheet.get_image(200, 107, 18, 24),
                            self.game.spritesheet.get_image(232, 107, 18, 24),
                            self.game.spritesheet.get_image(263, 108, 18, 23),
                            self.game.spritesheet.get_image(296, 109, 18, 22),
                            self.game.spritesheet.get_image(328, 107, 18, 24),
                            self.game.spritesheet.get_image(360, 107, 18, 24),
                            self.game.spritesheet.get_image(391, 107, 18, 24)]

        self.walking_fwd = [self.game.spritesheet.get_image(103, 189, 18, 22),
                            self.game.spritesheet.get_image(136, 189, 18, 22),
                            self.game.spritesheet.get_image(168, 187, 18, 24),
                            self.game.spritesheet.get_image(200, 186, 18, 25),
                            self.game.spritesheet.get_image(230, 187, 18, 24),
                            self.game.spritesheet.get_image(262, 189, 18, 22),
                            self.game.spritesheet.get_image(293, 189, 18, 22),
                            self.game.spritesheet.get_image(326, 187, 18, 24),
                            self.game.spritesheet.get_image(360, 186, 18, 25),
                            self.game.spritesheet.get_image(390, 187, 18, 24)]

        self.walking_right = [self.game.spritesheet.get_image(100, 151, 23, 22),
                             self.game.spritesheet.get_image(134, 152, 20, 21),
                             self.game.spritesheet.get_image(168, 152, 20, 21),
                             self.game.spritesheet.get_image(199, 151, 20, 22),
                             self.game.spritesheet.get_image(229, 151, 20, 22),
                             self.game.spritesheet.get_image(258, 151, 23, 22),
                             self.game.spritesheet.get_image(292, 151, 19, 22),
                             self.game.spritesheet.get_image(327, 151, 19, 22),
                             self.game.spritesheet.get_image(360, 151, 19, 22),
                             self.game.spritesheet.get_image(389, 151, 20, 22),]

        self.walking_left = []
        for frame in self.walking_right:
            self.walking_left.append(pg.transform.flip(frame, True, False))

        self.attack_front = [self.game.spritesheet.get_image(0, 229, 28, 22),
                             self.game.spritesheet.get_image(38, 228, 25, 25),
                             self.game.spritesheet.get_image(80, 227, 19, 33),
                             self.game.spritesheet.get_image(114, 227, 19, 34),
                             self.game.spritesheet.get_image(151, 228, 25, 33),
                             self.game.spritesheet.get_image(193, 227, 29, 32),
                             self.game.spritesheet.get_image(238, 227, 31, 24),
                             self.game.spritesheet.get_image(285, 228, 32, 23),]


    def animate(self):
        now = pg.time.get_ticks()
        keys = pg.key.get_pressed()
        if self.x or self.y != 0:
            self.walking = True
        else:
            self.walking = False

        if self.walking:
            if now - self.last_update > 100:
                self.last_update = now
                #bottom = self.rect.bottom
                if keys[pg.K_DOWN]:
                    self.current_frame = (self.current_frame + 1) % len(self.walking_bck)
                    self.image = self.walking_bck[self.current_frame]

                if keys[pg.K_UP]:
                    self.current_frame = (self.current_frame + 1) % len(self.walking_fwd)
                    self.image = self.walking_fwd[self.current_frame]

                if keys[pg.K_LEFT]:
                    self.current_frame = (self.current_frame + 1) % len(self.walking_left)
                    self.image = self.walking_left[self.current_frame]

                if keys[pg.K_RIGHT]:
                    self.current_frame = (self.current_frame + 1) % len(self.walking_right)
                    self.image = self.walking_right[self.current_frame]


        if keys[pg.K_SPACE]:
            self.current_frame = (self.current_frame + 1) % len(self.attack_front)
            self.image = self.attack_front[self.current_frame]

Code: https://gist.github.com/crushedhat/95ab270d723a8d7fb45721f1cad93ee4
Spritesheet: https://imgur.com/a/iXfgA

\$\endgroup\$
1
\$\begingroup\$

My advice is to normalize all your animation frames so that they are the same size. That way, your player's rect never changes and in your game's draw() method you can always just render the player's image at the player's rect without having to worry about variable sizes. Use a rect size that can accommodate the largest animation frame you have. This is what I do when I use Pygame.

If you're worried about such a large rect giving you problems with collision and so on—don't. You can define a bounding_rect object for your player with which to calculate collisions. The bounding rect should be significantly smaller than the rect and should sit inside it.

I would also suggest creating a position attribute, pos, for your Player class. This is what you should change when you do input processing. It's your pos attribute which changes when you press a direction key. Your bounding_rect will simply follow your position, and the larger rect you're using for blitting images will simply follow your bounding rect.

Here's an image:

enter image description here

And here's some example code:

if keys[pg.K_LEFT]:
        self.pos.x = -3 .                                   # update position
        self.bounding_rect.centerx = self.pos.x             # the bounding rect is centered at your position
        self.rect.midbottom = self.bounding_rect.midbottom  # the rect you use to blit the image simply follows along
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.