Jump to content
stobolewski

[FLASH] przeciąganie obiektów

Recommended Posts

Witam,

 

wiem, zaraz mnie zjecie za samą tematykę pytania ale cóż, radzę sobie jak umiem ;D

 

Zrobiłem prostą scenkę, w której za pomocą buttona dodaje się nowe obiekty [sPRITE] do sceny. Po dodaniu takiego obiektu można go przesunąć myszą po scence (wciśnięcie myszy - startDrag(), puszczenie - stopDrag()).

 

Problem w tym, że w momencie utworzenia kolejnego obiektu [sPRITE] tracę możliwość zaznaczenia i przeciągnięcia poprzedniego.

 

PYTANIE:

 

Co zrobić aby dało się swobodnie przeciągać wszystkie obiekciki na scence ?

Share this post


Link to post
Share on other sites

najwidoczniej źle odwołujesz się do obiektu, biorąc tylko ostatni.

Share this post


Link to post
Share on other sites

wsadzę część kodu, może to coś wyjaśni :)

 

kod "sceny"

import flash.events.MouseEvent;
import flash.events.Event;
import com.adobe.images.JPGEncoder;
btn_middleTable.addEventListener(MouseEvent.CLICK, f_middleIco);
btn_bigTable.addEventListener(MouseEvent.CLICK, f_bigIco);
btnSave.addEventListener(MouseEvent.CLICK, f_save);


function f_middleIco(event:MouseEvent):void
{
var middle:MiddleIco = new MiddleIco();
middle.x = 20;
middle.y = 20;
stage.addChild(middle);
trace("created");
}

function f_bigIco(event:MouseEvent):void
{
var big:BigIco = new BigIco();
big.x = 20;
big.y = 20;
stage.addChild(big);
trace("created");
}

 

kod obiektu (z oddzielnego pliku)

package  {

import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;


public class BigIco extends MovieClip {
		public var active:Boolean;

	public function BigIco() {
		// constructor code
		this.addEventListener(Event.ENTER_FRAME, f_move);
		this.addEventListener(MouseEvent.MOUSE_DOWN,downf);
		this.addEventListener(MouseEvent.MOUSE_UP,upf);
	}

	public function f_move(e:Event)
	{
		if(active==true)
		{
			startDrag();
		}
		else if(active==false)
		{
			stopDrag();
		}
	}

	public function downf(e:MouseEvent)
	{
		active = true;
	}
	public function upf(e:MouseEvent)
	{
		active = false;
	}

}

}

 

No i w klasie głównej buttonem tworzę instancje BigIco.

W klasie BigIco mam funkcję przesuwania i kończenia przesuwania obiektu.

Wielkim programista ze mnie nie jest więc myślałem, że skoro na jednej ikonce coś takiego działa to i na kilku będzie działało a tu zonk :/

funkcje działąją tylko na ostatnio dodanym obrazku.

 

Co ja robię nie tak, albo czego nie wiem a powinienem wiedzieć ?

Share this post


Link to post
Share on other sites

Sorka za dubla, ale udało się.

Oto rozwiązanie:

 

Klasa główna (z całym kodem - włącznie z datą i zliczaniem ilości miejsc przy stoliczkach).

 

import flash.events.MouseEvent;
import flash.events.Event;
import com.adobe.images.JPGEncoder;
import flash.events.KeyboardEvent;
import com.adobe.protocols.dict.Database;

var selected_item:int;
var big_table:int = 0;
var middle_table:int = 0;
var little_table:int = 0;

var actual_data:Date = new Date();
var the_data = actual_data.getDate();
data_field.text = " " + actual_data;

btn_middleTable.addEventListener(MouseEvent.CLICK, f_middleIco);
btn_bigTable.addEventListener(MouseEvent.CLICK, f_bigIco);
btn_littleTable.addEventListener(MouseEvent.CLICK, f_littleIco);
btnSave.addEventListener(MouseEvent.CLICK, f_save);

stage.addEventListener(Event.ENTER_FRAME, f_update);

stage.addEventListener(MouseEvent.MOUSE_DOWN, B_f_down);
stage.addEventListener(MouseEvent.MOUSE_UP, B_f_up);

stage.addEventListener(MouseEvent.MOUSE_DOWN, M_f_down);
stage.addEventListener(MouseEvent.MOUSE_UP, M_f_up);

