Processing互動編程開發實踐之動態文字打亂功能(別嫌長,代碼多,圖片多)

這篇文章有什麼價值?

  1. 簡單介紹Processing編程
  2. 提供一份基於鼠標響應的動畫的Processing代碼
  3. 重頭戲:描述動態文字打亂功能實現的重要細節,並將源碼公開

1.什麼是Processing編程?

這裏是~~非官方~~ 簡介:Processing是一個爲開發面向圖形的應用(visually oriented application)而生的簡單易用的編程語言和編程環境。Processing的創造者將它看作是一個代碼素描本。它尤其擅長算法動畫和即時交互反饋,所以近年來在交互動畫,複雜數據可視化,視覺設計,原型開發和製作方向越發流行,大家都喜歡這個可愛貼心,簡潔好用的編程工具。 Processing基於Java,其語法規則和Java是一致的 。

2.入門演示代碼

本博文免費提供Processing編程學習的鏈接:西天取經的路在這裏
首先是承諾好的鼠標響應動畫代碼:
void setup(){

size(400, 400);

}

 

void draw(){

background(#FFEE31);

pushMatrix();

translate(200, 200 - 60);

//eyes

PVector mouse = new PVector(mouseX, mouseY);

mouse.sub(200, 200 - 60, 0);

mouse.limit(7);

fill(0);

noStroke();

rectMode(CENTER);

rect(-1*40+mouse.x, -15+mouse.y, 15, 25, 8);

if(mousePressed)

rect(40+mouse.x, -15+mouse.y, 28, 10, 5);

else

rect(40+mouse.x, -15+mouse.y, 15, 25, 8);

//mouth

noFill();

strokeWeight(12);

stroke(0);

arc(0, 0, 150, 120, PI/4, PI-PI/4);

popMatrix();

//text

textSize(25);

textAlign(CENTER);

text("Enjoy your hacking with\nProcessing!\n I am LSS.", width/2, height/2+100);
println("We are the super star .Love is enough for me");

}

粘貼複製,保存運行,如果你沒有做任何改動的話,顯示效果應該像下面這樣:效果圖片

重頭戲:文字打亂功能實現

既然是重頭戲,不如回憶一下當時事情發生的全過程。事情是這樣子的。。。。。。。某一天,突然在某個接單羣看到一個任務(天上掉餡餅了),說要用java模仿某個網頁做一個功能(網頁地址在這裏:https://www.qqxiuzi.cn/zh/daluan/)。這還不簡單,JSP,HTML,JavaScript隨你選,分分鐘給你實現了。然而,被客服拉到一個討論組時才發現,客戶其實是想要使用Processing這個互動編程工具,輔助以Arduino控制,做一個課堂小作品。那麼,客戶爲什麼一上來說這個是java的編程任務呢?博文前面說了,processing的底層就是java寫的,所以,,,,對吧。我當即去網上百度學習一下客戶口中的Processing編程是個什麼東東,emmm,它竟然是老外用來教自家孩子入門編程的工具,不過呢,主要的還是用來做交互動畫,動態數據圖表等功能,賊強大。在簡單學習了之後,我在本地processing環境運行了我的第一個“hello world ”代碼後,覺得這個開發環境很友好(其實是客戶給出的報酬很誘惑人),有把握把客戶的作品給搞出來。最後,談妥,客戶下訂單,我便開始工作,下面是正文部分。
第一步,我先到這個網站https://www.qqxiuzi.cn/zh/daluan/體驗一把所謂的“文本打亂”功能,然後客戶說了,你的界面大小是要有限制的,必須是585*828 ,其次,你這個Processing代碼需要能接收到Arduino端口發過來的控制數據,(控制數據由一個傳感器發出,這個我不用管),每接受一個控制信號,就打亂一次文本。而且,文本的段落樣式不能變,比如換行位置不能變。呵呵,要求還挺多,可是客戶真的是很好說話,這次接單任務中,與人溝通的能力也提升不少,客戶的需求也不是說鐵定不能變的,我們技術人員可以明確表示,某某功能點“不科學”,咱們可以換一種方式去實現一個類似的功能等等方式。
第二步,開始 解決客戶問題。其實,當時整個過程是不是完全分成敲定任務需求細節和各種功能細節的,而是採取了編程開發的“最佳實踐模式”(忘了是誰說的什麼名詞了):快速上線,邊做邊改。當時,首項工作是實現Processing環境能接收到Arduino端的控制數據。還好,做過89C52系列的單片機開發(也就是點亮了幾個流水燈,控制串口數據收發),arduino端數據發送和端口部分代碼是客戶寫的,我這邊主要負責寫接收和顯示控制信號的代碼,完美分工。客戶的電腦是Mac Air ,所以在網上找到的arduino串口發送代碼都是面向Windows操作系統的,花了兩天時間才搞定這個數據接收。
下一步任務是,畫框框,這個界面中的文本內容是不可以隨便顯示的,要和像素尺寸打交道。我的天啊,這個是前端或者美工的任務好吧,,,,emm,沒事兒,有錢,管他那麼多幹啥。計算像素,最後畫出來文本框了。然後開始進入下一步,動態刷新。
Processing中存在一個draw()函數,這個函數在setup()函數結束之後,默認是死循環無限次運行的,一直在自動刷新頁面。這就導致了一個問題,就是你上一次在界面上顯示的文本,會被下一次的打亂後的文本覆蓋,,,3秒左右,那個界面就模糊不清了,原本理想中,即便會自動刷新界面,上一個界面中的文本應該要自動消失的,現實中確實發生了重疊。這個重影問題又花費了兩天時間才搞定,怎麼做的呢?一方面,客戶把 background(0)背景設置函數從setup()函數中搬到了draw()函數中,這樣每一次刷新後,界面背景顏色就要重新設定一次,然後,上一次的文本就神奇般地消失了,匪夷所思啊,太不科學了,這個現象,憑我三天來學習的Processing知識是解釋不了的。(其實三天來,我只是上午在做任務,學習Processing,主要是查英文版的API,也會查別人的博文,尋找思路,其他時間該幹嘛還幹嘛,我又不是全職做這個滴)轉念一想,我又不是要深入搞這個的。更何況,我自己也找到了解決方案,而且是官方API推薦的:將要顯示的內容使用一個PGraphic對象的text()方法保存,這個對象有一個clear()方法,可以清楚對象的文本信息。把這個對象顯示在界面上,問題就解決了。
既然重影問題解決了,也能接收到arduino傳過來的控制信號了,那就開始編寫實現文本打亂功能的函數吧。我的設計大致是這個樣子:隨機交換N次文本中的字符位置,然後再把文本對象傳出去顯示在界面上。難點是,段落控制這個樣式,如果不考慮這個話,指不定原來是空格的地方,下一次就會顯示字符了。這個問題困擾了我一上午。第二天的上午,我選擇分段顯示,把有樣式發生變化的字符 的像素座標作爲參數傳遞給我編寫的函數。“隔離變化,解耦”這一句話一直在大腦中會響,能抽象就別節約腦力。
最後,整個任務搞定了,代碼發給客戶了,Processing也失寵了,在我的編程語言世界裏,.NET 環境中C#用的最多,Java開發環境的地位在逐步提升,追上.NET只是時間問題,最近在空閒時間會偶爾調戲一下Python大蟒蛇,真香。
這是我承諾的文本打亂Processing代碼部分,歡迎複製運行
功能說明:運行後,每次單擊鼠標,文本便會隨機打亂一次,重新顯示。
  
String datas="第,一,編, ,藝,術,品,的,本,質,及,其,產,生, 41,由,此,我,們,可,以,定,下,一,條,規,則,:,要,了,解,一,件,藝,術,品,,,一,個,藝,術,家,,,一,羣,藝,術,家,,,必,須,正,確,的,設,想,他,們,所,屬,的,時,代,的,精,神,和,風,俗,概,況,。,這,是,藝,術,品,最,後,的,解,釋,,,也,是,決,定,一,切,的,基,本,原,因,。,這,一,點,已,經,經,由,經,驗,證,實,;,只,要,翻,一,下,藝,術,史,上,各,個,重,要,的,時,代,,,就,可,以,看,到,某,種,藝,術,是,和,某,些,時,代,精,神,與,風,俗,情,況,同,時,出,現,,,同,時,消,失,的,。,—,—,例,如,希,臘,悲,劇,:,埃,斯,庫,羅,斯,,,索,福,克,勒,斯,,,歐,裏,庇,得,斯,的,作,品,誕,生,的,時,代,,,正,是,希,臘,人,戰,勝,波,斯,人,的,時,代,,,小,小,的,共,和,城,邦,從,事,與,壯,烈,鬥,爭,的,時,代,,,以,極,大,的,努,力,爭,取,獨,立,,,在,文,明,世,界,中,取,得,領,先,地,位,的,時,代,。,等,到,民,氣,的,消,沉,與,馬,其,頓,的,入,侵,使,希,臘,受,到,異,族,統,治,,民,族,的,獨,立,與,元,氣,一,齊,喪,失,的,時,候,,,悲,劇,也,就,跟,着,消,滅,。,—,—,同,樣,,,哥,德,式,建,築,在,封,建,制,度,正,式,建,立,的,時,期,發,展,起,來,,,正,當,十,一,世,紀,的,黎,明,時,期,,,社,會,擺,脫,了,諾,曼,人,與,盜,匪,的,騷,擾,,,開,始,穩,定,的,時,候,。,到,十,五,世,紀,末,葉,,,近,代,君,主,政,體,誕,生,,,促,使,獨,立,的,小,諸,侯,割,據,的,制,度,,,以,及,與,之,有,關,的,全,部,風,俗,趨,於,瓦,解,的,時,候,,,哥,德,式,建,築,也,跟,着,消,滅,。,—,—,同,樣,,,荷,蘭,繪,畫,的,勃,興,,,正,是,荷,蘭,憑,着,頑,強,與,勇,敢,推,翻,西,班,牙,的,統,治,,,與,英,國,勢,均,力,敵,的,作,戰,,,在,歐,洲,成,爲,最,富,庶,,,最,自,由,,,最,繁,盛,,,最,發,達,的,國,家,的,時,候,。,十,八,世,紀,初,期,荷,蘭,繪,畫,衰,落,的,時,候,,,正,是,荷,蘭,的,國,勢,趨,於,頹,唐,,,讓,英,國,佔,了,第,一,位,,,國,家,縮,成,一,個,組,織,嚴,密,,,管,理,完,善,的,商,號,與,銀,行,,,人,民,過,着,安,分,守,己,的,小,康,生,活,,,不,再,有,什,麼,壯,志,雄,心,,,也,不,再,有,激,動,的,情,緒,的,時,代,。,—,—,同,樣,,,法,國,悲,劇,的,出,現,,,恰,好,是,正,規,的,君,主,政,體,在,路,易,十,四,統,治,下,確,立,了,規,矩,立,法,,,提,倡,宮,廷,生,活,,,講,究,優,美,的,儀,表,和,文,雅,的,起,居,習,慣,的,時,候,。,而,法,國,悲,劇,的,消,滅,,,又,正,好,是,貴,族,社,會,和,宮,廷,風,氣,被,大,革,命,一,掃,而,空,的,時,候,。,"+
",我,想,做,一,個,比,較,,,使,風,俗,和,時,代,精,神,對,美,術,的,作,用,更,明,顯,。,假,如,你,們,從,南,方,向,北,方,出,發,,,可,以,發,覺,進,到,某,一,地,帶,就,有,某,種,特,";

String[] Str = split(datas,',');

void firstly(int n){
  int ColNum = 0;
  int beginPixel= 276;
  for(int i=0;i<n+1 ;i++)
  { 
     if(i == 14){
        text(Str[i],284+ColNum*13+10,59);
        continue;
    }
    text(Str[i],beginPixel+ColNum*13,59);
    ColNum++;
  }
}

void secondly(int start,int end  ){
  int ColNum = 0;
  int beginPixel= 94;
  for(int i = start; i<end+1 ;i++)
  { 
    text(Str[i],beginPixel+ColNum*16,111);
    ColNum++;
  }
  
}

void thirdly(int start,int end){
  
    int ColNum=0,RowNum=0;
    int count=0;
    int beginPixel= 62;
    for(int i=start;i<end+1;i++)
    {
      if(count == 28)
        {
          ColNum=0;
          RowNum++;
          count =0;
        }
     text(Str[i],beginPixel+ColNum*16,131+RowNum*20);
     ColNum++;
     count++;
    }
}

void lastly(int start,int end1,int end2){
    int ColNum=0;
    int beginPixel= 94;
    for(int i=start;i<end1+1;i++)
    {
      text(Str[i],beginPixel+ColNum*16,610);
      ColNum++;
    }
    
     ColNum=0;
     for(int i=end1+1;i<end2+1;i++)
    {
      text(Str[i],beginPixel-28+ColNum*16,630);
      ColNum++;
    }
}

 
void disorder(int start,int end)
{
  String temp = null;
  for(int i=start;i<= end;i++){
     int randomNum1 =(int) random(start,end);
     int randomNum2 =(int) random(start,end);
     temp=Str[randomNum1];
     Str[randomNum1]=Str[randomNum2];
     Str[randomNum2]=temp;
   }
  
}


void setup(){
  size(585,828);
 // background(10);
  textAlign(LEFT);
 // myPort = new Serial(this, "/dev/cu.wchusbserial1450", 9600); 
  
  //this for() function is to display the indexes of different chars. It could be erased.
  for(int i=0;i<743 ;i++)
  { 
    print(Str[i]+i);
  }
  println(Str.length);
 
}

void draw(){
  background(10);
 
      firstly(14);
      secondly(15,40);
      thirdly(41,687);
      lastly(689,714,741);
 
 delay(2000); 
}

//the mousePressed() event used to test the functions above ,It could be erased too.
void mousePressed(){
  disorder(0,741);
}
  
  

效果圖:
在這裏插入圖片描述在這裏插入圖片描述

《圍城》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章