2014年6月29日 星期日

優秀是教出來的 (The Essential 55 by Ron Clark)

http://neptuner.666forum.tw/t114-topic

序: 我要給每個學生一個不同的人生。

克拉克老師的55條班規如下:

超基本 1:
遇到大人,要主動稱呼。大人問你話,你一定要清楚回答:「是/不是/好/不好/有/沒有」,或說「我不知道」。不可以光是點點頭或搖搖頭,也不可以含糊答「哦」或「嗯」。

超基本 2:
當別人在講話話,你的眼睛要一直看著他。如果旁邊有人發言,你就轉頭去面對那個說話的人。

超基本 3:
如果班上有同學贏得比賽,或有什麼出色的表現,大家都應該鼓掌恭喜他。鼓掌應該持續至少三秒,手掌的角度要剛好,才能拍出響亮的掌聲。

超基本 4:
課堂上進行討論時,要尊重別的學生的看法和意見。盡可能這麼說:「我同意約翰的說法,而且我還覺得…」或是「我不同意莎拉的看法。她的觀點很好,可是我認為…」或是「我認為維克多的看法很棒,他的話讓我想到…」。

超基本 5:
贏 得任何比賽,或有任何好表現,都不可以炫耀。如果輸了,也不要顯露出生氣的模樣。你可以這樣說:「參加剛剛這場比賽真是愉快,希望將來還能和你較較高 下。」要不然就說:「是很不錯的一場比賽。」不然就什麼都別說。生氣或說話酸溜溜,說什麼「我剛剛又沒盡全力,你真的沒那麼好」之類的,只是表示你很遜而 已。

超基本 6:
如果有人問你一個問題,你應該也回問他一個問題。如果有人問:「你這個週末愉快嗎?」你不只應該回答愉不愉快,還要回問他。舉例來說:
我:「你這個週末愉快嗎?」
你:「很愉快,我和家人去逛街買東西。你呢?你這個週末愉快嗎?
讓別人知道,你就跟他關心你一樣地關心他,這是基本的禮貌。

超基本 7:
咳嗽、打噴嚏、打嗝時,得體的做法是別過頭去,並用整個手掌掩口,然後你應該說聲:「對不起。」

超基本 8:
不要用咂嘴、翻白眼等類似動作表示輕蔑。

超基本 9:
每次我送你什麼獎品,你一定要說謝謝。如果你在收到獎品三秒之內沒有說謝謝,我會把送給你的東西要回來。因為不表示感謝是沒有藉口可以通融的。

超基本10:
有人送你東西時,絕對不要嫌棄禮物,也不要暗示你不領情,侮辱送禮的人。

超基本11:
隨時為別人做一些小小的貼心服務,帶給別人一個小驚喜,至少一個月一次。

超基本12:
偶而我會讓學生相互改考卷。為同學打分數時,如果你打錯分數,不管是打太高或打太低,多給的或少給的分數將由你自己的分數扣除。在別人的考卷上只能打「x」,以及答錯題的數目。

超基本13:
我們在課堂上一起讀課文時,你眼睛一定要看著課文一字一句。如果我叫你一人把課文讀下去,你一定要知道我們讀到哪裡,立刻就接著讀下去。

超基本14:
用紙筆作答的所有問答題,都應該以完整的句子回答。舉例來說,如果題目是:「俄羅斯的首都在那裡?」應該答:「俄羅斯的首都是莫斯科。」
此外,與別人對話時,以完整的句子回答問題也很重要,因為那是表現尊重。譬如,如果有人問:「你還好嗎?」 你不應該只說「很好」,而應該說:「我很好,謝謝。你呢?」 。
問題範例:籃球選手中,你認為誰比較棒,勞埃德或傑森?
1.重述問題並寫出答案:
籃球選手中,我認為勞埃德比較棒。
2.你為什麼這麼認為,說出一個理由:
我認為勞埃德比較棒,因為他投出致勝的一球。
3.把理由再加強一些:
他投出致勝的一球,表示他能在壓力下保持冷靜,具有求勝的決心。
4.重述問題並做結論。
因此,我認為勞埃德是比傑森優秀的球員。