stage.addEventListener(MouseEvent.MOUSE_DOWN, L_f_down);
stage.addEventListener(MouseEvent.MOUSE_UP, L_f_up);

function f_update(e:Event)
{
   dStoly.text = ""+big_table;
   sStoly.text = ""+middle_table;
   mStoly.text = ""+little_table;
   razemStoly.text = ""+(big_table+middle_table+little_table);
}

function L_f_down(e:MouseEvent)
{
   LittleIco.setDownVaue();
   trace("down");
   trace(LittleIco.active);
}
function L_f_up(e:MouseEvent)
{
   LittleIco.setUpVaue();
   trace("up");
   trace(LittleIco.active);
}
function B_f_down(e:MouseEvent)
{
   BigIco.setDownVaue();
   trace("down");
   trace(BigIco.active);
}
function B_f_up(e:MouseEvent)
{
   BigIco.setUpVaue();
   trace("up");
   trace(BigIco.active);
}
function M_f_down(e:MouseEvent)
{
   MiddleIco.setDownVaue();
   trace("down");
   trace(MiddleIco.active);
}
function M_f_up(e:MouseEvent)
{
   MiddleIco.setUpVaue();
   trace("up");
   trace(MiddleIco.active);
}

function f_littleIco(event:MouseEvent):void
{
   var little:LittleIco = new LittleIco();
   little.x = 20;
   little.y = 20;
   little_table+=4;
   stage.addChild(little);
   trace("created");
}

function f_middleIco(event:MouseEvent):void
{
   var middle:MiddleIco = new MiddleIco();
   middle.x = 20;
   middle.y = 20;
   middle_table+=6;
   stage.addChild(middle);
   trace("created");
}

function f_bigIco(event:MouseEvent):void
{
   var big:BigIco = new BigIco();
   big.x = 20;
   big.y = 20;
   big_table+=10;
   stage.addChild(big);
   trace("created : " + big_table);
}

function f_save(event:MouseEvent)
{
   var jpgEncoder:JPGEncoder;
   jpgEncoder = new JPGEncoder(90);

   var bitmapData:BitmapData = new BitmapData(stage.width, stage.height);
   bitmapData.draw(stage, new Matrix());
   var img = jpgEncoder.encode(bitmapData);

   var file:FileReference = new FileReference();
   file.save(img, "filename.png");
}

 

Klasa pomocnicza (w sumie są 3 klasy na każdą ikonkę stolika oddzielna - zamieszczam tylko jedna bo ich zawartość jest identyczna:)

 

package  {

   import flash.display.MovieClip;
   import flash.events.MouseEvent;
   import flash.events.Event;

   public class BigIco extends MovieClip {
           static public var active:Boolean;
           public var over:Boolean;

       public function BigIco() {
           // constructor code
           this.addEventListener(Event.ENTER_FRAME, f_move);
           this.addEventListener(MouseEvent.MOUSE_OVER, setOverTrue);
           this.addEventListener(MouseEvent.MOUSE_OUT, setOverFalse);
       }
       static public function setUpVaue():void
       {
       active = false;
       }
       static public function setDownVaue():void
       {
       active = true;
       }
       public function f_move(e:Event)
       {
           if(over)
           {
           if(active)
           {startDrag();}
           else
           {stopDrag();}
           }
       }

       public function setOverTrue(e:MouseEvent)
       {
           over = true;
           trace("over");
       }
       public function setOverFalse(e:MouseEvent)
       {
           over = false;
           trace("out");
       }



   }

}

 

Teraz pozostaje jeszcze zrobić opcję usuwania zaznaczonego stoliczka ;p.

 

Ps. czy ma ktoś pomysł jak usunąć zaznaczony myszą obiekt ?

Szukam czegoś o wyborze dziecka po id (coś w stylu: pobierz id aktualnie zaznaczonego obiektu), dzięki czemu później mógłbym usunąć taki obiekt właśnie za pomocą jego id (np. po wciśniećiu "x"), ale nigdzie nie mogę znaleźć nic przydatnego :/

 

Tak, wiem że to jest kod spagetti, ale biorąc pod uwagę moje (nie)umiejętności programistyczne inaczej nie umiałęm :/

Edited by stobolewski

Share this post


Link to post
Share on other sites

dobra rada, to nie uzywanie stage. sposobów masz kilka.

