UNPKG

@awayfl/awayfl-player

Version:

Flash Player emulator for executing SWF files (published for FP versions 6 and up) in javascript

239 lines (195 loc) 6.36 kB
// Delegate of b2World. import { b2Fixture } from './b2Fixture'; import { b2Body } from './b2Body'; import { b2World } from './b2World'; import { IBroadPhase } from '../Collision/IBroadPhase'; import { b2ContactFilter } from './b2ContactFilter'; import { b2ContactListener } from './b2ContactListener'; import { b2Contact, b2ContactEdge, b2ContactFactory } from './Contacts'; import { b2ContactPoint } from '../Collision/b2ContactPoint'; import { b2DynamicTreeBroadPhase } from '../Collision/b2DynamicTreeBroadPhase'; /** * @private */ export class b2ContactManager { __fast__: boolean = true; constructor() { this.m_world = null; this.m_contactCount = 0; this.m_contactFilter = b2ContactFilter.b2_defaultFilter; this.m_contactListener = b2ContactListener.b2_defaultListener; this.m_contactFactory = new b2ContactFactory(this.m_allocator); this.m_broadPhase = new b2DynamicTreeBroadPhase(); this.AddPairDelegate = (proxyUserDataA: any, proxyUserDataB: any) => this.AddPair(proxyUserDataA, proxyUserDataB); } public AddPairDelegate: (proxyUserDataA: any, proxyUserDataB: any) => void; // This is a callback from the broadphase when two AABB proxies begin // to overlap. We create a b2Contact to manage the narrow phase. public AddPair(proxyUserDataA: any, proxyUserDataB: any): void { let fixtureA: b2Fixture = proxyUserDataA as b2Fixture; let fixtureB: b2Fixture = proxyUserDataB as b2Fixture; let bodyA: b2Body = fixtureA.GetBody(); let bodyB: b2Body = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) return; // Does a contact already exist? let edge: b2ContactEdge = bodyB.GetContactList(); while (edge) { if (edge.other == bodyA) { const fA: b2Fixture = edge.contact.GetFixtureA(); const fB: b2Fixture = edge.contact.GetFixtureB(); if (fA == fixtureA && fB == fixtureB) return; if (fA == fixtureB && fB == fixtureA) return; } edge = edge.next; } //Does a joint override collision? Is at least one body dynamic? if (bodyB.ShouldCollide(bodyA) == false) { return; } // Check user filtering if (this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. const c: b2Contact = this.m_contactFactory.Create(fixtureA, fixtureB); // Contact creation may swap shapes. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); bodyA = fixtureA.m_body; bodyB = fixtureB.m_body; // Insert into the world. c.m_prev = null; c.m_next = this.m_world.m_contactList; if (this.m_world.m_contactList != null) { this.m_world.m_contactList.m_prev = c; } this.m_world.m_contactList = c; // Connect to island graph. // Connect to body A c.m_nodeA.contact = c; c.m_nodeA.other = bodyB; c.m_nodeA.prev = null; c.m_nodeA.next = bodyA.m_contactList; if (bodyA.m_contactList != null) { bodyA.m_contactList.prev = c.m_nodeA; } bodyA.m_contactList = c.m_nodeA; // Connect to body 2 c.m_nodeB.contact = c; c.m_nodeB.other = bodyA; c.m_nodeB.prev = null; c.m_nodeB.next = bodyB.m_contactList; if (bodyB.m_contactList != null) { bodyB.m_contactList.prev = c.m_nodeB; } bodyB.m_contactList = c.m_nodeB; ++this.m_world.m_contactCount; return; } public FindNewContacts(): void { this.m_broadPhase.UpdatePairs(this.AddPairDelegate); } private static readonly s_evalCP: b2ContactPoint = new b2ContactPoint(); public Destroy(c: b2Contact): void { const fixtureA: b2Fixture = c.GetFixtureA(); const fixtureB: b2Fixture = c.GetFixtureB(); const bodyA: b2Body = fixtureA.GetBody(); const bodyB: b2Body = fixtureB.GetBody(); if (c.IsTouching()) { this.m_contactListener.EndContact(c); } // Remove from the world. if (c.m_prev) { c.m_prev.m_next = c.m_next; } if (c.m_next) { c.m_next.m_prev = c.m_prev; } if (c == this.m_world.m_contactList) { this.m_world.m_contactList = c.m_next; } // Remove from body A if (c.m_nodeA.prev) { c.m_nodeA.prev.next = c.m_nodeA.next; } if (c.m_nodeA.next) { c.m_nodeA.next.prev = c.m_nodeA.prev; } if (c.m_nodeA == bodyA.m_contactList) { bodyA.m_contactList = c.m_nodeA.next; } // Remove from body 2 if (c.m_nodeB.prev) { c.m_nodeB.prev.next = c.m_nodeB.next; } if (c.m_nodeB.next) { c.m_nodeB.next.prev = c.m_nodeB.prev; } if (c.m_nodeB == bodyB.m_contactList) { bodyB.m_contactList = c.m_nodeB.next; } // Call the factory. this.m_contactFactory.Destroy(c); --this.m_contactCount; } // This is the top level collision call for the time step. Here // all the narrow phase collision is processed for the world // contact list. public Collide(): void { // Update awake contacts. let c: b2Contact = this.m_world.m_contactList; while (c) { const fixtureA: b2Fixture = c.GetFixtureA(); const fixtureB: b2Fixture = c.GetFixtureB(); const bodyA: b2Body = fixtureA.GetBody(); const bodyB: b2Body = fixtureB.GetBody(); if (bodyA.IsAwake() == false && bodyB.IsAwake() == false) { c = c.GetNext(); continue; } // Is this contact flagged for filtering? if (c.m_flags & b2Contact.e_filterFlag) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { var cNuke: b2Contact = c; c = cNuke.GetNext(); this.Destroy(cNuke); continue; } // Check user filtering. if (this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { cNuke = c; c = cNuke.GetNext(); this.Destroy(cNuke); continue; } // Clear the filtering flag c.m_flags &= ~b2Contact.e_filterFlag; } const proxyA: any = fixtureA.m_proxy; const proxyB: any = fixtureB.m_proxy; const overlap: boolean = this.m_broadPhase.TestOverlap(proxyA, proxyB); // Here we destroy contacts that cease to overlap in the broadphase if (overlap == false) { cNuke = c; c = cNuke.GetNext(); this.Destroy(cNuke); continue; } c.Update(this.m_contactListener); c = c.GetNext(); } } public m_world: b2World; public m_broadPhase: IBroadPhase; public m_contactList: b2Contact; public m_contactCount: number /** int */; public m_contactFilter: b2ContactFilter; public m_contactListener: b2ContactListener; public m_contactFactory: b2ContactFactory; public m_allocator: any; }