超基本15:
學 年中我不時會發獎品,獎勵學生在操行或學業各方面的優秀表現。可是,如果你開口主動要獎品,我就不會給。開口問表現良好有沒有獎,是很沒禮貌的。你努力做 個好學生,應該是為了你自己好,而不是為了要有獎品。我通常會獎勵每一個在單元測驗考一百分的同學。如果你考一百分,並開口問你有沒有獎品,所有考一百分 的同學就通通都沒有獎品。

超基本16:
每個學生每天都要交每一科目的家庭作業,沒有例外。
第一招 就是留校輔導
第二招 我製作一個追縱家庭作業完成記錄的統計牌。
本班已經連續____天全體同學都做完家庭作業。
第三招 我善用同伴壓力。

超基本17:
課堂上,教完一科要換別科時,換的過程要迅速、安靜、有秩序。大家應該總是以最快的速度,從一本課本換到另一本,連帶所有家庭作業和必要的教材都準備好。轉換的時間應該不超過十秒鐘,我們則以七秒鐘為目標。

超基本18:
做什麼事都要盡可能有條不紊。

超基本19:
當我指派家庭作業時,不要抱怨。抱怨將導致作業分量加倍。

超基本20:
代課老師來代課時,你們要和我在的時候一樣遵守班規。(我知道執行起來有困難,但還是很重要。)

超基本21:
要遵守某些課堂禮儀。為了要專心、有條理、有效率,要遵守下列規矩:
A.未經許可,不要離開你的座位。例外是身體不舒服的時候,不舒服的話,不用問老師,快去洗手間或醫護室。
B.不要發言,除非
1.你有舉手,我也叫了你的名字。
2.我問你問題,你回答。
3.在下課或午餐時間。
4.老師說你可以說話的時候(像分組討論)。

超基本22:
你可以帶一瓶開水放在桌上。我在上課時不可以問你是不是可以去倒水。你甚至可以放吃的東西在桌上,只要別人沒看到,我也聽不到你吃東西的聲音。
打開任何包裝絕對不能發出聲響。
不能讓班上任何人聽到咀嚼的聲音。
不可以在桌子附近留下食物殘渣。

超基本23:
快 速記住學校其他老師的姓名,並這樣打招呼:「葛蘭姆老師早」或「歐提茲老師好。老師今天穿的很漂亮。」(註:如果是全班列隊前進,照規矩是不准說話的,所 以這時不可以和遇到的老師說話。但是在上下學、下課休息、幫老師跑腿、外出辦事或換教室上課時,你就應該和其他老師打招呼。)

超基本24:
如廁後要沖水和洗手。使用公廁的話,洗手前要先拿一張紙巾。洗完手要拿著紙巾關水龍頭,再取另一張紙巾擦乾雙手。絕對不要用乾淨的手去碰別人髒手碰過的地方。

超基本25:
學校會有訪客來參觀。如果來參觀我們班,我將會派兩名學生去外面迎接。負責去迎接的學生會拿一個歡迎某某先生或某某女士光臨的牌子。來賓到達時,這兩名學生要和他握手,介紹自己的名字,並歡迎這位來賓光臨。兩位學生先帶來賓簡單參觀大樓的設施,再帶來賓到教室。

超基本26:
在校內的公用場所,不要幫要好的同學佔位子。如果有同學想坐下,就讓他坐。不要排拒任何人。全校都是一家人,彼此之間要親切,要尊重。

超基本27:
不管是我還是其他老師責罰某名學生時,同學都不可以盯著那個學生看。如果是你惹麻煩挨罵,你也不希望別人看著你,所以別的同學挨罵時,請不要看著他。如果是你正在被我挨罵,也請不要生那些看你同學的氣。若有請告訴我,讓我來處理。

超基本28:
如果你有家庭作業的問題,你可以打電話給我。如果我不在家,可以這樣留言:「克拉克老師您好,我是誰誰誰。我的什麼什麼作業有問題要請教您。可能的話請您在幾點鐘之前回電話給我。謝謝。」沒必要留言十四次。

超基本29:
用餐時有些禮儀一定要遵守,我稱之為「用餐禮儀ABC」。

超基本30:
用餐完畢要自行清理。要清潔桌面,確定沒有留下垃圾在地上或附近。不論你身在何處,都要為你自己製造的垃圾負責,確定沒有亂丟,這很重要。

超基本31:
你在餐廳、旅館等場合所受到的服務,你要懂得惜福感恩。

