Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Joe wants to know the world and the world about Joe

  1. #1

    Joe wants to know the world and the world about Joe

    I'm having some problems with my objects. Simply put I need my objects to know of eachother.

    Suppose have the following code. (/////////// marks a new unit)

    [pascal]
    unit windowUnit;

    interface

    uses worldUnit, (someMoreUnits)

    type TGameWindow = class(TObject)
    private
    (..)
    public
    (..)
    world : TWorld;
    end;

    var
    Window : TGameWindow;

    ///////////////////
    unit worldUnit;

    interface

    uses spriteUnit, (someMoreUnits);


    type TWorld = class(TObject)
    private
    (..)
    public
    Joe : TSprite;
    height : word;
    width : word;
    (...)
    end;

    /////////////////////////
    unit spriteUnit;

    interface

    uses (someMoreUnits)

    TDirection = (dLeft, dRight, dUp, dDown, dNone);

    type TSprite = class(Tobject)
    private
    x : single;
    y : single;
    direction : TDirection;
    (etc)
    public
    (etc)
    procedure move();
    end;

    (etc)

    procedure TSprite.move();
    begin
    if x < 0 then direction := dRight
    else if x > window.world.width then direction := dLeft;

    if y < 0 then direction := dUp
    else if y > window.world.height then direction := dDown;
    end;
    [/pascal]

    Ok, so I have a world that gets created in a window and in the world we have Joe. Suppose the world gives the order to move Joe from point A to B, then the move procedure of the sprite would be called.

    Here's where the problem arises. Joe has to know what the limits are of the world, otherwise he'd fall off. At some point he'll also want to know where he can walk and where he can't. Point is, currently Joe doesn't know of the world. Variable Window isn't known to him.

    How can I solve this? I've tried several things, but most of the time I got problems with circular referencing my units :?

    Thanks.

  2. #2
    Legendary Member cairnswm's Avatar
    Join Date
    Nov 2002
    Location
    Randburg, South Africa
    Posts
    1,537

    Joe wants to know the world and the world about Joe

    I asked this before as well.

    The best way I have found is.

    Unit 1
    BaseDefinition of a World

    Unit 2
    Definition of the World

    Unit 3
    Uses Unit 1
    Declares Sprite
    Has property of Type BaseWorld.

    Main game - creates World, creates Sprite and passes World to Sprite.

    I'll try put together a small example later.
    William Cairns
    My Games: http://www.cairnsgames.co.za (Currently very inactive)
    MyOnline Games: http://TheGameDeveloper.co.za (Currently very inactive)

  3. #3

    thanks!

    Quote Originally Posted by cairnswm
    I'll try put together a small example later.
    Thanks, that would be great!

  4. #4

    Re: Joe wants to know the world and the world about Joe

    Quote Originally Posted by Traveler
    How can I solve this? I've tried several things, but most of the time I got problems with circular referencing my units :?
    In my opinion this is one of the worst problems of ObjectPascal. You can't have classes referencing each other from different units. This badly limits how you can structure a program.

    One solution i've used is declaring an abstract supertype for each class. I put all this abstract declarations on a single unit (kind of an interface to the game logic), and then i make different units for each class that derive and implement the single abstract classes.

    Code:
    unit main;
    
     TWorld = abstract class
       items&#58;list of TItem
       ....
     end
     TItem = abstract class
      world&#58; TWorld
      ...
     end;
    Then:
    Code:
    unit worldunit
    uses main;
    TWorldImpl = class &#40;TWorld&#41;
     ...
    end;
    //////////////////
    unit itemunit
    uses main;
    TItemImpl = class &#40;TItem&#41;
     ...
    end;
    This works and also helps keep things decoupled, but is a little verbose.. So sometimes i just end up having all in the same unit.. So much for modularization!
    If you save your data in a proprietary format, the owner of the format owns your data.
    <br /><A href="http://msx80.blogspot.com">http://msx80.blogspot.com</A>

  5. #5

    Re: Joe wants to know the world and the world about Joe

    Quote Originally Posted by Traveler
    Ok, so I have a world that gets created in a window and in the world we have Joe. Suppose the world gives the order to move Joe from point A to B, then the move procedure of the sprite would be called.

    Here's where the problem arises. Joe has to know what the limits are of the world, otherwise he'd fall off. At some point he'll also want to know where he can walk and where he can't. Point is, currently Joe doesn't know of the world. Variable Window isn't known to him.

    How can I solve this? I've tried several things, but most of the time I got problems with circular referencing my units :?

    Thanks.
    In this case, it would be solved by adding

    uses worldunit, windowunit;

    immediately after the implementation keyword in spriteunit. You are getting circular references because you are adding to the uses clause in the interface section when actually half of the units could be specified in the uses clause in the implementation section.

    The uses clause in the interface section should only include units that are required for type, variable and procedure/function declarations that appear in the interface section. All other units that are only required in the implementation go in the uses clause of the implementation section.

    If you have the case where two classes reference each other, eg.
    [pascal]type
    TClass1 = class
    FClass2: TClass2;
    end;

    TClass2 = class
    FClass1: TClass1;
    end;[/pascal]
    then you have no choice but to place both classes in the same unit with a forward declaration for TClass2 prior to the declaration of TClass1.

  6. #6

    Joe wants to know the world and the world about Joe

    just have the sprite to have a pointer reference to the window and then typecast it

    You can then have a line just under implementation which says:

    uses windowunit;

    this way you avoid abstracted classes and cirkular references
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  7. #7

    Joe wants to know the world and the world about Joe

    Thanks for all the replies.
    I can't believe the answer in this case was so simple!

  8. #8
    Legendary Member cairnswm's Avatar
    Join Date
    Nov 2002
    Location
    Randburg, South Africa
    Posts
    1,537

    Joe wants to know the world and the world about Joe

    MSX's reply is exactly what I was going to suggest.

    I dont like the pointer idea as it make the code more difficult to read and maintain. (You may as well use C++ then)

    If you one class has a single global reference its also possible to refer to it by variable instead of a property in the child class (usefull for Screen manipulation type stuff).
    William Cairns
    My Games: http://www.cairnsgames.co.za (Currently very inactive)
    MyOnline Games: http://TheGameDeveloper.co.za (Currently very inactive)

  9. #9

    Joe wants to know the world and the world about Joe

    Thanks! I'll have a look at that solution as well.

  10. #10

    Joe wants to know the world and the world about Joe

    Look at the sources of the FreePascal RTL. The actual units there are split to multitudes of .inc files.

    I often use the strategies borrowed from C. The class declaration in one .inc file, the class implementation in the other .inc file, and a lot of these {$include ...}d into the same unit. With Pascal's famous compilation speed this strategy works just finely.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •