Results 1 to 7 of 7

Thread: My solution to the overlapping issue in isometric worlds.

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #2
    Code:
    Type
      tItem =
        Record
        	Item,X : Word;
      	End;
    
      pItem = ^tItem;
    
      tOrder = Array[0..300] of tItem;
    
    
    Const
      ItemSize = SizeOf(tItem);
    
    
    Var
    //  OrderHeap : Array[0..GroundSizeY] of ^tOrder;//tHeapArray;
      OrderHeap : Array[0..GroundSizeY] of ^tOrder;
      pHeap : Pointer;
    
    //  DrawOrder : Array[0..GroundSizeY] of PWordArray;// absolute OrderHeap;//Array[0..GroundSizeY] of Pointer;
      Items : Array[0..GroundSizeY] of LongInt;
      Dummy : pItem;
    
    
    
    
    Procedure InitHeap;
    Var
      y : longword;
    
    
    Begin
      For y := 0 to GroundSizeY do
      Begin
        GetMem(OrderHeap[y],SizeOf(tOrder));
        FillChar(OrderHeap[y]^[0],SizeOf(tOrder),00);
        Items[y] := 0;
      End;
    End;
    
    Procedure AddItem(y : LongWord; Data : tItem);
    Var
      b : longword;
    
    Begin
      OrderHeap[y]^[Items[y]] := data;
    //  writeln(y);
      Inc(Items[y]);
    End;
    
    
    Function ReadItem(y,x : LongWord) : tItem;
    Begin
      ReadItem := OrderHeap[y]^[x];
    End;
    
    
    Procedure MoveItem(y : LongWord; Src,Dest : Word);
    Var
      Dummy2 : pItem;
    
    Begin
    
      OrderHeap[y]^[Dest] := OrderHeap[y]^[Src];
      OrderHeap[y]^[Src] := OrderHeap[y]^[Items[y]-1];
      Dec(Items[y]);
    End;
    
    Procedure MoveItemToY(y1 : word; Src : byte; y2 : word);
    Var
      xxx : LongWord;
    
    Begin
      OrderHeap[y2]^[Items[y2]] := OrderHeap[y1]^[Src];
      OrderHeap[y1]^[Src] := OrderHeap[y1]^[Items[y1]-1];
      Dec(Items[y1]);
      Inc(Items[y2]);
    End;
    There are a few things to mind here.

    "OrderHeap" is actually just one long chain of bytes. Memory allocation is silly,
    but i want to switch this to actual pointers each pointing to the beginning of their
    line in one huge chunk of heap. ^_^

    GroundSizeY currently is ... 8192*2 = 16384, times 4 Bytes, times 300 items per Y ...
    making OrderHeap 19 MByte big ... which isn't even a lot.

    Please note that OrderHeap's height equals the depth of the drawn, visual city. (aka top to bottom of whole rendered map)
    I have "Blocks" of 512x512, which i plot at 256x256 to have more details when zoomed in.

    Now how does it work ?

    First, I'm scanning through a 128x128 bitmap.
    If a pixel is set, i calculate the y-position of the tile on the image
    and add an item to it's corresponding y-line in DrawOrder.

    Code:
    For y := 0 to 127 do
    For x := 0 to 127 do
    Begin
      If (CityMap[x,y] <> 0) then
      Begin
        m := x;          
        v := (y*64);   // v is the line we have our tile set at.
    
    //    writeln(m,' : ',v);
    
         xxx.Item := MaxHumans;
         xxx.X := m;
    
         AddItem(v,xxx);
      End;
    End;
    MaxHumans. That's a constant limiting the amount of NPC humans walking around on the map.
    With MaxHumans, the first building-tile starts. It's not relevant to this thread.


    After this went through, i had my OrderHeap filled.

    f = Y of the top most visible line on screen
    g = Y of the bottom most ...

    Code:
    for y := f to g do
    begin
      if (Items[y] > 0) then              
      for x := 0 to Items[y] - 1 do  
      begin
        xxx := ReadItem(y, x);
        m := xxx.X * (BlockSize div 2);
        v := y;
        DropSprite(0, m, v - (BlockSize div 2), BlockSize, BlockSize);
      end;
    end;
    Now this is a bit tricky. Obviously i have no idea how you made your tiles
    and how you plan on dropping them onto screen.

    All this basically does is go through a whole line and draw everything onto the backbuffer.
    Sorting on X is completely unnecessary, so we can just weeze through it all at once,
    enjoying the fact that we're making the cache happy too.

    This way ... buildings stay behind people ... or in front of them.

    There's something else i have to add, although i'm not sure if it will affect you.

    (v - (BlockSize div 2)) shows that i am dropping the Sprite actually ABOVE the current OrderHeap[y].
    This makes sense to me, because it pushes the tiles center line to y. Isometric tiles are basically blocks,
    starting with a tight top, extending into center and tightening again towards the bottom.

    Having it's center line at y will prevent sprites from wrongly overlapping with it.
    Last edited by Solstice Project; 01-11-2013 at 01:32 AM.

Tags for this Thread

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
  •