超基本32:
搭公車或校車,總是面朝著前方坐著。絕對不要轉頭和其他學生交談,不要把任何東西伸出窗外,不要離開座位走來走去。下車時,一定要和司機說謝謝。

超基本33:
到校外進行戶外教學時,我們會遇見不同的人。當我介紹你們認識這些人時,你們要記住對方的名字。大家離去時,一定要握手道謝,記得要稱呼對方。

超基本34:
有機會讓你拿東西吃時,不論是「吃到飽」的自助餐還是班上有人請客,絕對不要貪多拼命多拿。不只是因為吃不完會浪費,也因為你如果沒留下足夠別人吃的分量,是很失禮的行為。

超基本35:
不論我們是在校內,還是出去做校外教學,如果有人掉了東西,請幫忙撿起來,並物歸原主。即使物主比較靠近東西掉的位置,你還是要彎腰幫忙撿,這樣才顯得有教養。

超基本36:
如果你走進一扇門,有人在你後面,你要幫他扶住門。如果門是用拉的,你就拉開門,但自己先不進去,扶著門在旁,禮讓另一個人先行,你自己再進去。如果門是用推的,你自己就先進去,再幫後面的人扶住門。

超基本37:
如果有人撞到你,即使不是你的錯,也要說:「對不起。」

超基本38:
當我們舉辦校外教學時,進去任何場所都不可以講話。大家就悄悄地進去,安靜到沒人注意到我們的存在。無論是電影院、教堂、劇院或任何人群聚集的場所,都適用這條班規。

超基本39:
進 行校外參訪時,不妨讚美一下我們正在參觀的地方。譬如:如果參觀的是別人的家,讚美他家的窗帘很漂亮,聽起來就會讓人覺得很窩心。有客人來家中,主人多少 有點不自在,你的讚美可以讓主人放輕鬆。此外,如果我們在參觀博物館或劇院等場所,稱讚建築很有格調,或是跟導遊說整個設施很棒,都是一種禮貌。

超基本40:
全校集會時,不要說話,不要東張西望,也不要試圖吸引別班朋友的注意。我們所呈現出來的形象,就是自愛、自重!

超基本41:
當你在家接聽電話時,一定要應答得體。

超基本42:
校外參訪結束,你們要握一握我的手以及每一位隨行老師或家長的手。要說謝謝我們花時間帶你們出來,要說你很高興有這次參訪機會。我關心的不是我自己是否被感謝,我是要教你在有人撥出時間精力為你付出時,你要適當地表示感恩。

超基本43:
進行校外參訪,要搭電扶梯時,大家要靠右邊站,讓趕時間的人從左邊通行。當我們要進入升降梯、地鐵、進出口時,都要先等裡面的人出來,我們再進入。

超基本44:
排隊時要排成一列,距離前面同學兩、三呎(七、八十公分),雙手垂兩側。臉朝前,絕對不要說話。

超基本45:
絕對不要插隊。如果有人在你面前插隊,不要說什麼或做什麼。就讓那個人插隊,但要讓我知道這件事,我會處理。如果你打抱不平,可能會惹上麻煩,那不值得。只要讓我知道就好了。請以同樣的方式處理同學之間的所有紛爭,在你自己解決任何問題之前先來找我。

超基本46:
到 電影院看電影時,無論如何都不要講話。我不管電影有多好看,也不管你要告訴旁邊的人什麼事,連悄悄話也不行!不可以把腳放在前面的椅子上。如果要吃東西, 必須盡可能不出聲。如果買一包糖果想在看電影的時候吃,你要在開演前就打開包裝。電影看一半打開糖果袋,是會吵到別人的。看電影時開著行動電話或呼叫器, 也很失禮。

超基本47:
不可以帶零嘴「多力多滋」來學校。

超基本48:
如果有任何同學找你麻煩,讓我知道。我是你的老師,我本來就應該照顧你和保護你。我不會讓學校裡的任何人欺負你或讓你覺得不舒服。相對的,我要求你不要自己處理;讓我處理這個學生。

超基本49:
捍衛你的信念。如果你全心全意相信自己的方向沒錯,就不要因為別人的否定而畏縮。

超基本50:
要積極地去享受人生。有些煩惱是很不值得的。看事情要看清大小輕重,要專注生命中美好的一面。

