From 30e8db1710f3c3f1c0c0054b4e0b89bceb533c62 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Fri, 12 Apr 2013 10:48:40 +0000 Subject: Making initial git repository for Peter's version --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f3d74a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*~ diff --git a/Spirolaterals.py b/Spirolaterals.py new file mode 100755 index 0000000..54020b9 --- /dev/null +++ b/Spirolaterals.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python +# Spirolaterals.py +""" + Copyright (C) 2010 Peter Hewitt + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +""" +import g,utils,pygame,buttons,my_turtle,random,os,sys,load_save,slider +try: + import gtk +except: + pass + +class Spirolaterals: + + def __init__(self): + self.journal=True # set to False if we come in via main() + self.canvas=None # set to the pygame canvas if we come in via activity.py + + def display(self): # called each loop + if g.big: + g.screen.fill((0,0,0)) + utils.centre_blit(g.screen,g.big_surface,(g.sx(16),g.sy(11.5))) + else: + g.screen.blit(g.bgd,(g.sx(0),0)) + g.screen.blit(g.box,(g.x0,g.y0)) + g.screen.blit(g.box,(g.x1,g.y0)) + utils.centre_blit(g.screen,g.magician,g.magician_c) + self.draw_goal() + utils.centre_blit(g.screen,g.turtle,(g.x0+4*g.dd,g.y0+6*g.dd)) + self.tu.draw() + if self.tu.win: + utils.centre_blit(g.screen,g.smiley,(g.sx(16.6),g.sy(2.2))) + buttons.on('cyan') + self.draw_nos() + buttons.draw() + self.slider.draw() + if g.score>0: utils.display_score() + utils.display_number1(g.pattern,(g.sx(2.4),g.sy(2)),\ + g.font1,utils.BLUE) + + def do_button(self,bu): + if bu=='cyan': + g.pattern+=1 + if g.pattern==123: g.pattern=1 + g.help1=0; g.help2=0; self.get_goal() + self.tu.win=False; g.finale=False; g.show_help=False + self.tu.changed=True + buttons.off('cyan') + self.mouse_1st_no() # to 1st number + elif bu=='black': + self.tu.current=utils.copy_list(g.numbers) + self.tu.setup(); g.show_help=False + elif bu=='green': + g.show_help=False + if self.tu.changed: + self.tu.current=utils.copy_list(g.numbers) + self.tu.setup(); self.tu.changed=False + self.tu.running=True + elif self.tu.win or self.tu.crashed: + self.tu.setup(); self.tu.running=True + else: + if self.tu.step_count==0: self.tu.ms=pygame.time.get_ticks() + self.tu.running=True + elif bu=='red': + self.tu.running=False + + def do_key(self,key): + if key in g.CROSS: + if utils.mouse_on_img1(g.magician,g.magician_c): + self.help2(); return + bu=buttons.check() + if bu!='': self.do_button(bu); return + g.show_help=False; self.check_nos(1); return + if key in g.CIRCLE: self.check_nos(3); return + if key in g.RIGHT: self.mouse_right(); return + if key in g.LEFT: self.mouse_left(); return + if key in g.SQUARE: + if buttons.active('cyan'): self.do_button('cyan') + return + if key in g.TICK: self.change_level(); return + if key==pygame.K_v: g.version_display=not g.version_display; return + + def mouse_1st_no(self): + c=g.n_cx0+g.sy(.2),g.n_cy0+g.sy(1.2); pygame.mouse.set_pos(c); g.pos=c + + def mouse_magician(self): + x,y=g.magician_c; x-=g.sy(.15); y-=g.sy(.52); c=x,y + pygame.mouse.set_pos(c); g.pos=c + + def mouse_left(self): + bu=''; cx=g.n_cx0; cy=g.n_cy0; c=None + if utils.mouse_on_img1(g.magician,g.magician_c): + c=(cx+4*g.n_dx,cy) + elif buttons.mouse_on('cyan'): self.mouse_magician(); return + elif buttons.mouse_on('green'): + if buttons.active('cyan'): bu='cyan' + else: self.mouse_magician(); return + elif buttons.mouse_on('red'): bu='green' + elif buttons.mouse_on('black'): bu='red' + if bu!='': buttons.set_mouse(bu); return + if c==None: + c=(cx,cy) # default to 1st no. + for i in range(5): + n=g.numbers[i] + if utils.mouse_on_img_rect(g.n[n-1],(cx,cy)): + if i==0: buttons.set_mouse('black'); return + c=(cx-g.n_dx,cy); break + cx+=g.n_dx + cx,cy=c; cx+=g.sy(.2); cy+=g.sy(1.2); c=cx,cy + pygame.mouse.set_pos(c); g.pos=c; return + + def mouse_right(self): + bu='' + if utils.mouse_on_img1(g.magician,g.magician_c): + bu='green' + if buttons.active('cyan'): bu='cyan' + elif buttons.mouse_on('cyan'): bu='green' + elif buttons.mouse_on('green'): bu='red' + elif buttons.mouse_on('red'): bu='black' + if bu!='': buttons.set_mouse(bu); return + cx=g.n_cx0; cy=g.n_cy0; c=(cx,cy) # default to 1st no. + if buttons.mouse_on('black'): pass + else: + for i in range(5): + n=g.numbers[i] + if utils.mouse_on_img_rect(g.n[n-1],(cx,cy)): + if i==4: self.mouse_magician(); return + c=(cx+g.n_dx,cy); break + cx+=g.n_dx + cx,cy=c; cx+=g.sy(.2); cy+=g.sy(1.2); c=cx,cy + pygame.mouse.set_pos(c); g.pos=c; return + + def change_level(self): + g.level+=1 + if g.level>self.slider.steps: g.level=1 + g.delay=(3-g.level)*400 + + def draw_goal(self): # draws the left hand pattern + x1=g.x0+4*g.dd; y1=g.y0+6*g.dd; dx=0; dy=-g.dd + for i in range(4): + for j in g.goal: + for k in range(j): + x2=x1+dx; y2=y1+dy + pygame.draw.line(g.screen,utils.CYAN,(x1,y1),(x2,y2),4) + x1=x2; y1=y2 + if dy==-g.dd: dx=g.dd;dy=0 + elif dx==g.dd: dx=0;dy=g.dd + elif dy==g.dd: dx=-g.dd;dy=0 + else: dx=0;dy=-g.dd + + def calc_steps(self,l): # calculates total # of steps for a given pattern + # eg [1,2,3,4,5] = (1+2+3+4+5)*4=60 + return sum(l)*4 + + def get_goal(self): + fname=os.path.join('data','patterns.dat') + try: + f=open(fname, 'r') + for n in range(0,g.pattern): s=f.readline() + s=s[0:5] + except: + s=11132; g.pattern=1 + f.close + l=[int(c) for c in str(s)] + g.goal=l; g.steps=self.calc_steps(l) + + def draw_nos(self): # draw the numbers with glow in correct position + pos=self.calc_pos(self.tu.step_count) + x=g.n_cx0 + for i in range(5): + if i==pos: x_glow=x + n=g.numbers[i];utils.centre_blit(g.screen,g.n[n-1],(x,g.n_cy0)) + x+=g.n_dx + if self.tu.changed==False or g.show_help: + if self.tu.step_count=step_count: return pos #**** + steps+=1 + pos+=1 + + def inc_numbers(self,pos): # pos 0 to 4 - called with numberclicked + v=g.numbers[pos]+1 + if v==6: v=1 + g.numbers[pos]=v + + def dec_numbers(self,pos): # pos 0 to 4 - called with numberclicked + v=g.numbers[pos]-1 + if v==0: v=5 + g.numbers[pos]=v + + def solution(self): + s='' + for i in range(5):s+=str(g.goal[i])+' ' + s=s[:9] + return s + + def big_pic(self): + if not self.tu.running: + d=g.sy(1); s=g.bw-2*d + self.tu.draw() + g.player_surface.blit(g.screen,(0,0),(g.x1+d,g.y0+d,s,s)) + g.big=True + g.big_surface=pygame.transform.scale2x(g.player_surface) + + def help2(self): + self.tu.current=utils.copy_list(g.numbers) + self.tu.crashed=False + g.help1=0 + looking=True + while looking: + g.help1+=1;ind=g.help1-1 + if g.numbers[ind]<>g.goal[ind]: + g.numbers[ind]=g.goal[ind]; self.tu.current[ind]=g.goal[ind] + g.show_help=True; self.tu.changed=True; g.help2+=1 + looking=False + if g.help1>4: g.show_help=True; looking=False + + def flush_queue(self): + flushing=True + while flushing: + flushing=False + if self.journal: + while gtk.events_pending(): gtk.main_iteration() + for event in pygame.event.get(): flushing=True + + def run(self): + g.init() + if not self.journal: utils.load() + load_save.retrieve() + g.delay=(3-g.level)*400 + self.tu=my_turtle.TurtleClass() + self.tu.current=[1,1,1,3,2] + self.get_goal() + if g.pattern==1: self.tu.current=utils.copy_list(g.goal) + self.tu.setup() + g.numbers=utils.copy_list(self.tu.current) + #buttons + x=g.sx(7.3); y=g.sy(16.5); dx=g.sy(2.6); + buttons.Button("cyan",(x,y),True); x+=dx + buttons.off('cyan') + buttons.Button("green",(x,y),True); x+=dx + buttons.Button("red",(x,y),True); x+=dx + buttons.Button("black",(x,y),True); x+=dx + self.slider=slider.Slider(g.sx(23.5),g.sy(21),3,utils.YELLOW) + self.mouse_1st_no() # to 1st number + if self.canvas<>None: self.canvas.grab_focus() + ctrl=False + pygame.key.set_repeat(600,120); key_ms=pygame.time.get_ticks() + going=True + while going: + if self.journal: + # Pump GTK messages. + while gtk.events_pending(): gtk.main_iteration() + + # Pump PyGame messages. + for event in pygame.event.get(): + if event.type==pygame.QUIT: + if not self.journal: utils.save() + going=False + elif event.type == pygame.MOUSEMOTION: + g.pos=event.pos + g.redraw=True + if self.canvas<>None: self.canvas.grab_focus() + elif event.type == pygame.MOUSEBUTTONDOWN: + g.redraw=True + if g.big: + g.big=False + else: + bu=buttons.check() + if bu<>'': + self.do_button(bu); self.flush_queue() + elif utils.mouse_on_img1(g.magician,g.magician_c): + self.help2() + elif utils.mouse_in(g.x1,g.y0,g.x1+g.bw,g.y0+g.bw): + self.big_pic() + elif self.slider.mouse(): + g.delay=(3-g.level)*400 + else: + g.show_help=False + self.check_nos(event.button) + elif event.type == pygame.KEYDOWN: + # throttle keyboard repeat + if pygame.time.get_ticks()-key_ms>110: + key_ms=pygame.time.get_ticks() + if ctrl: + if event.key==pygame.K_q: + if not self.journal: utils.save() + going=False; break + else: + ctrl=False + if event.key in (pygame.K_LCTRL,pygame.K_RCTRL): + ctrl=True; break + self.do_key(event.key); g.redraw=True + self.flush_queue() + elif event.type == pygame.KEYUP: + ctrl=False + if not going: break + if self.tu.running: self.tu.move() + if not g.crash_drawn: g.crash_drawn=True; g.redraw=True + if g.redraw: + self.display() + if g.version_display: utils.version_display() + g.screen.blit(g.pointer,g.pos) + pygame.display.flip() + g.redraw=False + g.clock.tick(40) + +if __name__=="__main__": + pygame.init() + pygame.display.set_mode((1024,768),pygame.FULLSCREEN) + game=Spirolaterals() + game.journal=False + game.run() + pygame.display.quit() + pygame.quit() + sys.exit(0) diff --git a/activity.py b/activity.py new file mode 100755 index 0000000..212b890 --- /dev/null +++ b/activity.py @@ -0,0 +1,53 @@ +# activity.py +# my standard link between sugar and my activity + +from gettext import gettext as _ + +import gtk +import pygame +from sugar.activity import activity +from sugar.graphics.toolbutton import ToolButton +import gobject +import sugargame.canvas +import load_save +import Spirolaterals + +class PeterActivity(activity.Activity): + def __init__(self, handle): + super(PeterActivity, self).__init__(handle) + + # Build the activity toolbar. + toolbox = activity.ActivityToolbox(self) + activity_toolbar = toolbox.get_activity_toolbar() + activity_toolbar.keep.props.visible = False + activity_toolbar.share.props.visible = False + + toolbox.show() + self.set_toolbox(toolbox) + + # Create the game instance. + self.game = Spirolaterals.Spirolaterals() + + # Build the Pygame canvas. + self._pygamecanvas = \ + sugargame.canvas.PygameCanvas(self) + # Note that set_canvas implicitly calls + # read_file when resuming from the Journal. + self.set_canvas(self._pygamecanvas) + self.game.canvas=self._pygamecanvas + + # Start the game running. + self._pygamecanvas.run_pygame(self.game.run) + + def read_file(self, file_path): + try: + f = open(file_path, 'r') + except: + return #**** + load_save.load(f) + f.close() + + def write_file(self, file_path): + f = open(file_path, 'w') + load_save.save(f) + f.close() diff --git a/activity/activity.info b/activity/activity.info new file mode 100644 index 0000000..426e042 --- /dev/null +++ b/activity/activity.info @@ -0,0 +1,8 @@ +[Activity] +name = Spirolaterals +activity_version = 23 +host_version = 1 +bundle_id = org.laptop.community.Spirolaterals +icon = activity +show_launcher = yes +exec = sugar-activity activity.PeterActivity diff --git a/activity/activity.svg b/activity/activity.svg new file mode 100755 index 0000000..34af930 --- /dev/null +++ b/activity/activity.svg @@ -0,0 +1,544 @@ + + + + + +]> + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/buttons.py b/buttons.py new file mode 100755 index 0000000..9542796 --- /dev/null +++ b/buttons.py @@ -0,0 +1,106 @@ +# buttons.py +import g,utils,pygame + +class Button: + _instances=[] + + def __init__(self,name,(x1,y1),centre=True): # eg ('plus',(30,40)) + self._instances.append(self) + up=utils.load_image(name+"_up.png",True) + down=utils.load_image(name+"_down.png",True) + w=up.get_width();h=up.get_height();x=x1;y=y1 + if centre: + self.cx=x; self.cy=y + x=x-w/2; y=y-h/2 + else: + self.cx=x+w/2; self.cy=y+h/2 + self.rect=pygame.Rect(x,y,w,h) + self.name=name; self.x=x; self.y=y; self.active=True + self.up=up; self.down=down; self.stay_down=False + + def mouse_on(self): + mx,my=g.pos + return self.rect.collidepoint(mx,my) + + def draw_up(self): + g.screen.blit(self.up,(self.x,self.y)) + + def draw_down(self): + g.screen.blit(self.down,(self.x,self.y)) + + def on(self): + self.active=True + + def off(self): + self.active=False + +def draw(): + for b in Button._instances: + if b.active: + if b.stay_down: + b.draw_down() + else: + b.draw_up() + +def check(): + clear() + for b in Button._instances: + if b.active: + if b.mouse_on(): + if b.name in ('xyz1','xyz2'): + b.stay_down=True + else: + b.draw_down() + g.screen.blit(g.pointer,g.pos) + pygame.display.flip() + pygame.time.wait(300) + return b.name #**** + return '' # no button pressed + +def clear(): + for b in Button._instances: b.stay_down=False + +def active(name): + for b in Button._instances: + if b.name==name: return b.active #**** + return False # not found + +def stay_down(name): + for b in Button._instances: + if b.name==name: b.stay_down=True; return #**** + return + +def mouse_on(name): + mx,my=g.pos + for b in Button._instances: + if b.name==name: + return b.rect.collidepoint(mx,my) + return False + +def set_mouse(name): + p2=g.pointer.get_height()/2 + for b in Button._instances: + if b.name==name: + x=b.cx; y=b.cy+p2 + pygame.mouse.set_pos(x,y); g.pos=(x,y) + +# eg1 buttons.on('plus') +# eg2 buttons.on(['plus','times']) +def on(name): + if type(name)==type('a'): + list1=[]; list1.append(name) + else: + list1=name + for b in Button._instances: + if b.name in list1: b.active=True + +# eg1 buttons.off('plus') +# eg2 buttons.off(['plus','times']) +def off(name): + if type(name)==type('a'): + list1=[]; list1.append(name) + else: + list1=name + for b in Button._instances: + if b.name in list1: b.active=False + diff --git a/data/1.png b/data/1.png new file mode 100755 index 0000000..1883fcc --- /dev/null +++ b/data/1.png Binary files differ diff --git a/data/1g.png b/data/1g.png new file mode 100755 index 0000000..0165624 --- /dev/null +++ b/data/1g.png Binary files differ diff --git a/data/2.png b/data/2.png new file mode 100755 index 0000000..d4b9bc6 --- /dev/null +++ b/data/2.png Binary files differ diff --git a/data/2g.png b/data/2g.png new file mode 100755 index 0000000..ab29cc8 --- /dev/null +++ b/data/2g.png Binary files differ diff --git a/data/3.png b/data/3.png new file mode 100755 index 0000000..689af23 --- /dev/null +++ b/data/3.png Binary files differ diff --git a/data/3g.png b/data/3g.png new file mode 100755 index 0000000..296a811 --- /dev/null +++ b/data/3g.png Binary files differ diff --git a/data/4.png b/data/4.png new file mode 100755 index 0000000..905bd81 --- /dev/null +++ b/data/4.png Binary files differ diff --git a/data/4g.png b/data/4g.png new file mode 100755 index 0000000..1fc25f8 --- /dev/null +++ b/data/4g.png Binary files differ diff --git a/data/5.png b/data/5.png new file mode 100755 index 0000000..ab0e626 --- /dev/null +++ b/data/5.png Binary files differ diff --git a/data/5g.png b/data/5g.png new file mode 100755 index 0000000..a8d4ce6 --- /dev/null +++ b/data/5g.png Binary files differ diff --git a/data/black_down.png b/data/black_down.png new file mode 100755 index 0000000..ffa6f80 --- /dev/null +++ b/data/black_down.png Binary files differ diff --git a/data/black_up.png b/data/black_up.png new file mode 100755 index 0000000..58b1fa1 --- /dev/null +++ b/data/black_up.png Binary files differ diff --git a/data/box.png b/data/box.png new file mode 100755 index 0000000..debfcdd --- /dev/null +++ b/data/box.png Binary files differ diff --git a/data/crash.png b/data/crash.png new file mode 100755 index 0000000..fe01c64 --- /dev/null +++ b/data/crash.png Binary files differ diff --git a/data/cyan_down.png b/data/cyan_down.png new file mode 100755 index 0000000..55a5c49 --- /dev/null +++ b/data/cyan_down.png Binary files differ diff --git a/data/cyan_up.png b/data/cyan_up.png new file mode 100755 index 0000000..2fadbda --- /dev/null +++ b/data/cyan_up.png Binary files differ diff --git a/data/fast.png b/data/fast.png new file mode 100755 index 0000000..0da9a8a --- /dev/null +++ b/data/fast.png Binary files differ diff --git a/data/green_down.png b/data/green_down.png new file mode 100755 index 0000000..bb8d6fc --- /dev/null +++ b/data/green_down.png Binary files differ diff --git a/data/green_up.png b/data/green_up.png new file mode 100755 index 0000000..3b2e401 --- /dev/null +++ b/data/green_up.png Binary files differ diff --git a/data/magician.png b/data/magician.png new file mode 100755 index 0000000..c8dea81 --- /dev/null +++ b/data/magician.png Binary files differ diff --git a/data/minus_down.png b/data/minus_down.png new file mode 100755 index 0000000..a481f0a --- /dev/null +++ b/data/minus_down.png Binary files differ diff --git a/data/minus_up.png b/data/minus_up.png new file mode 100755 index 0000000..549084d --- /dev/null +++ b/data/minus_up.png Binary files differ diff --git a/data/patterns.dat b/data/patterns.dat new file mode 100755 index 0000000..5682cf8 --- /dev/null +++ b/data/patterns.dat @@ -0,0 +1,122 @@ +11132 +11133 +11142 +11232 +11233 +12142 +12143 +12152 +41321 +21333 +32241 +13243 +21131 +11223 +12141 +21132 +21141 +31131 +21232 +22141 +31231 +12233 +13142 +21233 +21323 +21332 +22142 +22151 +22241 +23141 +31232 +31241 +32141 +12243 +13152 +22242 +23151 +31332 +13153 +22243 +22252 +22333 +22342 +23152 +23242 +31333 +31342 +31423 +31432 +32242 +32251 +32341 +33151 +33241 +41332 +41341 +41422 +41431 +42241 +42331 +13253 +22343 +23252 +31433 +32342 +33251 +41432 +51431 +23253 +23343 +32343 +32352 +32433 +32442 +33252 +33342 +41433 +41442 +41523 +41532 +42342 +42351 +42432 +42441 +43251 +43341 +51432 +51441 +52341 +23353 +32443 +33352 +41533 +42442 +43351 +51532 +52441 +33353 +33443 +42443 +42452 +42533 +42542 +43352 +43442 +51533 +51542 +52442 +52451 +53351 +33453 +42543 +52542 +53451 +43453 +43543 +52543 +52552 +53452 +43553 +53552 +53553 diff --git a/data/plus_down.png b/data/plus_down.png new file mode 100755 index 0000000..b93cdaa --- /dev/null +++ b/data/plus_down.png Binary files differ diff --git a/data/plus_up.png b/data/plus_up.png new file mode 100755 index 0000000..c2dfccd --- /dev/null +++ b/data/plus_up.png Binary files differ diff --git a/data/pointer.png b/data/pointer.png new file mode 100755 index 0000000..7fceb06 --- /dev/null +++ b/data/pointer.png Binary files differ diff --git a/data/red_down.png b/data/red_down.png new file mode 100755 index 0000000..09e814c --- /dev/null +++ b/data/red_down.png Binary files differ diff --git a/data/red_up.png b/data/red_up.png new file mode 100755 index 0000000..90cd8e9 --- /dev/null +++ b/data/red_up.png Binary files differ diff --git a/data/slow.png b/data/slow.png new file mode 100755 index 0000000..15985d1 --- /dev/null +++ b/data/slow.png Binary files differ diff --git a/data/smiley.png b/data/smiley.png new file mode 100755 index 0000000..38407e1 --- /dev/null +++ b/data/smiley.png Binary files differ diff --git a/data/sparkle.png b/data/sparkle.png new file mode 100755 index 0000000..0aa2ae4 --- /dev/null +++ b/data/sparkle.png Binary files differ diff --git a/data/spiro.dat b/data/spiro.dat new file mode 100644 index 0000000..2b2f2e1 --- /dev/null +++ b/data/spiro.dat @@ -0,0 +1,2 @@ +1 +3 diff --git a/data/sunset.jpg b/data/sunset.jpg new file mode 100755 index 0000000..ac361dc --- /dev/null +++ b/data/sunset.jpg Binary files differ diff --git a/data/turtle.png b/data/turtle.png new file mode 100755 index 0000000..1dd56e9 --- /dev/null +++ b/data/turtle.png Binary files differ diff --git a/data/xo.png b/data/xo.png new file mode 100755 index 0000000..f957bf2 --- /dev/null +++ b/data/xo.png Binary files differ diff --git a/g.py b/g.py new file mode 100755 index 0000000..72347bd --- /dev/null +++ b/g.py @@ -0,0 +1,165 @@ +# g.py - spirolaterals globals +import pygame,utils + +XO=False # affects the pygame.display.set_mode() call only +app='Spirolaterals'; ver='1.0' +ver='1.1' +# new system - 32x24 display to allow scaling +ver='1.2' +# smooth scaling, nos display, mouse, utils +ver='1.3' +# moved nos & right buttons up .5 - looks better on XO +# smiley on win +ver='1.4' +# utils.message now has drop shadow +# global gdelay & pause before 1st turtle move by setting tu.ms to current time +# improved smiley +# help on magician click +# gwins - add 1 to level each 5 +ver='1.5' #<<<< Release 2 +# no image scaling if factor = 1.0 ie on XO box +ver='1.6' +# fixed for widescreen +# smiley on left +ver='2.0' +# new style - i.e g.py etc +# sugar cursor +# save level +# scale font +# no music +# right button -> decrease nos +ver='2.1' +# floating point comparisons necessary on XO resolution +ver='2.2' +# check cyan button b4 magician pic +ver='2.3' +# cursor off on button press +ver='2.4' +# speed -/+ (saved) +# No Esc on XO +# click on player pic for Big Pic - click to return +# blue button delay fixed +# black button funny fixed +# green & cyan buttons alternate +# smaller smiley +# help & score implemented +ver='2.5' +# pattern library +# speed slider +# uses mouse_on_image for magician pic - see utils.ImgClickClass +ver='2.6' +# fixed number click bug +ver='2.7' +# no number glow when pattern finished +# smiley - less glow +ver='2.8' # <<< 2 numbers - fixed +# blue button = new pattern but run button fails - fixed +ver='3.2' +# help - if all correct, still show path +ver='4.0' +# proper sugar cursor +# no frame rate +ver='4.1' +# no version display on XO +# doesn't bother with pygame.mouse.get_focused() in run() +# help starts off by ensuring current numbers are in self.tu.current +ver='4.2' +# drop g.current +ver='4.3' +# g.help2 limit check fixed +# magician "holes" filled +ver='21' +# flush_queue() added after button press and key press +ver='22' +# flush_queue() doesn't use gtk on non-XO +ver='23' +# removed patterns 9 & 10 - now have 122 patterns + +UP=(264,273) +DOWN=(258,274) +LEFT=(260,276) +RIGHT=(262,275) +CROSS=(259,120) +CIRCLE=(265,111) +SQUARE=(263,32) +TICK=(257,13) + +def init(): # called by main() + global redraw + global screen,w,h,font1,font2,font3,clock + global factor,offset,imgf,message,version_display + global pos,pointer + redraw=True + version_display=False + screen = pygame.display.get_surface() + pygame.display.set_caption(app) + screen.fill((70,0,70)) + pygame.display.flip() + w,h=screen.get_size() + if float(w)/float(h)>1.5: #widescreen + offset=(w-4*h/3)/2 # we assume 4:3 - centre on widescreen + else: + h=int(.75*w) # allow for toolbar - works to 4:3 + offset=0 + clock=pygame.time.Clock() + factor=float(h)/24 # measurement scaling factor (32x24 = design units) + imgf=float(h)/900 # image scaling factor - all images built for 1200x900 + if pygame.font: + t=int(54*imgf); font1=pygame.font.Font(None,t) + t=int(72*imgf); font2=pygame.font.Font(None,t) + t=int(46*imgf); font3=pygame.font.Font(None,t) + message='' + pos=pygame.mouse.get_pos() + pointer=utils.load_image('pointer.png',True) + pygame.mouse.set_visible(False) + + # this activity only + global x0,y0,x1,goal,steps,pattern,delay,help1,help2,show_help + global big,big_surface,score,slider,level,finale,player_surface + global crash_drawn,magician,magician_c + global bgd,box,dd,magician,turtle,crash,smiley,n,n_glow,n_cx0,n_cy0 + global n_dx,bw,sparkle + x0=sx(2.0); y0=sy(1.1) # left frame + x1=sx(16.8) # right frame + goal=[] + steps=40 # number of steps to draw pic + pattern=1; level=1 + delay=(3-level)*400 + help1=0; help2=0; show_help=False + score=0 + finale=False + crash_drawn=True # used to make sure crash is drawn + magician=utils.load_image('magician.png',True) + magician_c=(sx(5.5),sy(20)) + sparkle=utils.load_image('sparkle.png',True) + bgd=utils.load_image('sunset.jpg') + box=utils.load_image('box.png',True); bw=box.get_width(); s=bw-2*sy(1) + player_surface=pygame.Surface((s,s)); big=False; big_surface=None + dd=box.get_width()/8 # turtle step size + turtle=utils.load_image('turtle.png',True) + crash=utils.load_image('crash.png',True) + smiley=utils.load_image('smiley.png',True) + n=[] # 1,2,3,4,5 images + n_glow=[] # ... with glow + for i in range(5): + img=utils.load_image(str(i+1)+'.png',True); n.append(img) + img=utils.load_image(str(i+1)+'g.png',True); n_glow.append(img) + n_cx0=sx(17.4)+n[3].get_width()/2 # "4" is widest + n_cy0=sy(17); n_dx=sy(2.6) + +def sx(f): # scale x function + return f*factor+offset + +def sy(f): # scale y function + return f*factor diff --git a/load_save.py b/load_save.py new file mode 100755 index 0000000..9d2ba78 --- /dev/null +++ b/load_save.py @@ -0,0 +1,26 @@ +#load_save.py +import g + +loaded=[] # list of strings + +def load(f): + global loaded + try: + for line in f.readlines(): + loaded.append(line) + except: + pass + +def save(f): + f.write(str(g.pattern)+'\n') + f.write(str(g.level)+'\n') + +# note need for rstrip() on strings +def retrieve(): + global loaded + if len(loaded)==2: + g.pattern=int(loaded[0]) + g.level=int(loaded[1]) + + + diff --git a/my_turtle.py b/my_turtle.py new file mode 100755 index 0000000..421459c --- /dev/null +++ b/my_turtle.py @@ -0,0 +1,108 @@ +# my_turtle.py +import g,pygame,utils + +class TurtleClass: # used only for keeping track of the right hand turtle + + def setup(self): + steps=0 + for n in self.current: steps=steps+4*n + self.steps=steps + self.x1=g.x1+4.0*g.dd; self.y1=g.y0+6.0*g.dd; self.dx=0; self.dy=-g.dd + self.step_count=0 + self.ms=pygame.time.get_ticks() + self.running=False; self.crashed=False; self.changed=False + self.win=False + + def move(self): + if self.step_countg.delay: #time to move + g.redraw=True + x2=self.x1+self.dx; y2=self.y1+self.dy + self.x1=x2; self.y1=y2 + self.step_count+=1 + self.ms=pygame.time.get_ticks() + else: + self.running=False + + def help1(self): + x1=g.x1+4*g.dd; y1=g.y0+6*g.dd; dx=0; dy=-g.dd; steps=0; angle=0; n=0 + for j in self.current: + for k in range(j): + steps+=1 + x2=x1+dx; y2=y1+dy + pygame.draw.line(g.screen,utils.CYAN,(x1,y1),(x2,y2),4) + x1=x2; y1=y2 + if dy==-g.dd: dx=g.dd;dy=0;angle=90 + elif dx==g.dd: dx=0;dy=g.dd;angle=180 + elif dy==g.dd: dx=-g.dd;dy=0;angle=270 + else: dx=0;dy=-g.dd;angle=0 + n+=1 + if n==g.help1: break + utils.centre_blit(g.screen,g.turtle,(x2,y2),angle) + self.step_count=steps + + def draw(self): + x1=g.x1+4*g.dd; y1=g.y0+6*g.dd; dx=0; dy=-g.dd; steps=0; angle=0 + x2=x1; y2=y1 # in case we haven't moved yet - for turtle image + done=True; n=0 + for i in range(4): + for j in self.current: + for k in range(j): + steps+=1 + if not g.show_help: + if steps>self.step_count: done=False; break + x2=x1+dx; y2=y1+dy + pygame.draw.line(g.screen,utils.CYAN,(x1,y1),(x2,y2),4) + x1=x2; y1=y2 + if not g.show_help: + if steps>self.step_count: break + if dy==-g.dd: dx=g.dd;dy=0;angle=90 + elif dx==g.dd: dx=0;dy=g.dd;angle=180 + elif dy==g.dd: dx=-g.dd;dy=0;angle=270 + else: dx=0;dy=-g.dd;angle=0 + if g.show_help: + n+=1 + if n==g.help1: self.step_count=steps; break + if g.show_help: + if n==g.help1: break + elif steps>self.step_count: break + img=g.turtle + if self.crashed: img=g.crash + utils.centre_blit(g.screen,img,(x2,y2),angle) + d8=8*g.dd + if not g.show_help: + if abs(x2-g.x1)<.1 or abs(x2-(g.x1+d8))<.1 or abs(y2-g.y0)<.1 or abs(y2-(g.y0+d8))<.1: + if not self.crashed==True: g.crash_drawn=False + self.running=False; self.crashed=True + elif done: + self.win=correct(self.current) + if self.win: + if g.finale==False: + if g.help2>5: g.help2=5 + g.score=g.score+6-g.help2 + g.finale=True + +def correct(current): + return trace(g.goal)==trace(current) + +def trace(l): # returns a list based on the line segments drawn + hl=[0,0,0,0,0,0,0]; vl=[0,0,0,0,0,0,0] + x1=3;y1=1;dx=0;dy=1 + for i in range(4): + for j in l: + for k in range(j): + x2=x1+dx; y2=y1+dy;mark(hl,vl,x1,y1,x2,y2); x1=x2; y1=y2 + if dy==-1: dx=-1;dy=0 + elif dx==1: dx=0;dy=-1 + elif dy==1: dx=1;dy=0 + else: dx=0;dy=1 + return hl+vl + +def mark(hl,vl,x1,y1,x2,y2): + twos=[1,2,4,8,16,32] + if x1==x2: #vertical + y=min(y1,y2);vl[x1]=vl[x1]|twos[y] + else: + x=min(x1,x2);hl[y1]=hl[y1]|twos[x] + diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..77fda74 --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +from sugar.activity import bundlebuilder +if __name__ == "__main__": + bundlebuilder.start() diff --git a/slider.py b/slider.py new file mode 100755 index 0000000..8968e6f --- /dev/null +++ b/slider.py @@ -0,0 +1,55 @@ +# slider.py +import utils,pygame,g,copy + +# sets g.level 1..steps +class Slider: + def __init__(self,cx,cy,steps,colour=utils.BLACK): + self.easy=utils.load_image('slow.png',True) + self.hard=utils.load_image('fast.png',True) + self.xo=utils.load_image('xo.png',True) + iw=self.hard.get_width(); ih=self.hard.get_height() + w=g.sy(16); w2=w/2; h2=ih/2 + self.x1=cx-w2; self.y=cy-h2; self.x2=cx+w2-iw + x=cx-w2+iw*1.2; w=w-2*iw*1.2; h=g.sy(.12);y=cy+g.sy(.34) + self.rect=pygame.Rect(x,y,w,h) + mh=g.sy(1);self.mark=pygame.Rect(x,y-mh/2+h/2,h,mh) + self.steps=steps; self.dx=w/(steps-1);self.colour=colour + self.cx=cx; self.cy=cy + marks=[]; x=self.rect.left; click_rects=[]; dx=self.dx + for i in range(self.steps): + rect=copy.copy(self.mark); rect.left=x-5; rect.width=10; marks.append(rect) + click_rect=pygame.Rect(x-dx/2,self.mark.top,dx,self.mark.h) + click_rects.append(click_rect) + x+=dx + self.marks=marks; self.click_rects=click_rects + + def draw(self): + g.screen.blit(self.easy,(self.x1,self.y)); + g.screen.blit(self.hard,(self.x2,self.y)) + pygame.draw.rect(g.screen,self.colour,self.rect) # horizontal line + x=self.rect.left # now draw marks + for i in range(self.steps): + self.mark.left=x; pygame.draw.rect(g.screen,self.colour,self.mark) + if i==(g.level-1): + dx=self.xo.get_width()/2; dy=self.xo.get_height()/2 + g.screen.blit(self.xo,(x-dx+self.mark.w/2,self.cy-dy)) + x+=self.dx + + def mouse(self): + mx,my=g.pos + rect=self.easy.get_rect(topleft=(self.x1,self.y)) + if rect.collidepoint(mx,my): + if g.level>1: g.level-=1; return True#**** + rect=self.hard.get_rect(topleft=(self.x2,self.y)) + if rect.collidepoint(mx,my): + if g.level.1: # only scale if factor <> 1 + w=img.get_width(); h=img.get_height() + try: + img=pygame.transform.smoothscale(img,(int(g.imgf*w),int(g.imgf*h))) + except: + img=pygame.transform.scale(img,(int(g.imgf*w),int(g.imgf*h))) + return img + +# eg new_list=copy_list(old_list) +def copy_list(l): + new_list=[];new_list.extend(l) + return new_list + +def shuffle(lst): + l1=lst; lt=[] + for i in range(len(lst)): + ln=len(l1); r=random.randint(0,ln-1); + lt.append(lst[r]); l1.remove(lst[r]) + return lt + +def centre_blit(screen,img,(cx,cy),angle=0): # rotation is clockwise + img1=img + if angle!=0: img1=pygame.transform.rotate(img,-angle) + rect=img1.get_rect() + screen.blit(img1,(cx-rect.width/2,cy-rect.height/2)) + +def text_blit(screen,s,font,(cx,cy),(r,g,b)): + text=font.render(s,True,(0,0,0)) + rect=text.get_rect(); rect.centerx=cx+2; rect.centery=cy+2 + screen.blit(text,rect) + text=font.render(s,True,(r,g,b)) + rect=text.get_rect(); rect.centerx=cx; rect.centery=cy + screen.blit(text,rect) + return rect + +def text_blit1(screen,s,font,(x,y),(r,g,b)): + text=font.render(s,True,(r,g,b)) + rect=text.get_rect(); rect.x=x; rect.y=y + screen.blit(text,rect) + +# m is the message +# d is the # of pixels in the border around the text +# (cx,cy) = co-ords centre - (0,0) means use screen centre +def message(screen,font,m,(cx,cy)=(0,0),d=20): + if m!='': + if pygame.font: + text=font.render(m,True,(255,255,255)) + shadow=font.render(m,True,(0,0,0)) + rect=text.get_rect() + if cx==0: cx=screen.get_width()/2 + if cy==0: cy=screen.get_height()/2 + rect.centerx=cx;rect.centery=cy + bgd=pygame.Surface((rect.width+2*d,rect.height+2*d)) + bgd.fill((0,255,255)) + bgd.set_alpha(128) + screen.blit(bgd,(rect.left-d,rect.top-d)) + screen.blit(shadow,(rect.x+2,rect.y+2,rect.width,rect.height)) + screen.blit(text,rect) + +def mouse_on_img(img,(x,y)): # x,y=top left + w=img.get_width() + h=img.get_height() + mx,my=g.pos + if mx(x+w): return False + if my(y+h): return False + try: # in case out of range + col=img.get_at((int(mx-x),int(my-y))) + except: + return False + if col[3]<10: return False + return True + +def mouse_on_img1(img,(cx,cy)): + xy=centre_to_top_left(img,(cx,cy)) + return mouse_on_img(img,xy) + +def mouse_on_img_rect(img,(cx,cy)): + w2=img.get_width()/2; h2=img.get_height()/2 + x1=cx-w2; y1=cy-h2; x2=cx+w2; y2=cy+h2 + return mouse_in(x1,y1,x2,y2) + +def mouse_in(x1,y1,x2,y2): + mx,my=g.pos + if x1>mx: return False + if x2my: return False + if y2None: + outline=outline_font.render(str(n),True,BLACK) + centre_blit(g.screen,outline,(cx,cy)) + centre_blit(g.screen,text,(cx,cy)) + +def display_number1(n,(x,cy),font,colour=BLACK): + if pygame.font: + text=font.render(str(n),True,colour) + y=cy-text.get_height()/2 + g.screen.blit(text,(x,y)) + +def top_left_to_centre(img,(x,y)): + cx=x+img.get_width()/2; cy=y+img.get_height()/2 + return (cx,cy) + +def centre_to_top_left(img,(cx,cy)): + x=cx-img.get_width()/2; y=cy-img.get_height()/2 + return (x,y) + + + -- cgit v0.9.1