home *** CD-ROM | disk | FTP | other *** search
- { SPX Library Version 1.0 Copyright 1993 Scott D. Ramsay }
-
- SPX_OBJ is the object handling unit. It allows a easy way to
- keep track of multiple objects. I'm assuming you know alittle about
- Dynamic data structures with linked list and OOP. I don't know of
- any good books I'd recommend. But I'm sure anything would be helpful.
- "And in schooll I thought that I'd never use linked lists in real life. ;) "
-
- Each object is a descendent of TOBJS. All objects are added to a
- double linked list for the dynamic creation of numerous objects. When
- removing objects from the list, we add the node to a 'kill' list which
- we can quickly deallocate multiple objects.
-
- Plist: Is our double linked pointer type which its data points to a TOBJS
-
- Type
- Pobjs = ^Tobjs;
- Plist = ^Tlist;
- Tlist = record
- item : pobjs;
- prev,next : plist;
- end;
-
- Here is the basic structure of the linked lists. Brackets [] specifies
- actual records or objects.
-
- var
- head,tail : Plist; { Head/Tail pointers to our object list }
- kill : Pkill; { Our kill list }
-
- |- Tail
- \|/
- Head --> [Node1] <--> [Node2] <--> [Node3] <--> [Node4] --> NIL
- | | | |
- [Tobj] [Tobj] [Tobj] [Tobj]
-
-
- Kill --> [Knode1] --> [Knode2] --> NIL
- | |
- \|/ \|/
- [Node2] [Node4]
-
-
- In the above example we have four objects in our list. With the
- second and third node in the kill list (ready to be deleted).
-
- That's basically the structure. To do calcuations on each object, we
- just traverse the double linked list. Lets say that the object at Node2
- was a space alien and was shot. Ok its dead, so we add it to the kill list.
-
- After one iteration, usually the Kill list is traversed deallocating each
- Node(n) from our double linked list.
-
- pkill = ^tkill;
- tkill = record
- tk : plist; { TK - plist pointer To Kill }
- next : pkill;
- end;
-
- ───────────────────────────────────────────────────────────────────────────
- Type
- TObjs = object;
-
- Generic object type. TObjs is the base for all objects that
- need to be handled.
-
- VARIABLES:
- powner:plist A pointer to the object's node in the linked list;
- killed:boolean TRUE if the object was added to a kill list;
- cankill:boolean Set to TRUE if allowing the object to be added to
- the kill list. (See checkhit for better descript);
- overshow:boolean In my games I traverse the list twice. The first
- time is to display the objects that will be behind
- my character, the second time is for the objects
- that are above my character. Set OVERSHOW to
- TRUE for the object to be an over character.
- (In the game RSQUID, the cloud objects are set
- to TRUE "Always in front", all other objects are
- set to FALSE. "Behind my main character";
- id:integer For each object type I assign a unique number. This
- is incase I need to find certain objects while
- traversing the list
-
- METHODS:
-
- ---------------------------------------------------
- constructor Tobjs.init;
-
- Sets up the object
-
- DEFAULTS:
- KILLED set to FALSE
- ID set to 0
- OVERSHOW set to TRUE
-
- OVERRIDE: often
-
- Here is how you add an object to the linked list;
-
- var
- p : plist;
- begin
- new(p); { Create a new node }
- p^.item := new(Pobjs,init);{ Create the object }
- p^.item^.powner := p; { IMPORTANT! have the object point to its node }
- addp(head,tail,p); { Add the node to the list }
- end;
-
- See the procedure Add2Kill_list for reason for " p^.item^.powner := p;"
- ---------------------------------------------------
- procedure TObjs.drawitemobject;
-
- Displays the item.
-
- OVERRIDE: often
-
- Tobjs.drawitemobject is an empty function. In your drawitemobject
- function it will usually draw a sprite.
-
- ---------------------------------------------------
- procedure TObjs.calcitemobject;
-
- Does any calcuations to the object such as changing the object's
- position.
-
- OVERRIDE: often
-
- ---------------------------------------------------
- function TObjs.checkhit(hx,hy:integer;var item:pobjs):boolean;
-
- Return TRUE if hx,hy is in range of an object.
-
- HX,HY: Location to check;
- ITEM: Tobjs that it is in conflict with
-
- OVERRIDE: often
-
- For example:
-
- function TMyObject.checkhit(hx,hy:integer;var item:pobjs):boolean;
- begin
- checkhit := (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10);
- end;
-
- This is basically a collision detection function. For example,
- Lets assume we have a Tbullet object (desendant of Tobjs) that wants
- to check if it hit anyother objects in the list. In the procedure
- Tbullet.calcitemobject we would traverse the linked list calling
- the checkhit function for each object in the list. If the function
- returns TRUE, then the object collided with the object.
-
- procedure Tbullet.calcitemobject;
- var
- p : plist;
- begin
- p := head;
- while p<>nil do
- begin
- { Don't check for colliding bullets or dead objects }
- if (p^.item^.id<>id_bullet) and not p^.item^.killed
- then
- if p^.item^.checkhit(bullet_x,bullet_y,@self)
- then { we hit the object! }
- p := p^.next;
- end;
- end;
-
- ---------------------------------------------------
- destructor TObjs.done;
-
- Deallocates the object;
-
- OVERRIDE: sometimes
-
- ───────────────────────────────────────────────────────────────────────────
- procedure addp(var nkbeg,nkend,p:plist);
-
- Add a node to the linked list
-
- NKBEG: Linked list Head pointer;
- NKEND: Linked list Tail pointer;
- P: Node to add to the list
-
- ───────────────────────────────────────────────────────────────────────────
- procedure deletep(var nkbeg,nkend,p:plist);
-
- Delete a note from the list and deallocate the object connected to it
-
- NKBEG: Linked list Head pointer;
- NKEND: Linked list Tail pointer;
- P: Node to delete to the list
-
- ───────────────────────────────────────────────────────────────────────────
- procedure calcitems(var nkbeg:plist);
-
- Traverses a linked list calling the node's object's calcitemobject method
-
- NKBEG: Linked list Head pointer
-
- NOTE: Still calls method even if the KILLED flag it true.
-
- ───────────────────────────────────────────────────────────────────────────
- procedure drawitems(var nkbeg:plist;over:boolean);
-
- Traverses a linked list calling the node's object's drawitem object method
-
- NKBEG: Linked list Head pointer
- OVER: Set to TRUE to call only objects with OVERSHOW set to TRUE
- Set to FALSE to call only objects with OVERSHOW set to FALSE
-
- ───────────────────────────────────────────────────────────────────────────
- procedure add2kill_list(var kill:pkill;var i:plist);
-
- Adds a node to the kill list and sets the object's KILLED flag to TRUE.
-
- KILL: Kill list to add the node;
- I: Node to add to the kill list
-
- This procedure is usually called with in a object's calcitemobject or
- checkhit methods. Since this is the case, you CAN'T deallocate a
- object while still in the object's method. So by adding the node/object
- to a kill list. One can remove the object later.
-
- Each object has a pointer to its node (powner) that is passed to the
- kill list.
-
- Example:
-
- function TMyObject.checkhit(hx,hy:integer;var item:pobjs):boolean;
- begin
- if (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10)
- then
- begin
- checkhit := true;
- add2kill_list(kill,powner);
- end
- else checkhit := false;
- end;
-
- ───────────────────────────────────────────────────────────────────────────
- procedure cleankill_list(var kill:pkill;var nkbeg,nkend:plist);
-
- Traverses the KILL list deallocating node that are in the kill and
- linked list.
-
- KILL: Kill list to cleanout;
- NKBEG: Linked list Head pointer;
- NKEND: Linked list Tail pointer
-
- On return KILL=NIL
-
- ───────────────────────────────────────────────────────────────────────────
- procedure clean_plist(var nkbeg,nkend:plist);
-
- Traverse the LINKED list deallocating every node.
-
- NKBEG: Linked list Head pointer;
- NKEND: Linked list Tail pointer
-
- On return nkbeg=NIL and nkend=NIL
-
- ───────────────────────────────────────────────────────────────────────────
-