Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2013-04-12 10:48:40 (GMT)
committer Walter Bender <walter.bender@gmail.com>2013-04-12 10:48:40 (GMT)
commit30e8db1710f3c3f1c0c0054b4e0b89bceb533c62 (patch)
treea0de479b0e4f9a2e3967ee18ba90027a7cb5958a
Making initial git repository for Peter's version
-rw-r--r--.gitignore2
-rwxr-xr-xSpirolaterals.py345
-rwxr-xr-xactivity.py53
-rw-r--r--activity/activity.info8
-rwxr-xr-xactivity/activity.svg544
-rwxr-xr-xbuttons.py106
-rwxr-xr-xdata/1.pngbin0 -> 1881 bytes
-rwxr-xr-xdata/1g.pngbin0 -> 5603 bytes
-rwxr-xr-xdata/2.pngbin0 -> 4590 bytes
-rwxr-xr-xdata/2g.pngbin0 -> 10528 bytes
-rwxr-xr-xdata/3.pngbin0 -> 4829 bytes
-rwxr-xr-xdata/3g.pngbin0 -> 10704 bytes
-rwxr-xr-xdata/4.pngbin0 -> 3448 bytes
-rwxr-xr-xdata/4g.pngbin0 -> 9115 bytes
-rwxr-xr-xdata/5.pngbin0 -> 3893 bytes
-rwxr-xr-xdata/5g.pngbin0 -> 8992 bytes
-rwxr-xr-xdata/black_down.pngbin0 -> 7734 bytes
-rwxr-xr-xdata/black_up.pngbin0 -> 6114 bytes
-rwxr-xr-xdata/box.pngbin0 -> 13925 bytes
-rwxr-xr-xdata/crash.pngbin0 -> 1460 bytes
-rwxr-xr-xdata/cyan_down.pngbin0 -> 8314 bytes
-rwxr-xr-xdata/cyan_up.pngbin0 -> 7333 bytes
-rwxr-xr-xdata/fast.pngbin0 -> 24040 bytes
-rwxr-xr-xdata/green_down.pngbin0 -> 8259 bytes
-rwxr-xr-xdata/green_up.pngbin0 -> 7252 bytes
-rwxr-xr-xdata/magician.pngbin0 -> 192255 bytes
-rwxr-xr-xdata/minus_down.pngbin0 -> 8356 bytes
-rwxr-xr-xdata/minus_up.pngbin0 -> 7166 bytes
-rwxr-xr-xdata/patterns.dat122
-rwxr-xr-xdata/plus_down.pngbin0 -> 8762 bytes
-rwxr-xr-xdata/plus_up.pngbin0 -> 7452 bytes
-rwxr-xr-xdata/pointer.pngbin0 -> 427 bytes
-rwxr-xr-xdata/red_down.pngbin0 -> 8255 bytes
-rwxr-xr-xdata/red_up.pngbin0 -> 7264 bytes
-rwxr-xr-xdata/slow.pngbin0 -> 18550 bytes
-rwxr-xr-xdata/smiley.pngbin0 -> 36231 bytes
-rwxr-xr-xdata/sparkle.pngbin0 -> 6574 bytes
-rw-r--r--data/spiro.dat2
-rwxr-xr-xdata/sunset.jpgbin0 -> 103104 bytes
-rwxr-xr-xdata/turtle.pngbin0 -> 2018 bytes
-rwxr-xr-xdata/xo.pngbin0 -> 3814 bytes
-rwxr-xr-xg.py165
-rwxr-xr-xload_save.py26
-rwxr-xr-xmy_turtle.py108
-rwxr-xr-xsetup.py4
-rwxr-xr-xslider.py55
-rw-r--r--sugargame/__init__.py1
-rw-r--r--sugargame/canvas.py62
-rw-r--r--sugargame/event.py246
-rwxr-xr-xutils.py189
50 files changed, 2038 insertions, 0 deletions
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<self.tu.steps: # no glow if finished
+ n=self.tu.current[pos]
+ utils.centre_blit(g.screen,g.n_glow[n-1],(x_glow,g.n_cy0))
+
+ def check_nos(self,mouse_button):
+ w=g.n[3].get_width(); h=g.n[3].get_height() # "4" is widest
+ x1=g.n_cx0-w/2; y1=g.n_cy0-h/2
+ x2=g.n_cx0+w/2; y2=g.n_cy0+h/2
+ for pos in range(5):
+ if utils.mouse_in(x1,y1,x2,y2):
+ self.tu.changed=True; self.tu.running=False
+ if mouse_button==1:
+ self.inc_numbers(pos)
+ elif mouse_button==3:
+ self.dec_numbers(pos)
+ return True
+ x1+=g.n_dx; x2+=g.n_dx
+ return False
+
+ def calc_pos(self,step_count): # calculate which number we are currently on
+ steps=1
+ if self.tu.crashed:step_count-=1
+ for i in range(4):
+ pos=0
+ for j in self.tu.current:
+ for k in range(j):
+ if steps>=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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink " http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#FF0000">
+ <!ENTITY fill_color "#00FF00">
+]>
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="41.250999pt"
+ height="41.249001pt"
+ viewBox="0 0 41.251 41.249"
+ id="svg2"
+ style="fill-rule:evenodd;stroke-width:0.50099999;stroke-linejoin:bevel;overflow:visible">
+ <metadata
+ id="metadata156">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4">
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow2"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g7">
+ <path
+ d="M -9,54 -9,-54 117,0 z"
+ id="path9" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow3"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g12">
+ <path
+ d="M -27,54 -9,0 -27,-54 135,0 z"
+ id="path14" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow4"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g17">
+ <path
+ d="m -9,0 0,-45 c 0,-6.708 11.808,-11.58 18,-9 l 108,45 c 3.916,1.631 9,4.758 9,9 0,4.242 -5.084,7.369 -9,9 L 9,54 C 2.808,56.58 -9,51.708 -9,45 z"
+ id="path19" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow5"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g22">
+ <path
+ d="M -54,0 C -54,29.807 -29.807,54 0,54 29.807,54 54,29.807 54,0 54,-29.807 29.807,-54 0,-54 -29.807,-54 -54,-29.807 -54,0 z"
+ id="path24" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow6"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g27">
+ <path
+ d="M -63,0 0,63 63,0 0,-63 z"
+ id="path29" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow7"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g32">
+ <path
+ d="m 18,-54 90,0 L 63,0 108,54 18,54 -36,0 z"
+ id="path34" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow8"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g37">
+ <path
+ d="m -36,0 54,-54 36,0 -36,36 9,0 36,-36 36,0 -36,36 9,0 36,-36 36,0 -54,54 54,54 -36,0 -36,-36 -9,0 36,36 -36,0 -36,-36 -9,0 36,36 -36,0 z"
+ id="path39" />
+ </g>
+ </marker>
+ <marker
+ markerUnits="strokeWidth"
+ markerWidth="1"
+ markerHeight="1"
+ orient="auto"
+ viewBox="0 0 1 1"
+ id="DefaultArrow9"
+ style="overflow:visible">
+ <g
+ transform="scale(0.00925926,0.00925926)"
+ id="g42">
+ <path
+ d="M 0,45 -45,0 0,-45 45,0 z M 0,63 -63,0 0,-63 63,0 z"
+ id="path44" />
+ </g>
+ </marker>
+ <filter
+ color-interpolation-filters="sRGB"
+ id="StainedFilter">
+ <feBlend
+ in2="BackgroundImage"
+ mode="multiply"
+ in="SourceGraphic"
+ result="blend"
+ id="feBlend47" />
+ <feComposite
+ in2="SourceAlpha"
+ operator="in"
+ in="blend"
+ result="comp"
+ id="feComposite49" />
+ </filter>
+ <filter
+ color-interpolation-filters="sRGB"
+ id="BleachFilter">
+ <feBlend
+ in2="BackgroundImage"
+ mode="screen"
+ in="SourceGraphic"
+ result="blend"
+ id="feBlend52" />
+ <feComposite
+ in2="SourceAlpha"
+ operator="in"
+ in="blend"
+ result="comp"
+ id="feComposite54" />
+ </filter>
+ <filter
+ color-interpolation-filters="sRGB"
+ id="InvertTransparencyBitmapFilter">
+ <feComponentTransfer
+ id="feComponentTransfer57">
+ <feFuncR
+ id="feFuncR59"
+ offset="-0.055"
+ exponent=".416666666"
+ amplitude="1.055"
+ type="gamma" />
+ <feFuncG
+ id="feFuncG61"
+ offset="-0.055"
+ exponent=".416666666"
+ amplitude="1.055"
+ type="gamma" />
+ <feFuncB
+ id="feFuncB63"
+ offset="-0.055"
+ exponent=".416666666"
+ amplitude="1.055"
+ type="gamma" />
+ </feComponentTransfer>
+ <feComponentTransfer
+ id="feComponentTransfer65">
+ <feFuncR
+ id="feFuncR67"
+ intercept="1"
+ slope="-1"
+ type="linear" />
+ <feFuncG
+ id="feFuncG69"
+ intercept="1"
+ slope="-1"
+ type="linear" />
+ <feFuncB
+ id="feFuncB71"
+ intercept="1"
+ slope="-1"
+ type="linear" />
+ <feFuncA
+ id="feFuncA73"
+ intercept="0"
+ slope="1"
+ type="linear" />
+ </feComponentTransfer>
+ <feComponentTransfer
+ id="feComponentTransfer75">
+ <feFuncR
+ id="feFuncR77"
+ offset="0"
+ exponent="2.4"
+ amplitude="1"
+ type="gamma" />
+ <feFuncG
+ id="feFuncG79"
+ offset="0"
+ exponent="2.4"
+ amplitude="1"
+ type="gamma" />
+ <feFuncB
+ id="feFuncB81"
+ offset="0"
+ exponent="2.4"
+ amplitude="1"
+ type="gamma" />
+ </feComponentTransfer>
+ </filter>
+ </defs>
+ <g
+ transform="scale(1,-1)"
+ id="Document"
+ style="font-size:16px;fill:none;stroke:#000000;font-family:Times New Roman">
+ <g
+ transform="translate(0,-41.249)"
+ id="Spread">
+ <g
+ id="Layer 1">
+ <rect
+ width="41.250999"
+ height="41.249001"
+ x="0.001"
+ y="0.001"
+ id="rect86"
+ style="fill:&fill_color;;stroke:none" />
+ <rect
+ width="2.9990001"
+ height="20.999001"
+ x="13.499"
+ y="15.001"
+ id="rect88"
+ style="fill:&stroke_color;;stroke:none" />
+ <rect
+ width="3"
+ height="35.997002"
+ x="29.993"
+ y="0.0040000002"
+ id="rect90"
+ style="fill:&stroke_color;;stroke:none" />
+ <rect
+ width="19.499001"
+ height="2.9979999"
+ x="13.5"
+ y="32.998001"
+ id="rect92"
+ style="fill:&stroke_color;;stroke:none" />
+ <rect
+ width="26.997999"
+ height="2.9979999"
+ x="14.246"
+ y="14.997"
+ id="rect94"
+ style="fill:&stroke_color;;stroke:none" />
+ <rect
+ width="10.264"
+ height="7.1090002"
+ x="-5.132"
+ y="-3.5539999"
+ transform="matrix(1.3788101e-4,0.99999999,-0.99999999,1.3788101e-4,15,16.302)"
+ id="rect96"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="7.105"
+ height="1.581"
+ x="-3.552"
+ y="-0.79000002"
+ transform="matrix(0,1,-1,0,10.657,17.091)"
+ id="rect98"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="7.105"
+ height="1.581"
+ x="-3.552"
+ y="-0.79000002"
+ transform="matrix(0,1,-1,0,19.342,17.091)"
+ id="rect100"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="5.526"
+ height="2.3699999"
+ x="-2.763"
+ y="-1.1849999"
+ transform="matrix(0,1,-1,0,15,24.197)"
+ id="rect102"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="3.9489999"
+ x="-0.39399999"
+ y="-1.974"
+ transform="matrix(0,1,-1,0,15,10.775)"
+ id="rect104"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.79000002"
+ x="-0.39399999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,15,9.986)"
+ id="rect106"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,11.052,11.959)"
+ id="rect108"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,10.263,11.17)"
+ id="rect110"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.79000002"
+ x="-1.183"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,9.473,10.775)"
+ id="rect112"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="1.5779999"
+ height="0.79000002"
+ x="-0.78899997"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,8.684,10.38)"
+ id="rect114"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,18.947,11.959)"
+ id="rect116"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,19.737,11.17)"
+ id="rect118"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.79000002"
+ x="-1.183"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,20.526,10.775)"
+ id="rect120"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="1.5779999"
+ height="0.79000002"
+ x="-0.78899997"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,21.316,10.38)"
+ id="rect122"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,9.473,16.697)"
+ id="rect124"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,20.526,16.697)"
+ id="rect126"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="1.5779999"
+ height="0.79000002"
+ x="-0.78899997"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,7.896,21.435)"
+ id="rect128"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.78899997"
+ x="-1.183"
+ y="-0.39399999"
+ transform="matrix(0,1,-1,0,8.684,21.039)"
+ id="rect130"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.78899997"
+ x="-1.5779999"
+ y="-0.39399999"
+ transform="matrix(0,1,-1,0,9.473,20.644)"
+ id="rect132"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.78899997"
+ x="-0.39399999"
+ y="-0.39399999"
+ transform="matrix(0,1,-1,0,10.263,21.039)"
+ id="rect134"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.79000002"
+ x="-1.183"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,13.421,24.987)"
+ id="rect136"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.79000002"
+ x="-1.183"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,16.579,24.987)"
+ id="rect138"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.79000002"
+ x="-0.39399999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,16.579,21.828)"
+ id="rect140"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.79000002"
+ x="-0.39399999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,13.421,21.828)"
+ id="rect142"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.79000002"
+ x="-0.39399999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,15,27.355)"
+ id="rect144"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="0.78899997"
+ height="0.79000002"
+ x="-0.39399999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,19.737,21.039)"
+ id="rect146"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="3.1570001"
+ height="0.79000002"
+ x="-1.5779999"
+ y="-0.39500001"
+ transform="matrix(0,1,-1,0,20.529,20.644)"
+ id="rect148"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="2.3670001"
+ height="0.78899997"
+ x="-1.183"
+ y="-0.39399999"
+ transform="matrix(0,1,-1,0,21.316,21.039)"
+ id="rect150"
+ style="fill:#000000;stroke:none" />
+ <rect
+ width="1.5779999"
+ height="0.78899997"
+ x="-0.78899997"
+ y="-0.39399999"
+ transform="matrix(0,1,-1,0,22.105,21.434)"
+ id="rect152"
+ style="fill:#000000;stroke:none" />
+ </g>
+ </g>
+ </g>
+</svg>
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' # <<<<Release 11
+# pattern number displayed
+ver='2.9'
+# help only on wrong digits
+ver='3.0'
+# sugar
+ver='3.1'
+# redraw implented
+ver='3.2'
+# crash only shows after mouse move - fixed - g.crash_drawn
+# red mouse after crash + help - fixed
+# change help # -> 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_count<self.steps:
+ d=pygame.time.get_ticks()-self.ms
+ if d<0 or d>g.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<self.steps: g.level+=1; return True#****
+ n=1
+ for rect in self.click_rects:
+ if rect.collidepoint(mx,my):
+ if g.level==n:
+ return False#****
+ else:
+ g.level=n; return True#****
+ n+=1
+ return False
+
diff --git a/sugargame/__init__.py b/sugargame/__init__.py
new file mode 100644
index 0000000..439eb0c
--- /dev/null
+++ b/sugargame/__init__.py
@@ -0,0 +1 @@
+__version__ = '1.1'
diff --git a/sugargame/canvas.py b/sugargame/canvas.py
new file mode 100644
index 0000000..9cbef63
--- /dev/null
+++ b/sugargame/canvas.py
@@ -0,0 +1,62 @@
+import os
+import gtk
+import gobject
+import pygame
+import event
+
+CANVAS = None
+
+class PygameCanvas(gtk.EventBox):
+
+ """
+ mainwindow is the activity intself.
+ """
+ def __init__(self, mainwindow, pointer_hint = True):
+ gtk.EventBox.__init__(self)
+
+ global CANVAS
+ assert CANVAS == None, "Only one PygameCanvas can be created, ever."
+ CANVAS = self
+
+ # Initialize Events translator before widget gets "realized".
+ self.translator = event.Translator(mainwindow, self)
+
+ self._mainwindow = mainwindow
+
+ self.set_flags(gtk.CAN_FOCUS)
+
+ self._socket = gtk.Socket()
+ self.add(self._socket)
+ self.show_all()
+
+ def run_pygame(self, main_fn):
+ # Run the main loop after a short delay. The reason for the delay is that the
+ # Sugar activity is not properly created until after its constructor returns.
+ # If the Pygame main loop is called from the activity constructor, the
+ # constructor never returns and the activity freezes.
+ gobject.idle_add(self._run_pygame_cb, main_fn)
+
+ def _run_pygame_cb(self, main_fn):
+ assert pygame.display.get_surface() is None, "PygameCanvas.run_pygame can only be called once."
+
+ # Preinitialize Pygame with the X window ID.
+ assert pygame.display.get_init() == False, "Pygame must not be initialized before calling PygameCanvas.run_pygame."
+ os.environ['SDL_WINDOWID'] = str(self._socket.get_id())
+ pygame.init()
+
+ # Restore the default cursor.
+ #self._socket.window.set_cursor(None) = no "phantom" cursor
+
+ # Initialize the Pygame window.
+ r = self.get_allocation()
+ pygame.display.set_mode((r.width, r.height), pygame.RESIZABLE)
+
+ # Hook certain Pygame functions with GTK equivalents.
+ self.translator.hook_pygame()
+
+ # Run the Pygame main loop.
+ main_fn()
+ return False
+
+ def get_pygame_widget(self):
+ return self._socket
diff --git a/sugargame/event.py b/sugargame/event.py
new file mode 100644
index 0000000..0b81053
--- /dev/null
+++ b/sugargame/event.py
@@ -0,0 +1,246 @@
+import gtk
+import gobject
+import pygame
+import pygame.event
+import logging
+
+class _MockEvent(object):
+ def __init__(self, keyval):
+ self.keyval = keyval
+
+class Translator(object):
+ key_trans = {
+ 'Alt_L': pygame.K_LALT,
+ 'Alt_R': pygame.K_RALT,
+ 'Control_L': pygame.K_LCTRL,
+ 'Control_R': pygame.K_RCTRL,
+ 'Shift_L': pygame.K_LSHIFT,
+ 'Shift_R': pygame.K_RSHIFT,
+ 'Super_L': pygame.K_LSUPER,
+ 'Super_R': pygame.K_RSUPER,
+ 'KP_Page_Up' : pygame.K_KP9,
+ 'KP_Page_Down' : pygame.K_KP3,
+ 'KP_End' : pygame.K_KP1,
+ 'KP_Home' : pygame.K_KP7,
+ 'KP_Up' : pygame.K_KP8,
+ 'KP_Down' : pygame.K_KP2,
+ 'KP_Left' : pygame.K_KP4,
+ 'KP_Right' : pygame.K_KP6,
+ 'equal' : pygame.K_EQUALS,
+ 'multiply' : pygame.K_ASTERISK,
+ 'KP_Add' : pygame.K_PLUS,
+
+ }
+
+ mod_map = {
+ pygame.K_LALT: pygame.KMOD_LALT,
+ pygame.K_RALT: pygame.KMOD_RALT,
+ pygame.K_LCTRL: pygame.KMOD_LCTRL,
+ pygame.K_RCTRL: pygame.KMOD_RCTRL,
+ pygame.K_LSHIFT: pygame.KMOD_LSHIFT,
+ pygame.K_RSHIFT: pygame.KMOD_RSHIFT,
+ }
+
+ def __init__(self, mainwindow, inner_evb):
+ """Initialise the Translator with the windows to which to listen"""
+ self._mainwindow = mainwindow
+ self._inner_evb = inner_evb
+
+ # Enable events
+ # (add instead of set here because the main window is already realized)
+ self._mainwindow.add_events(
+ gtk.gdk.KEY_PRESS_MASK | \
+ gtk.gdk.KEY_RELEASE_MASK \
+ )
+
+ self._inner_evb.set_events(
+ gtk.gdk.POINTER_MOTION_MASK | \
+ gtk.gdk.POINTER_MOTION_HINT_MASK | \
+ gtk.gdk.BUTTON_MOTION_MASK | \
+ gtk.gdk.BUTTON_PRESS_MASK | \
+ gtk.gdk.BUTTON_RELEASE_MASK
+ )
+
+ self._mainwindow.set_flags(gtk.CAN_FOCUS)
+ self._inner_evb.set_flags(gtk.CAN_FOCUS)
+
+ # Callback functions to link the event systems
+ self._mainwindow.connect('unrealize', self._quit_cb)
+ self._inner_evb.connect('key_press_event', self._keydown_cb)
+ self._inner_evb.connect('key_release_event', self._keyup_cb)
+ self._inner_evb.connect('button_press_event', self._mousedown_cb)
+ self._inner_evb.connect('button_release_event', self._mouseup_cb)
+ self._inner_evb.connect('motion-notify-event', self._mousemove_cb)
+ self._inner_evb.connect('expose-event', self._expose_cb)
+ self._inner_evb.connect('configure-event', self._resize_cb)
+
+ # Internal data
+ self.__stopped = False
+ self.__keystate = [0] * 323
+ self.__button_state = [0,0,0]
+ self.__mouse_pos = (0,0)
+ self.__repeat = (None, None)
+ self.__held = set()
+ self.__held_time_left = {}
+ self.__held_last_time = {}
+ self.__tick_id = None
+
+ def hook_pygame(self):
+ pygame.key.get_pressed = self._get_pressed
+ pygame.key.set_repeat = self._set_repeat
+ pygame.mouse.get_pressed = self._get_mouse_pressed
+ pygame.mouse.get_pos = self._get_mouse_pos
+
+ def _expose_cb(self, event, widget):
+ if pygame.display.get_init():
+ pygame.event.post(pygame.event.Event(pygame.VIDEOEXPOSE))
+ return True
+
+ def _resize_cb(self, widget, event):
+ evt = pygame.event.Event(pygame.VIDEORESIZE,
+ size=(event.width,event.height), width=event.width, height=event.height)
+ pygame.event.post(evt)
+ return False # continue processing
+
+ def _quit_cb(self, data=None):
+ self.__stopped = True
+ pygame.event.post(pygame.event.Event(pygame.QUIT))
+
+ def _keydown_cb(self, widget, event):
+ key = event.keyval
+ if key in self.__held:
+ return True
+ else:
+ if self.__repeat[0] is not None:
+ self.__held_last_time[key] = pygame.time.get_ticks()
+ self.__held_time_left[key] = self.__repeat[0]
+ self.__held.add(key)
+
+ return self._keyevent(widget, event, pygame.KEYDOWN)
+
+ def _keyup_cb(self, widget, event):
+ key = event.keyval
+ if self.__repeat[0] is not None:
+ if key in self.__held:
+ # This is possibly false if set_repeat() is called with a key held
+ del self.__held_time_left[key]
+ del self.__held_last_time[key]
+ self.__held.discard(key)
+
+ return self._keyevent(widget, event, pygame.KEYUP)
+
+ def _keymods(self):
+ mod = 0
+ for key_val, mod_val in self.mod_map.iteritems():
+ mod |= self.__keystate[key_val] and mod_val
+ return mod
+
+ def _keyevent(self, widget, event, type):
+ key = gtk.gdk.keyval_name(event.keyval)
+ if key is None:
+ # No idea what this key is.
+ return False
+
+ keycode = None
+ if key in self.key_trans:
+ keycode = self.key_trans[key]
+ elif hasattr(pygame, 'K_'+key.upper()):
+ keycode = getattr(pygame, 'K_'+key.upper())
+ elif hasattr(pygame, 'K_'+key.lower()):
+ keycode = getattr(pygame, 'K_'+key.lower())
+ elif key == 'XF86Start':
+ # view source request, specially handled...
+ self._mainwindow.view_source()
+ else:
+ print 'Key %s unrecognized' % key
+
+ if keycode is not None:
+ if type == pygame.KEYDOWN:
+ mod = self._keymods()
+ self.__keystate[keycode] = type == pygame.KEYDOWN
+ if type == pygame.KEYUP:
+ mod = self._keymods()
+ ukey = unichr(gtk.gdk.keyval_to_unicode(event.keyval))
+ if ukey == '\000':
+ ukey = ''
+ evt = pygame.event.Event(type, key=keycode, unicode=ukey, mod=mod)
+ self._post(evt)
+
+ return True
+
+ def _get_pressed(self):
+ return self.__keystate
+
+ def _get_mouse_pressed(self):
+ return self.__button_state
+
+ def _mousedown_cb(self, widget, event):
+ self.__button_state[event.button-1] = 1
+ return self._mouseevent(widget, event, pygame.MOUSEBUTTONDOWN)
+
+ def _mouseup_cb(self, widget, event):
+ self.__button_state[event.button-1] = 0
+ return self._mouseevent(widget, event, pygame.MOUSEBUTTONUP)
+
+ def _mouseevent(self, widget, event, type):
+ evt = pygame.event.Event(type, button=event.button, pos=(event.x, event.y))
+ self._post(evt)
+ return True
+
+ def _mousemove_cb(self, widget, event):
+ # From http://www.learningpython.com/2006/07/25/writing-a-custom-widget-using-pygtk/
+ # if this is a hint, then let's get all the necessary
+ # information, if not it's all we need.
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x = event.x
+ y = event.y
+ state = event.state
+
+ rel = (x - self.__mouse_pos[0], y - self.__mouse_pos[1])
+ self.__mouse_pos = (x, y)
+
+ self.__button_state = [
+ state & gtk.gdk.BUTTON1_MASK and 1 or 0,
+ state & gtk.gdk.BUTTON2_MASK and 1 or 0,
+ state & gtk.gdk.BUTTON3_MASK and 1 or 0,
+ ]
+
+ evt = pygame.event.Event(pygame.MOUSEMOTION,
+ pos=self.__mouse_pos, rel=rel, buttons=self.__button_state)
+ self._post(evt)
+ return True
+
+ def _tick_cb(self):
+ cur_time = pygame.time.get_ticks()
+ for key in self.__held:
+ delta = cur_time - self.__held_last_time[key]
+ self.__held_last_time[key] = cur_time
+
+ self.__held_time_left[key] -= delta
+ if self.__held_time_left[key] <= 0:
+ self.__held_time_left[key] = self.__repeat[1]
+ self._keyevent(None, _MockEvent(key), pygame.KEYDOWN)
+
+ return True
+
+ def _set_repeat(self, delay=None, interval=None):
+ if delay is not None and self.__repeat[0] is None:
+ self.__tick_id = gobject.timeout_add(10, self._tick_cb)
+ elif delay is None and self.__repeat[0] is not None:
+ gobject.source_remove(self.__tick_id)
+ self.__repeat = (delay, interval)
+
+ def _get_mouse_pos(self):
+ return self.__mouse_pos
+
+ def _post(self, evt):
+ try:
+ pygame.event.post(evt)
+ except pygame.error, e:
+ if str(e) == 'Event queue full':
+ print "Event queue full!"
+ pass
+ else:
+ raise e
diff --git a/utils.py b/utils.py
new file mode 100755
index 0000000..841af65
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,189 @@
+# utils.py
+import g,pygame,sys,os,random,copy,load_save
+
+#constants
+RED,BLUE,GREEN,BLACK,WHITE=(255,0,0),(0,0,255),(0,255,0),(0,0,0),(255,255,255)
+CYAN,ORANGE,CREAM,YELLOW=(0,255,255),(255,165,0),(255,255,192),(255,255,0)
+
+def exit():
+ save()
+ pygame.display.quit()
+ pygame.quit()
+ sys.exit()
+
+def save():
+ dir=''
+ dir=os.environ.get('SUGAR_ACTIVITY_ROOT')
+ if dir==None: dir=''
+ fname=os.path.join(dir,'data','spiro.dat')
+ f=open(fname, 'w')
+ load_save.save(f)
+ f.close
+
+def load():
+ dir=''
+ dir=os.environ.get('SUGAR_ACTIVITY_ROOT')
+ if dir==None: dir=''
+ fname=os.path.join(dir,'data','spiro.dat')
+ try:
+ f=open(fname, 'r')
+ except:
+ return None #****
+ try:
+ load_save.load(f)
+ except:
+ pass
+ f.close
+
+def version_display():
+ g.message=g.app+' '+g.ver
+ g.message+=' '+str(g.screen.get_width())+' x '+str(g.screen.get_height())
+ message(g.screen,g.font1,g.message)
+
+# loads an image (eg pic.png) from the data subdirectory
+# converts it for optimum display
+# resizes it using the image scaling factor, g.imgf
+# so it is the right size for the current screen resolution
+# all images are designed for 1200x900
+def load_image(file1,alpha=False,subdir=''): # eg subdir='glow'
+ data='data'
+ if subdir!='': data=os.path.join('data',subdir)
+ fname=os.path.join(data,file1)
+ try:
+ img=pygame.image.load(fname)
+ except:
+ print "Peter says: Can't find "+fname; exit()
+ if alpha:
+ img=img.convert_alpha()
+ else:
+ img=img.convert()
+ if abs(g.imgf-1.0)>.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: return False
+ if mx>(x+w): return False
+ if my<y: 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 x2<mx: return False
+ if y1>my: return False
+ if y2<my: return False
+ return True
+
+def mouse_in_rect(rect): # x,y,w,h
+ return mouse_in(rect[0],rect[1],rect[0]+rect[2],rect[1]+rect[3])
+
+def display_score():
+ if pygame.font:
+ text=g.font2.render(str(g.score),True,ORANGE,BLUE)
+ w=text.get_width(); h=text.get_height()
+ x=g.sx(5.7); y=g.sy(18.8); d=g.sy(.3)
+ pygame.draw.rect(g.screen,BLUE,(x-d-g.sy(.05),y-d,w+2*d,h+2*d))
+ g.screen.blit(text,(x,y))
+ centre_blit(g.screen,g.sparkle,(x-d+g.sy(.05),y+h/2-g.sy(.2)))
+
+def display_number(n,(cx,cy),font,colour=BLACK,bgd=None,outline_font=None):
+ if pygame.font:
+ if bgd==None:
+ text=font.render(str(n),True,colour)
+ else:
+ text=font.render(str(n),True,colour,bgd)
+ if outline_font<>None:
+ 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)
+
+
+