I want to make sprites in SpriteManager collide, is it possible?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
4v4proj
Newbie
Posts: 5
Joined: Wed Mar 18, 2020 1:55 pm
Contact:

I want to make sprites in SpriteManager collide, is it possible?

#1 Post by 4v4proj »

Here's the idea. I am trying to set up a simulation where if 'green sprite' hits 'red sprite', there's a 50/50 chance on which one that survives.

Here's how it looks.
Image

It works as should so far, with sprites bouncing around within a box and random speeds as well.
The amount of red pixels are based on a variable ex "team1_infantry" and likewise with team2_* & etc.
When started 45 seconds will countdown, and then which side that has the most sprites will win.

This is the logic so far.

Code: Select all

    def repulsor_update(st):
        
        global team1_infantry
        # For each sprite in team 1...
        for i in repulsor_sprites:
            
            speed_clamped_y = i.team1_i_speed_y * .01
            speed_clamped_x = i.team1_i_speed_x * .01
            
            i.x += i.bdx * speed_clamped_x
            i.y += i.bdy * speed_clamped_y
            
            top = 120 - 5 / 2
            if i.y < top:
                i.y = top + (i.y - top)
                i.bdy = -i.bdy
            
            bottom = 520 - 5 / 2
            if i.y > bottom:
                i.y = bottom - (i.y - bottom)
                i.bdy = -i.bdy
                
            left = 175 - 5 / 2
            if i.x < left:
                i.x = left + (i.x - left)
                i.bdx = -i.bdx
            
            right = 905 - 5 / 2
            if i.x > right:
                i.x = right - (i.x - right)
                i.bdx = -i.bdx
                

            
        ## FOR OTHER TEAM
        for e in repulsor_sprites2:
            
            speed_clamped_y = e.team2_i_speed_y * .01
            speed_clamped_x = e.team2_i_speed_x * .01
            
            e.x += e.bdx * speed_clamped_x
            e.y += e.bdy * speed_clamped_y
            
            top = 120 - 5 / 2
            if e.y < top:
                e.y = top + (e.y - top)
                e.bdy = -e.bdy
            
            bottom = 520 - 5 / 2
            if e.y > bottom:
                e.y = bottom - (e.y - bottom)
                e.bdy = -e.bdy
                
            left = 175 - 5 / 2
            if e.x < left:
                e.x = left + (e.x - left)
                e.bdx = -e.bdx
            
            right = 905 - 5 / 2
            if e.x > right:
                e.x = right - (e.x - right)
                e.bdx = -e.bdx
                
        #find coords of e
        for i in repulsor_sprites:
            if i.x == e.x and i.y == e.y:
                team1_infantry -= 1
                renpy.sound.play("select.ogg", channel=1)
                i.destroy()

        return .01
And this is the code that sets up the numbers, within a label.

Code: Select all

label testers:
    ## DELTAS
    python:
        
        import pygame
        # Create a sprite manager.
        repulsor = SpriteManager(update=repulsor_update)
        repulsor_sprites = [ ]
        repulsor_sprites2 = [ ]

        # Ensure we only have one smile displayable.
        me = Image("team1_sprite.png")
        enemy = Image("team2_sprite.png")
        
        if team1_apcs > 0:
            apcs_1 = Image("apc_sprite_t1.png")
            
        if team2_apcs > 0:
            apcs_2 = Image("apc_sprite_t2.png")

        # Add 400 sprites.
        for i in range(team1_infantry):
            repulsor_sprites.append(repulsor.create(me))
            
        for i in range(team1_apcs):
            repulsor_sprites.append(repulsor.create(apcs_1))
            
        for i in range(team2_infantry):
            repulsor_sprites2.append(repulsor.create(enemy))
            
        for i in range(team2_apcs):
            repulsor_sprites2.append(repulsor.create(apcs_2))

        # Position the 400 sprites.
        for i in repulsor_sprites:
            i.x = renpy.random.randint(180, 360)
            i.y = renpy.random.randint(128, 512)
            
            i.team1_i_speed_x = renpy.random.randint(-300, 300)
            i.team1_i_speed_y = renpy.random.randint(-300, 300)
            i.bdx = .5
            i.bdy = .5
            i.rect = pygame.Rect(i.x,i.y,32,32)
            
            
        for e in repulsor_sprites2:
            e.x = renpy.random.randint(720, 900)
            e.y = renpy.random.randint(128, 512)
            
            e.team2_i_speed_x = renpy.random.randint(-300, 300)
            e.team2_i_speed_y = renpy.random.randint(-300, 300)
            e.bdx = .5
            e.bdy = .5
            e.rect = pygame.Rect(e.x,e.y,32,32)


        del me
        del i
        del e
        del enemy

    # Add the repulsor to the screen.
    show expression repulsor as repulsor

    "..."

    hide repulsor

    # Clean up.
    python:
        del repulsor
        del repulsor_sprites
I tried to do something like this, below.

Code: Select all

for i in repulsor_sprites:
            if i.x == e.x and i.y == e.y:
                team1_infantry -= 1
                i.destroy()
