Basic login screen for client-server games

I spent the morning building a very basic login screen. It prompts the user for a username/password, and then does some basic debugging.

Features

  • 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

Important Info

  1. 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.
  2. It’s really easy to add a background image behind the login form with a DirectImage object to make it look somewhat nice.
  3. 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.
  4. No textures or other external files are needed. The interface runs entirely off built-in Panda code.

Preview:

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()

Nice and simple, i like it :stuck_out_tongue: