# These donuts are meant to contrast in size and their # movement emphasizes the roomy new 200 x 200 canvas. # The user can interact with the donuts by placing # the mouse within them and they will hover toward # that point. If a donut is clicked, it slowly turns # to crumbs. import math def sqr(x): return x*x def mod(num, den): return (num-int(num/den)*den) objectTag = 123 pointTag = 234 pixelTag = 345 bitmapTag = 456 sailorTag = 567 def makeObject(newTag): data = [] data.append(objectTag) data.append(newTag) return data def checkObject(object): if object[0] != objectTag: print "error: not an object" def getObjectTag(object): checkObject(object) return object[1] def makePoint(x, y): data = [] data.append(makeObject(pointTag)) data.append(x) data.append(y) return data def checkPoint(p): if getObjectTag(p[0]) != pointTag: print "error: not a point" def getPointX(p): checkPoint(p) return p[1] def getPointY(p): checkPoint(p) return p[2] def makePixel(color): data = [] data.append(makeObject(pixelTag)) data.append(color) return data def checkPixel(pix): if getObjectTag(pix[0]) != pixelTag: print "error: not a pixel" def getPixelColor(pix): checkPixel(pix) return pix[1] def makeBitmap(width, height, backColor): bm = [] bm.append(makeObject(bitmapTag)) bm.append(int(width)) bm.append(int(height)) for y in range(0, int(height)): for x in range(0, int(width)): bm.append(makePixel(backColor)) return bm def checkBitmap(bm): if getObjectTag(bm[0]) != bitmapTag: print "error: not a bitmap" def getBitmapWidth(bm): checkBitmap(bm) return bm[1] def getBitmapHeight(bm): checkBitmap(bm) return bm[2] def getBitmapPixel(bm, p): checkBitmap(bm) return bm[3+int(getPointY(p))*getBitmapWidth(bm)+int(getPointX(p))] def setBitmapPixel(bm, p, pix): checkBitmap(bm) bm[3+(int(getPointY(p))*getBitmapWidth(bm))+int(getPointX(p))] = pix def drawBitmapOnBitmap(destBm, p, srcBm): for y in range(0, getBitmapWidth(srcBm)): for x in range(0, getBitmapHeight(srcBm)): setBitmapPixel(destBm, makePoint(x+getPointX(p), y+getPointY(p)), getBitmapPixel(srcBm, makePixel(x, y))) def drawPixel(pix, destP): g.setPixel(int(getPointX(destP)), int(getPointY(destP)), int(getPixelColor(pix))) def drawBitmap(bm, destP): for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): drawPixelField(getBitmapPixel(bm, makePoint(x, y)), makePoint(x+getPointX(destP), y+getPointY(destP))) def drawBitmapSprite(bm, destP, transKey): for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): pix = getBitmapPixel(bm, makePoint(x, y)) if getPixelColor(pix) != transKey: drawPixel(pix, makePoint(x+getPointX(destP), y+getPointY(destP))) def drawPixelField(pix, p1, p2): g.field(int(getPointX(p1)), int(getPointY(p1)), int(getPointX(p2)), int(getPointY(p2)), int(getPixelColor(pix))) def drawBitmapScaledBig(bm, destP, horizScale, vertScale): for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): drawPixelField(getBitmapPixel(bm, makePoint(x, y)), makePoint((x*horizScale)+getPointX(destP), (y*vertScale)+getPointY(destP)), makePoint((x*horizScale)+getPointX(destP)+horizScale, (y*vertScale)+getPointY(destP)+vertScale)) def drawBitmapScaledSmall(bm, destP, horizScale, vertScale): for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): drawPixelField(getBitmapPixel(bm, makePoint(x, y)), makePoint((x*horizScale)+getPointX(destP), (y*vertScale)+getPointY(destP)), makePoint((x*horizScale)+getPointX(destP)+horizScale, (y*vertScale)+getPointY(destP)+vertScale)) def drawBitmapScaled(bm, destP, horizScale, vertScale): if horizScale+vertScale > 2: drawBitmapScaledBig(bm, destP, horizScale, vertScale) else: drawBitmapScaledSmall(bm, destP, horizScale, vertScale) def drawBitmapSpriteScaledSmall(bm, destP, transKey, horizScale, vertScale): xi = -1 yi = -1 oxi = xi - 1 oyi = xi - 1 for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): pix = getBitmapPixel(bm, makePoint(x, y)) if getPixelColor(pix) != transKey: xi = x * horizScale yi = y * vertScale if oxi != xi or oyi != yi: drawPixel(getBitmapPixel(bm, makePoint(x, y)), makePoint(xi+getPointX(destP), yi+getPointY(destP))) oxi = xi*horizScale oyi = yi*vertScale def drawBitmapSpriteScaledBig(bm, destP, transKey, horizScale, vertScale): for y in range(0, getBitmapHeight(bm)): for x in range(0, getBitmapWidth(bm)): pix = getBitmapPixel(bm, makePoint(x, y)) if getPixelColor(pix) != transKey: drawPixelField(getBitmapPixel(bm, makePoint(x, y)), makePoint((x*horizScale)+getPointX(destP), (y*vertScale)+getPointY(destP)), makePoint((x*horizScale)+getPointX(destP)+horizScale, (y*vertScale)+getPointY(destP)+vertScale)) def drawBitmapSpriteScaled(bm, destP, transKey, horizScale, vertScale): if horizScale+vertScale > 2: drawBitmapSpriteScaledBig(bm, destP, transKey, horizScale, vertScale) else: drawBitmapSpriteScaledSmall(bm, destP, transKey, horizScale, vertScale) def drawBitmapWallSprite(bm, destP1, h1, destP2, h2, transKey): p1x = getPointX(destP1) p1y = getPointY(destP1) p2x = getPointX(destP2) p2y = getPointY(destP2) w = p2x - p1x + 1 hd = h2 - h1 y1d = p2y - p1y bmw = getBitmapWidth(bm) bmh = getBitmapHeight(bm) for x in range(int(p1x), int(p2x)+1): xoff = x - p1x xy1 = p1y+xoff*y1d/w xh = h1+xoff*hd/w xi = xoff*bmw/w for y in range(int(xy1), int(xy1+xh)): yi = (y-xy1)*bmh/xh drawPixel(getBitmapPixel(bm, makePoint(xi, yi)), makePoint(x, y)) def drawBitmapLevelSprite(bm, destP1, w1, destP2, w2, transKey): p1x = getPointX(destP1) p1y = getPointY(destP1) p2x = getPointX(destP2) p2y = getPointY(destP2) h = p2y - p1y wd = w2 - w1 x1d = p2x - p1x bmw = getBitmapWidth(bm) bmh = getBitmapHeight(bm) for y in range(int(p1y), int(p2y)): yoff = y - p1y yx1 = p1x+yoff*x1d/h yw = w1+yoff*wd/h+3 yi = yoff*bmh/h for x in range(int(yx1), int(yx1+yw)): xi = (x-yx1)*bmw/(yw+1) drawPixel(getBitmapPixel(bm, makePoint(xi, yi)), makePoint(x, y)) def drawBitmapFlatSprite(bm, p1, p2, transKey): p1x = getPointX(p1) p1y = getPointY(p1) p2x = getPointX(p2) p2y = getPointY(p2) w = p2x - p1x + 1 h = p2y - p1y + 1 bmw = getBitmapWidth(bm) bmh = getBitmapHeight(bm) horizScale = 1.0*w/bmw vertScale = 1.0*h/bmh drawBitmapSpriteScaled(bm, p1, -1, horizScale, vertScale) def renderSurface(bm, num): w = getBitmapWidth(bm) h = getBitmapHeight(bm) sqrRad = sqr((h+w)/4.0) / (num+1.0) minSqrRad = sqr((h+w)/8.0) / (num+1.0) avgRad = (sqrRad+minSqrRad)/2.0 for y in range(0, h): for x in range(0, w): sqrDist = sqr(1.0*x-(w-1.0)/2.0) + sqr(1.0*y-(h-1.0)/2.0) if sqrDist <= sqrRad and sqrDist >= minSqrRad: color = 2.0 * abs(100.0*(sqrDist-avgRad)/(sqrRad-minSqrRad)) setBitmapPixel(bm, makePoint(x,y), makePixel(color)) else: setBitmapPixel(bm, makePoint(x,y), makePixel(-1)) def makeSailor(width, height, bmNum, pos, vel, scale, sVel): data = [] data.append(makeObject(sailorTag)) data.append(bmNum) data.append([]) for a in range(0, bmNum): data[2].append(makeBitmap(width, height, -1)) renderSurface(data[2][a], a) data.append(pos) data.append(vel) data.append(scale) data.append(sVel) return data def checkSailor(s): if getObjectTag(s[0]) != sailorTag: print "error: not a sailor" def getSailorBmNum(s): checkSailor(s) return s[1] def getSailorBitmap(s, num): checkSailor(s) bmNum = getSailorBmNum(s) if num < bmNum and num >= 0: return s[2][num] else: print "error: bmNum out of range" def getSailorPos(s): checkSailor(s) return s[3] def getSailorVel(s): checkSailor(s) return s[4] def getSailorScale(s): checkSailor(s) return s[5] def getSailorSVel(s): checkSailor(s) return s[6] def setSailorBitmap(s, num, bm): checkSailor(s) bmNum = getSailorBmNum(s) if num < bmNum and num >= 0: s[2][num] = bm else: print "error: bmNum out of range" def setSailorPos(s, pos): checkSailor(s) s[3] = pos def setSailorVel(s, vel): checkSailor(s) s[4] = vel def setSailorScale(s, scale): checkSailor(s) s[5] = scale def setSailorSVel(s, sVel): checkSailor(s) s[6] = sVel def drawSailor(s): pos = getSailorPos(s) px = getPointX(pos) py = getPointY(pos) scale = getSailorScale(s) bm = getSailorBitmap(s, 0) bmw = getBitmapWidth(bm) bmh = getBitmapHeight(bm) w = bmw * scale h = bmh * scale x = px - w/2 y = py - h/2 drawBitmapFlatSprite(bm, makePoint(x,y), makePoint(x+w, y+h), -1) def movedSailor(s, mouX, mouY, click): pos = getSailorPos(s) px = getPointX(pos) py = getPointY(pos) vel = getSailorVel(s) vx = getPointX(vel) vy = getPointY(vel) scale = getSailorScale(s) bm = getSailorBitmap(s, 0) bmw = getBitmapWidth(bm) bmh = getBitmapHeight(bm) w = bmw * scale h = bmh * scale rad = (h+h)/4 sVel = getSailorSVel(s) if px < 100: vx = vx + 0.1 if px > 100: vx = vx - 0.1 if py < 100: vy = vy + 0.1 if py > 100: vy = vy - 0.1 if px > mouX-rad and px < mouX+rad and py > mouY-rad and py < mouY+rad: vx = vx + (mouX-px)/20 vy = vy + (mouY-py)/20 if click == 100: xi = bmw/2 + (mouX-px)/scale yi = bmh/2 + (mouY-py)/scale setBitmapPixel(bm, makePoint(xi, yi), makePixel(-1)) if scale < 200.0/rad: sVel = sVel + 0.1 else: sVel = sVel - 0.1 scale = scale + sVel setSailorBitmap(s, 0, bm) setSailorPos(s, makePoint(px+vx, py+vy)) setSailorVel(s, makePoint(vx, vy)) setSailorScale(s, scale) setSailorSVel(s, sVel) return s maxSailors = 0 sailor = [] res = 8 initSVel = 0.0 initKick = 3.0 sailor.append(makeSailor(res, res, 3, makePoint(100, 50), makePoint(initKick, 0), 100.0/res, initSVel)) maxSailors = maxSailors + 1 sailor.append(makeSailor(res, res, 3, makePoint(175, 100), makePoint(0, initKick), 50.0/res, initSVel)) maxSailors = maxSailors + 1 sailor.append(makeSailor(res, res, 3, makePoint(100, 187.5), makePoint(-initKick, 0), 25.0/res, initSVel)) maxSailors = maxSailors + 1 while 1: g.norefresh() g.paper(100) for a in range(0, maxSailors): drawSailor(sailor[a]) for a in range(0, maxSailors): sailor[a] = movedSailor(sailor[a], g.getMouse(1), g.getMouse(2), g.getMouse(3)) g.refresh()