added visual menu and live updates
parent
a87bc5bae4
commit
180a4fe80f
27
botany.py
27
botany.py
|
@ -8,8 +8,8 @@ import os.path
|
||||||
import random
|
import random
|
||||||
import getpass
|
import getpass
|
||||||
import threading
|
import threading
|
||||||
|
import errno
|
||||||
|
from menu_screen import *
|
||||||
# ideas go here
|
# ideas go here
|
||||||
# lifecycle of a plant
|
# lifecycle of a plant
|
||||||
# seed -> seedling -> sprout -> young plant -> mature plant -> flower ->
|
# seed -> seedling -> sprout -> young plant -> mature plant -> flower ->
|
||||||
|
@ -69,6 +69,7 @@ import threading
|
||||||
#
|
#
|
||||||
# curses.endwin()
|
# curses.endwin()
|
||||||
|
|
||||||
|
|
||||||
class Plant(object):
|
class Plant(object):
|
||||||
# This is your plant!
|
# This is your plant!
|
||||||
stage_dict = {
|
stage_dict = {
|
||||||
|
@ -214,7 +215,8 @@ class Plant(object):
|
||||||
output += self.stage_dict[self.stage] + " "
|
output += self.stage_dict[self.stage] + " "
|
||||||
if self.stage >= 2:
|
if self.stage >= 2:
|
||||||
output += self.species_dict[self.species] + " "
|
output += self.species_dict[self.species] + " "
|
||||||
print output
|
# print output
|
||||||
|
return output
|
||||||
|
|
||||||
def start_life(self):
|
def start_life(self):
|
||||||
# runs life on a thread
|
# runs life on a thread
|
||||||
|
@ -231,13 +233,13 @@ class Plant(object):
|
||||||
while (self.stage < 5) or (self.dead == False):
|
while (self.stage < 5) or (self.dead == False):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.ticks += 1
|
self.ticks += 1
|
||||||
print self.ticks
|
# print self.ticks
|
||||||
if self.stage < len(self.stage_dict)-1:
|
if self.stage < len(self.stage_dict)-1:
|
||||||
if self.ticks == life_stages[self.stage]:
|
if self.ticks == life_stages[self.stage]:
|
||||||
self.growth()
|
self.growth()
|
||||||
self.parse_plant()
|
print self.parse_plant()
|
||||||
if self.mutate_check():
|
if self.mutate_check():
|
||||||
self.parse_plant()
|
print self.parse_plant()
|
||||||
|
|
||||||
# what kills the plant?
|
# what kills the plant?
|
||||||
|
|
||||||
|
@ -258,8 +260,13 @@ class DataManager(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.this_user = getpass.getuser()
|
self.this_user = getpass.getuser()
|
||||||
if not os.path.exists(self.botany_dir):
|
# check for .botany dir in home
|
||||||
|
try:
|
||||||
os.makedirs(self.botany_dir)
|
os.makedirs(self.botany_dir)
|
||||||
|
except OSError as exception:
|
||||||
|
if exception.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
self.savefile_name = self.this_user + '_plant.dat'
|
self.savefile_name = self.this_user + '_plant.dat'
|
||||||
|
|
||||||
def check_plant(self):
|
def check_plant(self):
|
||||||
|
@ -293,7 +300,7 @@ if __name__ == '__main__':
|
||||||
if my_data.check_plant():
|
if my_data.check_plant():
|
||||||
print "Welcome back, " + getpass.getuser()
|
print "Welcome back, " + getpass.getuser()
|
||||||
my_plant = my_data.load_plant()
|
my_plant = my_data.load_plant()
|
||||||
my_plant.parse_plant()
|
print my_plant.parse_plant()
|
||||||
# otherwise create new plant
|
# otherwise create new plant
|
||||||
else:
|
else:
|
||||||
print "Welcome, " + getpass.getuser()
|
print "Welcome, " + getpass.getuser()
|
||||||
|
@ -301,7 +308,9 @@ if __name__ == '__main__':
|
||||||
my_plant = Plant(my_data.savefile_path)
|
my_plant = Plant(my_data.savefile_path)
|
||||||
my_plant.start_life()
|
my_plant.start_life()
|
||||||
print "Your plant is living :)"
|
print "Your plant is living :)"
|
||||||
raw_input('Press return to save and exit...\n')
|
botany_menu = CursedMenu(my_plant)
|
||||||
|
botany_menu.show([1,2,3], title=' botany ', subtitle='Options')
|
||||||
|
#raw_input('Press return to save and exit...\n')
|
||||||
my_data.save_plant(my_plant)
|
my_data.save_plant(my_plant)
|
||||||
my_data.data_write_json(my_plant)
|
my_data.data_write_json(my_plant)
|
||||||
print "end"
|
print "end"
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import curses, os, traceback, threading, time
|
||||||
|
|
||||||
|
class CursedMenu(object):
|
||||||
|
'''A class which abstracts the horrors of building a curses-based menu system'''
|
||||||
|
def __init__(self, this_plant):
|
||||||
|
'''Initialization'''
|
||||||
|
self.screen = curses.initscr()
|
||||||
|
curses.noecho()
|
||||||
|
curses.cbreak()
|
||||||
|
curses.start_color()
|
||||||
|
curses.curs_set(0)
|
||||||
|
self.screen.keypad(1)
|
||||||
|
self.plant = this_plant
|
||||||
|
self.exit = False
|
||||||
|
|
||||||
|
# Highlighted and Normal line definitions
|
||||||
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||||
|
self.highlighted = curses.color_pair(1)
|
||||||
|
self.normal = curses.A_NORMAL
|
||||||
|
thread = threading.Thread(target=self.update_plant_live, args=())
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
def show(self, options, title="Title", subtitle="Subtitle"):
|
||||||
|
'''Draws a menu with the given parameters'''
|
||||||
|
self.set_options(options)
|
||||||
|
self.title = title
|
||||||
|
self.subtitle = subtitle
|
||||||
|
self.selected = 0
|
||||||
|
self.draw_menu()
|
||||||
|
|
||||||
|
|
||||||
|
def set_options(self, options):
|
||||||
|
'''Validates that the last option is "Exit"'''
|
||||||
|
if options[-1] is not 'Exit':
|
||||||
|
options.append('Exit')
|
||||||
|
self.options = options
|
||||||
|
|
||||||
|
|
||||||
|
def draw_menu(self):
|
||||||
|
'''Actually draws the menu and handles branching'''
|
||||||
|
request = ""
|
||||||
|
try:
|
||||||
|
while request is not "Exit":
|
||||||
|
self.draw()
|
||||||
|
request = self.get_user_input()
|
||||||
|
self.handle_request(request)
|
||||||
|
self.__exit__()
|
||||||
|
|
||||||
|
# Also calls __exit__, but adds traceback after
|
||||||
|
except Exception as exception:
|
||||||
|
self.__exit__()
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
'''Draw the menu and lines'''
|
||||||
|
self.screen.border(0)
|
||||||
|
self.screen.addstr(2,2, self.title, curses.A_STANDOUT) # Title for this menu
|
||||||
|
self.screen.addstr(4,2, self.subtitle, curses.A_BOLD) #Subtitle for this menu
|
||||||
|
# Display all the menu items, showing the 'pos' item highlighted
|
||||||
|
for index in range(len(self.options)):
|
||||||
|
textstyle = self.normal
|
||||||
|
if index == self.selected:
|
||||||
|
textstyle = self.highlighted
|
||||||
|
self.screen.addstr(5+index,4, "%d - %s" % (index+1, self.options[index]), textstyle)
|
||||||
|
|
||||||
|
self.screen.refresh()
|
||||||
|
|
||||||
|
def update_plant_live(self):
|
||||||
|
while self.exit is not True:
|
||||||
|
plant_string = self.plant.parse_plant()
|
||||||
|
plant_ticks = str(self.plant.ticks)
|
||||||
|
self.screen.addstr(10,2, plant_string, curses.A_NORMAL)
|
||||||
|
self.screen.addstr(11,2, plant_ticks, curses.A_NORMAL)
|
||||||
|
self.screen.refresh()
|
||||||
|
time.sleep(1)
|
||||||
|
#curses.endwin()
|
||||||
|
#os.system('clear')
|
||||||
|
|
||||||
|
def get_user_input(self):
|
||||||
|
'''Gets the user's input and acts appropriately'''
|
||||||
|
user_in = self.screen.getch() # Gets user input
|
||||||
|
|
||||||
|
'''Enter and Exit Keys are special cases'''
|
||||||
|
if user_in == 10:
|
||||||
|
return self.options[self.selected]
|
||||||
|
if user_in == 27:
|
||||||
|
return self.options[-1]
|
||||||
|
|
||||||
|
# This is a number; check to see if we can set it
|
||||||
|
if user_in >= ord('1') and user_in <= ord(str(min(9,len(self.options)+1))):
|
||||||
|
self.selected = user_in - ord('0') - 1 # convert keypress back to a number, then subtract 1 to get index
|
||||||
|
return
|
||||||
|
|
||||||
|
# Increment or Decrement
|
||||||
|
if user_in == curses.KEY_DOWN: # down arrow
|
||||||
|
self.selected += 1
|
||||||
|
if user_in == curses.KEY_UP: # up arrow
|
||||||
|
self.selected -=1
|
||||||
|
self.selected = self.selected % len(self.options)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def handle_request(self, request):
|
||||||
|
'''This is where you do things with the request'''
|
||||||
|
if request is None: return
|
||||||
|
if request == 1:
|
||||||
|
self.screen.addstr(8,15,str(self.plant.ticks), curses.A_STANDOUT) # Title for this menu
|
||||||
|
self.screen.refresh()
|
||||||
|
|
||||||
|
def __exit__(self):
|
||||||
|
self.exit = True
|
||||||
|
curses.curs_set(2)
|
||||||
|
curses.endwin()
|
||||||
|
os.system('clear')
|
||||||
|
|
||||||
|
|
||||||
|
'''demo'''
|
||||||
|
# cm = CursedMenu()
|
||||||
|
# cm.show([1,2,3], title=' botany ', subtitle='Options')
|
Loading…
Reference in New Issue