• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Juliean

GUI nightmares

17 posts in this topic

Have you ever been told, or told someone not to unroll their own gui framework but to rely on the established available libaries? Well, this pretty much shows why they are right:

TowerStateCtrl::TowerStateCtrl(gui::Widget& parent, const ecs::Entity& tower, const ecs::MessageManager& messages): m_pTower(&tower), m_pMessages(&messages)
{
    gui::Area& area = AddWidget<gui::Area>(0, 0, parent.GetWidth(), parent.GetHeight());
    SetAsMainWidget(&area);
    parent.AddChild(area);

    const int imageX = parent.GetWidth()/12;
    const int imageY = parent.GetHeight()/12;
    const int imageWidth = parent.GetWidth() - imageX*2;
    const int imageHeight = parent.GetHeight() - (int)(imageY*3.75f);
    AddWidget<gui::Image>(imageX, imageY, imageWidth, imageHeight, L"GuiStateback");

    const Tower* pTower = m_pTower->GetComponent<Tower>();

    // name display
    m_pNameLabel = &AddWidget<gui::Label>(0, area.GetHeight() / 16, area.GetWidth(), 32, pTower->m_stName.c_str());

    const int iconSize = area.GetWidth() / 20;
    const int iconOffsetX = area.GetWidth() / 8;

    const int offsetX = iconOffsetX + iconOffsetX;
    const int offsetY = area.GetHeight() / 7;
    const int halfWidth = area.GetWidth() / 2;

    const int labelWidth = halfWidth - offsetX;
    const int labelOffsetX = offsetX + labelWidth;

    // damage display
    AddWidget<gui::Image>(iconOffsetX, offsetY, iconSize, iconSize, L"IcoThunder");
    gui::Label& damageLabel = AddWidget<gui::Label>(offsetX, offsetY, labelWidth, 32, L"Damage");
    damageLabel.SetAlign(gui::LEFT | gui::VCENTER);
    m_pDamageLabel = &AddWidget<gui::Label>(labelOffsetX, offsetY, labelWidth, 32, conv::ToString( pTower->m_atk ).c_str() );
    m_pDamageLabel->SetAlign(gui::RIGHT | gui::VCENTER);

    // speed display
    AddWidget<gui::Image>(iconOffsetX, offsetY*2, iconSize, iconSize, L"IcoHourglass");
    gui::Label& speedLabel = AddWidget<gui::Label>(offsetX, offsetY*2, labelWidth, 32, L"Speed");
    speedLabel.SetAlign(gui::LEFT | gui::VCENTER);
    m_pSpeedLabel = &AddWidget<gui::Label>(labelOffsetX, offsetY*2, labelWidth, 32, conv::ToString( pTower->m_speed ).c_str() );
    m_pSpeedLabel->SetAlign(gui::RIGHT | gui::VCENTER);

    // range display
    AddWidget<gui::Image>(iconOffsetX, offsetY*3, iconSize, iconSize, L"IcoWorld");
    gui::Label& rangeLabel = AddWidget<gui::Label>(offsetX, offsetY*3, labelWidth, 32, L"Range");
    rangeLabel.SetAlign(gui::LEFT | gui::VCENTER);
    m_pRangeLabel = &AddWidget<gui::Label>(labelOffsetX, offsetY*3, labelWidth, 32, conv::ToString( pTower->m_range ).c_str() );
    m_pRangeLabel->SetAlign(gui::RIGHT | gui::VCENTER);

    // level display
    AddWidget<gui::Image>(iconOffsetX, offsetY*4, iconSize, iconSize, L"IcoStar");
    gui::Label& levelLabel = AddWidget<gui::Label>(offsetX, offsetY*4, labelWidth, 32, L"Level");
    levelLabel.SetAlign(gui::LEFT | gui::VCENTER);
    m_pLevelLabel = &AddWidget<gui::Label>(labelOffsetX, offsetY*4, labelWidth, 32, conv::ToString( pTower->m_level + 1 ).c_str() );
    m_pLevelLabel->SetAlign(gui::RIGHT | gui::VCENTER);

	// upgrade button
    const int buttonY = (int)(offsetY * 5.75f);
	m_pUpgradeButton = &AddWidget<gui::Button>(16, buttonY, halfWidth - 32, area.GetHeight() / 6, (L"Upgrade:" + conv::ToString( 50 )).c_str() );
	m_pUpgradeButton->SigReleased.Connect(this, &TowerStateCtrl::OnUpgradeTower);

    const int iconOff = (m_pUpgradeButton->GetHeight() - iconSize) / 2;
    gui::Image& sell = AddWidget<gui::Image>(iconOff, iconOff, iconSize, iconSize, L"IcoUpgrade");
	sell.OnDisable();
    m_pUpgradeButton->AddChild(sell);

    // sell button
    m_pSellButton = &AddWidget<gui::Button>(halfWidth + 16, buttonY, halfWidth - 32, area.GetHeight() / 6, (L"Sell:" + conv::ToString( (int)(pTower->m_cost * 0.75) )).c_str() );
    m_pSellButton->SigReleased.Connect(this, &TowerStateCtrl::OnSellTower);

    gui::Image& money = AddWidget<gui::Image>(iconOff, iconOff, iconSize, iconSize, L"IcoMoney");
	money.OnDisable();
    m_pSellButton->AddChild(money);

    Update();

    OnFocus(true);
}

