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)
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) # Rotated 45 degrees quads[6].angle = math.pi / 4 # Rotated 22 degrees and scaled to 50%
class Asteroid(Entity): 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 update(self, game_speed): self._physicAsteroid.update_forces() self._quad.pos = self._physicAsteroid.body.position * PHYSICS_SCALE self._quad.angle = self._physicAsteroid.body.angle pass def draw(self, screen): self._quad.shader.bind() self._quad.shader.set_uniform_1f('mul_r', 0.3) self._quad.shader.set_uniform_1f('mul_g', 0.3) self._quad.shader.set_uniform_1f('mul_b', 0.3) self._quad.draw(screen) pass def collide(self, other, **kwargs): pass def destroy(self): goes_to_left = self._physicAsteroid.body.linearVelocity.x < 0 goes_to_right = not goes_to_left goes_to_top = self._physicAsteroid.body.linearVelocity.y < 0 goes_to_bottom = not goes_to_top return (goes_to_left and self._physicAsteroid.body.position.x < 0 - self._physicAsteroid.shape.radius) or \ (goes_to_right and (self._physicAsteroid.body.position.x * PHYSICS_SCALE > SCREEN_WIDTH + self._physicAsteroid.shape.radius)) or \ (goes_to_top and (self._physicAsteroid.body.position.y < 0 - self._physicAsteroid.shape.radius)) or \ (goes_to_bottom and (self._physicAsteroid.body.position.y * PHYSICS_SCALE > SCREEN_HEIGHT + - self._physicAsteroid.shape.radius))