''' Created on Dec 7, 2014 @author: Brett Paufler Copyright Brett Paufler Kivy App Kivy is not loaded In CBU-Installed, please find Kivy-1.8.0-py2.7-win32kivy.zip unzip drop this naked .py file on kivy.bat in first directly program should run unzip drop this naked .py file on Squares bounce off the sides of the game wall simplistic speed up or get larger on impact more of a tester as with other kivy projects, not the end of the world if this is never revived ''' import random import math from kivy.animation import Animation from kivy.app import App from kivy.uix.widget import Widget from kivy.graphics import Color, Line from kivy.uix.floatlayout import FloatLayout from kivy.uix.button import Button from kivy.clock import Clock from kivy.uix.spinner import Spinner from kivy.uix.popup import Popup from kivy.uix.label import Label from kivy.uix.togglebutton import ToggleButton from kivy.uix.gridlayout import GridLayout from kivy.uix.checkbox import CheckBox ''' TODO Ovals Buttons - Buttons - Buttons ''' class PlayingField(Widget): def __init__(self): Widget.__init__(self) self.playingDiscs = [] self.collision_size = 'Smaller' self.collision_speed = 'Faster' def update_disc_dir(self,m,x,y): ''' assigns x,y directional control to self.children[m] ''' self.children[m].dir_x = x self.children[m].dir_y = y def all_on_board(self): ''' ''' x,y = self.size for c in self.children: if c.center_x > x: c.dir_x = - abs(c.dir_x) if c.center_x < 0: c.dir_x = abs(c.dir_x) if c.center_y > y: c.dir_y = - abs(c.dir_y) if c.center_y < 0: c.dir_y = abs(c.dir_y) def collision_report(self,m,n,effect,): ''' speed=1.01,size=0.99 ''' if self.collision_size == "Bigger": e = 1.01 elif self.collision_size == "Smaller": e = 0.99 else: e = 1.0 w,h = self.children[m].size self.children[m].size = (w*e,h*e) w,h = self.children[n].size self.children[n].size = (w*e,h*e) if self.collision_speed == "Faster": s = 1.01 elif self.collision_size == "Bigger": s = 0.99 else: s = 1.0 mX = self.children[m].dir_x mY = self.children[m].dir_y nX = self.children[n].dir_x nY = self.children[n].dir_y if "diagonal" in effect or "horizontal" in effect: mX = abs(mX) nX = abs(nX) if "diagonal" in effect or "vertical" in effect: mY = abs(mY) nY = abs(nY) x = (mX + nX)/2.0 * s y = (mY + nY)/2.0 * s if "left" in effect or "vertical" in effect or "horizontal" in effect: self.update_disc_dir(m,x,y) self.update_disc_dir(n,-x,-y) elif "right" in effect: self.update_disc_dir(m,-x,y) self.update_disc_dir(n,x,-y) else: self.update_disc_dir(m,x,y) self.update_disc_dir(n,x,y) #callOther() def update(self, dt): self.all_on_board() for c in self.children: c.center_x += c.dir_x c.center_y += c.dir_y numC = len(self.children) for m in range(numC): for n in range(m+1, numC): if self.children[m].collide_widget(self.children[n]): #self.collide_diagonal_group(m, n) self.collision_report(m,n, "left diagonal") def on_touch_down(self, touch): ''' adds a PlayingDisc to the playingField on_touch_down ''' self.playingDiscs.append(PlayingDisc(touch)) self.add_widget(self.playingDiscs[len(self.playingDiscs)-1]) def on_touch_up(self, touch): pass class PlayingDisc(Button): def __init__(self,touch): Widget.__init__(self) self.background_color = [0,1,0,1] self.opacity = 1 self.pos = (touch.x,touch.y) self.size = (25,25) self.dir_x = 1 - 2 * random.random() self.dir_y = 1 - 2 * random.random() def minMaxSpeed(self,minSpeed=0,maxSpeed=50): ''' brackets the playingDisc speed between min and max ''' for v in [self.dir_x, self.dir_y]: if v < minSpeed: v = minSpeed if v > maxSpeed: v = maxSpeed print v class WallBouncerApp(App): def build(self): parent = FloatLayout() game = PlayingField() game.size_hint=(1.0, 1.0) game.pos_hint={'x':0, 'y':0.0} game.id = "GAME" parent.add_widget(game) #buttons = {} def lowerLeftPass(obj): pass lowerLeft = Button( size_hint=(0.25, 0.1), pos_hint={'x':0.0, 'y':0.0}, opacity = 1, text = "nada") parent.add_widget(lowerLeft) #lowerLeft.bind(on_release=lowerLeftPass) def callOther(): pass def enlargeEffect(obj): #print "ENLARGE" pW, pH = game.size for d in game.playingDiscs: w,h = d.size w = w * 1.25 h = h * 1.25 if w > pW/2.0: w = pW/2.0 if h > pH/2.0: h = pH/2.0 d.size = (w,h) #print d.size def reduceEffect(obj): #print "REDUCE" for d in game.playingDiscs: #print d.size w,h = d.size w = w/1.25 h = h/1.25 if w < 15: w = 15.0 if h < 15: h = 15.0 d.size = (w,h) #print d.size def fastEffect(obj): for d in game.playingDiscs: d.dir_x = d.dir_x * 1.25 + 0.01 d.dir_y = d.dir_y * 1.25 + 0.01 d.minMaxSpeed() def slowEffect(obj): for d in game.playingDiscs: d.dir_x = d.dir_x / 1.25 - 0.01 d.dir_y = d.dir_y / 1.25 - 0.01 d.minMaxSpeed() def lowerLeftUnbindAll(): lowerLeft.unbind(on_release=reduceEffect) lowerLeft.unbind(on_release=enlargeEffect) lowerLeft.unbind(on_release=fastEffect) lowerLeft.unbind(on_release=slowEffect) def upperLeftOptions(self,text): ''' TODO NEED TO ADD ALL TO UNBIND ABOVE ''' if text == 'Enlarge': lowerLeftUnbindAll() lowerLeft.bind(on_release=enlargeEffect) lowerLeft.text = "Enlarge" elif text == 'Reduce': lowerLeftUnbindAll() lowerLeft.bind(on_release=reduceEffect) lowerLeft.text = "Reduce" elif text == 'Fast': lowerLeftUnbindAll() lowerLeft.bind(on_release=fastEffect) lowerLeft.text = "Fast" elif text == 'Slow': lowerLeftUnbindAll() lowerLeft.bind(on_release=slowEffect) lowerLeft.text = "Slow" self.text = "controls\nlower left" #print "got to bottom" upperLeft = Spinner( size_hint=(0.25, 0.1), pos_hint={'x':0.0, 'y':0.9}, opacity = 0.25, text = "controls\nlower left", halign = 'center', values=('Enlarge','Reduce', 'Fast', "Slow", 'TODO shape') ) upperLeft.bind(text=upperLeftOptions) parent.add_widget(upperLeft) #ADD GROUP BIND FOR ALL #TODO - WE ARE HERE #checkbox.bind(active=on_checkbox_active) #Bind all to same #Check for checkbox.active, which is Boolean t = [] #toggles = [] collisionBox = GridLayout(cols=3, rows=5) t.append(Label(text="Effect")) t.append(Label(text="Yes")) t.append(Label(text="No")) t.append(Label(text="Faster")) t.append(CheckBox(group='speed')) t.append(CheckBox(group='speed')) t.append(Label(text="SLower")) t.append(CheckBox(group='speed')) t.append(CheckBox(group='speed')) t.append(Label(text="Bigger")) t.append(CheckBox(group='size')) t.append(CheckBox(group='size')) t.append(Label(text="Smaller")) t.append(CheckBox(group='size')) t.append(CheckBox(group='size')) #,state='down')) t.append(CheckBox(text='No Change', group='speed' )) t.append(CheckBox(text='Slower', group='speed' )) t.append(ToggleButton(text='Bigger', group='size',)) t.append(ToggleButton(text='No Change', group='size',)) t.append(ToggleButton(text='Smaller', group='size',state='down')) for r in range(15): collisionBox.add_widget(t[r]) def pullState(): print "\nPullState" print t[13].active print t[14].active ''' if t[0].state == "down": game.collision_speed = "Faster" elif t[1].state == "down": game.collision_speed = "No Change" else: game.collision_speed = "Slower" for b in t: print "T %s %s %s" % (b.text, b.state, b.state == "down") ''' collisionPopup = Popup(title='Collision Control (when objects collide)', size_hint=(1.0,0.5), content= collisionBox) def upperRightOptions(self,text): if text == 'Clear All': game.canvas.clear() if text == "Freeze": Clock.unschedule(game.update) if text == "Resume": Clock.unschedule(game.update) Clock.schedule_interval(game.update, 1.0/60.0) if text == 'Collision': #print "Called" #Clock.unschedule(game.update) collisionPopup.open() #pullState() #Clock.schedule_interval(game.update, 1.0/60.0) #print "Called Over" self.text = 'command\ncentral' upperRight = Spinner( size_hint=(0.25, 0.1), pos_hint={'x':0.75, 'y':0.9}, opacity = 0.25, text = "command\ncentral", halign = 'center', values=('Collision','Freeze', 'Resume', 'Clear All') ) #def show_selected_value(spinner, text): # print('The spinner', spinner, 'have text', text) parent.add_widget(upperRight) upperRight.bind(text=upperRightOptions) def lowerRightPass(obj): pass lowerRight = Button( size_hint=(0.50, 0.25), pos_hint={'x':0.50, 'y':0.0}, opacity = 0.1, text = "GOAL") parent.add_widget(lowerRight) #lowerLeft.bind(on_release=lowerLeftPass) Clock.schedule_interval(game.update, 1.0/60.0) return parent if __name__ == '__main__': WallBouncerApp().run()