Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import ui
- import random
- from math import radians
- import time
- from functools import partial
- class Die(ui.View):
- def __init__(self,faces='ABCDEF',*args,**kwargs):
- self.faces=faces
- self._face_idx=0
- ui.View.__init__(self,*args,**kwargs)
- self.flex=''
- @property
- def letter(self):
- return self.faces[self._face_idx]
- @property
- def face_idx(self):
- return self._face_idx
- @face_idx.setter
- def face_idx(self,value):
- if value < len(self.faces):
- self._face_idx=value
- def draw(self):
- w=self.width
- corner_frac=0.05 #fractional corner radius for dice itself
- face_frac=0.5*0.65 # fractional corner radius of the face
- highlight_color='#e4e4db'
- shadow_color='#c6c6be'
- face_color='#fefaed'
- s1=ui.Path.rounded_rect(0,0,w,w,w*corner_frac)
- s2=ui.Path.rounded_rect(0,w/2.,w,w/2.,w*corner_frac)
- s3=ui.Path.rounded_rect(0,0,w,w,w*face_frac)
- ui.set_color(highlight_color)
- s1.fill()
- ui.set_color(shadow_color)# little darker
- s2.fill()
- ui.set_color(face_color) # little lighter
- s3.fill()
- sz=ui.measure_string(self.faces[self.face_idx],font=('Futura',0.5*self.width))
- ui.draw_string(self.faces[self.face_idx],font=('Futura',0.5*w),
- rect=( (w-sz.width)/2, (w-sz.height)/2,sz.width,sz.height),
- color=(.17, .0, .97))
- def roll(self):
- ''' choose a random face. also, transform angle, and size for animation purposes'''
- maxsc=1.4 #amount of relative size variation during roll
- minsc=0.6
- randscale=minsc+(maxsc-minsc)*random.random()
- randangle=radians(90*random.randrange(5))
- self.face_idx=random.randrange(len(self.faces))
- self.transform=ui.Transform.rotation(randangle).concat(
- ui.Transform.scale(randscale,randscale) )
- #self.set_needs_display()
- def straighten(self):
- ''' set back to default orientation for reading'''
- self.transform=ui.Transform()
- class BoggleBoard(ui.View):
- ''' Just a container for dice. auto sizes the dice based on view size
- N: grid size (creates NxN grid)
- frame: size of board. always adjusts to be square
- other View attribs are valid (bg_color, etc)
- self.dice: list of Die's
- TODO: Take dice dictionary
- '''
- def __init__(self,N=4,*args,**kwargs):
- self.N=N
- self.border=0.05
- super(BoggleBoard,self).__init__(*args,**kwargs)
- dice=[]
- for i in range(N*N):
- dice.append(Die(['A','B','C','D','E','F'],
- frame=self._ind2frame(i)))
- self.add_subview(dice[-1])
- self.dice=dice
- self.flex='wh'
- self.shuffle()
- def layout(self):
- '''resize board, called when view size changes'''
- # first, ensure we are square
- if self.width>self.height:
- self.width=self.height
- elif self.height>self.width:
- self.height=self.width
- # Then, set dice size/positions based on order of self.dice
- for ind,d in enumerate(self.dice):
- d.frame=self._ind2frame(ind)
- def draw(self):
- ''' TODO: draw semi 3d indentations underneath dice that are visible when rolling'''
- pass
- def _ind2frame(self, index):
- ''' generate dice frame rect for a given index
- assume row major ordering'''
- N=self.N
- y,x=divmod(index,N) #gives x,y location in grid units of the given die
- b=self.border #fractional border width
- W=(self.width-(N+1)*b*self.width/N)/N #die width, accounting for border
- return ui.Rect(b*W + x*(1+b)*W, b*W + y*(1+b)*W, W, W)
- def shuffle(self,sender=None):
- #first, shuffle die locations, then tell each die to roll itself
- random.shuffle(self.dice)
- for ind,d in enumerate(self.dice):
- d.frame=self._ind2frame(ind) # move to new spot on grid
- d.roll() #roll it
- def letters(self, sender=None):
- '''return list of visible letters'''
- return [d.letter for d in self.dice]
- def solve(self):
- ''' find best possible score, using internet anagram server,or bogglewords.com, etc'''
- pass
- def animated_shuffle(self,sender=None, duration=0.5, straighten_after=True):
- '''animate a single shuffle.
- optionally: reorient dice after shuffling
- '''
- ui.animate(self.shuffle, duration)
- if straighten_after:
- ui.animate(self.straighten, duration/2, delay=duration/2)
- def straighten(self):
- '''rotate all dice to correct reading orientation'''
- for d in self.dice:
- d.straighten()
- @ui.in_background #needed to use sleep, but could also just use animation delay arguments
- def long_roll(self,sender=None, duration=0.5, num_rolls=10, straighten_after=True):
- '''keep running the shuffle animation, before the last one completes.
- duration: time if single roll, though it will be interupted a little way through
- num_rolls: number of times to roll
- '''
- for i in range(num_rolls):
- time.sleep(duration/5) #adjustable, but shorter than animation gives a more continuous shuffle appearance. todo: experiment with random times here
- self.animated_shuffle(sender,duration, straighten_after= straighten_after and (i==num_rolls-1 ) )
- if __name__=='__main__':
- '''this stuff all belongs in a BoggleGame type class ... but just here for experiments'''
- board_width=300
- b=BoggleBoard(frame=(10,10,board_width,board_width),bg_color='#664040')
- v=ui.View(frame=(0,0,board_width+20,board_width+64,))
- btn1=ui.Button(frame=(10,board_width+20,200,44),title='Roll',bg_color='white')
- btn1.border_color='blue'
- btn1.width+=20
- btn1.border_width=1
- btn1.corner_radius=5
- btn2=ui.Button(frame=(btn1.x+20+btn1.width,board_width+20,200,44),title='LongRoll',bg_color='white')
- btn2.border_color='blue'
- btn2.width+=20
- btn2.border_width=1
- btn2.corner_radius=5
- btn1.flex='tr'
- btn2.flex='tr'
- v.add_subview(b)
- v.add_subview(btn1)
- v.add_subview(btn2)
- '''some parameters to play with'''
- straighten_dice=False #set False for more authentic feel
- duration=.5 #set to 5 to see what is happening
- btn1.action=partial(b.animated_shuffle, duration=duration, straighten_after=straighten_dice)
- btn2.action=partial(b.long_roll, duration=duration, straighten_after=straighten_dice)
- #v.present('') #auto size
- v.present('sheet')
- #v.layout()
Add Comment
Please, Sign In to add comment