Ejemplo n.º 1
0
    def __init__(self, REMOTE):
        super(Melee, self).__init__(*self.screen_size)

        self.window_title = "OpenMelee 0.01"
        init_gl(*self.screen_size)

        # Registe callbacks
        self.register_kbd_callback(self.on_key_press)

        # Init network
        if REMOTE:
            self.net = NetConn(LOCAL, REMOTE, self)
            if LOCAL[1] == 8888:
                self.local_player, self.remote_player = 0, 1
            else:
                self.local_player, self.remote_player = 1, 0
            config.PLAYERS[self.remote_player] = NetPlayer
        else:
            self.net = None

        # Initialize physics engine
        gravity = Vec2(0, 0)
        width = 700
        height = 700
        self.world = World(-width / 2, -height / 2, width, height, gravity)

        # Register collision callbacks
        self.contacthub = ContactListener(self)

        # Create players/controllers
        self.players = list(cls() for cls in config.PLAYERS)

        # Create game objects (they add themselves to self.actors if necessary)
        self.actors = []
        self.me = Nemesis(self)
        self.enemy = KzerZa(self)
        self.planet = Planet(self)

        for i in range(NUM_ASTEROIDS):
            Asteroid(self)

        # Init AI
        self.enemy.ai = AI(self.enemy, self.me, self.actors)

        # Save state for rollback
        self.run_time = self.time
        # self.history = History(self)

        # Network handshake  # TODO move to NetConn and randomize master/slave
        if self.net:
            if self.local_player == 0:
                # Master
                self.net.handshake()
            else:
                # Slave
                state = self.net.wait_handshake()
                if state:
                    self.deserialize(state)
                else:
                    print "Network handshake failed or timed out"
                    return

        # Calculate radius
        for a in self.actors:
            a.calc_radius()

        # from utils import squirtle
        # self.svg = squirtle.SVG("data/butterfly.svg")
        # self.svg.init((0,0), 1)

        self.main_loop()