-mozesz po ID jeżeli potrafisz je zidentyfikować - tata.getChildByName(dziecko.name)

-mozesz po poziomie, jeżeli wiesz, że np. zaznaczony jest na górnym poziomie - tata.getChildAt(poziom)

-mozesz przypisać mu listener zwiazany z akcjami dla niego - wtedy odwołujesz się do niego jako event.currentTarget

-mozesz też definiować zmienną na czas wyboru np. KID=dziecko i przywoływać zmienną KID

 

generalnie dla mnie najwygodniejsze jest tworzenie listenerów dla obiektów i odwoływanie się do nich po np. znajdującym się w nich guziku dla przykładu buton=event.currentTarget; dziecko=parent.buton ale to kwestia własnych preferencji.

 

Wygodne w listenerze dla obiektu jet to, że nie musiałbyś duplikowac klas, co ułatwia pracę.

Share this post


Link to post
Share on other sites

olaf. Zapewne masz rację i zapewne piszesz mądrze. Ja z as3 mam do czynienie tyle, że wiem iż on istnieje (i że większość osób go unika).

Robię pseudo aranżator bo ... nikt inny w tym miejscu tego nie zrobi :/

 

Z tego co rozumiem mam identyfikować jakoś obiekty... tylko pytanie jak ? Jak widać tworzę kolejne obiekty (np. 200 stolików), które wg. mnie nie są w żaden sposób identyfikowane (wiem że istnieje coś takiego jak usunięcie "dziecka" po id [rozumuje ze każdy kolejny stolik ma kolejne id]. Nie wiem niestety w jaki sposób mam pobrać id obiektu, który jest aktualnie pod myszą.

 

Właśnie wpadłem na pomysł, że wszystkie te moje "stoliczki / ikony" będę tworzył w oddzielnym pustym movie clipie, może to mi ułatwi ich usuwanie (poprzedni test po wciśnięciu X usunął mi tło programiku ;D).

 

Jako człek nieogarnięty z programowaniem wiedzę czerpię z:

http://www.ilike2flash.com/2010/02/detect-key-press-in-actionscript-3.html

http://stackoverflow.com/questions/11934569/as3-delete-object-when-clicked

itp. rzeczy - sam się dziwie że działają mi te połączenia między klasami ;D

 

Poszukam i pokombinuje, może coś zdziałam.

Share this post


Link to post
Share on other sites

Aktualnie...

 

kombinuje jak to zrobić aby usunąć zaznaczony obiekt. Przykładowo tworzę 20 nowych mebli i dochodzę do wniosku że któryś z nich jest niepotrzebny. Trzymam nad nim mysz i przez dwuklik lub wciśnięcie jakis litery kasuję dany obiekt (ten aktualnie pod myszą).

 

W tej chwili wszystkie moje mebelki mam w oddzielnym movie clipie, dzięki czemu mogę za pomocą pętli usunąć wszystkie jego dzieci (przycisk z funkcją reset). Największy problem dla laika to pobranie id obiektu bezpośrednio pod kursorem myszy. Usunięcie takiego obiektu już sobie jakoś zorganizuje.

 

Znalazłem klika przykładów do pobierania ID, ale zawsze mam jakieś błędy o dostępie do funkcji przez instancje (zmieniłem kod więc tego błędu nie wkleję). Przyznam się, że niestety takie błędy niewiele mi mówią.

Większość przykładów, na jakie trafiam to usuwanie konkretnego dziecka po nazwie (u mnie nie ma nazw).

 

Przykład:

http://www.kirupa.com/forum/showthread.php?279476-getChildIndex()

 

Mam jeszcze coś takiego, ale jeszcze nie rozgryzłem jak to działą (tu pewnie będzie odpowiedz :)

http://www.flashandmath.com/intermediate/names/index.html

Edited by stobolewski

Share this post


Link to post
Share on other sites

pierwszy etap, to kod, ktory rozpozna Tobie, ze to jest to czego szukasz.

Daj mu listenera na rollOver np. tak (moge sie pomylic bo pracuje we wlasnym frameworku i dawno nie uzywalem takich podstawowych funkcji)

 

var M=new mebel; M.name='pantofel'

pokoj.addChild(M); M.addEventListener(maus rollover poprawna składnia,rOv)

 

function rOv(e){var M=e.currentTarget;

trace('najechałem na skurczybuka, jego imie to:'+M.name)}

 

co da Ci frazę: 'najechałem na skurczybuka, jego imie to:pantofel'

Masz juz obiekt we władaniu i teraz rob z nim co chcesz.

Share this post


Link to post
Share on other sites

A konkretnie samo usuwanie:

 

var mainMC:MovieClip //główny mc w którym masz wszystkie meble

 

//petla dodająca listener wszystkim meblom

for (var i:uint = 0; i

var mebel:* = mainMC.childAt(i);

mebel.addEventListener(MouseEvent.DOUBLE_CLICK, onMebelDoubleClick);

}

 

//usuwanie przy podwójnym klincieciu

function onMebelDoubleClick(e:MouseEvent):void{

var mebel:* = e.currentTarget;

mebel.removeEventListener(MouseEvent.DOUBLE_CLICK, onMebelDoubleClick);

mebel.parent.removeChild(mebel); // to moze wydawać się dziwne, ale działa:)

}

 

Pisałem z głowy, wiec przyjmij to jako metode, a nie gotowy kod:)

