def __init__( self, world, x, y, speed, torque, asset='resources/images/asteroides/asteroid_01.png', scale=1, ): super().__init__(world, x, y, 0) # Slightly smaller than the image texture = Texture.load_from_file(asset) image_size = min(texture.width, texture.height) radius = ((image_size / PHYSICS_SCALE) / 2) * 0.8 self._quad = QuadDrawable(x, y, texture.width * scale, texture.height * scale) self._quad.anchor_to_center() self._quad.texture = texture self._quad.shader = ShaderProgram.from_files(vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self._physicAsteroid = PhysicsAsteroid( self, world.physicsWorld, center=Vector2(x / PHYSICS_SCALE, y / PHYSICS_SCALE), radius=radius, speed=speed, torque=torque, )
def __init__(self, ship, world): super().__init__(ship._world, 0, 0) self._ship = ship self._quad = QuadDrawable(0, 0, 0, 0) self._quad.texture = Texture.load_from_file( 'resources/images/shield_arc.png') self._quad.shader = ShaderProgram.from_files( vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self._quad.size = Vector2(self._quad.texture.width, self._quad.texture.height) * 0.67 self._quad.anchor = Vector2(0, self._quad.size.y / 2) self._physicsShield = PhysicsShield( self, ship._physicsShip, world.physicsWorld, center=self._ship._physicsShip.body.position, radius=(self._quad.size.x / PHYSICS_SCALE) * 1.1, ) self._collision_timer = 0 self._rad1 = ship._dim.y / 2.9 self._rad2 = ship._dim.y / 2.9 self._angle = 0 self._angle_speed = 1 self._enable = False self._charge = 0 self.shield_state = ShieldState(self) self.update(0, (0.0, 0.0, 0.0))
class PostProcessingStep(object): def __init__(self, width, height, flip_y=True): super().__init__() self._fbo = FrameBuffer(width, height) self._drawable = QuadDrawable() self._drawable.size = Vector2(width, height) self._drawable.flip_y = flip_y self._drawable.pos = Vector2(0, height) self._drawable.invalidate_matrices() self._drawable.texture = self._fbo.texture def draw(self, screen): self._drawable.draw(screen) @property def fbo(self): return self._fbo @property def drawable(self): return self._drawable @drawable.setter def drawable(self, drawable): self._drawable = drawable
class SideTrail(Entity): def __init__(self, ship, offset_x, offset_y, offset_angle): self._ship = ship self.offset_x = offset_x self.offset_y = offset_y self.offset_angle = offset_angle self.side_trail_dimensions = Vector2(56 * self._ship.size, 11 * self._ship.size) self.side_trail = QuadDrawable(0, 0, self.side_trail_dimensions.x, self.side_trail_dimensions.y) self.side_trail.texture = Texture.load_from_file( 'resources/images/ship/side_trail.png') self.side_trail.anchor = Vector2(56 * self._ship.size, 5 * self._ship.size) self.side_trail.angle = offset_angle self.update(0, 0) def draw(self, screen): self.side_trail.draw(screen) def update(self, game_speed, axis): if axis > 0: self.side_trail.size = self.side_trail_dimensions self.side_trail.pos = PHYSICS_SCALE * ( self._ship._physicsShip.body.transform * (self.offset_x / PHYSICS_SCALE, self.offset_y / PHYSICS_SCALE)) self.side_trail.angle = self.offset_angle + self._ship._quad.angle else: self.side_trail.size = Vector2(0, 0)
class Bullet(Entity): def __init__(self, bullet_mgr, world): super().__init__(world, 0, 0, 0) # The visual representation of the bullet. self.owner = None self._world = world self._quad = QuadDrawable() self._quad.texture = Texture.load_from_file( 'resources/images/bullet.png') self._quad.size = Vector2(self._quad.texture.width, self._quad.texture.height) self._quad.anchor_to_center() # Attach physics only in the initialize method self.bullet_radius = min(self._quad.size.x, self._quad.size.y) / PHYSICS_SCALE / 2 self._angle = None self.bullet_mgr = bullet_mgr def initialize(self, x, y, direction, speed, owner): self.owner = owner self._physics = PhysicsBullet(self, self._world.physicsWorld, x / PHYSICS_SCALE, y / PHYSICS_SCALE, self.bullet_radius, owner) # Physics object corresponding to the bullet # self._physics.body.userData = {'type': 'bullet', 'obj': self, 'owner': owner} # self._physics.body.position = (x / PHYSICS_SCALE, y / PHYSICS_SCALE) self._physics.body.angle = math.atan2(-direction.x, direction.y) force_dir = b2Vec2(float(direction.x), float(direction.y)) force_pos = self._physics.body.GetWorldPoint(localPoint=(0.0, 0.0)) self._physics.body.ApplyLinearImpulse(force_dir * speed, force_pos, True) def draw(self, screen): self._quad.draw(screen) def update(self, screen): pos = self._physics.body.position if pos.x < 0 or pos.x > self._world.bounds.w / PHYSICS_SCALE or \ pos.y < 0 or pos.y > self._world.bounds.h / PHYSICS_SCALE: # Bullet is outside the screen self.remove_bullet() else: # Update the position of the bullet pos *= PHYSICS_SCALE self._quad.pos = Vector2(pos[0], pos[1]) self._quad.angle = self._physics.body.angle pos /= PHYSICS_SCALE def collide(self, other, began=False, **kwargs): # Don't do anything if a bullet is hitting a bullet. if isinstance(other, type(self)): return # If a bullet is hit by anything else, recycle it. if not began: self.remove_bullet() def remove_bullet(self): # Mark the associated physical object for deletion self.bullet_mgr.mark_for_recycle(self)
def __init__(self, x, y, length, angle): # self.quadb = QuadDrawable(x, y, 36/8, 100/8, angle) # self.quadb.texture = Texture.load_from_file('resources/images/burst_b.png') self.quadm = QuadDrawable(x + 36 / 8, y, length, 100 / 8, angle) self.quadm.texture = Texture.load_from_file('resources/images/burst_m.png') # self.quade = QuadDrawable(x+36/8+100-4, y, 64/8, 100/8, angle) # self.quade.texture = Texture.load_from_file('resources/images/burst_e.png') self.should_be_removed = False
def __init__(self): self._font_faces = {} self._page_textures = {} self._character_program = ShaderProgram.from_sources( vert_source=self.vert_shader_base, frag_source=self.frag_shader_texture) self._quad = QuadDrawable() self._quad.shader = self._character_program
def __init__(self, bounds, controllers, stage, debug=0): self.scene = self.SCENE_TITLE self.game_over_timer = 0 self.stage = stage self.game_over_quad = QuadDrawable( SCREEN_WIDTH / 2 - 496 / 2, SCREEN_HEIGHT / 2 - 321 / 2, 496, 321, ) self.game_over_quad.texture = Texture.load_from_file( 'resources/images/game_over.png') self.bounds = bounds self.debug = debug self.window_x = 0 self.window_y = 0 self.physicsWorld = b2World(gravity=(0, 0), contactListener=ContactListener()) # Physical bodies should be deleted outside the simulation step. self.physics_to_delete = [] self._shapes = Shapes() self.controllers = controllers self.bullet_mgr = bullet_mgr = BulletManager(self) self.players = [] self.entities = [bullet_mgr] def batch(iterable, n=1): l = len(iterable) for ndx in range(0, l, n): yield iterable[ndx:min(ndx + n, l)] quadrant = 0 for cs in batch(controllers, 3): x = 300 + (SCREEN_WIDTH - 600) * (quadrant & 1) + 100 * random.uniform(-1, 1) y = 200 + (SCREEN_HEIGHT - 400) * (quadrant >> 1 & 1) + 50 * random.uniform(-1, 1) ship = Ship( self, bullet_mgr, controllers=cs, x=x, y=y, # angle=math.degrees(math.atan2(y, x)) - 180 color=SHIP_TEXTURES[list(SHIP_TEXTURES.keys())[quadrant]], ) self.players.append(ship) self.entities.append(ship) quadrant += 1 self.asteroids = []
def __init__(self, filename): self._tmx_data = pytmx.TiledMap(filename, invert_y=True, image_loader=self._image_loader) self._size = self._tmx_data.width * self._tmx_data.tilewidth, self._tmx_data.height * self._tmx_data.tileheight self._layer_offsets = [ Vector2(0, 0) for _ in range(0, len(self._tmx_data.layers)) ] self._drawable = QuadDrawable()
def __init__(self, width, height, flip_y=True): super().__init__() self._fbo = FrameBuffer(width, height) self._drawable = QuadDrawable() self._drawable.size = Vector2(width, height) self._drawable.flip_y = flip_y self._drawable.pos = Vector2(0, height) self._drawable.invalidate_matrices() self._drawable.texture = self._fbo.texture
def __init__( self, world, bullet_mgr, controllers, x, y, z=0, angle=0, color='standard', ): super().__init__(world, x, y, z) self.world = world self._dim = Vector2(130 * SCALE, 344 * SCALE) self._angle = angle self._physicsShip = PhysicsShip( self, world.physicsWorld, x / config.PHYSICS_SCALE, y / config.PHYSICS_SCALE, angle=angle, ) # Used by ship components to scale themselves self.size = SCALE self._quad = QuadDrawable(0, 0, self._dim.x, self._dim.y) self._quad.pos = self._position self._quad.anchor = self._dim.__div__(2.0) texture_file = SHIP_TEXTURES.get(color, SHIP_TEXTURES['standard']) self._quad.texture = Texture.load_from_file(texture_file) self._quad.shader = ShaderProgram.from_files(vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self.controllers = controllers self.pilotController = controllers[0] if len(controllers) else None self.shieldController = controllers[1] if len(controllers) > 1 else None self.turretController = controllers[2] if len(controllers) > 2 else None self.shields = [ Shield(self, world), Shield(self, world), ] self.turret_right = Turret(self, bullet_mgr, offset_x=-59 * SCALE, offset_y=2 * SCALE) self.turret_left = Turret(self, bullet_mgr, offset_x=59 * SCALE, offset_y=2 * SCALE) self.ship_state = ShipState(self) self.trail = Trail(self, 0, 0) self.side_trail_left = SideTrail(self, 28 * SCALE, 40 * SCALE, -45) self.side_trail_right = SideTrail(self, -25 * SCALE, 40 * SCALE, 225)
class StageDemo(StageSky): def __init__(self, width, height): super().__init__(width, height) texture = Texture.load_from_file('resources/images/logo.png') self._logo = QuadDrawable(0, 0, texture.width, texture.height) self._logo.anchor = Vector2(texture.width / 2, texture.height / 2) self._logo.texture = texture def update(self, game_speed): super().update(game_speed) self._logo.pos = Vector2(self.width / 2, self.height / 2) def draw_foreground(self, surface, window_x, window_y): super().draw_foreground(surface, window_x, window_y) self._logo.draw(surface)
def __init__(self, bullet_mgr, world): super().__init__(world, 0, 0, 0) # The visual representation of the bullet. self.owner = None self._world = world self._quad = QuadDrawable() self._quad.texture = Texture.load_from_file( 'resources/images/bullet.png') self._quad.size = Vector2(self._quad.texture.width, self._quad.texture.height) self._quad.anchor_to_center() # Attach physics only in the initialize method self.bullet_radius = min(self._quad.size.x, self._quad.size.y) / PHYSICS_SCALE / 2 self._angle = None self.bullet_mgr = bullet_mgr
class Trail(Entity): def __init__(self, ship, offset_x, offset_y): self._isBoosting = False self._ship = ship self.offset_x = offset_x self.offset_y = offset_y self.engine_trail_dimensions = Vector2(130 * self._ship.size, 344 * self._ship.size) self.engine_trail = QuadDrawable(0, 0, self.engine_trail_dimensions.x, self.engine_trail_dimensions.y) self.engine_trail.texture = Texture.load_from_file( 'resources/images/ship/trail.png') # Don't ask why 173... self.engine_trail.anchor = Vector2(65 * self._ship.size, 173 * self._ship.size) self.engine_trail.shader = ShaderProgram.from_files( vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self.update(0, 0, False) def draw(self, screen): self.engine_trail.shader.bind() self.engine_trail.shader.set_uniform_1f( 'mul_r', 0 if self._isBoosting else 0.49) self.engine_trail.shader.set_uniform_1f( 'mul_g', .9 if self._isBoosting else 0.332) self.engine_trail.shader.set_uniform_1f( 'mul_b', .9 if self._isBoosting else 0.059) self.engine_trail.draw(screen) def update(self, game_speed, trigger_intensity, boost): self._isBoosting = boost """`trigger_intensity` is a number from 0 to 1 representing how much a player is pressing the controller's right trigger. """ self.engine_trail.size = self.engine_trail_dimensions * ( 1 if boost else trigger_intensity) self.engine_trail.pos = Vector2( self._ship._quad.pos.x + self.offset_x, self._ship._quad.pos.y + self.offset_y, ) self.engine_trail.angle = self._ship._quad._angle
def __init__(self, ship, offset_x, offset_y, offset_angle): self._ship = ship self.offset_x = offset_x self.offset_y = offset_y self.offset_angle = offset_angle self.side_trail_dimensions = Vector2(56 * self._ship.size, 11 * self._ship.size) self.side_trail = QuadDrawable(0, 0, self.side_trail_dimensions.x, self.side_trail_dimensions.y) self.side_trail.texture = Texture.load_from_file( 'resources/images/ship/side_trail.png') self.side_trail.anchor = Vector2(56 * self._ship.size, 5 * self._ship.size) self.side_trail.angle = offset_angle self.update(0, 0)
def __init__(self, width, height): super().__init__(width, height) self.quad = QuadDrawable(0, 0, width, height) self.quad.texture = Texture.load_from_file('resources/images/bg.png') number_of_planets = 9 self.planets = [] number_of_clouds_background = 5 number_of_clouds_foreground = 5 self.clouds_background = [] self.clouds_foreground = [] # Generate the list of planets self.generate_planets(number_of_planets, width, height) # Generate the list of clouds self.generate_clouds_background(number_of_clouds_background, width, height) self.generate_clouds_foreground(number_of_clouds_foreground, width, height)
class Stage1(Stage): def __init__(self, width, height): super().__init__(width, height) self.quad = QuadDrawable(0, 0, width, height) self.quad.texture = Texture.load_from_file('resources/images/bg.png') def get_width(self): return self.width def update(self, game_speed): pass def draw_background(self, surface, window_x, window_y): self.quad.draw(surface) def draw_foreground(self, surface, window_x, window_y): pass
class Laser: def __init__(self, x, y, length, angle): # self.quadb = QuadDrawable(x, y, 36/8, 100/8, angle) # self.quadb.texture = Texture.load_from_file('resources/images/burst_b.png') self.quadm = QuadDrawable(x + 36 / 8, y, length, 100 / 8, angle) self.quadm.texture = Texture.load_from_file('resources/images/burst_m.png') # self.quade = QuadDrawable(x+36/8+100-4, y, 64/8, 100/8, angle) # self.quade.texture = Texture.load_from_file('resources/images/burst_e.png') self.should_be_removed = False def update(self, screen): self.quadm.size = Vector2(self.quadm.scale.x, self.quadm.scale.y * 0.9) if self.quadm.scale.x < 0.01: self.should_be_removed = True self.quadm.size = Vector2(0, 0) def draw(self, screen): # self.quadb.draw(screen) self.quadm.draw(screen)
class HealthBar(Entity): def __init__(self, ship, world): super().__init__(world, ship.position.x, ship.position.y) self._ship = ship self._quad = QuadDrawable(0, 0, ship._dim.x, 5) self._quad.texture = Texture.load_from_file( 'resources/images/health.png') def update(self, game_speed): self._quad.size = Vector2( self._ship._dim.x * self._ship.ship_state.energy / ShipState.MAX_ENERGY, self._quad.size.y, ) self._quad.pos = self._position + Vector2(-self._ship._dim.x / 2, -self._ship._dim.y / 3) def draw(self, screen): self._quad.draw(screen)
def __init__(self, ship, offset_x, offset_y): self._isBoosting = False self._ship = ship self.offset_x = offset_x self.offset_y = offset_y self.engine_trail_dimensions = Vector2(130 * self._ship.size, 344 * self._ship.size) self.engine_trail = QuadDrawable(0, 0, self.engine_trail_dimensions.x, self.engine_trail_dimensions.y) self.engine_trail.texture = Texture.load_from_file( 'resources/images/ship/trail.png') # Don't ask why 173... self.engine_trail.anchor = Vector2(65 * self._ship.size, 173 * self._ship.size) self.engine_trail.shader = ShaderProgram.from_files( vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self.update(0, 0, False)
def create_cloud_quad(cloud, size, cloud_list, cloud_picked): cloud.quad = QuadDrawable(cloud.pos.x, cloud.pos.y, size, size, angle=random.random() * math.pi * 2) cloud.quad.texture = Texture.load_from_file('resources/images/clouds/' + cloud_list[cloud_picked - 1]) cloud.quad.shader = ShaderProgram.from_files( vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') cloud.quad.anchor_to_center()
def create_planet_quad(planet, size, planet_list, planet_picked): planet.quad = QuadDrawable(planet.pos.x, planet.pos.y, size, size, angle=random.random() * math.pi * 2) planet.quad.texture = Texture.load_from_file('resources/images/planets/' + planet_list[planet_picked - 1]) planet.quad.shader = ShaderProgram.from_files( vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') planet.quad.anchor_to_center()
def __init__(self, frames_store): self._frames_store = frames_store self._x = 0 self._y = 0 self._flags = 0 self._angle = 0 self._scale = Vector2(1, 1) # Collision detection self._attack_box = None self._hit_box = None # Frames and animations self._frame = None self._animation = None self._animation_name = None self._animation_frame_index = None self._animation_frame_delay = 0 self._animation_speed = 1 self._animating = False # Drawing self._drawable = QuadDrawable()
class Sprite: DEBUG = False def __init__(self, frames_store): self._frames_store = frames_store self._x = 0 self._y = 0 self._flags = 0 self._angle = 0 self._scale = Vector2(1, 1) # Collision detection self._attack_box = None self._hit_box = None # Frames and animations self._frame = None self._animation = None self._animation_name = None self._animation_frame_index = None self._animation_frame_delay = 0 self._animation_speed = 1 self._animating = False # Drawing self._drawable = QuadDrawable() def draw(self, screen): if self._frame is None: return self._drawable.pos = Vector2( self._x, self._y) # - camera.offset.x, self._y - camera.offset.y) self._drawable.draw(screen) # DEBUG boxes if Sprite.DEBUG: # TODO: !!! pass # anchor_x = self.frame.rect['x'] + self.frame.anchor['x'] - window_x # anchor_y = self.frame.rect['y'] + self.frame.anchor['y'] - window_y # pygame.draw.rect(surface, (255, 255, 255), pygame.Rect(anchor_x, anchor_y, 1, 1), 1) # if self.hit_box and self.hit_box.w > 0 and self.hit_box.h > 0: # pygame.draw.rect(surface, (0, 200, 0), self.hit_box.move(-window_x, -window_y), 1) # if self.attack_box and self.attack_box.w > 0 and self.attack_box.h > 0: # pygame.draw.rect(surface, (200, 0, 0), self.attack_box.move(-window_x, -window_y), 1) def set_frame(self, frame_name): self.stop_animation() self._animation = None self._frame = self._frames_store.get_frame(frame_name) def stop_animation(self): self._animation_frame_delay = 0 self._animation_frame_index = 0 self._animating = False def play_animation(self, animation_name, flags=0, speed=1): if (self._flags & FramesStore.FLAG_LOOP_ANIMATION) > 0 and \ self._flags == flags and animation_name == self._animation_name: return self._animating = True self._animation_speed = speed self._animation_name = animation_name self._flags = flags self._set_animation_frame(0) def skip_to_last_animation_frame(self): if not self._animating: return self._animating = False self._set_animation_frame(len(self._animation.frames) - 1) def update(self, game_speed): self._update_collision_boxes() if not self._animating: return if self._animation_frame_delay <= 0: self.next_animation_frame() return else: self._animation_frame_delay -= game_speed * self._animation_speed return def next_animation_frame(self): new_animation_frame_index = self._animation_frame_index + 1 if new_animation_frame_index > len(self._animation.frames) - 1: if not (self._flags & FramesStore.FLAG_LOOP_ANIMATION) > 0: self._animating = False return else: new_animation_frame_index = 0 self._set_animation_frame(new_animation_frame_index) def previous_animation_frame(self): new_animation_frame_index = self._animation_frame_index - 1 if new_animation_frame_index < 0: new_animation_frame_index = len(self._animation.frames) - 1 self._set_animation_frame(new_animation_frame_index) def _set_animation_frame(self, frame_index): self._animation = self._frames_store.get_animation( self._animation_name) self._animation_frame_index = frame_index self.animation_frame = self._animation.frames[ self._animation_frame_index] new_frame = self._animation.frames[frame_index] self._animation_frame_delay = new_frame.delay self._frame = self._frames_store.get_frame(new_frame.frame_name) # Override animation flip if the frame is also flipped flags = self._flags if self.animation_frame.flip_x: flags |= FramesStore.FLAG_FLIP_X if self.animation_frame.flip_y: flags |= FramesStore.FLAG_FLIP_Y # Updates the drawable self._drawable.texture = self._frame.image self._drawable.scale = Vector2(self._frame.rect.w, self._frame.rect.h).dot(self._scale) self._drawable.anchor = self._frame.anchor.dot(self._scale) self._drawable.flip_x = (flags & FramesStore.FLAG_FLIP_X > 0) self._drawable.flip_y = (flags & FramesStore.FLAG_FLIP_Y > 0) def _update_collision_boxes(self): if not self._animating: self._attack_box = None self._hit_box = None # TODO: flip_y should be handled as well animation_frame = self._animation.frames[self._animation_frame_index] flip_x = ((self._flags & FramesStore.FLAG_FLIP_X) > 0) ^ animation_frame.flip_x if self._frame.hit_box: self._hit_box = self._frame.hit_box.copy() if flip_x: self._hit_box.x = -self._hit_box.x - self._hit_box.width self._hit_box.move_ip(self._x, self._y) else: self._hit_box = None if self._frame.attack_box: self._attack_box = self._frame.attack_box.copy() if flip_x: self._attack_box.x = -self._attack_box.x - self._attack_box.width self._attack_box.move_ip(self._x, self._y) else: self._attack_box = None @property def x(self): return self._x @x.setter def x(self, value): self._x = value @property def y(self): return self._y @y.setter def y(self, value): self._y = value @property def angle(self): return self._angle @angle.setter def angle(self, value): self._angle = value self._drawable.angle = value @property def scale(self): return self._scale @scale.setter def scale(self, value): self._scale = value self._drawable.scale *= value @property def hit_box(self): return self._hit_box @property def attack_box(self): return self._attack_box @property def animating(self): return self._animating @property def shader(self): return self._drawable.shader @shader.setter def shader(self, shader): self._drawable.shader = shader
import logging from mgl2d.app import App from mgl2d.graphics.quad_drawable import QuadDrawable from mgl2d.graphics.screen import Screen from mgl2d.graphics.texture import Texture from mgl2d.math.vector2 import Vector2 logging.basicConfig(level=logging.INFO) app = App() screen = Screen(800, 600, 'Quad drawable') screen.print_info() # Textured quad centered quad = QuadDrawable(400, 300, 200, 200) quad.texture = Texture.load_from_file('data/texture.png') quad.anchor = Vector2(100, 100) def draw_frame(screen): quad.draw(screen) def update_frame(delta_ms): quad.angle += 0.1 pass app.run(screen, draw_frame, update_frame)
class Font: def __init__(self): self._font_faces = {} self._page_textures = {} self._character_program = ShaderProgram.from_sources( vert_source=self.vert_shader_base, frag_source=self.frag_shader_texture) self._quad = QuadDrawable() self._quad.shader = self._character_program def load_bmfont_file(self, filename): base_dir = dirname(filename) font_def = BMFontDef(filename) self._font_faces[font_def.size] = font_def self._page_textures[font_def.size] = [] for file in font_def.page_files: path = base_dir + '/' + file self._page_textures[font_def.size].append( Texture().load_from_file(path)) def draw_string(self, screen, font_size, string, x, y, scale=1): font = self._font_faces[font_size] for char in string: c = font.get_char(char) self._quad.texture = self._page_textures[font_size][c.page_index] self._quad.size = Vector2(c.width, c.height) * scale self._quad.pos = Vector2(x + c.offset_x * scale, y + c.offset_y * scale) self._character_program.bind() self._character_program.set_uniform_2f('area_pos', c.x / font.page_width, c.y / font.page_height) self._character_program.set_uniform_2f('area_size', c.width / font.page_width, c.height / font.page_height) self._quad.draw(screen) x += c.advance_x * scale def draw_char(self, screen, font_size, char, x, y, scale=1): font = self._font_faces[font_size] c = font.get_char(char) s = self._character_program self._quad.texture = self._page_textures[font_size][c.page_index] self._quad.size = Vector2(c.width, c.height) * scale self._quad.pos = Vector2(x, y + c.offset_y * scale) self._quad.shader = s s.bind() s.set_uniform_matrix4('projection', screen.projection_matrix.m) s.set_uniform_2f('area_pos', c.x / font.page_width, c.y / font.page_height) s.set_uniform_2f('area_size', c.width / font.page_width, c.height / font.page_height) self._quad.draw(screen) return c.advance_x vert_shader_base = """ #version 330 core uniform mat4 model; uniform mat4 projection; uniform vec2 area_pos; uniform vec2 area_size; layout(location=0) in vec2 vertex; layout(location=1) in vec2 uv; out vec2 uv_out; void main() { vec2 texture_out = uv; if (gl_VertexID == 0) { texture_out = area_pos; } else if (gl_VertexID == 1) { texture_out = vec2(area_pos.x, area_pos.y+area_size.y); } else if (gl_VertexID == 2) { texture_out = vec2(area_pos.x+area_size.x, area_pos.y+area_size.y); } else if (gl_VertexID == 3) { texture_out = vec2(area_pos.x+area_size.x, area_pos.y); } vec4 vertex_world = model * vec4(vertex, 1, 1); gl_Position = projection * vertex_world; uv_out = texture_out; } """ frag_shader_texture = """
class Ship(Entity): def __init__( self, world, bullet_mgr, controllers, x, y, z=0, angle=0, color='standard', ): super().__init__(world, x, y, z) self.world = world self._dim = Vector2(130 * SCALE, 344 * SCALE) self._angle = angle self._physicsShip = PhysicsShip( self, world.physicsWorld, x / config.PHYSICS_SCALE, y / config.PHYSICS_SCALE, angle=angle, ) # Used by ship components to scale themselves self.size = SCALE self._quad = QuadDrawable(0, 0, self._dim.x, self._dim.y) self._quad.pos = self._position self._quad.anchor = self._dim.__div__(2.0) texture_file = SHIP_TEXTURES.get(color, SHIP_TEXTURES['standard']) self._quad.texture = Texture.load_from_file(texture_file) self._quad.shader = ShaderProgram.from_files(vert_file='resources/shaders/base.vert', frag_file='resources/shaders/rgba.frag') self.controllers = controllers self.pilotController = controllers[0] if len(controllers) else None self.shieldController = controllers[1] if len(controllers) > 1 else None self.turretController = controllers[2] if len(controllers) > 2 else None self.shields = [ Shield(self, world), Shield(self, world), ] self.turret_right = Turret(self, bullet_mgr, offset_x=-59 * SCALE, offset_y=2 * SCALE) self.turret_left = Turret(self, bullet_mgr, offset_x=59 * SCALE, offset_y=2 * SCALE) self.ship_state = ShipState(self) self.trail = Trail(self, 0, 0) self.side_trail_left = SideTrail(self, 28 * SCALE, 40 * SCALE, -45) self.side_trail_right = SideTrail(self, -25 * SCALE, 40 * SCALE, 225) # self._healthbar = HealthBar(self, world) def update(self, game_speed): self._physicsShip.update_forces(self.pilotController) for c in self.controllers: c.update() # if c.is_button_pressed(GameController.BUTTON_DIR_PAD_UP): # if self.turretController == c: # self.turretController = None # if self.shieldController == c: # self.shieldController = None # self.pilotController = c # elif c.is_button_pressed(GameController.BUTTON_DIR_PAD_DOWN): # if self.pilotController == c: # self.pilotController = None # if self.shieldController == c: # self.shieldController = None # self.turretController = c # elif c.is_button_pressed(GameController.BUTTON_DIR_PAD_LEFT): # if self.turretController == c: # self.turretController = None # if self.pilotController == c: # self.pilotController = None # self.shieldController = c if self.pilotController and self.ship_state.state == ShipState.LIVE: boost = self.pilotController.is_button_down(GameController.BUTTON_A) trigger_intensity = self.pilotController.get_axis(GameController.AXIS_TRIGGER_RIGHT) or 0.0 self.trail.update(game_speed, trigger_intensity, boost) axis_intensity = self.pilotController.get_axis(GameController.AXIS_LEFT_X) or 0.0 self.side_trail_left.update(game_speed, axis_intensity) self.side_trail_right.update(game_speed, -axis_intensity) if self.shieldController and self.ship_state.state == ShipState.LIVE: shield0_input_values = ( self.shieldController.get_axis(GameController.AXIS_LEFT_X) or 0.0, self.shieldController.get_axis(GameController.AXIS_LEFT_Y) or 0.0, 0.0, ) shield1_input_values = ( self.shieldController.get_axis(GameController.AXIS_RIGHT_X) or 0.0, self.shieldController.get_axis(GameController.AXIS_RIGHT_Y) or 0.0, 0.0, ) else: shield0_input_values = (0.0, 0.0, 0.0) shield1_input_values = (0.0, 0.0, 0.0) self.shields[0].update(game_speed, shield0_input_values) self.shields[1].update(game_speed, shield1_input_values) if self.turretController and self.ship_state.state == ShipState.LIVE: turret_left_x, turret_left_y = ( self.turretController.get_axis(GameController.AXIS_LEFT_X) or 0.0, self.turretController.get_axis(GameController.AXIS_LEFT_Y) or 0.0, ) turret_right_x, turret_right_y = ( self.turretController.get_axis(GameController.AXIS_RIGHT_X) or 0.0, self.turretController.get_axis(GameController.AXIS_RIGHT_Y) or 0.0, ) threshold = 0.2 turret_left_fire = (self.turretController.get_axis(GameController.AXIS_TRIGGER_LEFT) or 0.0) > threshold turret_right_fire = (self.turretController.get_axis(GameController.AXIS_TRIGGER_RIGHT) or 0.0) > threshold else: turret_left_x, turret_left_y = (0, 0) turret_right_x, turret_right_y = (0, 0) turret_left_fire = turret_right_fire = False self.turret_left.update( game_speed, turret_left_x, turret_left_y, turret_left_fire, is_right_wing=False, ) self.turret_right.update( game_speed, turret_right_x, turret_right_y, turret_right_fire, is_right_wing=True, ) self._angle = self._physicsShip.body.angle + math.pi pos = self._physicsShip.body.position * config.PHYSICS_SCALE self._position = Vector2(pos[0], pos[1]) self._quad.pos = self._position self._quad.angle = self._angle self.ship_state.update( time_passed_ms=(game_speed * config.GAME_FRAME_MS), ) # self._healthbar.update(game_speed) def draw(self, screen): if self.is_live(): for shield in self.shields: shield.draw(screen) self.trail.draw(screen) self.side_trail_left.draw(screen) self.side_trail_right.draw(screen) if self.has_recent_damage(): energy_ratio = self.ship_state.energy / self.ship_state.MAX_ENERGY damage_ratio = 1.0 - energy_ratio self._quad.shader.bind() self._quad.shader.set_uniform_1f('mul_r', 0.0) self._quad.shader.set_uniform_1f('mul_g', 0.2 + 0.8 * damage_ratio) self._quad.shader.set_uniform_1f('mul_b', 0.2 + 0.8 * damage_ratio) else: self._quad.shader.bind() self._quad.shader.set_uniform_1f('mul_r', 0.0) self._quad.shader.set_uniform_1f('mul_g', 0.0) self._quad.shader.set_uniform_1f('mul_b', 0.0) self.turret_left.draw(screen) self.turret_right.draw(screen) # Important: this has to be drawn AFTER the trails and turrets (to # be positioned on top of them) self._quad.draw(screen) def destroy_ship(self): pos = self._physicsShip.body.position * config.PHYSICS_SCALE x, y = pos self.world.asteroids.append(Asteroid( self.world, x, y - 30, Vector2(random() * 30 - 15, random() * -100), random() * 3.0, 'resources/images/derelict/part_01.png', config.SHIP_SCALE )) self.world.asteroids.append(Asteroid( self.world, x + 30, y + 30, Vector2(random() * 60 + 30, random() * 60 + 30), random() * 3.0, 'resources/images/derelict/part_02.png', config.SHIP_SCALE )) self.world.asteroids.append(Asteroid( self.world, x - 30, y + 30, Vector2(random() * -60 - 30, random() * 60 + 30), random() * 3.0, 'resources/images/derelict/part_03.png', config.SHIP_SCALE )) self.world.asteroids.append(Asteroid( self.world, x, y - 30, Vector2(random() * 3.0 - 1.5, random() * -10), random() * 3.0, 'resources/images/people/pilot.png', config.SHIP_SCALE )) self.world.asteroids.append(Asteroid( self.world, x + 30, y + 30, Vector2(random() * 6.0 + 3.0, random() * 6.0 + 3.0), random() * 3.0, 'resources/images/people/gunner.png', config.SHIP_SCALE )) self.world.asteroids.append(Asteroid( self.world, x - 30, y + 30, Vector2(random() * -6.0 - 3.0, random() * 6.0 + 3.0), random() * 3.0, 'resources/images/people/technician.png', config.SHIP_SCALE )) def is_live(self): return self.ship_state.state == ShipState.LIVE def has_recent_damage(self): return self.ship_state.has_recent_damage def collide(self, other, intensity=10.0, **kwargs): # TODO: Calculate the damage: # Collision between shield and bullet (sensor) # Collision between shield and everything else self.ship_state.damage(energy=10.0) def heal(self, amount): self.ship_state.heal(amount)
def __init__(self, width, height): super().__init__(width, height) self.quad = QuadDrawable(0, 0, width, height) self.quad.texture = Texture.load_from_file('resources/images/bg.png')
from mgl2d.app import App from mgl2d.graphics.quad_drawable import QuadDrawable from mgl2d.graphics.screen import Screen from mgl2d.graphics.texture import Texture from mgl2d.math.vector2 import Vector2 app = App() main_screen = Screen(800, 600, 'Quad drawable') main_screen.print_info() quads = [] for y in range(3): for x in range(4): quad = QuadDrawable(100 + x * 200, 100 + y * 200, size_x=120, size_y=120) quad.texture = Texture.load_from_file('data/texture.png') quad.anchor_to_center() quads.append(quad) # Flipped horizontally quads[1].flip_x = True # Flipped vertically quads[2].flip_y = True # Flipped in both directions quads[3].flip_x = quads[3].flip_y = True # Scaled smaller quads[4].scale = Vector2(0.8, 0.8) # Scaled bigger quads[5].scale = Vector2(1.2, 1.2)
def __init__(self, ship, world): super().__init__(world, ship.position.x, ship.position.y) self._ship = ship self._quad = QuadDrawable(0, 0, ship._dim.x, 5) self._quad.texture = Texture.load_from_file( 'resources/images/health.png')