I have written some simple user interface code for my game and actually finished a simple seek-and -find style game. What worries me is that 'Im doing it wrong'. The way it works in a nutshell is the mouse event is captured by the window-procedure and depending on what screen the user is on (i.e.game State), a function is called that checks the position and does whatever processing is required.
Is this a reasonable way to go? It meant I have a different ' mouse button pressed' function for every screen, title screen, options, in-game. Somehow it seemed a bit....er....crap
Maybe Im being paranoid, would like to hear from someone who knows what they are doing a bit more. Here is my button class in case it clarifys things:
class button
{
public:
button();
button(RECT);
~button();
void setID(unsigned int);
unsigned int getID();
int getSpriteID();
void setSpriteID( int);
RECT getPosition();
unsigned int getSelectionInfo();
void setSelectionInfo(unsigned int);
bool isEnabled();
void setEnabled(bool);
button* getNext();
void setNext(button*);
bool* getCollisionMask();
bool setCollisionMask(IDirect3DTexture9*, DWORD, DWORD);
void delCollisionMask();
private:
unsigned int id;//unique identifier 0..n
int spriteID;//array index for source rectange within bmp
RECT position;//screen position
unsigned int selectionInfo;//flag
bool enabled;
bool* collisionMask;
button* next;//next in list
};
How should UI work
You could simply add more info to the event to include button name, parent window name, etc. Then it would be easier to parse through. You can also just do it the way windows forms does it and create a separate event for each button action. There's no right/wrong way really, it depends on how much functionality you need and how extendable you want it to be. Just consider how your code is going to look once you start having 100s of buttons (if you ever will) and consider how you could put the handlers in different classes, and if that requires changed object design. This is some general advice, but really you shouldn't worry too much imho.
OK thanks good to know its not totally wrong. By the way though, I cant add more info to the event as I did not create the event, that was done automatically by windows.
This is the code:
LRESULT CALLBACK WindowProcedure(HWND win, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
switch(uMessage)//Check message
{
case WM_LBUTTONDOWN:lastCoords = MAKEPOINTS (lParam);
mainMenu.press(mainMenu.checkCoordinates(lastCoords.x,lastCoords.y));
break;
case WM_LBUTTONUP:coords = MAKEPOINTS (lParam);
switch (currentState)
{
case GS_PLAYING:playscreenButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
break;
case GS_MAINMENU:if (mainMenu.pressedID() !=-1)
{
mainmenuButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
}
break;
case GS_OPTIONS:optionscreenButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
break;
}
This is the code:
LRESULT CALLBACK WindowProcedure(HWND win, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
switch(uMessage)//Check message
{
case WM_LBUTTONDOWN:lastCoords = MAKEPOINTS (lParam);
mainMenu.press(mainMenu.checkCoordinates(lastCoords.x,lastCoords.y));
break;
case WM_LBUTTONUP:coords = MAKEPOINTS (lParam);
switch (currentState)
{
case GS_PLAYING:playscreenButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
break;
case GS_MAINMENU:if (mainMenu.pressedID() !=-1)
{
mainmenuButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
}
break;
case GS_OPTIONS:optionscreenButtonUp(mainMenu.checkCoordinates(coords.x,coords.y),win);
break;
}
A good scalable solution would be to create two components: a button and a container. They should both have a rectangle, to declare their bounds.
For each screen you have you should add one container the size of the screen. In each of those containers you should then add the buttons, so their bounds are inside the containers bounds.
When ever a user clicks the screen, the click should be passed on to the active container, which should iterate through all its children to test if the click was inside any of those. If it was the click should be passed on to that button.
This is scalable, since you can add other components than buttons inside the containers, like check boxes or canvases or even other containers.
For each screen you have you should add one container the size of the screen. In each of those containers you should then add the buttons, so their bounds are inside the containers bounds.
When ever a user clicks the screen, the click should be passed on to the active container, which should iterate through all its children to test if the click was inside any of those. If it was the click should be passed on to that button.
This is scalable, since you can add other components than buttons inside the containers, like check boxes or canvases or even other containers.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement