pygame move collide circles

6-2-2020:
Update, removing the original code, and placing in a slightly refactored and cleaned up code block.
I'm currently trying to play with the idea of a JavaScript collision detection piece of code for drawing on canvases and games, and came back to this piece to refresh my memory.   I ran the code, and it still just needs 'pygame' for it to run with Python 3 +.   The bubbles are set at high speed, so that I could test that the list cleared, and the screen started new when 200 bubbles were populating the screen area.

The main idea of doing this code was discover how in a GUI environment the code can detect and alter an item based on where it is on the screen.   I will hopefully be updating this a bit more soon, but wanted to drop in and clean the code for this up a bit since I was looking through it anyways.

The background color can be altered without any effect on the bubbles.
The bubble colors are set to stay below 240 on the 0-255 RGB scale, Because of conflicts that may arise when a new bubble is spawned by the original.  There are also conflicts with the shading, if the colors exceed 255.

Feel free to scroll down to the heading: GIMME the CODE, if you don't want to read through past updates.  I hope to make a post explaining collision with javascript soon.

As always, take it, break it, have fun.



5-29-18:
trying to make a pygame.surface circle shaped... No simple answers to be found.
Will put the code in if I figure it out.

5-29-18:
tweek to make this happen:



I only altered the move_bubble of Bubble class, and the init attributes to be able to alter color passed in (new_bubble altered for new Bubble attributes also):

