Esempio n. 1
0
def collide_shape_details(left, right, details=True):
    sleft = shapeOf(left)
    sright = shapeOf(right)
    if type(sleft) is Circle and type(sright) is Circle:
        v = delta(sleft.pos, sright.pos)
        if hypot(*v) < sleft.radius + sright.radius:
            if details:
                c = sright.containsPoint(sleft.pos) or sleft.containsPoint(sright.pos)
                return delta(v, mag=(-1 if c else 1))
            else: return True
    return False
Esempio n. 2
0
 def _bounce(self, cv):
     "Bounce sprite from the edge of its canvas"
     vx, vy = self.vel
     w, h = cv.size
     b = self.bounce
     update = 0
     if self.bounceType == 0:
         x, y = delta(self.rect.center, cv.rect.topleft)
         r = self.radius
         if b & HORIZONTAL and (x < r and vx < 0 or x > w - r and vx > 0):
             self.vel = -vx, vy
             update += HORIZONTAL
         if b & VERTICAL and (y < r and vy < 0 or y > h - r and vy > 0):
             self.vel = vx, -vy
             update += VERTICAL
     else:
         r = self.rect
         if b & HORIZONTAL and (r.left < 0 and vx < 0
                                or r.right >= w and vx > 0):
             self.vel = -vx, vy
             update += HORIZONTAL
         if b & VERTICAL and (r.top < 0 and vy < 0
                              or r.bottom >= h and vy > 0):
             self.vel = vx, -vy
             update += VERTICAL
     return update
Esempio n. 3
0
    def ondraw(self):
        "Update robot sprite each frame"

        if not self.active: raise InactiveError()

        # Target wheel speed...
        sk = self.sketch
        v = self.maxSpeed * sk.width
        v1, v2 = self._motors
        v1 *= v
        v2 *= v

        # Angular speed and turning radius...
        w = (v1 - v2) / (2 * self.radius)
        self.spin = w / DEG
        if w:
            R = (v1 + v2) / (2 * w)
            v = w * R
        else:
            v = v1

        # Acceleration...
        v = vec2d(v, self.angle)
        a = delta(v, self.vel)
        if hypot(*a) > 0.05:
            self.acc = delta(a, mag=0.05)
        else:
            self.vel = v
            self.acc = 0, 0

        # Adjust wheel speed...
        p = self.power
        self.costumeTime = 0 if p == 0 else round(36 / (1 + 5 * p))

        # Update position and angle...
        super().ondraw()

        # Update sensors if requested...
        if self._updateSensors:
            try:
                self._checkDown()
                self._checkFront()
                self._drawLEDs()
                self._updateSensors = False
            except:
                logError()
        self._startup = False
Esempio n. 4
0
    def ondraw(self):
        "Update robot sprite each frame"

        if not self.active: raise InactiveError()

        # Target wheel speed...
        sk = self.sketch
        v = self.maxSpeed * sk.width
        v1, v2 = self._motors
        v1 *= v
        v2 *= v

        # Angular speed and turning radius...
        w = (v1 - v2) / (2 * self.radius)
        self.spin = w / DEG
        if w:
            R = (v1 + v2) / (2 * w)
            v = w * R
        else: v = v1

        # Acceleration...
        v = vec2d(v, self.angle)
        a = delta(v, self.vel)
        if hypot(*a) > 0.05:
            self.acc = delta(a, mag=0.05)
        else:
            self.vel = v
            self.acc = 0, 0

        # Adjust wheel speed...
        p = self.power
        self.costumeTime = 0 if p == 0 else round(36 / (1 + 5 * p))

        # Update position and angle...
        super().ondraw()

        # Update sensors if requested...
        if self._updateSensors:
            try:
                self._checkDown()
                self._checkFront()
                self._drawLEDs()
                self._updateSensors = False
            except: logError()
        self._startup = False
Esempio n. 5
0
    def ondraw(self):

        # Calculate electric force
        sk = self.sketch
        dr = delta(self.pos, sk["blue"].pos)
        r = hypot(*dr) / sk.scale / 100
        F = delta(dr, mag=8.99e-3 * sk.q1 * sk.q2 / (r * r))

        # Add electric plus gravitational forces
        F = F[0], F[1] + sk.mass * 9.81e-3

        # Tangential acceleration
        s = sk["string"]
        u = s.u
        t = 1 / sk.frameRate
        F = (F[0] * u[1] - F[1] * u[0]) / (sk.mass / 1000) * (sk.scale /
                                                              100) / t**2
        ax, ay = F * u[1], -F * u[0]

        # Kinematics
        v1x, v1y = tuple(0.95 * v for v in self.vel)
        v2x = v1x + ax * t
        v2y = v1y + ay * t
        self.vel = v2x, v2y
        x, y = self.pos
        x += (v1x + v2x) * t / 2
        y += (v1y + v2y) * t / 2
        x, y = delta((x, y), s.pos, 20 * sk.scale)
        self.pos = s.pos[0] + x, s.pos[1] + y
        s.__init__(s.pos, self.pos)

        # Protractor
        if s.u[1] > 0:
            a = round(2 * degrees(asin(s.u[0]))) / 2
            a = "Angle = {:.1f}°".format(abs(a))
        else:
            a = "Angle > 90°"
        sk["angle"].config(data=a)
