Simulating Shadows

Simulating Shadows

Postby ChristianCareaga » Fri Mar 21, 2014 6:39 am

I'm trying to simulate shadows for a 2d topdown RPG, but I can't think of the best way to do this

so far I've tried making copies of the original game entities and turning all opaque pixels black (which is a bit slow), then rotating them around the bottom of the original image, But i couldn't quite get that approach to work

So what is the best way to simulate this affect?

Here is the class I use to make the shadow objects and to rotate them:

Code: Select all
class Shadow():
    def __init__(self, game, surface, pos):
        self.game = game
        self.sun = [0, 650]
        self.center = self.game.center_point
        self.image = self.renderShadow(surface)
        self.og_image = self.image
        self.rect = self.image.get_rect(topleft=pos)
        self.og_rect = self.rect.copy()

    def renderShadow(self, surface):
        #Makes the shadow shape out of a surface (slow)
        surface = surface.copy()
        alphas = pygame.surfarray.pixels_alpha(surface)
        pixels = pygame.PixelArray(surface)

        for x in xrange(surface.get_width()):
            for y in xrange(surface.get_height()):
                if alphas[x, y] != 0:
                    pixels[x, y] = (0,0,0,50)

        sub = pixels.make_surface()
        return sub

    def rotate(self):
        #gets angle from suns pos to centerpoint then makes the shadow rotate by that much (doesnt really work)
        self.rect = self.og_rect
        self.image = self.og_image

        angle = degrees(atan2(self.center[0]-self.sun[0], self.center[1]-self.sun[1]))
        angle = 180 + angle

        self.image = rotate(self.image, angle)

    def moveSun(self, mouse):
        self.sun[0] = mouse [0] #the "sun's" x-axis is assigned to the mouse so I can simulate sun movement

    def Draw(self, screen):
        screen.blit(self.image, (self.game.off(self.rect)))

    def update(self, screen):
        #ran in loop to update shadows
        self.moveSun(pygame.mouse.get_pos())
        self.rotate()
        self.Draw(screen)


here is the repo with all the code:
https://github.com/linkey11/Necromonster
ChristianCareaga
 
Posts: 52
Joined: Sat Jun 22, 2013 9:54 am

Re: Simulating Shadows

Postby Mekire » Fri Mar 21, 2014 10:46 am

I'll probably clean this up a bit, but here is a pretty simple implementation. I cut the sprite into horizontal strips, setting pixels that are not transparent. Then when drawing I find the slope between the sun and player and offset the x axis accordingly.

Drag the sun around with the mouse to see the shadow move:
http://pastebin.com/4jY6tpgY

-Mek
User avatar
Mekire
 
Posts: 1031
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Simulating Shadows

Postby ChristianCareaga » Fri Mar 21, 2014 10:39 pm

PERFECT! how do you do it Mek! haha

Thanks so much, I got it implemented really easy! and it looks good! :mrgreen:
Last edited by Mekire on Sun Mar 23, 2014 11:02 am, edited 1 time in total.
Reason: Quote removed.
ChristianCareaga
 
Posts: 52
Joined: Sat Jun 22, 2013 9:54 am

Re: Simulating Shadows

Postby justinmeister » Sat Mar 22, 2014 5:51 am

Awesome! Great example
justinmeister
 
Posts: 9
Joined: Fri Jan 31, 2014 5:01 am

Re: Simulating Shadows

Postby Mekire » Sun Mar 23, 2014 11:00 am

Threw up a repo for this. Also fixed a math error I didn't notice before.
Includes the previous example with the draggable sun and also a more complex example with a sprite that has different animations in each direction.

https://github.com/Mekire/dynamic-sprite-shadows

-Mek
User avatar
Mekire
 
Posts: 1031
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Simulating Shadows

Postby ChristianCareaga » Mon Mar 24, 2014 10:46 pm

how can I change the alpha of the strips without remaking the whole thing?
ChristianCareaga
 
Posts: 52
Joined: Sat Jun 22, 2013 9:54 am

Re: Simulating Shadows

Postby Mekire » Tue Mar 25, 2014 1:36 am

In this function:
Code: Select all
def make_shadow_elements(self, image):
    """Split the image into horizontal strips."""
    colorkey = image.get_colorkey()
    transparent = colorkey if colorkey else (0,0,0,0)
    shadow_strips = []
    for j in range(self.sprite.rect.height):
        strip = pg.Surface((self.sprite.rect.width,1)).convert_alpha()
        strip.fill((0,0,0,0))
        for i in range(self.sprite.rect.width):
            pixel = image.get_at((i,j))
            if pixel != transparent:
                alpha = min(j*5, 255)
                strip.set_at((i,0), (10,0,10,alpha))
        shadow_strips.append(strip)
    return shadow_strips[::-1]

It's right here:
Code: Select all
alpha = min(j*5, 255)
strip.set_at((i,0), (10,0,10,alpha))

I just made it step by 5 until it is completely solid, but it is easily changed.

-Mek
User avatar
Mekire
 
Posts: 1031
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Simulating Shadows

Postby ChristianCareaga » Wed Mar 26, 2014 12:04 am

I mean't like change the alpha of the whole shadow on the go. I figured it out, I had to use convert() instead of convert_alpha() and then I blitted it with a color key after making the transparent pixels white and the visible ones black. Thanks Mek!
ChristianCareaga
 
Posts: 52
Joined: Sat Jun 22, 2013 9:54 am

Re: Simulating Shadows

Postby Kebap » Wed Mar 26, 2014 7:17 am

ChristianCareaga wrote:I figured it out. Thanks Mek!

If you mind, you can actually post your new code, so others can review it in the future, who maybe have a same question. :geek:
Learn: How To Ask Questions The Smart Way
Join the #python-forum IRC channel on irc.freenode.net and chat with uns directly!
Kebap
 
Posts: 400
Joined: Thu Apr 04, 2013 1:17 pm
Location: Germany, Europe


Return to Game Development

Who is online

Users browsing this forum: No registered users and 1 guest