超基本51:
生活要抱著「別讓將來有遺憾」的態度。如果你想要做什麼,那就去做!絕對不要讓恐懼、疑慮或其他阻擋你。如果你想要追求什麼,就全心去追求。是你想做的,就要努力,沒真做到絕不放棄。如果你有什麼夢想,你就要竭盡所能去實現,直到夢想成真。

超基本52:
你是會犯錯的,請接受這個事實。你要從錯誤中學習,並繼續前進。

超基本53:
無論什麼情況,一定要誠實。你做了錯事,最好對我坦白承認,因為我欣賞誠實的人,常會因為你誠實而選擇不給予任何懲罰。

超基本54:
把握今天。今天是不能重來的,所以不要浪費它。生命是由特別的時刻組成的,許多時刻之所以特別,就是因為我們把警戒心拋到腦後,先行動再說,抓住這一天。

超基本55:
在你的能力範圍內,做一個最棒、最棒的人。
大人與小孩之間的互動
孩子需要有所適從,也喜歡有所適從。
如果孩子喜歡你的人,就會努力配合你。
孩子喜歡知道你對他們的期望。
孩子喜歡知道有人在關心他們。

2014年6月24日 星期二

Android Canvas drawText实现中文垂直居中

http://blog.csdn.net/hursing/article/details/18703599


目标:
把中文字符绘制到目标矩形的居中位置。
问题:
Android的Canvas绘图,drawText里的origin是以baseline为基准的,直接以目标矩形的bottom传进drawText,字符位置会偏下。这样写代码:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void onDraw (Canvas canvas) {  
  3.     Rect targetRect = new Rect(50501000200);  
  4.     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  5.     paint.setStrokeWidth(3);  
  6.     paint.setTextSize(80);  
  7.     String testString = "测试:ijkJQKA:1234";  
  8.     paint.setColor(Color.CYAN);  
  9.     canvas.drawRect(targetRect, paint);  
  10.     paint.setColor(Color.RED);  
  11.     canvas.drawText(testString, targetRect.left, targetRect.bottom, paint);  
  12. }  
会得到难看的结果:

找方案:
首先自己动手做实验,自己定一个baseline,然后把文字画上去,并对画上FontMetrics的几条线。FontMetrics里是字体图样的信息,有float型int型的版本,都可以从Paint中获取。它的每个成员数值都是以baseline为基准计算的,所以负值表示在baseline之上。实验代码:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void onDraw (Canvas canvas) {  
  3.     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  4.     paint.setStrokeWidth(3);  
  5.     paint.setTextSize(80);  
  6.     FontMetricsInt fmi = paint.getFontMetricsInt();  
  7.     String testString = "测试:ijkJQKA:1234";  
  8.     Rect bounds1 = new Rect();  
  9.     paint.getTextBounds("测"01, bounds1);  
  10.     Rect bounds2 = new Rect();  
  11.     paint.getTextBounds("测试:ijk"06, bounds2);  
  12.     // 随意设一个位置作为baseline  
  13.     int x = 200;  
  14.     int y = 400;  
  15.     // 把testString画在baseline上  
  16.     canvas.drawText(testString, x, y, paint);  
  17.     // bounds1  
  18.     paint.setStyle(Style.STROKE);  // 画空心矩形  
  19.     canvas.save();  
  20.     canvas.translate(x, y);  // 注意这里有translate。getTextBounds得到的矩形也是以baseline为基准的  
  21.     paint.setColor(Color.GREEN);          
  22.     canvas.drawRect(bounds1, paint);  
  23.     canvas.restore();  
  24.     // bounds2  
  25.     canvas.save();  
  26.     paint.setColor(Color.MAGENTA);  
  27.     canvas.translate(x, y);  
  28.     canvas.drawRect(bounds2, paint);  
  29.     canvas.restore();  
  30.     // baseline  
  31.     paint.setColor(Color.RED);  
  32.     canvas.drawLine(x, y, 1024, y, paint);  
  33.     // ascent  
  34.     paint.setColor(Color.YELLOW);  
  35.     canvas.drawLine(x, y+fmi.ascent, 1024, y+fmi.ascent, paint);  
  36.     // descent  
  37.     paint.setColor(Color.BLUE);  
  38.     canvas.drawLine(x, y+fmi.descent, 1024, y+fmi.descent, paint);  
  39.     // top  
  40.     paint.setColor(Color.DKGRAY);  
  41.     canvas.drawLine(x, y+fmi.top, 1024, y+fmi.top, paint);  
  42.     // bottom  
  43.     paint.setColor(Color.GREEN);  
  44.     canvas.drawLine(x, y+fmi.bottom, 1024, y+fmi.bottom, paint);  
  45. }  
