PDA

View Full Version : Overriding Twice



dazappa
12-01-2010, 04:42 AM
System: Windows Vista
Compiler/IDE: Lazarus .9.28.2, FPC 2.2.4
Libraries/API: Andorra 2D (Not quite relevant, please try to ignore the superfluous code that deals with Andorra if you can.)

Well, I'm trying to flesh out a very flexible system at the moment for game development with Andorra, but to do so, I need to override some key procedures that are already overridden...

Here is the current class, taken from a tutorial and modified very slightly.

TSpr = class(TImageSpriteEx)
protected
procedure DoMove(timegap:double);override;
procedure DoDraw;override;
public
procedure onDraw;virtual;

col:boolean;
xspeed,yspeed: integer;
end;

The thing is, I have other units that create instances of TSpr, but I'd like to override DoDraw again, for example.

Instantiating a TSpr:

spr := TSpr.Create(engine);
with spr do
begin
Image := gui.Items[1];
X := 0;
Y := 0;
CollisionTester := ColTest;
end;

What I would like to do would be something along the lines of

spr := TSpr.Create(engine);
elGUI.add(spr);
with spr do
begin
Image := gui.Items[1];
X := 0;
Y := 0;
CollisionTester := ColTest;
DoDraw := SecondOverride;
end;

procedure SecondOverride;
begin
Color := rgb(200,200,200);
end;

The idea is that there would be one main "object" class, where I can specify which functions handle collisions, drawing, and so on, while also having that main object track some variables such as the current x and y speeds.

With my hacked up idea above, a few things:
1. Is that even possible?
2. If that code was even going to work, wouldn't I have to make a class of TSpr, and change it to procedure TSpr.SecondOverride; ?
3. PS: Color is a property of TImageSpriteEx, and thus of TSpr, so the thing I'd hope is that if I was able to override this function again, it would realize that Color was a property of TSpr which is a property of TImageSpriteEx, so I'd be able to throw that variable in there and have it affect the image as expected.

The other idea that I had, that I've now thrown out would be this:
(Forward declaration of DoDraw of TSpr, how it currently is)

procedure TSpr.DoDraw;
begin
if not col then
Color := rgb(200,200,200);
inherited;
Color := rgb(255,255,255);
end;

I was thinking (and tried) doing this:

procedure TSpr.DoDraw;
begin
onDraw;
inherited;
end;

procedure TSpr.onDraw;
begin
if not col then
Color := rgb(200,200,200);
Color := rgb(255,255,255);
end;

But this resulted in the TSpr not being visible at all.

Still learning! Thanks for your patience.

User137
12-01-2010, 10:02 AM
onDraw approach is propably what you are after. I'll try show you the details.

[quote=dazappa ]
type
TDrawProcedure = procedure();
// add "of object" at end if you want to define procedure in a class
// and you propably do want.. so onDraw knows the sprite's variables

TSpr = class(TImageSpriteEx)
protected
procedure DoMove(timegap:double); override;
procedure DoDraw; override;
public
onDraw: TDrawProcedure; // It is a pointer to procedure

col:boolean;
xspeed,yspeed: integer;
end;



spr := TSpr.Create(engine);
elGUI.add(spr);
with spr do
begin
Image := gui.Items[1];
X := 0;
Y := 0;
CollisionTester := ColTest;
onDraw := SecondOverride;
end;

procedure SecondOverride;
begin
Color := rgb(200,200,200);
end;



procedure TSpr.DoDraw;
begin
if assigned(onDraw) then onDraw;
inherited;
end;

dazappa
12-01-2010, 07:49 PM
Hi, yes I would like SecondOverride to know of the sprite's variables, so I defined it as procedure of object. However, I'm fairly sure it needs tweaking to make it work with procedure of object, as just changing it to a procedure of object gives a compilation error (which I was not able to solve with trusty Google): "Main.pas(134,26) Error: Incompatible types: got "DecondOverride;" expected "<procedure variable type of procedure of object;Register>"" Where the line contains the onDraw:=SecondOverride;

The code you did provide so far is compilable, however. It's just not useful if I have no access to the variables ;).

- Thanks for the help so far.

User137
12-01-2010, 11:17 PM
Object procedures are defined in the class like mentioned.

so Not this:
procedure SecondOverride;
begin
Color := rgb(200,200,200);
end;

but this works:
type
TMySprite = class(TSpr)
public
procedure SecondOverride; // It's defined within class, not in unit functions
end;

procedure TMySprite.SecondOverride;
begin
Color := rgb(200,200,200);
end;
...
spr := TMySprite.Create(engine);
with spr do
begin
onDraw := SecondOverride;
end;

dazappa
13-01-2010, 01:04 AM
Hm, I was in the middle of doing that too. (I wasn't sure if you could have a class of a class, but wanted to try because it made sense for this)

When I do assign SecondOverride (through "spr.onDraw := TMySprite.secondOverride;"), it seg faults on that line where it sets the color variable... to narrow it down, I just used another variable, "Alpha := 255;" to make sure the rgb function wasn't the cause, but it seems that any variable of the parent's parent (TImageSpriteEx) causes the crash. I believe I can set the parent's variables just fine (like xspeed)

Is that typical for this type of situation? I believe I could devise some sort of dirty workaround, but just wanted to double check.

I believe this one is my own fault, although I'm not sure exactly why setting the Alpha/Color variables in certain areas causes the seg fault, but doesn't in others (If I set Alpha in the actual DoDraw event, and not a function called from it, it works, as well as setting the Alpha during Andorra's drawing procedure)... but this is probably more on the side of an Andorra tweak now.