Цели:
понять что такое MVC и ООП
научиться кодить на AS3
Решение:
написать скрипт/проект по следующему ТЗ:
Цитата:
Написать программу с применением ООП в MVC. Шарик (X, Y, масса, коэф. упругости, радиус и цвет(hex) указаны в data/set.txt) "пинается" курсором и падает на землю по физ. законам, вместе с отскоком от стены и земли.
Не реализовано в проекте:
отскок (вместо него костыль который обнуляет скорость, когда шарик касается "пол" сцены)
Много где костылей, много где не доделано. Основная задача разобраться с AS3, MVC.
|
Результат (+прикрепил весь проект
as.rar):
mvc/Main.as

Код AS3:
package mvc
{
import flash.display.Sprite;
import mvc.*;
public class Main extends Sprite
{
private var _model:Model;
private var _view:Viewer;
private var _controller:Controller;
public function Main()
{
_model = new Model(stage); // я так понимаю с точки зрения MVC я сделал крупную ошибку передав всю сцену? см. 118-119 строки модели
_view = new Viewer(_model);
super.addChild(_view);
_controller = new Controller(_view, _model);
}
}
}
mvc/Controller.as

Код AS3:
package mvc
{
import flash.events.*;
import flash.utils.Timer;
public class Controller extends EventDispatcher
{
private var _model:Model;
private var _view:Viewer;
public function Controller(view:Viewer, model:Model)
{
_view = view;
_model = model;
_view.stage.getChildByName('root1').addEventListener(MouseEvent.CLICK, _model.getDataObj); // так и не понял, почему root1 название? вроде везде mc_create
_model.loadData.addEventListener(Event.COMPLETE, _model.createObj); // после загрузки txt файла с параметрами, вызываем метод создания шара
_model.addEventListener('sharCreated', _view.addObj);
_view.addEventListener('sharShowed', InitEvents);
}
private function InitEvents(e:Event):void
{
_model.currentShar.addEventListener(Event.ENTER_FRAME, _model.passivMove);
_model.currentShar.Obj.addEventListener(MouseEvent.MOUSE_OVER, _model.mouseMove);
var time:Timer=new Timer(50, 0); // каждые 50 мс вычисляем скорость мыши по текущим и предыдущим координатам
time.addEventListener(TimerEvent.TIMER, _model.OnTimeCursorV);
time.start();
}
}
}
mvc/Model.as

Код AS3:
package mvc
{
import flash.events.*;
import objects.Shar;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.EventDispatcher;
import flash.display.Stage;
public class Model extends EventDispatcher
{
public var currentShar:Shar;
public var loadData:URLLoader=new URLLoader();
private var stage:Stage;
private const CURSOR_WEIGHT:Number=5; //масса шарика
private var g:Number; // сила тяжесть
private var stageWidth:uint;
private var stageHeight:uint;
private var cursorV:Number=0; // сохраненная скорость мыши в момент столкновения
private var cursorCurrentV:Number=0; // текущая(мгновенная) скорость мыши
private var cursorLastX:Number;
private var cursorLastY:Number;
private var lastLocalX:Number=0;
private var lastLocalY:Number=0;
public function Model(stage:Stage)
{
this.stage=stage; // я так понимаю с точки зрения MVC я сделал крупную ошибку передав всю сцену? см. 118-119 строки
this.g=10/stage.frameRate; // сила тяжесть
this.stageWidth=stage.stageWidth;
this.stageHeight=stage.stageHeight;
this.cursorLastX=stageWidth/2;
this.cursorLastY=stageHeight/2;
}
public function getDataObj(e:Event):void
{
e.target.stage.getChildByName('root1').removeEventListener(MouseEvent.CLICK, getDataObj);
//e.target.stage.removeChild(e.target.stage.getChildByName('root1')); // удаление кнопки, почемуто если удалить кнопку, то все перестает работать
loadData.load(new URLRequest('data/set.txt')); // считали параметры шара из файла
}
public function createObj(e:Event = null):void
{
var arr:Array=new Array();
arr=loadData.data.split(';');
currentShar=new Shar({ // создали экземпляр шара по параметрам из файла (класс objects/Shar.as)
X:arr[0],
Y:arr[1],
M:arr[2],
E:arr[3],
R:arr[4],
C:arr[5]
});
dispatchEvent(new Event('sharCreated'));
}
public function passivMove(e:Event):void
{
var shar:Object=e.target;
// сохраненная скорость мыши при столкновении постепенно уменьшается до 0
if(this.cursorV>0)
this.cursorV-=g;
else if(this.cursorV<0)
this.cursorV=0;
var Fc:Number=this.CURSOR_WEIGHT*this.cursorV; // вычислить вектор столкновения мыши с шариком (если мышь не сталкивалась тоthis.cursorV=0 и вектор=0)
var XFc:Number=(lastLocalX/shar.R)*Fc;
var YFc:Number=(-lastLocalY/shar.R)*Fc;
var Fs:Number=shar.M*shar.V; // вычисляем mg
var XFs:Number=0*Fs; // знаю что бессмысленно умножать на 0, но с точки зрения физики так понятней, сейчас разговор идет исключительно про MVC и ООП
var YFs:Number=1*Fs;
var Nx:Number=XFs+XFc; // вычисляем новый результирующий вектор
var Ny:Number=YFs+YFc;
shar.direc=Math.atan2(Ny, -Nx); // вычисляем новый угол движения шара
shar.A=Math.sqrt(Ny*Ny+Nx*Nx)*0.05; // вычисляем скалярную величину нового векутор (0.05 - коэф. ибо без него слишком быстро меняеться)
shar.V+=shar.A; // изменяем скорость шарика
shar.X+=shar.V*Math.cos(shar.direc); // изменяем координаты, лучше делать через _viewer.updateObj ?
shar.Y+=shar.V*Math.sin(shar.direc); // изменяем координаты, лучше делать через _viewer.updateObj ?
// далее идут вычисления границу сцены и предотвращения ухода за них шара
if(shar.Y+shar.R>=stageHeight)
{
shar.Y=stageHeight-shar.R;
shar.V=0; // сбрасываем скорость на 0, когда шар упал вниз сцены, правильнее будет делать отскок от сцены за счет изменения shar.direc
}
if(shar.Y-shar.R<=0)
{
shar.Y=shar.R;
shar.V=0; // если уперся в потолок, тоже сбрасываем скорость на 0, в идеале опять же сделать отскок
}
if(shar.X+shar.R>=stageWidth)
{
shar.X=stageWidth-shar.R;
}
if(shar.X-shar.R<=0)
{
shar.X=shar.R;
}
}
public function OnTimeCursorV(e:TimerEvent):void
{
var dX:Number=Math.abs(stage.mouseX-cursorLastX); // через таймер же не предать stage.mouseX, он нужен для вычисления скорости мышки за счет измерения изменения координат курсора
var dY:Number=Math.abs(stage.mouseY-cursorLastY);
this.cursorCurrentV=Math.sqrt(dX*dX+dY*dY); // мгновенная скорость см. 127 строку
this.cursorLastX=stage.mouseX;
this.cursorLastY=stage.mouseY;
}
public function mouseMove(e:MouseEvent):void
{
this.cursorV=this.cursorCurrentV; // мгновенная становиться текущуй скоростью, и используеться в расчетах именно она в момент сталкнвовения с мыщью
this.lastLocalX=e.localX; // сохраняем координаты мыши для вычисления вектора силы мыши
this.lastLocalY=e.localY;
}
}
}
mvc/Viewer.as

