Note: The following code is fully, 100% functional and does exactly what I want, and everything I want. It works. I'm just curious about ways it could be re-written to be "better". When I write code, I tend to hack things together until they work. I'll note - I fully understand HOW it works, and what it's doing, but it's usually a "learn as I go along and do it, and run into problems, figure out why I'm having them and how to fix it". Which basically means I know what I know, but I don't know what I don't know.
The code is for my phone/text messaging system. I'll post it in snippets, since it's spread out amongst multiple files all over the place.
First: The very basic python code behind most of it.
Next, there's 3 seperate types of variable declarations. First assigns a variable, the next three are dictionaries referenced later on, and the last is just a list.
The next 3 are various screens that are used. The first is the contact list (shows all the contacts as buttons, which opens up a the second screen). The second screen is the actual text msgs, and the 3rd is the screen to select responses. Anything that is displayed as "new_idle", etc - it's just seperate buttons I have for a visual indication when there's new messages available.
contacts screen:
The 2nd screen is the actual messaging window that displays the texts: Notes - "extra" in the "not re.findall" section is to exclude certain images I want inline and not separate. images that are separated are simply a button that opens up a larger version of the image. I need background None there because default buttons (via gui styles) have a background. I have more buttons I *want* the background on than ones I don't, so it's easier to do it that way, than try and apply to all the ones I want it on. Finally for this, the on show action simply exists to prevent the message from endlessly looping - that's the same reason the "close this window" buttons are disabled while the label is active.
The 3rd screen is just a response screen that gets called a lot:
Finally, there's the "Actually using it" bit. First, when I want the msgs to be enabled I have something like this:
(I could have defaulted "Jasmine" in the initial list in this instance, since it's the first time text msgs are being used in the game. I didn't because when I wrote that I was testing to make sure it worked properly, then just left it). When I want the msgs to be disabled, (Example, you passed that point in the game, and never checked it) I'll just reset the variables to 0 and False.
Finally, a snippet of the label where everything works. (I'll only give a partial bit, since it's fairly long):
at the end of the label I do two things: I reset all the variables, so you can't loop through the msgs sequence again, and I run a small while loop to check if there are any more new texts. (The main phone screen not pictured here, has a notification for when you have new text msgs, that loop just checks if it should be turned off or kept on if you still have more you haven't checked).
Note: A big part of the reason for calling the "Response" screen even when there's only one available response, is simply to give the player a chance to read whatever is there, and CTC. I could easily just "add" the text and not bother with the screen call, but from a gameplay standpoint I didn't like that option as much.
All in all, the entire thing works exactly the way I want. I also tested it against everything I have planned for the future, and it worked correctly, so no issues later on either. Functionally, there is absolutely no reason to change a single thing. I'm just curious how this code could be re-written to be functionally identical, but "better" - because like I said to start, I don't know what I don't know.
One last note - if you look through the code and see things that don't look like they do anything at all, they probably don't. When I wrote this, it went through a few iterations, and I didn't fully cleanup the code once I settled on a working model. As I was pasting it I noticed at least one that I left behind and never got rid of, even though it does absolutely nothing - there's probably a couple of those I should clean up at some point.
The code is for my phone/text messaging system. I'll post it in snippets, since it's spread out amongst multiple files all over the place.
First: The very basic python code behind most of it.
Code:
init python:
import re
class phoneMessage:
def __init__(self,name,message):
self.name = name
self.message = message
class phoneLog:
def __init__(self):
self.history = []
def addmessage(self,name,message):
self.history.append(phoneMessage(name,message))
def delphone(self):
self.history = []
Code:
default Jasmine_msg = phoneLog()
default Jack_msg = phoneLog()
default Paisley_msg = phoneLog()
default Henry_msg = phoneLog()
default Samantha_msg = phoneLog()
default Marie_msg = phoneLog()
default chatstate = {'Jack':0,'Samantha':0,'Henry':0,'Jasmine':0,'Paisley':0,'Marie':0}
default newtext={'Jasmine':False,'Jack':False,'Paisley':False,'Henry':False,'Samantha':False,'Marie':False}
default msghistory ={'Jack':Jack_msg.history,'Samantha':Samantha_msg.history,'Henry':Henry_msg.history,'Jasmine':Jasmine_msg.history,'Paisley':Paisley_msg.history,'Marie':Marie_msg.history}
default contact_list=["Jack","Samantha","Henry","Marie"]
contacts screen:
Code:
screen contacts():
modal True
add "phonecontacts" pos 800,150
add "cdiv" pos 812,320
text "Contacts" pos 905,265 style "contacts"
imagebutton:
idle "powerb"
tooltip "Power"
pos 971,809
action Hide("contacts"),Show("phone")
imagebutton:
idle "back"
tooltip "Back"
pos 870,809
action Hide("contacts"),Show("bigphone")
vpgrid:
mousewheel True
draggable True
cols 2
spacing 20
xpos 825
ypos 330
xsize 0.21
ysize 0.42
for i in contact_list:
$tmp1 = i.lower() + "msg"
$tmp2 = i + "chat" + str(chatstate[i])
imagebutton:
if newtext[i]:
idle "contact_" + i.lower() + "new_idle"
hover "contact_" + i.lower() + "new_hover"
else:
idle "contact_" + i.lower() + "_idle"
hover "contact_" + i.lower() + "_hover"
action Show('textmsgs',name=i,chatnum=tmp2), Hide("contacts")
if i == "Jack":
textbutton "Dad":
yalign 0.8
background None
action Show('textmsgs',name=i,chatnum=tmp2), Hide("contacts")
elif i == "Samantha":
textbutton "Mom" yalign 0.8 background None action Show('textmsgs',name=i,chatnum=tmp2), Hide("contacts")
else:
textbutton i yalign 0.8 background None action Show('textmsgs',name=i,chatnum=tmp2), Hide("contacts")
The 2nd screen is the actual messaging window that displays the texts: Notes - "extra" in the "not re.findall" section is to exclude certain images I want inline and not separate. images that are separated are simply a button that opens up a larger version of the image. I need background None there because default buttons (via gui styles) have a background. I have more buttons I *want* the background on than ones I don't, so it's easier to do it that way, than try and apply to all the ones I want it on. Finally for this, the on show action simply exists to prevent the message from endlessly looping - that's the same reason the "close this window" buttons are disabled while the label is active.
Code:
screen textmsgs(name,chatnum):
$chatname = msghistory[name]
on "show":
if newtext[name]:
action SetDict(chatstate,name,0),SetDict(newtext,name,False), Call(chatnum)
else:
action NullAction()
default yadj = ui.adjustment()
python:
if yadj.value == yadj.range:
yadj.value = float('inf')
modal True
add "phonechat" pos 800,150
add "cdiv" pos 812,320
add "contact_" + name.lower() + "_idle" pos 955,250
if current_label == chatnum:
imagebutton idle "powerb" pos 971,809 action NullAction()
imagebutton idle "back" pos 870,809 action NullAction()
elif freeroam:
imagebutton idle "powerb" pos 971,809 tooltip "Power" action Hide("textmsgs"), Show("phone"), Jump(freeroamlabel)
imagebutton idle "back" pos 870,809 tooltip "Back" action Hide("textmsgs"), Show("contacts"), Jump(freeroamlabel)
else:
imagebutton idle "powerb" pos 971,809 tooltip "Power" action Hide("textmsgs"), Show("phone")
imagebutton idle "back" pos 870,809 tooltip "Back" action Hide("textmsgs"), Show("contacts")
vpgrid yadjustment yadj:
style_prefix "msgs"
ypos 0.31
xoffset 0
yoffset 1
ysize 0.43
xsize 0.21
cols 1
spacing 0
draggable True
mousewheel True
xfill True
scrollbars "vertical"
side_xalign 0.513
yinitial 1.0
vbox:
spacing 5
xalign 0.0 yalign 0.05
xsize 260
for i in chatname:
if i.name == "MC":
hbox:
if re.findall(r'jpg|png', i.message, re.I) and not re.findall(r'extra', i.message, re.I):
xalign 0.75
frame:
background Frame(i.message,240,135)
button background None action Show('imagescrn4', img=i.message)
else:
xsize 360
frame:
background Frame("yc",10,10)
xmaximum 280
xalign 1.0
xoffset 0
text i.message style "textmsg"
else:
hbox:
if re.findall(r'jpg|png', i.message, re.I) and not re.findall(r'extra', i.message, re.I):
xalign 0.0
frame:
xmaximum 250
ymaximum 250
xoffset 53
background Frame(i.message)
button background None action Show('imagescrn4', img=i.message)
elif re.findall(r'extra', i.message, re.I):
xalign 0.0
frame:
background Frame("tc",10,10)
xmaximum 250
xoffset 39
text i.message style "themmsg"
else:
xalign 0.0
frame:
background Frame("tc",10,10)
xmaximum 250
#xoffset 53
xanchor -0.17
text i.message style "themmsg"
$tooltip = GetTooltip()
if tooltip:
nearrect:
focus "tooltip"
prefer_top False
frame:
background None
xalign 0.5
text tooltip size 24
The 3rd screen is just a response screen that gets called a lot:
Code:
screen msg_choice(choice1,choice2=False,choice3=False):
vbox:
xpos 1180
yalign 0.7
spacing 5
if choice1:
frame:
xmaximum 320
background Frame("yc",10,10)
textbutton "[choice1]" text_style "textmsgchoice" background None action Return(choice1)
if choice2:
frame:
xmaximum 320
background Frame("yc",10,10)
textbutton "[choice2]" text_style "textmsgchoice" background None action Return(choice2)
if choice3:
frame:
xmaximum 320
background Frame("yc",10,10)
textbutton "[choice3]" text_style "textmsgchoice" background None action Return(choice3)
Code:
$chatstate['Jasmine'] = 1
$contact_list.append("Jasmine")
$newtext['Jasmine'] = True
$newtextmsg = True
Finally, a snippet of the label where everything works. (I'll only give a partial bit, since it's fairly long):
Code:
label Jasminechat1:
$Jasmine_msg.addmessage("Jasmine","images/chapter1/phone/phoneTP.png")
call screen msg_choice("You actually got a picture? LOL!")
if _return:
$reply = _return
$Jasmine_msg.addmessage("MC",reply)
$Jasmine_msg.addmessage("Jasmine","I had to. I wonder if anyone ever told her.")
call screen msg_choice("I saw her later and it was gone, so....")
if _return:
$reply = _return
$Jasmine_msg.addmessage("MC",reply)
$Jasmine_msg.addmessage("Jasmine","{image=images/phone/extra/laughemo.png}")
$renpy.pause(1,modal=False)
$Jasmine_msg.addmessage("Jasmine","Later {image=images/phone/extra/blood.png}")
call screen msg_choice("Is... is that a threat?")
.
Note: A big part of the reason for calling the "Response" screen even when there's only one available response, is simply to give the player a chance to read whatever is there, and CTC. I could easily just "add" the text and not bother with the screen call, but from a gameplay standpoint I didn't like that option as much.
All in all, the entire thing works exactly the way I want. I also tested it against everything I have planned for the future, and it worked correctly, so no issues later on either. Functionally, there is absolutely no reason to change a single thing. I'm just curious how this code could be re-written to be functionally identical, but "better" - because like I said to start, I don't know what I don't know.
One last note - if you look through the code and see things that don't look like they do anything at all, they probably don't. When I wrote this, it went through a few iterations, and I didn't fully cleanup the code once I settled on a working model. As I was pasting it I noticed at least one that I left behind and never got rid of, even though it does absolutely nothing - there's probably a couple of those I should clean up at some point.