From 8ee1d89d6fa222fbd0f7ed0ab75b2a65103a350c Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 27 Jan 2010 21:28:29 +0000 Subject: multi-turtle support --- diff --git a/constants.py b/constants.py index 49d36d0..2ccb98d 100644 --- a/constants.py +++ b/constants.py @@ -59,7 +59,7 @@ PALETTES = [['forward', 'back', 'clean', 'left', 'right', 'show', 'storeinbox', 'start'], ['kbinput', 'push', 'printheap', 'keyboard', 'pop', 'clearheap', 'myfunc', 'nop', 'leftpos', 'toppos', 'width', 'rightpos', - 'bottompos', 'height', 'print'], + 'bottompos', 'height', 'turtle', 'print'], ['hideblocks'], ['restore']] @@ -90,7 +90,7 @@ BASIC_STYLE = ['clean', 'penup', 'pendown', 'stack1', 'stack2', 'vspace', BASIC_STYLE_1ARG = ['forward', 'back', 'left', 'right', 'setheading', 'show', 'setscale', 'setpensize', 'setcolor', 'setshade', 'print', 'settextsize', 'settextcolor', 'print', 'wait', 'storeinbox1', - 'storeinbox2', 'wait', 'stack', 'push', 'nop'] + 'storeinbox2', 'wait', 'stack', 'push', 'nop', 'turtle'] BASIC_STYLE_2ARG = ['arc', 'setxy', 'fillscreen', 'storeinbox', 'myfunc'] BOX_STYLE = ['number', 'xcor', 'ycor', 'heading', 'pensize', 'color', 'shade', 'textcolor', 'textsize', 'box1', 'box2', 'string', 'leftpos', 'scale', @@ -148,7 +148,7 @@ BLOCK_NAMES = {'clean':[_('clean')], 'forward':[_('forward')], 'scale':[_('scale')], 'keyboard':[_('keyboard')], 'push':[_('push')], 'pop':[_('pop')], 'kbinput':[_('query keyboard')], 'myfunc':[_('python'), _('code'), _('value')], 'nop':[' '], - 'printheap':[_('show heap')], + 'printheap':[_('show heap')], 'turtle':[_('turtle')], 'clearheap':[_('empty heap')], 'restore':[_('restore')]} # @@ -180,7 +180,7 @@ PRIMITIVES = {'clean':'clean', 'forward':'forward', 'back':'back', 'arc':'arc', 'stopstack':'stopstack', 'hspace':'nop', 'vspace':'nop', 'start':'start', 'hat1':'nop1', 'stack1':'stack1', 'hat2':'nop2', 'stack2':'stack2', - 'hat':'nop3', 'action':'stack', + 'hat':'nop3', 'action':'stack', 'turtle':'turtle', 'storeinbox1':'storeinbox1', 'box1':'box1', 'storeinbox2':'storeinbox2', 'box2':'box2', 'storeinbox':'storeinbox', 'box':'box', @@ -196,7 +196,7 @@ PRIMITIVES = {'clean':'clean', 'forward':'forward', 'back':'back', 'arc':'arc', DEFAULTS = {'forward':[100], 'back':[100], 'left':[90], 'right':[90], 'arc':[90,100], 'setheading':[0], 'setscale':[33], 'show':[_('text')], - 'setpensize':[5], 'settextsize':[32], 'setcolor':[0], + 'setpensize':[5], 'settextsize':[32], 'setcolor':[0], 'turtle':[1], 'setshade':[50], 'fillscreen':[60,80], 'number':[100], 'random':[0,100], 'wait':[1], 'repeat':[4], 'setxy':[0,0], 'storeinbox':[_('my box'),100], 'box':[_('my box')], diff --git a/sprite_factory.py b/sprite_factory.py index 20ce42f..b4d0b36 100755 --- a/sprite_factory.py +++ b/sprite_factory.py @@ -245,12 +245,12 @@ class SVG: self._width, self._height = 60, 60 return self._header() + svg - def palette(self, width, height): - self._width, self._height = width, height + def palette(self, width1, width2, height): + self._width, self._height = width2, height self._fill, self._stroke = "#282828", "none" - svg = self._rect(width, 55, 0, 0) + svg = self._rect(width2, 55, 0, 0) self._fill, self._stroke = "#FFD000", "none" - svg += self._rect(width, height-55, 0, 55) + svg += self._rect(width1, height-55, 0, 55) svg += self._footer() return self._header() + svg diff --git a/tacanvas.py b/tacanvas.py index 3f680d9..bf81876 100644 --- a/tacanvas.py +++ b/tacanvas.py @@ -21,8 +21,6 @@ import gtk from math import sin,cos,pi -class taTurtle: pass - from tasetup import load_image import sprites import taturtle @@ -30,6 +28,16 @@ import pango from constants import * +def wrap100(n): + n = int(n) + n %= 200 + if n>99: n=199-n + return n + +def calc_shade(c,s): + if s<0: return int(c*(1+s*.8)) + return int(c+(65536-c)*s*.9) + colors = {} DEGTOR = 2*pi/360 @@ -55,262 +63,266 @@ color_table = ( 0xFF00FF,0xFF00E6,0xFF00CC,0xFF00B3,0xFF0099, 0xFF0080,0xFF0066,0xFF004D,0xFF0033,0xFF001A) -def tNew(tw,w,h): - t = taTurtle() - t.tw, t.width, t.height = tw, w, h - t.canvas = sprites.Sprite(tw.sprite_list, 0, 0, - gtk.gdk.Pixmap(tw.area,w,h,-1)) - (t.cx,t.cy) = t.canvas.get_xy() - t.canvas.type = 'canvas' - t.canvas.set_layer(CANVAS_LAYER) - # t.shapelist = [] - t.t = taturtle.Turtle(tw.turtle_list, tw.sprite_list, - ["#800000", "#A00000", "#D00000", "#800000"]) - t.spr = t.t.spr - t.spr.type = 'turtle' - t.spr.set_layer(TURTLE_LAYER) - t.gc = t.canvas.image.new_gc() - t.shade = 0 - clearscreen(t) - return t - -def clearscreen(t): - t.xcor, t.ycor, t.heading = 0,0,0 - rect = gtk.gdk.Rectangle(0,0,t.width,t.height) - t.gc.set_foreground(t.tw.bgcolor) - t.canvas.image.draw_rectangle(t.gc, True, *rect) - invalt(t,0,0,t.width,t.height) - setpensize(t,5) - setcolor(t,0) - settextcolor(t,70) - settextsize(t,32) - setshade(t,50) - t.pendown = True - move_turtle(t) - turn_turtle(t) - return None - -def forward(t, n): - n *= t.tw.coord_scale - t.gc.set_foreground(t.tw.fgcolor) - oldx, oldy = t.xcor, t.ycor - try: - t.xcor += n*sin(t.heading*DEGTOR) - t.ycor += n*cos(t.heading*DEGTOR) - except: - pass - if t.pendown: - draw_line(t,oldx,oldy,t.xcor,t.ycor) - move_turtle(t) - return None - -def seth(t,n): - try: - t.heading=n - except: - pass - t.heading%=360 - turn_turtle(t) - return None - -def right(t,n): - try: - t.heading+=n - except: - pass - t.heading%=360 - turn_turtle(t) - return None - -def arc(t,a,r): - t.gc.set_foreground(t.tw.fgcolor) - r *= t.tw.coord_scale - try: - if a<0: larc(t,-a,r) - else: rarc(t,a,r) - except: - pass - move_turtle(t) - turn_turtle(t) - -def rarc(t,a,r): - if r<0: r=-r; a=-a - cx = t.xcor+r*cos(t.heading*DEGTOR) - cy = t.ycor-r*sin(t.heading*DEGTOR) - x,y,w,h=t.width/2+int(cx-r),t.height/2-int(cy+r),int(2*r),int(2*r) - if t.pendown: - t.canvas.image.draw_arc(t.gc,False,x,y,w,h, \ - int(180-t.heading-a)*64,int(a)*64) - invalt(t,x-t.pensize*t.tw.coord_scale/2-3,y-t.pensize*t.tw.coord_scale/2-3,\ - w+t.pensize*t.tw.coord_scale+6,h+t.pensize*t.tw.coord_scale+6) - right(t,a) - t.xcor=cx-r*cos(t.heading*DEGTOR) - t.ycor=cy+r*sin(t.heading*DEGTOR) - -def larc(t,a,r): - if r<0: r=-r; a=-a - cx = t.xcor-r*cos(t.heading*DEGTOR) - cy = t.ycor+r*sin(t.heading*DEGTOR) - x,y,w,h=t.width/2+int(cx-r),t.height/2-int(cy+r),int(2*r),int(2*r) - if t.pendown: - t.canvas.image.draw_arc(t.gc,False,x,y,w,h,int(360-t.heading)*64, \ - int(a)*64) - invalt(t,x-t.pensize*t.tw.coord_scale/2-3,y-t.pensize*t.tw.coord_scale/2-3,\ - w+t.pensize*t.tw.coord_scale+6,h+t.pensize*t.tw.coord_scale+6) - right(t,-a) - t.xcor=cx+r*cos(t.heading*DEGTOR) - t.ycor=cy-r*sin(t.heading*DEGTOR) - -def setxy(t,x,y): - x *= t.tw.coord_scale - y *= t.tw.coord_scale - try: - t.xcor,t.ycor = x,y - except: - pass - move_turtle(t) - -def setpensize(t,ps): - try: - if ps<0: - ps=0; - t.pensize = ps - except: - pass - t.gc.set_line_attributes(int(t.pensize*t.tw.coord_scale), \ - gtk.gdk.LINE_SOLID, \ - gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_MITER) - return None - -def setcolor(t,c): - try: - t.color = c - t.tcolor = c - except: - pass - set_fgcolor(t) - set_textcolor(t) - return None - -def settextcolor(t,c): - try: - t.tcolor = c - except: - pass - set_textcolor(t) - return None - -def settextsize(t,c): - try: - t.tw.textsize = c - except: - pass - return None - -def setshade(t,s): - try: - t.shade = s - except: - pass - set_fgcolor(t) - set_textcolor(t) - return None - -def fillscreen(t,c,s): - oldc, olds = t.color,t.shade - try: - setcolor(t,c); setshade(t,s) - rect = gtk.gdk.Rectangle(0,0,t.width,t.height) - t.gc.set_foreground(t.tw.fgcolor) - t.canvas.image.draw_rectangle(t.gc, True, *rect) - invalt(t,0,0,t.width,t.height) - setcolor(t,oldc); setshade(t,olds) - except: - pass - return None - -def set_fgcolor(t): - sh = (wrap100(t.shade)-50)/50.0 - rgb = color_table[wrap100(t.color)] - r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 - r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) - t.tw.rgb = [r>>8,g>>8,b>>8] - t.tw.fgcolor = t.tw.cm.alloc_color(r,g,b) - -def set_textcolor(t): - sh = (wrap100(t.shade)-50)/50.0 - rgb = color_table[wrap100(t.tcolor)] - r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 - r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) - t.tw.textcolor = t.tw.cm.alloc_color(r,g,b) - -def wrap100(n): - n = int(n) - n %= 200 - if n>99: n=199-n - return n - -def calc_shade(c,s): - if s<0: return int(c*(1+s*.8)) - return int(c+(65536-c)*s*.9) - -def setpen(t,bool): - t.pendown = bool - -def draw_pixbuf(t,pixbuf,a,b,x,y,w,h): - w *= t.tw.coord_scale - h *= t.tw.coord_scale - t.canvas.image.draw_pixbuf(t.gc, pixbuf, a, b, x, y) - invalt(t,x,y,w,h) - -def draw_text(t, label, x, y, size, w): - w *= t.tw.coord_scale - t.gc.set_foreground(t.tw.textcolor) - fd = pango.FontDescription('Sans') - try: - fd.set_size(int(size*t.tw.coord_scale)*pango.SCALE) - except: - pass - if type(label) == str or type(label) == unicode: - pl = t.tw.window.create_pango_layout(label.replace("\0"," ")) - elif type(label) == float or type(label) == int: - pl = t.tw.window.create_pango_layout(str(label)) - else: - print "draw text: Type Error: %s" % (type(label)) - pl = t.tw.window.create_pango_layout(str(label)) - pl.set_font_description(fd) - pl.set_width(int(w)*pango.SCALE) - t.canvas.image.draw_layout(t.gc,int(x),int(y),pl) - w,h = pl.get_pixel_size() - invalt(t,x,y,w,h) - -def draw_line(t,x1,y1,x2,y2): - x1,y1 = t.width/2+int(x1), t.height/2-int(y1) - x2,y2 = t.width/2+int(x2), t.height/2-int(y2) - if x1>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 + r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) + self.tw.rgb = [r>>8,g>>8,b>>8] + self.tw.fgcolor = self.tw.cm.alloc_color(r,g,b) + + def set_textcolor(self): + sh = (wrap100(self.shade)-50)/50.0 + rgb = color_table[wrap100(self.tcolor)] + r,g,b = (rgb>>8)&0xff00,rgb&0xff00,(rgb<<8)&0xff00 + r,g,b = calc_shade(r,sh),calc_shade(g,sh),calc_shade(b,sh) + self.tw.textcolor = self.tw.cm.alloc_color(r,g,b) + + def setpen(self,bool): + self.pendown = bool + + def draw_pixbuf(self,pixbuf,a,b,x,y,w,h): + w *= self.tw.coord_scale + h *= self.tw.coord_scale + self.canvas.image.draw_pixbuf(self.gc, pixbuf, a, b, x, y) + self.invalt(x,y,w,h) + + def draw_text(self, label, x, y, size, w): + w *= self.tw.coord_scale + self.gc.set_foreground(self.tw.textcolor) + fd = pango.FontDescription('Sans') + try: + fd.set_size(int(size*self.tw.coord_scale)*pango.SCALE) + except: + pass + if type(label) == str or type(label) == unicode: + pl = self.tw.window.create_pango_layout(label.replace("\0"," ")) + elif type(label) == float or type(label) == int: + pl = self.tw.window.create_pango_layout(str(label)) + else: + print "draw text: Type Error: %s" % (type(label)) + pl = self.tw.window.create_pango_layout(str(label)) + pl.set_font_description(fd) + pl.set_width(int(w)*pango.SCALE) + self.canvas.image.draw_layout(self.gc,int(x),int(y),pl) + w,h = pl.get_pixel_size() + self.invalt(x,y,w,h) + + def draw_line(self,x1,y1,x2,y2): + x1,y1 = self.width/2+int(x1), self.height/2-int(y1) + x2,y2 = self.width/2+int(x2), self.height/2-int(y2) + if x1 self.tw.turtle_list.turtle_count()-1: + # if it is a new turtle, put it in the center of the screen + self.tw.turtle = self.tw.turtle_list.get_turtle(i, True) + self.xcor = 0 + self.ycor = 0 + self.heading = 0 + self.tw.turtle.move_turtle() + self.tw.turtle.rotate(self.heading) + self.tw.turtle = self.tw.turtle_list.get_turtle(i, True) + tx, ty = self.tw.turtle.get_xy() + self.xcor = tx+30-self.width/2 + self.ycor = self.height/2-ty-30 + self.heading = self.tw.turtle.get_heading() + self.tw.turtle_list.show_all() diff --git a/talogo.py b/talogo.py index 56f1996..ec34570 100644 --- a/talogo.py +++ b/talogo.py @@ -170,7 +170,7 @@ def readline(lc, line): return res def setup_cmd(lc, str): - lc.tw.turtle.spr.set_layer(HIDE_LAYER) + lc.tw.turtle.hide() lc.procstop=False list = readline(lc, str) lc.step = start_eval(lc, list) @@ -188,11 +188,11 @@ def evline(lc, list): lc.arglist = None while lc.iline: if lc.tw.step_time > 0: - lc.tw.turtle.spr.set_layer(TURTLE_LAYER) + lc.tw.turtle.show() endtime = millis()+an_int(lc,lc.tw.step_time)*100 while millis() len(self.list)-1: - return(None) + def get_turtle(self, i, append=False): + print "get turtle %d (%d)" % (i, len(self.list)) + if i < 0: + print "IndexError: Turtles %d" % (i) + return self.list[0] + elif i > len(self.list)-1: + if append is False: + print "IndexError: Turtles %d" % (i) + return self.list[0] + else: + print "Adding %d turtles" % (i-len(self.list)+1) + for t in range(i-len(self.list)+1): + Turtle(self) + return(self.list[i]) else: return(self.list[i]) - def length_of_list(self): + def turtle_count(self): return(len(self.list)) def append_to_list(self, turtle): self.list.append(turtle) def remove_from_list(self, turtle): - if block in self.list: + if turtle in self.list: self.list.remove(turtle) + def show_all(self): + for turtle in self.list: + turtle.show() + # # sprite utilities # @@ -61,23 +77,44 @@ class Turtles: # class Turtle: # The turtle is not a block, just a sprite with an orientation - def __init__(self, turtle_list, sprite_list, + def __init__(self, turtle_list, colors=["#008000", "#00A000", "#D0D000", "#808000"], scale=1.0): + self.x = 0 + self.y = 0 self.shapes = [] self.type = 'turtle' + self.heading = 0 _svg = SVG() _svg.set_scale(scale) - self.spr = sprites.Sprite(sprite_list, 0, 0, + self.spr = sprites.Sprite(turtle_list.sprite_list, self.x, self.y, svg_str_to_pixbuf(_svg.turtle(colors))) turtle_list.append_to_list(self) for i in range(36): _svg.set_orientation(i*10) self.shapes.append(svg_str_to_pixbuf(_svg.turtle(colors))) - def rotate(self, orientation): + def rotate(self, heading): + self.heading = heading + i = (int(self.heading+5)%360)/10 try: - self.spr.set_shape(self.shapes[orientation]) + self.spr.set_shape(self.shapes[i]) except IndexError: self.spr.set_shape(self.shapes[0]) - print "Turtle shape IndexError %d" % orientation + print "Turtle shape IndexError %f -> %d" % (heading, i) + + def hide(self): + self.spr.set_layer(HIDE_LAYER) + + def show(self): + self.spr.set_layer(TURTLE_LAYER) + + def move(self, pos): + self.x, self.y = pos[0], pos[1] + self.spr.move(pos) + + def get_xy(self): + return(self.x, self.y) + + def get_heading(self): + return(self.heading) diff --git a/tawindow.py b/tawindow.py index aff0a83..0abe047 100644 --- a/tawindow.py +++ b/tawindow.py @@ -143,9 +143,11 @@ class TurtleArtWindow(): self.drag_group = None self.block_list = block.Blocks() self.sprite_list = sprites.Sprites(self.window, self.area, self.gc) - self.turtle_list = taturtle.Turtles() + self.turtle_list = taturtle.Turtles(self.sprite_list) + self.turtle = taturtle.Turtle(self.turtle_list) self.selected_turtle = None - self.turtle = tNew(self,self.width,self.height) + self.canvas = TurtleGraphics(self, self.width, self.height) + self.lc = lcNew(self) """ @@ -222,7 +224,7 @@ class TurtleArtWindow(): blk.spr.set_layer(BLOCK_LAYER) self.show_palette() self.hide = False - self.turtle.canvas.inval() + self.canvas.canvas.inval() """ hideshow_palette @@ -480,7 +482,7 @@ class TurtleArtWindow(): dx, dy = mdx, mdy else: dx, dy = x-sx-30, y-sy-30 - seth(self.turtle, int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10) + self.canvas.seth(int(dragx+atan2(dy,dx)/DEGTOR+5)/10*10) # If we are hoving, show popup help. elif self.drag_group is None: self._show_popup(x, y) @@ -837,12 +839,12 @@ class TurtleArtWindow(): print "processing remote button release: %d, %d" % (x, y) # We may have been moving the turtle if self.selected_turtle is not None: - (tx, ty) = self.turtle.spr.get_xy() - self.turtle.xcor = tx-self.turtle.cx- \ - self.turtle.canvas._width/2+30 - self.turtle.ycor = self.turtle.canvas._height/2-ty+ \ - self.turtle.cy-30 - move_turtle(self.turtle) + (tx, ty) = self.canvas.spr.get_xy() + self.canvas.xcor = tx-self.canvas.cx- \ + self.canvas.canvas._width/2+30 + self.canvas.ycor = self.canvas.canvas._height/2-ty+ \ + self.canvas.cy-30 + self.canvas.move_turtle() display_coordinates(self) self.selected_turtle = None return @@ -983,7 +985,8 @@ class TurtleArtWindow(): Is x,y over the trash can? """ def _in_the_trash(self, x, y): - if self.selected_palette == TRASH and self.palette_spr.hit((x,y)): + if self.selected_palette == TRASH and \ + self.palette_sprs[TRASH].hit((x,y)): return True return False @@ -1072,10 +1075,10 @@ class TurtleArtWindow(): Turtle pressed """ def _turtle_pressed(self, x, y): - (tx, ty) = self.turtle.spr.get_xy() + (tx, ty) = self.canvas.spr.get_xy() dx, dy = x-tx-30, y-ty-30 if dx*dx+dy*dy > 200: - self.dragpos = ('turn', self.turtle.heading-atan2(dy,dx)/DEGTOR, 0) + self.dragpos = ('turn', self.canvas.heading-atan2(dy,dx)/DEGTOR, 0) else: self.dragpos = ('move', x-tx, y-ty) @@ -1149,12 +1152,12 @@ class TurtleArtWindow(): """ def _jog_turtle(self, dx, dy): if dx == -1 and dy == -1: - self.turtle.xcor = 0 - self.turtle.ycor = 0 + self.canvas.xcor = 0 + self.canvas.ycor = 0 else: - self.turtle.xcor += dx - self.turtle.ycor += dy - move_turtle(self.turtle) + self.canvas.xcor += dx + self.canvas.ycor += dy + self.canvas.move_turtle() display_coordinates(self) self.selected_turtle = None -- cgit v0.9.1