Recent

Author Topic: Problems with abstract class in allegro5  (Read 1984 times)

zelda16bit

  • Full Member
  • ***
  • Posts: 118
Problems with abstract class in allegro5
« on: January 10, 2023, 06:02:17 pm »
Code: Pascal  [Select][+][-]
  1.  
  2.     unit Upadre;
  3.      
  4.     {$mode objfpc}{$H+}
  5.      
  6.     interface
  7.      
  8.     uses
  9.       Allegro5,Generics.Collections;
  10.      
  11.     type
  12.       Tpadre = class
  13.         strict private
  14.           padre: Tpadre;
  15.           lista: specialize TObjectList<Tpadre>;
  16.         public
  17.           constructor Create();
  18.           procedure pintar();virtual;abstract;
  19.           procedure actualizar();
  20.           destructor Destroy(); override;
  21.       end;
  22.      
  23.     implementation
  24.      
  25.       constructor Tpadre.Create();
  26.       begin
  27.         lista := specialize TObjectList<Tpadre>.Create(True);
  28.         lista.Add(Self);
  29.       end;
  30.      
  31.       procedure Tpadre.actualizar();
  32.       begin
  33.         for padre in lista do begin
  34.           padre.pintar();
  35.         end;
  36.       end;
  37.      
  38.       destructor Tpadre.Destroy();
  39.       begin
  40.         lista.Free();
  41.         lista := nil;
  42.       end;
  43.      
  44.     end.
  45.  