But I'm not a programmer, and I thought that, if 'green sprite' is in the same position as a 'red sprite', red would be destroyed, but nothing happens.

User avatar
Alex
Lemma-Class Veteran
Posts: 3094
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: I want to make sprites in SpriteManager collide, is it possible?

#2 Post by Alex »

Check this sample - viewtopic.php?f=8&t=29439#p348727

So, you can have all your sprites as an objects with x, y, width, height properties, and create a function to determine collisions to use it in repulsor_update function.
Try something like

Code: Select all

init python:
    def get_size(d):
        w, h = renpy.render(renpy.easy.displayable(d), 0, 0, 0, 0).get_size()
        return int(round(w)), int(round(h))

    def got_collision(sprite1, sprite2):
        left_side_1 = sprite1.x
        right_side_1 = sprite1.x + sprite1.width
        top_side_1 = sprite1.y
        bottom_side_1 = sprite1.y + sprite1.height
        
        left_side_2 = sprite2.x
        right_side_2 = sprite2.x + sprite2.width
        top_side_2 = sprite2.y
        bottom_side_2 = sprite2.y + sprite2.height
        
        if (right_side_1 > left_side_2 and left_side_1 < right_side_2) and (bottom_side_1 > top_side_2 and top_side_1 < bottom_side_2):
            return True
        else:
            return False

    class My_sprite(object):
        def __init__(self, sprite, xpos=0, ypos=0):
            self.sprite = sprite
            self.show = manager.create(sprite)
            self.width, self.height = get_size(sprite)
            self.show.x = xpos
            self.show.y = ypos - self.height
            
        @property
        def x(self):
            return self.show.x
        @x.setter
        def x(self, value):
            self.show.x = value
            
        @property
        def y(self):
            return self.show.y
        @y.setter
        def y(self, value):
            self.show.y = value

    def repulsor_update(st):
        blah-blah-blah

        for i in repulsor_sprites:
            for j in repulsor_sprites2:
                if got_collision(i, j):
                    # some code to determine what sprite will die X_x
                    # then...
                    # i.show.destroy()
                    # repulsor_sprites.remove(i)

4v4proj
Newbie
Posts: 5
Joined: Wed Mar 18, 2020 1:55 pm
Contact:

Re: I want to make sprites in SpriteManager collide, is it possible?

#3 Post by 4v4proj »

Your code seems to work fine, but for some reason only 1 sprite in 'repulsor_sprites' is doing the action.

4v4proj
Newbie
Posts: 5
Joined: Wed Mar 18, 2020 1:55 pm
Contact:

Re: I want to make sprites in SpriteManager collide, is it possible?

#4 Post by 4v4proj »

Alex wrote: Wed Mar 18, 2020 4:40 pm Check this sample - viewtopic.php?f=8&t=29439#p348727

So, you can have all your sprites as an objects with x, y, width, height properties, and create a function to determine collisions to use it in repulsor_update function.
Try something like

Code: Select all

init python:
    def get_size(d):
        w, h = renpy.render(renpy.easy.displayable(d), 0, 0, 0, 0).get_size()
        return int(round(w)), int(round(h))

    def got_collision(sprite1, sprite2):
        left_side_1 = sprite1.x
        right_side_1 = sprite1.x + sprite1.width
        top_side_1 = sprite1.y
        bottom_side_1 = sprite1.y + sprite1.height
        
        left_side_2 = sprite2.x
        right_side_2 = sprite2.x + sprite2.width
        top_side_2 = sprite2.y
        bottom_side_2 = sprite2.y + sprite2.height
        
        if (right_side_1 > left_side_2 and left_side_1 < right_side_2) and (bottom_side_1 > top_side_2 and top_side_1 < bottom_side_2):
            return True
        else:
            return False

    class My_sprite(object):
        def __init__(self, sprite, xpos=0, ypos=0):
            self.sprite = sprite
            self.show = manager.create(sprite)
            self.width, self.height = get_size(sprite)
            self.show.x = xpos
            self.show.y = ypos - self.height
            
        @property
        def x(self):
            return self.show.x
        @x.setter
        def x(self, value):
            self.show.x = value
            
        @property
        def y(self):
            return self.show.y
        @y.setter
        def y(self, value):
            self.show.y = value

    def repulsor_update(st):
        blah-blah-blah

        for i in repulsor_sprites:
            for j in repulsor_sprites2:
                if got_collision(i, j):
                    # some code to determine what sprite will die X_x
                    # then...
                    # i.show.destroy()
                    # repulsor_sprites.remove(i)
I worked on it a bit longer and I finally figured it out! I thought the 'for j in..' being contained in 'for i in...' was a mistake on your part as it caused my game to slow down massively.
For some ""optimization"", I ended up basing the speed on how slow the game is running. Basically, adds more speed; the more that are on screen.
I also added more variables to 'My_sprite' so I could have vehicles as an example.
Anyway, thanks for the help. Was stuck on this for a few days.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Majestic-12 [Bot]