void Init() { // Set the map to default g_Map.SetDefault(); // By default set the current tile type to map tiles g_Map.SetCurrentType(TILE_TYPE); // Set our current map to .... our current map :) g_pCurrentMap = &g_Map; }
void Init(HWND hWnd) { // Set our global window handle to our main window g_hWnd = hWnd; // Create our double buffering for each window g_Buffer.CreateDoubleBuffering(hWnd); g_ToolBuffer.CreateDoubleBuffering(g_hWndTool); // Set the map to default g_Map.SetDefault(); // Load the tiles into the global lists and then get the scroll bar max scroll position g_ScrollInfo.nMax = LoadTiles(); // By default set the current tile type to map tiles g_Map.SetCurrentType(TILE_TYPE); // Set our current map to .... our current map :) g_pCurrentMap = &g_Map; // Initialize the scroll bar information g_ScrollInfo.cbSize = sizeof(SCROLLINFO); g_ScrollInfo.nMin = 0; g_ScrollInfo.nPage = 1; g_ScrollInfo.fMask = SIF_PAGE | SIF_RANGE; SetScrollInfo(g_hWndTool, SB_VERT, &g_ScrollInfo, FALSE); //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Here we initialize our open file information g_OpenInfo.lStructSize = sizeof(OPENFILENAME); // Set the size of the structure g_OpenInfo.nMaxFile = MAX_PATH; // Set the max characters for a file name g_OpenInfo.lpstrFile = g_szFileName; // Give a string to store the file name g_OpenInfo.lpstrFilter = "Map Files (*.map)\0*.map"; // Only accept .map files to load g_OpenInfo.hwndOwner = g_hWndTool; // Assign the window owner and give it desired flags g_OpenInfo.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Here we set the current pen to red for drawing our exit rectangles g_Buffer.SetPen(PS_SOLID,2,RGB(255,0,0)); // Set the backbuffer to black first (This clears the backbuffer) g_Buffer.ClearScreen(BLACK_BRUSH); g_ToolBuffer.ClearScreen(BLACK_BRUSH); }
void Init(HWND hWnd) { // Set our global window handle to our main window g_hWnd = hWnd; // Create our double buffering for each window g_Buffer.CreateDoubleBuffering(hWnd); g_ToolBuffer.CreateDoubleBuffering(g_hWndTool); // Set the map to default g_Map.SetDefault(); // Load the tiles into the global lists and then get the scroll bar max scroll position g_ScrollInfo.nMax = LoadTiles(); // By default set the current tile type to map tiles g_Map.SetCurrentType(TILE_TYPE); // Set our current map to .... our current map :) g_pCurrentMap = &g_Map; // Initialize the scroll bar information g_ScrollInfo.cbSize = sizeof(SCROLLINFO); g_ScrollInfo.nMin = 0; g_ScrollInfo.nPage = 1; g_ScrollInfo.fMask = SIF_PAGE | SIF_RANGE; SetScrollInfo(g_hWndTool, SB_VERT, &g_ScrollInfo, FALSE); //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Here we set the current pen to red for drawing our exit rectangles g_Buffer.SetPen(PS_SOLID,2,RGB(255,0,0)); //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Set the backbuffer to black first (This clears the backbuffer) g_Buffer.ClearScreen(BLACK_BRUSH); g_ToolBuffer.ClearScreen(BLACK_BRUSH); }
void CheckMouseInput(const INPUT_RECORD &InputRecord) { // Get the current position of the mouse in the console window g_cursorPos = InputRecord.Event.MouseEvent.dwMousePosition; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // If we have the exit map open (destination map) then we don't want the // user to click on the editor tiles since it will screw up our placing // of the destination point, so we quit this function if they try that. if( (g_cursorPos.Y >= MAP_HEIGHT - EDITOR_HEIGHT) && g_bExitMapOpen) return; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // If the user hits the left mouse button if(InputRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) { // Here we check if the user chose a tile from our editor. if(g_cursorPos.Y > MAP_HEIGHT - EDITOR_HEIGHT) { // Get the character chosen from the editor CHAR_INFO chosenTile = g_Map.GetEditorSelection(g_cursorPos.X, g_cursorPos.Y); CHAR_INFO cursorTile = chosenTile; // If we already have a tile selected, let's grab it's image instead if(g_pCursorTile != NULL) cursorTile = g_pCursorTile->GetChar(); // Check if the user clicked the color tiles if(g_cursorPos.X >= 15 && g_cursorPos.Y == (MAP_HEIGHT - 1)) { CHAR_INFO newTile; // Create a new tile to work with for color // Check if the user clicked the background colors, otherwise it was foreground if(g_cursorPos.X > 30) newTile = g_Map.AddNewBackground(cursorTile, chosenTile); else newTile = g_Map.AddNewForeground(cursorTile, chosenTile); // Apply the new tile with it's new color to our cursor. g_vTiles[g_vTiles.size() - 1].SetChar(newTile); } else { // Otherwise, if we didn't choose a color, then we must // have chosen a new tile character from the editor. chosenTile.Attributes = cursorTile.Attributes; g_vTiles[g_vTiles.size() - 1].SetChar(chosenTile); // Let's set the cursor to a normal tile index and type g_pCursorTile = &g_vTiles[g_vTiles.size() - 1]; g_Map.SetCurrentType(TILE_TYPE); } } else { // If we have a tile, let's insert a tile into the map if(g_pCursorTile != NULL) g_pCurrentMap->InsertTile(g_pCursorTile, g_cursorPos.X, g_cursorPos.Y); //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // After we insert a tile, we want to check if that tile was an exit. If // it was, we need to handle the exits because it might either be a placing // of a destination exit or the end of a list of exits. This is why the // function HandleExitTiles() gets called twice. We first call it when // we are done placing our desired exit(s) on the normal map, which will // bring up a prompt to open the destination map. It's called again // when we choose the destination point on the exit map. 1 + 1 = ... 2 :) // Here we check if our current type are exits if(g_pCurrentMap->GetCurrentType() == EXIT_TYPE) { // If we don't have the shift key down or the exit map is open // we want to stop setting exits and handle the exits that were just set. if(!g_bShiftKeyDown || g_bExitMapOpen) HandleExitTiles(); } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// } } // Here we check if the right mouse button was clicked if(InputRecord.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED) { // Here we either delete a tile on the map, or delete the cursor tile if(g_pCursorTile == NULL) { // Delete a tile under our cursor position on the map g_pCurrentMap->DeleteTile(g_cursorPos.X, g_cursorPos.Y); } else g_pCursorTile = NULL; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // If the user is in the middle of setting exits and decide to abort, we want to // still let them right click to destroy the cursor tile and unset exit tiles. // We need to handle both situations of the user having placed exits and not yet // opened a destination map, as well as having the destination map open as well. // So, after the cursor tile is delete, if the exit map is open we want to return // to the previous map and delete the blank exits that were never filled in with // a destination point. If the destination map isn't open, we still want to get // rid of the wasted exits already set on the map. // Check if the current tile type are exits if(g_pCurrentMap->GetCurrentType() == EXIT_TYPE) { // Check if our destination map is open and we need to abort to the previous map if(g_bExitMapOpen) { // To abort, we need to set the current map pointer back and reset the flag g_pCurrentMap = &g_Map; g_bExitMapOpen = false; } // Go through and delete all the useless exits and redraw the screen g_pCurrentMap->DeleteBlankExits(); g_pCurrentMap->Draw(); } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// } }
void CheckKeyboardInput(const INPUT_RECORD &InputRecord) { //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // If we have the exit map open, we don't want to allow the user to type in // commands because it will screw up the placing of our destination exit. // We only want the user to right click to delete the exit if they change their mind. // By placing a return here, we won't go through this function if our exit map is open. if(g_bExitMapOpen) return; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // If the user hits the escape key if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) { exit(0); // Quit the program } // If the user hits the I key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'I') { g_ItemIndex = 0; // Reset the current index for the item list g_pCursorTile = &g_vItems[g_ItemIndex]; // Set the cursor tile to the first item g_Map.SetCurrentType(ITEM_TYPE); // Set the type of list to an item type } // If the user hits the M key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'M') { g_MonsterIndex = 0; // Reset the current index for the monster list g_Map.SetCurrentType(MONSTER_TYPE); // Set the type of list to an monster type g_pCursorTile = &g_vMonsters[g_MonsterIndex]; // Set the cursor tile to the first monster } // If the user hits the N key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'N') { g_ItemIndex = 0; // Reset the current index for the npc list g_pCursorTile = &g_vNpcs[g_ItemIndex]; // Set the cursor tile to the first npc g_Map.SetCurrentType(NPC_TYPE); // Set the type of list to an npc type } // If the user hits the E key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'E') { CHAR_INFO image = {'E', FOREGROUND_RED}; // Create an image for exits g_pCursorTile = &g_vTiles[g_vTiles.size() - 1]; // Set the cursor tile to the last tile g_pCursorTile->SetChar(image); // Set the image of our exit tile g_Map.SetCurrentType(EXIT_TYPE); // Set the type of list to an exit type } // If the user hits the space bar else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_SPACE) { if(g_Map.GetCurrentType() == ITEM_TYPE) // If we have items selected { // Use the modulus operator to restrict our index to the size of the item list, // then set the cursor tile to the current tile in the item list. g_ItemIndex = (g_ItemIndex + 1) % (int)g_vItems.size(); g_pCursorTile = &g_vItems[g_ItemIndex]; } else if(g_Map.GetCurrentType() == MONSTER_TYPE) // If the user has the monsters selected { // Use the modulus operator to restrict our index to the size of the monster list, // then set the cursor tile to the current tile in the monster list. g_MonsterIndex = (g_MonsterIndex + 1) % (int)g_vMonsters.size(); g_pCursorTile = &g_vMonsters[g_MonsterIndex]; } else if(g_Map.GetCurrentType() == NPC_TYPE) // If the user has the npcs selected { // Use the modulus operator to restrict our index to the size of the npc list, // then set the cursor tile to the current tile in the npc list. g_NpcIndex = (g_NpcIndex + 1) % (int)g_vNpcs.size(); g_pCursorTile = &g_vNpcs[g_NpcIndex]; } } // Check if we want to load a new map (Pass in true to LoadOrSaveAMap()) else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'L') { LoadOrSaveAMap(true); } // Check if we want to save the current map (Pass in false to LoadOrSaveAMap()) else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'S') { LoadOrSaveAMap(false); } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // So that we don't have to place 1 exit at a time, we added the feature of being // able to hold down shift to place many exits before we choose the destination // exit. This makes it so if you want to make a whole side of a map an exit to another // map (like out in the forest or open spaces) we can hold down shift and click // every character along that side. Before we place the last exit for that side, we // left go of shift and then choose the last exit, which will bring up the prompt // to choose the destination point. If you want the destination map to have the same // exit point, just open the exit map and do the same thing for that side, and then // choose a point on the first map to end up on, like in the middle of that side. // If shift is pressed, let's set our flag to true else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) g_bShiftKeyDown = true; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// }
void HandleMenu(int menuID) { if(menuID == ID_FILE_QUIT) // If the user chose File->Quit { PostQuitMessage(0); // Quit the program } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// else if(menuID == ID_FILE_OPENUP) // If the user chose File->Open { // Have windows bring up the Open File dialog box and Load the file chosen if(GetOpenFileName(&g_OpenInfo)) g_Map.Load(g_OpenInfo.lpstrFile); } else if(menuID == ID_FILE_SAVEIT) // If the user chose File->Save { // If we have a n valid name for our map already, do a normal save if(strlen(g_Map.GetMapName()) > 3) g_Map.Save(g_Map.GetMapName()); else { // If haven't given our map a name yet, do a "SaveAs" and bring up the save dlg box if(GetSaveFileName(&g_OpenInfo)) g_Map.Save(g_OpenInfo.lpstrFile); } } else if(menuID == ID_FILE_SAVEAS) // If the user chose File->SaveAs { // Bring up the save dlg box and allow the user to type in a new map name and save it if(GetSaveFileName(&g_OpenInfo)) g_Map.Save(g_OpenInfo.lpstrFile); } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// else if(menuID == ID_FILE_RESET) // If the user chose File->Reset g_Map.SetDefault(); // Destroy all the tiles on the map and start over else if(menuID == ID_TILES_TILES) // If the user chose Tiles->Tiles g_Map.SetCurrentType(TILE_TYPE); // Set the tool bar tile type to tiles else if(menuID == ID_TILES_ITEMS) // If the user chose Tiles->Items g_Map.SetCurrentType(ITEM_TYPE); // Set the tool bar tile type to items else if(menuID == ID_TILES_MONSTERS) // If the user chose Tiles->Monsters g_Map.SetCurrentType(MONSTER_TYPE); // Set the tool bar tile type to monsters else if(menuID == ID_TILES_CITIZENS) // If the user chose Tiles->Citizens g_Map.SetCurrentType(NPC_TYPE); // Set the tool bar tile type to citizens else if(menuID == ID_TILES_EXITS) // If the user chose Tiles->Exits g_Map.SetCurrentType(EXIT_TYPE); // Set the tool bar tile type to exits (no tiles of course) else if(menuID == ID_HELP_ABOUT) // If the user chose Help->About // Instead of creating a help dialog box, we can just use a simple system MessageBox() call MessageBox(g_hWnd, "www.GameTutorials.com Map Editor\n\n" "\t- Choose the desired tile type from the Tiles menu,\n" "\t then click on a tile in the tile window. You can\n" "\t then draw the tiles on the map with the left mouse button.\n\n" "\t- Right click to remove the current cursor tile.\n\n" "\t- To delete a item:monster:citizen:exit, make sure you choose\n" "\t that type from the menu, then right click on the tile.\n\n" "\t- When setting an exit you can hold down shift to place more exits.\n" "\t Once you place an exit without holding the shift key you will be\n" "\t prompted to choose the destination map. Then place one tile for\n" "\t the position where the character will end up.\n\n" "\t- Hit Esc to quit the program.", "About", MB_OK | MB_ICONINFORMATION); // Over assuming that a tile type was changed, reset the scroll bar size. // The -1 is because the tool bar window's title size offsets it a bit (being smaller). g_ScrollInfo.nMax = g_Map.GetCurrentTypeSize() - MAP_HEIGHT - 1; // If there isn't enough (or any) tiles to fill up the tool bar window, disable the scroll bar if(g_ScrollInfo.nMax < 0) { g_ScrollInfo.nMax = 0; EnableScrollBar(g_hWndTool, SB_VERT, ESB_DISABLE_BOTH); } else EnableScrollBar(g_hWndTool, SB_VERT, ESB_ENABLE_BOTH); // Enable the scroll bar if it's needed // Reset the scroll bar info g_scrollBarPosY = 0; g_ScrollInfo.nPage = 0; // Update the current scroll bar information with no need to redraw (FALSE) SetScrollInfo(g_hWndTool, SB_VERT, &g_ScrollInfo, FALSE); ShowScrollBar(g_hWndTool, SB_VERT, TRUE); // If we chose a tile type, put a check box next to it switch(menuID) { case ID_TILES_TILES: case ID_TILES_ITEMS: case ID_TILES_MONSTERS: case ID_TILES_CITIZENS: case ID_TILES_EXITS: g_pCursorTile = NULL; CheckTileType(menuID); break; } }
void CheckMouseInput(const INPUT_RECORD &InputRecord) { // Get the current position of the mouse in the console window g_cursorPos = InputRecord.Event.MouseEvent.dwMousePosition; // If the user hits the left mouse button if(InputRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) { // Here we check if the user chose a tile from our editor. if(g_cursorPos.Y > MAP_HEIGHT - EDITOR_HEIGHT) { // Get the character chosen from the editor CHAR_INFO chosenTile = g_Map.GetEditorSelection(g_cursorPos.X, g_cursorPos.Y); CHAR_INFO cursorTile = chosenTile; // If we already have a tile selected, let's grab it's image instead if(g_pCursorTile != NULL) cursorTile = g_pCursorTile->GetChar(); // Check if the user clicked the color tiles if(g_cursorPos.X >= 15 && g_cursorPos.Y == (MAP_HEIGHT - 1)) { CHAR_INFO newTile; // Create a new tile to work with for color // Check if the user clicked the background colors, otherwise it was foreground if(g_cursorPos.X > 30) newTile = g_Map.AddNewBackground(cursorTile, chosenTile); else newTile = g_Map.AddNewForeground(cursorTile, chosenTile); // Apply the new tile with it's new color to our cursor. g_vTiles[g_vTiles.size() - 1].SetChar(newTile); } else { // Otherwise, if we didn't choose a color, then we must // have chosen a new tile character from the editor. chosenTile.Attributes = cursorTile.Attributes; g_vTiles[g_vTiles.size() - 1].SetChar(chosenTile); // Let's set the cursor to a normal tile index and type g_pCursorTile = &g_vTiles[g_vTiles.size() - 1]; g_Map.SetCurrentType(TILE_TYPE); } } else { // If we have a tile, let's insert a tile into the map if(g_pCursorTile != NULL) g_pCurrentMap->InsertTile(g_pCursorTile, g_cursorPos.X, g_cursorPos.Y); } } // Here we check if the right mouse button was clicked if(InputRecord.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED) { // Here we either delete a tile on the map, or delete the cursor tile if(g_pCursorTile == NULL) { // Delete a tile under our cursor position on the map g_pCurrentMap->DeleteTile(g_cursorPos.X, g_cursorPos.Y); } else g_pCursorTile = NULL; } }
void CheckKeyboardInput(const INPUT_RECORD &InputRecord) { // If the user hits the escape key if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) { exit(0); // Quit the program } // If the user hits the I key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'I') { g_ItemIndex = 0; // Reset the current index for the item list g_pCursorTile = &g_vItems[g_ItemIndex]; // Set the cursor tile to the first item g_Map.SetCurrentType(ITEM_TYPE); // Set the type of list to an item type } // If the user hits the M key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'M') { g_MonsterIndex = 0; // Reset the current index for the monster list g_Map.SetCurrentType(MONSTER_TYPE); // Set the type of list to an monster type g_pCursorTile = &g_vMonsters[g_MonsterIndex]; // Set the cursor tile to the first monster } // If the user hits the N key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'N') { g_ItemIndex = 0; // Reset the current index for the npc list g_pCursorTile = &g_vNpcs[g_ItemIndex]; // Set the cursor tile to the first npc g_Map.SetCurrentType(NPC_TYPE); // Set the type of list to an npc type } // If the user hits the E key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'E') { CHAR_INFO image = {'E', FOREGROUND_RED}; // Create an image for exits g_pCursorTile->SetChar(image); // Set the image of our exit tile g_pCursorTile = &g_vTiles[g_vTiles.size() - 1]; // Set the cursor tile to the last tile g_Map.SetCurrentType(EXIT_TYPE); // Set the type of list to an exit type } // If the user hits the space bar else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_SPACE) { if(g_Map.GetCurrentType() == ITEM_TYPE) // If we have items selected { // Use the modulus operator to restrict our index to the size of the item list, // then set the cursor tile to the current tile in the item list. g_ItemIndex = (g_ItemIndex + 1) % (int)g_vItems.size(); g_pCursorTile = &g_vItems[g_ItemIndex]; } else if(g_Map.GetCurrentType() == MONSTER_TYPE) // If the user has the monsters selected { // Use the modulus operator to restrict our index to the size of the monster list, // then set the cursor tile to the current tile in the monster list. g_MonsterIndex = (g_MonsterIndex + 1) % (int)g_vMonsters.size(); g_pCursorTile = &g_vMonsters[g_MonsterIndex]; } else if(g_Map.GetCurrentType() == NPC_TYPE) // If the user has the npcs selected { // Use the modulus operator to restrict our index to the size of the npclist, // then set the cursor tile to the current tile in the npc list. g_NpcIndex = (g_NpcIndex + 1) % (int)g_vNpcs.size(); g_pCursorTile = &g_vNpcs[g_NpcIndex]; } } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Now that we can load and save, let's add the keyboard functionality to // allow the user to do that. This is done with the 'L' and 'S' key. // Check if we want to load a new map (pass in true to LoadOrSaveAMap()) else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'L') { LoadOrSaveAMap(true); } // Check if we want to save the current map (Pass in false to LoadOrSaveAMap()) else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'S') { LoadOrSaveAMap(false); } //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// }