获得结果:
红线是baseline,最上面的灰线是FontMetrics.top,最下面的绿线是FontMetrics.bottom。(绿色的bottom和蓝色的descent非常接近)
从图中可知,字符本身是在灰线和绿线之间居中的,知道这个就好办了。网上说的使用paint.getTextBounds的方法都不靠谱,可以看到对一个“测”字和6个字得到的bounds是不同的,图中的矩形能很好地表示这个函数得到的是字符的边界,而不是字体的边界。
FontMetrics.top的数值是个负数,其绝对值就是字符绘制边界到baseline的距离。
所以如果是把文字画在 FontMetrics高度的矩形中, drawText就应该传入 -FontMetrics.top。
要画在targetRect的居中位置,baseline的计算公式就是:
targetRect.top + (targetRect.bottom - targetRect.top) / 2 - (FontMetrics.bottom - FontMetrics.top) / 2 - FontMetrics.top
解决:
所以最开始的代码应该改成(顺便加入水平居中):
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void onDraw (Canvas canvas) {  
  3.     Rect targetRect = new Rect(50501000200);  
  4.     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  5.     paint.setStrokeWidth(3);  
  6.     paint.setTextSize(80);  
  7.     String testString = "测试:ijkJQKA:1234";  
  8.     paint.setColor(Color.CYAN);  
  9.     canvas.drawRect(targetRect, paint);  
  10.     paint.setColor(Color.RED);  
  11.     FontMetricsInt fontMetrics = paint.getFontMetricsInt();  
  12.         // 转载请注明出处:http://blog.csdn.net/hursing  
  13.     int baseline = targetRect.top + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;  
  14.     // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()  
  15.     paint.setTextAlign(Paint.Align.CENTER);  
  16.     canvas.drawText(testString, targetRect.centerX(), baseline, paint);  
  17. }  
效果(点击查看大图):

还可以去看看android sdk源码,
$android4.2/frameworks/base/corej/ava/android/text/BoringLayout.java是TextView画文字的算法
转载请注明出处:http://blog.csdn.net/hursing

2014年4月24日 星期四

Cocos2d-x 屏幕适配新解 - 兼容与扩展

http://blog.leafsoar.com/archives/2013/05-13.html

在读这篇文章之前,先读前一篇文章 Cocos2d-x 屏幕适配新解 是必要的。
如果说前一篇文章文章在 LsSize 提出之前的是基础,LsSize 是应用,那么对于这篇文章来说,LsSize 是基础,而这里是其的综合应用,我之初衷是其扩展性和兼容性,激发读者思维。也许你并没有体会出 LsSize 的强大,而实际上,它能做的比你想象的要多的多,这是前话 ~

ShoAll 模式的兼容

首先 LsSize 能满足 ShowAll 模式的需要,因为开始就是把 LsSize 当作 ShowAll 中的 WinSize 来设计的。 并且可以为背景做装饰,而在游戏设计之时并没有什么区别,LsSize 可以设定显示区域的大小,使背景层与 LsSize 分离(这一点在上一篇文章最后已经提到),从而保证了游戏的元素不会超出 LsSize 而露出到 VisibleSize 的区域内。

NoBorder 模式兼容

