def on_key_press(self, symbol, modifiers): if symbol == key.UP: self.thrustdir = self.thrustdir + v(0,2) if symbol == key.DOWN: self.thrustdir = self.thrustdir + v(0,-1) if symbol == key.LEFT: self.thrustdir = self.thrustdir + v(-1,0) if symbol == key.RIGHT: self.thrustdir = self.thrustdir + v(1,0) if symbol == key.Z: self.fire_bullet() if symbol == key.X: self.fire_laser() if symbol == key.C: self.fire_bomb()
def __init__(self, window): """ Initialize the gamescreen. window is the parent window. """ self.window = window self.width = window.width self.height= window.height self.draw_debug = False self.killcount = 0 self.total_time = 0 self.constants = {'drag':10, 'gravity':v(0,-30000), 'elasticity':0.7, 'friction':0.9, 'displace':0.7} opengl.glEnable(opengl.GL_BLEND) opengl.glBlendFunc(opengl.GL_SRC_ALPHA,opengl.GL_ONE) opengl.glLineWidth(2.0) # opengl.glEnable(opengl.GL_POINT_SMOOTH) # opengl.glHint(opengl.GL_POINT_SMOOTH_HINT,opengl.GL_NICEST) # opengl.glEnable(opengl.GL_LINE_SMOOTH) # opengl.glHint(opengl.GL_LINE_SMOOTH_HINT,opengl.GL_NICEST) # opengl.glEnable(opengl.GL_POLYGON_SMOOTH) # opengl.glHint(opengl.GL_POLYGON_SMOOTH_HINT,opengl.GL_NICEST) #Activate the depth buffer. opengl.glEnable(opengl.GL_DEPTH_TEST) #Lighting! #opengl.glEnable(opengl.GL_LIGHTING) #opengl.glEnable(opengl.GL_LIGHT0) #opengl.glLightf(opengl.GL_LIGHT0, opengl.GL_LINEAR_ATTENUATION, 0.05) ########### # Now, since this screen represents gameplay, we're going to initialize all the elements of the game we're playing. # For now, this is just a pile of stuff. ########### # Set up all the different lists of objects in the world. These roughly correspond to managers! Sort of. self.entities = [] self.physics_objects = [] self.collision_objects = [] self.nonstatic_objects = [] self.coltree = collision_structures.SpatialGrid() self.draw_objects = [] self.draw_priority = [] self.draw_tree = collision_structures.SpatialGrid() self.draw_tree.camera_rect = CollisionComponent(owner=None, pos=v(0,0), shape=shapes.Rectangle(-1,1,-1,1)) self.listeners = [] label = text.Label( 'THIS IS A TEST', 'Arial', 24, color = (0, 0, 0, 200), x = self.window.width/2, y = self.window.height/4, anchor_x="center", anchor_y="center", width=3*self.window.width/4, height=3*self.window.height/4, multiline=1) self.draw_objects.append(label) self.draw_priority.append(label)
def __init__(self, pscreen, location=v(0,0), endpoint=v(0,1), thick = 0,*args, **kwargs): self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Line(owner=self, vector=endpoint - location, thickness=thick) self.physics_component = PhysicsBody(owner=self, immobile=True) self.renderable_component = ShapeRenderer(owner=self) self.collision_component = Collider(owner=self)
def rectrect(me, you): separation = you.position_component.position - me.position_component.position x = compare_interval(me.xbounds, you.xbounds, separation.x) y = compare_interval(me.ybounds, you.ybounds, separation.y) if x is None or y is None: return None if abs(x) < abs(y): return v(x, 0) else: return v(0, y)
def perlin_2d(x, y, source=None, x_w=None, y_w=None, interpolate=None): """ Takes x and y coordinates and produces perlin noise, seeded by the 2d array `source` and using the 2d interpolation function interpolate. """ if source is None: source=r_2d if x_w is None: x_w = len(source)-1 if y_w is None: y_w = len(source[0])-1 if interpolate is None: interpolate=interpolate_2d p = v(x*x_w,y*y_w) i,j = int(p.x),int(p.y) # Don't need to use floor because these are assumed to be positive. c=[(i,j),(i,j+1),(i+1,j+1),(i+1,j)] corners = [source[u][w]*(p-v(u,w)) for (u,w) in c] output = interpolate(p-v(i,j), corners) return output
def update(self, timestep): if self.spawn_count > self.spawn_count_max: return if random.random() < self.spawn_chance: r = random.random()*self.shape.radius angle = random.random()*2*math.pi position = self.position_component.position + v(r*math.cos(angle), r*math.sin(angle)) newball = EnemyBall(self.lifecycle.parent_screen, location=position, rad=30) vel = random.uniform(0.0, self.max_velocity) angle = random.uniform(0.0, 2*math.pi) newball.physics_component.vel = v( vel*math.cos(angle), vel*math.sin(angle) ) self.lifecycle.parent_screen.add_entity(newball) self.spawn_count = self.spawn_count + 1
def __init__(self, pscreen, location=v(0,0)): self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.lifecycle.update = self.update self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=15) self.physics_component = PhysicsBody(owner=self) self.renderable_component = ShapeRenderer(owner=self, color=(0.0, 0.6, 0.0)) self.input_listeners = None #TODO: input listener component. self.collision_component = Collider(owner=self) self.thrust = 30000 self.thrustdir = v(0,0) self.player = True
def __init__(self, pscreen, parent,location=v(0,0), direction=v(0,1), length=1000): self.parent = parent self.bullet = True self.time_to_live = 0.5 self.time=0 self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.lifecycle.update = self.update self.position_component = PositionComponent(owner=self, position=location) self.shape=shapes.Line(owner=self, vector=direction*length) self.physics_component = PhysicsBody(owner=self, tangible=False, immobile=True) self.renderable_component = ShapeRenderer(owner=self, color=(0.0, 0.0, 1.0, 1.0)) self.collision_component = Collider(owner=self) self.collision_component.collides_with = lambda other: other is not self.parent self.collision_component.collide = self.collide
def update(self, timestep): if not self.immobile: if self.world_forces: self.acc += timestep * self.screen.constants["gravity"] self.acc -= timestep * self.screen.constants["drag"] * self.vel self.vel = self.vel + timestep * self.acc self.position_component.position += timestep * self.vel self.acc = v(0, 0)
def __init__(self, pscreen, location=v(0,0), rad=20): self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=rad, drawtype="3d") self.physics_component = PhysicsBody(owner=self, immobile=True) self.renderable_component = ShapeRenderer(owner=self) self.collision_component = Collider(owner=self)
def __init__(self, window, file_name): """ Initialize the gamescreen. window is the parent window. """ self.window = window self.width = window.width self.height= window.height self.draw_debug = False self.killcount = 0 self.total_time = 0 self.camera_rect = components.Collider(owner=None, shape=components.shapes.Rectangle(-1,1,-1,1)) self.constants = {'drag':10, 'gravity':v(0,-30000), 'elasticity':0.7, 'friction':0.9, 'displace':0.7} opengl.glEnable(opengl.GL_BLEND) opengl.glBlendFunc(opengl.GL_SRC_ALPHA, opengl.GL_ONE) opengl.glLineWidth(2.0) # opengl.glEnable(opengl.GL_POINT_SMOOTH) # opengl.glHint(opengl.GL_POINT_SMOOTH_HINT,opengl.GL_NICEST) # opengl.glEnable(opengl.GL_LINE_SMOOTH) # opengl.glHint(opengl.GL_LINE_SMOOTH_HINT,opengl.GL_NICEST) # opengl.glEnable(opengl.GL_POLYGON_SMOOTH) # opengl.glHint(opengl.GL_POLYGON_SMOOTH_HINT,opengl.GL_NICEST) #Activate the depth buffer. opengl.glEnable(opengl.GL_DEPTH_TEST) ########### # Now, since this screen represents gameplay, we're going to initialize all the elements of the game we're playing. # For now, this is just a pile of stuff. ########### # Set up all the different lists of objects in the world. These roughly correspond to managers! Sort of. self.entities = [] self.physics_objects = [] self.collision_objects = [] self.nonstatic_objects = [] self.coltree = collision_structures.SpatialGrid() self.draw_objects = [] self.draw_priority = [] self.draw_tree = collision_structures.SpatialGrid() self.draw_tree.camera_rect = self.camera_rect self.listeners = [] try: import importlib level_data = importlib.import_module("levels." + file_name) for item in level_data.generate(self): self.add_entity(item) except ImportError as e: print("Error loading the level " + file_name) raise e
def __init__(self, vector=v(1, 0), thickness=0, draw_type=None, num_points=9, depth=20, *args, **kwargs): super(Line, self).__init__(*args, **kwargs) self.name = SHAPE_LINE self.v = vector self.normal = self.v.rperp().unit() self.length = abs(vector) self.thickness = thickness self.angle = math.atan2(vector.y, vector.x) self.drawtype = draw_type # Build the vertex list. if thickness == 0: self.drawtype = draw_type or "oneline" self.vertex_list = pyglet.graphics.vertex_list(2, "v3f") self.vertex_list.vertices = [0, 0, 0, vector.x, vector.y, 0] else: self.drawtype = draw_type or "lines" self.vertex_list = pyglet.graphics.vertex_list(4 + 2 * num_points, "v3f") # For the record, here's the logic of this vertex-generation code: # We start at `thickness` distance out on the x-axis. Then, we travel up on the y-axis a distance of self.length. This is the first sidewall of the capsule shape. self.vertex_list.vertices[0 : d * 1] = [thickness, 0.0, 0.0] self.vertex_list.vertices[d * 1 : d * 2] = [thickness, self.length, 0.0] # Next, we draw the far end cap. # This starts at the specified thickness away from the end anchor of the line, pointing in the direction of the positive x-axis. It proceeds counterclockwise around until it arrives at the location on the other side of the x-axis. for i in range(num_points): self.vertex_list.vertices[d * 2 + d * i : d * 3 + d * i] = [ thickness * math.cos(math.pi * (i + 1) / num_points), self.length + thickness * math.sin(math.pi * (i + 1) / num_points), 0.0, ] # A vertical connection is next, vertically back down to the negative x-axis. self.vertex_list.vertices[d * (num_points + 2) : d * (num_points + 3)] = [-thickness, self.length, 0.0] self.vertex_list.vertices[d * (num_points + 3) : d * (num_points + 4)] = [-thickness, 0.0, 0.0] # And again we proceed in a half-circle, this time around the origin, to draw the near end cap. for i in range(num_points): self.vertex_list.vertices[d * (num_points + 4 + i) : d * (num_points + 4 + i + 1)] = [ -thickness * math.cos(math.pi * (i + 1) / num_points), -thickness * math.sin(math.pi * (i + 1) / num_points), 0.0, ] self.drawtype = "3d" self.vertex_lists_3d = make_3d(self.vertex_list, depth) # Define the bounds. self.xbounds = (min(0, vector.x) - thickness, max(0, vector.x) + thickness) self.ybounds = (min(0, vector.y) - thickness, max(0, vector.y) + thickness)
def __init__(self, pscreen, location=v(0,0), rad=30): self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=rad, drawtype="fill") self.physics_component = PhysicsBody(owner=self) self.renderable_component = ShapeRenderer(owner=self, color=(0.5,0.5,0.5)) self.collision_component = Collider(owner=self) self.collision_component.collide = self.collide self.enemy = True
def __init__(self, pscreen, location=v(0,0), rad=100, z=0.25): self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.lifecycle.update = self.update self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=rad, invert=0, drawtype="fill") self.renderable_component = ShapeRenderer(owner=self, z=z, color=(0.6, 0, 0.6, 0.4)) self.spawn_count = 0 self.spawn_count_max = 20 # Maximum number that will spawn before the spawner dies. self.spawn_chance = 0.01 # chance of spawning, per frame. self.max_velocity = 1000
def rescale_2d(source, m): x_old_w, y_old_w = len(source), len(source[0]) x_new_w, y_new_w = int(x_old_w*m), int(y_old_w*m) output = list() for inew in range(x_new_w): a = list() for jnew in range(y_new_w): x, y = 1.0*inew/x_new_w, 1.0*jnew/y_new_w iold, jold = int(x*x_old_w), int(y*y_old_w) c=[(iold,jold),(iold,jold+1),(iold+1,jold+1),(iold+1,jold)] a.append(interpolate_2d(v(x-1.0*iold/x_old_w, y-1.0*jold/y_old_w), [source[u][w] for (u,w) in c])) output.append(a) return output
def __init__( self, position_component=None, pos=None, vel=None, acc=None, shape=None, tangible=True, immobile=False, world_forces=True, *args, **keyword_args ): super().__init__(*args, **keyword_args) if position_component is None: if hasattr(self.owner, "position_component"): position_component = self.owner.position_component else: position_component = PositionComponent(owner=self.owner, position=(pos or v(0, 0))) self.position_component = position_component if shape is None: if hasattr(self.owner, "shape"): shape = self.owner.shape else: shape = shapes.Point() self.shape = shape if hasattr(self.owner, "lifecycle"): self.screen = self.owner.lifecycle.parent_screen self.vel = vel or v(0, 0) self.acc = acc or v(0, 0) self.tangible = tangible self.immobile = immobile self.world_forces = world_forces
def __init__(self, pscreen, parent, location=v(0,0)): self.parent = parent self.time_to_live=2 self.time=0 self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.lifecycle.update = self.update self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=8) self.physics_component = PhysicsBody(owner=self, pos=location) self.renderable_component = ShapeRenderer(owner=self, color=(0.0, 0.0, 0.0, 1.0)) self.collision_component = Collider(owner=self) self.collision_component.collides_with = lambda other: other is not self.parent
def __init__(self, pscreen, parent, location=v(0,0)): self.parent = parent self.time_to_live=0.5 self.time=0 self.lifecycle = Lifecycle(owner=self, screen=pscreen) self.lifecycle.update = self.update self.position_component = PositionComponent(owner=self, position=location) self.shape = shapes.Circle(owner=self, rad=100, drawtype="fill") self.physics_component = PhysicsBody(owner=self, tangible=False, immobile=True) self.renderable_component = ShapeRenderer(owner=self, color=(1, 0, 0, 1)) self.collision_component = Collider(owner=self) self.collision_component.collide = self.collide
def __init__(self, position=None, priority=False, *args, **kwargs): super().__init__(*args, **kwargs) # Alternately, what if we intelligently decide how to handle a more general position argument? if position is None: # If no position was given to us, be smart about it: if not hasattr(self.owner, 'position_component'): # If the owner doesn't have a position component AND we didn't get passed one, then... uh... TODO: logging... framework... time? position = v(0,0) else: # if the owner has a position component, fall through to that. # TODO: more full-featured fallthrough behavior position = self.owner.position_component if isinstance(position, v): position = PositionComponent(owner=self.owner, position=position) if isinstance(position, PositionComponent): self.position_component = position self.priority=priority
def rectcircle(me, you): rect_min_corner = v(me.xbounds[0], me.ybounds[0]) + me.position_component.position rect_max_corner = v(me.xbounds[1], me.ybounds[1]) + me.position_component.position rect_center = (rect_min_corner + rect_max_corner) / 2 displacement = you.position_component.position - me.position_component.position if displacement.x < me.xbounds[0]: edge_x = -1 elif me.xbounds[0] < displacement.x < me.xbounds[1]: edge_x = 0 elif me.xbounds[1] < displacement.x: edge_x = +1 if displacement.y < me.ybounds[0]: edge_y = -1 elif me.ybounds[0] < displacement.y < me.ybounds[1]: edge_y = 0 elif me.ybounds[1] < displacement.y: edge_y = +1 if abs(edge_x) == 1 and abs(edge_y) == 1: x = rect_min_corner.x if edge_x < 0 else rect_max_corner.x y = rect_min_corner.y if edge_y < 0 else rect_max_corner.y corner = v(x, y) vect = you.position_component.position - corner if abs(vect) < you.radius: return vect.unit() * (you.radius - abs(vect)) else: return None x_vect = compare_interval(me.xbounds, you.xbounds, displacement.x) y_vect = compare_interval(me.ybounds, you.ybounds, displacement.y) if x_vect is not None and y_vect is not None: if abs(x_vect) > abs(y_vect): return v(x_vect, 0) else: return v(0, y_vect) elif x_vect is not None: return v(x_vect, 0) elif y_vect is not None: return v(0, y_vect)
def circlecircle(me, you): """If I am intersecting you, find the shortest vector by which to change my position to no longer be intersecting. This function takes two objects with shape attributes. It checks to see if they are colliding and returns the shortest vector by which to move the object `me`, to remedy the collision. If the objects do not collide, it returns None. """ separation = you.position_component.position - me.position_component.position # The vector from me to you. if separation.x == 0 and separation.y == 0: separation_direction = v(0, -1) separation_distance = 0 else: separation_direction = separation.unit() separation_distance = abs(separation) my_extents = (-me.radius, me.radius) your_extents = (-you.radius, you.radius) output = compare_interval(my_extents, your_extents, separation_distance) if output is None: return None return output * separation_direction
def rectpoint(me, you): my_min = v(me.xbounds[0], me.ybounds[0]) + me.position_component.position my_max = v(me.xbounds[1], me.ybounds[1]) + me.position_component.position you_pos = you.position_component.position center = (my_min + my_max) / 2 vect = you_pos - center if my_min.x < you_pos.x < my_max.x and my_min.y < you_pos.y < my_max.y: if abs(vect.x) < abs(vect.y): if vect.x > 0: return v(you_pos.x - me.xbounds[1], 0) else: return v(you_pos.x - me.xbounds[0], 0) else: if vect.y > 0: return v(0, you_pos.y - me.ybounds[1]) else: return v(0, you_pos.y - me.ybounds[0])
def generate(self): manifest = [] player = PlayerBall(self, location = v(0,0)) manifest.append( player ) manifest.append( CameraFollower(self, latch=player, spring=50, damping=10) ) manifest.append( FreeBall(self, location = v(0,-50)) ) manifest.append( FreeBall(self, location = v(-100,0)) ) manifest.append( FreeBall(self, location = v(100,0)) ) manifest.append( FreeBall(self, location = v(0, 1700), rad=80) ) manifest.append( Spawner(self, location = v(-500, 1500), rad=250) ) manifest.append( Spawner(self, location = v(500, 1500), rad=250) ) manifest.append( EnemyBall(self, location = v(-200,30), rad=30) ) manifest.append( EnemyBall(self, location = v(-260,0), rad=30) ) manifest.append( EnemyBall(self, location = v(-100,60), rad=30) ) height = 1000 width = 4000 quantity = 100 balls = [ ObstacleBall(self, location=v(uniform(-1,1)*width, uniform(-1,1)*height), rad=40) for i in range(quantity) ] manifest.extend(balls) wavelength = 600 depth = 150 h = -1000 wave_1 = [ ObstacleLine(self, location=v(i*wavelength, h), endpoint=v((i+0.5)*wavelength, h+depth), thick=20) for i in range(-10,10) ] manifest.extend(wave_1) wave_2 = [ ObstacleLine(self, location=v((i+0.5)*wavelength, h+depth), endpoint=v((i+1)*wavelength, h), thick=20) for i in range(-10,10) ] manifest.extend(wave_2) class DummyRender(Renderable): label = text.Label("", 'Arial', 24, color=(0, 0, 0, 200), x=0, y=0, anchor_x="center", anchor_y="center", width=3*self.window.width/4, height=3*self.window.height/4, multiline=1) def __init__(self, text='THIS IS A TEST', *args, **kwargs): super().__init__(*args, **kwargs) self.label.text = text def draw(self): position = self.position_component.position pyglet.gl.glPushMatrix() pyglet.gl.glTranslatef(position.x, position.y, 0) self.label.draw() pyglet.gl.glPopMatrix() dummy = Entity() dummy.renderable_component = DummyRender(owner=dummy, position=v(self.window.width/2, self.window.height/4)) #dummy = {'renderable_component': text.Label( 'THIS IS A TEST', 'Arial', 24, color = (0, 0, 0, 200), # x = self.window.width/2, y = self.window.height/4, anchor_x="center", anchor_y="center", # width=3*self.window.width/4, height=3*self.window.height/4, multiline=1)} manifest.append( dummy ) return manifest
def fire_bomb(self): newthing = BombBall(self.lifecycle.parent_screen, self, location=self.position_component.position) svel = self.physics_component.vel if abs(svel) == 0: newthing.physics_component.vel = v(0, 800) else: newthing.physics_component.vel = svel + 800*svel.unit() self.lifecycle.parent_screen.add_entity(newthing)
def pointpoint(me, you): return v(0, 1) if me.position_component.position == you.position_component.position else None
def fire_laser(self): svel = self.physics_component.vel if abs(svel) == 0: direct = v(0,1) else: direct = svel.unit() newlaser = LaserLine(self.lifecycle.parent_screen, self, location=self.position_component.position, direction=direct) self.lifecycle.parent_screen.add_entity(newlaser)
return output def interpolate_2d(p, c, interpolate=None): """ Takes a point normalized to 0,1 and four corner values (0,0, 0,1, 1,1, 1,0) and interpolates between them. """ if interpolate is None: interpolate = hermite bottom_int = hermite(p.x, (c[0],c[3])) top_int = hermite(p.x, (c[1],c[2])) return hermite(p.y, (bottom_int, top_int)) def hermite(p, c): """ Hermite interpolation between two points, with starting and ending tangents zero. """ return c[0]*(2*(p**3) - 3*(p**2) + 1) + c[1]*(-2*(p**3) + 3*(p**2)) rands = list() rands.append( [[v(uniform(-1,1),uniform(-1,1)) for i in range(100)] for j in range(100)] ) for i in range(10): if len(rands[i]) < 10: break rands.append(rescale_2d(rands[i], 0.5)) def apply(function): return lambda source, index: function(source[index]) def identity(source, index): """ Returns the requested value. """ return source[index] class CompositeSignal(object): """ A signal which is a user-defined compositing of other signals and operators. """ def __init__(self, source, operation=lambda source, index: source[index]): self.source = source
def __init__(self, position=None, *arguments, **keyword_args): super().__init__(*arguments, **keyword_args) self.position = position or v(0,0)
def on_key_release(self, symbol, modifiers): if symbol == key.UP: self.thrustdir = self.thrustdir - v(0,2) if symbol == key.DOWN: self.thrustdir = self.thrustdir - v(0,-1) if symbol == key.LEFT: self.thrustdir = self.thrustdir - v(-1,0) if symbol == key.RIGHT: self.thrustdir = self.thrustdir - v(1,0)