import { BlockPair, PluginPureHook } from '@gedit/runtime-compiler'; import { Component, CollisionBodyGameObject, CollisionBodyType, isScene, isCollisionBody, } from '@gedit/runtime-render'; import { local, global, isComponentCanAttachCollictionBody } from '../common'; import { LocalBody } from './utils'; let count = 1; const uniq = new Map(); function hashCode(str: string): number { const num = uniq.get(str); if (!num) { uniq.set(str, count); count++; return count; } return num; } export function collisionBody( ctx: PluginPureHook, component: CollisionBodyGameObject, parent: Component | undefined ): void { const { collision_body: data, position, size } = component; const { x, y } = position; const { width, height } = size; if (!parent || isScene(parent)) { throw new Error('collision body cannot attach to scene or root!'); } ctx.comment( `@type ${component.displayType}\n@name ${component.name}\n@parent ${parent.name}` ); ctx.print(`${global.GAME_BODY_MAP}.set('${component.id}', `); switch (data.bodyType) { case CollisionBodyType.circle: ctx.print( `${global.GAME_BODY_FACTORY}.circle(${x}, ${y}, ${data.circleRaduis})` ); break; case CollisionBodyType.rectangle: ctx.print( `${global.GAME_BODY_FACTORY}.rectangle(${x}, ${y}, ${width}, ${height})` ); break; default: throw new Error(`collisino body not support ${data.bodyType} shape!`); } ctx.println(');'); } export function setCollisionBodyConfig( ctx: PluginPureHook, component: CollisionBodyGameObject, ): void { const { collision_body: data } = component; if (data.firction) { ctx.println(`${local.BODY}.firction = ${data.firction};`); } if (data.firctionAir) { ctx.println(`${local.BODY}.firctionAir = ${data.firctionAir};`); } if (data.firctionStatic) { ctx.println(`${local.BODY}.firctionStatic = ${data.firctionStatic};`); } if (data.bounce) { ctx.println(`${local.BODY}.restitution = ${data.bounce};`); } if (data.mass) { ctx.println(`${local.BODY}.mass = ${data.mass};`); } if (data.group) { ctx.println(`${local.BODY}.collisionFilter.category = ${hashCode(data.group)};`); ctx.println(`${local.BODY}.collisionFilter.mask = ${hashCode(data.group)};`); } if (data.isSleeping) { ctx.println(`${local.BODY}.isSensor = true;`); } if (data.isSensor) { ctx.println(`${local.BODY}.isSensor = true;`); } if (data.isStatic) { ctx.println(`${local.BODY}.isStatic = true;`); } } export function attachCollisionBody(ctx: PluginPureHook, component: Component): void { if (isComponentCanAttachCollictionBody(component) && component.children && component.children.length > 0) { const collisionChild = component.children.find(child => isCollisionBody(child)); const blk = new LocalBody(ctx); if (!collisionChild || !isCollisionBody(collisionChild)) { return; } ctx.comment( `@name ${component.name}\n@external attach collision bodies` ); blk.in(); ctx.print(`${global.GAME_BODY}.create(`); ctx.push(); ctx.print('parts: '); ctx.push(BlockPair.bracket); component.children.forEach(child => { if (isCollisionBody(child)) { ctx.println(`${global.GAME_BODY_MAP}.get('${child.id}'),`); } }); ctx.pop(false); ctx.println(','); ctx.pop(false); ctx.println(');'); setCollisionBodyConfig(ctx, collisionChild); ctx.println(`this.matter.add.gameObject(${local.COMPONENT}, ${local.BODY});`); blk.out(); } }