OK, I've realised that I'm not a good programmer..

Miscellaneous Forums/General Discussion/OK, I've realised that I'm not a good programmer..

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

I think using a separate type for the bubbles in the circle is a good idea. This way, you can use Blitz's builtin list to keep track of the order of the bubbles in the circle. When you fire a bubble at the circle, you can Insert the new bubble into the correct location.

Here's a quick hack of the general idea:

const BUBBLE_RADIUS = 20
const POPPING_THRESHOLD = 3

type circle_bubble
	field colour_index%
end type

type middle_bubble
	field colour_index%
end type

global circle_bubble_count%
global circle_origin_angle_offset#
global middle_bubble.middle_bubble

function create_circle_bubble.circle_bubble(colour_index% = -1)
	eb.circle_bubble = new circle_bubble
	if colour_index = -1 then colour_index = rand(1, 7)
	eb\colour_index = colour_index
	circle_bubble_count = circle_bubble_count + 1
	return eb
end function

function destroy_circle_bubble(eb.circle_bubble)
	delete eb
	circle_bubble_count = circle_bubble_count - 1
end function

function find_circle_bubble_at_position.circle_bubble(index%)
	this_bubble.circle_bubble = first circle_bubble
	for i = 0 to index - 1
		this_bubble = after this_bubble
	next
	return this_bubble
end function

function find_angle_of_bubble(this_bubble.circle_bubble)
	ang# = circle_origin_angle_offset
	for b.circle_bubble = each circle_bubble
		if b = this_bubble then return ang
		ang = ang + 360.0 / circle_bubble_count
	next
end function

function create_middle_bubble()
	middle_bubble = new middle_bubble
	middle_bubble\colour_index = rand(1, 7)
end function

function correct_circle_offset(insertion_ang#, bubbles_added%)
	; this is all wrong!
	;effect# = (constrain_0_to_360(insertion_ang) - 180) / 180
	;circle_origin_angle_offset = circle_origin_angle_offset - bubbles_added*BUBBLE_RADIUS/2 * -effect
end function



; init
graphics 800, 600
setbuffer backbuffer()

for i = 1 to 20
	create_circle_bubble()
next
create_middle_bubble()

; game loop
while not keyhit(1)
	update_game()
	draw_world()
wend
end

function update_game()
	circle_origin_angle_offset = circle_origin_angle_offset + 1

	if mousehit(1) then
		mx# = mousex() - graphicswidth() / 2
		my# = mousey() - graphicsheight() / 2
		local firing_angle#
		if my <> 0 then
			firing_angle = atan(mx / my)
			if my < 0 then firing_angle = firing_angle + 180
		else
			if mx > 0 then firing_angle = 90 else firing_angle = 270
		endif

		firing_angle = constrain_0_to_360(firing_angle - circle_origin_angle_offset)

		strike_after_index% = floor(firing_angle / (360.0 / circle_bubble_count)) + 1
		bubble_before.circle_bubble = find_circle_bubble_at_position(strike_after_index)

		correct_circle_offset(find_angle_of_bubble(bubble_before) + 360.0 / circle_bubble_count / 2, 1)

		new_bubble.circle_bubble = create_circle_bubble(middle_bubble\colour_index)
		if bubble_before <> null then insert new_bubble before bubble_before

		delete middle_bubble
		create_middle_bubble()
		
		check_for_poppage(new_bubble)
	endif
end function

function check_for_poppage(bubble_to_check.circle_bubble)

	bubbles_to_pop% = 1
	first_bubble_to_pop.circle_bubble = bubble_to_check
	last_bubble_to_pop.circle_bubble = bubble_to_check
	
	while true
		test_bubble.circle_bubble = before first_bubble_to_pop
		if test_bubble = null then test_bubble = last circle_bubble
		if test_bubble\colour_index <> first_bubble_to_pop\colour_index then exit
		if test_bubble = last_bubble_to_pop then exit
		first_bubble_to_pop = test_bubble
		bubbles_to_pop = bubbles_to_pop + 1
	wend
	while true
		test_bubble.circle_bubble = after last_bubble_to_pop
		if test_bubble = null then test_bubble = first circle_bubble
		if test_bubble\colour_index <> last_bubble_to_pop\colour_index then exit
		if test_bubble = first_bubble_to_pop then exit
		last_bubble_to_pop = test_bubble
		bubbles_to_pop = bubbles_to_pop + 1
	wend

	if bubbles_to_pop >= POPPING_THRESHOLD then
		popping_angle# = (find_angle_of_bubble(first_bubble_to_pop) + find_angle_of_bubble(last_bubble_to_pop)) / 2
		correct_circle_offset(popping_angle, -bubbles_to_pop)

		doomed_bubble.circle_bubble = first_bubble_to_pop
		repeat
			next_bubble.circle_bubble = after doomed_bubble
			if next_bubble = null then next_bubble = first circle_bubble
			destroy_circle_bubble(doomed_bubble)
			doomed_bubble = next_bubble
		until last_bubble_to_pop = null
		
		; check if we just closed a gap on more bubbles to pop
		if doomed_bubble <> null then check_for_poppage(doomed_bubble)
	endif

end function

function draw_world()
	cls

	circle_circumference = circle_bubble_count * BUBBLE_RADIUS * 2
	circle_radius# = circle_circumference / PI / 2
	eb_index% = 0
	
	for eb.circle_bubble = each circle_bubble
		ang# = eb_index * 360.0 / circle_bubble_count + circle_origin_angle_offset
		x = sin(ang) * circle_radius + graphicswidth() / 2
		y = cos(ang) * circle_radius + graphicsheight() / 2

		set_colour_by_index(eb\colour_index)
		oval(x-BUBBLE_RADIUS, y-BUBBLE_RADIUS, BUBBLE_RADIUS*2, BUBBLE_RADIUS*2)
	
		eb_index = eb_index + 1
	next

	x = graphicswidth() / 2
	y = graphicsheight() / 2
	set_colour_by_index(middle_bubble\colour_index)
	oval(x-BUBBLE_RADIUS, y-BUBBLE_RADIUS, BUBBLE_RADIUS*2, BUBBLE_RADIUS*2)

	flip
end function

function set_colour_by_index(colour_index%)
	if colour_index = 1 then color(255,   0,   0)
	if colour_index = 2 then color(  0, 255,   0)
	if colour_index = 3 then color(255, 255,   0)
	if colour_index = 4 then color(  0,   0, 255)
	if colour_index = 5 then color(255,   0, 255)
	if colour_index = 6 then color(  0, 255, 255)
	if colour_index = 7 then color(255, 255, 255)
end function

function constrain_0_to_360#(ang#)
	while ang < 0 : ang = ang + 360 : wend
	ang = ang mod 360
	return ang
end function


I can't figure out the correct math for the correct_circle_offset() routine, which is supposed to be responsible for making the circle expand or contract equally on both sides of an insert or pop, instead of leaving the first bubble always in the same place.

Hopefully this is useful to you.