Ejemplo n.º 2
0
class Melee(Game):

    WINDOW_POSITION = "800,400"

    # Keep this at 60 - no not tie to FPS
    hz = 60
    TIME_STEP = 1.0 / hz
    ts_ms = TIME_STEP * 1000.0

    # Screen size
    screen_size = 800.0, 600.0

    button_change = False  # Buttons pressed/released _locally_ since update?

    # Space upper and lower bounds
    aabb = AABB()
    aabb.lower_bound = Vec2(-200, -200)
    aabb.upper_bound = Vec2(200, 200)

    # Collision callback dictionary
    contact_register = {}

    ##
    ## INITIALIZATION
    ##

    def __init__(self, REMOTE):
        super(Melee, self).__init__(*self.screen_size)

        self.window_title = "OpenMelee 0.01"
        init_gl(*self.screen_size)

        # Registe callbacks
        self.register_kbd_callback(self.on_key_press)

        # Init network
        if REMOTE:
            self.net = NetConn(LOCAL, REMOTE, self)
            if LOCAL[1] == 8888:
                self.local_player, self.remote_player = 0, 1
            else:
                self.local_player, self.remote_player = 1, 0
            config.PLAYERS[self.remote_player] = NetPlayer
        else:
            self.net = None

        # Initialize physics engine
        gravity = Vec2(0, 0)
        width = 700
        height = 700
        self.world = World(-width / 2, -height / 2, width, height, gravity)

        # Register collision callbacks
        self.contacthub = ContactListener(self)

        # Create players/controllers
        self.players = list(cls() for cls in config.PLAYERS)

        # Create game objects (they add themselves to self.actors if necessary)
        self.actors = []
        self.me = Nemesis(self)
        self.enemy = KzerZa(self)
        self.planet = Planet(self)

        for i in range(NUM_ASTEROIDS):
            Asteroid(self)

        # Init AI
        self.enemy.ai = AI(self.enemy, self.me, self.actors)

        # Save state for rollback
        self.run_time = self.time
        # self.history = History(self)

        # Network handshake  # TODO move to NetConn and randomize master/slave
        if self.net:
            if self.local_player == 0:
                # Master
                self.net.handshake()
            else:
                # Slave
                state = self.net.wait_handshake()
                if state:
                    self.deserialize(state)
                else:
                    print "Network handshake failed or timed out"
                    return

        # Calculate radius
        for a in self.actors:
            a.calc_radius()

        # from utils import squirtle
        # self.svg = squirtle.SVG("data/butterfly.svg")
        # self.svg.init((0,0), 1)

        self.main_loop()

    ##
    ## EVENTS
    ##

    def on_key_press(self, key, state):
        # print "on_key_press(id=%s state=%s)" % (id, state)
        update_ship(self, key, state)

    def update(self):

        # Update states
        for a in self.actors:
            if a.check_death():
                continue
            a.limit_velocity()
            a.update_ai()
            a.update_state()
            a.apply_gravity()

        # Update game mechanics
        self.world.step(self.TIME_STEP, 5, 2)

        # End of frame maintenance
        for a in self.actors:
            if not self.in_bounds(a.body):
                self.boundary_violated(a.body)

        self.run_time += self.ts_ms
        # self.history.update(self.time)

    def render(self):
        zoom, center = self.calculate_view()
        reset_zoom(zoom, center, self.screen_size)

        cyan = 0.3, 0.9, 0.9
        ub = self.aabb.upper_bound
        lb = self.aabb.lower_bound
        verts = [(lb.x, ub.y), (lb.x, lb.y), (ub.x, lb.y), (ub.x, ub.y)]
        draw_polygon(verts, cyan)

        for a in self.actors:
            a.debug_draw()

        # self.svg.render(0, 10, angle = 0)

    ##
    ## NETWORK
    ##

    def serialize(self):  # TODO move to NetConn
        lst = []
        for ship in self.actors:
            s = ship.body
            lst += list(s.position) + list(s.linear_velocity) + [s.angle, s.angular_velocity]
        n = len(self.actors)
        return struct.pack("!B %df" % (n * 6), n, *lst)

    def deserialize(self, state):
        nlen = 1  # Encoded length of 'n'
        n, = struct.unpack("!B", state[:nlen])
        if (len(state) - nlen) != (struct.calcsize("!6f") * n):
            print "deserialize(): PACKET SIZE MISMATCH -- PACKET DROPPED"
            return
        lst = struct.unpack("!%df" % (n * 6), state[nlen:])
        for i, ship in enumerate(self.actors):
            s = ship.body
            p = lst[i * 6 : (i + 1) * 6]
            s.position = Vec2(p[0], p[1])
            s.velocity = Vec2(p[2], p[3])
            s.angle = p[4]
            s.angular_velocity = p[5]

    ##
    ## PRIVATE HELPER METHODS
    ##

    def calculate_view(self):
        from utils import clamp, bounding_box

        # Zoom in on the ships (and planet?)
        # objects = self.actors[:2]

        if not self.me.dead and not self.enemy.dead:
            p1 = self.me.body.position
            p2 = self.enemy.body.position
        else:
            p1 = Vec2(125, 125)
            p2 = Vec2(-125, -125)

        range = Vec2(p1.x - p2.x, p1.y - p2.y)
        zoom = clamp(1000 / range.length, 2, 75)
        # Calculate view center
        vcx = p1.x - range.x * 0.5
        vcy = p1.y - range.y * 0.5

        return zoom, (vcx, vcy)

    def in_bounds(self, body):
        ub = self.aabb.upper_bound
        lb = self.aabb.lower_bound

        if body.position.x > ub.x or body.position.x < lb.x:
            return False
        if body.position.y > ub.y or body.position.y < lb.y:
            return False
        return True

    def boundary_violated(self, body):
        ub = self.aabb.upper_bound
        lb = self.aabb.lower_bound
        pos = body.position

        if pos.x > ub.x:
            x = lb.x + 5
            body.position = Vec2(x, pos.y)
        elif pos.x < lb.x:
            x = ub.x - 5
            body.position = Vec2(x, pos.y)
        elif pos.y > ub.y:
            y = lb.y + 5
            body.position = Vec2(pos.x, y)
        elif pos.y < lb.y:
            y = ub.y - 5
            body.position = Vec2(pos.x, y)

    def collision_callback(self, shape1, shape2):
        key1 = hash(shape1)
        key2 = hash(shape2)

        actor1 = self.contact_register[key1]
        actor2 = self.contact_register[key2]
        actor1.apply_damage(actor2.damage)
        actor2.apply_damage(actor1.damage)