That monstrousity just to display a small status-widget, without any functionality mind you. I probably could have used more constants (yieks!) or seperated this huge method into smaller ones, but its a mess anyway. Anyone else here who encountered their own "gui horrors"? biggrin.png

Edited by Juliean
0

Share this post


Link to post
Share on other sites


Try the same with bare Win32 API (or even MFC) and then compare

 

Would I really want to? :D

 

Interesting though, I didn't have any other experience in gui other than looking at some Qt-headers/examples, so I figured this was a real horrid design, specially since one of my fellow students who had done some gui work said that gui programming is supposed to work quite easy oO. Still, one thing that makes this extraordinarly hard to maintain is that I was using a fixed position mode, forcing me to hand-calculate all the sizes, etc...

 


Most GUI frameworks provide some sort of instantiation of elements, whether from XML configuration or some other means, but if you refrain from using these configuration schemes and build your elements by hand instead then your code ends up looking a whole lot like what you have written here.

 

Thats how it ended up for me, too. This, plus a relative metrics mode - 0.0f, 0.0f, 1.0f, 1.0f would mean a widget that fills its whole parent - made things work out much better. Thats the same widget, in XML:

<Controller>
	<Area name="Tower">
		<Main/>
		<Metrics type="rel" x="0.0" y="0.0" w="1.0" h="1.0" />
	</Area>
	<Image name="" img="GuiStateback">
		<Metrics type="rel" x="0.0" y="0.15" w="0.8" h="0.6" />	
		<Center h="1" v="0" />
		<Alignment h="1" v="0" />
		<Image name="" img="IcoThunder">
			<Metrics type="rel" x="0.075" y="0.2" w="0.05" h="1.0" />
			<Center h="0" v="1" />´
			<BorderRel value="1" />
		</Image>
		<Label name="" label="Damage">
			<Metrics type="rel" x="0.3" y="0.2" w="0.4" h="0.15" />
			<Center h="0" v="1" />
			<Align value="4" />
		</Label>
		<Label name="Damagelabel" label="0">
			<Metrics type="rel" x="0.5" y="0.2" w="0.3" h="0.15" />
			<Center h="0" v="1" />
			<Align value="6" />
		</Label>
		<Image name="" img="IcoHourglass">
			<Metrics type="rel" x="0.075" y="0.4" w="0.05" h="1.0" />
			<Center h="0" v="1" />´
			<BorderRel value="1" />
		</Image>
		<Label name="" label="Speed">
			<Metrics type="rel" x="0.3" y="0.4" w="0.4" h="0.15" />
			<Center h="0" v="1" />
			<Align value="4" />
		</Label>
		<Label name="Speedlabel" label="0">
			<Metrics type="rel" x="0.5" y="0.4" w="0.3" h="0.15" />
			<Center h="0" v="1" />
			<Align value="6" />
		</Label>
		<Image name="" img="IcoWorld">
			<Metrics type="rel" x="0.075" y="0.6" w="0.05" h="1.0" />
			<Center h="0" v="1" />´
			<BorderRel value="1" />
		</Image>
		<Label name="" label="Range">
			<Metrics type="rel" x="0.3" y="0.6" w="0.4" h="0.15" />
			<Center h="0" v="1" />
			<Align value="4" />
		</Label>
		<Label name="Rangelabel" label="0">
			<Metrics type="rel" x="0.5" y="0.6" w="0.3" h="0.15" />
			<Center h="0" v="1" />
			<Align value="6" />
		</Label>
		<Image name="" img="IcoStar">
			<Metrics type="rel" x="0.075" y="0.8" w="0.05" h="1.0" />
			<Center h="0" v="1" />´
			<BorderRel value="1" />
		</Image>
		<Label name="" label="Level">
			<Metrics type="rel" x="0.3" y="0.8" w="0.4" h="0.15" />
			<Center h="0" v="1" />
			<Align value="4" />
		</Label>
		<Label name="Levellabel" label="0">
			<Metrics type="rel" x="0.5" y="0.8" w="0.3" h="0.15" />
			<Center h="0" v="1" />
			<Align value="6" />
		</Label>
	</Image>
	<Label name="Namelabel" label="">
		<Align value="1" />
		<Metrics type="rel" x="0.0" y="0.05" w="1.0" h="0.2" />
	</Label>
	<Button name="Upgradebutton" label="Upgrade: 0">
		<Metrics type="rel" x="0.275" y="0.775" w="0.4" h="0.175" />	
		<Center h="1" v="0" />
		<Image name="" img="IcoUpgrade">
			<Disabled/>
			<Metrics type="rel" x="0.075" y="0.5" w="1.0" h="0.5" />
			<Center h="0" v="1" />´
			<BorderRel value="2" />
		</Image>
	</Button> 
	<Button name="Sellbutton" label="Sell: 0">
		<Metrics type="rel" x="0.725" y="0.775" w="0.4" h="0.175" />	
		<Center h="1" v="0" />
		<Image name="" img="IcoMoney">
			<Disabled/>
			<Metrics type="rel" x="0.075" y="0.5" w="1.0" h="0.5" />
			<Center h="0" v="1" />´
			<BorderRel value="2" />
		</Image>
	</Button>
