def __init__(self, image_filename, data_filename, extra_names=True): if extra_names: extra_names = ('_normal', '_occlude', '_displace') extra_names = [ image_filename[:-4] + extra + image_filename[-4:] for extra in extra_names ] else: extra_names = [] self.texture = Texture(image_filename, *extra_names) self.subimages = {} #data_filename = os.path.join(globals.dirs.resource,data_filename) with open(data_filename, 'rb') as f: for line in f: subimage_name,\ image_name ,\ x ,\ y ,\ w ,\ h = line.strip().split(':') #print image_name,image_filename #assert(image_name) == image_filename w = int(w) h = int(h) if subimage_name.startswith('font_'): subimage_name = chr(int(subimage_name[5:7], 16)) h -= 4 subimage_name = '_'.join(subimage_name.split('/')) self.subimages[subimage_name] = SubImage( Point( float(x) / self.texture.width, float(y) / self.texture.height), (Point(w, h)))
def PhysUpdate(self): if self.dead: return if self.squirting: if not self.UpdateLevel(-1): self.StopSquirting() return thrust = -0.5 vector = cmath.rect(thrust, self.GetDirection()) point_phys = self.parent.body.GetWorldPoint(self.middle.to_vec()) point_screen = Point( *point_phys) / self.parent.physics.scale_factor self.parent.body.ApplyForce( (vector.real, vector.imag), self.parent.body.GetWorldPoint(self.middle.to_vec())) if len(self.squirters) < 100: angle = self.GetDirection() + (random.random() - 0.5) * self.squirt_range distance = random.random( ) * self.squirt_distance + self.min_squirt_distance vector = cmath.rect(distance, angle) vector = Point(vector.real, vector.imag) start = point_screen self.squirters.append(Squirt(start, vector, 1000)) #Always update the squirters even if not squirting self.squirters = [ squirt for squirt in self.squirters if squirt.Update() == True ] for i, vertex in enumerate(self.shape.vertices): screen_coords = Point(*self.parent.body.GetWorldPoint( vertex)) / self.parent.physics.scale_factor self.quad.vertex[self.parent.vertex_permutation[i]] = ( screen_coords.x, screen_coords.y, self.z_level)
def __init__(self,parent,gameview,computer,background,foreground): bl = Point(13,13).to_float()/parent.absolute.size tr = (Point(1,1) - bl) super(Emulator,self).__init__(parent,bl,tr) self.background_colour = background self.foreground_colour = foreground self.scale = 3 self.gameview = gameview self.computer = computer self.text_buffer = '' self.last = 0 self.size = (self.absolute.size/(globals.text_manager.GetSize(' ',self.scale).to_float())).to_int() self.quads = [] for x in xrange(self.size.x): col = [] for y in xrange(self.size.y): q = globals.text_manager.Letter(' ',drawing.texture.TextTypes.SCREEN_RELATIVE,self.foreground_colour) bl = (Point(x,self.size.y - 1 - y).to_float())/self.size tr = (Point(x+1,self.size.y - y).to_float())/self.size q.SetVertices(self.GetAbsolute(bl),self.GetAbsolute(tr),drawing.constants.DrawLevels.ui + self.level + 1) col.append(q) self.quads.append(col) self.cursor_flash = None self.cursor_flash_state = False self.current_buffer = [] self.cursor = Point(0,0) self.start = None self.AddMessage(self.GetBanner())
def __init__(self, parent): self.parent = parent self.blurb = self.blurb self.blurb_text = None pygame.mixer.music.load('end_music.ogg') pygame.mixer.music.play(-1) pygame.mixer.music.set_volume(0.6) self.handlers = { TitleStages.TEXT: self.TextDraw, TitleStages.SCROLL: self.Wait, TitleStages.WAIT: self.Wait } self.backdrop = ui.Box(parent=globals.screen_root, pos=Point(0, 0), tr=Point(1, 1), colour=(0, 0, 0, 0.6)) bl = Point(0.3, 0.5) tr = Point(0.7, 0.7) self.blurb_text = ui.TextBox( parent=globals.screen_root, bl=bl, tr=tr, text=self.blurb, textType=drawing.texture.TextTypes.SCREEN_RELATIVE, scale=3) self.start = None self.blurb_text.EnableChars(0) self.stage = TitleStages.TEXT self.played_sound = False self.skipped_text = False self.letter_duration = 20 self.continued = False
def __init__(self, parent): self.parent = parent self.blurb = self.blurb self.blurb_text = None self.handlers = { TitleStages.TEXT: self.TextDraw, TitleStages.SCROLL: self.Wait, TitleStages.WAIT: self.Wait } self.backdrop = ui.Box(parent=globals.screen_root, pos=Point(0, 0), tr=Point(1, 1), colour=(0, 0, 0, 0.6)) bl = self.parent.GetRelative(Point(0, 0)) tr = bl + self.parent.GetRelative(globals.screen) self.blurb_text = ui.TextBox( parent=globals.screen_root, bl=bl, tr=tr, text=self.blurb, textType=drawing.texture.TextTypes.SCREEN_RELATIVE, scale=3) self.start = None self.blurb_text.EnableChars(0) self.stage = TitleStages.TEXT self.played_sound = False self.skipped_text = False self.letter_duration = 20 self.continued = False
def __init__(self,parent,bl,tr,text,scale,colour = None,textType = drawing.texture.TextTypes.SCREEN_RELATIVE,alignment = drawing.texture.TextAlignments.LEFT): if tr == None: #If we're given no tr; just set it to one row of text, as wide as it can get without overflowing #the parent self.shrink_to_fit = True text_size = (globals.text_manager.GetSize(text,scale).to_float()/parent.absolute.size) margin = Point(text_size.y*0.06,text_size.y*0.15) tr = bl + text_size + margin*2 #Add a little breathing room by using 2.1 instead of 2 #We'd like to store the margin relative to us, rather than our parent self.margin = margin/(tr-bl) else: self.shrink_to_fit = False super(TextBox,self).__init__(parent,bl,tr) if not self.shrink_to_fit: #In this case our margin is a fixed part of the box self.margin = Point(0.05,0.05) self.text = text self.current_enabled = len(self.text) self.scale = scale self.colour = colour self.text_type = textType self.alignment = alignment self.text_manager = globals.text_manager self.ReallocateResources() #self.quads = [self.text_manager.Letter(char,self.text_type) for char in self.text] self.viewpos = 0 #that sets the texture coords for us self.Position(self.bottom_left,self.scale,self.colour) self.Enable()
def SetVertices(self): for i in xrange(4): self.hover_quads[i].SetColour((1,0,0,1)) #top bar self.hover_quads[0].SetVertices(Point(self.absolute.bottom_left.x,self.absolute.top_right.y-self.line_width), self.absolute.top_right, drawing.constants.DrawLevels.ui+1) #right bar self.hover_quads[1].SetVertices(Point(self.absolute.top_right.x-self.line_width,self.absolute.bottom_left.y), self.absolute.top_right, drawing.constants.DrawLevels.ui+1) #bottom bar self.hover_quads[2].SetVertices(self.absolute.bottom_left, Point(self.absolute.top_right.x,self.absolute.bottom_left.y+self.line_width), drawing.constants.DrawLevels.ui+1) #left bar self.hover_quads[3].SetVertices(self.absolute.bottom_left, Point(self.absolute.bottom_left.x+self.line_width,self.absolute.top_right.y), drawing.constants.DrawLevels.ui+1) if not self.enabled: for i in xrange(4): self.hover_quads[i].Disable()
def __init__(self, physics, bl, angle=0): self.dead = False self.arms = [] self.selected = False self.unset = None self.fire_extinguisher = None self.push_start = None self.squirting = False self.subimage = globals.atlas.SubimageSprite(self.texture_name) self.texture_coords = globals.atlas.TextureSpriteCoords( self.texture_name) self.selected_subimage = globals.atlas.SubimageSprite( self.selected_name) self.selected_texture_coords = globals.atlas.TextureSpriteCoords( self.selected_name) tr = bl + self.subimage.size super(Player, self).__init__(physics, bl, tr, self.texture_coords, angle) self.joints = [] self.other_obj = None self.filter_group = Player.filter_id Player.filter_id -= 1 self.resting_hand_positions = (self.midpoint * Point(0.8, 1), self.midpoint * Point(-0.8, 1)) self.current_hand_positions = self.resting_hand_positions self.shoulders = (self.midpoint * Point(0.8, 0), self.midpoint * Point(-0.8, 0)) self.arms = [ PlayerArm(self, (self, self.shoulders[0]), (self, self.resting_hand_positions[0])), PlayerArm(self, (self, self.shoulders[1]), (self, self.resting_hand_positions[1])) ]
def Init(): """Initialise everything. Run once on startup""" w,h = (1280,720) globals.tile_scale = Point(1,1) globals.scale = Point(3,3) globals.screen = Point(w,h)/globals.scale globals.screen_root = ui.UIRoot(Point(0,0),globals.screen) globals.quad_buffer = drawing.QuadBuffer(131072) globals.screen_texture_buffer = drawing.QuadBuffer(131072) globals.ui_buffer = drawing.QuadBuffer(131072) globals.nonstatic_text_buffer = drawing.QuadBuffer(131072) globals.colour_tiles = drawing.QuadBuffer(131072) globals.mouse_relative_buffer = drawing.QuadBuffer(1024) globals.line_buffer = drawing.LineBuffer(16384) globals.tile_dimensions = Point(16,16)*globals.tile_scale globals.sounds = sounds.Sounds() globals.zoom_scale = None globals.dirs = globals.types.Directories('resource') pygame.init() screen = pygame.display.set_mode((w,h),pygame.OPENGL|pygame.DOUBLEBUF) pygame.display.set_caption('The Gosh Signal') drawing.Init(globals.screen.x,globals.screen.y) globals.text_manager = drawing.texture.TextManager()
def avoid_light_old(self, player_diff, player_distance): #Get the brightness at a few points and go in the direction that it's #Use green light for some reason elapsed = globals.time - self.last_random if elapsed < self.random_segments: return self.last_random = globals.time self.fleeing = True sp = self.screen_pos self.pixel_data = glReadPixels(sp.x - self.width * 2, sp.y - self.width * 2, self.width * 4, self.height * 4, GL_RGB, GL_FLOAT)[:, :, 1:3] max_index = numpy.argmax(self.pixel_data[:, :, 1:2]) min_index = numpy.argmin(self.pixel_data[:, :, 1:2]) indices = numpy.unravel_index((max_index, min_index), self.pixel_data.shape) max_index = indices[0][0], indices[1][0], indices[2][0] min_index = indices[0][1], indices[1][1], indices[2][1] #print 'max=',max_index,self.pixel_data[max_index] #print 'test',self.pixel_data[indices] d = Point(indices[0][0] - indices[0][1], indices[1][0] - indices[1][1]).unit_vector() if d.length() == 0: self.seek_player(player_diff, player_distance) self.move_direction *= -1 self.move_direction = d.unit_vector() * self.speed
def Update(self,t): self.angle = (self.parent.angle + math.pi*0.5)%(2*math.pi) box = (globals.tile_scale*Point(self.width,self.height)) bl = Point(*self.pos[:2]) - box*0.5 tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4)
def SetPointer(self): offset = self.offsets[self.index] pointer_bl = Point(offset,0.3) - (Point(2,10)/self.clickable_area.absolute.size) pointer_tr = pointer_bl + (Point(7,14)/self.clickable_area.absolute.size) self.pointer_ui.SetBounds(pointer_bl,pointer_tr) self.pointer_quad.SetVertices(self.pointer_ui.absolute.bottom_left,self.pointer_ui.absolute.top_right,self.uilevel + 0.1) self.pointer_quad.SetColour(self.pointer_colour)
class Clock(object): range = math.pi * 2 * 0.77 start = math.pi / 4 name = 'clock.png' hour_hand_name = 'hour_hand.png' minute_hand_name = 'minute_hand.png' start_pos = Point(0.8, 0.81) centre = Point(16, 16) hour_hand_coords = ((-1, -1), (-1, 6), (1, 6), (1, -1)) minute_hand_coords = ((-0.5, -1), (-0.5, 13), (0.5, 13), (0.5, -1)) seconds_to_hours = 0.01 def __init__(self, train, initial_level=0.0): self.train = train self.quad = drawing.Quad(globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords( self.name)) self.size = globals.atlas.SubimageSprite(self.name).size self.hour_hand_quad = drawing.Quad( globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords(self.hour_hand_name)) self.hour_hand_size = globals.atlas.SubimageSprite( self.hour_hand_name).size self.minute_hand_quad = drawing.Quad( globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords(self.minute_hand_name)) self.minute_hand_size = globals.atlas.SubimageSprite( self.minute_hand_name).size bl = self.start_pos * globals.screen tr = bl + self.size self.pos = bl self.hour_hand_pos = bl + self.centre self.minute_hand_pos = bl + self.centre self.quad.SetVertices(bl, tr, 5.4) self.Update(0) def set_dial(self, hour, minute): hour_angle = -2 * math.pi * float(hour) / 12 minute_angle = -2 * math.pi * float(minute) / 60 for quad, coords, angle in ((self.hour_hand_quad, self.hour_hand_coords, hour_angle), (self.minute_hand_quad, self.minute_hand_coords, minute_angle)): vertices = [0, 0, 0, 0] for i, coord in enumerate(coords): p = coord[0] + coord[1] * 1j distance, old_angle = cmath.polar(p) c = cmath.rect(distance, old_angle + angle) vertices[i] = self.pos + self.centre + Point(c.real, c.imag) quad.SetAllVertices(vertices, 5.5 + i + 1) def Update(self, elapsed): time = self.train.parent.start_time_hours + self.seconds_to_hours * float( globals.time - self.train.parent.start_time) / 1000 minutes = (time % 1.0) * 60 hours = time % 12 self.set_dial(hours, minutes)
def set_pos(self, pos): self.world_pos = pos pos = pos * globals.tile_dimensions self.pos = (pos.x, pos.y, self.z) box = (globals.tile_scale * Point(self.width, self.height)) bl = Point(*self.pos[:2]) - box * 0.5 tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl, tr, 4)
def SetSelected(self, n): if n < 0: n = 0 if n > 3: n = 3 self.selected = n self.screen.selected.bottom_left = Point(self.selected * 0.25, -0.05) self.screen.selected.top_right = Point((self.selected + 1) * 0.25, 0.15) self.screen.selected.UpdatePosition()
def set_pos(self,pos): self.world_pos = pos pos = pos*globals.tile_dimensions self.pos = (pos.x,pos.y,self.z) box = (globals.tile_scale*Point(self.width,self.height)) bl = Point(*self.pos[:2]) - box*0.5 tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4)
def __init__(self): self.dish_door = None self.atlas = globals.atlas = drawing.texture.TextureAtlas( 'tiles_atlas_0.png', 'tiles_atlas.txt') self.map = GameMap('level1.txt', self) self.map.world_size = self.map.size * globals.tile_dimensions self.viewpos = Viewpos(Point(915, 0)) self.player_direction = Point(0, 0) self.game_over = False self.computer = None self.info_box = ui.Box(parent=globals.screen_root, pos=Point(0, 0), tr=Point(1, 0.05), colour=(0, 0, 0, 0.9)) self.info_box.text = ui.TextBox( self.info_box, bl=Point(0, 0), tr=Point(1, 0.7), text='Space to interact, I for inventory, DEL to toggle music', textType=drawing.texture.TextTypes.SCREEN_RELATIVE, colour=(1, 1, 0, 1), scale=3, alignment=drawing.texture.TextAlignments.CENTRE) self.info_box.Disable() #pygame.mixer.music.load('music.ogg') self.music_playing = False super(GameView, self).__init__(Point(0, 0), globals.screen) #skip titles for development of the main game self.mode = modes.Titles(self) #self.mode = modes.LevelOne(self) super(GameView, self).__init__(Point(0, 0), Point(*self.map.world_size))
def __init__(self,parent,bl,tr,points,callback): super(Slider,self).__init__(parent,bl,tr) self.points = sorted(points,lambda x,y:cmp(x[0],y[0])) self.callback = callback self.lines = [] self.uilevel = utils.ui_level+1 self.enabled = False self.clickable_area = UIElement(self,Point(0.05,0),Point(0.95,1)) line = drawing.Quad(globals.ui_buffer) line_bl = self.clickable_area.absolute.bottom_left + self.clickable_area.absolute.size*Point(0,0.3) line_tr = line_bl + self.clickable_area.absolute.size*Point(1,0) + Point(0,2) line.SetVertices(line_bl,line_tr,self.uilevel) line.Disable() low = self.points[ 0][0] high = self.points[-1][0] self.offsets = [float(value - low)/(high-low) if low != high else 0 for value,index in self.points] self.lines.append(line) self.index = 0 self.pointer_quad = drawing.Quad(globals.ui_buffer) self.pointer_colour = (1,0,0,1) self.lines.append(self.pointer_quad) self.pointer_ui = UIElement(self.clickable_area,Point(0,0),Point(0,0)) self.SetPointer() self.pointer_quad.Disable() self.dragging = False #now do the blips for offset in self.offsets: line = drawing.Quad(globals.ui_buffer) line_bl = self.clickable_area.absolute.bottom_left + Point(offset,0.3)*self.clickable_area.absolute.size line_tr = line_bl + self.clickable_area.absolute.size*Point(0,0.2) + Point(2,0) line.SetVertices(line_bl,line_tr,self.uilevel) line.Disable() self.lines.append(line)
def set_vertices(self): if self.parent.incline == 0: return self.quad.SetVertices(self.pos, self.pos + self.size, 0.2) bl = self.pos - globals.rotation_offset tr = bl + self.size vertices = [0, 0, 0, 0] for (i, coord) in enumerate((Point(bl.x, bl.y), Point(bl.x, tr.y), Point(tr.x, tr.y), Point(tr.x, bl.y))): vertices[i] = globals.rotation_offset + coord.Rotate( self.parent.incline) self.quad.SetAllVertices(vertices, 0.2)
def __init__(self, name, parent): self.size = Point(120, 50) self.data = [[TileTypes.GRASS for i in xrange(self.size.y)] for j in xrange(self.size.x)] self.object_cache = {} self.object_list = [] self.actors = [] self.doors = [] self.player = None self.parent = parent y = self.size.y - 1 player_pos = None with open(name) as f: last = None for line in f: line = line.strip('\n') if len(line) < self.size.x: line += ' ' * (self.size.x - len(line)) if len(line) > self.size.x: line = line[:self.size.x] for inv_x, tile in enumerate(line[::-1]): x = self.size.x - 1 - inv_x #try: if 1: #hack, also give the adjacent tile so we know what kind of background to put it on... td = TileDataFactory(self, self.input_mapping[tile], Point(x, y), last, parent) last = self.input_mapping[tile] for tile_x in xrange(td.size.x): for tile_y in xrange(td.size.y): if self.data[x + tile_x][ y + tile_y] != TileTypes.GRASS: self.data[x + tile_x][y + tile_y].Delete() self.data[x + tile_x][y + tile_y] = TileTypes.GRASS if self.data[x + tile_x][ y + tile_y] == TileTypes.GRASS: self.data[x + tile_x][y + tile_y] = td if self.input_mapping[tile] == TileTypes.PLAYER: player_pos = Point(x + 0.2, y) if self.input_mapping[tile] == TileTypes.ENEMY: self.parent.enemy_positions.append( Point(x + 0.2, y)) #except KeyError: # raise globals.types.FatalError('Invalid map data') y -= 1 if y < 0: break if not player_pos: raise Exception('No player defined') self.player = actors.Player(self, player_pos) self.actors.append(self.player)
def Update(self): vertices = [] for i, (obj, vertex) in enumerate( ((self.start_object, self.start_pos - Point(0.1, 0)), (self.start_object, self.start_pos + Point(0.1, 0)), (self.end_object, self.end_pos + Point(0.1, 0)), (self.end_object, self.end_pos - Point(0.1, 0)))): screen_coords = Point(*obj.body.GetWorldPoint( vertex.to_vec())) / self.parent.physics.scale_factor self.quad.vertex[i] = (screen_coords.x, screen_coords.y, self.z_level)
class PressureGauge(object): range = math.pi * 2 * 0.77 start = math.pi / 4 name = 'pressure.png' arrow_name = 'arrow.png' start_pos = Point(-0.02, 0.72) wobble = 0.2 centre = Point(24, 32) arrow_coords = ((-11, -3), (-11, 3), (9, 3), (9, -3)) def __init__(self, train, initial_level=0.0): self.train = train self.quad = drawing.Quad(globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords( self.name)) self.size = globals.atlas.SubimageSprite(self.name).size self.arrow_quad = drawing.Quad(globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords( self.arrow_name)) self.arrow_size = globals.atlas.SubimageSprite(self.arrow_name).size bl = self.start_pos * globals.screen tr = bl + self.size self.pos = bl self.arrow_pos = bl + self.centre self.quad.SetVertices(bl, tr, 5.4) self.Update(initial_level, 0) def set_dial(self): new_angle = -self.level * self.range + self.start vertices = [0, 0, 0, 0] for i, coord in enumerate(self.arrow_coords): p = coord[0] + coord[1] * 1j distance, old_angle = cmath.polar(p) c = cmath.rect(distance, old_angle + new_angle) vertices[i] = self.arrow_pos + Point(c.real, c.imag) self.arrow_quad.SetAllVertices(vertices, 5.5) def Update(self, level, elapsed): self.level = level if level < 0.05: #no wobble pass elif level < 0.5: self.level += self.wobble * random.random() * elapsed if level > 0.5: self.level += self.wobble * random.random() * elapsed * 20 * ( level - 0.5) if self.level < 0: self.level = 0 if self.level > 1: self.level = 1.0 self.set_dial()
def NewLight(self): row = self.current_size / self.num_points light = Quad(self) #Now set the vertices for the next line ... bl = Point(0, row) tr = Point(globals.screen_abs.x, (row + 1)) print bl, ':', tr #bl = Point(0,0) #tr = Point(drawing.opengl.ShadowMapBuffer.WIDTH,drawing.opengl.ShadowMapBuffer.HEIGHT) light.SetVertices(bl, tr, row) light.shadow_index = row return light
def AdjustZoom(self,amount,pos): pos_coords = self.viewpos.Get() + (pos/self.zoom) oldzoom = self.zoom self.zoom -= (amount/10.0) if self.zoom < self.min_zoom: self.zoom = self.min_zoom if self.zoom > self.max_zoom: self.zoom = self.max_zoom #if we've zoomed so far out that we can see an edge of the screen, fix that top_left= Point(0,globals.screen.y/self.zoom) top_right = globals.screen/self.zoom bottom_right = Point(globals.screen.x/self.zoom,0) new_viewpos = self.viewpos.Get() if new_viewpos.y < 0: new_viewpos.y = 0 if new_viewpos.x < 0: new_viewpos.x = 0 #now the top left new_top_right = new_viewpos+top_right if new_top_right.y > self.absolute.size.y: new_viewpos.y -= (new_top_right.y - self.absolute.size.y) if new_top_right.x > self.absolute.size.x: new_viewpos.x -= (new_top_right.x - self.absolute.size.x) try: if new_viewpos.y < 0: raise ValueError if new_viewpos.x < 0: raise ValueError #now the top left new_top_right = new_viewpos+top_right if new_top_right.y > self.absolute.size.y: raise ValueError if new_top_right.x > self.absolute.size.x: raise ValueError except ValueError: #abort! This is a bit shit but whatever self.zoom = oldzoom return new_pos_coords = self.viewpos.Get() + pos/self.zoom self.viewpos.Set(self.viewpos.Get() + (pos_coords - new_pos_coords)) self.ClampViewpos()
class CoalDial(PressureGauge): start_pos = Point(0.47, 0.85) name = 'dial.png' arrow_name = 'needle.png' wobble = 0.2 start = 0 centre = Point(16, 4) range = math.pi max_level = 4 arrow_coords = ((-11, -2), (-11, 2), (0, 3), (0, -3)) def Update(self, level, elapsed): level = float(level) / self.max_level super(CoalDial, self).Update(level, elapsed)
def update(self, t): self.t = t elapsed = t - self.last_update self.last_update = t if self.shake_end: if t >= self.shake_end: self.shake_end = None self.shake = Point(0, 0) else: left = (self.shake_end - t) / self.shake_duration radius = left * self.shake_radius self.shake = Point(random.random() * radius, random.random() * radius) if self.follow: #We haven't locked onto it yet, so move closer, and lock on if it's below the threshold fpos = (self.follow.GetPosCentre() * globals.tile_dimensions ).to_int() + globals.screen * Point(0, 0.03) if not fpos: return target = fpos - (globals.screen * 0.5).to_int() diff = target - self._pos #print diff.SquareLength(),self.follow_threshold direction = diff.direction() if abs(diff.x) < self.max_away.x and abs(diff.y) < self.max_away.y: adjust = diff * 0.02 * elapsed * 0.06 else: adjust = diff * 0.03 * elapsed * 0.06 #adjust = adjust.to_int() if adjust.x == 0 and adjust.y == 0: adjust = direction self._pos += adjust return elif self.target: if t >= self.target_time: self._pos = self.target self.NoTarget() if self.callback: self.callback(t) self.callback = None elif t < self.start_time: #I don't think we should get this return else: partial = float(t - self.start_time) / self.duration partial = partial * partial * (3 - 2 * partial) #smoothstep self._pos = (self.start_point + (self.target_change * partial)).to_int()
def set_coords(self): for (i, quad) in enumerate(self.quads): view_offset = Point((i - 2) * self.size.x + self.moved, 0) bl = self.pos - globals.rotation_offset + view_offset tr = bl + self.size vertices = [0, 0, 0, 0] for (j, coord) in enumerate((Point(bl.x, bl.y), Point(bl.x, tr.y), Point(tr.x, tr.y), Point(tr.x, bl.y))): vertices[j] = globals.rotation_offset + coord.Rotate( self.angle) quad.SetAllVertices(vertices, self.z)
def __init__(self, tex_coords, xoffset, yoffset, width, height, opacity=0): self.tex_coords = tex_coords sf = 1.05 self.outline_vertices = numpy.array( ((0, 0, 0), (0, height * sf, 0), (width * sf, height * sf, 0), (width * sf, 0, 0)), numpy.float32) self.width = width self.height = height self.size = Point(width, height) self.outline_size = self.size * sf self.offset = Point(xoffset, yoffset) self.opacity = opacity self.outline_offset = Point( float(self.width) / 40, float(self.height) / 40)
def SetVertices(self, bl, tr): #top bar self.quads[0].SetVertices(Point(bl.x, tr.y - self.line_width), tr, drawing.constants.DrawLevels.ui + 1) #right bar self.quads[1].SetVertices(Point(tr.x - self.line_width, bl.y), tr, drawing.constants.DrawLevels.ui + 1) #bottom bar self.quads[2].SetVertices(bl, Point(tr.x, bl.y + self.line_width), drawing.constants.DrawLevels.ui + 1) #left bar self.quads[3].SetVertices(bl, Point(bl.x + self.line_width, tr.y), drawing.constants.DrawLevels.ui + 1)
def __init__(self, train): self.train = train self.last_screech = 0 self.size = Point(64, 48) self.knob_quad = drawing.Quad(globals.screen_texture_buffer, tc=globals.atlas.TextureSpriteCoords( self.knob_name)) self.knob_coords = ((-30, -29), (-30, 19), (34, 19), (34, -29)) self.knob_settings = (0.45, 0.13, -0.25) bl = self.start_pos * globals.screen #tr = bl + self.size self.knob_pos = bl + Point(30, 29) self.pos = bl self.level = 0 self.Reset()
def SetPos(self,pos): self.pos = pos bl = pos * globals.tile_dimensions tr = bl + (globals.tile_scale*Point(self.width,self.height)) bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4)
def __init__(self,map,pos): self.map = map self.tc = globals.atlas.TextureSpriteCoords('%s.png' % self.texture) self.quad = drawing.Quad(globals.quad_buffer,tc = self.tc) self.size = Point(float(self.width)/16,float(self.height)/16) self.corners = self.size, Point(-self.size.x,self.size.y), Point(-self.size.x,-self.size.y), Point(self.size.x,-self.size.y) self.corners = [p*0.5 for p in self.corners] self.corners_polar = [(p.length(),((1+i*2)*math.pi)/4) for i,p in enumerate(self.corners)] self.radius_square = (self.size.x/2)**2 + (self.size.y/2)**2 self.radius = math.sqrt(self.radius_square) self.corners_euclid = [p for p in self.corners] self.current_sound = None self.last_update = None self.dead = False self.move_speed = Point(0,0) self.angle_speed = 0 self.move_direction = Point(0,0) self.pos = None self.last_damage = 0 self.health = self.initial_health self.interacting = None self.SetPos(pos) self.set_angle(3*math.pi/2) self.hand_offset = Point(0,self.size.y*1.1) self.track_quads = [] self.last_track = 0
def RemoveFromMap(self): if self.pos != None: bl = self.pos.to_int() tr = (self.pos + self.size).to_int() for x in xrange(bl.x, tr.x + 1): for y in xrange(bl.y, tr.y + 1): self.map.RemoveActor(Point(x, y), self)
def __init__(self,pos,size): #self.world_pos = pos self.pos = pos*globals.tile_dimensions self.size = size self.quad_buffer = drawing.QuadBuffer(4) self.quad = drawing.Quad(self.quad_buffer) self.colour = (0.2,0.2,0.2) self.on = True globals.uniform_lights.append(self) self.pos = (self.pos.x,self.pos.y,self.z) box = (self.size*globals.tile_dimensions) bl = Point(*self.pos[:2]) tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4)
def Move(self,amount): amount = Point(amount.x,amount.y) dir = None if amount.x > 0: dir = Directions.RIGHT elif amount.x < 0: dir = Directions.LEFT elif amount.y > 0: dir = Directions.UP elif amount.y < 0: dir = Directions.DOWN if dir != None and dir != self.dir: self.dir = dir self.quad.SetTextureCoordinates(self.dirs[self.dir]) #check each of our four corners for corner in self.corners: pos = self.pos + corner target_x = pos.x + amount.x if target_x >= self.map.size.x: amount.x = 0 target_x = pos.x elif target_x < 0: amount.x = -pos.x target_x = 0 target_tile_x = self.map.data[int(target_x)][int(pos.y)] if target_tile_x.type in game_view.TileTypes.Impassable: amount.x = 0 elif (int(target_x),int(pos.y)) in self.map.object_cache: obj = self.map.object_cache[int(target_x),int(pos.y)] if obj.Contains(Point(target_x,pos.y)): amount.x = 0 target_y = pos.y + amount.y if target_y >= self.map.size.y: amount.y = 0 target_y = pos.y elif target_y < 0: amount.y = -pos.y target_y = 0 target_tile_y = self.map.data[int(pos.x)][int(target_y)] if target_tile_y.type in game_view.TileTypes.Impassable: amount.y = 0 elif (int(pos.x),int(target_y)) in self.map.object_cache: obj = self.map.object_cache[int(pos.x),int(target_y)] if obj.Contains(Point(pos.x,target_y)): amount.y = 0 self.SetPos(self.pos + amount)
def Update(self,t): if self.last_update == None: self.last_update = globals.time return elapsed = globals.time - self.last_update self.last_update = globals.time if self.on: burned = elapsed * self.burn_rate self.adjust_level(-burned) else: restored = elapsed * self.restore_rate self.adjust_level(restored) box = (globals.tile_scale*Point(self.width,self.height)) bl = Point(*self.pos[:2]) - box*0.5 tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4)
def __init__(self,pos,angle,width): self.quad_buffer = drawing.QuadBuffer(4) self.quad = drawing.Quad(self.quad_buffer) self.shadow_quad = globals.shadow_quadbuffer.NewLight() self.shadow_index = self.shadow_quad.shadow_index self.colour = (1,1,1) self.initial_angle = angle self.angle = angle self.angle_width = width self.on = True pos = pos*globals.tile_dimensions self.world_pos = pos self.pos = (pos.x,pos.y,self.z) box = (globals.tile_scale*Point(self.width,self.height)) bl = Point(*self.pos[:2]) - box*0.5 tr = bl + box bl = bl.to_int() tr = tr.to_int() self.quad.SetVertices(bl,tr,4) globals.cone_lights.append(self)
def avoid_light_old(self, player_diff, player_distance): #Get the brightness at a few points and go in the direction that it's #Use green light for some reason elapsed = globals.time - self.last_random if elapsed < self.random_segments: return self.last_random = globals.time self.fleeing = True sp = self.screen_pos self.pixel_data = glReadPixels(sp.x-self.width*2,sp.y-self.width*2,self.width*4,self.height*4,GL_RGB,GL_FLOAT)[:,:,1:3] max_index = numpy.argmax(self.pixel_data[:,:,1:2]) min_index = numpy.argmin(self.pixel_data[:,:,1:2]) indices = numpy.unravel_index((max_index,min_index),self.pixel_data.shape) max_index = indices[0][0],indices[1][0],indices[2][0] min_index = indices[0][1],indices[1][1],indices[2][1] #print 'max=',max_index,self.pixel_data[max_index] #print 'test',self.pixel_data[indices] d = Point(indices[0][0]-indices[0][1],indices[1][0]-indices[1][1]).unit_vector() if d.length() == 0: self.seek_player(player_diff, player_distance) self.move_direction *= -1 self.move_direction = d.unit_vector()*self.speed
def PhysUpdate(self): super(SeekingMissile,self).PhysUpdate() #Apply a thrust in the direction of the target target_pos = self.target.GetPos() self.pos = self.GetPos() if not target_pos or not self.pos: return diff = target_pos - self.pos direction = self.GetAngle() + (math.pi/2) distance,angle = cmath.polar(complex(diff.x,diff.y)) #angle = (angle - (math.pi/2) - self.GetAngle())%(math.pi*2) angle = (angle - direction)%(math.pi*2) if angle < (math.pi): #need to turn right, but by how much? amount = angle/math.pi else: amount = -(2*math.pi - angle)/math.pi desired_av = 10*amount f = 1 - abs(amount) current_speed = Point(*self.body.linearVelocity) if f < 0.8 or current_speed.length() > 80: desired_velocity = 0 #Apply a force in the direction we're not going to slow us down force = Point(-current_speed.x,-current_speed.y) self.body.ApplyForce(tuple(force),self.body.position) else: desired_velocity = 1 thrust = 20 vector = cmath.rect(thrust,direction) self.body.ApplyForce((vector.real,vector.imag),self.body.position) torque = (desired_av - self.body.angularVelocity) self.body.ApplyTorque(torque)
def Move(self,t): if self.last_update == None: self.last_update = globals.time return elapsed = globals.time - self.last_update self.last_update = globals.time if self.attacking: return if self.on_ground() or self.on_ladder(): self.move_speed.x += self.move_direction.x*elapsed*0.03 if self.jumping and not self.jumped: self.move_speed.y += self.jump_amount self.jumped = True self.move_speed.x *= 0.8*(1-(elapsed/1000.0)) if self.ladder and not self.above_ladder(): self.ladder = False if self.ladder or (self.on_ladder() and self.move_direction.y != 0): #no gravity on the ladder self.ladder = True self.move_speed.y = self.move_direction.y else: self.move_speed.y += globals.gravity*elapsed*0.03 amount = Point(self.move_speed.x*elapsed*0.03,self.move_speed.y*elapsed*0.03) self.walked += amount.x dir = None if amount.x > 0: dir = Directions.RIGHT elif amount.x < 0: dir = Directions.LEFT if dir != None and dir != self.dir: self.dir = dir self.dirs[self.dir][self.weapon.type].SetStart(self.walked) if abs(amount.x) < 0.0001: self.still = True amount.x = 0 self.move_speed.x = 0 else: self.still = False self.quad.SetTextureCoordinates(self.dirs[self.dir][self.weapon.type].GetTc(self.still,self.walked)) if self.still: self.ResetWalked() #check each of our four corners for corner in self.corners: pos = self.pos + corner target_x = pos.x + amount.x target_y = pos.y + amount.y if target_x >= self.map.size.x: target_x = self.map.size.x-self.threshold amount.x = target_x - pos.x elif target_x < 0: amount.x = -pos.x target_x = 0 target_tile_x = self.map.data[int(target_x)][int(pos.y)] if target_tile_x.type in game_view.TileTypes.Impassable: if amount.x > 0: amount.x = (int(target_x)-pos.x-self.threshold) else: amount.x = (int(target_x)+1-pos.x+self.threshold) target_x = pos.x + amount.x self.TriggerCollide(None) elif (int(target_x),int(pos.y)) in self.map.object_cache: obj = self.map.object_cache[int(target_x),int(pos.y)] if obj.Contains(Point(target_x,pos.y)): if amount.x > 0: amount.x = (int(target_x)-pos.x-self.threshold) else: amount.x = (int(target_x)+1-pos.x+self.threshold) target_x = pos.x + amount.x self.TriggerCollide(obj) else: for actor in target_tile_x.actors: if actor is self: continue if isinstance(actor,Bullet): actor.TriggerCollide(self) continue if isinstance(actor,Collectable): self.TriggerCollide(actor) continue if target_x >= actor.pos.x and target_x < actor.pos.x + actor.size.x and pos.y >= actor.pos.y and pos.y < actor.pos.y + actor.size.y: self.TriggerCollide(actor) if amount.x > 0: new_amount = (actor.pos.x-pos.x-self.threshold) else: new_amount = (actor.pos.x+actor.size.x-pos.x+self.threshold) if abs(new_amount - amount.x) < 0.2: amount.x = new_amount target_x = pos.x + amount.x break for corner_i,corner in enumerate(self.corners): pos = self.pos + corner target_y = pos.y + amount.y if target_y >= self.map.size.y: target_y = self.map.size.y-self.threshold amount.y = target_y - pos.y elif target_y < 0: amount.y = -pos.y target_y = 0 target_tile_y = self.map.data[int(pos.x)][int(target_y)] if target_tile_y.type in game_view.TileTypes.Impassable or not self.ladder and target_tile_y.type in game_view.TileTypes.LadderTops: if amount.y > 0: amount.y = (int(target_y)-pos.y-self.threshold) else: amount.y = (int(target_y)+1+self.threshold-pos.y) if amount.y < 0 and self.move_speed.y > 0: #hit our head print 'head' self.move_speed.y = 0 target_y = pos.y + amount.y self.TriggerCollide(None) elif (int(pos.x),int(target_y)) in self.map.object_cache: obj = self.map.object_cache[int(pos.x),int(target_y)] if obj.Contains(Point(pos.x,target_y)): if amount.y > 0: amount.y = (int(target_y)-pos.y-self.threshold) else: amount.y = (int(target_y)+1+self.threshold-pos.y) target_y = pos.y + amount.y self.TriggerCollide(obj) else: for actor in target_tile_y.actors: if actor is self: continue if isinstance(actor,Bullet): actor.TriggerCollide(self) continue if isinstance(actor,Collectable): self.TriggerCollide(actor) continue if target_y >= actor.pos.y and target_y < actor.pos.y + actor.size.y and pos.x >= actor.pos.x and pos.x < actor.pos.x + actor.size.x: if amount.y > 0: new_amount = (actor.pos.y-pos.y-self.threshold) else: new_amount = (actor.pos.y+actor.size.y-pos.y+self.threshold) if abs(new_amount) <= 0.0001 and abs(amount.y) > 0.0001: self.move_speed.y = 0 if (abs(new_amount) < 0.2): amount.y = new_amount target_y = pos.y + amount.y self.TriggerCollide(actor) break #self.move_speed.y = amount.y if amount.y == 0: self.move_speed.y = 0 self.SetPos(self.pos + amount)
def Move(self,t): if self.last_update == None: self.last_update = globals.time return elapsed = (globals.time - self.last_update)*globals.time_step self.last_update = globals.time angle_change = self.angle_speed*elapsed if 0 != self.required_turn: self.turned += abs(angle_change) self.set_angle(self.angle + angle_change) self.move_speed += self.move_direction.Rotate(self.angle)*elapsed if self.move_speed.SquareLength() > self.max_square_speed: self.move_speed = self.move_speed.unit_vector() * self.max_speed mp = self.mid_point().to_int() try: tile = self.map.data[mp.x][mp.y] if tile.type == game_view.TileTypes.ICE: friction = 0.002*elapsed if not globals.wee_played: globals.sounds.weee.play() globals.wee_played = True else: friction = 0.05*elapsed except IndexError: friction = 0.05*elapsed if friction: friction = self.move_speed.unit_vector()*friction if friction.SquareLength() < self.move_speed.SquareLength(): #self.move_speed *= 0.7*(1-(elapsed/1000.0)) self.move_speed -= friction else: self.move_speed = Point(0,0) if tile.type != game_view.TileTypes.ICE:#There's friction so also make some tracks if globals.time - self.last_track > 10 and self.move_speed.SquareLength() > 0.001 or abs(angle_change) > 0.001: self.last_track = globals.time quad = drawing.Quad(globals.quad_buffer,tc = globals.atlas.TextureSpriteCoords('tracks.png')) quad.SetAllVertices(self.vertices, 0.5) self.track_quads.append(quad) if len(self.track_quads) > 10000: q = self.track_quads.pop(0) q.Delete() if self.interacting: self.move_speed = Point(0,0) amount = self.move_speed * elapsed bl = self.pos.to_int() tr = (self.pos+self.size).to_int() for x in xrange(bl.x,tr.x+1): for y in xrange(bl.y,tr.y+1): try: for actor in self.map.data[x][y].actors: if actor is self: continue distance = actor.pos - self.pos if distance.SquareLength() < self.radius_square + actor.radius_square: overlap = self.radius + actor.radius - distance.length() adjust = distance.unit_vector()*-overlap amount += adjust*0.1 self.TriggerCollide(actor) #We've hit, so move us away from it's centre by the overlap except IndexError: pass #check each of our four corners for corner in self.corners: pos = self.pos + corner target_x = pos.x + amount.x if target_x >= self.map.size.x: amount.x = 0 target_x = pos.x elif target_x < 0: amount.x = -pos.x target_x = 0 target_tile_x = self.map.data[int(target_x)][int(pos.y)] if target_tile_x.type in game_view.TileTypes.Impassable: amount.x = 0 elif (int(target_x),int(pos.y)) in self.map.object_cache: obj = self.map.object_cache[int(target_x),int(pos.y)] if obj.Contains(Point(target_x,pos.y)): amount.x = 0 target_y = pos.y + amount.y if target_y >= self.map.size.y: amount.y = 0 target_y = pos.y elif target_y < 0: amount.y = -pos.y target_y = 0 target_tile_y = self.map.data[int(pos.x)][int(target_y)] if target_tile_y.type in game_view.TileTypes.Impassable: amount.y = 0 elif (int(pos.x),int(target_y)) in self.map.object_cache: obj = self.map.object_cache[int(pos.x),int(target_y)] if obj.Contains(Point(pos.x,target_y)): amount.y = 0 self.SetPos(self.pos + amount) if self.interacting: diff = self.interacting.pos + (self.interacting.size*0.5) - self.pos distance = diff.length() if distance > 2.5: self.deactivate()
def Move(self): if self.last_update is None: self.last_update = globals.time return elapsed = globals.time - self.last_update self.last_update = globals.time self.stance = Stances.STANDING if self.on_ground: if self.move_direction.y > 0: #sort of a jump self.move_speed.y += self.move_direction.y*0.5 self.move_direction.y = 0 self.crouch = False elif self.move_direction.y < 0: #crouching self.stance = Stances.CROUCH if self.stance != Stances.CROUCH: self.move_speed.x += self.move_direction.x*elapsed*0.03 else: self.move_speed.x += self.move_direction.x*elapsed*0.03*0.6 #Apply friction self.move_speed.x *= math.pow(0.7,(elapsed/20.0)) if self.gravity: self.move_speed.y += globals.gravity*elapsed*0.03 amount = Point(self.move_speed.x*elapsed*0.03,self.move_speed.y*elapsed*0.03) self.walked += amount.x if abs(amount.x) < 0.01: self.still = True self.walked = 0 amount.x = 0 self.move_speed.x = 0 if self.in_bow and globals.time < self.in_bow: new_animation = self.bowing[self.dir] else: self.in_bow = False new_animation = self.standing[self.dir][self.stance] else: self.still = False new_animation = self.walking[self.dir][self.stance] if self.transition_requested or self.end_frame is None: self.transition_requested = False #We can set the frame directly since we're not transitioning if new_animation is not self.current_animation: #we want to quickly transition to the first frame of the new animation new_animation.start = globals.time self.set_key_frame(new_animation.get_frame(globals.time,0),100) else: self.set_key_frame(self.current_animation.get_frame(globals.time,self.walked*24.0),0) self.current_animation = new_animation if self.punching: elapsed = globals.time - self.punching.start if elapsed > self.punching.damping: self.punching = False else: damping = 1.0 if elapsed > self.punching.duration: damping = (elapsed - self.punching.duration)/self.punching.damping_duration damping = 1.0 - damping #transition smoothly back to where it should be self.set_key_frame(self.punching.get_frame(globals.time - self.punching.start),0,damping=damping) target = self.pos + amount if target.y < 0: amount.y = -self.pos.y self.move_speed.y = 0 if target.x < 0: amount.x = -self.pos.x if target.x + self.size.x > globals.game_view.absolute.size.x: amount.x = globals.game_view.absolute.size.x - self.size.x - self.pos.x target = self.pos + amount if abs(target.y) < 0.1: self.on_ground = True else: self.on_ground = False self.set_pos(target)
def Position(self,pos,scale,colour = None,ignore_height = False): """Draw the text at the given location and size. Maybe colour too""" #set up the position for the characters. Note that we do everything here in size relative #to our text box (so (0,0) is bottom_left, (1,1) is top_right. self.pos = pos self.absolute.bottom_left = self.GetAbsoluteInParent(pos) self.scale = scale self.lowest_y = 0 row_height = (float(self.text_manager.font_height*self.scale*drawing.texture.global_scale)/self.absolute.size.y) #Do this without any kerning or padding for now, and see what it looks like cursor = Point(self.margin.x,-self.viewpos + 1 - row_height-self.margin.y) letter_sizes = [Point(float(quad.width *self.scale*drawing.texture.global_scale)/self.absolute.size.x, float(quad.height*self.scale*drawing.texture.global_scale)/self.absolute.size.y) for quad in self.quads] #for (i,(quad,letter_size)) in enumerate(zip(self.quads,letter_sizes)): i = 0 while i < len(self.quads): if i in self.newlines: i += 1 cursor.x = self.margin.x cursor.y -= row_height*1.2 continue quad,letter_size = self.quads[i],letter_sizes[i] if cursor.x + letter_size.x > (1-self.margin.x)*1.001: #This would take us over a line. If we're in the middle of a word, we need to go back to the start of the #word and start the new line there restart = False if quad.letter in ' \t': #It's whitespace, so ok to start a new line, but do it after the whitespace try: while self.quads[i].letter in ' \t': i += 1 except IndexError: break restart = True else: #look for the start of the word while i >= 0 and self.quads[i].letter not in ' \t': i -= 1 if i <= 0: #This single word is too big for the line. Shit, er, lets just bail break #skip the space i += 1 restart = True cursor.x = self.margin.x cursor.y -= row_height*1.2 if restart: continue if cursor.x == self.margin.x and self.alignment == drawing.texture.TextAlignments.CENTRE: #If we're at the start of a row, and we're trying to centre the text, then check to see how full this row is #and if it's not full, offset so that it becomes centred width = 0 for size in letter_sizes[i:]: width += size.x if width > 1-self.margin.x: width -= size.x break if width > 0: cursor.x += float(1-(self.margin.x*2)-width)/2 target_bl = cursor target_tr = target_bl + letter_size if target_bl.y < self.lowest_y: self.lowest_y = target_bl.y if target_bl.y < 0 and not ignore_height: #We've gone too far, no more room to write! break absolute_bl = self.GetAbsolute(target_bl) absolute_tr = self.GetAbsolute(target_tr) self.SetLetterVertices(i,absolute_bl, absolute_tr, drawing.texture.TextTypes.LEVELS[self.text_type]) if colour: quad.SetColour(colour) cursor.x += letter_size.x i += 1 #For the quads that we're not using right now, set them to display nothing for quad in self.quads[i:]: quad.SetVertices(Point(0,0),Point(0,0),-10) height = max([q.height for q in self.quads]) super(TextBox,self).UpdatePosition()
def Move(self,t): if self.last_update == None: self.last_update = globals.time return elapsed = (globals.time - self.last_update)*globals.time_step self.last_update = globals.time self.move_speed += self.move_direction*elapsed if self.move_speed.SquareLength() > self.max_square_speed: self.move_speed = self.move_speed.unit_vector() * self.max_speed friction = self.move_speed.unit_vector()*0.03*elapsed if friction.SquareLength() < self.move_speed.SquareLength(): #self.move_speed *= 0.7*(1-(elapsed/1000.0)) self.move_speed -= friction else: self.move_speed = Point(0,0) if self.interacting: self.move_speed = Point(0,0) amount = self.move_speed * elapsed bl = self.pos.to_int() tr = (self.pos+self.size).to_int() for x in xrange(bl.x,tr.x+1): for y in xrange(bl.y,tr.y+1): try: for actor in self.map.data[x][y].actors: if actor is self: continue distance = actor.pos - self.pos if distance.SquareLength() < self.radius_square + actor.radius_square: overlap = self.radius + actor.radius - distance.length() adjust = distance.unit_vector()*-overlap #print type(self),self.radius,actor.radius,distance.length(),overlap,adjust amount += adjust*0.1 self.TriggerCollide(actor) #We've hit, so move us away from it's centre by the overlap except IndexError: pass #check each of our four corners for corner in self.corners: pos = self.pos + corner target_x = pos.x + amount.x if target_x >= self.map.size.x: amount.x = 0 target_x = pos.x elif target_x < 0: amount.x = -pos.x target_x = 0 target_tile_x = self.map.data[int(target_x)][int(pos.y)] if target_tile_x.type in game_view.TileTypes.Impassable: amount.x = 0 elif (int(target_x),int(pos.y)) in self.map.object_cache: obj = self.map.object_cache[int(target_x),int(pos.y)] if obj.Contains(Point(target_x,pos.y)): amount.x = 0 target_y = pos.y + amount.y if target_y >= self.map.size.y: amount.y = 0 target_y = pos.y elif target_y < 0: amount.y = -pos.y target_y = 0 target_tile_y = self.map.data[int(pos.x)][int(target_y)] if target_tile_y.type in game_view.TileTypes.Impassable: amount.y = 0 elif (int(pos.x),int(target_y)) in self.map.object_cache: obj = self.map.object_cache[int(pos.x),int(target_y)] if obj.Contains(Point(pos.x,target_y)): amount.y = 0 self.SetPos(self.pos + amount) if self.interacting: diff = self.interacting.pos + (self.interacting.size*0.5) - self.pos distance = diff.length() if distance > 2.5: self.deactivate()
class Actor(object): texture = None width = None height = None threshold = 0.01 initial_health = 100 max_speed = 0.25 max_square_speed = max_speed**2 def __init__(self,map,pos): self.map = map self.tc = globals.atlas.TextureSpriteCoords('%s.png' % self.texture) self.quad = drawing.Quad(globals.quad_buffer,tc = self.tc) self.size = Point(float(self.width)/16,float(self.height)/16) self.corners = self.size, Point(-self.size.x,self.size.y), Point(-self.size.x,-self.size.y), Point(self.size.x,-self.size.y) self.corners = [p*0.5 for p in self.corners] self.corners_polar = [(p.length(),((1+i*2)*math.pi)/4) for i,p in enumerate(self.corners)] self.radius_square = (self.size.x/2)**2 + (self.size.y/2)**2 self.radius = math.sqrt(self.radius_square) self.corners_euclid = [p for p in self.corners] self.current_sound = None self.last_update = None self.dead = False self.move_speed = Point(0,0) self.move_direction = Point(0,0) self.pos = None self.last_damage = 0 self.health = self.initial_health self.interacting = None self.SetPos(pos) self.set_angle(3*math.pi/2) def RemoveFromMap(self): if self.pos != None: bl = self.pos.to_int() tr = (self.pos+self.size).to_int() for x in xrange(bl.x,tr.x+1): for y in xrange(bl.y,tr.y+1): self.map.RemoveActor(Point(x,y),self) def AdjustHealth(self,amount): self.health += amount if self.health > self.initial_health: self.health = self.initial_health if self.health < 0: #if self.dead_sound: # self.dead_sound.play() self.health = 0 self.dead = True self.Death() def damage(self, amount): if globals.time < self.last_damage + self.immune_duration: #woop we get to skip return self.last_damage = globals.time self.AdjustHealth(-amount) def SetPos(self,pos): self.RemoveFromMap() self.pos = pos self.vertices = [((pos + corner)*globals.tile_dimensions).to_int() for corner in self.corners_euclid] bl = pos tr = bl + self.size bl = bl.to_int() tr = tr.to_int() #self.quad.SetVertices(bl,tr,4) self.quad.SetAllVertices(self.vertices, 4) for x in xrange(bl.x,tr.x+1): for y in xrange(bl.y,tr.y+1): self.map.AddActor(Point(x,y),self) def TriggerCollide(self,other): pass def set_angle(self, angle): self.angle = angle self.corners_polar = [(p.length(),self.angle + ((1+i*2)*math.pi)/4) for i,p in enumerate(self.corners)] cnums = [cmath.rect(r,a) for (r,a) in self.corners_polar] self.corners_euclid = [Point(c.real,c.imag) for c in cnums] def Update(self,t): self.Move(t) def Move(self,t): if self.last_update == None: self.last_update = globals.time return elapsed = (globals.time - self.last_update)*globals.time_step self.last_update = globals.time self.move_speed += self.move_direction*elapsed if self.move_speed.SquareLength() > self.max_square_speed: self.move_speed = self.move_speed.unit_vector() * self.max_speed friction = self.move_speed.unit_vector()*0.03*elapsed if friction.SquareLength() < self.move_speed.SquareLength(): #self.move_speed *= 0.7*(1-(elapsed/1000.0)) self.move_speed -= friction else: self.move_speed = Point(0,0) if self.interacting: self.move_speed = Point(0,0) amount = self.move_speed * elapsed bl = self.pos.to_int() tr = (self.pos+self.size).to_int() for x in xrange(bl.x,tr.x+1): for y in xrange(bl.y,tr.y+1): try: for actor in self.map.data[x][y].actors: if actor is self: continue distance = actor.pos - self.pos if distance.SquareLength() < self.radius_square + actor.radius_square: overlap = self.radius + actor.radius - distance.length() adjust = distance.unit_vector()*-overlap #print type(self),self.radius,actor.radius,distance.length(),overlap,adjust amount += adjust*0.1 self.TriggerCollide(actor) #We've hit, so move us away from it's centre by the overlap except IndexError: pass #check each of our four corners for corner in self.corners: pos = self.pos + corner target_x = pos.x + amount.x if target_x >= self.map.size.x: amount.x = 0 target_x = pos.x elif target_x < 0: amount.x = -pos.x target_x = 0 target_tile_x = self.map.data[int(target_x)][int(pos.y)] if target_tile_x.type in game_view.TileTypes.Impassable: amount.x = 0 elif (int(target_x),int(pos.y)) in self.map.object_cache: obj = self.map.object_cache[int(target_x),int(pos.y)] if obj.Contains(Point(target_x,pos.y)): amount.x = 0 target_y = pos.y + amount.y if target_y >= self.map.size.y: amount.y = 0 target_y = pos.y elif target_y < 0: amount.y = -pos.y target_y = 0 target_tile_y = self.map.data[int(pos.x)][int(target_y)] if target_tile_y.type in game_view.TileTypes.Impassable: amount.y = 0 elif (int(pos.x),int(target_y)) in self.map.object_cache: obj = self.map.object_cache[int(pos.x),int(target_y)] if obj.Contains(Point(pos.x,target_y)): amount.y = 0 self.SetPos(self.pos + amount) if self.interacting: diff = self.interacting.pos + (self.interacting.size*0.5) - self.pos distance = diff.length() if distance > 2.5: self.deactivate() def GetPos(self): return self.pos def GetPosCentre(self): return self.pos def click(self, pos, button): pass def unclick(self, pos, button): pass @property def screen_pos(self): p = (self.pos*globals.tile_dimensions - globals.game_view.viewpos._pos)*globals.scale return p