From 9486dd411e22ffdf900dd5b51b72f4a8d3631f0f Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Sun, 23 Jun 2013 23:49:17 +0000 Subject: turtle-centric --- (limited to 'TurtleArt/taturtle.py') diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py index 7db72e6..992af95 100644 --- a/TurtleArt/taturtle.py +++ b/TurtleArt/taturtle.py @@ -26,11 +26,13 @@ import cairo from taconstants import (TURTLE_LAYER, DEFAULT_TURTLE_COLORS) from tasprite_factory import (SVG, svg_str_to_pixbuf) -from tacanvas import (wrap100, COLOR_TABLE) +from tacanvas import (wrap100, COLOR_TABLE, COLORDICT) from sprites import Sprite -from tautils import debug_output +from tautils import debug_output, data_to_string, round_int SHAPES = 36 +DEGTOR = pi / 180. +RTODEG = 180. / pi def generate_turtle_pixbufs(colors): @@ -109,8 +111,9 @@ class Turtles: class Turtle: - def __init__(self, turtles, key, turtle_colors=None): + def __init__(self, turtle_window, turtles, key, turtle_colors=None): """ The turtle is not a block, just a sprite with an orientation """ + self.tw = turtle_window self.x = 0.0 self.y = 0.0 self.hidden = False @@ -124,6 +127,8 @@ class Turtle: self.pen_gray = 100 self.pen_size = 5 self.pen_state = True + self.pen_fill = False + self.pen_poly_points = [] self.label_block = None self._prep_shapes(key, turtles, turtle_colors) @@ -175,7 +180,7 @@ class Turtle: if turtle_colors is not None: self.colors = turtle_colors[:] self.shapes = generate_turtle_pixbufs(self.colors) - self.set_heading(self.heading) + self.set_heading(self.heading, share=False) def set_shapes(self, shapes, i=0): """ Reskin the turtle """ @@ -218,9 +223,16 @@ class Turtle: self.shapes = generate_turtle_pixbufs(self.colors) self.custom_shapes = False - def set_heading(self, heading): + def set_heading(self, heading, share=True): """ Set the turtle heading (one shape per 360/SHAPES degrees) """ - self.heading = heading + try: + self.heading = heading + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.heading %= 360 + i = (int(self.heading + 5) % 360) / (360 / SHAPES) if not self.hidden and self.spr is not None: try: @@ -228,28 +240,142 @@ class Turtle: except IndexError: self.spr.set_shape(self.shapes[0]) - def set_color(self, color): + if self.tw.sharing() and share: + event = 'r|%s' % (data_to_string([self.tw.nick, + round_int(self.heading)])) + self.tw.send_event(event) + + def set_color(self, color=None, share=True): """ Set the pen color for this turtle. """ - self.pen_color = color + # Special case for color blocks + if color is not None and color in COLORDICT: + self.set_shade(COLORDICT[color][1], share) + self.set_gray(COLORDICT[color][2], share) + if COLORDICT[color][0] is not None: + self.set_color(COLORDICT[color][0], share) + color = COLORDICT[color][0] + else: + color = self.pen_color + + try: + self.pen_color = color + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + self.tw.canvas.set_fgcolor(shade=self.pen_shade, + gray=self.pen_gray, + color=self.pen_color) + + if self.tw.sharing() and share: + event = 'c|%s' % (data_to_string([self.tw.nick, + round_int(self.pen_color)])) + self.tw.send_event(event) - def set_gray(self, gray): + def set_gray(self, gray=None, share=True): """ Set the pen gray level for this turtle. """ - self.pen_gray = gray + if gray is not None: + try: + self.pen_gray = gray + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + if self.pen_gray < 0: + self.pen_gray = 0 + if self.pen_gray > 100: + self.pen_gray = 100 + + self.tw.canvas.set_fgcolor(shade=self.pen_shade, + gray=self.pen_gray, + color=self.pen_color) - def set_shade(self, shade): + if self.tw.sharing() and share: + event = 'g|%s' % (data_to_string([self.tw.nick, + round_int(self.pen_gray)])) + self.tw.send_event(event) + + def set_shade(self, shade=None, share=True): """ Set the pen shade for this turtle. """ - self.pen_shade = shade + if shade is not None: + try: + self.pen_shade = shade + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + self.tw.canvas.set_fgcolor(shade=self.pen_shade, + gray=self.pen_gray, + color=self.pen_color) - def set_pen_size(self, pen_size): + if self.tw.sharing() and share: + event = 's|%s' % (data_to_string([self.tw.nick, + round_int(self.pen_shade)])) + self.tw.send_event(event) + + def set_pen_size(self, pen_size=None, share=True): """ Set the pen size for this turtle. """ - self.pen_size = pen_size + if pen_size is not None: + try: + self.pen_size = max(0, pen_size) + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + self.tw.canvas.set_pen_size(self.pen_size) - def set_pen_state(self, pen_state): + if self.tw.sharing() and share: + event = 'w|%s' % (data_to_string([self.tw.nick, + round_int(self.pen_size)])) + self.tw.send_event(event) + + def set_pen_state(self, pen_state=None, share=True): """ Set the pen state (down==True) for this turtle. """ - self.pen_state = pen_state + if pen_state is not None: + self.pen_state = pen_state + + self.tw.canvas.set_pen(self.pen_state) + + if self.tw.sharing() and share: + event = 'p|%s' % (data_to_string([self.tw.nick, + self._pen_state])) + self.tw.send_event(event) + + def set_fill(self, state=False): + self.pen_fill = state + if not self.pen_fill: + self.poly_points = [] + + def set_poly_points(self, poly_points=None): + if poly_points is not None: + self.poly_points = poly_points[:] + + def start_fill(self): + self.pen_fill = True + self.poly_points = [] + + def stop_fill(self, share=True): + self.pen_fill = False + if len(self.poly_points) == 0: + return + + self.tw.canvas.fill_polygon(self.poly_points) + + if self.tw.sharing() and share: + shared_poly_points = [] + for p in self.poly_points: + shared_poly_points.append( + (self.tw.canvas.screen_to_turtle_coordinates(p[0], p[1]))) + event = 'F|%s' % (data_to_string([self.tw.nick, + shared_poly_points])) + self.tw.send_event(event) + self.poly_points = [] def hide(self): - """ Hide the turtle. """ if self.spr is not None: self.spr.hide() if self.label_block is not None: @@ -257,7 +383,6 @@ class Turtle: self.hidden = True def show(self): - """ Show the turtle. """ if self.spr is not None: self.spr.set_layer(TURTLE_LAYER) self.hidden = False @@ -266,8 +391,18 @@ class Turtle: if self.label_block is not None: self.label_block.spr.set_layer(TURTLE_LAYER + 1) + def move_turtle(self, pos=None): + if pos is None: + x, y = self.tw.canvas.get_xy() + else: + x, y = self.tw.canvas.turtle_to_screen_coordinates(pos[0], pos[1]) + if self.tw.interactive_mode: + self.move((self.tw.canvas.cx + x - self.spr.rect.width / 2., + self.tw.canvas.cy + y - self.spr.rect.height / 2.)) + else: + self.move((self.tw.canvas.cx + x, self.tw.canvas.cy + y)) + def move(self, pos): - """ Move the turtle. """ self.x, self.y = pos[0], pos[1] if not self.hidden and self.spr is not None: self.spr.move((int(pos[0]), int(pos[1]))) @@ -277,33 +412,183 @@ class Turtle: return(self.x, self.y) def get_name(self): - ''' return turtle name (key) ''' return self.name def get_xy(self): - """ Return the turtle's x, y coordinates. """ return(self.x, self.y) def get_heading(self): - """ Return the turtle's heading. """ return(self.heading) def get_color(self): - """ Return the turtle's color. """ return(self.pen_color) def get_gray(self): - """ Return the turtle's gray level. """ return(self.pen_gray) def get_shade(self): - """ Return the turtle's shade. """ return(self.pen_shade) def get_pen_size(self): - """ Return the turtle's pen size. """ return(self.pen_size) def get_pen_state(self): - """ Return the turtle's pen state. """ return(self.pen_state) + + def get_fill(self): + return(self.pen_fill) + + def get_poly_points(self): + return(self.poly_points) + + def right(self, degrees, share=True): + ''' Rotate turtle clockwise ''' + try: + self.heading += degrees + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.heading %= 360 + + if self.tw.sharing() and share: + event = 'r|%s' % (data_to_string([self.tw.nick, + round_int(self.heading)])) + self.tw.send_event(event) + + def forward(self, distance, share=True): + scaled_distance = distance * self.tw.coord_scale + + self.tw.canvas.set_rgb(self.tw.canvas.fgrgb[0] / 255., + self.tw.canvas.fgrgb[1] / 255., + self.tw.canvas.fgrgb[2] / 255.) + + oldx, oldy = self.tw.canvas.get_xy() + try: + xcor = oldx + scaled_distance * sin(self.heading * DEGTOR) + ycor = oldy + scaled_distance * cos(self.heading * DEGTOR) + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + self.tw.canvas.set_xy(xcor, ycor) + if self.pen_state: + self.tw.canvas.draw_line(oldx, oldy, xcor, ycor) + if self.pen_fill: + if self.poly_points == []: + x, y = self.tw.canvas.turtle_to_screen_coordinates(oldx, oldy) + self.poly_points.append(('move', x, y)) + x, y = self.tw.canvas.turtle_to_screen_coordinates(xcor, ycor) + self.poly_points.append(('line', x, y)) + + self.move_turtle((xcor, ycor)) + + if self.tw.sharing() and share: + event = 'f|%s' % (data_to_string([self.tw.nick, + int(distance)])) + self.tw.send_event(event) + + def set_xy(self, x, y, share=True, pendown=True): + oldx, oldy = self.tw.canvas.get_xy() + try: + xcor = x * self.tw.coord_scale + ycor = y * self.tw.coord_scale + self.tw.canvas.set_xy(x, y) + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + if self.pen_state and pendown: + self.tw.canvas.set_rgb(self.tw.canvas.fgrgb[0] / 255., + self.tw.canvas.fgrgb[1] / 255., + self.tw.canvas.fgrgb[2] / 255.) + self.tw.canvas.draw_line(oldx, oldy, xcor, ycor) + if self.pen_fill: + if self.poly_points == []: + x, y = self.tw.canvas.turtle_to_screen_coordinates(oldx, oldy) + self.poly_points.append(('move', x, y)) + x, y = self.tw.canvas.turtle_to_screen_coordinates(xcor, ycor) + self.poly_points.append(('line', x, y)) + + self.move_turtle((xcor, ycor)) + + if self.tw.sharing() and share: + event = 'x|%s' % (data_to_string([self.tw.nick, + [round_int(x), round_int(y)]])) + self.tw.send_event(event) + + def arc(self, a, r, share=True): + ''' Draw an arc ''' + if self.pen_state: + self.tw.canvas.set_rgb(self.tw.canvas.fgrgb[0] / 255., + self.tw.canvas.fgrgb[1] / 255., + self.tw.canvas.fgrgb[2] / 255.) + try: + if a < 0: + self.larc(-a, r) + else: + self.rarc(a, r) + except (TypeError, ValueError): + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + xcor, ycor = self.tw.canvas.get_xy() + self.move_turtle((xcor, ycor)) + + if self.tw.sharing() and share: + event = 'a|%s' % (data_to_string([self.tw.nick, + [round_int(a), round_int(r)]])) + self.tw.send_event(event) + + def rarc(self, a, r): + ''' draw a clockwise arc ''' + r *= self.tw.coord_scale + if r < 0: + r = -r + a = -a + xcor, ycor = self.tw.canvas.get_xy() + cx = xcor + r * cos(self.heading * DEGTOR) + cy = ycor - r * sin(self.heading * DEGTOR) + if self.pen_state: + x, y = self.tw.canvas.turtle_to_screen_coordinates(cx, cy) + self.tw.canvas.rarc(x, y, r, a, self.heading) + + if self.pen_fill: + x, y = self.tw.canvas.turtle_to_screen_coordinates(x, y) + if self.poly_points == []: + self.poly_points.append(('move', x, y)) + self.poly_points.append(('rarc', x, y, r, + (self.heading - 180) * DEGTOR, + (self.heading - 180 + a) * DEGTOR)) + + self.right(a, False) + self.tw.canvas.set_xy(cx - r * cos(self.heading * DEGTOR), + cy + r * sin(self.heading * DEGTOR)) + + def larc(self, a, r): + ''' draw a counter-clockwise arc ''' + r *= self.tw.coord_scale + if r < 0: + r = -r + a = -a + xcor, ycor = self.tw.canvas.get_xy() + cx = xcor - r * cos(self.heading * DEGTOR) + cy = ycor + r * sin(self.heading * DEGTOR) + if self.pen_state: + x, y = self.tw.canvas.turtle_to_screen_coordinates(cx, cy) + self.tw.canvas.larc(x, y, r, a, self.heading) + + if self.pen_fill: + x, y = self.tw.canvas.turtle_to_screen_coordinates(x, y) + if self.poly_points == []: + self.poly_points.append(('move', x, y)) + self.poly_points.append(('larc', x, y, r, + (self.heading) * DEGTOR, + (self.heading - a) * DEGTOR)) + + self.right(-a, False) + self.tw.canvas.set_xy(cx + r * cos(self.heading * DEGTOR), + cy - r * sin(self.heading * DEGTOR)) -- cgit v0.9.1