为什么说 NoBorder 兼容模式,它本身不就是 NoBorder 么,它与实际的 NoBorder 区别又在何处,有何优势?首先说说兼容,使用此模式,并不影响 你继续使用 VisibleSize 和 VisibleOrigin(以后简写Visible),你可以不使用 LsSize 的参考点,而使用 Visible 的相关值获取屏幕的拐点,游戏元素按照 Visible 来设置也可。下面详细介绍基于 LsSize 的 NoBorder 和原油 NoBorder 的区别以及其优势。
我们设想这样一个 实际情况 。我们需要一套资源图片,做为在适合分辨率的资源展示,当屏幕的大小分辨率在 854x480,800x480,728x480 (横屏下:为什么高度同样是 480 而宽度有这么多值 : P 这也是屏幕适配万恶之一了吧) 时,我们使用一套资源,当高度小于 480 时,我们使用另一套小的资源是合理的设计。而这里我们的资源宽姑且先不论,高一定是 480 最为合适了,最接近此分辨率的图片。那我们使用 NoBorder 的时候该 设置 WinSize 为多少 了呢?
基于 854x480 设计!好,那么当程序跑在 854x480 的屏幕上,正好满屏显示,而图片资源并没有放大或者缩小,或者说基于像素点点对点显示的。但是当这样设计的 WinSize 跑在 800x480 和 728x480 分辨率会如何?也许已经知道了,为了保证小于 854 那一小块区域的显示,画面将会缩小那么一点点,也许在如今屏幕的 ppi 日益渐高的情况下,并不十分明显,但画面一定是有那么一点模糊了。同理可以遇见,不论 WinSize 如何设置,在 三种少许不同分辨率下,显示的效果肯定略有不同。 而分辨率差别越大,这种效果就越明显。
注:细心的朋友已经读出上文描述中出现的 Bug ,并多谢指出问题的朋友。下面修复 Bug 并重新描述问题的情况 ~
折衷方案,我们基于 800x480 设计,那么此时出现的情况是,当跑在 800x480 的屏幕上时,正好满屏显示,而图片并没有任何放大或者缩小,或者说基于像素点点对点显示的。而当这样设计的 WinSize 跑在 728x480 和 854x480 的分辨率会如何? 854x480 相比 800x480,前者的宽高比要大于后者,所以它是宽对齐的,这意味着,画面有所放大,而上下将会有一部分残缺,此时设计高度将会失去参考价值。728x480 相比 800x480 ,前者的宽高比小于后者,所以它是高对齐的,此时画面并没有缩放,只是横向截取了小部分,这样的情况是由于 NoBorder 的实现机制所决定。当然我们可以将设计的宽度设置的很宽很宽,以保证高对齐,哈~但是魔(设计宽度)高一尺,道(实际宽度)高一丈,倒不如使用后文提到的“固定高度”方式了~ 而这里的 854x480,800x480,728x480 等数据只是屏幕适配等问题的“缩影”
读到这里也许已经发现了,LsSize 已经完美 (这里的完美,并非只此特殊情况下的解决方法,而是总览全文,基于 LsSize 的设计理念,其兼容性和可扩展性,显然在此时,固定高度是更好的实现方式) 的解决了这个问题,动态 WinSize ,一个合理的设计,我梦将 LsSize 设定为 720x480,并且使用 高度为 480 的图片资源,而宽度可以往大了设计,比如 854x480 的图片资源,读过前文 LsSize 的实现原理,我们可以知道,在这三种情况下,屏幕的画面并没有缩放,因为实际的宽度总是大于 720 ,从而达不到缩放的条件。480 高度的图片,能够正好填充 480 高度的屏幕,而图片的宽度往大了设计,在宽度稍微小的屏幕下,会被截取一部分,但就显示效果来说,并没有什么损失,而游戏的元素位置可以用原来的方法基于 Visible 来设计。
为什么可以做到如此!原本的 NoBorder 通过固定 WinSize 根据屏幕宽高比缩放,所以会有不同程度的缩放,而 LsSizeNoBorder 的设计实现,通过屏幕宽高比来获得 WinSize 的值,以保证 LsSize 总能在屏幕上正好全部显示。
LsSizeNoBorder 比 NoBorder 好,好多少,这就仁者见仁,智者见智了 ~

kResolutionFixedHeight,kResolutionFixedWidth 扩展兼容模式

