Împachetați un videoclip în timp real cu AS3

Bună ziua, ciudați cod! Acest tutorial vă va arăta cum să împărțiți un videoclip care rulează în blocuri ca și cum ar fi explodat. Și toate acestea folosind doar ActionScript. Pentru acest tutorial vom folosi camera ca sursă video, astfel încât să puteți vedea modificările live.


Rezultatul final al rezultatelor

Să aruncăm o privire asupra rezultatului final pe care îl vom strădui:

Faceți clic și trageți un bloc pentru al muta în jurul ecranului! (Este necesar accesul camerei.)


Pasul 1: Configurare - IDE

Pentru acest tutorial vom folosi FlashDevelop IDE (deși ați putea folosi orice editor AS3). În cazul în care nu aveți și doriți să încercați, puteți să-l luați de aici. Un tutorial de bază pentru configurarea aplicației FlashDevelop pe mașina dvs. poate fi găsit aici.

De asemenea, dacă aveți instalat Flash Professional pe partea dvs., acest lucru va funcționa prea. Tot ce trebuie să faceți este să creați un fișier de clasă externă așa cum este menționat mai jos și să îl conectați la proiectul dvs. Flash ca o clasă Document.

Aceasta ne determină mediul de lucru.


Pasul 2: Configurare - Proiect nou

Creați un nou proiect AS3 în FlashDevelop.

Când sa terminat, veți avea o Principal clasa creată în folderul src după cum se vede în panoul din dreapta:


Pasul 3: Configurarea - clasa principală

Înainte trebuie să facem Main.as trimiteți un program de curățare mic eliminând un anumit cod. Inițial când deschideți Main.as fișier, ar fi codul ceva de genul:

 pachet import flash.display.Sprite; importul flash.events.Event; clasa publică principală extinde Sprite funcția publică Main (): void if (stage) init (); altfel addEventListener (Event.ADDED_TO_STAGE, init);  funcția privată init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // punct de intrare   

Vom șterge o parte din cod pentru al face mai curat. Deci, ar trebui să aveți acest lucru:

 pachet import flash.display.Sprite; importul flash.events.Event; clasa publică principală se extinde Sprite funcția publică principală (): void 

Acum, toate setările se fac și este momentul să vă aruncați într-un anumit cod.


Pasul 4: Declarația variabilelor video și aparat de fotografiat

Primul nostru scop este să desenăm filmul pe scenă folosind camera; pentru aceasta avem nevoie să declarăm câteva variabile. Puneți aceste declarații chiar deasupra Principal constructor de clasă.

 // variabilele video private var camW: int = 300; privat var camH: int = 300; privat video var: Video;

camW - Lățimea camerei / video.

CAMH - Înălțimea aparatului foto / video.

video - Al nostru Video clasă instanță.


Pasul 5: Pregătiți camera aparatului

Așa cum am menționat mai înainte, vom folosi ieșirea camerei video în video. Deci, mai întâi trebuie să facem aparatul foto gata pregătit. Următorul cod trebuie să intre în constructorul de clasă.

 camera var: Camera = Camera.getCamera ();

Aici, instanțiăm a aparat foto instanță și obțineți camera aparatului disponibil utilizând metoda statică getCamera () din aparat foto clasă.

 camera.setMode (camW, camH, 30);

Oferim câteva setări pentru cameră: lățime, înălțime și fps.

Rețineți că nu am făcut ca camera să fie variabilă la nivel global, pentru că nu avem nevoie să o accesăm oriunde în afara acestei funcții, după cum veți vedea în continuare. În pasul următor vom inițializa video variabil.


Pasul 6: Creați de fapt videoclipul!

 video = videoclip nou (camW, camH); video.attachCamera (aparat foto);

Am injectat acum video variabile și utilizate attachCamera () pentru a atașa aparatul foto la acesta. Aceasta înseamnă că acum videoclipul folosește ieșirea camerei ca sursă.

