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.
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.)
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.
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:
Î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.
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ță.
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.
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
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
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 ();
Înainte de a crea blocurile, să înțelegem ce reprezintă un singur bloc. Fiecare bloc este de fapt:
spiriduș
Bitmap
inauntruBitmapData
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
.
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
.
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
.
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);
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:
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);
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
.
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
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.
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:
BitmapData
obeject. Captură de ecran a videoclipului în acest caz (srcBmpd
).Dreptunghi
obiect care specifică punctul de sus-stânga, lățimea și coloana regiunii din sursa care urmează să fie copiată. Punct
obiect. Totul este gata! Acum este timpul să vă conduceți proiectul și să vedeți efectul minunat.
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);
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.
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!