Code: Pascal  [Select][+][-]
  1. unit Udisparo;
  2.  
  3. {$Mode objfpc} {$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Allegro5,Upadre;
  9.  
  10. type
  11. //prototipo clase disparo-----------------------------
  12.   Tdisparo = class(Tpadre)
  13.     strict private
  14.       imagen: ALLEGRO_BITMAPptr;
  15.       x,y: real;
  16.     public
  17.       constructor Create(x1,y1: real);
  18.       procedure pintar();
  19.       procedure mover();
  20.       procedure eliminar();
  21.       destructor Destroy(); override;
  22.   end;
  23.  
  24. //fin prototipo clase disparo-------------------------
  25.  
  26. implementation
  27.  
  28. //implementacion clase disparo-----------------------
  29.   constructor Tdisparo.Create(x1,y1: real);
  30.   begin
  31.     inherited Create();
  32.     imagen := al_load_bitmap('estrella.png');
  33.     x := x1;
  34.     y := y1;
  35.   end;
  36.  
  37.   procedure Tdisparo.pintar();
  38.   begin
  39.     mover();
  40.     eliminar();
  41.     al_draw_bitmap(imagen,x,y,0);
  42.   end;
  43.  
  44.   procedure Tdisparo.mover();
  45.   begin
  46.     y := y - 5;
  47.   end;
  48.  
  49.   procedure Tdisparo.eliminar();
  50.   begin
  51.     if(y < 64) then
  52.     begin
  53.       self.destruir();
  54.     end;
  55.   end;
  56.  
  57.   destructor Tdisparo.Destroy();
  58.   begin
  59.     al_destroy_bitmap(imagen);
  60.     imagen := nil;
  61.     inherited;
  62.   end;
  63. //fin implementacion clase disparo-------------------
  64.  
  65. end.
  66.  
  67.  

Code: Pascal  [Select][+][-]
  1. {$mode objfpc} {$H+}
  2. program alegro10;
  3.  
  4. (*
  5.   allegro5 -> biblioteca alegro
  6.   al5image -> biblioteca para imagenes
  7.   Generics.Collections -> para usar listas
  8. *)
  9.  
  10. uses
  11.   allegro5,al5image,Udisparo,Upadre;
  12.  
  13. //prototipo clase jugador-----------------------------
  14. type
  15.   Tjugador = class
  16.     strict private
  17.       imagen: ALLEGRO_BITMAPptr;
  18.       estado_de_teclas: ALLEGRO_KEYBOARD_STATE;
  19.       x,y: real;
  20.       contador: integer;
  21.       disparo: Tdisparo;
  22.     public
  23.       constructor Create();
  24.       procedure pintar();
  25.       procedure mover();
  26.       procedure disparar();
  27.       destructor Destroy(); override;
  28.   end;
  29. //fin prototipo clase jugador-------------------------
  30.  
  31. //implementacion clase jugador------------------------
  32.   constructor Tjugador.Create();
  33.   begin
  34.     imagen := al_load_bitmap('nave.png');
  35.     x := 320;
  36.     y := 240;
  37.   end;
  38.  
  39.   procedure Tjugador.pintar();
  40.   begin
  41.     mover();
  42.     disparar();
  43.     //pintamos imagen(imagen,x,y,voltear)
  44.     al_draw_bitmap(imagen,x,y,0);
  45.   end;
  46.  
  47.   procedure Tjugador.mover();
  48.   begin
  49.     al_get_keyboard_state(estado_de_teclas);
  50.     if(al_key_down(estado_de_teclas,ALLEGRO_KEY_LEFT)) then
  51.     begin
  52.       x := x - 5;
  53.     end
  54.     else if(al_key_down(estado_de_teclas,ALLEGRO_KEY_RIGHT)) then
  55.     begin
  56.       x := x + 5;
  57.     end;
  58.  
  59.     if(al_key_down(estado_de_teclas,ALLEGRO_KEY_UP)) then
  60.     begin
  61.       y := y - 5;
  62.     end
  63.     else if(al_key_down(estado_de_teclas,ALLEGRO_KEY_DOWN)) then
  64.     begin
  65.       y := y + 5;
  66.     end;
  67.   end;
  68.  
  69.   procedure Tjugador.disparar();
  70.   begin
  71.     al_get_keyboard_state(estado_de_teclas);
  72.     contador := contador + 1;
  73.     if (al_key_down(estado_de_teclas,ALLEGRO_KEY_Z)) and (contador > 10) then
  74.     begin
  75.       //crear disparo
  76.       disparo := Tdisparo.Create(x,y);
  77.       contador := 0;
  78.     end;
  79.   end;
  80.  
  81.   destructor Tjugador.Destroy();
  82.   begin
  83.     al_destroy_bitmap(imagen);
  84.     imagen := nil;
  85.     disparo.Free;
  86.     disparo := nil;
  87.   end;
  88. //fin implementacion clase jugador-------------------
  89.  
  90. var
  91.   ventana: ALLEGRO_DISPLAYptr = nil;
  92.   evento: ALLEGRO_EVENT;
  93.   cola_de_eventos: ALLEGRO_EVENT_QUEUEptr = nil;
  94.   tiempo: ALLEGRO_TIMERptr = nil;
  95.   ejecutar: Boolean;
  96.   jugador: Tjugador;
  97.   //padre: Tpadre;
  98.  
  99. begin
  100.   //iniciar allegro
  101.   al_init();
  102.   //instalar teclado
  103.   al_install_keyboard();
  104.   //iniciar imagen
  105.   al_init_image_addon();
  106.  
  107.   //configurar ventana en modo ventana
  108.   al_set_new_display_flags(ALLEGRO_WINDOWED);
  109.   //crear ventana(ancho,alto)
  110.   ventana := al_create_display(640,480);
  111.  
  112.   //ocultar raton
  113.   al_hide_mouse_cursor(ventana);
  114.  
  115.   //crear cola de eventos
  116.   cola_de_eventos := al_create_event_queue();
  117.  
  118.   //crear tiempo para fps
  119.   tiempo := al_create_timer(1/60);
  120.  
  121.   //registrar eventos
  122.   al_register_event_source(cola_de_eventos,al_get_keyboard_event_source());
  123.   al_register_event_source(cola_de_eventos,al_get_display_event_source(ventana));
  124.   al_register_event_source(cola_de_eventos,al_get_timer_event_source(tiempo));
  125.  
  126.   //inicio de variables
  127.   ejecutar := true;
  128.   jugador := Tjugador.Create();
  129.   //padre := Tpadre.Create();
  130.  
  131.   //iniciamos el tiempo
  132.   al_start_timer(tiempo);
  133.   while (ejecutar = true) do
  134.   begin
  135.  
  136.     //esperamos a la cola de eventos
  137.     al_wait_for_event(cola_de_eventos,@evento);
  138.     case evento.ftype of
  139.       //manejo de fps
  140.       ALLEGRO_EVENT_TIMER: begin
  141.         //limpiar pantalla con un color cualquiera
  142.         al_clear_to_color(al_map_rgb(0,0,160));
  143.  
  144.         jugador.pintar();
  145.         Tpadre.actualizar();
  146.  
  147.         //actualizar pantalla
  148.         al_flip_display();
  149.       end;
  150.       //si pulso escape salgo del bucle
  151.       ALLEGRO_EVENT_KEY_DOWN: begin
  152.         if (evento.keyboard.keycode = ALLEGRO_KEY_ESCAPE) then
  153.         begin
  154.           ejecutar := false;
  155.         end;
  156.       end;
  157.     end; //fin case
  158.  
  159.   end; //fin bucle while
  160.  
  161.   al_destroy_display(ventana); //destruir ventana
  162.   ventana := nil;
  163.   al_destroy_event_queue(cola_de_eventos); //destruir cola
  164.   cola_de_eventos := nil;
  165.   al_destroy_timer(tiempo); //destruir tiempo
  166.   tiempo := nil;
  167.   al_uninstall_keyboard(); //desinstalar teclado
  168.   jugador.Free(); //liberar jugador
  169.   jugador := nil;
  170.   //padre.Free;
  171.   //padre := nil;
  172.  
  173. end. //fin programa
  174.  
  175.  

I have created the abstract method paint to use it in the child classes that inherit from this, in the parent class I will not use it only in the daughters but in the update method I call it because this method will be responsible for updating all the methods to paint of all the child classes, however the compiler tells me that it can not be used and gives me an error.

There are also problems with memory freeing,I leave the file with the complete code, Allegro 5 is needed to compile.
« Last Edit: January 10, 2023, 09:39:46 pm by zelda16bit »

Eugene Loza

  • Hero Member
  • *****
  • Posts: 663
    • My games in Pascal
Re: Problems with abstract class in allegro5
« Reply #1 on: January 10, 2023, 06:17:50 pm »
Quote
however the compiler tells me that it can not be used and gives me an error

If I understand your code correctly, compiler is correct about it. While FPC will indeed let you instantiate a class with an abstract method and it should be ok if you don't use the abstract method, in your case you:

Code: Pascal  [Select][+][-]
  1. lista.Add(Self);
and then

Code: Pascal  [Select][+][-]
  1.  for padre in lista do begin
  2.   padre.pintar();
  3. end;

I.e. the Self class is in the list and you call an abstract `pintar` method on it, which is not allowed. If you really need to make something like that - just don't make `pintar` abstract, just an empty method:

Code: Pascal  [Select][+][-]
  1. procedure Tpadre.pintar;
  2. begin
  3. end;

and then override it in children to make something more useful there.
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

zelda16bit

  • Full Member
  • ***
  • Posts: 118
Re: Problems with abstract class in allegro5
« Reply #2 on: January 10, 2023, 09:44:49 pm »
I have added all the code from my example, the problem with the abstract method has been solved with what you have told me, but another problem has arisen. The parent class update method when I call it from the main file I get a generic.collection error.
« Last Edit: January 10, 2023, 09:50:06 pm by zelda16bit »

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Problems with abstract class in allegro5
« Reply #3 on: January 12, 2023, 06:03:11 pm »
I've downloaded and tested your program and I have no problem at all.

Debian GNU/Linux 11 + Lazarus 2.2.4 + FPC 3.2.2 + Allegro.pas 5.2.β.1.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

zelda16bit

  • Full Member
  • ***
  • Posts: 118
Re: Problems with abstract class in allegro5
« Reply #4 on: January 13, 2023, 05:59:35 pm »
That's because I have commented this line //Tpadre.update(); In the while loop, if you do not comment you will see that the problems begin. You will also see that pressing z does not shoot anything, uncomment and you will see

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Problems with abstract class in allegro5
« Reply #5 on: January 15, 2023, 12:05:52 pm »
Maybe that is because you didn't added any object to the TPadre list.  I'm not sure though.

Also, it isn't the problem, but it is a bad idea to use a global variable as a target of a for .. in loop.  Use a local one instead.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

 

TinyPortal © 2005-2018