</Controller>

Still a lot of code, but at least there is some consistency ;)

2

Share this post


Link to post
Share on other sites

Here's the code that I generally write to assemble UI's. This one in particular is in Java and assembles a UI for the lobby of an online card game (screenshot below). As you can see, I take some of the more interesting UI components into their own classes so that I don't have to worry about their function at the same time that I'm worrying about the spatial relationships of the components. 

package residentevil.game.ui.lobby;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.HashMap;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import library.menu.MenuScreen;
import library.menu.MenuStack;
import residentevil.cards.Card;
import residentevil.cards.Character;
import residentevil.game.ui.CardButton;
import residentevil.game.ui.CardPreviewControl;
import residentevil.game.ui.CardPreviewPanel;

public class LobbyScreen extends MenuScreen implements ActionListener {
   private final static String READY_ACTION = "Ready";
   private final static String CHARACTER_SELECT_ACTION = "Character Selection";
   private final static String QUIT_ACTION = "Quit";

   private final static int CARD_PREVIEW_PANEL_WIDTH = 250;
   private final static Dimension MAX_BUTTON_SIZE = new Dimension(126, 56);
   private final static int STRUT_SIZE = 15;
   
   private final static float PLAYER_LIST_SIZE_PERCENTAGE = 0.32f;
   private final static float CHARACTER_BUTTON_PANEL_SIZE_PERCENTAGE = 0.45f;
   
   private MenuStack mMenuStack;
   
   private CardPreviewPanel mCardPreview;
   private CardPreviewControl mCardPreviewControl;
   
   private HashMap<String, PlayerStatus> mPlayers;
   private PlayerTableModel mPlayerList;
   private JScrollPane mPlayerTablePanel;
   
   private CardSelectionPanel mCharacterCardPanel;
   private StatusListener mStatusListener;
   
