Processing
Børre Stenseth
Skisser >VideoPussel

Video Eksplosjon

Hva

For å spille av video i en Processingskisse må vi kople til et eget bibliotek, video. Dette gjør du ved å velge Tools/Add Tool... Velg libraries og søk etter video.

Begreper som du finner i dokumentasjonen til Processing Video Reference

Movie, play(), available(), read(), loop(), volum(), copy()

I eksempelet nedenfor har vi brukt en mp4-fil som er lagt i data-katalogen i skissen. Fila er fritt tilgjengelige og er hentet fra pixabay.com.

Relevante Skisser
videoPuzzle
videopuzzle

Dette eksempelet er en modifikasjon av eksplosjonseksempelet VideoEksplosjon . Vi bruker en litt modifisert versjon av vRute. I stedet for at rutene finne veien hjem på egenhånd,forventes de å bli dratt på plass. Vi skriver hovedskissen slik:

_videoPuzzle.pde
/*
deler opp en video i nxn ruter
Brukeren kan flytte rutene tilbake på plass
*/
import processing.video.*;
// videoen
Movie enVideo;
// husk vilken rute vi flytter
vRute aktivRute=null;
// rutene
ArrayList<vRute>rutene=null;
// antall ruter horisontalt og vertikalt
int rH =3;
int rV =3;
void setup(){
  size(800,600);    
  // fri video lastet ned fra pixabay.com/videos/
  enVideo = new Movie(this,"Dance - 4428.mp4");   
  enVideo.loop();
  // start med lyd
  enVideo.volume(1);
  frameRate(20);
}
// del opp videoen i ruter
void setOppRuter(Movie m,int rader,int kolonner){
  rutene=new ArrayList();  
  int MW=m.width;
  int MH=m.height;
  for(int rad=0;rad< rader;rad++)
    for(int kol=0;kol< kolonner;kol++){
      rutene.add(new vRute(m,
                           kol*MW/kolonner,
                           rad*MH/rader,
                           MW/kolonner,
                           MH/rader));
   }
}
void spreRutene(){
  for(vRute R:rutene){
    R.finnTilfeldigPlass();
  }
  enVideo.volume(0);
}
void draw() {  
  background(255);
  if(enVideo.available()){
   // instruksjoner
   textAlign(CENTER);
   textSize(20);
   fill(0);
   text("klikk og tast for å starte..",width/2,height-30);
   //translate((width-enVideo.width)/2,(height-enVideo.height)/2);
   enVideo.read();
    
    // oppsett av ruter gjøres bare en gang
    // men må skje etter at videoen er lastet
    if(rutene==null){
      setOppRuter(enVideo,rH,rV);
    }    
    // rutene finner selv ut vilken del av videoene de skal vise
    // tegn hjemmeposisjon bakerst
    for(int ix=0;ix<rutene.size();ix++){
      rutene.get(ix).tegnHjemmePos();
    }
    // tegn rutene
    for(int ix=0;ix<rutene.size();ix++){
      rutene.get(ix).tegn();
    }
  }
}
  
void mousePressed(){ 
  for(int ix=rutene.size()-1;ix>=0;ix--){
    // truffett en rute ?
    if(rutene.get(ix).inneholder(mouseX,mouseY)){
      aktivRute=rutene.get(ix);
      //putt den bakerst så blir den tegnet sist
      rutene.remove(ix);
      rutene.add(aktivRute);
      return;
    }
  }
  aktivRute=null;
}
  
void mouseReleased(){
  aktivRute=null;
  if(erAllePlassert()){
    // skru på lyden og sett alt presist
    enVideo.volume(1);
    setOppRuter(enVideo,rV,rH);
  }
  else
    enVideo.volume(0);  
} 
  
void mouseDragged(){
  if(aktivRute!=null){
    aktivRute.flytt(mouseX-pmouseX,mouseY-pmouseY);
  }
}
boolean erAllePlassert(){
    // er alle rutene nesten hjemme ?
    for(int ix=0;ix<rutene.size();ix++)
      if(!rutene.get(ix).erNesteHjemme())
        return false;
  enVideo.volume(0);
  return true;
}
void keyPressed(){
  spreRutene();
}

De bevegelige rutene er beskrevet slik:

_vRute.pde
/*
Viser fram en del av videobildet
i en bevegelig rute
*/
class vRute{
  // videoen
  Movie mov;
  // hvor vi skal hente rutas innhold fra videoen
  int L; // venstre
  int T; // høyre
  int W; // bredde
  int H; // høyde
  
  // der den befinner seg
  PVector posisjon;
  // der den hører hjemme
  PVector hjemmePosisjon;
  
  // konstruktør
  vRute(Movie mov,int L,int T, int W, int H){
    this.mov=mov;
    this.L=L;
    this.T=T;
    this.W=W;
    this.H=H;
    
    // starter hjemme
    hjemmePosisjon=new PVector(L+(width-mov.width)/2,
                               T+(height-mov.height)/2);
    posisjon=new PVector(hjemmePosisjon.x,
                         hjemmePosisjon.y);
  }
  
 void tegnHjemmePos(){
    noFill();
    rect(hjemmePosisjon.x,hjemmePosisjon.y,W,H);
  }
  void tegn(){
    PImage p=createImage(W, H, RGB);
    // kopier fra video
    p.copy(mov,L,T,W,H,0,0,W,H); // L+W,T+H
    // tegn det vi har kopiert
    image(p,posisjon.x,posisjon.y);
  }
  // har vi klikket på den
  boolean inneholder(int x,int y){
    return (x>posisjon.x)&&(x<posisjon.x+W)&&
           (y>posisjon.y)&&(y<posisjon.y+H);
  }
  
  void flytt(int dx,int dy){
    //hold ruta på skissen
    posisjon=new PVector(max(0,min(posisjon.x+dx,width-W)),
                         max(0,min( posisjon.y+dy,height-H)));
  }
  
 // er vi så nærme at vi skal godta det
 boolean erNesteHjemme(){
   float d=dist(posisjon.x,posisjon.y, 
                hjemmePosisjon.x,hjemmePosisjon.y);
   return (d < 10.0);
 }
 
 void finnTilfeldigPlass(){
   int dx=int(random(-width/2,width/2));
   int dy=int(random(-height/2,height/2));
   flytt(dx,dy);
 }
}
Skisser >VideoPussel