class Bubble(object):
     def __init__(self, my_screen, R,G,B, pos_x, pos_y, radius, thickness, speed):
        self.my_screen = my_screen
        self.pos_x = pos_x
        self.pos_y = pos_y
        self.R = R
        self.G = G
        self.B = B

        self.radius = radius
        self.thickness = thickness
        self.speed_y = speed
        self.speed_x = speed
        self.y_charge = 1
        self.x_charge = 1


     def move_bubble(self):
        dark = (self.R - 5, self.G - 5, self.B - 5)
        light = (self.R + 5, self.G + 5, self.B + 5)
        shine = (self.R + 5, self.G + 5, self.B + 10)
        color = (self.R, self.G, self.B)

       pg.draw.circle(screen, (dark), (self.pos_x + 10, self.pos_y + 10), self.radius, self.thickness)
        pg.draw.circle(screen, (color), (self.pos_x, self.pos_y), self.radius, self.thickness)
        pg.draw.circle(screen, (light), (self.pos_x, self.pos_y -2), self.radius - 5, self.thickness)
        pg.draw.circle(screen, (shine), (self.pos_x - 5, self.pos_y -1), self.radius//2, self.thickness)


        self.pos_x += self.speed_x
        self.pos_y += self.speed_y



def new_bubble(x_pos, y_pos, radius):
    change_x = 1 * radius
    change_y = 1 * radius
    x = 100
    y = 100
    z = 100
    base_clr = 0
    place = radius * 2
    if x_pos - place <= 0:
        x += 50
    elif x_pos + place >= width:
        change_x = change_x * -1
    else:
        y += 20
    if y_pos + place >= height:
        change_y = change_y * -1
    elif y_pos - place <= 0:
        z += 50
    else:
        y += 20

There is wiggle room for color to change by 15
in total, the biggest number you can get( x,y, or z) from above is: 240 ,
I have to work on the math of this part, not sure how I get so many colors to appear...

    newx = x_pos + change_x
    newy = y_pos + change_y
    R = base_clr + x
    G = base_clr + y
    B = base_clr + z

    new_bubble = Bubble(screen, R,G,B, newx, newy, 50, 0, 3)

    return new_bubble

Original Post:

Today I was curious about how collision works,  I came up with this little pygame screen to play with collision.

It's not tested other then my manual prints and running it for a long time to see if errors popped up. I did change the size after this video so it was bigger on screen. Speed was changed to alter the movements of newbubbles opposed to the main collider bubble.  Also the code needs some major refactoring, but readers can play with it and alter it as they see fit as always.



Real easy to install pygame... for python3,  just pip3 install pygame.  Done.

New video with 200 circles.  Old circles 'pop' or go back to small set size when they get too large for collision purposes. Still working on giving it some 3D effects.  Played mostly with memory usage of it today.
Didn't find that it was using much if any significant value.



GIMME the CODE


-- Start code Block--

#!usr/bin/python3
# -*- coding: utf-8 -*-
import pygame as pg



# Setting up variables for Pygame

(width, height) = (800, 800)
background_color = (0, 0, 0)
BLUE = (20, 20, 230)
LBLUE = (100, 100, 255, 0)


# init Pygame so screen is set and ready for drawing functions
pg.init()
screen = pg.display.set_mode((width, height))
pg.display.set_caption(('Bubbles'))
screen.fill(background_color)
animation_timer = pg.time.Clock()
#pg.display.flip()


class Bubble(object):

    def __init__(self, my_screen, R,G,B, pos_x, pos_y, radius, thickness, speed):
        self.my_screen = my_screen
        self.pos_x = pos_x
        self.pos_y = pos_y
        self.R = R
        self.G = G
        self.B = B
        self.radius = radius
        self.thickness = thickness
        self.speed_y = speed
        self.speed_x = speed
        self.y_charge = 1
        self.x_charge = 1

    def alter_y(self, aninteger): 
        # change the position of bubble on Y axis, charge is the direction
        if type(aninteger) != int:
            message = "alter_y(aninteger) for class Bubble: aninteger must be type int."
            raise TypeError(message)
        else:
            charge = self.y_charge
            self.pos_y += (aninteger * charge)

    def alter_x(self, aninteger):
        # change the position of bubble on X axis, charge is the direction
        if type(aninteger) != int:
            message = "alter_x(aninteger) for class Bubble: aninteger must be type int."
            raise TypeError(message)
        else:
            charge = self.x_charge
            self.pos_x += (aninteger * charge)


    def move_bubble(self):
        # --- Maths ----- #
        #circle = 2 * Pi * radius
        #area = 2 * Pi * radius --> squared

        #rad = int(math.sqrt(self.pos_x * 3.14 * self.radius))
        #trad = int(math.sqrt(self.pos_y * 3.14 * self.radius))
        #white bright = (200,200,200)
        #dark grey = (75, 75, 75)
        dark = (self.R - 5, self.G - 5, self.B - 5)
        light = (self.R + 5, self.G + 5, self.B + 5)
        shine = (self.R + 5, self.G + 5, self.B + 10)
        color = (self.R, self.G, self.B)

        #Drawing 4 circles instead of just one, to try and give the bubble a 3D look
        pg.draw.circle(screen, (dark), (self.pos_x + 10, self.pos_y + 10), self.radius, self.thickness)
        pg.draw.circle(screen, (color), (self.pos_x, self.pos_y), self.radius, self.thickness)
        pg.draw.circle(screen, (light), (self.pos_x, self.pos_y -2), self.radius - 5, self.thickness)
        pg.draw.circle(screen, (shine), (self.pos_x - 5, self.pos_y -1), self.radius//2, self.thickness)

        self.pos_x += self.speed_x
        self.pos_y += self.speed_y

    def bubble_collide(self):
        # Check if the coordinates of the bubble intersect with the size,
        #  or boundary of the pygame screen
       
        if height < width:
            smallest = width
        else:
            smallest = height
        max_rad = smallest // 40
        rad_change = smallest // 100
        diff_x = self.radius * self.x_charge
        diff_y = self.radius * self.y_charge
        if self.pos_x + diff_x >= width or self.pos_x + diff_x <= 0:
            #print("bubble collide on x")
            self.speed_x = self.speed_x * -1
            self.x_charge = self.x_charge * -1
            if self.radius < height//4 or self.radius < width//4:
                self.radius += rad_change
            else:
                self.radius = max_rad
            return True


        if self.pos_y + diff_y >= height or self.pos_y + diff_y <= 0:
            #print("bubble collide on y")
            self.speed_y = self.speed_y * -1
            self.y_charge = self.y_charge * -1
            if self.radius < height//3 or self.radius < width//3:
                self.radius += 10
            else:
                self.radius = 50
            return True

        return False






def new_bubble(x_pos, y_pos, radius):
    # Create a new bubble with the x position, y position, and 
    # give it it's own color scheme
    change_x = 1 * radius
    change_y = 1 * radius
    x = 100
    y = 100
    z = 100
    base_clr = 0
    place = radius * 2
   
    if x_pos - place <= 0:
        x += 50
    elif x_pos + place >= width:
        change_x = change_x * -1
    else:
        y += 20
    if y_pos + place >= height:
        change_y = change_y * -1
    elif y_pos - place <= 0:
        z += 50
    else:
        y += 20




    newx = x_pos + change_x
    newy = y_pos + change_y
    R = base_clr + x
    G = base_clr + y
    B = base_clr + z
    if R > 240:
        R = 100
    if G > 240:
        G = 75
    if B > 240:
        B = 100

    color = (base_clr + x, base_clr + y,  base_clr + z)
    new_bubble = Bubble(screen, R,G,B, newx, newy, 50, 0, 3)
    return new_bubble



running = True

#LBUE tuple:
red = 100
green = 100
blue = 230
bubble_one = Bubble(screen, red, green, blue, 20, 20, 50, 0, 10)
alist = [bubble_one]

while running:
    animation_timer.tick(60)
    screen.fill(background_color)
    #shadow = pg.Surface(800, 800)
    #pg.Surface.blit(shadow, screen, BLEND_RGB)

    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
    add_bubble = False
    for bubbles in alist:
        # check collision on original bubble_one
        # bubble_one is the only one that will spawn new bubbles
        bubbles.move_bubble()
        if bubbles == bubble_one:
            if bubble_one.bubble_collide():
                #print("creating new bubble --> collision")
                spawn = new_bubble(bubbles.pos_x, bubbles.pos_y, bubbles.radius)
                spawn.x_charge = bubble_one.x_charge
                spawn.y_charge = bubble_one.y_charge
                spawn.speed_x = bubble_one.x_charge * spawn.speed_x
                spawn.speed_y = bubble_one.y_charge * spawn.speed_y
                # alternate the direction of the spawned bubbles
                if len(alist) % 2:
                    spawn.alter_x(2)
                else:
                    spawn.alter_y(2)
                add_bubble = True
        else:
            bubbles.bubble_collide()

        
    if add_bubble:
        alist.append(spawn)
        #print("alist size =============", len(alist))
    if len(alist) > 200:
        #https://stackoverflow.com/questions/850795/different-ways-of-clearing-lists
        # checking if del alist[:]
        # is a safer way to keep memory build up
        # python garbage collects, but I don't trust it
        # memory usage seems very slim... trying bigger list of bubbles
        del alist[:]
        #print("**********deleting alist[:]**********")
        alist = [bubble_one]



    pg.display.update()




-- End code Block --

Comments

Popular posts from this blog

playing with color in powershell python

JavaScript Ascii animation with while loops and console.log

playing with trigonometry sin in pygame