Totul a fost făcut cu materialele video și camera. Rețineți că trebuie să importați clasele corespunzătoare în codul dvs. Codul dvs. de clasă completă ar trebui să arate astfel în acest moment:

 pachet import flash.display.Sprite; importul flash.events.Event; import flash.media.Camera; import flash.media.Video; clasa publică principală extinde Sprite // variabilele video private var camW: int = 300; privat var camH: int = 300; privat video var: Video; funcția publică Main (): void var camera: Camera = Camera.getCamera (); camera.setMode (camW, camH, 30); video = videoclip nou (camW, camH); video.attachCamera (aparat foto); 

Dacă rulați (F5 sau CTRL + Enter) proiectul acum, ar fi un stadiu gol, dar cel mai probabil veți obține o cerere de acces la cameră deoarece aplicația încearcă să acceseze camera aparatului. Permite.

Motivul pentru care nu vedeți nimic este că nu dorim să afișăm videoclipul și nu l-am adăugat la scenă (lista de afișare). Acesta va fi folosit doar ca sursă pentru blocurile noastre separate. Dacă doriți să testați că totul funcționează bine, adăugați următoarea linie la sfârșitul secțiunii Principal constructor:

 addChild (video); // Eliminați această linie după testare

Pasul 7: Declarația blocurilor variabile

Acum creăm blocurile - peicele separate ale videoclipului. Primul pas este de a declara unele variabile necesare pentru aceasta. Deci, continuați și adăugați următoarele declarații variabile chiar sub variabilele video:

 // bloc variabile private var rânduri: int = 3; privat var cols: int = 3; privat var blocW: int = camW / cols; privat var blocH: int = camH / rânduri; private var punctCollecție: obiect = Obiect nou ();

rânduri - Numărul de rânduri pentru divizarea videoclipului în.

cols - Da. Ai înțeles. Numărul de coloane pentru divizarea videoclipului în.

blockW - Lățimea fiecărui bloc. Aceasta este o variabilă derivată deoarece este pur și simplu calculată prin împărțirea lățimii totale (camW) după numărul de coloane (cols).

blockH - Înălțimea fiecărui bloc, adică. CAMH impartit de rânduri.

pointCollection - Valoarea finală, dar cea mai importantă. Este o matrice asociativă pe care o vom folosi pentru a stoca punctul corespunzător al fiecărui bloc. De exemplu, dacă un bloc are un nume block12, atunci am stoca punctul corespunzător P12 asa :

 punctCollecție ["bloc12"] = p12; // Punctele sunt instanțe de clasă de puncte aici

Pasul 8: Începeți să faceți blocurile

Acum, când avem variabilele definite definite, începem să creăm blocurile. Vom păstra întregul cod de creare a blocului într-o funcție numită initBlocks (). Această funcție va fi apelată de la Principal constructor după ce ați setat videoclipul.

Deci, să spunem mai întâi o funcție numită initBlocks () imediat după Principal constructor.

 funcția privată initBlocks (): void pentru (var r: int = 0; r < rows; r++)  for (var c:int = 0; c < cols; c++)  // code to create each block   

Observați cele două pentru buclele pe care le-am plasat înăuntru, ceea ce ne va ajuta să creăm blocurile într-o rețea 2D, în ordine. Apoi adăugați un apel la această funcție la sfârșitul paginii Principal():

 funcția publică Main (): void var camera: Camera = Camera.getCamera (); camera.setMode (camW, camH, 30); video = videoclip nou (camW, camH); video.attachCamera (aparat foto); initBlocks (); 

Pasul 9: Componentele unui bloc

Înainte de a crea blocurile, să înțelegem ce reprezintă un singur bloc. Fiecare bloc este de fapt:

  • A spiriduș
  • cu Bitmap inauntru
  • care la rândul său are nevoie de a BitmapData

A se gandi la spiriduș ca cel mai exterior container. Complet gol.

Pentru a desena blocul, avem nevoie de a Bitmap care va afișa ieșirea video corespunzătoare.

Și, în sfârșit, fiecare Bitmap are nevoie de date pentru a desena în interiorul acestuia. Acest lucru este dat sub formă de BitmapData.


Pasul 10: Creați baza blocului - Sprite

Prima componentă a unui bloc, așa cum am discutat, este un Sprite. Deci, vă permite să creați unul. Tot codul pe care îl scriem pentru a crea blocul trebuie scris în interiorul lui pentru bucle.

 var nou Bloc: Sprite = Sprite nou ();

