def render(self, surf, dt): tmpV = math3d.VectorN((self.imgRect[2],self.imgRect[3])) tmpV *= self.scaleMultiplier scaleImg = pygame.transform.scale(self.img[self.imgIndex], tmpV.iTuple()) rotImg = pygame.transform.rotate(scaleImg, self.rotation) rotRect = rotImg.get_rect() screen.blit(rotImg, self.mPos-math3d.VectorN((rotRect[2]/2,rotRect[3]/2)))
def rayHit(self, R): Ox = R.mOrigin[0] Oz = R.mOrigin[2] Dx = R.mDirection[0] Dz = R.mDirection[2] Bx = self.mBase[0] Bz = self.mBase[2] epsilon = 0.0001 # Check the sides of the cylinder a = Dx**2 + Dz**2 b = 2 * (-Bx * Dx - Bz * Dz + Ox * Dx + Oz * Dz) c = -2 * Bx * Ox - 2 * Bz * Oz + Bx**2 + Bz**2 + Ox**2 + Oz**2 - self.mRadiusSq inner = b**2 - 4 * a * c den = 2 * a if inner < 0 or den < epsilon: return None inner **= 0.5 root1 = (-b + inner) / den root2 = (-b - inner) / den result = RayHitResult(R, self) oneHit = False if root1 > 0: P1 = R.getPoint(root1) if P1[1] >= self.mBase[1] - epsilon and P1[ 1] <= self.mBase[1] + self.mHeight + epsilon: oneHit = True result.appendIntersection(root1) if root2 > 0: P2 = R.getPoint(root2) if P2[1] >= self.mBase[1] - epsilon and P2[ 1] <= self.mBase[1] + self.mHeight + epsilon: oneHit = True result.appendIntersection(root2) # Now check the top / bottom of the cylinder planeT = Plane(math3d.VectorN((0, 1, 0)), self.mBase[1] + self.mHeight, self.mMaterial) planeB = Plane(math3d.VectorN((0, -1, 0)), -self.mBase[1], self.mMaterial) resultT = planeT.rayHit(R) if resultT: P = resultT.mIntersectionPoints[0] if (P[0] - Bx)**2 + (P[2] - Bz)**2 < self.mRadiusSq: result.appendIntersection(resultT.mIntersectionDistances[0]) oneHit = True resultB = planeB.rayHit(R) if resultB: P = resultB.mIntersectionPoints[0] if (P[0] - Bx)**2 + (P[2] - Bz)**2 < self.mRadiusSq: result.appendIntersection(resultB.mIntersectionDistances[0]) oneHit = True if oneHit: return result else: return None
def movePoint(self): """Moves point to mouse position""" if self.isClicked: self.mPos = math3d.VectorN(pygame.mouse.get_pos()) self.tangentPos = self.mPos + self.tangentOffset elif self.isTanClicked: self.tangentPos = math3d.VectorN(pygame.mouse.get_pos())
def __init__(self, index, pos): self.index = index self.mPos = math3d.VectorN(pos) self.color = (0, 255, 0) self.textOffset = math3d.VectorN((0, -17)) self.mRad = 8 self.isClicked = False self.destroy = False self.isTanClicked = False self.tangentOffset = math3d.VectorN( (random.randint(-100, 100), random.randint(-100, 100))) self.tangentPos = self.mPos + self.tangentOffset self.tangentColor = (255, 0, 0) self.lineColor = (255, 255, 255)
def __init__(self, pos, screenWidth, rad, boulderList, player): self.mPos = math3d.VectorN(pos) self.objectList = boulderList[:] self.objectList.append(player) self.angleMax = 360 self.angleMin = 0 #self.angle = 180 tmp = math3d.VectorN((pygame.display.Info().current_w/2,pygame.display.Info().current_h/2)) - self.mPos self.angle = math.atan2(-tmp[1], tmp[0])*180/math.pi + 180 self.angleInc = 50 self.laserLength = screenWidth*.6 self.endPos = self.mPos-self.mPos.normalized_copy()*self.laserLength self.color = (255,255,255) self.mRad = rad self.beamColor = (255,0,0)
def friction(self, dt, k): """In this lab, friction is only used for cannon""" oldVel = self.mVel.copy() af = -k * self.mVel.normalized_copy() self.mVel += af * dt if (oldVel[0] > 0 and self.mVel[0] < 0) or (oldVel[0] < 0 and self.mVel[0] > 0): self.mVel = math3d.VectorN(2)
def render(self, dt): """Rotates barrelImg first, then draws barrel and finally draws cannon base""" tmp = self.rotate() tmpRect = tmp.get_rect() tmpVector = self.barrelOffset - math3d.VectorN( (tmpRect[2], tmpRect[3])) / 2 screen.blit(tmp, (self.mPos + tmpVector).iTuple()) screen.blit(self.img, self.mPos.iTuple())
def update(self,deltaTime,mpos): bavg=math3d.VectorN(0,0) if not mpos: for i in self.boidList: bavg+=i.mPos bavg/=len(self.boidList) Boid.boidOffset=bavg else: bavg+=mpos
def __init__(self, ptA, ptB, color): self.mColor = color self.mMinPoint = ptA.copy() self.mMaxPoint = ptB.copy() for i in range(len(ptA)): if ptB[i] < self.mMinPoint[i]: self.mMinPoint[i] = ptB[i] if ptA[i] > self.mMaxPoint[i]: self.mMaxPoint[i] = ptA[i] self.mPlanes = [] for i in range(len(ptA)): L = [0.0] * len(ptA) L[i] = 1 posNorm = math3d.VectorN(*L) L[i] = -1 negNorm = math3d.VectorN(*L) self.mPlanes.append( Plane(posNorm, posNorm.dot(self.mMaxPoint), color)) self.mPlanes.append( Plane(negNorm, negNorm.dot(self.mMinPoint), color))
def __init__(self): self.count = 0 self.cpList = [] self.lineColor = (255, 255, 255) self.closed = False self.msg = "Left Click: Add C.P. Middle Click: Remove C.P. Right Drag: Move C.P./Tan Space: Toggle Closed/Open" self.msgPos = math3d.VectorN((12, 570)) self.tmpIndex = None self.res = 20
def checkMouseOver(self, pos): """Checks if this given pos was clicked on""" tmp = math3d.VectorN(pygame.mouse.get_pos()) tmpV = tmp - pos lhs = pow(tmpV[0], 2) + pow(tmpV[1], 2) rhs = pow(self.mRad, 2) if lhs < rhs: return True else: return False
def getAngle(self): """Returns angle using mouse position and self.mPos""" mouseV = math3d.VectorN(self.getMousePos()) newV = mouseV - self.mPos angle = math.atan2(-newV.mData[1], newV.mData[0]) angle = angle * (180 / math.pi) if angle > 45: angle = 45 elif angle < 0: angle = 0 return angle
def render(self, screen): """draw a circle for practice before I made the actual bird""" #self.boid=pygame.draw.circle(screen,(255,0,0),self.mPos.int(),5) """ this is the actual bird for the program, draws the boid to the screen""" VelHat = self.mVel.normalized() fwd = self.mPos + VelHat * 10 self.mVelHatPerp = math3d.VectorN(-VelHat[1], VelHat[0]) right = self.mPos + self.mVelHatPerp * 5 left = self.mPos - self.mVelHatPerp * 5 self.boid = pygame.draw.polygon(screen, (255, 0, 0), (fwd.int(), left.int(), right.int()))
def getLastDirection(self): tmp = "down" mousePos = math3d.VectorN(pygame.mouse.get_pos()) tmpV = (mousePos - self.mPos).iTuple() angle = math.atan2(-tmpV[1], tmpV[0])*180/math.pi if angle >= -45 and angle <= 45: tmp = "right" elif angle > 45 and angle <= 135: tmp = "up" elif angle > 135 and angle <= 180 or angle >= -180 and angle <= -135: tmp = "left" elif angle < -45 and angle > -135: tmp = "down" return tmp
def drawShape(surf, s): # You might *not* want to comment anything here -- these are the attributes / class names I'd like # you to use in this lab. pygameColor = None if hasattr(s, "mColor"): pygameColor = (s.mColor * 255).int() if isinstance(s, objects3d.Ray): pygame.draw.circle(surf, (255, 255, 255), s.mOrigin.int()[0:2], 4) pygame.draw.line(surf, (255, 255, 255), s.mOrigin.int()[0:2], s.getPoint(2000).int()[0:2]) elif isinstance(s, objects3d.Sphere): pygame.draw.circle(surf, pygameColor, s.mCenter.int()[0:2], s.mRadius, 2) elif isinstance(s, objects3d.Plane): # This is an iteresting one. We first have to determine if this plane is more horizontal (the normal # will be more closely-aligned with an up vector) than vice-versa. Note: the normal is perpendicular to the # plane. So to test for vertical-ish-ness, you actually look for a horizontal normal. Then, solve the plane # equation for the points on the sides (for horizontal planes) or top / bottom # (for vertical planes) of the screen. vertAlign = abs(math3d.VectorN(1, 0, 0).dot(s.mNormal)) horzAlign = abs(math3d.VectorN(0, 1, 0).dot(s.mNormal)) if vertAlign > horzAlign: h = surf.get_height() - 1 pt1 = math3d.VectorN((s.mDistance - s.mNormal[1]) / s.mNormal[0], 0) pt2 = math3d.VectorN( (s.mDistance - h * s.mNormal[1]) / s.mNormal[0], h) else: w = surf.get_width() - 1 pt1 = math3d.VectorN(0, (s.mDistance - s.mNormal[0]) / s.mNormal[1]) pt2 = math3d.VectorN(w, (s.mDistance - w * s.mNormal[0]) / s.mNormal[1]) pygame.draw.line(surf, pygameColor, pt1.int(), pt2.int(), 2) # Draw the normal vector midPt = (pt1 + pt2) * 0.5 normal2D = math3d.VectorN(s.mNormal[0], s.mNormal[1]) pygame.draw.line(surf, pygameColor, midPt.int(), (midPt + 10 * normal2D)) elif isinstance(s, objects3d.AABB): pygame.draw.rect(surf, pygameColor, (s.mMinPoint[0], s.mMinPoint[1], \ s.mMaxPoint[0] - s.mMinPoint[0], s.mMaxPoint[1] - s.mMinPoint[1]), 2) elif isinstance(s, objects3d.Polymesh): for i in range(len(s.mFList)): v1 = s.mVList[s.mFList[i][0]].int()[0:2] v2 = s.mVList[s.mFList[i][1]].int()[0:2] v3 = s.mVList[s.mFList[i][2]].int()[0:2] pygame.draw.polygon(surf, pygameColor, (v1, v2, v3), 1) pygame.draw.rect(surf, (255 * (s.mColor * 0.25)).int(), (s.mAABB.mMinPoint[0], s.mAABB.mMinPoint[1], \ s.mAABB.mMaxPoint[0] - s.mAABB.mMinPoint[0], s.mAABB.mMaxPoint[1] - s.mAABB.mMinPoint[1]), 2)
def update(self, dt): #print(self.angle) self.angle += self.angleInc*dt #if self.angle >= self.angleMax or self.angle <= self.angleMin: # self.angleInc *= -1 x = math.cos(math.radians(self.angle)) y = math.sin(math.radians(self.angle)) tmp = math3d.VectorN((x,y))*self.laserLength self.endPos = tmp + self.mPos #Hitting object #Get perpendicular line with object and check if that line is less than radius of object #Best way is to check all objects for obj in self.objectList: pass
def __init__(self): #loads the tank image, that I cut out self.image= pygame.image.load("turret.png") self.turret = self.image self.turretState=[] self.turretState.append(True) self.turretState.append(False) self.x=random.randint(10,790) self.y=random.randint(10,590) self.angle=random.randint(0,360) self.pos=math3d.VectorN(self.x,self.y,0) self.Vec= math3d.Ray(self.pos,self.pos) self.Timer=time.time() self.State=0 self.StatePeriod=5
def __init__(self, pos, vel): super().__init__(pos, vel) #Cannon Base self.img = pygame.image.load("images/cannon.png").convert_alpha() self.imgRect = self.img.get_rect() self.width = self.imgRect[0] #Cannon Barrel self.barrelOffset = math3d.VectorN((75, 12)) self.barrelImg = pygame.image.load( "images/barrell.png").convert_alpha() self.barrelRect = self.barrelImg.get_rect() self.angle = 0 #Other self.accelSpd = width self.projectiles = []
def shoot(self): """Creates a cannonball object at cannon tip with a random velocity in that angle""" #Position angle = math.radians(self.getAngle()) cY = math.sin(angle) * self.barrelRect[2] / 2 cX = math.cos(angle) * self.barrelRect[2] / 2 offset = math3d.VectorN((cX, -cY)) + self.barrelOffset finalPos = self.mPos + offset #velocity velV = finalPos - self.mPos velV = velV.normalized_copy() * random.uniform(350, 700) #velV = math3d.VectorN((random.uniform(50,350),-random.uniform(50,350))) self.projectiles.append( cannonBall((finalPos[0], finalPos[1]), velV.iTuple()))
def loadMesh(self, fname, offset, sfactor): self.mPos = offset self.mSFactor = sfactor self.mVList = [] self.mFList = [] self.mFArea = [] self.mFNorm = [] self.mFDVal = [] minPt = None maxPt = None fp = open(fname, "r") for line in fp: elem = line.strip().split(" ") if elem[0] == "v": v = math3d.VectorN(elem[1], elem[2], elem[3]) * sfactor + offset if minPt == None: minPt = v.copy() maxPt = v.copy() else: if v[0] < minPt[0]: minPt[0] = v[0] if v[1] < minPt[1]: minPt[1] = v[1] if v[2] < minPt[2]: minPt[2] = v[2] if v[0] > maxPt[0]: maxPt[0] = v[0] if v[1] > maxPt[1]: maxPt[1] = v[1] if v[2] > maxPt[2]: maxPt[2] = v[2] self.mVList.append(v) elif elem[0] == "f": if len(elem) != 4: raise ValueError( "Sorry -- I can only currently handle meshes with all triangles :-(" ) indicies = (int(elem[1]) - 1, int(elem[2]) - 1, int(elem[3]) - 1) va = self.mVList[indicies[0]] vb = self.mVList[indicies[1]] vc = self.mVList[indicies[2]] self.mFList.append(indicies) self.mFArea.append(self.triangleArea(va, vb, vc)) self.mFNorm.append((va - vc).cross(vb - vc).normalized()) self.mFDVal.append(va.dot(self.mFNorm[-1])) fp.close() return AABB(minPt, maxPt, self.mColor)
def update(self, deltaTime, mpos): """updates the movement of each of the boids in the flock""" if not mpos: avg = math3d.VectorN(0, 0) for boid in self.boid_list: avg += boid.mPos avg /= len(self.boid_list) Boid.new_mPos = avg else: avg = mpos """moves the flock based on the mouse button being clicked down""" for i in self.boid_list: i.accel(deltaTime, avg) """this is the update method from boid that does not have the mouse clicking I did not know if this was the way you wanted it to be set up""" for b in self.boid_list: b.update(deltaTime)
def update(self): self.AngleFacing=math3d.VectorN(math.cos(math.radians(self.angle)),math.sin(math.radians(self.angle)), 0) self.Vec=math3d.Ray(self.pos,self.AngleFacing) VecDist=self.pos-p.PlayerPos PassTime=time.time()-self.Timer if PassTime> self.StatePeriod: self.State+=1 self.Timer=time.time() if self.State>1: self.State=0 if VecDist.cross(self.Vec.destination)[2]<0: self.angle-=1 * deltaTime else: self.angle+=1 * deltaTime self.turret = pygame.transform.rotate(self.image,-int(self.angle+90)) if self.Vec.getDistanceToPoint(p.PlayerPos)==None: pass elif self.Vec.getDistanceToPoint(p.PlayerPos)<20 and self.State==0: print("pain train")
def update(self, eList, dt): self.laser.update(dt) self.player.update(eList, dt) if self.boulderList: for b in self.boulderList: b.update(dt) #For bouncing with other boulders, look in the link in the assignment pdf if len(self.boulderList) >= 2: for i in range(len(self.boulderList)): for j in range(i+1, len(self.boulderList)): B1 = self.boulderList[i] B2 = self.boulderList[j] n = B2.mPos-B1.mPos un = n.normalized_copy() if n.dot(n) <= pow(B1.radius+B2.radius,2): V1 = B1.mVel V2 = B2.mVel nV = V2-V1 unV = nV.normalized_copy() utV = math3d.VectorN((-unV[1],unV[0])) dotV = unV.dot(utV) #? nV1 = unV.dot(V1) tV1 = utV.dot(V1) nV2 = unV.dot(V2) tV2 = utV.dot(V2) new_nV1 = (nV1*(B1.radius - B2.radius)+2*B2.radius*nV2)/(B1.radius+B2.radius) new_nV2 = (nV2*(B2.radius - B1.radius)+2*B1.radius*nV1)/(B1.radius+B2.radius) new_nV1 *= unV new_tV1 = tV1*utV new_nV2 *= unV new_tV2 = tV1*utV new_V1 = new_nV1 + new_tV1 new_V2 = new_nV2 + new_tV2 B1.mVel = new_V1 B2.mVel = new_V2
def render(self, surf, closed): #Display this curvePoint if closed: pygame.draw.circle(surf, self.color, self.mPos.iTuple(), self.mRad) else: pygame.draw.circle(surf, self.color, self.mPos.iTuple(), self.mRad, 2) #Display Tangent Circle pygame.draw.circle(surf, self.tangentColor, self.tangentPos.iTuple(), self.mRad, 2) pygame.draw.line(surf, self.lineColor, self.mPos, self.tangentPos) #Display number above this point font = pygame.font.SysFont('Arial', 20) text = font.render(str(self.index), 1, (0, 255, 255)) textRect = text.get_rect() textV = math3d.VectorN((textRect[2], textRect[3])) / 2 textpos = self.mPos + self.textOffset - textV surf.blit(text, textpos.iTuple())
def __init__(self, ptA, ptB, material): self.mMinPt = ptA.copy() self.mMaxPt = ptB.copy() for i in range(ptA.mDim): if ptB[i] < self.mMinPt[i]: self.mMinPt[i] = ptB[i] if ptA[i] > self.mMaxPt[i]: self.mMaxPt[i] = ptA[i] self.mMaterial = material normals = (math3d.VectorN((-1,0,0)), math3d.VectorN((1,0,0)), \ math3d.VectorN((0,-1,0)), math3d.VectorN((0,1,0)), \ math3d.VectorN((0,0,-1)), math3d.VectorN((0,0,1))) self.mPlanes = [] for i in range(6): if i % 2 == 0: p = self.mMinPt else: p = self.mMaxPt self.mPlanes.append(Plane(normals[i], normals[i].dot(p), material))
def __init__(self, pos, vel): super().__init__(pos, vel) self.img = pygame.image.load("images/coconut.png").convert_alpha() self.imgRect = self.img.get_rect() self.gravity = math3d.VectorN((0, .2)) self.rotation = 0
def accel(self, a, dt): self.mVel += math3d.VectorN((a * dt, 0))
def __init__(self, pos, vel): self.mPos = math3d.VectorN(pos) self.mVel = math3d.VectorN(vel)
def __init__(self, x, y): """creating the beginning values for the boid""" self.mPos = math3d.VectorN(x, y) #VectorN self.mVel = math3d.VectorN(15, 10) #VectorN self.AccelMag = 100
import math3d import pygame #Pygame setup pygame.init() screen=pygame.display.set_mode((800,600)) clock=pygame.time.Clock() done=False circlePos=math3d.VectorN(400,300) #The POSITION of the circle circleVel=math3d.VectorN(200,100) #The OFFSET to move circle every SECOND circleAccelMag=100 #Attraction to mouse #Game Loop while not done: #Non-input related updates deltaTime=clock.tick()/1000.0 circleOffset=circleVel*deltaTime circlePos+=circleOffset circleVelHat=circleVel.normalized() circleVelHatPerp=math3d.VectorN(-circleVelHat[1],circleVelHat[0]) fwd=circlePos+circleVelHat*100 right=circlePos+circleVelHatPerp*50 #Input-related updates event=pygame.event.poll() #...event-handling