Esempio n. 6
0
def _knobDrag(knob, ev):
    "Handle drag events on the slider's 'knob' object"
    slider = knob.canvas
    if knob._dragRel is None:
        knob._dragRel = delta(knob.rect.center, ev.pos)
    if slider._lastButton in slider.allowButton:
        x = pygame.event.Event(pygame.USEREVENT, pos=sigma(ev.pos, knob._dragRel))
        v = slider._val
        slider.val = slider._eventValue(x)
        x = slider.val
        setattr(ev, "target", slider)
        if x != v:
            setattr(ev, "method", DRAG)
            slider.bubble("onchange", ev)
Esempio n. 7
0
def dragDrop(gr, ev):
    "Drag a Graphic, possibly into a different canvas"
    gr.hoverable = False
    pos = sigma(gr.pos, ev.rel)
    drop = False
    try:
        cv = [gr for gr in gr.sketch.objectAt(ev.pos).path if getattr(gr, "allowDrop", False)][0]
        if cv is not gr.canvas:
            pos = sigma(pos, delta(gr.canvas.rect.topleft, cv.rect.topleft))
            drop = True
            gr.setCanvas(cv)
    except: pass
    gr.config(pos=pos, hoverable=True)
    if drop: gr.bubble("ondrop", ev)
Esempio n. 8
0
    def ondraw(self):

        # Calculate electric force
        sk = self.sketch
        dr = delta(self.pos, sk["blue"].pos)
        r = hypot(*dr) / sk.scale / 100
        F = delta(dr, mag = 8.99e-3 * sk.q1 * sk.q2 / (r * r))

        # Add electric plus gravitational forces 
        F = F[0], F[1] + sk.mass * 9.81e-3

        # Tangential acceleration
        s = sk["string"]
        u = s.u
        t = 1 / sk.frameRate
        F = (F[0] * u[1] - F[1] * u[0]) / (sk.mass / 1000) * (sk.scale / 100) / t ** 2
        ax, ay = F * u[1], -F * u[0]

        # Kinematics
        v1x, v1y = tuple(0.95 * v for v in self.vel)
        v2x = v1x + ax * t
        v2y = v1y + ay * t
        self.vel = v2x, v2y
        x, y = self.pos
        x += (v1x + v2x) * t / 2
        y += (v1y + v2y) * t / 2
        x, y = delta((x,y), s.pos, 20 * sk.scale)
        self.pos = s.pos[0] + x, s.pos[1] + y
        s.__init__(s.pos, self.pos)

        # Protractor
        if s.u[1] > 0:
            a = round(2 * degrees(asin(s.u[0]))) / 2
            a = "Angle = {:.1f}°".format(abs(a))
        else: a = "Angle > 90°"
        sk["angle"].config(data=a)
Esempio n. 9
0
 def intersect(self, other):
     "Find the intersection(s) of two circles as list of points"
     R = self.radius
     r = other.radius
     d = dist(self.pos, other.pos)
     if d > r + R or d == 0 or d < abs(r - R): return []
     r2 = r * r
     x = (d*d + r2 - R*R) / (2*d)
     ux, uy = delta(self.pos, other.pos, 1)
     x0, y0 = other.pos
     x0 += x * ux
     y0 += x * uy
     if x < r:
         y = sqrt(r2 - x*x)
         return [(x0 - y * uy, y0 + y * ux), (x0 + y * uy, y0 - y * ux)]
     else: return [(x0, y0)]
Esempio n. 10
0
    def __init__(self, ship):
        "Fire a new missile from the ship"
        super().__init__(self.original)

        # Initial position of missile
        u = vec2d(1.3 * ship.radius, ship.angle)
        pos = ship.pos[0] + u[0], ship.pos[1] + u[1]

        # Initial velocity of missile
        u = delta(u, mag=ship.sketch.height / 135)
        vel = ship.vel[0] + u[0], ship.vel[1] + u[1]

        self.config(width=ship.width / 4,
                    pos=pos,
                    vel=vel,
                    spin=ship.spin,
                    angle=ship.angle)
