From 9d8c8fa4251081b43610ad0805d14cc26e4b4e19 Mon Sep 17 00:00:00 2001 From: Raymond Hogenson Date: Sun, 9 Oct 2016 23:26:42 -0400 Subject: Merge --- bridge.py | 1 + events-example3.py | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) mode change 100644 => 100755 bridge.py create mode 100755 events-example3.py diff --git a/bridge.py b/bridge.py old mode 100644 new mode 100755 index 70adb99..2018611 --- a/bridge.py +++ b/bridge.py @@ -1,3 +1,4 @@ +#!/usr/bin/python2 from fish_show import FishShow from sunrise import SunriseShow from constants import * diff --git a/events-example3.py b/events-example3.py new file mode 100755 index 0000000..d21877b --- /dev/null +++ b/events-example3.py @@ -0,0 +1,206 @@ +#!/usr/bin/python +# events-example3.py +# Demos timer, mouse, and keyboard events + +from tkinter import * +import math +import random + +class Vector(object): + """N-dimensional vector class.""" + def __init__(self, *components): + """Create a vector from its components.""" + self.components = components + + def __add__(self, other): + """Add two vectors.""" + return self.__class__( + *map(lambda xy: xy[0] + xy[1], zip(self.components, other.components)) + ) + + def __sub__(self, other): + """Subtract two vectors.""" + return self.__class__( + *map(lambda xy: xy[0] - xy[1], zip(self.components, other.components)) + ) + + def __mul__(self, other): + """Multiply a vector by a constant.""" + return self.__class__(*map(lambda x: x * other, self.components)) + + def __rmul__(self, other): + """Multiply a constant by a vector.""" + return self * other + + def __abs__(self): + """Return the 2-norm of the vector.""" + return math.sqrt(sum(map(lambda x: x * x, self.components))) + + def __truediv__(self, scalar): + """Return self * 1 / scalar.""" + return self * (1 / scalar) + + def __eq__(self, other): + return self.components == other.components + + +def init(data): + data.squareLeft = 50 + data.squareTop = 0 + data.squareFill = "red" + data.squareSize = 25 + data.circleCenters = [ ] + data.counter = 0 + data.headingRight = True + data.headingDown = True + data.isPaused = False + data.timerDelay = 50 + + data.speed = Vector(10, 0) + data.drag = -1 + + data.tailAcceleration = Vector(5, 0) + data.tailDuration = 2 + data.tailMoving = False + data.tailThreshold = 5 + data.tailMoveCount = 0 + +def mousePressed(event, data): + newCircleCenter = (event.x, event.y) + data.circleCenters.append(newCircleCenter) + +def keyPressed(event, data): + if (event.char == "d"): + if (len(data.circleCenters) > 0): + data.circleCenters.pop(0) + else: + print("No more circles to delete!") + elif (event.char == "p"): + data.isPaused = not data.isPaused + elif (event.char == "s"): + doStep(data) + if (event.keysym == "Left"): + moveLeft(data) + elif (event.keysym == "Right"): + moveRight(data) + +def moveLeft(data): + data.squareLeft -= 20 + +def moveRight(data): + data.squareLeft += 20 + +def moveUp(data): + data.squareTop -= 20 + +def moveDown(data): + data.squareTop += 20 + +def timerFired(data): + if (not data.isPaused): doStep(data) + +def fixDirection(data, theta=None): + if theta is None: + theta = random.random() * 2 * math.pi + costheta = math.cos(theta) + sintheta = math.sin(theta) + speedx = data.tailAcceleration.components[0] + speedy = data.tailAcceleration.components[1] + # From en.wikipedia.org/wiki/Rotation_matrix + data.tailAcceleration = Vector( + speedx * costheta - speedy * sintheta, + speedx * sintheta + speedy * costheta + ) + +def doStep(data): + data.counter += 1 + if random.random() < 1 / 50: + fixDirection(data) + #print(abs(data.tailAcceleration)) + data.speed += data.drag * data.speed / abs(data.speed) + if abs(data.speed) < data.tailThreshold: + data.tailMoving = True + if data.tailMoveCount > data.tailDuration: + data.tailMoveCount = 0 + data.tailMoving = False + if data.tailMoving: + data.speed += data.tailAcceleration + data.tailMoveCount += 1 + data.squareLeft += data.speed.components[0] + data.squareTop += data.speed.components[1] + if data.squareLeft + data.squareSize > data.width: + data.squareLeft = 0 + if data.squareLeft < 0: + data.squareLeft = data.width - data.squareSize + if data.squareTop < 0: + data.squareTop = data.height - data.squareSize + if data.squareTop + data.squareSize > data.height: + data.squareTop = 0 + +def redrawAll(canvas, data): + # draw the square + canvas.create_rectangle(data.squareLeft, + data.squareTop, + data.squareLeft + data.squareSize, + data.squareTop + data.squareSize, + fill=data.squareFill) + # draw the circles + for circleCenter in data.circleCenters: + (cx, cy) = circleCenter + r = 20 + canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill="cyan") + # draw the text + canvas.create_text(150,20,text="events-example3.py") + canvas.create_text(150,40,text="Mouse clicks create circles") + canvas.create_text(150,60,text="Pressing 'd' deletes circles") + canvas.create_text(150,80,text="Pressing 'p' pauses/unpauses timer") + canvas.create_text(150,100,text="Pressing 's' steps the timer once") + canvas.create_text(150,120,text="Left arrow moves square left") + canvas.create_text(150,140,text="Right arrow moves square right") + canvas.create_text(150,160,text="Timer changes color of square") + +#################################### +# use the run function as-is +#################################### + +def run(width=300, height=300): + def redrawAllWrapper(canvas, data): + canvas.delete(ALL) + redrawAll(canvas, data) + canvas.update() + + def mousePressedWrapper(event, canvas, data): + mousePressed(event, data) + redrawAllWrapper(canvas, data) + + def keyPressedWrapper(event, canvas, data): + keyPressed(event, data) + redrawAllWrapper(canvas, data) + + def timerFiredWrapper(canvas, data): + timerFired(data) + redrawAllWrapper(canvas, data) + # pause, then call timerFired again + canvas.after(data.timerDelay, timerFiredWrapper, canvas, data) + # Set up data and call init + class Struct(object): pass + data = Struct() + data.width = width + data.height = height + data.timerDelay = 100 # milliseconds + init(data) + # create the root and the canvas + root = Tk() + canvas = Canvas(root, width=data.width, height=data.height) + canvas.pack() + # set up events + root.bind("", lambda event: + mousePressedWrapper(event, canvas, data)) + root.bind("", lambda event: + keyPressedWrapper(event, canvas, data)) + timerFiredWrapper(canvas, data) + # and launch the app + root.mainloop() # blocks until window is closed + print("bye!") + +run(600, 1000) -- cgit v1.3.1 From ad2fbe28d4e345c9b100f47eef2da0b8f76ff9a5 Mon Sep 17 00:00:00 2001 From: liwencTaiwan Date: Fri, 14 Oct 2016 13:33:01 -0400 Subject: Add img-disable css and usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The “socket.on(enable/disable image)” haven’t been tested. --- webapp/app/static/carousel.css | 10 ++++++++-- webapp/app/templates/index.html | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/webapp/app/static/carousel.css b/webapp/app/static/carousel.css index 9ef5474..4e49305 100644 --- a/webapp/app/static/carousel.css +++ b/webapp/app/static/carousel.css @@ -93,6 +93,14 @@ body { letter-spacing: -1px; } +img.img-disable { + -webkit-filter: grayscale(100%); + -moz-filter: grayscale(100%); + -o-filter: grayscale(100%); + -ms-filter: grayscale(100%); + filter: grayscale(100%); + opacity: 0.5; +} /* RESPONSIVE CSS -------------------------------------------------- */ @@ -133,6 +141,4 @@ body { margin-top: 120px; } - - } diff --git a/webapp/app/templates/index.html b/webapp/app/templates/index.html index 3592985..4dadb7b 100644 --- a/webapp/app/templates/index.html +++ b/webapp/app/templates/index.html @@ -124,6 +124,23 @@ var c = new creature(msg.name, socket); c.render($('#creatures')); }); + + socket.on('enable image', function(msg) { + console.log('enable image'); + // to be tested + var name = msg.name; + var myImgElement = $("#" + name); + myImgElement.removeClass('img-disable'); + + }); + + socket.on('disable image', function(msg) { + console.log('disable image'); + // to be tested + var name = msg.name; + var myImgElement = $("#" + name); + myImgElement.addClass('img-disable'); + }); socket.on('disconnect', function() { console.log('disconnected'); @@ -134,6 +151,13 @@ function clickImg(element) { console.log(element.id); + + //-----Testing------------------ + //var name = element.id; + //var myImgElement = $("#" + name); + //myImgElement.addClass('img-disable'); + // ----------------------------- + var c = new creature(element.id, socket); c.click() } -- cgit v1.3.1 From b606a27d7ce7e91250c0c8795270bb1862e15e26 Mon Sep 17 00:00:00 2001 From: Raymond Hogenson Date: Sun, 16 Oct 2016 12:54:32 -0400 Subject: Create new sorts of fish to be displayed --- fish_show.py | 87 +--------------------- fish_types.py | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 84 deletions(-) create mode 100644 fish_types.py diff --git a/fish_show.py b/fish_show.py index 6677ddd..62a07c9 100644 --- a/fish_show.py +++ b/fish_show.py @@ -6,85 +6,7 @@ import constants from constants import * import math from show import Show - - - -class Fish(object): - """Object displayed on the bridge, probably a fish.""" - def __init__(self, x, y, width, height, color, step): - """Create fish with default parameters.""" - self.x = x - self.y = y - self.width = width - self.height = height - self.color = color - self.speed = step - self.step = step - - self.speed = Vector(0.1, 0) - self.drag = -0.09 - - self.tailAccelMag = 0.4 - self.tailAcceleration = Vector(self.tailAccelMag, 0) - self.tailDuration = 2 - self.tailMoving = False - self.tailThreshold = 0.7 - self.tailMoveCount = 0 - - def update(self): - """Swim gently to the other side of the bridge.""" - if self.x > constants.BRIDGE_WIDTH or self.x < -self.width: - return False - - self.speed += self.drag * self.speed - if abs(self.speed) < self.tailThreshold: - self.tailMoving = True - self.tailThreshold = rand_in_range(0.5, 1.4) - self.fix_direction() - if self.tailMoveCount > self.tailDuration: - self.tailMoveCount = 0 - self.tailMoving = False - if self.tailMoving: - self.speed += self.tailAcceleration - self.tailMoveCount += 1 - self.x += self.speed.components[0] - self.y += self.speed.components[1] - - return True - - def fix_direction(self): - min_theta = -0.32 - max_theta = 0.32 - if self.y < 0: - min_theta = 0 - if self.y > 1: - max_theta = 0 - - #theta = rand_in_range(min_theta, max_theta) - theta = random.gauss((max_theta+min_theta)/2, (max_theta - min_theta)/12) - self.tailAcceleration = Vector(self.tailAccelMag, 0).rot2d(theta) - - @classmethod - def by_type(cls, fish_type): - if (fish_type == 'jellyfish'): - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'dolphin': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'boat': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'dory': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'nemo': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'whale': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'stingray': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'eel': - return cls(0, 0.5, 23, 1.5, color.black, 1) - if fish_type == 'shark': - return cls(0, 0.5, 23, 1.5, color.black, 1) - +from fish_types import Fish class Light(object): @@ -112,7 +34,8 @@ class Light(object): new_color = new_background for fish in fishes: coverage = compute_coverage(fish, self.x, self.y) - new_color = coverage * fish.color + (1 - coverage) * new_color + fish_color = fish.color_at(self.x, self.y) + new_color = coverage * fish_color + (1 - coverage) * new_color self.light.setRGBRaw( *map(lambda x: clamp(0, x, 1), new_color.components) ) @@ -194,7 +117,3 @@ class FishShow(Show): if self.depth > self.MAX_DEPTH: self.stop() - - -def rand_in_range(low, high): - return random.random() * (high - low) + low diff --git a/fish_types.py b/fish_types.py new file mode 100644 index 0000000..63e082e --- /dev/null +++ b/fish_types.py @@ -0,0 +1,231 @@ +from __future__ import division +import color as C +import functools +import constants +import random +import math + +class Fish(object): + """Object displayed on the bridge, probably a fish. + + Must override color (or color_at), drag, width, height, tailThreshold, + tailDuration, tailAccelMag + """ + def __init__(self, x=None, y=None): + """Create fish with default parameters.""" + if x is not None: + self.x = x + elif not hasattr(self, 'x'): + self.x = 0 + if x is not None: + self.y = y + elif not hasattr(self, 'y'): + self.y = 0.5 + self.speed = C.Vector(0, 0) + self.tailAcceleration = C.Vector(self.tailAccelMag, 0) + self.tailMoving = False + self.tailMoveCount = 0 + + @classmethod + def by_type(cls, fish_type): + if (fish_type == 'jellyfish'): + return Jellyfish() + if fish_type == 'dolphin': + return Dolphin() + if fish_type == 'boat': + return Boat() + if fish_type == 'dory': + return Dory() + if fish_type == 'nemo': + return Nemo() + if fish_type == 'whale': + return Whale() + if fish_type == 'stingray': + return Stingray() + if fish_type == 'eel': + return Eel() + if fish_type == 'shark': + return Shark() + + def update(self): + """Swim gently to the other side of the bridge.""" + if self.x > constants.BRIDGE_WIDTH or self.x < -self.width: + return False + + self.speed += self.drag * self.speed + if abs(self.speed) < self.tailThreshold: + self.tailMoving = True + self.tailThreshold = rand_in_range(0.5, 1.4) + self.fix_direction() + if self.tailMoveCount > self.tailDuration: + self.tailMoveCount = 0 + self.tailMoving = False + if self.tailMoving: + self.speed += self.tailAcceleration + self.tailMoveCount += 1 + self.x += self.speed.components[0] + self.y += self.speed.components[1] + + return True + + def fix_direction(self): + min_theta = -0.32 + max_theta = 0.32 + if self.y < 0: + min_theta = 0 + if self.y > 1: + max_theta = 0 + + #theta = rand_in_range(min_theta, max_theta) + theta = random.gauss( + (max_theta+min_theta)/2, (max_theta - min_theta)/12 + ) + self.tailAcceleration = C.Vector(self.tailAccelMag, 0).rot2d(theta) + + def color_at(self, x, y): + """May be overridden to provide multicolored fish.""" + return self.color + + +class Jellyfish(Fish): + color = C.HSV(298/360, 89/100, 53/100).to_RGB() + drag = -0.01 + width = 15 + height = 1.5 + tailThreshold = 0.001 + tailDuration = 4 + tailAccelMag = 0.001 + + +class Dolphin(Fish): + color = C.HSV(18/360, 0/100, 40/100).to_RGB() + drag = -0.09 + width = 35 + height = 1.5 + tailThreshold = 0.7 + tailDuration = 2 + tailAccelMag = 0.8 + gravity = C.Vector(0, -0.01) + + direction_fixed = False + def update(self): + """Swim gently to the other side of the bridge.""" + if self.x > constants.BRIDGE_WIDTH or self.x < -self.width: + return False + + if not self.direction_fixed: + self.tailAcceleration = self.tailAcceleration.rot2d(math.pi / 32) + self.direction_fixed = True + + self.speed += self.drag * self.speed + self.gravity + if self.y <= 0.25: + self.tailMoving = True + if self.tailMoveCount > self.tailDuration: + self.tailMoveCount = 0 + self.tailMoving = False + if self.tailMoving: + self.speed += self.tailAcceleration + self.tailMoveCount += 1 + self.x += self.speed.components[0] + self.y += self.speed.components[1] + + return True + + +class Boat(Fish): + color = C.HSV(24/360, 45/100, 44/100).to_RGB() + drag = 0 + width = 23 + height = 1 + tailDuration = 1 + tailAccelMag = 0.25 + tailThreshold = tailAccelMag + y = 1 + + def fix_direction(self): + pass + + +class Dory(Fish): + # Need to try this on the bridge + color = C.HSV(235/360, 100/100, 88/100).to_RGB() + drag = -0.1 + width = 23 + height = 1.5 + tailThreshold = 0.7 + tailDuration = 2 + tailAccelMag = 0.4 + + +class Nemo(Fish): + color = C.HSV(31/360, 100/100, 50/100).to_RGB() + drag = -0.09 + width = 23 + height = 1.5 + tailThreshold = 0.7 + tailDuration = 2 + tailAccelMag = 0.4 + + +class Whale(Fish): + drag = -0.2 + width = 50 + height = 2 + tailThreshold = 0.7 + tailDuration = 3 + tailAccelMag = 0.4 + + white_x_min = 30 + white_x_width = 8 + white_y_min = 1 + white_y_height = 1 + + def color_at(self, x, y): + """Mostly copied from compute_coverage. + + The point here is to render that white part of the Orca. + """ + white_x_min = self.white_x_min + self.x + white_x_max = white_x_min + self.white_x_width + white_y_min = self.white_y_min + self.y + white_y_max = white_y_min + self.white_y_height + min_x = min(max(x, white_x_min), x + 1) + max_x = max(min(x + 1, white_x_max), x) + min_y = min(max(y, white_y_min), y + 1) + max_y = max(min(y + 1, white_y_max), y) + coverage = (max_x - min_x) * (max_y - min_y) + return C.white * coverage + + +class Stingray(Fish): + color = C.HSV(0/360, 0/100, 50/100).to_RGB() + drag = -0.09 + width = 15 + height = 2 + tailThreshold = 0.7 + tailDuration = 2 + tailAccelMag = 0.2 + + +class Eel(Fish): + color = C.HSV(109/360, 83/100, 35/100).to_RGB() + drag = -0.09 + width = 23 + height = 1.5 + tailThreshold = 0.7 + tailDuration = 2 + tailAccelMag = 0.4 + + +class Shark(Fish): + color = C.HSV(0/360, 0/100, 50/100).to_RGB() + drag = -0.2 + width = 50 + height = 2 + tailThreshold = 0.7 + tailDuration = 3 + tailAccelMag = 0.4 + + +def rand_in_range(low, high): + return random.random() * (high - low) + low -- cgit v1.3.1 From e717c90bbdc3089f64c943afb98f44df031cab18 Mon Sep 17 00:00:00 2001 From: Raymond Hogenson Date: Sun, 16 Oct 2016 14:35:05 -0400 Subject: Improve eel movement --- fish_show.py | 2 +- fish_types.py | 47 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/fish_show.py b/fish_show.py index 62a07c9..cb80d55 100644 --- a/fish_show.py +++ b/fish_show.py @@ -51,7 +51,7 @@ def compute_coverage(fish, x, y): min_y = min(max(y, fish.y), y + 1) max_y = max(min(y+1, fish.y + fish.height), y) coverage = (max_x - min_x) * (max_y - min_y) - return coverage * scale + return coverage * scale * fish.alpha_at(x, y) def pick_HSV(depth): diff --git a/fish_types.py b/fish_types.py index 63e082e..73b58c1 100644 --- a/fish_types.py +++ b/fish_types.py @@ -25,6 +25,8 @@ class Fish(object): self.tailAcceleration = C.Vector(self.tailAccelMag, 0) self.tailMoving = False self.tailMoveCount = 0 + if not hasattr(self, 'theta_scale'): + self.theta_scale = 12 @classmethod def by_type(cls, fish_type): @@ -71,14 +73,14 @@ class Fish(object): def fix_direction(self): min_theta = -0.32 max_theta = 0.32 - if self.y < 0: + if self.y + self.height < 0: min_theta = 0 - if self.y > 1: + if self.y > 2: max_theta = 0 #theta = rand_in_range(min_theta, max_theta) theta = random.gauss( - (max_theta+min_theta)/2, (max_theta - min_theta)/12 + (max_theta+min_theta)/2, (max_theta - min_theta)/self.theta_scale ) self.tailAcceleration = C.Vector(self.tailAccelMag, 0).rot2d(theta) @@ -86,6 +88,12 @@ class Fish(object): """May be overridden to provide multicolored fish.""" return self.color + def alpha_at(self, x, y): + """Return an additional scale amount for clear parts. + + This is overridden to have oddly shaped fish, such as the eel.""" + return 1 + class Jellyfish(Fish): color = C.HSV(298/360, 89/100, 53/100).to_RGB() @@ -174,6 +182,9 @@ class Whale(Fish): tailThreshold = 0.7 tailDuration = 3 tailAccelMag = 0.4 + theta_scale = 20 + + y = 0 white_x_min = 30 white_x_width = 8 @@ -210,11 +221,34 @@ class Stingray(Fish): class Eel(Fish): color = C.HSV(109/360, 83/100, 35/100).to_RGB() drag = -0.09 - width = 23 - height = 1.5 + width = 50 + height = 2 tailThreshold = 0.7 tailDuration = 2 - tailAccelMag = 0.4 + tailAccelMag = 0.1 + + front_offset = 0 + y = 0 + + def alpha_at(self, x, y): + rel_x = x - self.x + rel_y = y - self.y + eel_height = math.sin( + 2 * math.pi * (rel_x + self.front_offset) / self.width + ) / 2 + 0.5 + y_blend = abs(rel_y - eel_height) + if y_blend > 0.5: + return 0 + return (1 - y_blend) + + def update(self): + self.front_offset += abs(self.speed) + if self.front_offset > self.width: + self.front_offset = 0 + return super(Eel, self).update() + + def fix_direction(self): + pass class Shark(Fish): @@ -225,6 +259,7 @@ class Shark(Fish): tailThreshold = 0.7 tailDuration = 3 tailAccelMag = 0.4 + theta_scale = 20 def rand_in_range(low, high): -- cgit v1.3.1 From 7bb99edd9ac78bee36b6f748f3016a27ace9afce Mon Sep 17 00:00:00 2001 From: Raymond Hogenson Date: Sun, 16 Oct 2016 14:35:46 -0400 Subject: Add __unicode__ to Vector --- color.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/color.py b/color.py index c65252b..8f7f72c 100644 --- a/color.py +++ b/color.py @@ -50,6 +50,12 @@ class Vector(object): new_y = self.x * sintheta + self.y * costheta return self.__class__(new_x, new_y) + def __unicode__(self): + return '<{}, {}, {}>'.format(self.x, self.y, self.z) + + def __str__(self): + return unicode(self) + @property def components(self): -- cgit v1.3.1 From 0f54d73feea16124e92ff6baab78e3d3d3d97fa3 Mon Sep 17 00:00:00 2001 From: Raymond Hogenson Date: Sun, 16 Oct 2016 14:38:44 -0400 Subject: Use staticmethod instead of classmethod in by_type --- fish_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fish_types.py b/fish_types.py index 73b58c1..61cd36a 100644 --- a/fish_types.py +++ b/fish_types.py @@ -28,8 +28,8 @@ class Fish(object): if not hasattr(self, 'theta_scale'): self.theta_scale = 12 - @classmethod - def by_type(cls, fish_type): + @staticmethod + def by_type(fish_type): if (fish_type == 'jellyfish'): return Jellyfish() if fish_type == 'dolphin': -- cgit v1.3.1