Передвижение мира
Вложений: 1
Доброго времени!
Пытаюсь написать визуализацию компании (схема с ответвлениями).
Использую для физики Box2d . В центре сцены статический объект с привязанным к нему мувиклипом от него идут связи с другими динамическими объектами. Пример прикреплён. В дальнейшем при клике на любой динамический объект будет ещё ответвления со связями ИТП. Получается некое подобие графической карты.
Вопрос в том чтобы организовать скроллинг всей этой карты мышкой при клике на свободную область.
Координаты чего надо менять (пересчитывать)?
Форум я читал, но если честно я так и не понял что к чему, сильно не пинайте box2d изучаю ровно 3 дня, но уже голова кругом. Сильно не пинайте.
Сам движок я изучал по достаточно неплохим туториалам с сайта http://redefy.net. Увы там описано не всё.
Во сам скрипт:
Код AS3:
package
{
/* Классы Box2d */
import adobe.utils.CustomActions;
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2CircleShape;
import Box2D.Collision.Shapes.b2PolygonShape;
import Box2D.Collision.Shapes.b2Shape;
import Box2D.Common.b2Color;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2Fixture;
import Box2D.Dynamics.b2FixtureDef;
import Box2D.Dynamics.b2World;
import Box2D.Dynamics.Joints.*;
import flash.display.MovieClip;
/* import Box2D.Dynamics.Joints.b2LineJoint;
import Box2D.Dynamics.Joints.b2MouseJoint;
import Box2D.Dynamics.Joints.b2MouseJointDef;
import Box2D.Dynamics.Joints.b2JointDef;
import Box2D.Dynamics.Joints.b2DistanceJoint;
import Box2D.Dynamics.Joints.b2DistanceJointDef;
import Box2D.Dynamics.Joints.b2FrictionJointDef;
import Box2D.Dynamics.Joints.b2JointEdge;
*/
import flash.display.Graphics;
/* Классы встроенные во Flash */
import flash.display.Shape;
import flash.display.Graphics;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
/* Пользовательские классы */
/**
* @author Andrey Averin
*/
[SWF(width = "800", height = "600", framerate = "60", backgroundColor = 0xFFFFFF)] // с какими параметрами запускается сам ролик
public class Main extends Sprite
{
private var world:b2World; //Создаём мир
private var meters:int = 30; // один метр будет равен 30 пикселям
private var velocityIterations:int = 10;
private var positionIterations:int = 10;
private var timeStep:Number = 1.0 / 24.0;
private var isMouseDown:Boolean = false;
private var debugSprite:Sprite = new Sprite();
private var logo:Sprite = new logoMC();
public function Main():void // Конструктор
{
graphics.beginFill(0xc7c7c7);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
addChild(debugSprite);
// логотип
logo.x = logo.width - 77;
logo.y = logo.height - 30;
createWorld(); // создаёт мир box2d
//createWallStage(); // создаёт стены мира (не уверен что они нужны)
createBodies();
createDebugDraw(); // метод включает дебаг для объектов box2d
addEventListener(Event.ENTER_FRAME, update);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(MouseEvent.MOUSE_DOWN, flagCheck);
stage.addEventListener(MouseEvent.MOUSE_UP, flagCheck);
stage.addEventListener(Event.RESIZE, onResizeStage); // Отрисовываем стены при измнении размера флеш ролика
stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
}
private function onResizeStage(e:Event):void { // Здесь будет перерисовываться границы из твёрдых тел
//var bb:b2Body; //тело
for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext() ) {
//if (bb.GetType() == b2Body.b2_staticBody) {
if (bb.GetUserData()) {
//world.DestroyBody(bb);
var data:Array = bb.GetUserData();
var clip:MovieClip = data[0];
trace(clip);
}
}
//this.createBodies();
//trace(stage.x);
}
private function handleMouseWheel(e:MouseEvent):void { // прокрутка мыши
trace(stage.width);
}
private function createWorld():void { // метод создания мира
var gravity:b2Vec2 = b2Vec2.Make(0.0, 0.0);
var sleepingBody:Boolean = true;
world = new b2World(gravity, sleepingBody);
}
private function createWallStage():void { //создадим статические тела по границам сцены чтобы наши тела не вылетали за нее
// очищаем мир от статических тел
/* var bb:b2Body; //тело
for (bb = world.GetBodyList(); bb; bb = bb.GetNext() ) {
if (bb.GetType() == b2Body.b2_staticBody) {
world.DestroyBody(bb);
}
}
*/
var body:b2Body; //тело
var bodyDef:b2BodyDef; //геометрические настройки тела
var bodyShapePoligon:b2PolygonShape;
var wallThickness:Number = 2; // толщина стен, ( он же width )
//left
/* bodyDef = new b2BodyDef(); //создаем b2BodyDef геометрические свойства тела
bodyDef.type = b2Body.b2_staticBody; //
bodyDef.active = true;
bodyDef.position.Set(wallThickness/meters/2, stage.stageHeight/meters/2); //устанавливаем позицию тела на сцене
bodyShapePoligon = new b2PolygonShape();
bodyShapePoligon.SetAsBox(wallThickness/meters/ 2, stage.stageHeight / meters / 2);
body = world.CreateBody(bodyDef); //создаем тело
body.CreateFixture2(bodyShapePoligon);
//right
bodyDef = new b2BodyDef(); //создаем b2BodyDef
bodyDef.position.Set((stage.stageWidth-wallThickness/2)/meters, stage.stageHeight/meters/2); //устанавливаем позицию тела на сцене
body = world.CreateBody(bodyDef);//создаем тело
body.CreateFixture2(bodyShapePoligon);
//down
bodyDef = new b2BodyDef(); //создаем b2BodyDef
bodyDef.position.Set(stage.stageWidth/2/meters, (stage.stageHeight-wallThickness/2)/meters);
bodyShapePoligon = new b2PolygonShape();
bodyShapePoligon.SetAsBox(stage.stageWidth/meters/ 2, wallThickness / meters / 2); //устанавливаем позицию тела на сцене
body = world.CreateBody(bodyDef); //создаем тело
body.CreateFixture2(bodyShapePoligon);
//up
bodyDef = new b2BodyDef(); //создаем b2BodyDef
bodyDef.position.Set(stage.stageWidth/2/meters, wallThickness/2/meters); //устанавливаем позицию тела на сцене
body = world.CreateBody(bodyDef); //создаем тело
body.CreateFixture2(bodyShapePoligon);
*/
}
private function createBodies():void { // Создание тел на сцене
var body:b2Body;
var bodyA:b2Body;
var bodyDef:b2BodyDef;
var bodyShapePoligon:b2PolygonShape;
var bodyShapeCircle:b2CircleShape;
var fixture:b2FixtureDef;
var jointDef:b2JointDef; //определение соединения
//var jointDef:b2DistanceJointDef; //определение соединения
//var joint:b2DistanceJoint; //соединение
// Главный спрайт компании BodyA
var company:Sprite = new companyMC();
var userdadaStaticStore:Array = new Array(company); // массив присоедияемых к телу данных
bodyDef = new b2BodyDef();
bodyDef.position.Set(stage.stageWidth / meters / 2, stage.stageHeight / meters / 2);
bodyDef.userData = userdadaStaticStore;
bodyA = world.CreateBody(bodyDef);
bodyShapePoligon = new b2PolygonShape();
bodyShapePoligon.SetAsBox((company.width /2) / meters, (company.height /2 - 10) / meters);
bodyA.CreateFixture2(bodyShapePoligon);
var i:int;
for (i = 0; i < 5; i++) {
var connectionLine:Sprite = new Sprite(); // линия соединитель
connectionLine.graphics.lineStyle(1, 0xc7c7c7, 1);
addChild(connectionLine);
var clip:Sprite = new humanMC(); // тело компаньона
clip.x = clip.x + Math.random() * 500;
clip.y = clip.y + Math.random() * 500;
addChild(clip);
// рисуеми тело
bodyDef = new b2BodyDef();
//bodyDef.position.Set((Math.random() * 700 +50) / meters, 100 / meters / 2);
bodyDef.position.Set(clip.x / meters, clip.y / meters);
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.fixedRotation = true; // запрещаем вращение
//bodyDef.linearVelocity.Set(Math.random() * 10, Math.random() * 10);
bodyDef.linearVelocity.Set(5, 5);
var userdadaStore:Array = new Array(clip, connectionLine); // массив присоедияемых к телу данных
//userdadaStore[0] = clip;
//userdadaStore[1] = ConnectionLine;
//bodyDef.userData = clip;
bodyDef.userData = userdadaStore;
body = world.CreateBody(bodyDef);
bodyShapePoligon = new b2PolygonShape();
//bodyShapePoligon.SetAsBox((Math.random() * 25 + 5) / meters, (Math.random() * 25 + 5) / meters);
bodyShapePoligon.SetAsBox( ( (clip.width - 15) / meters)/2, ( (clip.height - 15) / meters)/2);
fixture = new b2FixtureDef();
//fixture.density = Math.random() * 9 + 1; //
fixture.shape = bodyShapePoligon;
body.CreateFixture(fixture);
jointDef = new b2FrictionJointDef(); //создаем определение соединения первым способом
b2FrictionJointDef(jointDef).bodyA = bodyA; //первое тело
b2FrictionJointDef(jointDef).bodyB = body; //второе тело
b2FrictionJointDef(jointDef).localAnchorA = new b2Vec2(-0.3, 0); //якорная точка первого тела
b2FrictionJointDef(jointDef).localAnchorB = new b2Vec2(-0.3, 0); //якорная точка второго тела
b2FrictionJointDef(jointDef).maxForce = 1000; //максимальная сила
b2FrictionJointDef(jointDef).maxTorque = 0; //максимальный крутящмй момент
world.CreateJoint(jointDef); //создаем и добавляем соединение в мир
}
addChild(company);
}
private function clickChecker(e:Event):void {
trace(e.target.body);
}
private function createDebugDraw():void {
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(30.0);
debugDraw.SetFillAlpha(0.4);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);
world.DrawDebugData();
}
private function update(e:Event):void { // Метод обновления мира
for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext() ) {
if (bb.GetUserData()) {
var data:Array = bb.GetUserData(); // забираем массив данных привязанных к телу box2d
//trace(data[1]);
// тут происходит привязка мувиклипов к телам box2d (без этого никак)
data[0].x = bb.GetPosition().x * meters; // по оси X
data[0].y = bb.GetPosition().y * meters; // по оси Y
data[0].rotation = bb.GetAngle() * (180 / Math.PI) % 360; // здесь включется вращение тела если разрешено вращение
for (var jj:b2JointEdge = bb.GetJointList(); jj; jj = jj.next){
//trace(jj.joint.GetAnchorA().x, jj.joint.GetAnchorA().y);
//trace(bb.GetUserData());
// линии соединители (обработка координат)
if(data.length > 1){
data[1].graphics.clear();
data[1].graphics.lineStyle(1, 0x88000, 1);
data[1].graphics.moveTo(jj.joint.GetAnchorA().x * meters, jj.joint.GetAnchorA().y * meters);
data[1].graphics.lineTo(jj.joint.GetAnchorB().x * meters, jj.joint.GetAnchorB().y * meters);
}
}
}
}
UpdateMouseWorld();
MouseDrag();
world.Step(timeStep, velocityIterations, positionIterations);
world.ClearForces();
world.DrawDebugData();
}
private function flagCheck(e:MouseEvent):void {
switch(e.type) {
case "mouseDown":
isMouseDown = true;
break;
case "mouseUp":
isMouseDown = false;
break;
}
}
//////////////////////////////////////////////////////////////////////////
private var m_mouseJoint:b2MouseJoint;
static public var mouseXWorldPhys:Number;
static public var mouseYWorldPhys:Number;
static public var mouseXWorld:Number;
static public var mouseYWorld:Number;
public function UpdateMouseWorld():void{
mouseXWorldPhys = mouseX/meters;
mouseYWorldPhys = mouseY/meters;
mouseXWorld = mouseX;
mouseYWorld = mouseY;
}
public function MouseDrag():void{
if (isMouseDown && !m_mouseJoint){
var body:b2Body = GetBodyAtMouse();
if (body != null){ // перемещение одного елемента
var md:b2MouseJointDef = new b2MouseJointDef();
md.bodyA = world.GetGroundBody();
md.bodyB = body;
md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
md.collideConnected = true;
md.maxForce = 3000;
m_mouseJoint = world.CreateJoint(md) as b2MouseJoint;
body.SetAwake(true);
} else {
// перемещение группы елементов
}
}
if (!isMouseDown){
if (m_mouseJoint){
world.DestroyJoint(m_mouseJoint);
m_mouseJoint = null;
}
}
if (m_mouseJoint){
var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
m_mouseJoint.SetTarget(p2);
}
}
private var mousePVec:b2Vec2 = new b2Vec2();
public function GetBodyAtMouse(includeStatic:Boolean = false):b2Body {
mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys);
var aabb:b2AABB = new b2AABB();
aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
var body:b2Body = null;
var fixture:b2Fixture;
function GetBodyCallback(fixture:b2Fixture):Boolean{
var shape:b2Shape = fixture.GetShape();
if (fixture.GetBody().GetType() != b2Body.b2_staticBody || includeStatic){
var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(), mousePVec);
if (inside){
body = fixture.GetBody();
return false;
}
}
return true;
}
world.QueryAABB(GetBodyCallback, aabb);
return body;
}
}
}
Тыкните пожалуйста в нужную сторону, как реализовать скроллинг карты. На сколько я понимаю координаты мира менять нельзя.
|