Example #1
0
    def query_point(self, x_or_point, y=None, from_mask=0xffffffff):
        """Hit test at the point specified. 

        :param x_or_point: x coordinate (float) or sequence of (x, y) floats.

        :param y: y coordinate (float) if x is not a sequence

        :param from_mask: Bit mask used to filter query results. This value
            is bit ANDed with candidate entities' ``collision.into_mask``.
            If the result is non-zero, then it is considered a hit. By
            default all entities colliding with the input point are
            returned.

        :return: A set of entities where the point is inside their collision
            radii as of the last time step.

        """
        if y is None:
            point = Vec2d(x_or_point)
        else:
            point = Vec2d(x_or_point, y)
        hits = set()
        position = getattr(self.world.components, self.position_component)
        collision = getattr(self.world.components, self.collision_component)
        for entity in self.broad_phase.query_point(x_or_point, y, from_mask):
            separation = point - position[entity].position
            if separation.get_length_sqrd() <= collision[entity].radius**2:
                hits.add(entity)
        return hits
Example #2
0
	def test_generate_verts_with_angle(self):
		from grease.renderer import Vector
		from grease.geometry import Vec2d, Vec2dArray
		world = self.make_world()
		renderer = Vector()
		renderer.set_world(world)
		self.assertTrue(renderer.world is world)
		world.shapes = [
			Data(closed=True, verts=Vec2dArray([(0,0), (0, 1), (1, 0)])),
			Data(closed=True, verts=Vec2dArray([(-2, -1), (2, -1), (2, 1), (-2, 1)])),
			Data(closed=False, verts=Vec2dArray([(1, -1), (-1, -1), (1, 1), (-1, 1)])),
		]
		world.positions = [
			Data(position=Vec2d(10, 10), angle=45),
			Data(position=Vec2d(4, 3), angle=90),
			Data(position=Vec2d(0, 0), angle=-45),
		]
		v_array, i_size, i_array, i_count = renderer._generate_verts()
		self.assertEqual(i_count, 20)
		sin45 = math.sin(math.radians(45))
		cos45 = math.cos(math.radians(45))
		self.assertArrayEqual(self.get_verts(v_array[:3]), 
			[(10, 10), (sin45+10, cos45+10), (cos45+10, -sin45+10)]) 
		self.assertEqual(list(i_array[:6]), [0, 1, 1, 2, 2, 0]) 
		self.assertArrayEqual(self.get_verts(v_array[3:7]), [(3, 5), (3, 1), (5, 1), (5, 5)]) 
		self.assertEqual(list(i_array[6:14]), [3, 4, 4, 5, 5, 6, 6, 3]) 
		self.assertArrayEqual(self.get_verts(v_array[7:11]), 
			[(sqrt2, 0), (0, -sqrt2), (0, sqrt2), (-sqrt2, 0)]) 
		self.assertEqual(list(i_array[14:20]), [7, 8, 8, 9, 9, 10]) 
		self.assertEqual(self.get_rgba(v_array[:11]), [(255,255,255,255)] * 11)
Example #3
0
 def set(self, entity, position):
     from grease.geometry import Vec2d
     if entity in self:
         data = self[entity]
     else:
         data = self[entity] = Data()
     data.entity = entity
     data.position = Vec2d(position)
Example #4
0
 def test_cast(self):
     from grease.component.field import Field
     from grease.geometry import Vec2d
     f = Field(None, "string", str)
     self.assertEqual(f.cast(22), "22")
     f = Field(None, "int", int)
     self.assertEqual(f.cast("42"), 42)
     f = Field(None, "vec", Vec2d)
     self.assertEqual(f.cast((11, 12)), Vec2d(11, 12))
Example #5
0
	def make_world(self):
		from grease.geometry import Vec2d, Vec2dArray
		from grease.color import RGBA
		world = TestWorld()
		world.shapes = [
			Data(closed=True, verts=Vec2dArray([(0,0), (0, 1), (0.5, 0.5)])),
			Data(closed=True, verts=Vec2dArray([(-1, -1), (1, -1), (1, 1), (-1, 1)])),
			Data(closed=False, verts=Vec2dArray([(1, -1), (-1, -1), (1, 1), (-1, 1)])),
		]
		world.positions = [
			Data(position=Vec2d(10, 10), angle=0),
			Data(position=Vec2d(4, 3), angle=0),
			Data(position=Vec2d(0, 0), angle=0),
		]
		world.renderable = [
			Data(color=RGBA(1,1,1,1)),
			Data(color=RGBA(1,1,1,1)),
			Data(color=RGBA(1,1,1,1)),
		]
		return world
Example #6
0
 def _generate_verts(self):
     """Generate vertex and index arrays for rendering"""
     vert_count = sum(
         len(shape.verts) + 1
         for shape, ignored, ignored in self.world.components.join(
             self.shape_component, self.position_component,
             self.renderable_component))
     v_array = (CVertColor * vert_count)()
     if vert_count > 65536:
         i_array = (ctypes.c_uint * 2 * vert_count)()
         i_size = pyglet.gl.GL_UNSIGNED_INT
     else:
         i_array = (ctypes.c_ushort * (2 * vert_count))()
         i_size = pyglet.gl.GL_UNSIGNED_SHORT
     v_index = 0
     i_index = 0
     scale = self.scale
     rot_vec = Vec2d(0, 0)
     for shape, position, renderable in self.world.components.join(
             self.shape_component, self.position_component,
             self.renderable_component):
         shape_start = v_index
         angle = radians(-position.angle)
         rot_vec.x = cos(angle)
         rot_vec.y = sin(angle)
         r = int(renderable.color.r * 255)
         g = int(renderable.color.g * 255)
         b = int(renderable.color.b * 255)
         a = int(renderable.color.a * 255)
         for vert in shape.verts:
             vert = vert.cpvrotate(rot_vec) * scale + position.position
             v_array[v_index].vert.x = vert.x
             v_array[v_index].vert.y = vert.y
             v_array[v_index].color.r = r
             v_array[v_index].color.g = g
             v_array[v_index].color.b = b
             v_array[v_index].color.a = a
             if v_index > shape_start:
                 i_array[i_index] = v_index - 1
                 i_index += 1
                 i_array[i_index] = v_index
                 i_index += 1
             v_index += 1
         if shape.closed and v_index - shape_start > 2:
             i_array[i_index] = v_index - 1
             i_index += 1
             i_array[i_index] = shape_start
             i_index += 1
     return v_array, i_size, i_array, i_index