FixedHeight 和 FixedWidth 是什么模式,如果你试用了最新版的 cocos2d-x (2.1.3)就能发现这两种模式,一种是固定设计时的高,一种是固定设计时的宽。而在当前的 2.0.4 并没有这两种模式,而现在,你可以通过 LsSize 来实现这两种模式。存在既是合理,FixedHeight 和 FixedWidth 的存在是合理的,比如我们写一个横版过关游戏,同样是三种分辨率 854x480,800x480,728x480 使用固定设计高度的方法,可以避免在 NoBorder 中会根据宽度而做的缩放。
而在 LsSizeNoBorder 中好似也实现了相同的功能!但注意有一点区别,在 LsSizeNoBorder 中,实际屏幕高度为 480 ,如果宽度小于 720 时,那么画面会缩放,而这里新模式固定高度不会。如果我们想让 LsSize 实现这种功能怎么做,我们将对 LsSize 的设计稍作扩展,上篇文章的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CCSize frameSize = CCEGLView::sharedOpenGLView()->getFrameSize();
// 设置 LsSize 固定值
CCSize lsSize = CCSizeMake(480, 320);

float scaleX = (float) frameSize.width / lsSize.width;
float scaleY = (float) frameSize.height / lsSize.height;

// 定义 scale 变量
float scale = 0.0f; // MAX(scaleX, scaleY);
if (scaleX > scaleY) {
    // 如果是 X 方向偏大,那么 scaleX 需要除以一个放大系数,放大系数可以由枞方向获取,
    // 因为此时 FrameSize 和 LsSize 的上下边是重叠的
    scale = scaleX / (frameSize.height / (float) lsSize.height);
} else {
    scale = scaleY / (frameSize.width / (float) lsSize.width);
}

CCLog("x: %f; y: %f; scale: %f", scaleX, scaleY, scale);

// 根据 LsSize 和屏幕宽高比动态设定 WinSize
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(lsSize.width * scale,
      lsSize.height * scale, kResolutionNoBorder);
我们的实际缩放系数,是根据 scaleX 和 scaleY 的大小来判断,依据哪个方向缩放,从而在显示效果上是高对齐还是宽对齐。而想要固定是高度对其还是宽度对其,那只要换用如下方法即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 要实现这种功能,我们需要做的就是算得 缩放系数,缩放系数由 原来的设计稍作演变即可
// 由于 NoBorder 的缩放是根据 scaleX 和 scaleY 的熟大熟小来判断缩放系数是参照横向还是竖向
// 固我们需要两个先决条件,固定的方向 和 缩放的参照方向,而得到如下算法

// 固定高度
if (scaleX > scaleY)
  scale = scaleX / (frameSize.height / (float) lsSize.height);
else
  scale = scaleX / (frameSize.width / (float) lsSize.width);

// 固定宽度
if (scaleX > scaleY)
  scale = scaleY / (frameSize.height / (float) lsSize.height);
else
  scale = scaleY / (frameSize.width / (float) lsSize.width);
下面通过几张效果图展示 固定高度 和 固定宽度 效果:
显示效果:(NoBorder 固定高度模式 ;FrameSize = 520x320; LsSize = 480x320; WinSize = 动态获取) 图片
显示效果:(NoBorder 固定高度模式 ;FrameSize = 520x360; LsSize = 480x320; WinSize = 动态获取) 图片
显示效果:(NoBorder 固定宽度模式 ;FrameSize = 480x360; LsSize = 480x320; WinSize = 动态获取) 图片
显示效果:(NoBorder 固定宽度模式 ;FrameSize = 480x300; LsSize = 480x320; WinSize = 动态获取) 图片
如图所示,我们固定了一个方向,使得这个方向上的设计长度正好填充屏幕,而另一个方向上会有所延伸或截取,而此时如果想或者屏幕拐点,可以配合 Visible 的显示区域算得。而这也正式 cocos2d-x 2.1.3 所实现的功能,而如果你此时为了稳定而使用 2.0.4 stable 版本,那么就可以通过这种基于 LsSize 的设计方法实现 FixedHeight 与 FixedWidth。 而在将来后续版本稳定,也可以很平滑的升级到使用自带的方式替换,其显示效果一样,只是后续版本 cocos2d-x 在内部将它封装了而已。

kResolutionLeafsoar 模式的核心思想

透过现象看本质!基于固定 LsSize 的动态 WinSize 设计。之所以能够兼容这么多模式并且有所加强,在于 LsSize 在 FrameSize、WinSize、VisibleSize、VisibleOrigin等概念之外的存在,并且通过动态计算 scale 而游走于此等之间。它的存在并不依赖于 这些已有概念,而反过来,让已有的概念去依赖 LsSize 。从而保持设计上的灵活性与扩展性。

Comments