Python Forum
Need help figuring out Sprite.Group Collision code
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Need help figuring out Sprite.Group Collision code
#1
OK, so in my "sim" I've managed to assign "cells" or agents to a sprite group, and plants (for cells to eat and obtain food) into another group. After scouring google I came up with the following to process collisions in a manner that each plant give its unique self.food value to the cell that "eats" it, increasing the cells.food (up to its limit or else skip)

However after verbosing the collision handling code, it seems I'm not actually accessing and 'feeding' the plant.food, but rather cell.food to the same cell, thereby doubling its food exponentially with hilarious results (their self.size is based on food, making them produce screen filling 'babies' who inherit half the insane amount of food lol).:

Question: How do I make it so when a "cell" object from spr_cell_group hits a "plant" object from spr_plant_group, the plant and cell in the individual collision are referenced correctly and the 'food' is provided from THAT plant to THAT cell ?

Simplified code:

spr_cell_group = sprite.Group()
spr_plant_group = sprite.Group()

class Agent(sprite.Sprite):

    def __init__(self, sense_range, size, food, maxspeed):

        sprite.Sprite.__init__(self)
        self.x = randint(0,450)
        self.y = randint(0,450)
        self.ang = 0
        self.dx = 0
        self.dy = 0
        self.speed = 0
        self.maxspeed = maxspeed
        self.food = food
        self.max_food = 300
        self.target = []
        self.age = 1
        # generic sensor range to allow it to see how large the cell is
        self.sense_range = sense_range  
        self.size = size                
        self.color = (randint(0,255), randint(0,255),randint(0,255))

        width = int(self.size)
        height = int(self.size)
        self.image = pg.Surface([width*2, height*2])
        self.image.fill(white)
        self.image.set_colorkey(white)

        pg.draw.circle (self.image, self.color, (int(width),int(height)), int(self.size))

        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y
        spr_cell_group.add(self)


class Plant (sprite.Sprite):
    def __init__(self):

        sprite.Sprite.__init__(self)
        
        self.x = randint(0,450)
        self.y = randint(0,450)
        self.age = 1 + randint(0,50)
        #varying colors 1-4
        #varying food value based on color
        self.color = 1 + randint(0,3)
        self.food = self.color * 10 + randint(1,10)
        self.size = self.food / 7

        if self.color == 1:
            color = (0,50,0)
        elif self.color == 2:
            color = (0,100,0)
        elif self.color == 3:
            color = (0,150,0)
        elif self.color == 4:
            color = (0,250,0)
            
        width = self.size
        height = self.size
        self.image = pg.Surface([width*2, height*2])
        self.image.fill(white)
        self.image.set_colorkey(white)
        
        pg.draw.circle (self.image, color, (int(width),int(height)), int(self.size))

        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y
        spr_plant_group.add(self)


# Create initial random cell animals
def populate_cells (num): 
    for x in range(num):
        smell = randint(50,75)
        size = randint(1,5)
        food = 100 + randint(-25,50)
        maxspeed = randint(1,3)
        agent.append (Agent(smell, size, food, maxspeed))

# Create initial plants (food)
def populate_plants (num): 
    for x in range(num):
        plant.append (Plant())

#.blah blah blah
#
#
def update_cells()
#stuff and thangs

def update_plants()
#stuff and thangs

# ============ SOMETHING IS WRONG BELOW WITH THE COLLISION HANDLING?

def check_collisions():
    hit_list = sprite.groupcollide(spr_cell_group, spr_plant_group, False, False)
    #if hit_list != {}:
       #print (hit_list)
    for a in hit_list:
        for p in hit_list:
            if a.food < a.max_food:
                a.food += p.food
                print(a, a.food)
                print(p, p.food)
                p.kill()
#lots of blah


# In the main loop I'm running this ---------------------

while done == False:

    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True

    screen.fill(black)

    # Debug info showing food for an agent at index [3]  
    i = 0
    if agent[i] in spr_cell_group: 
        font = pg.font.SysFont(None, 20)
        text = font.render ("Food: "+str(agent[i].food), True, white)
        screen.blit (text,(agent[i].x,agent[i].y+10))

    update_cells()
    update_plants()
    check_collisions()

    rep += 1
    if rep >= rep_limit:
        done = True
        print ("Sim completed =", done)

    spr_cell_group.draw(screen)
    spr_plant_group.draw(screen)
    
    #pg.display.update()
    pg.display.flip()
    clock.tick(60)

pg.quit()
BTW this is the output to the console from my debug messages. As you can see, everytime there is a collision, I'm supposed to be printing the a.food (the cell, hopefully?) and p.food (that is pointing to the plant?) and instead it looks like duplicates i.e. I'm feeding the cell its own food value??

