PROGRAM Bouncing; (* Simple animated example. *) USES allegro5, al5font, al5image, al5primitives; TYPE BOUNCER_TYPE = ( BT_HELLO = 0, BT_MYSHA, BT_TRIANGLE, BT_RECTANGLE_1, BT_RECTANGLE_2, BT_CIRCLE, BT_LINE1, BT_LINE2 ); BOUNCER = RECORD x, y: REAL; dx, dy: REAL; bType: BOUNCER_TYPE; END; (* Helper to test intialization. *) PROCEDURE MustInit (aTest: BOOLEAN; aDescription: STRING); BEGIN IF NOT aTest THEN BEGIN WriteLn ('couldn''t initialize ', aDescription, '.'); WriteLn ('Press [Enter] to close.'); ReadLn; Halt (1) END END; (* Helper to assign vertex. *) FUNCTION CreateVertex (CONST x, y: REAL; CONST Color: ALLEGRO_COLOR) : ALLEGRO_VERTEX; INLINE; BEGIN CreateVertex.x := x; CreateVertex.y := y; CreateVertex.z := 0; CreateVertex.u := 0; CreateVertex.v := 0; CreateVertex.color := Color END; VAR Timer: ALLEGRO_TIMERptr; Queue: ALLEGRO_EVENT_QUEUEptr; Event: ALLEGRO_EVENT; Display: ALLEGRO_DISPLAYptr; Font: ALLEGRO_FONTptr; Redraw, EndProgram: BOOLEAN; Mysha: ALLEGRO_BITMAPptr; Obj: ARRAY [0..ORD (BT_LINE2)] OF BOUNCER; v: ARRAY [0..3] OF ALLEGRO_VERTEX; Ndx: INTEGER; BEGIN { Initialization. } MustInit (al_init, 'Allegro'); MustInit (al_install_keyboard, 'keyboard'); Timer := al_create_timer (1.0 / 30.0); MustInit (Assigned (Timer), 'timer'); { Create display. } al_set_new_display_option (ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option (ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST); al_set_new_bitmap_flags (ALLEGRO_MIN_LINEAR OR ALLEGRO_MAG_LINEAR); Display := al_create_display (640, 480); MustInit (Assigned (Display), 'display'); { Init/load graphics. } Font := al_create_builtin_font; MustInit (Assigned (Font), 'font'); MustInit (al_init_image_addon, 'image addon'); Mysha := al_load_bitmap ('mysha.png'); MustInit (Assigned (Mysha), 'mysha'); MustInit (al_init_primitives_addon, 'primitives'); { Create event queue. } Queue := al_create_event_queue; MustInit (Assigned (Queue), 'queue'); al_register_event_source (Queue, al_get_keyboard_event_source); al_register_event_source (Queue, al_get_display_event_source(Display)); al_register_event_source (Queue, al_get_timer_event_source (Timer)); { Initialize bouncers. } Randomize; FOR Ndx := LOW (Obj) TO HIGH (Obj) DO BEGIN Obj[Ndx].x := Random (640); Obj[Ndx].y := Random (480); Obj[Ndx].dx := ((Random (65635) / 65635) - 0.5) * 2 * 4; Obj[Ndx].dy := ((Random (65635) / 65635) - 0.5) * 2 * 4; Obj[Ndx].bType := BOUNCER_TYPE (Ndx); END; { Initialize loop stuff. } Redraw := TRUE; EndProgram := FALSE; al_start_timer (Timer); { Main loop. } REPEAT al_wait_for_event (Queue, @Event); CASE Event.ftype OF ALLEGRO_EVENT_TIMER: BEGIN { Update bouncers. } FOR Ndx := LOW (Obj) TO HIGH (Obj) DO BEGIN Obj[Ndx].x := Obj[Ndx].x + Obj[Ndx].dx; Obj[Ndx].y := Obj[Ndx].y + Obj[Ndx].dy; IF Obj[Ndx].x < 0 THEN Obj[Ndx].dx := Obj[Ndx].dx * (-1); IF Obj[Ndx].x > 640 THEN Obj[Ndx].dx := Obj[Ndx].dx * (-1); IF Obj[Ndx].y < 0 THEN Obj[Ndx].dy := Obj[Ndx].dy * (-1); IF Obj[Ndx].y > 480 THEN Obj[Ndx].dy := Obj[Ndx].dy * (-1); END; Redraw := TRUE END; ALLEGRO_EVENT_KEY_DOWN, ALLEGRO_EVENT_DISPLAY_CLOSE: { Close the program. } EndProgram := TRUE; END; { If must redraw and there's nothing pending... } IF Redraw AND al_is_event_queue_empty (Queue) THEN BEGIN al_clear_to_color (al_map_rgb (0, 0, 0)); { Draw bouncers. } FOR Ndx := LOW (Obj) TO HIGH (Obj) DO BEGIN CASE Obj[Ndx].bType OF BT_HELLO: al_draw_text ( Font, al_map_rgb (255, 255, 255), Obj[Ndx].x, Obj[Ndx].y, 0, 'Hello world!' ); BT_MYSHA: al_draw_bitmap (Mysha, Obj[Ndx].x, Obj[Ndx].y, 0); BT_TRIANGLE: al_draw_filled_triangle ( Obj[Ndx].x, Obj[Ndx].y, Obj[Ndx].x + 50, Obj[Ndx].y + 25, Obj[Ndx].x, Obj[Ndx].y + 50, al_map_rgb_f (0, 1, 0) ); BT_RECTANGLE_1: al_draw_filled_rectangle ( Obj[Ndx].x, Obj[Ndx].y, Obj[Ndx].x + 100, Obj[Ndx].y + 80, al_map_rgba_f (0, 0, 0.5, 0.5) ); BT_RECTANGLE_2: BEGIN v[0] := CreateVertex ( Obj[Ndx].x, Obj[Ndx].y, al_map_rgb_f (1, 0, 0) ); v[1] := CreateVertex ( Obj[Ndx].x + 120, Obj[Ndx].y, al_map_rgb_f (0, 1, 0) ); v[2] := CreateVertex ( Obj[Ndx].x, Obj[Ndx].y + 100, al_map_rgb_f (0, 0, 1) ); v[3] := CreateVertex ( Obj[Ndx].x + 120, Obj[Ndx].y + 100, al_map_rgb_f (0, 0, 1) ); al_draw_prim (v, Nil, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP) END; BT_CIRCLE: al_draw_circle (Obj[Ndx].x, Obj[Ndx].y, 30, al_map_rgb_f (1, 0, 1), 2); BT_LINE1: al_draw_line ( Obj[Ndx].x, Obj[Ndx].y, Obj[Ndx].x + 20, Obj[Ndx].y + 100, al_map_rgb_f (1, 0, 0), 1 ); BT_LINE2: al_draw_line ( Obj[Ndx].x, Obj[Ndx].y, Obj[Ndx].x + 70, Obj[Ndx].y -20, al_map_rgb_f (1, 1, 0), 1 ); END END; { Drawing was done in a backbuffer. } al_flip_display; { Updated. } Redraw := FALSE END UNTIL EndProgram; { Release resources. } al_destroy_bitmap (mysha); al_destroy_font (Font); al_destroy_display (Display); al_destroy_timer (Timer); al_destroy_event_queue (Queue) END.