Boreas
2010-12-16 15:12:36
This is a thread about how we can work together to prepare for several possible future color tile walking systems. By color tile walking system, I mean something that is based on a color version of GetMyPos, can accept paths (and webs made of nodes and paths) designed for reflection, and uses autocolor based simplification algorithms (write once (not counting tweaking) and apply everywhere). For this to work, regardless of what simplification algorithms are used, we need to prepare a special clean map before it can be simplified:
Step 1 is determining how the map will be stored. To do this we need the following data.
Q:How many pixels is a tile?
A:4x4=16 Thanks Quickmarch
Q:What are the dimensions in tiles of the world map?
It is 1863 by 1680 tiles.
Q:What is the diameter of the minimap (in pixels or tiles)?
A:37 tiles Thanks lordsaturn
Q:Where is MMCX,MMCY in relation to the current tile?
A:MMCX 627 MMCY 85. The center tile is MMCX1 626 MMCY1 83 MMCX2 629 MMCY2 86 Thanks lordsaturn for great pics
Q:What is the tile position of a known place?
A:Thanks again to lordsaturn. Tile 3043, 3349 (0,0 to the bottom left) by the falador fountain is pixels 3995,3275 to 3998,3278 on a map that is 7452, 6722 pixels (0,0 to the top left)
With this data I'm working a diagram here that will outline how to store the map.
Step 2 will be writing a function to take screenshots based on the specs in the diagram.
The screenshots will not contain symbols, so symbols approximate tile locations will need to be saved to a text file.
Q: Should we use something like this with explode in an INI or XML file?
A: INI with SymbolsChunk09,45=Bank-TileX,TileY-Water-TileX,TileY
Q: Do we have function that will detect all symbols within a given TBox, and return which symbols they are and where?
A: Never mind, see next one.
Is there a better way than recording symbol locations when processing screenshots?
Rather than doing that, would a few people like to volunteer to do the following? Use the PathMaker program to click on some bank symbols, and it spits out tile coords for each one. Have a script takes those tiles, figure out what chunk they are in (Tile X,Y is in chunk ((X-2044) div 25), ((Y-861) div 25)), stick those into the INI. Rinse and repeat for other symbols.
In the same file, we will need the tile locations of yellow NPC dots that do not walk around (bankers etc). Any volunteers for this?
More important than the symbols.
We also need someone to create an svn repo which will distribute this file, plus another INI file with a list of contributed map chunks, and the .simba file with the actual bitmap generating code.
Q: Can someone make a function that finds all symbol circles (which symbol is in them doesn't matter) in a given TBox and spits out a TPA of pixels that the symbol is covering?
A: Talked it over with my dad (programmer), I should have something soon.
Q: See previous question except for NPC/Drop/Player dots (maybe look for the shadow as it is the same for all 3).
A: Being handled on another thread
Step 2 so far:
const
CTWP = false; //Make true to help out CTWP
{*******************************************************************************
function CTWPGetMyPos: TTile;
By: BenLand100
Description: Returns the global tile position of your player.
*******************************************************************************}
function CTWPGetMyPos: TTile;
var
me: Integer;
begin
me := SmartGetFieldObject(0, hook_static_MyPlayer);
Result.x := SmartGetFieldInt(0, hook_static_BaseX) + SmartGetFieldInt(me, hook_animable_PixelX) / 512;
Result.y := SmartGetFieldInt(0, hook_static_BaseY) + SmartGetFieldInt(me, hook_animable_PixelY) / 512;
SmartFreeObject(me);
if CTWP then
CTWPMakeClean(Result);
end;
//LordSaturn
{function }procedure CTWPCollectDots(Bitmap: integer);//: TPointArray;
var
SearchColors: TIntegerArray;
OtherColors: T2DIntegerArray;
i, j, Hi, x, y, leftDev, rightDev, L, LTop: Integer;
ATPA: T2DPointArray;
TPA, FoundColorsTPA: TPointArray;
begin //red white yellow
//Freeze;
SearchColors := [217, 188, 14869218, 12961221, 56797, 52428];
SetLength(OtherColors, 3);
OtherColors[0] := [3553023, 789758, 2105598, 395004, 237, 206, 65536, 217, 188]; //red
OtherColors[1] := [16711422, 15527148, 13816530, 65536, 14869218, 12961221]; //white
OtherColors[2] := [1179390, 195836, 62965, 56797, 60909, 52428, 65536]; //yellow
LTop := 999;
SetLength(Result, LTop);
for i := 0 to 5 do
begin
if FindColors(TPA, SearchColors[i], 14, 14, 113, 113) then
FoundColorsTPA := CombineTPA(FoundColorsTPA, TPA); //if one color is covered, we will find the other
if (i mod 2 = 1) then
begin
ATPA := TPAtoATPAEx(FoundColorsTPA, 1, 0);
Hi := High(ATPA);
for j := 0 to Hi do
begin
//if (GetColor(ATPA[j][0].x, ATPA[j][0].y+1) = 65536) then //it is a dot
begin //begin finding the whole dot
leftDev := 0;
if (GetColor(ATPA[j][0].x-1, ATPA[j][0].y) = 65536) then //finding the left bound of the dot
leftDev := -1
else
if (GetColor(ATPA[j][0].x-2, ATPA[j][0].y) = 65536) then
leftDev := -2
else
if (GetColor(ATPA[j][0].x-1, ATPA[j][0].y) = 217) then
leftDev := -1;
rightDev := 0;
if (GetColor(ATPA[j][0].x+1, ATPA[j][0].y) = 65536) then //finding the right bound of the dot
rightDev := 1
else
if (GetColor(ATPA[j][0].x+2, ATPA[j][0].y) = 65536) then
rightDev := 2
else
if (GetColor(ATPA[j][0].x+1, ATPA[j][0].y) = 188) then
rightDev := 1;
for x := ATPA[j][0].x + leftDev to ATPA[j][0].x + rightDev do
for y := ATPA[j][0].y - 3 to ATPA[j][0].y + 1 do
begin
if ((x = ATPA[j][0].x + leftDev) and (y = ATPA[j][0].y - 3)) or //ignore 4 corners
((x = ATPA[j][0].x + leftDev) and (y = ATPA[j][0].y + 1)) or
((x = ATPA[j][0].x + rightDev) and (y = ATPA[j][0].y - 3)) or
((x = ATPA[j][0].x + rightDev) and (y = ATPA[j][0].y + 1)) then
Continue;
if InIntArray(OtherColors[i/2], GetColor(x, y)) then
begin
if (L = LTop) then
begin
LTop := LTop*2;
//SetLength(Result, LTop);
end;
FastSetPixel(x,y,clWhite,Bitmap); //Result[L] := Point(x, y);
Inc(L);
end;
end;
end;
end;
SetLength(FoundColorsTPA, 0);
end;
end;
//SetLength(Result, L);
//Unfreeze;
end;
procedure CTWPMakeClean(MyTile: TTile);
var
CAB: TBox; //CurrentAreaBox
Chunks, Corners, Corners2: TPointArray;
i, i2, counter, MainBitmap, ChunkBitmap: intger;
ChunkBitmaps: array of integer;
TmpPoint: TPoint;
ChunksTiles, FragmentsTiles, FragmentsPixels, FragmentsPos: TBoxArray;
begin
//Get tile bounds of CurrentAreaBox
CAB := IntToBox(MyTile.x - 12, MyTile.y + 12, MyTile.x + 12, MyTile.y - 12);//Make sure this does not normalize
//CurrentAreaBox is spread over 1, 2, or 4 chunks, so these arrays are set to 4
//In these arrays, [0] corresponds to the chunk that the top left corner of CAB is in,
//[1] is top right, [2] is bottom left, [3] is bottom right. This defined in Corners
Corners := [Point(CAB.x1, CAB.y1), Point(CAB.x2, CAB.y1), Point(CAB.x1, CAB.y2), Point(CAB.x2, CAB.y2)];
SetArrayLength(Chunks, 4);
SetArrayLength(ChunksTiles, 4);
SetArrayLength(FragmentsTiles, 4);
SetArrayLength(FragmentsPixels, 4);
SetArrayLength(FragmentsPos, 4);
//I'm using these conventions when working with tiles and pixels
//Pixels have 0,0 in the top left
//Tiles have 0,0 in the bottom left
//Chunks have 0,0 in the bottom left (the are 100x100 pixels, but they deliberately start and end on tiles so that no tile
//is spread over multiple chunks (25x25 tiles), therefore, they follow the tile convention)
//X1,Y1 is always top left, X2,Y2 is always bottom right
//For pixels, Y1 is lower than Y2. For tiles and chunks, Y2 is lower than Y1
for i:= 0 to 3) do
begin
//Find the Chunk that the corresponding corner of CAB is in
Chunks[i] := Point(((Corners[i].x-2044) div 25),((Corners[i].y-861) div 25));
//Find the tile bounds of that chunk
ChunksTiles[i] := IntToBox(2044+Chunks[i].x*25, 885+Chunks[i].y*25, 2068+Chunks[i].x*25, 861+Chunks[i].y*25);//No normalize
//These are the opposite corners of Corners
Corners2 := [Point(ChunksTiles[i].x2, ChunksTiles[i].y2), Point(ChunksTiles[i].x1, ChunksTiles[i].y2), Point(ChunksTiles[i].x2, ChunksTiles[i].y1), Point(ChunksTiles[i].x1, ChunksTiles[i].y1)]; //yes normalize
//Find the intersection of the corresponding Corner of CAB and the opposite corner of the Chunk
//that contains the Corner of CAB. Also make X1 lower than X2, and Y1 higher than Y2 (tiles start from the bottom left)
FragmentsTiles[i] := IntToBox(Min(Corners[i].x,Corners2[i].x), Max(Corners[i].y,Corners2[i].y), Max(Corners[i].x,Corners2[i].x), Min(Corners[i].y,Corners2[i].y);
//Find the pixel bounds (on MainBitmap) of thoses tiles
FragmentsPixels[i] := IntToBox(14+(FragmentsTiles[i].x1-(MyTile.x-12))*4, 14+((MyTile.y+12)-FragmentsTiles[i].y1)*4, 112-((MyTile.x+12)-FragmentsTiles[i].x2)*4, 112-(FragmentsTiles[i].y2-(MyTile.y-12))*4);
//Find the pixel box in Chunk that fragment will be copied to
FragmentsPos
end;
//Is this right?
MainBitmap := CreateBMP(128,128) //Create a bitmap 128x128
//Freeze; //Is this needed for CopyClientToBitmap?
//What is the command to do this?
CopyClientToBitmap(MainBitmap, 564, 21, 691, 148, 0, 0, 127, 127)
//Unfreeze;//Is this needed for CopyClientToBitmap?
//What is the command to do this?
SetTargetBitmap(MainBitmap);
//Do FindColorsTolerance etc on the MainBitmap
CTWPCollectDots(MainBitmap); //needs to set pixels on MainBitmap
White out the symbols //needs to set pixels on MainBitmap
//end of setting pixels on MainBitmap
SetLength(CopiedChunks,1);
CopiedChunks[0] := Point(-1,-1);
for i:= 0 to 3 do
Skip := false;
for i2 := 0 to counter do
begin
if (Chunks[i].x = CopiedChunks[i2].x) and (Chunks[i].x = CopiedChunks[i2].x) then
begin
Skip := true;
break;
end;
end;
if not Skip then
begin
SetArrayLength(CopiedChunks, counter+1);
CopiedChunks[Counter] := Chunks[i];
Inc(Counter);
//How to Load bitmap? How to make a number 2 digits by padding 0 on the left if needed? ie CleanChunk03-48.bmp
ChunkBitmap := CreateBitmapFromFile(CTWPath+'CleanChunk'+Pad(2,inttostr(Chunks[i].x))+'-'+Pad(2,inttostr(Chunks[i].y))'+'.bmp');
//If this file does not exist, create it, and fill with clWhite if it isn't already. (clWhite is RGB 255,255,255 right?)
//How to do this while skipping pixels in box FragmentPixels in MainBitmap that are clWhite?
Copy from FragmentsPixels[i].x1, FragmentsPixels[i].y1, FragmentsPixels[i].x2 FragmentsPixels[i].y2 on MainBitmap
to FragmentsPos[i].x1, FragmentsPos[i].y1, FragmentsPos[i].x2, FragmentsPos[i].y2 on ChunkBitmap
end;
end;
//restore the target
end;


then:


