Funny, when I want to develop something as quickly as possible, I make it flexible...
It takes time to design something to be flexible. You have to consider all possibilities for its use. Do you deny that it is faster to write simple programs using global variables and arrays than to carefully design types which are far more powerful?
My sprite system for example. Easier in the short run to just create an array to hold loaded images and an array of XY positions and health and a count of how many monsters there are and shuffle that stuff around as they are created and destroyed... But not very flexible when you want to start animating them with the same automated system that animates all your other objects. Yet it takes far longer to properly design and code the sprite system than it does to use the arrays. But if you us the arrays you end up with spaghetti code that gets harder and harder to maintain and add to as it gets bigger.
Which is just what happened with Builder Bots. I was in a rush, I used the equivalent of arrays for the menus. I didn't design the loop in a way which was easy to read. I didn't bother trying to figure out what should be stuck in a function outside the main loop.
Your sprite system isn't that good, the ABSOLUTELY CRAZY way you stuck everything in an array was just, well... aboslutely crazy.
Now wait just a minute. Im gonna assume you're talking about my BlitzPlus sprite system which is a whole different beast than my BlitzMax one, but neither uses arrays to store anything.
I think what you're talking about is how in the main program I used arrays to store the pointers to the images the robots needed and stuff:
Const TOTAL_ROBOT_CLASSES = 4
Const TOTAL_ROBOT_COLORS = 4
Const TOTAL_ROBOT_ANIMATIONS = 12
Dim IMG_Robot.IMG(TOTAL_ROBOT_COLORS, TOTAL_ROBOT_CLASSES, TOTAL_ROBOT_ANIMATIONS) ; Images of robots: IMG_Robot(Color, Class, Animation)
Global Building_Bot_Color ; This is the color of the robot the player is currently building.
Global Building_Bot_Class ; This is the class of the robot the player is currently building.
Dim Robot_Blocks_Needed(TOTAL_ROBOT_CLASSES) ; This is the number of bricks needed to construct a particular class of robot.
Robot_Blocks_Needed(0) = 6
Robot_Blocks_Needed(1) = 12
Robot_Blocks_Needed(2) = 18
Robot_Blocks_Needed(3) = 24
; These are values which are loaded from the config file at the start of each level:
Global RECYCLE_BIN_SPEED = 400 ; The speed at which the recycle bins move in pixels per second.
Dim Default_Robot_Color_Weight(TOTAL_ROBOT_COLORS) ; These arrays define the probaiblity that a particular color of robot will appear.
Dim Robot_Color_Weight(TOTAL_ROBOT_COLORS) ; Why do I store defaults?
Dim Default_Robot_Class_Weight(TOTAL_ROBOT_CLASSES) ; These arrays define the probaiblity that a particular class of robot will appear.
Dim Robot_Class_Weight(TOTAL_ROBOT_CLASSES)
Dim Robot_Build_Repeats(TOTAL_ROBOT_CLASSES) ; This is the number of times the robot's build animation repeats.
Dim Robot_Pattern_Bricks(TOTAL_ROBOT_CLASSES) ; This is the number of bricks each robot class will place at one time
Dim Robot_Pattern_Area(TOTAL_ROBOT_CLASSES, 2) ; This is the size of the area in which the robot can place those bricks. In the form of an X and Y radius. Pattern only extends up in Y direction, so if the Y radius is three, the area built in will be three bricks tall.
Dim Robot_Walk_Speed(TOTAL_ROBOT_CLASSES) ; This is the speed at which each class of robot moves in pixels per second.
Dim Robot_Recharge_Time(TOTAL_ROBOT_CLASSES) ; This is the number of milliseconds it takes each class of robot to recharge.
Dim Robot_Lifespan(TOTAL_ROBOT_CLASSES) ; This is the default lifespan of this class of robot.
And while I might do this differently if I had more than four classes to worry about, this is hardly any more difficult to use than it would have been if I created a type with one field for each of those properties and created four instances of that and referenced those instead for the properties of the class.
As for the individual robots, those has a type to handle them:
Type Robot
Field BOB.BOB ; This is the pointer to the sprite that represents the object.
Field Robot_Color
Field Robot_Class
Field X#, Y#
Field Vy#
Field Speed_X#, Direction_X#
Field State
Field Life_Remaining
Field NextFlash ; This is the time at which the robot should next go from visible to hidden, or vice versa.
Field FlashState
Field NextBrickTime ; This is the time at which the robot should next place a brick.
Field Expiring
Field Paused
Field RecycleBin.BOB ; This is the BOB that represents the recycle bin currently moving to collect the robot.
Field RecycleBinWheels.BOB
Field LastSpeedEffectTime
End Type
I also noticed that in the end I did end up cleaning up the menu system and making types and functions for it. Not as tidy as what I could do now in BlitzMax, but that was a limitation of the language.
The real problem was the main loop being messy with gosubs to try to move sections of code out of the main loop to make things easier to read, and a horrible state system which results in a big case statement with lots of code in it. I still haven't come up with a good solution for that, but at least the state systems I'm currently using are a bit neater and tider than this:
; --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.Get_Input
; Get any pending events.
; Pause app if application loses focus.
EventHandler()
; Get mouse input.
Old_Mouse_X = Mouse_X
Old_Mouse_Y = Mouse_Y
If Not Windowed
; Fullscreen.
If MouseDown(1) Then MouseDown_Left = True
If MouseDown(2) Then MouseDown_Right = True
If MouseDown(3) Then MouseDown_Middle = True
If MouseHit(1) Then MouseHit_Left = True
If MouseHit(2) Then MouseHit_Right = True
If MouseHit(3) Then MouseHit_Middle = True
Mouse_X = MouseX()
Mouse_Y = MouseY()
Else
; Windowed.
; In windowed mode, the MouseDown and MouseHit variables are updated in the event handler.
Mouse_X = MouseX(Window_Canvas)
Mouse_Y = MouseY(Window_Canvas)
EndIf
MouseSpeed_X = Mouse_X - Old_Mouse_X
MouseSpeed_Y = Mouse_Y - Old_Mouse_Y
; Recenter the mouse if desired.
; Recentering the mouse allows MouseSpeed to work
If Mouse_ForceRecenter
If Windowed
MoveMouse SCREEN_WIDTH/2, SCREEN_HEIGHT/2, Window_Canvas
Else
MoveMouse SCREEN_WIDTH/2, SCREEN_HEIGHT/2
EndIf
Mouse_X = SCREEN_WIDTH/2
Mouse_Y = SCREEN_HEIGHT/2
EndIf
Select True
; Logos are being displayed.
Case (GLOBAL_State >= GS_BUILDERBOTS_LOGO_FADING_IN) And (GLOBAL_State <= GS_RETRO64_LOGO_PAUSE2)
; If the ESC key or the SPACEBAR is pressed while the logos are being displayed, skip directly to the main menu.
If (KeyHit(KEY_ESC) = True) Or (KeyHit(KEY_SPACE) = True) Or (MouseHit_Left = True)
GotoMainMenu()
EndIf
; The game is displaying a menu.
; This could be over the gameplay screen, or over a background of clouds.
; When a menu is active, no input will go to the game, and a mouse cursor may be displayed in addition to the catcher.
; The catcher will not move with the mouse however.
Case GLOBAL_State = GS_MENU_ACTIVE
; If the left mouse button is no longer down, deselect the selected menu item.
If (MouseDown_Left = False) Then Selected_Menu_Item = 0
; If the user has clicked on a menu button with the left mouse button, select it.
If MouseDown_Left
For Loop = 1 To MAX_MENU_ITEMS-1
Select True
; Ths following should not be treated like buttons:
; I really ought to have made the menus have a number to tell what the last item that is clickable is.
Case (Active_Menu = MENU_MAIN) And (Loop > 8) ; Arcade/advanced togggle button special states
Case (Active_Menu = MENU_HELP) And (Loop > 2) ; The text on the context sensitive help menu.
Case (Active_Menu = MENU_HELP_ARCADE) And (Loop > 3) ; The text on the arcade help menu.
Case (Active_Menu = MENU_HELP_ADVANCED) And (Loop > 3) ; The text on the advanced help menu.
Case (Active_Menu = MENU_PLAYERSELECT) And (Loop > 14) ; The player selection outlines on the player selection screen.
Case (Active_Menu = MENU_LEVELSTART) And (Loop > 0) ; Level numbers
Case (Active_Menu = MENU_CREDITS) And (Loop > 1) ; The credit scroll.
Case (Active_Menu = MENU_HIGHSCORES) And (Loop > 1) ; The alternate background.
Case (Active_Menu = MENU_OPTIONS) And (Loop > 6) ; Checks for help and fulslcreen buttons.
; What to do if this item is a button:
Case True
; If a BOB exists for this menu item...
If BOB_Menu(Active_Menu, Loop) <> Null
; If the top left pixel of the mouse cursor is over it...
If BOB_RectOverlap(BOB_Menu(Active_Menu, Loop), Mouse_X, Mouse_Y, 1, 1)
; If the left mouse button was clicked...
If (MouseHit_Left = True)
; Play a click sound.
PlaySND(3)
; Record which menu item was clicked.
Selected_Menu_Item = Loop
Last_Selected_Menu_Item = Selected_Menu_Item
Last_Active_Menu = Active_Menu
; Exit loop.
Exit
EndIf
EndIf
EndIf
End Select
Next
EndIf
; Highlight the menu item which the mouse is hovering over.
; If no menu item is currently selected...
If Selected_Menu_Item = 0
For Loop = 1 To MAX_MENU_ITEMS-1
Select True
; This item is not a button:
Case (Active_Menu = MENU_MAIN) And (Loop > 8) ; Arcade/advanced togggle button special states
Case (Active_Menu = MENU_HELP) And (Loop > 2) ; The text on the context sensitive help menu.
Case (Active_Menu = MENU_HELP_ARCADE) And (Loop > 3) ; The text on the arcade help menu.
Case (Active_Menu = MENU_HELP_ADVANCED) And (Loop > 3) ; The text on the advanced help menu.
Case (Active_Menu = MENU_PLAYERSELECT) And (Loop > 14) ; The player selection outlines on the player selection screen.
Case (Active_Menu = MENU_LEVELSTART) And (Loop > 0) ; Level numbers
Case (Active_Menu = MENU_CREDITS) And (Loop = 2) ; The credit scroll.
Case (Active_Menu = MENU_HIGHSCORES) And (Loop > 1) ; The alternate background.
Case (Active_Menu = MENU_OPTIONS) And (Loop > 6) ; Checks for help and fulslcreen buttons.
; This item is a button:
Case True
; If a BOB exists for this menu item...
If BOB_Menu(Active_Menu, Loop) <> Null
; If the top left pixel of the mouse cursor is over this menu item...
If BOB_RectOverlap(BOB_Menu(Active_Menu, Loop), Mouse_X, Mouse_Y, 1, 1)
; If this menu item is not hidden...
If BOBHidden(BOB_Menu(Active_Menu, Loop))
Select True
Case (Active_Menu = MENU_PLAYERSELECT) And (Loop > 4)
; This is a player selection highlight.
; Do nothing.
Default
; Highlight menu item and play a sound.
ShowBOB(BOB_Menu(Active_Menu, Loop))
PlaySND(2)
End Select
EndIf
Else
; The mouse isn't over this menu item. Hide the menu item's highlight.
Select True
; This is a button whose highlight image should never be hidden:
Case (Active_Menu = MENU_GALLERY) And (Loop >= 5) ; This is one of the thumbnails in the gallery. Don't hide it.
Case (Active_Menu = MENU_GALLERYZOOM) ; This is a zoomed image in the gallery. Don't hide it.
Case (Active_Menu = MENU_PLAYERSELECT) And (Loop >= 5) ; This is a a player name selection box on the player selection screen. Don't hide it.
; This is a normal button:
Default
; Hide the highlight for this menu item.
HideBOB(BOB_Menu(Active_Menu, Loop))
End Select
EndIf
EndIf
End Select
Next
EndIf
; If a menu item is selected, perform the appropriate action.
Select Active_Menu
Case MENU_MAIN
; ESC = Quit
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 6
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_MAIN_Play()
Case 2 MENU_MAIN_Toggle()
Case 3 MENU_MAIN_Options()
Case 4 MENU_MAIN_HighScores()
Case 5 MENU_MAIN_Help()
Case 6 MENU_MAIN_Quit()
Case 7 MENU_MAIN_Gallery()
Case 8 MENU_MAIN_PlayerSelect()
End Select
Case MENU_PLAYERSELECT
; ESC = Cancel
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 3
; DEL = Delete
If KeyHit(KEY_DELETE)
Selected_Menu_Item = 2
MouseHit_Left = True ; Need to do this because function checks mouse state to avoid repeating.
EndIf
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_PLAYERSELECT_NewPlayer()
Case 2 MENU_PLAYERSELECT_Delete()
Case 3 MENU_PLAYERSELECT_Cancel()
Case 4 MENU_PLAYERSELECT_Okay()
Case 5,6,7,8,9,10,11,12,13,14 MENU_PLAYERSELECT_PlayerHighlight(Selected_Menu_Item-5)
End Select
Case MENU_NAMEENTRY
; ESC = Cancel
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; ENTER = Ok
If KeyHit(KEY_ENTER) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_NAMEENTRY_Cancel()
Case 2 MENU_NAMEENTRY_Okay()
End Select
; Record keystrokes.
Key = GetKey()
; Was a key hit?
If Key <> 0
; Is the key in the allowed character set?
If Instr(FONT_PlayerName\CharacterSet$, Chr$(Key))
; Is the player name being edited shorter than the allowed maximum length?
If Len(GLOBAL_NewName$) < 30
; Add character to player name being edited.
GLOBAL_NewName$ = GLOBAL_NewName$ + Chr$(Key)
; Update name display.
UpdateText(TEXT2D_PlayerNameEntry, GLOBAL_NewName$)
; Play keyclick sound.
PlaySND(4)
Else
; Player is trying to enter too many characters into text field.
; Play error beep.
EndIf
Else
; Is this key a backspace?
If (Key = 8)
; Are there are characters in the player name being edited?
If Len(GLOBAL_NewName$) > 0
; Remove one character from the end of the player name.
GLOBAL_NewName$ = Left$(GLOBAL_NewName$, Len(GLOBAL_NewName$)-1)
; Update name display.
UpdateText(TEXT2D_PlayerNameEntry, GLOBAL_NewName$)
; Play keyclick sound.
PlaySND(4)
Else
; No characters to delete.
; Play error beep.
EndIf
EndIf
EndIf
EndIf
Case MENU_ARCADE
; ESC = Cancel
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_ARCADE_Cancel()
Case 2 MENU_ARCADE_Continue()
Case 3 MENU_ARCADE_NewGame()
End Select
Case MENU_ADVANCED
; ESC = Cancel
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_ADVANCED_Cancel()
Case 2 MENU_ADVANCED_Continue()
Case 3 MENU_ADVANCED_NewGame()
End Select
Case MENU_OPTIONS
; Display and position the sliders.
ShowBOB(BOB_Menu(MENU_OPTIONS, 4))
ShowBOB(BOB_Menu(MENU_OPTIONS, 5))
; Show the radio button dot if fullscren mode is active.
;
; Doing this causes the button to click repeatedly while the mouse is over it in windowed mode, presumably because it is being hidden
; and the above code shows a hidden button and plays a click if the mouse is over it.
; HideBOB(BOB_Menu(Active_Menu, 6))
; If Not Windowed Then ShowBOB(BOB_Menu(Active_Menu, 6))
; ESC = Main Menu
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_OPTIONS_Credits()
Case 2 MENU_OPTIONS_MainMenu()
Case 3 MENU_OPTIONS_ContextualHelp()
Case 4 MENU_OPTIONS_SoundFXSlider()
Case 5 MENU_OPTIONS_MusicSlider()
Case 6 MENU_OPTIONS_Fullscreen()
End Select
Case MENU_HIGHSCORES
; ESC = Main Menu
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_HIGHSCORES_MainMenu()
End Select
Case MENU_CREDITS
; ESC = Main Menu
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_CREDITS_MainMenu()
End Select
Case MENU_BUYNOW
; ESC = No Thanks.
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_BUYNOW_BuyNow()
Case 2 MENU_BUYNOW_NoThanks()
End Select
Case MENU_LEVELSTART
; ESC, SPACE, ENTER. LEFT MOUSE BUTTON = Proceed
If (KeyHit(KEY_SPACE) = True) Or (KeyHit(KEY_ESC) = True) Or (MouseHit_Left = True) Or (KeyHit(KEY_ENTER) =True) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_LEVELSTART_Proceed()
End Select
Case MENU_PAUSE
; P = Resume
If (KeyHit(KEY_P) = True) Then Selected_Menu_Item = 1
; ESC = Main Menu
If (KeyHit(KEY_ESC) = True) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_PAUSE_ResumeGame()
Case 2 MENU_PAUSE_ExitToMainMenu()
End Select
Case MENU_LEVELEND
; ESC, SPACE, ENTER. LEFT MOUSE BUTTON = Proceed
; If (KeyHit(KEY_ESC) = True) Then Selected_Menu_Item = 2
; ESC, SPACE, ENTER. LEFT MOUSE BUTTON = Proceed
If (KeyHit(KEY_SPACE) = True) Or (KeyHit(KEY_ESC) = True) Or (MouseHit_Left = True) Or (KeyHit(KEY_ENTER) =True) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_LEVELEND_Proceed()
Case 2 MENU_LEVELEND_MainMenu()
End Select
Case MENU_GAMEOVER
; ESC, SPACE, ENTER = Main Menu
If (KeyHit(KEY_SPACE) = True) Or (KeyHit(KEY_ESC) = True) Or (KeyHit(KEY_ENTER) = True) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_GAMEOVER_PlayAgain()
Case 2 MENU_GAMEOVER_MainMenu()
End Select
Case MENU_GALLERY
; ESC = Main Menu
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 3
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_GALLERY_LeftArrow()
Case 2 MENU_GALLERY_RightArrow()
Case 3 MENU_GALLERY_MainMenu()
;Case 4 MENU_GALLERY_Print()
Case 5,6,7,8,9 MENU_GALLERY_GalleryImage(Selected_Menu_Item-5)
End Select
Case MENU_GALLERYZOOM
; ESC = Image clicked
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_GALLERYZOOM_Image()
End Select
Case MENU_HELP
; ESC = Okay clicked.
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_HELP_TurnOffHelpMessage()
Case 2 MENU_HELP_Okay()
End Select
Case MENU_HELP_SELECT
; ESC = Main Menu
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 3
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_HELP_SELECT_Arcade()
Case 2 MENU_HELP_SELECT_Advanced()
Case 3 MENU_HELP_SELECT_MainMenu()
End Select
Case MENU_HELP_ARCADE
; ESC = Done
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_HELP_ARCADE_Done()
Case 2 MENU_HELP_ARCADE_LeftArrow()
Case 3 MENU_HELP_ARCADE_RightArrow()
End Select
Case MENU_HELP_ADVANCED
; ESC = Done
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 1
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_HELP_ADVANCED_Done()
Case 2 MENU_HELP_ADVANCED_LeftArrow()
Case 3 MENU_HELP_ADVANCED_RightArrow()
End Select
Case MENU_CONFIRM_ENDGAME
; ESC = Done
If KeyHit(KEY_ESC) Then Selected_Menu_Item = 2
; If a menu item was selected, perform the action linked to it.
Select Selected_Menu_Item
Case 1 MENU_CONFIRM_ENDGAME_Cancel()
Case 2 MENU_CONFIRM_ENDGAME_Okay()
End Select
End Select
; If the selected menu item was a button, checkbox, or radio button, deselect it.
; If it was a slider, allow it to remain selected.
; This needs to be updated. The buttons should be contained in types and contain the type of button they are so this can be managed easier.
; But it's much too late to write a proper GUI system for the game at this point.
Select True
Case (Active_Menu = MENU_OPTIONS) And ((Selected_Menu_Item = 4) Or (Selected_Menu_Item = 5))
; Do nothing.
Default
Selected_Menu_Item = 0
End Select
; Reset mouse state.
; Failing to do this causes the advanced mode bot change to trigger when the level begins or a contextual help screen appears.
; Because this only triggers when a menu is active, it won't affect the gameplay.
MouseHit_Left = False
MouseHit_Right = False
Case GLOBAL_State = GS_GAME_PLAYING
; If player hit P or ESC, pause the game and the music.
If (KeyHit(KEY_P) = True) Or (KeyHit(KEY_ESC) = True)
ShowMenu(MENU_PAUSE)
Pause_Music()
EndIf
; Cheat keys:
If Upper$(Savegame_Name$(GLOBAL_Editing_Savegame)) = "SHAWN SWIFT"
; If player hit S, spawn a random robot.
If KeyHit(KEY_S) Then SpawnRobot(Rand(0,3), Rand(0,3))
; Go to next/previous level.
If (KeyHit(KEY_PGUP) = True) And (Level > 1)
; End the level.
End_Level()
; Decrement the level by 2 so that when the menu goes to the "next level" it will be the previous level.
Level = Level - 2
EndIf
If (KeyHit(KEY_PGDN) = True) And (Level < GLOBAL_Total_Levels+1) Then End_Level()
; Skip to end.
If KeyHit(KEY_END)
End_Level()
Level = 100
EndIf
EndIf
End Select
; Keys which work at any time during game:
; Take a screenshot.
If KeyHit(KEY_F8) Then SaveScreenshot()
; Switch between fullscreen and windowed mode.
; If the F key was hit, and the game is not in player name entry mode, then switch to fullscreen mode.
If (KeyHit(KEY_F) = True) And (((GLOBAL_State = GS_MENU_ACTIVE) And (Active_Menu = MENU_NAMEENTRY)) = False)
If Windowed
Switch_to_Fullscreen()
Else
Switch_to_Windowed()
EndIf
EndIf
Return