   public LobbyScreen(MenuStack menuStack) {
      super();
      
      mMenuStack = menuStack;
      mPlayers = new HashMap<>();
      
      createWidgets();
      addComponentListener();
      
      mStatusListener = new StatusListener() {
         public void toggleReady() { }
         public void changeCharacter(String characterName) { }
         public void quit() {  }
      };
   }
   
   private void addComponentListener() {
      addComponentListener(new ComponentListener() {
         @Override
         public void componentResized(ComponentEvent e) {
            resizePlayerTablePanel();
            mCharacterCardPanel.resizeCardSelectionPanel(CHARACTER_BUTTON_PANEL_SIZE_PERCENTAGE);
            revalidate();
            repaint();
         }
         @Override
         public void componentHidden(ComponentEvent e) {}
         @Override
         public void componentMoved(ComponentEvent e) {}
         @Override
         public void componentShown(ComponentEvent e) {}
      });
   }
   
   /*************************************************************************************
    *                                    UI ASSEMBLY                                    *
    *************************************************************************************/
   
   private void createWidgets() {
      setLayout(new BorderLayout());
      
      createPreviewPanel();
      createMainPanel();
   }
   
   private void createPreviewPanel() {
      mCardPreview = new CardPreviewPanel();
      mCardPreview.setPreferredSize(new Dimension(CARD_PREVIEW_PANEL_WIDTH, Integer.MAX_VALUE));
      mCardPreviewControl = new CardPreviewControl(mCardPreview);
      add(mCardPreview, BorderLayout.WEST);
   }
   
   private void createMainPanel() {
      JPanel mainPanel = new JPanel();
      mainPanel.setOpaque(false);
      mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
      
      createConnectedPlayersTable(mainPanel);
      mainPanel.add(Box.createVerticalStrut(STRUT_SIZE));
      createCharacterSelectionPanel(mainPanel);
      mainPanel.add(Box.createVerticalStrut(STRUT_SIZE));
      createControlButtons(mainPanel);
      mainPanel.add(Box.createVerticalStrut(STRUT_SIZE));
      
      add(mainPanel, BorderLayout.CENTER);
   }
   
   private void createConnectedPlayersTable(JPanel mainPanel) {
      mPlayerList = new PlayerTableModel();
      JTable playerTable = new JTable(mPlayerList);
      playerTable.setAlignmentX(Component.CENTER_ALIGNMENT);
      
      mPlayerTablePanel = new JScrollPane(playerTable);
      resizePlayerTablePanel();
      
      mainPanel.add(mPlayerTablePanel);
   }
   
   private void resizePlayerTablePanel() {
      Dimension parentSize = getSize();
      Dimension preferredSize = new Dimension(parentSize);
      preferredSize.height = (int)(parentSize.height*PLAYER_LIST_SIZE_PERCENTAGE);
      mPlayerTablePanel.setPreferredSize(preferredSize);
   }
   
   private void createCharacterSelectionPanel(JPanel mainPanel) {
      JLabel charactersLabel = new JLabel("Characters");
      charactersLabel.setForeground(Color.WHITE);
      charactersLabel.setAlignmentX(CENTER_ALIGNMENT);
      
      mCharacterCardPanel = new CardSelectionPanel(mCardPreviewControl, this, CHARACTER_SELECT_ACTION);
      mCharacterCardPanel.resizeCardSelectionPanel(CHARACTER_BUTTON_PANEL_SIZE_PERCENTAGE);
      
      mainPanel.add(charactersLabel);
      mainPanel.add(mCharacterCardPanel);
   }
   
   private void createControlButtons(JPanel mainPanel) {
      JPanel buttonPanel = new JPanel();
      buttonPanel.setOpaque(false);
      buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
      
      JButton startButton = createButton("Ready", READY_ACTION);
      JButton quitButton = createButton("Quit", QUIT_ACTION);
      
      buttonPanel.add(startButton);
      buttonPanel.add(quitButton);
      
      mainPanel.add(buttonPanel);
   }
   
   private JButton createButton(String title, String action) {
      JButton button = new JButton(title);
      button.setActionCommand(action);
      button.addActionListener(this);
      button.setMaximumSize(MAX_BUTTON_SIZE);
      return button;
   }
   
   /***************************************************************************
    *                                INTERFACE                                *
    ***************************************************************************/
   
   public void setStatusListener(StatusListener statusListener) {
      mStatusListener = statusListener;
   }
   
   public void addPlayer(String playerName) {
      PlayerStatus status = new PlayerStatus();
      status.mName = playerName;
      status.mCharacter = "Unknown";
      status.mReady = false;
      
      mPlayers.put(playerName, status);
      mPlayerList.addPlayer(status);
   }
   
   public void updatePlayerStatus(String playerName, String characterName, boolean ready) {
      PlayerStatus status = mPlayers.get(playerName);
      status.mCharacter = characterName;
      status.mReady = ready;
      mPlayerList.fireTableDataChanged();
   }
   
   public void removePlayer(String playerName) {
      PlayerStatus status = mPlayers.get(playerName);
      mPlayers.remove(playerName);
      mPlayerList.removePlayer(status);
   }
   
   public void addCharacterCards(Character cards[]) {
      mCharacterCardPanel.removeAll();
      mCharacterCardPanel.createCardButtons(cards);
      revalidate();
      repaint();
   }

   @Override
   public void actionPerformed(ActionEvent actionEvent) {
      String command = actionEvent.getActionCommand();
      
      if(command.equals(READY_ACTION)) {
         mStatusListener.toggleReady();
      } else if(command.equals(CHARACTER_SELECT_ACTION)) {
         CardButton cardButton = (CardButton)actionEvent.getSource();
         Card card = cardButton.getCard();
         mStatusListener.changeCharacter(card.getName());
      } else if(command.equals(QUIT_ACTION)) {
         mStatusListener.quit();
         mMenuStack.popScreen();
      }
   }
}

Unfortunately, this is probably one of the more tame UI code that I have XD 

 

Here is a screenshot of the lobby:
RELobbyUI.png

 

The pink squares are where that card images are. I blocked them out because they are not my work and I don't want to violate any rules :) Basically, when the player hovers above the cards, information about the card is updated in the panels on the left.

0

Share this post


Link to post
Share on other sites

I'm looking forward to writing my own GUI framework for my current project. I've written one before but it used SDL surfaces and real-time transformations (SDL_gfx), so it was very slow and painful to think about. I've written buttons so far in my current one (OpenGL based) and they look nice, but I'm still pondering how to do the other controls like text input and listviews.
 

Originally I planned on emulating DOS/ncurses style GUIs since that would be much easier to do and I already have an output system for that, but it wouldn't fit with the cartoony look of the rest of the application which is a shame.

Edited by Nüb?ek Pænus
0

Share this post


Link to post
Share on other sites

This reminds me of the reasons why I wrote simplui, once upon a time: roughly 90% of the time, what one actually needs is an immediate-mode GUI with auto-layout.

 

Of course, the corollary to that rule is that the other 10% of the time you need the whole of QT, and anything less is miserable.

1

Share this post


Link to post
Share on other sites

I'm about to take on the adventure of writing the GUI's for my game. I hope it looks better although I promise nothing!

0

Share this post


Link to post
Share on other sites

I'm also writing the GUI for my game from scratch. I would recommend you to use XML to create your windows/panels instead of pure code. That helped me to separate the code to create a new window into different modules while parsing the XML. I use TinyXML2.

0

Share this post


Link to post
Share on other sites

I'm also writing the GUI for my game from scratch. I would recommend you to use XML to create your windows/panels instead of pure code. That helped me to separate the code to create a new window into different modules while parsing the XML. I use TinyXML2.

 

 

Yep, that helped a lot for me too. I was so crazy though, and wrote my own XML-Parser. No reason, just madness (and probably a bit learning-factor). I also gotta say that one thing that probably makes my gui a little more complicated than it should be, is that I'm not only using it for the game, but also for the editor/toolchain. When you want to do somthing like I did in the attached screenshot, it adds some additional levels of complications in comparison to when you "only" need some simple game overlays, I assume.

0

Share this post


Link to post
Share on other sites

There's just no way to write a fully configurable and flexible GUI system without having to specify a lot of data, either by hand or by config file. So don't feel too bad.

 

First, look at the new JavaFX stuff for GUIs that just came out with Java 8.  They had to rewrite EVERYTHING from Swing because it no longer worked.  So GUI code is hard.  

 

