def renew_coloring_rule(self, bees, speed = 0.1): test.add_sticky("palette") x = zip(*[array(b.outputs)[0] for b in bees]) newmax = [max(x[i]) for i in range(2)] newmin = [min(x[i]) for i in range(2)] for i in range(2): self.max[i] *= (1-speed) self.max[i] += speed * newmax[i] self.min[i] *= (1-speed) self.min[i] += speed * newmin[i] self.scaling = [1.0 / (abs(M- m) + 0.01) for M, m in zip(self.max, self.min)] for i, x in enumerate(self.scaling): if math.isnan(x): self.scaling[i] = 0.5 test.remove_sticky("palette")
def project(self): '''Moves point forward while modifying velocity and grounded information''' test.add_sticky('bee:update:physics:project') # if self.name == "Harold": # self.xy += self.vxy*self.dt # self.push() # test.remove_sticky('project') # return # if not self.visible and ignoreinvisible: # return # if self.stationary: # return num_deflections = 0 num_stationary = 0 self.push() test.remove_sticky("bee:update:physics:project")
def compute(self, inp, use_memory=1): prefix = 'bee:update:thinking:compute:' add_sticky(prefix + "loadinputs") self.loadinputs(inp + [settings[BRAIN_BIAS]]) remove_sticky(prefix + "loadinputs") for i, edges in enumerate(self._all_edges): add_sticky(prefix + 'multiplication') if include_cycles: '''combine current and previous layer''' add_sticky(prefix + 'multiplication:appending') g = append( (settings[MEMORY_STRENGTH] * use_memory) * self.nodes[i + 1], self.nodes[i], axis=1) remove_sticky(prefix + 'multiplication:appending') dot(g, edges, out=self.nodes[i + 1]) else: dot(self.nodes[i], edges, out=self.nodes[i + 1]) remove_sticky(prefix + 'multiplication') add_sticky(prefix + 'activation') '''apply activation function''' expit(self.nodes[i + 1], out=self.nodes[i + 1]) remove_sticky(prefix + 'activation') return self.nodes[-1] # output is now a matrix; used to be a list
def repel(self, other = None, circle = None, radius = -1, corners = 0): prefix = "bee:update:physics:project:push:repel_loop:repel" ''' returns the minimum displacement, if any, required to push the other convex out. bool circle: - tells you whether it's a circle or a polygon int radius: - tells you the radius for collision - if negative, use the object's own radius other: - does... nothing? bool corners: - tells you whether or not to spend extra time and push using corners too. ''' '''the basic way that this works is you look at each potential separating axis find the shadow of both guys on each one and push the guy out out as quickly as possible.''' test.add_sticky(prefix+":normals") '''set the normals to consider''' my_ns = [k for k in self.shadowDict] other_ns = [] if radius < 0 and circle: radius = circle.radius if circle: if corners: for p in self.points: if self.use[p]: disp = (circle.xy - p).astype(float) dist = linalg.norm(disp) if dist == 0: continue disp /= dist other_ns.append(disp) else: other_ns = [k for k in other.shadowDict] ns_to_consider = my_ns + other_ns #ns_to_consider = no_parallels2(my_ns + other_ns, vector_slope) test.remove_sticky(prefix+":normals") test.add_sticky(prefix+":displacements") '''find all possible displacements''' disps = [] for n in ns_to_consider: if n in self.shadowDict: my_sh = self.shadowDict[n] else: my_sh = find_shadows([n], self.points)[n] my_l, my_r = my_sh if circle: center_sh = find_shadows(([n]), [circle.xy])[n] other_sh = (center_sh[0] - radius, center_sh[0] + radius) else: if n in other_sh: other_sh = self.shadowDict[n] else: other_sh = find_shadows([n], other.points)[n] other_l, other_r = other_sh if my_r <= other_l or my_l >= other_r: test.remove_sticky(prefix+":displacements") return matrix([0,0]) else: move_it_left = my_l - other_r move_it_right = my_r - other_l if move_it_right < abs(move_it_left): disps.append((n, move_it_right)) else: disps.append((n, move_it_left)) test.remove_sticky(prefix+":displacements") '''pick the shortest displacement''' disps = filter(lambda (normal, distance): abs(distance) != float('infinity'), disps) if disps: for n,m in disps: push = m * n #test.lines.append(((circle.xy[0,0], circle.xy[0,1]), ((circle.xy + push)[0,0], (circle.xy + push)[0,1]))) best_n, best_move = min(disps, key = lambda (n, m): abs(m)) #best_n = best_n / linalg.norm(best_n) push = best_move * best_n #test.lines.append(((circle.xy[0,0], circle.xy[0,1]), ((circle.xy + push)[0,0], (circle.xy + push)[0,1]))) direction = best_n*rotation #if (best_n*vdir.T)[0,0] > 0: circle.vxy = (circle.vxy * direction.T)[0,0] * direction test.record(prefix+":shortest") return best_move * best_n else: "no collision 2" x = matrix([0,0]) test.record(prefix+":no collision") return x
def push(self): '''uses volume-based methods to remove the physical from surfaces.''' prefix = "bee:update:physics:project:push" test.add_sticky(prefix) test.add_sticky(prefix + ":preliminaries") # wat if not self.grounded or self.vxy[0, 0]**2 + self.vxy[0, 1]**2 > 0.2: self.xy += self.vxy * self.dt if numpy.isnan(self.xy).any(): print "xy:", self.xy print "vxy:", self.vxy print "dt:", self.dt r = 0 if self.kind == "player": r = -1 corners = 1 else: r = -1 corners = 0 #disp = self.xy- self.room.player.xy # if disp[0,0]**2 + disp[0,1]**2 > 332800: # return #r = -1 #corners = 0 test.remove_sticky(prefix + ":preliminaries") test.add_sticky(prefix + ":repel_loop") for x, y in self.tiles_that_cover_me(r): try: c = self.room.convex_directory[x][y] except: continue if c: test.add_sticky(prefix + ":repel_loop:repel") w = c.repel(circle=self, radius=r, corners=corners) test.remove_sticky(prefix + ":repel_loop:repel") if linalg.norm(w) > 0: test.tiles.append((x, y)) self.health -= (linalg.norm(w) + 2) / 1000 if w[0, 1] < -0.1: # and abs(w[0,1]) > 2*abs(w[0,0]): self.grounded = 1 l = linalg.norm(w) assert l != 0 assert not math.isnan(l) assert l not in (float('infinity'), -float('infinity')) self.normals.append(w / l) p1 = (int(self.xy[0, 0]), int(self.xy[0, 1])) self.xy += w p2 = (int(self.xy[0, 0]), int(self.xy[0, 1])) test.lines.append((p1, p2)) '''test.add_sticky('repel') w = c.repel(circle = self, radius = r, corners = corners) test.record() test.remove_sticky('repel') distance = linalg.norm(w) if not distance: continue #self.health -= (distance + 2) / 1000 if self.kind == "bee" and settings[STICKY_WALLS]: if 0 < settings[STICKY_WALLS] < 1: self.vxy *= (1 - settings[STICKY_WALLS]) normalizednormal = w / distance if normalizednormal[0,1] < -0.7: #and abs(w[0,1]) > 2*abs(w[0,0]): self.grounded = 1 self.normals.append(normalizednormal) self.xy += w ''' test.remove_sticky(prefix + ":repel_loop") test.remove_sticky(prefix)
def draw(self, surface): test.add_sticky('bee:draw') # for b in self.bullets: # b.draw(surface) # fullname = self.name + str(self.ancestry) super(Bee, self).draw(surface) ixy = self.xy.astype(int) if 0 and settings[SHOW_EYES]: box = self.decoration.get_rect( x=self.xy[0, 0] + self.eyedrawingoffset[0], y=self.xy[0, 1] + self.eyedrawingoffset[1]) surface.blit(self.decoration, box, special_flags=pygame.BLEND_ADD) if settings[SHOW_EYES]: for x, y in self.eyepoints: ixy = self.xy.astype(int) X = ixy[0, 0] + x Y = ixy[0, 1] + y # X %= surface.get_width() # Y %= surface.get_height() # if abs(X - ixy[0, 0]) > 500 or abs(Y - ixy[0, 1]) > 100: # continue # surface.set_at((X, y), graphics.outline) pygame.draw.line( surface, self.color, array(self.xy)[0], (X, Y), 1) start = self.xy end = self.prevpos '''this is here to make things trippy''' if abs(start[0, 0] - end[0, 0]) < 100: if abs(start[0, 1] - end[0, 1]) < 100: if self.madness == 1: '''lines''' w = 10 # pygame.draw.line(self.room.background, [0, 0, 0], array(self.xy)[0], array(self.prevpos)[0], w) pygame.draw.line( self.room.background, self.color, array(self.xy)[0], array(self.prevpos)[0], 1) elif self.madness == 2: '''extra mad''' c = self.color d = int(linalg.norm(self.prevpos - self.xy)) pygame.draw.circle( self.room.background, c, array(self.xy)[0], d / 3, 0) pygame.draw.line( self.room.background, c, array(self.xy)[0], array(self.prevpos)[0], 1) elif self.madness == 3: '''super mad''' w = int(linalg.norm(self.vxy) * 100 + 1) # pygame.draw.line(self.room.background, [255,20,20], array(self.xy)[0], array(self.prevpos)[0], w + 10) pygame.draw.line( self.room.background, self.color, array(self.xy)[0], array(self.prevpos)[0], w) # pygame.draw.line(self.room.background, [0, 0, 0], array(self.xy)[0], array(self.prevpos)[0], 1) elif self.madness == 4: '''lines with shadows''' w = 10 pygame.draw.line( self.room.background, [0, 0, 0], array(self.xy)[0], array(self.prevpos)[0], w) pygame.draw.line( self.room.background, self.color, array(self.xy)[0], array(self.prevpos)[0], 1) for x, y in utils.body_copies(self.xy, self.radius): px = ixy[0, 0] + x * graphics.world_w py = ixy[0, 1] + y * graphics.world_h # c = self.color blood = [255, 0, 0] # pygame.draw.circle(surface, c, (px, py), int(self.radius)) r = int(self.radius * 0.6) draw_blood = 0 if draw_blood: if self.vxy[0, 0] > 0: pygame.draw.line( surface, blood, (px - r, py - r), (px + r, py + r), 1) else: pygame.draw.line( surface, blood, (px + r, py - r), (px - r, py + r), 1) # pygame.draw.circle(surface, [int(p) for p in self.color], (px, py), int(self.radius)) # centercolor = [255-n for n in c] # rad = int(self.radius*(1-self.health)) # rad = max( rad, 0) # pygame.draw.circle(surface, [int(p) for p in centercolor], (px, py), rad) # if self.flash: # pygame.draw.circle(surface, [255, 255, 255], (px, py), self.flash + 1, 1) # self.flash -= 1 regularcolor = self.color r2 = int(self.radius * 0.6 * self.health) if settings[BEE_STYLE] == 1: if self.vxy[0, 0] > 0: pygame.draw.line( surface, regularcolor, (px - r2, py - r2), (px + r2, py + r2), 1) else: pygame.draw.line( surface, regularcolor, (px + r2, py - r2), (px - r2, py + r2), 1) elif settings[BEE_STYLE] == 2: # self.dvxy = matrix([0.0, 0.0]) rotation = self.dvxy[0, 0] * 600 dx = math.cos(rotation) dy = math.sin(rotation) dx, dy = 4 * dx, 4 * dy if self.flash: self.flash -= 1 if self.flash > 25: self.flash = 25 if self.flash < 0: self.flash = 0 c = [255 - 25 * self.flash, 255, 255 - 25 * self.flash] if self.see_bullet: c = [255, 255, 0] try: pygame.draw.line( surface, c, (px + dx, py + dy), (px - dx, py - dy), 3) except TypeError: print "TypeError while drawing bee, position is", print surface, c, (px + dx, py + dy), (px - dx, py - dy), 3 else: radius = 1 + int(self.radius * self.health) if (radius < 1): radius = 1 pygame.draw.circle(surface, regularcolor, (px, py), radius) if settings[SHOW_EYES]: for distance, (x, y) in zip(self.wallproximities, self.sharedeyes): l = (x**2 + y**2)**0.5 '''x0 = x/l*distance*graphics.screen_h/2 y0 = y/l*distance*graphics.screen_h/2 pygame.draw.line(surface, [255,255,255], (px,py), (px+x0, py+y0), 1)''' x1 = int(x / l * 10) y1 = int(y / l * 10) # size represents proximity # pygame.draw.circle(surface, regularcolor, ( px+x1, py+y1), 1 + int( (1 - distance) * 6) ) # color represents proximity # pygame.draw.circle(surface, regularcolor, ( px+x1, py+y1), 1 + int( (1 - distance) * 6) ) intensity = (1 - distance) * 255 if intensity < 0: intensity = 0 if intensity > 255: intensity = 255 # pygame.draw.circle(surface, (intensity, intensity, intensity), ( px+x1, py+y1), 3) scaling = math.sin(22.5) pygame.draw.line(surface, (intensity, intensity, intensity), ( px + x1 - y1 * scaling, py + y1 + x1 * scaling), (px + x1 + y1 * scaling, py + y1 - x1 * scaling)) if settings[SHOW_NAMES]: try: surface.blit(self.tag[1], array(self.xy)[0]) except: self.tag = "blah", "noway" l = self.firstname + " " + self.name if self.tag[0] != l: t = tinyfont.render(l, 0, [255, 255, 255]) self.tag = l, t # My velocity # endxy = ixy+numpy.round_(self.vxy*10) # pygame.draw.line(surface, (255, 255, 0), array(ixy)[0], array(endxy)[0], 1) test.remove_sticky('bee:draw')
def update(self, dt, key_states, key_presses, allow_randomize=1): '''physics, thinking, moving''' try: self.lifetime += 1 except: print "temporary transition error" if self.skipupdate: self.skipupdate = 0 return '''This is where you cruise without physics and without thinking''' if not self.slow: self.dt = dt self.xy += self.vxy * self.dt return test.add_sticky('bee:update') test.add_sticky("bee:update:start") self.prevpos = self.xy * 1 fullname = self.name + str(self.ancestry) super(Bee, self).update(dt, key_states, key_presses) test.remove_sticky("bee:update:start") test.add_sticky("bee:update:health,birth,eating") self.timesincelastshot += dt # for b in self.bullets: # b.update(dt, key_states, key_presses) if not self.room.stasis: self.update_health(dt) self.considergivingbirth() self.friends *= 0.9 self.friendsrelpos *= 0.9 for p in self.objectsinview: if p.kind == "bullet": p.hit_bee(self) elif p.name != self.name and settings[SWARMING_PEER_PRESSURE] and p.kind == "bee": othervel = p.vxy - self.vxy self.friendsrelpos = p.xy - self.xy self.vxy += settings[SWARMING_PEER_PRESSURE] * othervel elif p.kind == "player" and not self.room.stasis: self.eat_player() self.timesincelastthought += dt test.remove_sticky("bee:update:health,birth,eating") test.add_sticky("bee:update:thinking") if self.timesincelastthought > self.responsetime: test.add_sticky("bee:update:thinking:inputs") test.add_sticky("bee:update:thinking:inputs:collection") test.record() self.timesincelastthought -= self.responsetime infoz = None LIDAR = 1 POINTCHECK = 2 TILES = 3 vision_mode = LIDAR if vision_mode == LIDAR: c = int(self.xy[0, 0] / bw) r = int(self.xy[0, 1] / bw) infoz = self.room.visiondirectory[ c % graphics.world_tw][r % graphics.world_th] self.wallproximities = infoz test.record("bee:update:thinking:inputs:vision") elif vision_mode == POINTCHECK: test.record() a = int(self.xy[0, 0]) b = int(self.xy[0, 1]) infoz = [self.room.pointcheck( (a + eye_x, b + eye_y)) for eye_x, eye_y in self.eyepoints] test.record("bee:update:thinking:inputs:pointchecks") else: infoz = [] test.record() a = int(self.xy[0, 0]) b = int(self.xy[0, 1]) points_to_check = ((a + eye_x, b + eye_y) for eye_x, eye_y in self.eyepoints) self.see_bullet = False for i, (x, y) in enumerate(points_to_check): c = int(x / bw) r = int(y / bh) objects = self.room.object_directory[ c % graphics.world_tw][r % graphics.world_th] g = i % 2 if g == 0: infoz.append( any(other.kind == "bullet" for other in objects)) if infoz[-1]: self.see_bullet = True else: infoz.append(self.room.pointcheck((x, y))) # walls test.record("bee:update:thinking:inputs:tiles") # go = time.time() # t = [math.sin(go), math.sin(go/2.3), math.sin(go)%1.5] test.remove_sticky("bee:update:thinking:inputs:collection") test.add_sticky("bee:update:thinking:inputs:actually wraparound") # center = matrix([graphics.world_w/2, graphics.world_h/2]) if STALK_CAMERA: self.stalkcamera() disp_to_p = self.player.xy - self.xy if settings[WRAPAROUND_TRACKING]: disp_to_p += graphics.world_center disp_to_p[0, 0] %= graphics.world_w disp_to_p[0, 1] %= graphics.world_h disp_to_p -= graphics.world_center test.remove_sticky( "bee:update:thinking:inputs:actually wraparound") test.add_sticky("bee:update:thinking:inputs:player offset") player_sight_scale = 0.02 disp_to_p *= player_sight_scale dist = linalg.norm(disp_to_p) sharpness = 1 radius = 2 if dist > 0: disp_to_p *= settings[SENSITIVITY_TO_PLAYER] / \ (dist * (1 + 2 ** (sharpness * (dist - radius)))) # tweaked_disp *= self.sensitivity # dispx, dispy = tuple(array(disp_to_p)[0]) # BE REALLY CAREFUL WHEN DIVIDING THIS BY STUFF THEY ARE INTEGERS test.remove_sticky("bee:update:thinking:inputs:player offset") test.add_sticky( "bee:update:thinking:inputs:packaging and nodetags") disps = [disp_to_p[0, 0], disp_to_p[0, 1]] # dvx = self.player.vxy[0, 0] - self.vxy[0, 0] # dvy = self.player.vxy[0, 1] - self.vxy[0, 1] inputs = disps + [1 - distance for distance in infoz] + [self.health / settings[ MAX_HEALTH]] + [expit(self.vxy[0, 0]), expit(self.vxy[0, 1])] # 1 # self.brain.nodetags[(0, 0)] = "verbatim", "player x" # self.brain.nodetags[(0, 1)] = "verbatim", "player y" # i = 2 # for vector in self.eyepoints: # self.brain.nodetags[(0,i)] = "vector", vector # i+=1 # self.brain.nodetags[(0,i)] = "verbatim", "health" # i+=1 # self.brain.nodetags[(0,i)] = "verbatim", "x velocity" # i+=1 # self.brain.nodetags[(0,i)] = "verbatim", "y velocity" # i+=1 test.remove_sticky( "bee:update:thinking:inputs:packaging and nodetags") # inputs += [self.friends[0, 0], self.friends[0, 1], # self.friendsrelpos[0, 0], self.friendsrelpos[0, 1]] # 4 test.remove_sticky("bee:update:thinking:inputs") test.add_sticky("bee:update:thinking:compute") # Note: output is now a matrix! # print inputs # self.brain.set_inputs(matrix(inputs)) self.brain.compute(inputs) outputs = matrix([0.0, 0.0]) self.brain.get_outputs(outputs) self.outputs = outputs[:, :] + 0 # self.outputs = outputs = self.brain.compute(inputs) test.remove_sticky("bee:update:thinking:compute") test.add_sticky("bee:update:thinking:outputs") self.up = 2 * outputs[0, 0] - 1 # down = outputs[1] self.leftright = 2 * outputs[0, 1] - 1 # print linalg.norm(self.vxy) self.color = self.room.painter.get_color(self) '''self.color = [outputs[0]*3, (outputs[1] - 0.75)*4, (self.leftright + 0.7) / 2] self.color = [int(i*255) for i in self.color] self.color = [max(a, 0) for a in self.color] self.color = [min(a,255) for a in self.color]''' ''' if outputs[2] > 0 and self.timesincelastshot > 1000: self.timesincelastshot = 0 direction = matrix([outputs[3],outputs[4]]) direction = disp_to_p direction /= linalg.norm(direction) b = bullet.Bullet(self, self.player, self.room, direction * outputs[2] * 2) b.xy = self.xy + matrix([0, 0]) self.room.bullets.append(b) self.health -= 0.05''' test.remove_sticky("bee:update:thinking:outputs") test.remove_sticky("bee:update:thinking") test.add_sticky("bee:update:physics") test.add_sticky("bee:update:physics:basicmovement") if settings[CREATURE_MODE] == 0: '''bees''' self.vxy += gravity * dt self.dvxy = self.up * jumpvel * dt + \ self.leftright * yogroundacc * dt self.vxy += dt * self.dvxy self.vxy *= speed_decay**dt else: '''fleas''' self.vxy += 2 * gravity * dt if self.grounded: self.vxy[0, 0] = self.leftright * 0.3 if self.up > 0.5: self.dvy = self.up * jumpvel * 20000 self.vxy += self.dvy self.health -= settings[COST_OF_JUMP] else: self.vxy[0, 0] += self.leftright * 0.01 self.vxy *= speed_decay**dt # if abs(self.vxy[0, 0]) > maxvelx: # print self.vxy, "has too much horizontal" # self.vxy[0, 0] *= maxvelx / abs(self.vxy[0, 0]) # if linalg.norm(self.vxy) > maxvel: # self.vxy /= linalg.norm(self.vxy) # self.vxy *= maxvel # collision testing and further modification of position and velocity self.grounded = 0 # num_deflections = 0 del self.normals[:] test.remove_sticky("bee:update:physics:basicmovement") self.project() # This will consume dt test.add_sticky("bee:update:physics:worldwrap") # stay in the box self.xy[0, 0] = self.xy[0, 0] % graphics.world_w self.xy[0, 1] = self.xy[0, 1] % graphics.world_h test.remove_sticky("bee:update:physics:worldwrap") test.add_sticky("bee:update:physics:teleport") # maybe teleport back if allow_randomize and self.room.pointcheck((int(self.xy[0, 0]), int(self.xy[0, 1]))): if (self.lastnonwall[0, 0] < 0): self.randomize_position() else: self.xy = self.lastnonwall * 1 self.health -= 0.1 self.vxy *= -1 else: self.lastnonwall = self.xy * 1 # if linalg.norm(self.prevpos - self.xy) < 200: # test.lines.append( ( (int(self.prevpos[0, 0]), int(self.prevpos[0, 1]) ), (int(self.xy[0, 0]), int(self.xy[0, 1]) ) ) ) c = int(self.xy[0, 0] / bw) r = int(self.xy[0, 1] / bh) if self.room.tiles[c][r].name == "bounce": self.vxy[0, 1] += -0.001 * dt test.remove_sticky("bee:update:physics:teleport") test.remove_sticky("bee:update:physics") self.age() test.remove_sticky('bee:update')
def push_out(self, p_xy, radius): '''checks for intersection of circle with side. Returns false if there are no intersections... otherwise returns a new path to travel assumption here is that motion is not parallel to surface''' test.add_sticky("pushout") rotation = matrix([[0,1], [-1,0]]) #takes (1,0) to (0, -1) #takes (0,1) to (1, 0) #Like an anticlockwise rotation in our choice of axis ''' #for player p_target = p_start + p_dxy#; print p_target p_normal = p_dxy * rotation#; print p_normal ''' #for this side s_start, s_target = self.side#; print s_start, s_target s_dxy = s_target - s_start#; print s_dxy s_normal = s_dxy * rotation#; print s_normal # Let's find the closest point! We can do this with projection # Something that takes (1,0) to s_dxy and (0,1) to s_normal G = numpy.append(s_dxy.T, s_normal.T, axis = 1) G /= linalg.det(G)**0.5 # Now just a rotation H = linalg.inv(G) # rotation that takes s_dxy to x axis p0 = H * s_start.T p1 = H * s_target.T p0 = p0.T p1 = p1.T q = H * p_xy.T # move q and then move T cp = matrix([0,0]) if p0[0,0] > p1[0,0]: p0, p1 = p1, p0 # making sure p0 is on left if p0[0,0] <= q[0,0] <= p1[0,0]: # If the closest point is on the line cp[0,0] = q[0,0] cp[0,1] = p0[0,1] elif q[0,0] < p0[0,0]: cp = p0 elif p1[0,0] < q[0,0]: # q is on cp = p1 else: print "problem: Can't find closest point" w = G * cp.T test.lines.append(((w[0,0],w[1,0]), (p_xy[0,0], p_xy[0,1]))) q = q.T if linalg.norm(q-cp) < radius: if linalg.norm(q-cp) != 0: direction = (q-cp) / linalg.norm(q-cp) else: print "darn! No idea where to project! Modify later to incorporate vxy" direction = matrix([1,0]) q = cp + radius * direction p_xy = (G * q.T).T test.remove_sticky("pushout") return p_xy
def update(self, dt, key_states, key_presses): test.add_sticky('player') super(Player, self).update(dt, key_states, key_presses) self.maybe_die() for phys in self.objectsinview: if phys.kind == "bullet": phys.hit_player() elif phys.kind == "bee": phys.eat_player() self.lifetime += 1 #self.radius *= 1.001 #self.radius = self.radius*0.92 + 40*0.08 bw = graphics.bw bh = graphics.bh myleft = (self.xy[0,0] - self.radius) / bw myright = (self.xy[0,0] + self.radius) / bw mytop = (self.xy[0,1] - self.radius) / bh mybottom = (self.xy[0,1] + self.radius) / bh myleft, myright, mytop, mybottom = int(myleft), int(myright), int(mytop), int(mybottom) self.counter += 1 self.counter2 += 1 if key_states[pygame.K_UP]: if self.feetSupported: self.jetpackfuel = 200 self.vxy += jumpvel if self.jetpackfuel: jv = jumpvel / 50 consumedfuel = min(dt, self.jetpackfuel) self.vxy += jv * consumedfuel self.jetpackfuel -= consumedfuel if self.jetpackfuel < 0: self.jetpackfuel = 0 else: self.jetpackfuel = 0 #modify velocity ''' if key_states[pygame.K_UP] and self.grounded: #jv = jumpspeed * self.normals[0] * -1 jv = jumpvel#jumpspeed * self.normals[0] self.vxy += jv# jumpspeed*matrix(self.testvectors[0])/linalg.norm(self.testvectors[0])#jumping ''' #if key_states[pygame.K_DOWN]: # jv = jumpspeed * self.normals[0] # self.vxy += jv# jumpspeed*matrix(self.testvectors[0])/linalg.norm(self.testvectors[0])#jumping #if key_states[pygame.K_DOWN]: #self.vxy -= jumpvel self.vxy += matrix([[0, settings[GRAVITY]]])*38/6*dt if key_states[pygame.K_SPACE]: self.randomize_position() if key_states[pygame.K_g]: #self.topbar.flash("Generating bees!") self.room.generate_bees(1) '''add kill mode''' allowkillmode = False ''' if allowkillmode: if key_states[pygame.K_z]: self.killmode = 1 self.radius = killmoderadius else: self.killmode = 0 self.radius = defaultradius ''' self.feetSupported = self.grounded ''' if self.feetSupported and not (key_states[pygame.K_LEFT] or key_states[pygame.K_RIGHT] or key_states[pygame.K_UP]): self.vxy *= (1-friction)**dt # Friction self.vxy *= 0 if key_states[pygame.K_LEFT] : self.vxy += groundacc*self.normals[0]*matrix([[0, -1],[1, 0]])*dt# Left # used to be elif key_states[pygame.K_RIGHT] : self.vxy += groundacc*self.normals[0]*matrix([[0, 1],[-1, 0]])*dt# Right else: self.vxy -= airresist*self.vxy*dt*linalg.norm(self.vxy) # Air resistance if key_states[pygame.K_LEFT] : self.vxy -= airacc*dt# Left elif key_states[pygame.K_RIGHT] : self.vxy += airacc*dt# Right ''' if self.feetSupported: if key_states[pygame.K_LEFT]: if self.normals: self.vxy += groundacc*self.normals[0]*matrix([[0, -1],[1, 0]])*dt# Left # used to be else: self.vxy += groundacc*matrix([-1, 0])*dt elif key_states[pygame.K_RIGHT]: if self.normals: self.vxy += groundacc*self.normals[0]*matrix([[0, 1],[-1, 0]])*dt# Right else: self.vxy += groundacc*matrix([1, 0])*dt elif not self.beepushes or key_states[pygame.K_UP]: self.vxy *= 0.2 else: self.vxy -= airresist*self.vxy*dt*linalg.norm(self.vxy) # Air resistance if key_states[pygame.K_LEFT] : self.vxy -= airacc*dt# Left elif key_states[pygame.K_RIGHT] : self.vxy += airacc*dt# Right #if abs(self.vxy[0,0]) > maxvelx: # self.vxy[0,0] *= maxvelx / abs(self.vxy[0,0]) if linalg.norm(self.vxy) > maxvel: self.vxy /= linalg.norm(self.vxy) self.vxy *= maxvel #collision testing and further modification of position and velocity #if self.grounded: # if self.beepushes or (key_states[pygame.K_LEFT] or key_states[pygame.K_RIGHT] or key_states[pygame.K_UP]): # self.grounded = 0 self.grounded = 0 num_deflections = 0 self.normals = [] self.project() # This will consume dt #stay in the box self.xy[0,0] = self.xy[0,0]%graphics.world_w self.xy[0,1] = self.xy[0,1]%graphics.world_h c = int(self.xy[0,0] / bw) r = int(self.xy[0,1] / bh) if self.room.tiles[c][r].name == "wall": if (self.lastnonwall == 0): self.randomize_position(10) else: c0, r0 = self.lastnonwall self.xy[0,0] = (c0 + 0.5) * bw self.xy[0,1] = (r0 + 0.5) * bh self.vxy *= 0.5 else: self.lastnonwall = c, r test.remove_sticky('player')
def draw(self, surface): test.add_sticky('player') super(Player, self).draw(surface) if self.losinghealth: self.walkingspeed = self.radius / 15 * 0.04 self.displaycolor[0] = 0.9 * self.displaycolor[0] + 0.1 * 255 self.displaycolor[1] = 0.9 * self.displaycolor[1] self.displaycolor[2] = 0.9 * self.displaycolor[2] #self.color[0] = 255 else: self.displaycolor[0] = 0.9 * self.displaycolor[0] + 0.1 * self.color[0] self.displaycolor[1] = 0.9 * self.displaycolor[1] + 0.1 * self.color[1] self.displaycolor[2] = 0.9 * self.displaycolor[2] + 0.1 * self.color[2] color = [int(x) for x in self.displaycolor] #if self.counter >= self.radius - 10: # if self.radius < 20: # color = [255, 200, 0] # if self.counter >= self.radius: # self.counter -= self.radius ixy = self.xy.astype(int) for x,y in utils.body_copies(self.xy, self.radius): px = ixy[0,0] + x*graphics.world_w py = ixy[0,1] + y*graphics.world_h #pygame.draw.circle(surface, [180,255,255], (px, py), int(self.radius), 1) pi = 3.1415926 '''shoulders''' shouldershift = 0#max(min(int(10*self.vxy[0,0]), 10), -10) shoulderx = px + shouldershift shouldery = py - int(self.radius*0.7) if self.losinghealth: if self.beepushes: n = random.choice(self.beepushes) self.offset += n * 0.5 self.offset *= 0.95 for i in range(2): if self.offset[0,i] > 5: self.offset[0,i] = 5 if self.offset[0,i] < -5: self.offset[0,i] = -5 offsetx = int(self.offset[0,0]) offsety = int(self.offset[0,1]) self.beepushes = [] shoulderx += offsetx shouldery += offsety shoulders = (shoulderx, shouldery) '''head''' headx = shoulderx heady = shouldery-int(self.radius*0.1) #headx -= offsetx/2 #heady -= offsety/2 head = int(headx), int(heady) pygame.draw.circle(surface, color, head, int(self.radius*0.2), 0) '''groin''' groinx = px groiny = py+int(self.radius*0.1) groinx += offsetx / 2 groiny += offsety groin = (groinx, groiny) '''neck''' pygame.draw.line(surface, color, head, shoulders, 2) '''torso''' pygame.draw.line(surface, color, shoulders, groin, 2) '''right leg''' rightfootx = px + 0.4*self.radius - 3 * self.vxy[0,0] * self.radius rightfooty = py+int(self.radius) + 0.1*self.radius rightfootx = px + 0.4*self.radius*math.cos(self.walkingspeed*pi*self.xy[0,0]) if abs(self.vxy[0,0]) > 0.01: rightfooty = py+int(self.radius) step = 0.1*self.radius*math.sin(self.walkingspeed*pi*self.xy[0,0]) if step < 0: step *= abs(self.offset[0,1]*5 + 1) rightfooty += step rightfoot = rightfootx, rightfooty pygame.draw.line(surface, color, groin, rightfoot, 2) #pygame.draw.line(surface, color, (px,py+int(self.radius*0.2)), (px + self.radius*math.cos(0.4*pi), py+inself.radius*math.sin(0.4*pi)), 1) '''left leg''' leftfootx = px - 0.4*self.radius - 3 * self.vxy[0,0] * self.radius leftfooty = py+int(self.radius) + 0.1*self.radius leftfootx = px - 0.4*self.radius*math.cos(self.walkingspeed*pi*self.xy[0,0]) if abs(self.vxy[0,0]) > 0.01: leftfooty = py+self.radius step = - 0.1*self.radius*math.sin(self.walkingspeed*pi*self.xy[0,0]) if step < 0: step *= abs(self.offset[0,1]*5 + 1) leftfooty += step leftfooty = int(leftfooty) leftfoot = leftfootx, leftfooty pygame.draw.line(surface, color, groin, leftfoot, 2) rightpoint = px + 0.8 * self.radius, py + 0.8 * self.radius leftpoint = px - 0.8 * self.radius, py + 0.8 * self.radius rightpoint, leftpoint = [int(x) for x in rightpoint], [int(x) for x in leftpoint] #self.feetSupported = self.room.pointcheck(leftfoot) or self.room.pointcheck(rightfoot) or self.room.pointcheck(rightpoint) or self.room.pointcheck(leftpoint) #print "feet supported:", self.feetSupported ''''right arm''' #howfar = 0.3 #if self.vxy[0,0] >= 0: # howfar = 0.3 - 2.3 * (self.vxy[0,0]) #self.righta = 0.9 * self.righta + 0.1 * howfar #pygame.draw.line(surface, color, shoulders, (px + 0.7*self.radius*math.cos(self.righta*pi), py+0.7*self.radius*math.sin(self.righta*pi)), 2) righthandx = shoulderx + 0.4*self.radius * math.cos(self.walkingspeed*pi*self.xy[0,0]) * (0.2+min(abs(self.vxy[0,0]), 0.1))**0.5 * 2 righthandy = shouldery + self.radius righthandy -= abs(int(self.offset[0,1] * 5)) righthand = (righthandx, righthandy) pygame.draw.line(surface, color, shoulders, righthand, 2) '''left arm''' #howfar = 0.7 #if self.vxy[0,0] <= 0: # howfar = 0.7 - 2.3 * (self.vxy[0,0]) #self.lefta = 0.9 * self.lefta + 0.1 * howfar #pygame.draw.line(surface, color, shoulders, (px + 0.7*self.radius*math.cos(self.lefta*pi), py+0.7*self.radius*math.sin(self.lefta*pi)), 2) lefthandx = shoulderx - 0.4*self.radius * math.cos(self.walkingspeed*pi*self.xy[0,0]) * (0.2+min(abs(self.vxy[0,0]), 0.1))**0.5 * 2 lefthandy = shouldery + self.radius lefthandy -= abs(int(self.offset[0,1] * 5)) lefthand = (lefthandx, lefthandy) pygame.draw.line(surface, color, shoulders, lefthand, 2) ffcolor = [255, 255, 255] #if self.losinghealth: # ffcolor = [255, 0, 0] '''force field''' '''if self.losinghealth: pygame.draw.circle(surface, self.displaycolor, (px, py), int(self.forcefield), 1) ''' #pygame.draw.circle(surface, [255,255,0], (px, py), int(self.radius), 1) #centercolor = [0, 0, 0] #if self.losinghealth: # centercolor = [255, 200, 0] #pygame.draw.circle(surface, centercolor, (px, py), int(0.1*self.radius)) # My velocity #endxy = ixy+numpy.round_(self.vxy*10) #pygame.draw.line(surface, (255, 255, 0), array(ixy)[0], array(endxy)[0], 1) test.remove_sticky('player') self.losinghealth = 0
def main_loop(): print "\n" * 12 + "* * * * * NEW GAME * * * * *" """these things only need to happen once""" screen = pygame.display.get_surface() screen.fill(graphics.background) load_settings() messages.screen = screen clock = pygame.time.Clock() dt = 0 world, t, r = 0, 0, 0 loadedSavedGame = 0 if getChoiceUnbounded("Load saved game?", ["yes", "no"]) == "yes": r = game_progress.load_game() if r: messages.say("Loading saved game", down=4) pygame.display.flip() world = pygame.Surface((graphics.world_w, graphics.world_h)) t = r.topbar loadedSavedGame = 1 else: """these are level-specific""" level = enteredlevel(allowcancel=0) if level == "quit": return world, t, r = preparelevel(screen, level) pygame.display.get_surface().fill((50, 50, 50)) p = player.Player(r) # h = zoo.Beehive() h = zoo.Beehive("the fact that any argument is passed here means that I'll load saved bees") c = camera.Camera(p, world, screen, r) c.jump_to_player() # myfamilytree = familytree.FamilyTree() myspeciesplot = species_visualization.SpeciesPlot() # Generating new bees # r.bees = h.preserved_bees(r, p) if loadedSavedGame: for b in r.bees: b.player = p else: r.generate_bees(settings[MAXIMUM_BEES]) r.h = h # for b in r.bees: # b.randomize_position() framecount = 0 previous_key_states = [] key_ups = [] global time_to_quit info_panel = StackingPanel() left = 0 top = 0 for family_name in game_settings.families: family_panel = ShrinkingPanel(min_width=250) top = 0 title = MessagePanel(family_name) family_panel.children.append(title) title.onclick.append(get_toggler(family_panel)) top += 30 for entry in game_settings.families[family_name]: new_button = SettingButton(entry, y=top, typeface="DejaVu Sans", bold=True, italic=True, visible=False) top += 20 family_panel.children.append(new_button) left += family_panel.rect.w info_panel.children.append(family_panel) # we should never see reassignment of gameobjects! gameobjects = { "room": r, "player": p, "hive": h, "camera": c, "world": world, "screen": screen, "info_panel": info_panel, } info_panel.children.append(StatisticsPanel(gameobjects)) while not close(r): # Main game loop # Don't need cancel and quit works if time_to_quit: try: print "Quitting indirectly at main loop. Saving room..." game_progress.save_game(r) break except Exception: print "Failed to save" framecount += 1 test.begin_timing(test.segs, test.segdescriptors) key_presses = pygame.event.get(pygame.KEYDOWN) key_states = pygame.key.get_pressed() if previous_key_states: key_ups = [old and not new for new, old in zip(key_states, previous_key_states)] else: key_ups = [0 for x in key_states] previous_key_states = key_states[:] time_gap = handle_player_input(key_presses, key_ups, key_states, gameobjects) r = gameobjects["room"] c = gameobjects["camera"] h = gameobjects["hive"] world = gameobjects["world"] screen = gameobjects["screen"] p = gameobjects["player"] if time_gap: clock.tick(400) dt = 0 mod = 20 # each bee updates once every mod frames """Update""" for i, bee in enumerate(r.bees): bee.slow = 1 # (i + framecount) % mod test.add_sticky("main:playerupdate") p.update(dt, key_states, key_presses) test.remove_sticky("main:playerupdate") for phys in r.food + r.bullets: phys.update(dt, key_states, key_presses) test.add_sticky("bee") for b in r.bees: b.update(dt, key_states, key_presses) if b.request_family_tree_update: updatefamilytree = 1 b.request_family_tree_update = 0 test.remove_sticky("bee") screen.fill([0, 0, 0]) if settings[SHOW_FAMILY_TREE]: test.add_sticky("tree") # draw every frame, since the tree follows the player around if settings[SPECIES_STYLE] == 3: if not framecount % settings[TREE_UPDATE_TIME]: myspeciesplot.update(r.bees + r.deadbees) for b in r.deadbees: if b.dead == 2: r.deadbees.remove(b) myspeciesplot.draw( world, (int(p.xy[0, 0]) - myspeciesplot.w / 2, int(p.xy[0, 1]) - myspeciesplot.h / 2) ) else: # update once every few frames if not framecount % settings[TREE_UPDATE_TIME]: myspeciesplot.update(r.bees + r.deadbees) myspeciesplot.draw(screen, (840, 0)) for b in r.deadbees: if b.dead == 2: r.deadbees.remove(b) updatefamilytree = 0 if updatefamilytree: myfamilytree.update(r.bees) myfamilytree.draw(screen, (840, 0)) test.remove_sticky("tree") test.add_sticky("room") # Necessarily comes afterwards so that the bees can see the player r.update() test.remove_sticky("room") """ if r.signal_new_tree: r.signal_new_tree = 0 myfamilytree.depth += 2*settings[TREE_V_SPACING] test.remove_sticky('tree') ########## """ test.add_sticky("camera_update") c.follow_player(dt) # Here so that room knows what to draw c.updatesight() test.remove_sticky("camera_update") test.add_sticky("main:drawing") test.add_sticky("main:drawing:test") test.draw(world, r) test.remove_sticky("main:drawing:test") test.add_sticky("main:drawing:bee") for x in r.bees: x.draw(world) test.remove_sticky("main:drawing:bee") test.add_sticky("main:drawing:other") for x in r.food + [p] + r.bullets: x.draw(world) test.remove_sticky("main:drawing:other") # Time dt = clock.tick(120) # used to be 120 # Make it seem like a slowed down version of 22fps if necessary dt = min(dt, 45) # print dt, "this is dt" test.add_sticky("main:drawing:camera") c.draw() test.remove_sticky("main:drawing:camera") info_panel.draw_to(screen) """ seconds = pygame.time.get_ticks() / 1000 t0 = "" if settings[SPECIES_STYLE] == 1: t0 += "Plotted on right: x: horizontal movement, y: generation" elif settings[SPECIES_STYLE] == 2: t0 += "Plotted on right: x: generation, y: vertical movement" elif settings[SPECIES_STYLE] == 3: t0 += "angle: direction, radius: generation" t.permanent_text = [t0] ta = "Time: " + str(seconds) tb = " | current bees: " + str(len(r.bees)) tbb = " | total dead bees " + str(len(r.deadbees)) tc = " |" + str(int(clock.get_fps()))+"fps" t.permanent_text += [ ta + tb + tbb + tc,] if settings[SHOW_HELP]: t.permanent_text += [ "click anywhere for options", "plotted on right: Recent lifetimes, max is %s" % (max(t.data) if t.data else "not defined"), "[a]: %s birth and deaths" % ("resume" if r.stasis else "pause"), "[g]: generate bees", "[e]: visualize paths of a random bee", "[r]: %s eyes" % ("hide" if settings[SHOW_EYES] else "show"), "[n]: %s names" % ("hide" if settings[SHOW_NAMES] else "show"), "[m]: %s visual madness" % ("decrease" if r.madness == 2 else "increase"), "[SPACE]: teleport to a random position", "[t]: turn %s random map generation" % ("off" if settings[GENERATE_RANDOM_MAP] else "on"), ] t.permanent_text.append("[h]: %s help" % ("hide" if settings[SHOW_HELP] else "show")) t.draw(screen)""" test.add_sticky("main:drawing:displayflip") pygame.display.flip() test.remove_sticky("main:drawing:displayflip") test.remove_sticky("main:drawing") for phys in r.bees + r.food + [p]: phys.visible = c.can_see(phys) test.summarizetimings(test.segs, test.segdescriptors) # if framecount % 30 == 0: # print int(clock.get_fps()), "fps" pygame.event.pump()