MessageBoxPlusを作る
今まではCircleやRectを移動して、
きちんと動いているか確認してきました。
しかし物足りなさを感じます。
文字を入力した出力したりするものがあると
とても便利です。
まずはTextFieldを使って文字を表示したりすることから初めて。
簡単な"メッセージボックス+"なものを作ってみましょう。
SWFTextField
文字を表示する
include_once("mcObject.php");
class mcText extends mcObject
{
function __construct($name)
{
parent::__construct($name);
$text = new SWFTextField();
$text->setColor(0x00, 0x80, 0xc0);
$font = new SWFFont('UTF8');
$text->setFont($font);
$text->addString("ass縺ィ縺玲・縺ッdfdfgdfgdA");
$this->setFigure($text);
}
}
ming_useSWFVersion(6);
$A = new SWFMovie();
$B = new mcText("text");
$B->compile();
$A->add($B->getMovieclip());
$A->nextFrame();
$A->save("text.swf");
utf-8で保存すると日本語で表示されます。
作成されたもの
フレームを作る
マウス操作によって、移動するようなものを作る。
<?php
include_once("mcObject.php");
include_once("mcRect.php");
class Frame extends mcObject
{
function __construct($name)
{
parent::__construct($name);
$pen = new SWFShape();
$pen->setLine(1,0,30,20);
$pen->setRightFill(200,10,10,100);
$pen->movePenTo(0,0);
$pen->drawLine(0,100);
$pen->drawLine(80,0);
$pen->drawLine(0,-100);
$pen->drawLine(-80,0);
$this->setFigure_name($pen,"base");
$this->setAction(
new SWFAction(
" base.onPress=function(){ this.startDrag('');};
base.onRelease=function(){ stopDrag();};"
)
);
}
}
ming_useswfversion(6);
$f = new Frame("frame");
$f->compile();
$m = new SWFMovie();
$m->add($f->getMovieclip());
$m->nextFrame();
$m->save("Frame.swf");
?>
作成したもの
Frameにテキストを張る
Frameにテキストを張ることにします。ただしここで問題が生じている
思います。onPressが邪魔をして、TextAreaに書き込めなくなっていませんか?
tabキーを押すとよいのですが、使い勝手が少し悪いと思います。
たとえば、親が優先されて選択されてしまうのが気に入りません。子を優先した
ものに変更をします。onRollOverなども親を優先しています
そこで、どのmovieclipがさされているのかを、特定してあげる機能を追加
してみることにしましょう。
hitAreaのテスト
this.onEnterFrame = function(){ this.output.opt.text += 'Fra :'+ hitTest(_root._xmouse,_root._ymouse,true);};
作成したもの
実現のためhitTest()を使ってみる。 "作成したもの"を見ると
親movieclipは子movieclipの範囲まで調べてくれるので、
親が呼び出されたらとりあえず子を呼びだすという形でうまくいきそうです。
後 onEnterFrameが子から実行されているのも使えるかもしれません。
まあ、ドラックアンドドロップの機能を子に持たせればよいだけかもしれませんが
深く考えないことしよ。
for in
テスト
for( b in this){
this.output.opt.text += b+'\n';
}
movieclip(frame)が保持するものを取り出す。
typeof
型チェック
チェック
this.onEnterFrame = function()
{
for( b in this){
this.output.opt.text +=b +'\n'+ typeof(this[b])+'\n';
}
};
状態をつくる
とりあえず、状態を作りましょう。状態というのはあれです。
var state;
function =init()
{
state = ****
}
function = changeState(sta)
{
state = sta;
};
onEnterFrame = function()
{
state.EnterFrame(this);
};
といったものをつくります。 とりあえず機能の入れ替えが楽になります。
まあ、るんどくさらず、階層ごとごっそり入れ替える xstate(勝手に命名)とか
も考えられますね?作らないけど。
(
*コメント やはり interfaceとかないと不便ですね。 書き間違えても教えてくれないのです。
エラーチェックが増えて、作業効率は低下しています。 まあ、movieclipは重いけど便利な機能が
いっぱいあるし、actionsriptは充実していますから、差し引き "零" と
いうことで、..。 mingはクラスにいつ対応するのだろう(2004.12.05)?
あと、今回は_globalは使わないことにする。)
initをキチント作る前に
Stateを実現するにはinitがしっかりしていたほうがよいと思います。
が、とりあえず、動かしてみる。
変更できないstate?
movieclipをクリックして キーボードのDを押すとDragDropでできるようになります。
D以外押すと、移動しなくなります。
作ったもの
./dragAct.php
$this->setAction(new SWFAction("
var dragdrop;
var x;
var y;
EnterFrame = function(mc){
;
};
MouseDown = function(mc){
dragdrop = 1;
};
MouseUp = function(mc){
dragdrop = 0;
};
MouseMove = function(mc){
if(dragdrop ==1){
mc._x += _root._xmouse -x; mc._y +=_root._ymouse -y;
}
x = _root._xmouse;
y = _root._ymouse;
};
"));
./frame.php
$this->setAction(
new SWFAction(
"
var state;// = _root.dragact;
focusEnabled =true;
Selection.setFocus(this);
onKeyDown = function()
{
if(68 == Key.getCode())
{
state = _root.dragact;
}
else
{
state = movieclip;
}
};
onEnterFrame = function()
{
state.EnterFrame(this);
};
onMouseDown = function()
{
state.MouseDown(this);
};
onMouseUp=function()
{
state.MouseUp(this);
};
onMouseMove = function()
{
state.MouseMove(this);
};
"
)
);
詳しくはおまけ2
問題点
initをつくっておけば、
focusEnabled =true;
Selection.setFocus(this);
もinitにまかせればいいやと思ったけれども、ループする気に
かならずfalseで初期化されているようである。
これは非効率だね。← 間違い
SelectionはクリップボードのようなものでsetFocus(this)は、desetFocus見たいな感じて
はずさなくても、別のものにsetFocusされると自動的にはすされる。
詳しくはおまけ3をみて。
こんな感じ
あと、相互に参照している場合、
もう初期化したよということを伝えるために、
init_optをinitに追加しました。
どのmovieclipが選択されるか特定するためものを作る
MessageBoxていどのものを作るのにこんなことをする必要はありませんが
さあ、作ってみよう。 あと 親子関係が単純な場合も必要ないですが.....
ちなみに、今回はとても単純構造をしておりますので、... 気にしない気にしい
setFocusという手もあるかも知れないけど....
(コメント:: 作りたい物が特にないので、ごめんなさい)
initの改造
./現在 init_optに依存している
init = function(mc)
{
_root.frame.output.opt.text += 'dragact';
for(m in mc)
{
if('movieclip' == typeof(mc[m])){
if(mc[m].init_opt != 1){
mc[m].init_opt = 1;
mc[m].init();
_root.baseact.init(mc[m]);
}
}
}
};
これらのmovieclipを取り出す場所と そのmovieclipに何をするのかの部分に分ける。
あと、別のmovieclipに移すと使いやすくなるかもしれないが作業が大掛かりなるので
関数のように使う。
init_optわなくして、Arrayに参照を渡して === で比較する用にする
./新しいの
*******
./focus用
**********
やっぱりやめる、 もしも、何重にもmovieclipが重なることを考える、
すべのmovieclipの参照を保持しているのは非効率に感じる。 そもそも、
まだわたしはmovieclipが参照渡しか確認していない。まあ。名前などで
管理すれば、そんなに重くなることはないと思いますが、....。
ということで、探し出してほしいmovieclipは必ずbaseact_optionを
保持していなくてはならないことにします。以下
注意
typeof()でundefinedと返される場合、 宣言していない場合も、中身が決まって強いない場合どちらもundefinedとでる
存在するのか知りたい場合は大変です。
といことで init()の時必ず何か代入しておくほうがいいのかもしれない
中身がない場合はundefineを返します。 宣言するだけでは undefineなことに注意。
関数だってオブジェクトのように扱える
var search_exe;
var searchz_exe;
var baseact_option;
init = function()
{
baseact_option = 0;
search_exe = exe;
};
exe = function()
{
_root.frame.output.opt.text += 'mcxcvbxcvb';
};
もしかすると、すべてに対して行うならも init_opt baeact_optionはいらないかもしりない?
...多分 調べいけど。 ..調べる
いつでも宣言できるのですね? つまりいらないです。 そのかわり、上書きされるので
init_opt baeact_optionはつかってはいけないという設定になります、
できた
var init_opt;
var search_exe;
var baseact_option;
focusMovie = function()
{
search_exe = exe;
searchMovieclip(_root);
clearSearch();
}
init = function()
{
baseact_option = 0;
//
};
exe = function(mc)
{
_root.frame.output.opt.text +=mc +'\n';
if('true' == mc.hitTest(_root._xmouse,_root._ymouse,true) )
{
if( 0 == this.searchMovieclip(mc))
{
mc.focusEnabled =true;
mc.setFocus(mc);
}
return 1;
}
return 0;
};
searchMovieclip = function(mc)
{
chck = 0;
for(m in mc)
{
if('movieclip' == typeof(mc[m]))
{
if('undefined' !=typeof(mc[m]['baseact_option']) && mc[m].baseact_option != 1)
{
mc[m].baseact_option = 1;
chck = search_exe(mc[m]);
}
}
}
return chck;
};
改善1
onMouseDownで上記は使うことを想定していますが、focusを手放すまで
調べる必要はない。 次はこれを実装する。
いろいろ
本当はmovieclipは個々で動いているので、自分の親に対してだけ、
私がfocus持ってるよと知らせてあげるだけでよいのです。
ためしに、onMouseDownが実行される順番を調べて見ましょう。
もしも、子から行われているのでしたら。この問題は簡単になります。
子がが実行された場合、親は何もしないとしてあげるだけでよくなります。
iroiro.swf iroiro.lzh
ということで、子から、そして後ろの方から実行されていきます。
_frame -- textare
|
_root
|_ obj
↑ 参考程度に、
おまけ1
./TextArea.php
<?
include_once("mcObject.php");
class mcTextArea extends mcObject
{
function __construct($name)
{
parent::__construct($name);
$text = new SWFTextField(SWFTEXTFIELD_DRAWBOX| SWFTEXTFIELD_MULTILINE | SWFTEXTFIELD_WORDWRAP | SWFTEXTFIELD_USEFONT );
$text->setColor(0x00, 0x80, 0xc0);
$text->setbounds(60,80);
$font = new SWFFont('UTF8');
$text->setFont($font);
$text->addString("◎");
$this->setFigure_name($text,"opt");
$this->setAction(new SWFAction("
this.onEnterFrame = function(){this.opt.text = 'Area:'+ hitTest(_root._xmouse,_root._ymouse,true)+'\n';};
"));
}
}
/*
ming_useswfversion(6);
$f = new mcTextArea("frame");
$f->compile();
$m = new SWFMovie();
$m->add($f->getMovieclip());
$m->nextFrame();
$m->save("TextArea.swf");
*/
?>
./Frame.php
<?php
include_once("mcObject.php");
include_once("TextArea.php");
class Frame extends mcObject
{
function __construct($name)
{
parent::__construct($name);
$pen = new SWFShape();
$pen->setLine(1,0,30,20);
$pen->setRightFill(200,10,10,100);
$pen->movePenTo(0,0);
$pen->drawLine(0,100);
$pen->drawLine(80,0);
$pen->drawLine(0,-100);
$pen->drawLine(-80,0);
$this->setFigure_name($pen,"base");
$area = new mcTextArea("output");
$this->addmcObject($area);
$this->setAction(
new SWFAction(
"
var state;
var x;
var y;
this.onEnterFrame = function(){ this.output.opt.text += 'Fra :'+ hitTest(_root._xmouse,_root._ymouse,true);};
onMouseDown = function()
{
state = 1;
};
onMouseUp=function(){state = 0;};
onMouseMove = function()
{
if(state ==1)
{
this._x += _root._xmouse -x; this._y +=_root._ymouse -y;
}
x = _root._xmouse;
y = _root._ymouse;
};
"
)
);
}
}
ming_useswfversion(6);
$f = new Frame("frame");
$f->compile();
$m = new SWFMovie();
$i=$m->add($f->getMovieclip());
$i->setName("frame");
$m->nextFrame();
$m->save("Frame.swf");
?>
./mcObject.php
class mcObject
{
protected $_movieclip; //SWFSprite
protected $_displayitem;//SWFDisplayitem
protected $_action;
protected $_figure;
protected $_figurename;
protected $_name;
protected $_mcObjects;
function __construct($name)
{
print("mcObject const \n");
$this->_name = $name;
$this->_action= null;
$this->_figure = null;
$this->_displayitem = null;
$this->_movieclip = new SWFSprite();
$this->_mcObjects = array();
}
function addmcObject($obj){
$this->_mcObjects[count($this->_mcObjects)+1] = $obj;
}
function setName($name)
{
$this->_name = $name;
}
function getName()
{
return $this->_name;
}
function setDisplayitem($dis)
{
print("get".$this->_displayitem);
$this->_displayitem = $dis;
}
function getDisplayitem()
{
// print("ge$this->_displayitem);
return $this->_displayitem;
}
function setAction($pen)
{
$this->_action = $pen;
}
function setFigure($pen)
{
$this->_figure = $pen;
}
function setFigure_name($pen,$nam)
{
$this->_figure = $pen;
$this->_figurename = $nam;
}
function getMovieclip()
{
return $this->_movieclip;
}
function compile()
{
if($this->_figure != null){
print("figure_compile");
$a = $this->_movieclip->add($this->_figure);
}
$a->setName($this->_figurename);
print("\n".$this->_figurename."\n");
for($i=0; $i < count($this->_mcObjects)+1;$i++)
{
if($this->_mcObjects[$i] != null)
{
$this->_mcObjects[$i]->compile();
$this->_mcObjects[$i]->setDisplayitem
(
$this->_movieclip->add($this->_mcObjects[$i]->getMovieclip())
);
$this->_mcObjects[$i]->getDisplayitem()->setName($this->_mcObjects[$i]->getName());
$this->_mcObjects[$i]->getDisplayitem()->moveTo(70,70);
print "\n pla ".$this->_mcObjects[$i]->getName();
}
}
$this->_movieclip->nextFrame();
if($this->_action !=null){
print("act\n");
$this->_movieclip->add($this->_action);
$this->_movieclip->nextFrame();
}
}
}
おまけ2
state_00.zip
ExeでのsetNameなど手抜きですが
おまけ3
omake3.lzh
戻る