1
votes

Currently, I am working on a 2D top-down style RPG (in Pygame; newest version of Python), and I want to make the character drawing process as simple as possible. However, I have no earthly idea of how to pull it off.

I know already that drawing out sprites using a for loop will kill my game's performance, and then I'd also have more code to worry about.

What I want to do is take a 'nude' sprite, put eyes, hair, and clothes on top of it, and save that as a new image.

(MaleSprite.png + Eyes1.png + Hair1.png + Clothes1.png = Spritesheet.png)

I already have a sprite sheet for a nude sprite, and I also have a sprite sheet for a hair style. I need to shift the hair up by two pixels and then draw it on top of the character, then save that to a new image (since the sprite sheet for the character is 64px tall, the new image will be 66px tall).

I'll handle any other dependencies that come up in the code, I just need to combine these images, and I believe I should be using Pillow for this.

I want to get the player's choices for eye color, hair, and clothing, and then write that to their player file. After that, the makesprite() function should take the sprites, adjust them as needed (hair will be shifted up by two pixels, hats will probably be more), and then save that as a new sprite sheet (png) that I can use in my sprite.draw() function.

1
This sounds like premature optimisation, which is generally bad. Often our thoughts of what is slow and fast are different from practice. I recommend implementing your initial approach and then looking at how to optimise the issue. In terms of overlapping images, you can blit them all onto your sprite image during your configuration process. It will be easier to answer questions when you show what you have tried so far.import random
@Eric makes a good point. Obviously the code should not be drawing 4x sprites every time to paint the player bitmap, but the 4 parts can be combined as a one-off operation, then used as a single sprite. Even in the sprite.__init__(). Sounds quite flexible actually.Kingsley
Actually, you both make great points. I've never heard the proverb about premature optimization (which is actually what I've been doing), so I'll get to work on making it function first, heh. Thanks for the advice!Endvisible

1 Answers

1
votes

Pygame can handle this just fine, no need for other libraries. Just take a look at the image module, where you'll find a save function as well as tostring/fromstring.

But if you create your player sprite from some a set of templates, there's not much reason to actually save the image to disk. You could just create the player image at startup by blitting all the different parts (body, hair, eyes....) onto a new Surface and just use this.

Here's some pseudo code of how that could look like:

import pygame 
from collections import defaultdict

def load_image(filename): 
    ... load and cache the image ...

offset = defaultdict(lambda: (0, 0))
offset['eyes'] = (0, 2) # let's blit eyes not at (0, 0), but at (0, 2)

def build_body_image(**look):
    surf = pygame.Surface((66, 66))
    for part in look:
        surf.blit(load_image(look[part]), offset[part])

class Actor(pygame.sprite.Sprite):
    def __init__(self, **look):
        super().__init__()
        self.look = look
        self.image = build_body_image(**self.look)
        ...

player = Actor(body='MaleSprite.png',
               clothes='Clothes1.png'
               eyes='Eyes1.png',
               hair='Hair1.png')

If you want to persist the player look, you'll just have to persist the look attribute, then call build_body_image once at startup to recreate the final player image.

Of course there are several ways to do something like this (e.g. you could just store an index instead of full filename and/or look up the images in a spritesheet, whatever), choose a way that fits your needs.