I spent the morning building a very basic login screen. It prompts the user for a username/password, and then does some basic debugging.
- Verification - When the form is submitted it checks to make sure that a username and password have been entered and throws an error at the user if they didn’t enter either field.
- Points to Missing Field - if the user tries to submit the form without a password, it will set the cursor to the password field after giving the error message. Same with the username field.
- Tab Cycling - pressing the TAB key will cycle the cursor between the username and password box
- Submission - the form can be submitted by click in the Login button or hitting the ENTER key
- Layout Modification - every form element’s position is set relative to a simple Vec3 coordinate. Thus you can change the entire form positioning by changing the Vec3 variable coordinates (boxloc variable), or edit the coordinates of each individual element
- This code does NOT include any kind of client-server authentication or networking code of any kind. It’s just a simple interface. I’m working on the networking bit next. All this will do right now is give you a really simple and easy-to-manipulate login screen that is very easy to change.
- It’s really easy to add a background image behind the login form with a DirectImage object to make it look somewhat nice.
- Additionally, the login box does not shift to the right as it appears in the screenshots below. That’s just my really bad pasting with Photoshop.
- No textures or other external files are needed. The interface runs entirely off built-in Panda code.
import direct.directbase.DirectStart from direct.showbase.DirectObject import DirectObject from direct.gui.OnscreenText import OnscreenText from direct.gui.DirectGui import * from pandac.PandaModules import * ### client logic # connect to patcher to see if update is available # connect to login server # send login credentials class GameClient(DirectObject): def __init__(self): base.setBackgroundColor( 0, 0, 0 ) # sets the background color to black because the # default grey color bugs me for some reason self.loginScreen() # draws the login screen self.usernameBox['focus'] = 1 # sets the cursor to the username field by default self.accept('tab', self.cycleLoginBox) # enables the user to cycle through the text fields with the tab key # this is a standard feature on most login forms self.accept('enter', self.attemptLogin) # submits the login form, or you can just click the Login button def loginScreen(self): # creates a basic login screen that asks for a username/password boxloc = Vec3(0.0, 0.0, 0.0) # all items in the login form will have a position relative to this # this makes it easier to shift the entire form around once we have # some graphics to display with it without having to change the # positioning of every form element # p is the position of the form element relative to the boxloc # coordinates set above it is changed for every form element p = boxloc + Vec3(-0.5, 0, 0.0) self.textObject = OnscreenText(text = "Username:", pos = p, scale = 0.07,fg=(1, 1, 1, 1),align=TextNode.ALeft) # "Username: " text that appears beside the username box p = boxloc + Vec3(-0.1, 0.0, 0.0) self.usernameBox = DirectEntry(text = "" , pos = p, scale=.05, initialText="", numLines = 1) # Username textbox where you type in your username p = boxloc + Vec3(-0.5, -0.1, 0.0) self.textObject = OnscreenText(text = "Password:", pos = p, scale = 0.07,fg=(1, 1, 1, 1),align=TextNode.ALeft) # "Password: " text that appears beside the password box p = boxloc + Vec3(-0.1, 0, -0.1) self.passwordBox = DirectEntry(text = "" , pos = p, scale=.05, initialText="", numLines = 1, obscured = 1) # Password textbox where you type in your password # Note - obscured = 1 denotes that all text entered will be replaced # with a * like a standard password box p = boxloc + Vec3(0, 0, -0.2) self.loginButton = DirectButton(text = ("Login", "Login", "Login", "Login"), pos = p, scale = 0.075, command=self.attemptLogin) # The 'Login' button that will trigger the attemptLogin function # when clicked p = boxloc + Vec3(-0.5, -0.4, 0) self.statusText = OnscreenText(text = "", pos = p, scale = 0.05, fg = (1, 0, 0, 1), align=TextNode.ALeft) # A simple text object that you can display an error/status messages # to the user def updateStatus(self, statustext): self.statusText.setText(statustext) # all this does is change the status text. def attemptLogin(self): # checks to make sure the user inputed a username and password: # if they didn't it will spit out an error message # if they did, it will try to connect to the login server # (under construction) if(self.usernameBox.get() == ""): if(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a username and password before logging in.") else: self.updateStatus("ERROR: You must specify a username") self.passwordBox['focus'] = 0 self.usernameBox['focus'] = 1 elif(self.passwordBox.get() == ""): self.updateStatus("ERROR: You must enter a password") self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1 else: self.updateStatus("Attempting to login...") print "Attempting to connect to Server with credentials: (" + self.usernameBox.get() + ", " + self.passwordBox.get() + ")" # # this is where the networking code will get put in # def cycleLoginBox(self): # function is triggered by the tab key so you can cycle between # the two input fields like on most login screens # IMPORTANT: When you change the focus to one of the text boxes, # you have to unset the focus on the other textbox. If you do not # do this Panda seems to get confused. if(self.passwordBox['focus'] == 1): self.passwordBox['focus'] = 0 self.usernameBox['focus'] = 1 elif(self.usernameBox['focus'] == 1): self.usernameBox['focus'] = 0 self.passwordBox['focus'] = 1 Client = GameClient() run()