![]() |
| | #1 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| New editor updates I finally got transparent blitting working in GDI. Pretty simple really. Link with msimg32.lib and use TransparentBlt(). It's faster than writing your own and it stretches/shrinks images to fit the destination rectangle. Nice...very nice.
__________________ If you aim at everything you will hit something but you won't know what it is. |
| Bubba is offline | |
| | #2 |
| Registered User Join Date: May 2004
Posts: 1,362
| Is this what you have done with MFC? |
| sand_man is offline | |
| | #3 |
| ∞ Join Date: May 2005
Posts: 962
| Looks like a very functional tile editor, keep up the good work.
__________________ argus triad mingus |
| BobMcGee123 is offline | |
| | #4 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Yeppers. This is what I've done with MFC. I'm not a woman, but I'm sure this experience has been akin to childbirth.
__________________ If you aim at everything you will hit something but you won't know what it is. |
| Bubba is offline | |
| | #5 |
| Registered User Join Date: May 2004
Posts: 1,362
| lol well it looks well worth it. |
| sand_man is offline | |
| | #6 | |
| ∞ Join Date: May 2005
Posts: 962
| Quote:
__________________ argus triad mingus | |
| BobMcGee123 is offline | |
| | #7 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Added more support to the editor. Having a lot of problems with zooming. Anyone have any ideas on how to do this? As you can see really big maps are supported. Here is one with 17 layers and a map size of 1000x1000.
__________________ If you aim at everything you will hit something but you won't know what it is. |
| Bubba is offline | |
| | #8 | |
| Registered User Join Date: Aug 2001
Posts: 411
| Quote:
Provided that i have no idea how your code is designed, what I would try first is to create a new child window, like one of the tile selection windows, and use it to display a 50x50 grid of the main map It should not be too hard to setup methods to transfer all the data for a small grid back and forth. Give it scroll bars so you can move around, and maybe even another mouse tool so you can snap the focus to another spot by clicking on the desired spot on the main map. Make the soom window resizable, but with a fixed aspect ratio, and instead of changing the number of tiles displayed, if grows and shrinks the tiles.
__________________ www.EberKain.com | |
| Eber Kain is offline | |
| | #9 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Well here is what I have. The scrolling is done in the main window. I would like to create that type of map system but the calculations are far beyond what I would have imagined - they get complicated. You can zoom in on this map until cell sizes reach 256 pixels. My idea is that I never want the map to have borders. In other words if you zoom out far enough, I never want you to be able to see off of the map. My calculations are as follows. It works fine for computing the scrolling maxX and maxY, but when you zoom in, scroll down, and then zoom out.....everything goes to um...crap. Code: void CZeldaEditorView::UpdateScrollSizes()
{
//Set new scroll sizes based on map size and current cellsize
//or grid size
CSize size;
//Get pointer to document class for map info
CZeldaEditorDoc *pDoc=(CZeldaEditorDoc *)GetDocument();
size.cx=pDoc->m_iMapSizeX*m_iGridSize;
size.cy=pDoc->m_iMapSizeY*m_iGridSize;
SetScrollSizes(MM_TEXT,size);
//Retrieve width and height of client rect
CRect rect;
GetClientRect(&rect);
int mapx=pDoc->m_iMapSizeX;
int mapy=pDoc->m_iMapSizeY;
int maxx=pDoc->m_iMapSizeX*m_iGridSize;
int maxy=pDoc->m_iMapSizeY*m_iGridSize;
//Set max scroll
m_iMaxScrollX=(m_iGridSize*(mapx-1))-rect.Width();
m_iMaxScrollY=(m_iGridSize*mapy)-rect.Height();
//Don't show borders
if (m_iMaxScrollX<0) m_iMaxScrollX=0;
if (m_iMaxScrollY<0) m_iMaxScrollY=0;
//If map size won't fit in window because map is too small
//Re-adjust cell size so map fits perfectly in window
if (rect.Width()>=maxx-m_iGridSize)
{
m_iGridSize=rect.Width()/mapx;
m_iScrollX=-m_iMaxScrollX;
m_iScrollY=-m_iMaxScrollY;
}
}
//Transforms mouse clicks to always click on nearest tile
//to cursor regardless of zoom and scroll
void CZeldaEditorView::TransformMouseXY(CPoint mouse,CRect &rect,DWORD &offset)
{
//Find out remainder of m_iScrollX/m_iGridSize
int offsetx=(m_iScrollX % m_iGridSize);
int offsety=(m_iScrollY % m_iGridSize);
//Temporaries so I don't have to use mouse.x, mouse.y every
//time
int mx=mouse.x;
int my=mouse.y;
//Subtract mouse by offsets
mx-=offsetx;
my-=offsety;
//Snap to grid size
mx-=(mx % m_iGridSize);
my-=(my % m_iGridSize);
//Re-adjust on-screen rect to new grid rectangle
rect.left=mx+offsetx;
rect.top=my+offsety;
rect.right=mx+m_iGridSize+offsetx;
rect.bottom=my+m_iGridSize+offsety;
//Compute actual memory location of grid clicked
int MemoryX=(mouse.x - m_iScrollX)/m_iGridSize;
int MemoryY=(mouse.y - m_iScrollY)/m_iGridSize;
//Set offset in document
CZeldaEditorDoc *ptrDoc=(CZeldaEditorDoc *)GetDocument();
offset=MemoryY*ptrDoc->m_iMapSizeX+MemoryX;
}
Sorry for the mess but MFC code is a mess. Basically I'm adhering to the document/view architecture so that the document handles the info about the map and the view just draws the map according to the info. It's a real pain in the arse. These calculations work but zooming only zooms in on the upper left corner. I know why it does this, but how would I zoom in on an area? Do I have to draw my map relative to the center of the screen, or can I just start at the upper left corner and set m_iScrollX and m_iScrollY to different values when zooming to get the zoom in on a point effect? Hard to explain. Maybe showing the actual OnDraw() will help. Pardon the mess but it's a major work in progress. Code: void CZeldaEditorView::OnDraw(CDC* pDC)
{
//Pointer to document class
CZeldaEditorDoc* pDoc = (CZeldaEditorDoc *)GetDocument();
//Pointer to frame clasee
CMainFrame *ptrFrame=(CMainFrame *)AfxGetMainWnd();
//Number of maps (layers)
DWORD numMaps=pDoc->m_pMapManager->GetNumberOfMaps();
//Handle to destination DC
HDC dcDest=pDC->GetSafeHdc();
//Black brush for drawing
CBrush blackbrush;
blackbrush.CreateSolidBrush(RGB(0,0,0));
//Retrieve client rect
CRect ScreenRect;
GetClientRect(&ScreenRect);
//Fill it with black
pDC->FillRect(&ScreenRect,&blackbrush);
//Check for tile manager and map count
//Don't draw if null or maps=0
if (pDoc->m_pTileManager && numMaps>1)
{
//Tile size from bitmap
int TileSize=pDoc->m_iTileSize;
//Horizontal offset - debug info
int iOffsetHoriz=abs(m_iScrollX/m_iGridSize);
//Vertical offset - debug info
int iOffsetVert=abs(m_iScrollY/m_iGridSize);
//Function to compute relative to center of screenrect
//Algos don't work right with this yet
//ComputeStartGrid();
//Iterate through maps
//m_dwStartMapNum is starting map
//m_dwEndMapNum is ending map
//To view one layer set start to layer and end to start+1
for (DWORD map=m_dwStartMapNum;map<m_dwEndMapNum;map++)
{
//Get pointer to map
CMap *ptrMap=pDoc->m_pMapManager->GetMapClass(map);
//Get pointer to movement map - disabled
//CMap *ptrMove=pDoc->m_pMapManager->GetMapClass(0);
//Screen calculations for memory offset
int CurrentY=(-m_iScrollY/m_iGridSize);
int CurrentX=(-m_iScrollX/m_iGridSize);
//Remember CurrentX before it changes
int OriginX=CurrentX;
//Compute memory offset
DWORD offset=CurrentY*pDoc->m_iMapSizeX+CurrentX;
int offsetx=m_iScrollX % m_iGridSize;
int offsety=m_iScrollY % m_iGridSize;
//Save starting offset
DWORD startoffset=offset;
//Rect for grid display - if enabled
CRect GridRect;
//Draw the map finally
for (int i=offsety;i<ScreenRect.bottom;i+=m_iGridSize)
{
for (int j=offsetx;j<ScreenRect.right;j+=m_iGridSize)
{
//Retrieve ID from map
DWORD ID=ptrMap->GetValueAtOffset(offset);
//If this block is not empty
if (ID!=0xFFFFFFFF)
{
//Get DC of tile bitmap from tile manager
CDC *tempDC=pDoc->m_pTileManager->GetTileDC(ID);
//Get handle to tile bitmap DC
HDC dcSource=tempDC->GetSafeHdc();
//Get transparent color of tile
UINT dwTransColor=pDoc->m_pTileManager->GetTransColor(ID);
//Do a transparent blit
::TransparentBlt(dcDest,
j,i,
m_iGridSize,m_iGridSize,
dcSource,
0,0,
TileSize,TileSize,
dwTransColor);
}
//Draw the grid
GridRect.left=j;
GridRect.top=i;
GridRect.right=j+m_iGridSize;
GridRect.bottom=i+m_iGridSize;
//If view->Grid checked then draw grid
if (m_bGrid)
{
CBrush gridbrush;
gridbrush.CreateSolidBrush(RGB(255,255,255));
pDC->FrameRect(&GridRect,&gridbrush);
}
//Increment offset into memory
offset++;
//Increment cell column counter
CurrentX++;
//If column is at width of map break
if (CurrentX>=pDoc->m_iMapSizeX-1) break;
}
//Set column counter to origin
CurrentX=OriginX;
//Increment startoffset by one row
startoffset+=pDoc->m_iMapSizeX;
//Save startoffset
offset=startoffset;
//Increment row counter
CurrentY++;
//If no more rows, break
if (CurrentY>pDoc->m_iMapSizeY-1) break;
}
}
}
}
It'a a pain in the arse but it's a linear algorithm and it's quite fast. The array is indexed in linear fashion and the render is done in linear fashion. The Tile manager holds all of the tiles. But get this. Instead of storing bitmaps each tile is an object with a device context that has been prepared beforehand so the image data is on the device context. Then blitting the image is as simple as using TransparentBlt from the API using the handles to the source DC and the dest DC. Simple. It all works great. But zooming is a mess. The ComputeStartGrid() function is a function that can center the grid inside of the client rect, but then all of the LButtonDown and MouseMove() functions don't compute the mouse cursor to grid and mouse cursor to memory right. If you'ev ever done a tile engine I'm sure you will understand in the editor you must transform mouse clicks to align with the displayed grid or you cannot place tiles correctly. Also if the current tile is the selected tile and you click on the tile in the map, it erases it. The selected tile is stored in the m_pTileManager class and is set by the tile tool dialogs when you select a tile to use. This hasn't been easy so forgive me if the algo sucks.
__________________ If you aim at everything you will hit something but you won't know what it is. Last edited by Bubba; 11-05-2005 at 03:51 PM. |
| Bubba is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|