Creați o nouă instanță a spiriduș clasă.

 newBlock.name = "bloc" + r + c;

Apoi vom numi sprite, astfel încât să putem face referire mai târziu în cod. Convenția de numire este simplă: se numește un bloc la rândul r și coloana c bloc + r + c (+ înseamnă concatenare). Deci, este numit un bloc la rândul 2 și coloana 1 block21.


Pasul 11: Poziționați-l

După ce am creat-o, trebuie să o poziționăm pe scenă în funcție de rând și coloană. Prin urmare, permiteți adăugarea următorului cod.

 var p: Punct = punct nou (c * blockW, r * blockH);

Noi folosim a Punct un obiect de clasă pentru a stoca aici coordonatele punctului. Așadar, noi creăm o nouă instanță Punct și treci c * blockW ca valoare x și r * blockH ca valoarea y. Acum, coordonatele pot fi accesate pur și simplu ca p.x și p.y și este folosit mai târziu pentru a prelua regiunea tăiată a fiecărui bloc dintr-un cadru video complet. Amintiți-vă că fiecare punct al blocului este de fapt coordonatele punctului din stânga sus al rețelei.

Dacă aveți o îndoială cu privire la modul în care se calculează poziția aici, următoarea figură va clarifica.

 newBlock.x = c * (blocW + 1) + 20; newBlock.y = r * (blocH + 1) + 20;

Apoi, poziționăm sprite. Coordonatele sunt mai mult sau mai puțin aceleași, așteptăm acum să adăugăm 20 pentru a da o compensare. De asemenea, adăugăm 1 la blockW și blockH pentru a separa blocurile cu 1 pixel, așa cum se vede în demo-ul de mai sus.

 pointCollection [newBlock.name] = p;

În cele din urmă, salvăm punctul pe care l-am calculat mai devreme în pointCollection.


Pasul 12: Adăugarea Bitmap-ului în bloc

Acum, venind la cea de-a doua și a treia componentă a blocului.

 var bmpd: BitmapData = BitmapData nou (blockW, blockH);

Mai intai creem a BitmapData instanță și să treacă lățimea și înălțimea dorită a blocurilor pe care le-am stocat înainte. După cum sa discutat mai devreme, a BitmapData instanța este obligată să creeze o Bitmap exemplu care este trecut în constructor.

 var bmp: bitmap = Bitmap nou (bmpd); bmp.name = "myBmp";

Acum, creăm un Bitmap instanță și treceți înainte bmpd în constructor. De asemenea, numim bitmap-ul myBmp așa că o putem referi mai târziu.

 newBlock.addChild (bmp); addChild (newBlock);

În final adăugăm bitmap bmp ca un copil de newBlock și newBlock ea însăși fiind copilul scenei.

Doar pentru a vă asigura că sunteți pe calea cea bună, dumneavoastră Main.as cod ar trebui să arate ceva de genul:

 pachet import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.geom.Point; import flash.media.Camera; import flash.media.Video; clasa publică principală extinde Sprite // variabilele video private var camW: int = 300; privat var camH: int = 300; privat video var: Video; // bloc variabile private var rânduri: int = 3; privat var cols: int = 3; privat var blocW: int = camW / cols; privat var blocH: int = camH / rânduri; priv var varCollecție: Array = Array nou (); funcția publică Main (): void var camera: Camera = Camera.getCamera (); camera.setMode (camW, camH, 30); video = videoclip nou (camW, camH); video.attachCamera (aparat foto); initBlocks ();  funcția privată initBlocks (): void pentru (var r: int = 0; r < rows; r++)  for (var c:int = 0; c < cols; c++)  var newBlock:Sprite = new Sprite(); newBlock.name = "block" + r + c; var p:Point = new Point(c * blockW, r * blockH); newBlock.x = c * (blockW + 1) + 20; newBlock.y = r * (blockH + 1) + 20; pointCollection[newBlock.name] = p; var bmpd:BitmapData = new BitmapData(blockW, blockH); var bmp:Bitmap = new Bitmap(bmpd); bmp.name = "myBmp"; newBlock.addChild(bmp); addChild(newBlock);     

Pasul 13: Actualizarea blocurilor - Concept

