def setup(sk): # Load image originals fldr = resolvePath("img", __file__) sk.imgs = [ Image("{}/{}.png".format(fldr, f)) for f in ("target", "paper", "scissors") ] # Create button controls and add images to buttons w, h = sk.size x = w / 4 - 44 for img in sk.imgs: btn = Button((40, 40), 2).config(anchor=BOTTOM, pos=(x, h - 4)) btn += Image(img).config(pos=btn.center, height=32) sk += btn.bind(onclick) # Bind event handlers x += 44 # Initialize scores to zero font = {"font": Font.mono(), "fontSize": 40, "fontStyle": BOLD} sk["Score1"] = Text(0).config(color="red", anchor=TOPLEFT, pos=(4, 4), **font) sk["Score2"] = Text(0).config(color="blue", anchor=TOPRIGHT, pos=(w - 4, 4), **font) # Create status text sk["Status"] = Text("Make a choice!").config(pos=(0.75 * w, h - 24), font=Font.sans(), fontSize=32, color="red")
def onclick(btn, ev): "Event handler for button clicks" # Remove images from previous round sk = btn.sketch try: sk -= sk["Player1"], sk["Player2"] except: pass # Nothing to remove in first round! # Add images for current round p1, p2 = btn.layer, randint(0, 2) w, h = sk.size x, y, h = w / 4, h / 2, 0.6 * h sk["Player1"] = Image(sk.imgs[p1]).config(height=h, pos=(x, y)) sk["Player2"] = Image(sk.imgs[p2]).config(height=h, pos=(3 * x, y)) # Determine the winner and update scores/status if p1 == p2: win = "It's a draw!" elif p1 - p2 in (1, -2): win = "You win!" sk["Score1"] += 1 else: win = "You lose!" sk["Score2"] += 1 sk["Status"].config(data=win, layer=-1)
def setup(self): # Draw star field self.bg = img = Image(self.size, "black") img = img.image for i in range(150): img.set_at(randPixel(self.size), rgba(False)) # Load high scores try: with open(JSON) as f: self.highScores = json.load(f) except: self.highScores = [] # Load images Missile.original = Image(self.imgFldr + "/missile.png") Asteroid.original = Image(self.imgFldr + "/target.png") self.player = Ship(self.imgFldr + "/ship.png").config(wrap=BOTH) # Start the game self.playerName = None self.score = Score() self.collisions = Collisions(self) self.start()
def field(self): "Draw red and yellow goal boxes on green turf" w, h = self.size y = self.center[1] sz = boxSize(w, h) cv = Canvas((w, h), "#20b050") cv += Image(sz, "red").config(pos=(0, y), anchor=LEFT) cv += Image(sz, "yellow").config(pos=(w-1, y), anchor=RIGHT) return cv.snapshot()
def __init__(self, image, cols=1, rows=1, flip=0, padding=0): # Clone costumes images from existing list if type(image) in (list, tuple): tiles = [Image(s if type(s) is str else s.image) for s in image] # Slice spritesheet into individual costumes and make flipped copies else: tiles = Image(image).tiles(cols, rows, flip, padding) # Initialize self._costumes = self.costumeList = tiles self._size = tiles[0].size
def _joinLines(self, srfs): "Join the lines of text into a single surface" # Calculate total size wMax, hMax = 0, 0 n = len(srfs) for s in srfs: w, h = s.get_size() if w > wMax: wMax = w if h > hMax: hMax = h y = self.padding w = wMax + 2 * y h = n * hMax + (n - 1) * self.spacing + 2 * y # Blit lines to final image wt = self.weight dx = 2 * wt y += wt srf = Image((w + dx, h + dx), self.bg).image a = self.color.a for s in srfs: if a < 255: setAlpha(s, a) x = self.padding + wt if self.align != LEFT: dx = wMax - s.get_size()[0] x += dx if self.align == RIGHT else dx // 2 srf.blit(s, (x, y)) y += hMax + self.spacing if wt: drawBorder(srf, self.border, wt) return srf
def setup(self): try: img = self.pattern try: self.bg = img(self) except: self.bg = Image(img) except: self.bg = Image(self.size, "white") self.weight = 1 robo = Robot(["#ff5050", "#ffd428"]) self["Red"] = self.bindBrain(robo).config(width=64, pos=self.center, angle=270, bounce=BOTH) robo.gyro = robo.angle
def setup(sk): "Add all content to the sketch" # Add text to the sketch font = {"font": Font.mono(), "fontStyle": BOLD} sk["Score"] = Text(0).config(anchor=TOPLEFT, color="red", **font) text = "Pummel the Chimp, and Win $$$" sk += Text(text).config(pos=(sk.width - 1, 0), anchor=TOPRIGHT, **font).config(width=0.75 * sk.width) # Add fist folder = resolvePath("examples/data", pygame.__file__) + "/" img = loadImage(folder + "fist.bmp") sk += Image(img).config(pos=sk.center, anchor=TOP).bind(ondraw) # Add chimp sprite img = loadImage(folder + "chimp.bmp") sk["Chimp"] = Sprite(img).config(pos=(48, 48), vel=(10, 0), bounce=BOTH).bind(ondraw=chimpDraw) # Load audio files audio = "punch.wav", "whiff.wav" sk.sounds = [pygame.mixer.Sound(folder + f) for f in audio] # Bind click event handler; hide cursor sk.bind(onmousedown) sk.cursor = False
def render(self): "Render the vector as an arrow on a pygame.Surface" l = self.length() * self.canvas.unit if l < 2: return Image((1, 1), self.stroke).image shape = self.arrowShape if type(shape) is dict: if shape["fixed"]: shape = shape.copy() shape["width"] /= l shape["head"] /= l del shape["fixed"] a = Arrow(l, **shape).config(fill=self.fill, stroke=self.stroke, weight=self.weight) else: dx, dy = shape cv = Canvas((l, 2 * dy)) y = cv.center[1] cv += Line((0, y), (l, y)).config(stroke=self.stroke, weight=self.weight) cv += Line((l - dx, y - dy), (l, y)).config(stroke=self.stroke, weight=self.weight) cv += Line((l - dx, y + dy), (l, y)).config(stroke=self.stroke, weight=self.weight) a = cv.snapshot() return a.image
def __init__(self, size=(128, 16), color="grey", lower=0, upper=1): super().__init__(size) cfg = dict(anchor=BOTTOMLEFT, pos=(0, size[1] - 1)) if tall( *size) else dict(anchor=TOPLEFT) self += Image(bg=color).config(**cfg) self.lower = lower self.upper = upper self.value = lower
def _title(cv, title, font, folders): "Add graph or axis titles" if "text" in title: gr = Text(title["text"]).config(**font) else: # TODO: Pass image rather than text gr = Image(title["image"].format(**folders)) if gr: gr.setCanvas(cv).config(role="title", **title.get("config", {})) return gr
def buttonClick(gr, ev): "Event handler for buttons" path = ev.target.path # [..., button, button box, dialog, sketch] btn, dlg = path[-4], path[-2] print(btn, btn.selected) if btn.name == "Popup": btn.status = "normal" dlg["Cover"] = Image(dlg.size, "#ffffffc0").config(anchor=TOPLEFT) dlg += dlg.menu
def render(self): "Render the plot as a surface" srf = Image(self._size, self.bg).image if self._xgrid: self._drawGrid(srf, 0, self._xgrid) if self._ygrid: self._drawGrid(srf, 1, self._ygrid) if self._xaxis: self._drawAxis(srf, 0, *self._xaxis) if self._yaxis: self._drawAxis(srf, 1, *self._yaxis) for k in self._keys: self._series[k].draw(srf, self.pixelCoords) return srf
def setup(self): "Add random-color rectangles to the sketch to represent the disks" h = min(14, max(1, self.height // self.disks - 1)) self.height = max(self.height, self.disks * (h + 1)) width = lambda i: self.width * (0.07 + 0.24 * i / (self.disks - 1)) for i in range(self.disks): w = width(i) img = Image((2 * w, 2 * h), False) self += img.snapshot(weight=2).config(anchor=BOTTOM, size=(w, h)) self.setDiskPositions()
def recordButton(self, y): "Compose the record button" sz = 21, 21 btn = Button(sz, ["#ffffff00", "#ffc0c0"]).config(anchor=LEFT, pos=(12, y), weight=0).bind(onclick) img = Circle(76).config(fill="red", weight=6).snapshot(), Image( (19, 19)) btn += Sprite(img).config(pos=btn.center, height=19) return btn
def __init__(self, size=(128,16), knob="grey", lower=0, upper=1, steps=0): super().__init__(size) self.steps = steps if not isinstance(knob, Graphic): knob = Image(self._knobSize(), knob) self += knob.bind(ondrag=_knobDrag, onrelease=_knobRelease) self.knob = knob.config(_dragRel=None) if upper < lower: self._flip = True upper, lower = lower, upper else: self._flip = False self.lower = lower self.upper = upper self.val = lower
def __getitem__(self, n): "Return a frame as an Image instance, or a slice as a new Video instance" if type(n) is slice: r = range(n.start, n.stop, n.step) if n.step else range(n.start, n.stop) return self.clip(r) if n != self._current[0]: self._current = n, self._costumes[n].img img = self._current[1] srf = img.original if self.alpha and not hasAlpha(srf): img = Image(srf.convert_alpha()) self._current = n, img return img.config(size=self.size, angle=self.angle)
def textIcon(self, text, icon=None, padding=6): "Add text and icon to button" if type(text) is str: text = Text(text) if type(icon) is bool: icon = Image(self._yesNoImg(icon)) if icon: w = self._icon(icon, padding) x = (w + padding) / 2 else: x = w = 0 cx, cy = self.center if cx <= 0: self._size = (w + text.width + (3 if w else 2) * padding), self._size[1] cx = self.center[0] self += text.config(pos=(x + cx, cy)) return self
def setup(self): self.config(border="blue", weight=1, bg=self.field()) # Display the score attr = {"font":self.font, "fontSize":48} self += Text(0).config(pos=(8,8), anchor=TOPLEFT, color="red", **attr) self += Text(0).config(pos=(631,8), anchor=TOPRIGHT, color="yellow", **attr) self.score = list(self)[-2:] # Paint the back of the nets so the robots can see them w, h = self.size d = h / 8 r = 0.65 * boxSize(w, h)[1] h = (h - 1) / 2 self += Sprite(Image((2,2), "red")).config(pos=(-d, h), wrap=0) self += Sprite(Image((2,2), "yellow")).config(pos=(w+d, h), wrap=0) for s in self[-2:]: s.radiusFactor *= r / s.radius # Get a soccer ball self += SoccerBall().config(pos=self.center) # Start the simulation if hasattr(self, "brains"): self.start() else: self += Dialog(self).config(pos=self.center)
def _tick(param, marker=9, y=False, **kwargs): if type(marker) is int: marker = ((9, 1) if y else (1, 9), "black") label = type(marker) is str if not (label or isinstance(marker, Graphic)): marker = Image(*marker) s = list(Series._lattice(0, param) if y else Series._lattice(param, 0)) if label: isZero = (lambda x: _isZero(x, marker)) if kwargs.get("omitZero")\ else (lambda x: False) i = 1 if y else 0 text = list(marker.format(x[i]) for x in s) marker = [ Text("" if isZero(x) else x).config(**kwargs) for x in text ] return Series(s).config(marker=marker)
def setup(game): "Create Tic-Tac-Toe board with 100 pixel squares and 20 pixel margins" # Load costumes for X and O sprites, and logo img = Image(resolvePath("img/xo.png", __file__)).tiles(3) game.alien = Image.fromBytes(sc8prData("alien")).config(height=36) # Create and position sprites, one per square for s in range(9): pos = 70 + 100 * (s % 3), 70 + 100 * (s // 3) game += Sprite(img).bind(contains=Graphic.contains, onclick=clickSquare).config(pos=pos, width=100) # Draw the board and start game for pts in [((20,120), (320,120)), ((20,220), (320,220)), ((120,20), (120,320)), ((220,20), (220,320))]: game += Line(*pts) startGame(game)
def makeSlider(self, cv, dim, ch, sh, cw, other=False): "Create a vertical or horizontal scroll bar" w = min(self.sliderWidth, ch - 1, cw // 12) h = ch + 1 - (w if other and dim == 0 else 0) knob = round(ch * (h - 1) / sh) knob = Image((w, knob) if dim else (knob, w), self.knobColor) size = (w, h) if dim else (h, w) a = TOPRIGHT if dim else BOTTOMLEFT u = ch - sh - (w if other else 0) gr = Slider(size=size, knob=knob, upper=u).bind(onchange=self.sliderChange) gr.config(bg=self.sliderBg, anchor=a, weight=0, val=-cv._scroll[dim], dim=dim, _scrollAdjust=False) return gr
def grid(*args, cols=None, size=None, fit=True): n = len(args) if cols is None: cols = n rows = (n - 1) // cols + 1 args = [(a if isinstance(a, Graphic) else Image(a)) for a in args] w, h = size if size else args[0].size cv = Table(cols * [w], rows * [h]) r = c = 0 for a in args: cv += a.config(pos=cv.cell(c, r).center, anchor=CENTER) if fit: f = min(w / a.width, h / a.height) if f < 1: a.scale(f) c += 1 if c == cols: c = 0 r += 1 return cv
def quilt(sk): "Draw some colors on the floor in a quilt pattern" w, h = sk.size w = (w - 64) // 6 h = (h - 64) // 4 cv = Canvas(sk.size, "grey") c = [ "pink", "darkgreen", "mintcream", "gold", "white", "cyan", "yellow", "blue", "brown", "tan2", "royalblue", "steelblue", "violet", "orange", "skyblue", "black", "tomato", "seashell", "salmon", "turquoise", "red", "magenta", "purple", "green", ] shuffle(c) for i in range(4): for j in range(6): color = c[j + 6 * i] cv += Image( (w, h), color).config(pos=(32 + (j + 0.5) * w, 32 + (i + 0.5) * h)) return cv.snapshot()
def __init__(self, scale=10, size=50, step=5, unit=("cm", 2), **cfg): if "bg" not in cfg: cfg["bg"] = Image(bg="#e0e0f0a0") if "weight" not in cfg: cfg["weight"] = 1 coord = lambda x: (x + 1) * scale h = 3.5 * scale super().__init__((coord(size + 1), h)) self.config(**cfg) x = 0 cfg = dict(anchor=BOTTOM, font=MONO, fontStyle=BOLD, color="#000000a0") while x <= size: self += Text(x).config(pos=(coord(x), h - 1), **cfg) x += step if unit: self += Text(unit[0]).config(pos=(coord(unit[1]), h - 1), **cfg) x = 0 while x <= size: s = coord(x) self += Line((s, 0), (s, scale / (2 if x % step else 1))) x += 1 for t in self: if isinstance(t, Text): t.config(height=h / 2) self.bind(ondrag)
def _series(cv, series, font, folders): "Add markers, data labels, or bars" config = {} marker = series.get("marker", None) if marker is None: imgs = series["image"] if type(imgs) is str: imgs = [imgs] cfg = series.get("image_config", {}) marker = [Image(img.format(**folders)).config(**cfg) for img in imgs] if len(marker) == 1: marker = marker[0] elif type(marker) is str: config = font.copy() elif type(marker) is list: r = marker[0] marker = Circle(10 * r).config(**marker[1]).snapshot().config(height=2 * r) config.update(series.get("config", {})) data = series.get("data") sList = cv.series(data, marker, series.get("shift", (0, 0)), **config) cv.seriesList.append(sList) cv += sList for gr in sList: gr.role = "marker" return data
def loadImage(filename): "Load image file and change background to transparent" img = Image(filename) color = img.original.get_at((0, 0)) return ReplaceColor(color).apply(img)
def __init__(self): img = Image(resolvePath("img/ball.png", __file__)) SoccerBall.ballImage = img super().__init__(img) self.config(height=30, mass=1, drag=0.00025, bounce=BOTH)
def checkbox(imgs=None): "Return a check box Button" if imgs is None: imgs = Button._checkTiles() return Button(None, (Image(x) for x in imgs)).config(weight=0)
def triangle(): if Menu._tri is None: srf = Image((56, 64)).image pygame.draw.polygon(srf, (0, 0, 0), [(0, 8), (0, 56), (55, 32)]) Menu._tri = srf return Image(Menu._tri)