I am of two minds on this one.  I've coded up lots of GUIs in my career, from Win32, MFC, all the way to Scheme, Java, and Javascript Web 2.0, and I have experienced so many little issues and work arounds that I know trying to create your own GUI APA is waste of time.  There are too many details to work out.

 

However, that's not for a game, that's for an API used by a million people.  For a game, if you don't roll your own, then your GUI will look just like everyone else.  Creating your own controls could lead to some awesome innovation.  But as pointed out above, if you try to make a super flexable, robust, easy-to-use, well-documented GUI library that can be used by millions of beginning programmers to create amazing GUIs, you'll run out of time.

 

Long story short (too late), don't worry if it looks bad.  That means you didn't over-engineer it, which is a good thing.

Edited by Glass_Knife
2

Share this post


Link to post
Share on other sites
I don't get the overemphasis regarding code structure. Sure this code isn't exactly an example of how beautiful code looks like but if it works, is tailored to exactly what you need and you and/or your coworkers see through it - well why not?
0

Share this post


Link to post
Share on other sites

 

 

I'm also writing the GUI for my game from scratch. I would recommend you to use XML to create your windows/panels instead of pure code. That helped me to separate the code to create a new window into different modules while parsing the XML. I use TinyXML2.

 

 

Yep, that helped a lot for me too. I was so crazy though, and wrote my own XML-Parser. No reason, just madness (and probably a bit learning-factor). I also gotta say that one thing that probably makes my gui a little more complicated than it should be, is that I'm not only using it for the game, but also for the editor/toolchain. When you want to do somthing like I did in the attached screenshot, it adds some additional levels of complications in comparison to when you "only" need some simple game overlays, I assume.

 

 

Yes it seems a lot more complicated than mine. However, if I were to create a level editor (not applicable to my game) I think I would use an already existing GUI, it's not so easy to find a OpenGL or DirectX GUI, though. Because since the editor is ¨not part¨ of the game it wouldn't matter if the GUI is ugly and already used in other projects, that could actually be a point in your favor because people may be already used to that aspect or feeling of the GUI. But... I don't know, I guess that if you implemented your own XML parser is because you're using it as a learning process so it's better to do everything by yourself. biggrin.png  

0

Share this post


Link to post
Share on other sites

Yes it seems a lot more complicated than mine. However, if I were to create a level editor (not applicable to my game) I think I would use an already existing GUI, it's not so easy to find a OpenGL or DirectX GUI, though. Because since the editor is ¨not part¨ of the game it wouldn't matter if the GUI is ugly and already used in other projects, that could actually be a point in your favor because people may be already used to that aspect or feeling of the GUI. But... I don't know, I guess that if you implemented your own XML parser is because you're using it as a learning process so it's better to do everything by yourself. biggrin.png

 

Yeah, if I were to go back and start over I would probably use an existing gui system too. Not to say that I can't work with my own gui and that there isn't some neat stuff that probably ties in better to my overall system than an external libary would, but there is almost at least one "WTF? why is it doing that (again)???" every day biggrin.png . But you said it right, its all part of a giant learning process, for that reason I've decided to enroll almost everything on my own. But it really paid off, I've been learning so much let alone via the gui system about decoupling systems, and (ironically, looking at my first post) writing cleaner and more maintainably code. My old projects always died after a few months because the code became too messy for me to work with, this engine I'm working on for about 1 1/2 years, and still going. So people are right in a way that writing your own big guid lib for something like editor is a waste of time, but only unless for the learning experience, that is.

Edited by Juliean
1

Share this post


Link to post
Share on other sites

Eh, your code actually looks pretty slick, considering you're doing GUI programming. Also, the "established libraries" for GUIs are notoriously bulky, so hand-rolling a solution is actually a viable option in this case.

0

Share this post


Link to post
Share on other sites

A lot of folks do not like "losing creating control" by using 3rd party GUI libraries ...

... that and a lot of free libraries have almost no good documentation that comes with it.

0

Share this post


Link to post
Share on other sites

In my own table-driven programming language (Steamroller), I would just put all the values and method pointers in a table and read it from a tiny loop. I just haven't been able to connect the language to a graphics API yet.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0