Chiar dacă blocurile sunt plasate în pozițiile potrivite, încă nu vedem nimic despre rularea proiectului. Asta pentru că încă nu am atras nimic în interiorul blocurilor bitrate.

Următorul pas este să executați o buclă care rulează în mod constant și care efectuează următoarele operații:

  1. Obțineți cadrul video actual.
  2. Faceți buclă prin toate blocurile.
  3. Aduceți copilul punct și bitmap al fiecărui bloc.
  4. Desenați partea corespunzătoare a cadrului video pe bitmap-ul blocului.

Asa de? s-o facem!

Înainte de a implementa codul de buclă, avem nevoie de o LOOP FUNCTION (o formă asemănătoare unei bucăți de joc). Adăugați următoarea declarație a funcției sub initBlocks () funcție:

 funcția privată updateBlocks (e: Event): void 

Așa cum se vede din parametrul funcției, se pare că este un ascultător al evenimentului și da. Aceasta este o funcție de ascultător pe care o vom atașa ENTER_FRAME eveniment al scenei. Pentru a atașa ascultătorul, adăugați această linie la sfârșitul secțiunii Principal() constructor.

 funcția publică Main (): void var camera: Camera = Camera.getCamera (); camera.setMode (camW, camH, 30); video = videoclip nou (camW, camH); video.attachCamera (aparat foto); initBlocks (); addEventListener (Event.ENTER_FRAME, updateBlocks); 

Pasul 14: Captură cadru

Aceasta este prima operație pe care o efectuăm în bucla noastră - updateBlocks () funcție care este apelată pe fiecare cadru. Introduceți codul următor updateBlocks () funcţie.

 var srcBmpd: BitmapData = BitmapData nouă (camW, camH);

Fiecare date bitmap din Actionscript 3.0 trebuie să fie conținute într-un BitmapData instanță și astfel creăm una. Vom acumula această instanță cu datele curente ale cadrelor video următoare.

 srcBmpd.draw (video);

Aici am folosit a desena() funcția BitmapData clasă. Este nevoie de un obiect al oricărei clase care implementează IBitmapDrawable interfață. De exemplu. Sprite, MovieClip, BitmapData etc. Ceea ce face este pur și simplu să ia datele vizuale ale obiectului trecut și să-l stocheze în BitmapData instanță.

Deci, acum avem cadrul video curent (sau, ar putea spune, o captură de ecran) în variabila srcBmpd.

Pasul 15: Să ne bifăm

Deoarece trebuie să actualizăm fiecare bloc, creăm un dublu pentru-buclă, similar cu cea pe care am scris-o pentru crearea blocurilor. Deci, mergeți mai departe și adăugați-o.

Funcția ar trebui să pară similară acum:

 funcția privată updateBlocks (e: Event): void var srcBmpd: BitmapData = BitmapData nouă (camW, camH); srcBmpd.draw (video); pentru (var r: int = 0; r < rows; r++)  for (var c:int = 0; c < cols; c++)  // update code here   

Pasul 16: Returnați Bitmap-ul și Punctul blocului

Amintiți-vă că am numit blocurile într-un anumit mod în timp ce le-am creat, astfel încât să putem face referire la orice bloc folosind numărul rândului și coloanei. Asta vom folosi acum pentru a obține referințele fiecărui bloc.

 var b_mc: Sprite = this.getChildByName ("bloc" + r + c) ca Sprite;

Noi folosim getChildByName funcția etapă (acest) care returnează o referință la un obiect al cărui nume corespunde șirului trecut. De asemenea, am introdus-o spiriduș pentru a vă asigura că obiectul returnat este a spiriduș. Acum, referința blocului se află în variabila b_mc.

 var bmp: bitmap = b_mc.getChildByName ("myBmp") ca bitmap;

În același mod, vom prelua referința la bitmapul care a fost adăugat ca copil al blocului sprite.

 var p: Punct = punctCollecție [b_mc.name];

În cele din urmă, obținem blocurile actuale (b_mc) coordonează din matricea în care l-am stocat mai devreme folosind numele blocului.

Pasul 17: Trageți-l!