Esempio n. 11
0
    def _checkFront(self):
        "Update the front color sensor"

        # Sensor info
        sw = self.sensorWidth
        res = 0.5 * self.sensorResolution
        pos = delta(self.pos, vec2d(-self.radius, self.angle))

        # Distance from sensor to edge of sketch
        obj = prox = None
        sk = self.sketch
        if sk.weight:
            prox = _distToWall(pos, self.angle, self.sensorWidth, *sk.size)
            if prox: obj = sk

        # Find closest object within "sensor cone"
        for gr in self.sensorObjects(sk):
            if gr is not self and gr.avgColor and hasattr(gr, "rect"):
                r = gr.radius
                view = subtend(pos, gr.rect.center, r,
                               None if prox is None else prox + r)
                if view:
                    # Object may be closer than the current closest object
                    sep, direct, half = view
                    if not res or half > res:
                        # Object size meets sensor resolution threshold
                        beta = abs(angleDifference(self.angle, direct)) - sw
                        if beta < half or sep < r:
                            # Object is in sensor cone
                            pr = sep - r
                            if beta > 0:
                                # CLOSEST point is NOT in sensor cone
                                dr = r + sep * (cos(half * DEG) - 1)
                                pr += dr * (beta / half)**2
                            if prox is None or pr < prox:
                                # Object is closest (so far)
                                prox = pr
                                obj = gr

        # Save data
        self.closestObject = obj
        c = rgba(sk.border if obj is sk else obj.avgColor if obj else (0, 0,
                                                                       0))
        self.sensorFront = noise(divAlpha(c), self.sensorNoise, 255)
        self.proximity = None if prox is None else max(0, round(prox))
Esempio n. 12
0
    def _checkFront(self):
        "Update the front color sensor"

        # Sensor info
        sw = self.sensorWidth
        res = 0.5 * self.sensorResolution
        pos = delta(self.pos, vec2d(-self.radius, self.angle))
    
        # Distance from sensor to edge of sketch
        obj = prox = None
        sk = self.sketch
        if sk.weight:
            prox = _distToWall(pos, self.angle, self.sensorWidth, *sk.size)
            if prox: obj = sk

        # Find closest object within "sensor cone"
        for gr in self.sensorObjects(sk):
            if gr is not self and gr.avgColor and hasattr(gr, "rect"):
                r = gr.radius
                view = subtend(pos, gr.rect.center, r, None if prox is None else prox + r)
                if view:
                    # Object may be closer than the current closest object
                    sep, direct, half = view
                    if not res or half > res:
                        # Object size meets sensor resolution threshold
                        beta = abs(angleDifference(self.angle, direct)) - sw
                        if beta < half or sep < r:
                            # Object is in sensor cone
                            pr = sep - r
                            if beta > 0:
                                # CLOSEST point is NOT in sensor cone
                                dr = r + sep * (cos(half * DEG) - 1)
                                pr += dr * (beta / half) ** 2
                            if prox is None or pr < prox:
                                # Object is closest (so far)
                                prox = pr
                                obj = gr

        # Save data
        self.closestObject = obj
        c = rgba(sk.border if obj is sk else obj.avgColor if obj else (0,0,0))
        self.sensorFront = noise(divAlpha(c), self.sensorNoise, 255)
        self.proximity = None if prox is None else max(0, round(prox))
Esempio n. 13
0
 def _bounce(self, cv):
     "Bounce sprite from the edge of its canvas"
     vx, vy = self.vel
     w, h = cv.size
     b = self.bounce
     update = 0
     if self.bounceType == 0:
         x, y = delta(self.rect.center, cv.rect.topleft)
         r = self.radius
         if b & HORIZONTAL and (x < r and vx < 0 or x > w-r and vx > 0):
             self.vel = -vx, vy
             update += HORIZONTAL
         if b & VERTICAL and (y < r and vy < 0 or y > h-r and vy > 0):
             self.vel = vx, -vy
             update += VERTICAL
     else:
         r = self.rect
         if b & HORIZONTAL and (r.left < 0 and vx < 0 or r.right >= w and vx > 0):
             self.vel = -vx, vy
             update += HORIZONTAL
         if b & VERTICAL and (r.top < 0 and vy < 0 or r.bottom >= h and vy > 0):
             self.vel = vx, -vy
             update += VERTICAL  
     return update
Esempio n. 14
0
 def between(tail, tip, width=0.1, head=0.1, flatness=2):
     r, a = polar2d(*delta(tip, tail))
     return Arrow(r, width, head, flatness).config(pos=tip, angle=a)
Esempio n. 15
0
 def toward(self, pos, mag=None):
     "Return a vector directed toward the specified position"
     if mag is None: mag = hypot(*self.vel)
     return delta(pos, self.pos, mag)
Esempio n. 16
0
 def px(self, *pt):
     return delta(self._px(pt), self._scroll)
Esempio n. 17
0
 def contains(self, pos):
     "Determine if the point is within the shape, accounting for canvas offset"
     cv = self.canvas
     cvPos = delta(pos, cv.rect.topleft) if cv else pos
     return self.containsPoint(cvPos)
Esempio n. 18
0
 def between(tail, tip, width=0.1, head=0.1, flatness=2):
     r, a = polar2d(*delta(tip, tail))
     return ArrowSprite(r, width, head, flatness).config(pos=tip, angle=a)
Esempio n. 19
0
 def contains(self, pos):
     "Determine if the point is within the shape, accounting for canvas offset"
     cv = self.canvas
     cvPos = delta(pos, cv.rect.topleft) if cv else pos
     return self.containsPoint(cvPos)
Esempio n. 20
0
 def toward(self, pos, mag=None):
     "Return a vector directed toward the specified position"
     if mag is None: mag = hypot(*self.vel)
     return delta(pos, self.pos, mag)