Example #7
0
    def on_collide(self, other, point, normal):
        if isinstance(other, Asteroid):
            if self.collision.radius == 0: return
            if other.collision.radius == 0: return
            nx, ny = normal
            ppx, ppy = other.position.position
            px, py = self.position.position
            dx = ppx - px
            dy = ppy - py
            d2 = dx**2 + dy**2
            d = math.sqrt(d2)
            d1 = d - self.collision.radius - other.collision.radius
            if d1 > 0: d1 += 1
            else: d1 = d / (self.collision.radius + other.collision.radius)
            if d1 < 0.001: d1 = 0.001
            if (self.world.time - self.states.created < 1.5
                    or self.world.time - other.states.created < 1.5):
                d1 += 0.1
                d1 /= 5.0
                self.position.position[0] += nx / d1 * 0.4
                self.position.position[1] += ny / d1 * 0.4
                other.movement.velocity[0] -= nx / d1 * 3.0
                other.movement.velocity[1] -= ny / d1 * 3.0
                self.movement.velocity *= 0.5
                other.movement.velocity *= 0.5

            self.movement.velocity *= 0.8
            self.movement.velocity[
                0] += nx / d1 * 3.0 * other.collision.radius / self.collision.radius
            self.movement.velocity[
                1] += ny / d1 * 3.0 * other.collision.radius / self.collision.radius
            if self.world.time - self.states.created < 1: return
            if self.world.time - other.states.created < 1: return

            px1, py1 = self.position.position
            px2, py2 = other.position.position
            """
            if d < 5:
                total_radius = math.sqrt(self.collision.radius**2 + other.collision.radius**2)
                if total_radius > 60: return
                px = (px1 + px2) / 2.0
                py = (py1 + py2) / 2.0
            
                dx1, dy1 = self.movement.velocity
                dx2, dy2 = other.movement.velocity
                dx = (dx1 + dx2) / 2.0
                dy = (dy1 + dy2) / 2.0
                if total_radius >= 4:
                    Asteroid(self.world, total_radius, (px,py), 
                        (dx,dy), self.award.points / 2)
                    self.collision.radius = 0
                    other.collision.radius = 0
                    self.delete()
                    other.delete()
            """
            return
        if isinstance(other, Shot):
            if other.collision.radius == 0: return
            if self.collision.radius == 0: return
            other.collision.radius = 0
            if self.collision.radius > 6:
                total_area = 3.1415927 * (self.collision.radius**2)
                total_area -= 2
                count = 0
                for i in range(50):
                    if total_area < 4: break
                    min_area = 3.1415927 * 8 * 8
                    if min_area < total_area - 10:
                        chunk_size = random.gauss(self.collision.radius / 8,
                                                  self.collision.radius / 8)
                        if chunk_size < 4: continue
                    else:
                        chunk_size = math.sqrt(total_area) / 3.1415927 - 0.5
                        if chunk_size < 4: break
                    chunk_area = 3.1415927 * (chunk_size**2)

                    if chunk_area > total_area: continue
                    total_area -= chunk_area
                    px, py = self.position.position
                    angle = random.uniform(0, 360)
                    offset = random.uniform(2 + chunk_size / 2,
                                            self.collision.radius / 2)
                    dx, dy = math.cos(angle) * offset, math.sin(angle) * offset
                    px += dx
                    py += dy
                    ppos = (px, py)
                    Asteroid(self.world, chunk_size, ppos,
                             self.movement.velocity + Vec2d(dx, dy) * 10,
                             self.award.points * 2)
                    count += 1
                if random.gauss(0, total_area) > 8: count += 1
                if random.gauss(0, total_area) > 8: count += 1
                if random.gauss(0, total_area) > 8: count += 1
                for i in range(random.randint(0, int(count / 4))):
                    Collectable(self.world, None, self.position.position,
                                self.movement.velocity)
                random.choice(self.HIT_SOUNDS).play()
            else:
                random.choice(self.HIT_SMALL_SOUNDS).play()
            self.collision.radius = 0

            self.explode()
            self.delete()
Example #8
0
File: field.py Project: msarch/py
#############################################################################

__version__ = '$Id$'

import operator
from grease.geometry import Vec2d, Vec2dArray, Rect
from grease import color

# Allowed field types -> default values
types = {
    int: lambda: 0,
    float: lambda: 0.0,
    bool: lambda: False,
    str: lambda: "",
    object: lambda: None,
    Vec2d: lambda: Vec2d(0, 0),
    Vec2dArray: lambda: Vec2dArray(),
    color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0),
    Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0)
}


class Schema(dict):
    """Field schema definition for custom components"""
    def __init__(self, **fields):
        for ftype in fields.values():
            assert ftype in types, fname + " has an illegal field type"
        self.update(fields)


class FieldAccessor(object):