Acum, că avem toate informațiile necesare cu privire la ceea ce să atragă în cazul în care, putem de fapt, DRAW aceasta. Motivul nostru aici este de a obține regiunea dreptunghiulară a cadrului video (adică,. srcBmpd) cu punctul de sus-sus ca punct de preluare p, lățime ca blockW și înălțimea blockH.

În acest scop, folosim copyPixels () metodă a BitmapData clasă. Copiază de fapt regiunea unei alte surse BitmapData specificate prin trecerea a Dreptunghi obiect.

 bmp.bitmapData.copyPixels (srcBmpd, nou dreptunghi (p.x, p.y, blockW, blockH), new Point ());

a desena() funcția este solicitată bmp„s bitmapData proprietate. Parametrii introduși în acesta sunt:

  1. Sursa BitmapData obeject. Captură de ecran a videoclipului în acest caz (srcBmpd).
  2. A Dreptunghi obiect care specifică punctul de sus-stânga, lățimea și coloana regiunii din sursa care urmează să fie copiată.
  3. Punctul în distanța în care porțiunea tăiată trebuie copiată. (0,0) în acest caz. Deci, pur și simplu trecem un nou Punct obiect.

Totul este gata! Acum este timpul să vă conduceți proiectul și să vedeți efectul minunat.

Pasul 18: Adăugarea funcțiilor Drag-and-Drop

Pentru a adăuga caracteristica drag-and-drop așa cum se vede în demo, trebuie doar să atașăm doi ascultători ai mouse-ului în fiecare bloc - unul pentru MOUSE_DOWN eveniment și altul pentru MOUSE_UP eveniment. Deci, mergeți mai departe și definiți două funcții de manipulare a mouse-ului la sfârșitul clasei:

 funcția privată onMouseDown (e: MouseEvent): void Sprite (e.currentTarget) .startDrag ();  funcția privată onMouseUp (e: MouseEvent): void Sprite (e.currentTarget) .stopDrag (); 

Tot ce facem în interiorul acestor funcții de ascultător este să trimiteți referința la blocul de expediere a evenimentului folosind currentTarget proprietate a Eveniment obiect, tastați-l la spiriduș (pentru că asta sunt blocurile noastre) și sunați-l startDrag () și stopDrag () pentru a face față tragerii și căderii.

Asta nu e încă tot. Trebuie să atașăm acești ascultători la evenimentele lor corespunzătoare. Adăugați aceste două linii la initBlocks () funcţie.

 funcția privată initBlocks (): void pentru (var r: int = 0; r < rows; r++)  for (var c:int = 0; c < cols; c++)  var newBlock:Sprite = new Sprite(); newBlock.name = "block" + r + c; var p:Point = new Point(c * blockW, r * blockH); newBlock.x = c * (blockW + 1) + 20; newBlock.y = r * (blockH + 1) + 20; pointCollection[newBlock.name] = p; var bmpd:BitmapData = new BitmapData(blockW, blockH); var bmp:Bitmap = new Bitmap(bmpd); bmp.name = "myBmp"; newBlock.addChild(bmp); addChild(newBlock); newBlock.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); newBlock.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);   

Pasul 19: Touch Final

Un ultim lucru doar pentru a face să pară mai interactivă. S-ar putea să fi observat cum blocurile se estompează și se sting atunci când sunt presate și eliberate. Aceasta este o manipulare alfa pe care o facem în interiorul ascultătorilor. Modificați-vă ascultătorii la ceva de genul:

 funcția privată onMouseDown (e: MouseEvent): void Sprite (e.currentTarget) .alpha = 0.4; Sprite (e.currentTarget) .startDrag ();  funcția privată onMouseUp (e: MouseEvent): void Sprite (e.currentTarget) .alpha = 1; Sprite (e.currentTarget) .stopDrag (); 

Și acolo aveți efectul schimbării alfa.

Concluzie

Efectul are un potențial foarte mare de a fi utilizat în diferite aplicații. Am dezvoltat recent un joc de puzzle folosind-l.

În afară de aceasta, ar putea fi folosit pentru a crea efecte de tranziție pentru playerele video sau în concordanță cu 3D pentru a textura o suprafață cu un videoclip.

Sper să văd niște lucruri minunate pe care oamenii le folosesc!

Cod