Nie pamietam tez od której wersji flash obsługuje MouseEvent.DOUBLE_CLICK.

Ewentualnie mozesz sobie zrobić ze klikniecie z wciśnietym altem/shiftem/ctrl bedzie usuwać meble.

Share this post


Link to post
Share on other sites

Dzięki wielkie za pomoc.

Double_click w as3 jest więc nie ma problemu. Teraz pozostaje mi to jakoś wkomponować w mój wspaniały aranżaror ;p

Nie wiem kiedy to będzie, ale na 100% dam znać czy się udalo :)

 

zaraz nad tym siadam.

 

A tak swoją drogą. Czy jest jakaś różnica między dodaniem eventu w pętli a dodaniem go przy tworzeniu obiektu ?

function f_bigIco(event:MouseEvent):void{
   var big:BigIco = new BigIco();
   big.x = 20;
   big.y = 20;
   big_table+=10;
   table_holder.addChild(big);
   big.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeBig);
   trace("created : " + big_table);
}

 

Coś takiego zmajstrowałem (wzorując się na przykłądzie z sieci), ale coś nie chce działać (ale błędów nie ma ;p).

 

WoW, to żyje. Udało się !

dwuklik usuwa wskazany obiekt. Okazało się że dla każdego obiektu trzeba jeszcze odblokować opcję dwukliku :).

 

To się ludkowie ucieszą, jak będą mogli poustawiać stoliczki pod dyktando klienta, a nie tylko wysłać pdf (a i ja może dzięki temu będę miał mniej "problemów" ;)

 

Jak skończę to się pochwalę "efektem" ;p

 

Dzięki wielkie za pomoc :*

Edited by stobolewski

Share this post


Link to post
Share on other sites

Spoko, miło jest pomóc:)

 

Pewnie już znasz odpowiedź, ale nie, nie ma różnicy w którym momencie nadasz obiektowi listener.

 

See ya, jak cos to pytaj, mam subskrypcje na wątek.

Share this post


Link to post
Share on other sites

A więc pytam ;p.

 

Dlaczego ta funkcja nie działa jeśli dodam do sceny inne rodzaje stoliczków ?

W tej chwili mam na stole "mapke" pomieszczenia i dodaje tam 3 rodzaje stolików (wszystkie są zdefiniowane w oddzielnych klasach)

- Małe

- Średnie

- Duże

 

Sposób który mi podałeś działa ale tylko dla dużych stolików (tam dodałem go na samym początku).

Postępując zgodnie z ta zasadą zrobiłem podobny schemat dla pozostałych stoliczków, z tym że w dodanym evencie wywołuje funkcje z o innych nawach (np. f_removeBig, f_removeMiddle, f_removeSmall). Działa tylko jedna (znaczy tylko w przypadku jednej funkcji działa double click) :/

 

czyli mam (fragment kodu)