=================== RESTART: C:\Python\GA_sim4_Sprites.py ===================
<Group(20 sprites)>
<Group(40 sprites)>
<Agent sprite(in 1 groups)> 151.8
<Agent sprite(in 1 groups)> 151.8
<Agent sprite(in 1 groups)> 229.00000000000006
<Agent sprite(in 1 groups)> 229.00000000000006
<Agent sprite(in 1 groups)> 287.20000000000016
<Agent sprite(in 1 groups)> 287.20000000000016
<Agent sprite(in 1 groups)> 244.00000000000023
<Agent sprite(in 1 groups)> 244.00000000000023
<Agent sprite(in 1 groups)> 161.40000000000026
<Agent sprite(in 1 groups)> 161.40000000000026
<Agent sprite(in 1 groups)> 251.40000000000038
<Agent sprite(in 1 groups)> 251.40000000000038
<Agent sprite(in 1 groups)> 143.00000000000074
<Agent sprite(in 1 groups)> 143.00000000000074
<Agent sprite(in 1 groups)> 232.8000000000011
<Agent sprite(in 1 groups)> 232.8000000000011
<Agent sprite(in 1 groups)> 252.80000000000223
<Agent sprite(in 1 groups)> 252.80000000000223
<Agent sprite(in 1 groups)> 204.00000000000273
<Agent sprite(in 1 groups)> 204.00000000000273
<Agent sprite(in 1 groups)> 139.20000000000346
<Agent sprite(in 1 groups)> 139.20000000000346
<Agent sprite(in 1 groups)> 130.2000000000035
<Agent sprite(in 1 groups)> 130.2000000000035
<Agent sprite(in 1 groups)> 146.20000000000363
<Agent sprite(in 1 groups)> 146.20000000000363
<Agent sprite(in 1 groups)> 157.4000000000039
<Agent sprite(in 1 groups)> 157.4000000000039
<Agent sprite(in 1 groups)> 180.00000000000625
<Agent sprite(in 1 groups)> 180.00000000000625
<Agent sprite(in 1 groups)> 128.8000000000078
<Agent sprite(in 1 groups)> 128.8000000000078
<Agent sprite(in 1 groups)> 50.400000000003104
<Agent sprite(in 1 groups)> 50.400000000003104
Sim completed = True
>>> 
Reply
#2
I read your post like 3 times and still not exactly sure what you want or what is going on.

Quote: instead it looks like duplicates i.e. I'm feeding the cell its own food value??
for a and p in hit_list you are going to be multiplying its value by 2 once every element, let alone every other element.
Quote:
# ============ SOMETHING IS WRONG BELOW WITH THE COLLISION HANDLING?
 
def check_collisions():
    hit_list = sprite.groupcollide(spr_cell_group, spr_plant_group, False, False)
    #if hit_list != {}:
       #print (hit_list)
    for a in hit_list:
        for p in hit_list:
            if a.food < a.max_food:
                a.food += p.food
                print(a, a.food)
                print(p, p.food)
                p.kill()
Recommended Tutorials:
Reply
#3
Sorry I wasn't clear.
Let me repeat the main part:


Question: How do I make it so when a "cell" object from spr_cell_group hits a "plant" object from spr_plant_group, the plant and cell in the individual collision are referenced correctly and the 'food' is provided from THAT plant to THAT cell ?



I basically want to check:

IF a cell hits a plant, feed the cell the plant.food value. Kill the plant.

What's happening is as I found out, the code is somehow returning the cell's own food and the result is the cell's .food rises exponentially (instead of eating 20 food, it's eating, 100 whatever it has left, at the time of collision).
Reply
#4
Ok I figured out my mistake. I was iterating the same object twice in the for loops above that you quoted. Anyway, here is the corrected code bit:

for c in hit_list:
            for p in hit_list[c]:
                if c.food < c.max_food:
                    c.food += p.food
                    #print(c, c.food-p.food, c.food)
                    if p == c.target:
                        c.target = []
                    p.kill()
I am having a hard time grasping a lot of the way lists work, especially in situations like this where I have to use FOR loops and somehow figure out where the data I need exists, if it's an index, or an object, etc. Coming from Game Maker 6.1 way back and it's BASIC like scripting, this stuff is on another level (I am sure in a good way, giving me 100 ways to do one thing, which right now is almost overwhelming, hehe).

Now to my current problem... which is figuring out how to detect when a cell's target (plant) is no longer a valid plant or has died/eaten (and probably respawned to another location, and probably has its index changed), and re-initiating its food seeking code...But that's for another thread (?)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Star I was making code for collision for my character izmamonke 2 2,095 Aug-06-2021, 04:30 PM
Last Post: izmamonke
  SOLVED - Collision detection - TURTLE OuateDePhoque 9 11,381 Nov-18-2020, 06:29 PM
Last Post: OuateDePhoque
  bouncing ball with variable collision points (in time) Zhaleh 1 2,382 Jul-24-2020, 02:54 PM
Last Post: Marbelous
  Player object wont recognize collision with other objects. Jan_97 3 2,725 Dec-22-2019, 04:08 PM
Last Post: joe_momma
  Help figuring out why I can't install pygame Skeleton_Warrior 4 13,093 Oct-20-2019, 10:02 PM
Last Post: Skeleton_Warrior
  Collision function problem jtstewart95 2 2,767 May-02-2018, 11:44 PM
Last Post: scidam
  Union of dictionaries (taking max value on collision) meee 5 3,764 Jan-17-2018, 09:14 PM
Last Post: Mekire

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020