Pastey Bouncing balls
- Posted by irv
Aug 17, 2019
include GtkEngine.e
include GtkCairo.e
constant fps = 60
integer frameCounter = 0
enum X,Y,RAD,XSPD,YSPD,COLOR
object balls = {{10,20,20,6,4,"red"},{30,30,20,5,4,"green"}}
constant rad360 = 6.283185307179586 -- full circle in radians;
constant
disp = create(GdkDisplay),
scrn = get(disp,"default screen"),
win = create(GtkWindow,"title=Bouncing Ball,size=800x450,border=10,$destroy=Quit"),
pan = create(GtkBox,"orientation=vertical,spacing=10"),
screen = create(GtkDrawingArea,"background=white"),
lbl = create(GtkLabel),
box = create(GtkButtonBox),
btn1 = create(GtkButton,"gtk-quit","Quit"),
btn2 = create(GtkToggleButton,"Pause","Update"),
tic = create(GTimeout,1000/fps,call_back(routine_id("Update"))),
tok = create(GTimeout,1000,call_back(routine_id("ResetCounter")))
add(win,pan)
pack(pan,screen,1,1)
add(box,{btn1,lbl,btn2})
pack(pan,-box)
show_all(win)
integer screen_width, screen_height
{screen_width,screen_height} = get(win,"size") -- allow for window borders;
for i = 1 to length(balls) do
balls[i][X] = rand(screen_width) / 2
balls[i][Y] = rand(screen_height) / 2
end for
main()
---------------------------------
global function ResetCounter() -- reset value for fps display;
-------------------------------
set(lbl,"text",sprintf("%d fps",frameCounter))
frameCounter = 0
return 1
end function
----------------------------------------------
function CollideCircles(object A, object B) --
----------------------------------------------
atom x = A[X] - B[X]
atom y = A[Y] - B[Y]
atom centerDistanceSq = x * x + y * y -- squared distance
atom radius = A[RAD] + B[RAD]
atom radiusSq = radius * radius
return centerDistanceSq <= radiusSq
end function
-------------------------------------------
global function Update(atom ctl, atom data) --
----------------------------------------------
if get(btn2,"active") then -- pause button is depressed;
return 1
end if
{screen_width,screen_height} = get(win,"size") - {20,60} -- in case changed;
for i = 1 to length(balls) do
balls[i][X] += balls[i][XSPD]
balls[i][Y] += balls[i][YSPD]
if (balls[i][X] <= balls[i][RAD]) or (balls[i][X] >= screen_width - balls[i][RAD]) then
balls[i][XSPD] *= -1
end if
if (balls[i][Y] <= balls[i][RAD]) or (balls[i][Y] >= screen_height - balls[i][RAD]) then
balls[i][YSPD] *= -1
end if
end for
if CollideCircles(balls[1],balls[2]) then
balls[1][XSPD] *= -1
balls[1][YSPD] *= -1
balls[2][XSPD] *= -1
balls[2][YSPD] *= -1
end if
frameCounter += 1
atom cr = create(GdkCairo_t,get(screen,"window"))
set(cr,{ -- clear screen;
{"source rgba",255,255,255,255},
{"operator",CAIRO_OPERATOR_SOURCE},
{"paint"}})
for i = 1 to length(balls) do
set(cr,{ -- draw ball A
{"color",balls[i][COLOR]},
{"arc", balls[i][X], balls[i][Y], balls[i][RAD], 0, rad360}, -- full circle;
{"fill"}})
end for
set(cr,"destroy")
return 1
end function