function f_littleIco(event:MouseEvent):void{
   var little:LittleIco = new LittleIco();
   little.x = 20;
   little.y = 20;
   little.doubleClickEnabled=true;
   little_table+=4;
   table_holder.addChild(little);
   little.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeSmall);
   trace("created");
}
function f_middleIco(event:MouseEvent):void
{
   var middle:MiddleIco = new MiddleIco();
   middle.x = 20;
   middle.y = 20;
   middle.doubleClickEnabled=true;
   middle_table+=6;
   table_holder.addChild(middle);
   middle.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeMiddle);
   trace("table added, function added...");
   trace("created");
}
function f_bigIco(event:MouseEvent):void
{
   var big:BigIco = new BigIco();
   big.x = 20;
   big.y = 20;
   big.doubleClickEnabled=true; 
   big_table+=10;
   table_holder.addChild(big);
   big.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeBig);
   trace("table added, function added...");
   trace("created : " + big_table);
}
function f_removeBig(e:MouseEvent)
{
   trace("event added ...");
   var qqq:* = e.currentTarget;
   qqq.removeEventListener(MouseEvent.DOUBLE_CLICK, f_removeBig);
   qqq.parent.removeChild(qqq);
   big_table-=10;
}
function f_removeMiddle(ev:MouseEvent)
{
   trace("middle function called");
   var sredni:* = ev.currentTarget;
   sredni.removeEventListener(MouseEvent.DOUBLE_CLICK, f_removeMiddle);
   sredni.parent.removeChild(sredni);
   middle_table-=6;
}
function f_removeSmall(e:MouseEvent)
{
   trace("event added ...");
   var qqq:* = e.currentTarget;
   qqq.removeEventListener(MouseEvent.DOUBLE_CLICK, f_removeSmall);
   qqq.parent.removeChild(qqq);
   little_table-=4;
}

 

działa tylko część dla BigIco :(

Dodałem w funkcjach "trace" żeby sprawdzic czy są wywoływane... nie są :/

Wychodzi na to, że z jakiegoś powodu flash nie widzi tych kolejnych kliknięć na innych ikonach (bez względu na to, czy tworzę wszystkie stóły, czy tylko średnie).

 

Problem rozwiązany (googlowanie pomaga)

Nie wiem czy to dobra technika ale działa. Wystarczyło dodać 2 linijki do funkcji tworzącej nowe obiekty

 

big.buttonMode = true;
big.mouseChildren = false;

 

function f_littleIco(event:MouseEvent):void{
var little:LittleIco = new LittleIco();
little.x = 20;
little.y = 20;
little.doubleClickEnabled=true;
little_table+=4;
little.buttonMode = true;
little.mouseChildren = false;
table_holder.addChild(little);
little.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeSmall);
trace("created");
}
function f_middleIco(event:MouseEvent):void
{
var middle:MiddleIco = new MiddleIco();
middle.x = 20;
middle.y = 20;
middle.doubleClickEnabled=true;
middle_table+=6;
middle.buttonMode = true;
middle.mouseChildren = false;
table_holder.addChild(middle);
middle.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeMiddle);
trace("table added, function added...");
trace("created");
}
function f_bigIco(event:MouseEvent):void
{
var big:BigIco = new BigIco();
big.x = 20;
big.y = 20;
big.doubleClickEnabled=true; 
big_table+=10;
big.buttonMode = true;
big.mouseChildren = false;
table_holder.addChild(big);
big.addEventListener(MouseEvent.DOUBLE_CLICK, f_removeBig);
trace("table added, function added...");
trace("created : " + big_table);
}

Edited by stobolewski

Share this post


Link to post
Share on other sites

Jasne, to dlatego, że gdy masz *.mouseChildren na true, to klikając na obiekt, klikasz de facto na to co ma w sobie - czyli w twoim wypadku pewnie albo obrazek, albo innego MovieClipa. A event Double_Clicka jest nadany tylko na obiekt główny - na jego dzieci nie - dlatego nic się nie działo. Gdy ustawisz mouseChildren na false, cały obiekt jest traktowany jako jedność (dla interakcji myszką).

Share this post


Link to post
Share on other sites

Wersja testowa (taka dla mnie ;)

 

wersja beta

 

się kilka w ikonki pod "dostępne stoliki" ;p

 

"Troszeczkę" pracy jeszcze zostało ale coś już działa a to sukces.

Dzięki za pomoc.

Share this post


Link to post
Share on other sites

jest moc w jakości tła ;D

musiałem wydupcyć plan pomieszczenia bo nie wiem co na takie udostępnianie go powiedział by mój "pracodawca" ;).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

We are using cookies. Read about our Privacy Policy