Код AS3:
package mvc
{
import flash.display.Sprite;
import flash.events.*;
import objects.Shar;
public class Viewer extends Sprite
{
private var _model:Model;
public function Viewer(model:Model)
{
_model=model;
}
public function addObj(e:Event):void
{
addChild(e.target.currentShar.Obj);
dispatchEvent(new Event('sharShowed'));
}
public function updateObj(x:Number, y:Number) // пожалуй, этим должен заниматься вьювер, но как туда предать параметры через контроллер? Или можно передать ссылку на сам вьювер?
{
_model.currentShar.X=x;
_model.currentShar.Y=y;
}
}
}
objects/Shar.as

Код AS3:
package objects
{
import flash.display.Sprite;
public class Shar extends Sprite
{
private var _obj:Sprite=new Sprite();
private var _X:Number;
private var _Y:Number;
private var _M:Number;
private var _E:Number;
private var _R:uint;
private var _C:uint;
private var _V:Number=1;
private var _A:Number;
private var _direc:Number=1.5*Math.PI;
public function Shar(param:Object)
{
this.M=param.M;
this.E=param.E;
this.C=param.C;
this.Obj.graphics.drawCircle(0, 0, param.R);
this.R=param.R;
this.X=param.X;
this.Y=param.Y;
}
public function get Obj():Object
{
return this._obj;
}
public function set X(X:Number):void
{
_X=X;
this.Obj.x=X;
}
public function get X():Number
{
return _X;
}
public function set Y(Y:Number):void
{
_Y=Y;
this.Obj.y=Y;
}
public function get Y():Number
{
return _Y;
}
public function set R(r:uint):void
{
_R=r;
this.Obj.width=r*2;
this.Obj.height=r*2;
}
public function get R():uint
{
return _R;
}
public function set C(c:uint):void
{
_C=c;
this.Obj.graphics.beginFill(c);
}
public function get C():uint
{
return _C;
}
public function set E(e:Number):void
{
_E=e;
}
public function get E():Number
{
return _E;
}
public function set M(m:Number):void
{
_M=m;
}
public function get M():Number
{
return _M;
}
public function set V(v:Number):void
{
_V=v;
}
public function get V():Number
{
return _V;
}
public function set A(a:Number):void
{
_A=a;
}
public function get A():Number
{
return _A;
}
public function set direc(d:Number):void
{
_direc=d;
}
public function get direc():Number
{
return _direc;
}
}
}
(упс, спойлер не пашет)
Вопросы:
как все поняли в AS я новичок, хотел бы, чтобы меня тыкнули носом в мои ошибки (все, кроме физики объекта), и услышать как бы вы реализовали с точки зрения MVC данный проект, какие есть
направления MVC и т.п.
P. S. "движка" громко сказано =)