<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-9004261571334633871</atom:id><lastBuildDate>Sun, 12 Oct 2025 18:31:44 +0000</lastBuildDate><category>程式雜技</category><category>寫不完的遊戲引擎</category><category>電影雜記</category><category>遊戲雜記</category><category>旅行</category><category>偶發雜感</category><category>生活筆記</category><title>藍斯洛‧雜技的雜記</title><description>&quot;Good programmers copy, great programmers steal.&quot;</description><link>http://lancelotdiary.blogspot.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>102</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-6090116353454203744</guid><pubDate>Fri, 26 May 2017 08:19:00 +0000</pubDate><atom:updated>2017-05-26T16:22:32.823+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>Native Game Programming</title><description>&lt;p&gt;用 Unity 做遊戲，C#寫遊戲程式，是工作上的必需。&lt;/p&gt;  &lt;p&gt;用 C++ 寫手機遊戲程式，過程中有一種不同的樂趣與成就感。&lt;/p&gt;  &lt;p&gt;所以我仍然抓著空餘時間套著 Android NDK 在手機上玩玩 Graphic，把以前半成品的 Engine 想辦法 Porting 到 Android 系統上玩。&lt;/p&gt;  &lt;p&gt;對於要在 Visual Studio 上開發原生Android 程式，NVidia 的 Nsight Tegra for Visual Studio 是很好用的支援工具，當中的 Android Log Output 尤其好用。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-FwhutIKRobE/WSflxsrV3qI/AAAAAAAAAu8/-xokBLHTAzYScotvZMojVxYYjlnOldEdACHM/s1600-h/android_log%255B3%255D&quot;&gt;&lt;img title=&quot;android_log&quot; style=&quot;margin: 3px 5px; display: inline; background-image: none;&quot; border=&quot;0&quot; alt=&quot;android_log&quot; src=&quot;https://lh3.googleusercontent.com/-WI18SUK5pj8/WSflx28D8yI/AAAAAAAAAvA/-syGW7m4ymUdO_M0UkkaIwd1N1d3iFgugCHM/android_log_thumb%255B1%255D?imgmax=800&quot; width=&quot;601&quot; height=&quot;143&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;即使是用 Unity 開發手機遊戲，這 Log Window 也幫助很大。&lt;/p&gt;  &lt;p&gt;Android Logcat 輸出的訊息量很龐大，如果不能好好的過濾訊息，Debug 抓問題的時候，會幾乎不知從何下手。&lt;/p&gt;  &lt;p&gt;Nsight Tegra 這套工具裡的 Log Output，給了還算完善的自訂過濾器功能，而且提供了 UI 來訂製過濾器。&lt;/p&gt;  &lt;p&gt;所以我才會面對這樣的問題:&lt;/p&gt;  &lt;p&gt;Visual Studio 今年改版出了 2017 版，但是 NVidia 遲遲不將 Nsight Tegra 支援 VS2017，以致我只能選擇繼續使用 VS2015或是，在 VS2017上用功能很差的Logcat。&lt;/p&gt;  &lt;p&gt;最後我決定，在 VS2017上，自己開發個外掛，&amp;quot;山寨&amp;quot; Nsight Tegra 的 Log Output。&lt;/p&gt;  &lt;p&gt;沒想到的是，我為了 Native Game Programming，還是繞了回來用 C#寫工具。&lt;/p&gt;  &lt;p&gt;上面這句話才是本篇的重點。&lt;/p&gt;  &lt;p&gt;這個 Extension 還沒完成，不過也還可以先給個 GitHub Link&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://github.com/lancelot-coder-chen/logcat-toolwindow-vsext&quot;&gt;Visual Studio Tool Window Extension for Android Logcat Output &amp;amp; Filter&lt;/a&gt;&lt;/p&gt;</description><link>http://lancelotdiary.blogspot.com/2017/05/native-game-programming.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-WI18SUK5pj8/WSflx28D8yI/AAAAAAAAAvA/-syGW7m4ymUdO_M0UkkaIwd1N1d3iFgugCHM/s72-c/android_log_thumb%255B1%255D?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-1983559123084131358</guid><pubDate>Sat, 13 Jul 2013 02:43:00 +0000</pubDate><atom:updated>2013-07-13T10:44:10.433+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>Android NDK + Cocos2d-x + WinGDB Mobile + Visual Studio 2012</title><description>&lt;p&gt;小小的搞定了 Cocos2d-x 這個跨平台開發的遊戲引擎，做個紀錄。&lt;/p&gt;  &lt;p&gt;Android SDK, NDK 的安裝就不提了。WinGDB 有個 Mobile 版本，可以支援 Android NDK 的 Build 與 Debug，這個也要先安裝起來。&lt;/p&gt;  &lt;p&gt;Cocos2d-x 先去下載來，這次裝的是新版本，Cocos-x 2.1.4。&lt;/p&gt;  &lt;p&gt;接著就是整合的步驟了。&lt;/p&gt;  &lt;p&gt;1. 以 WinGDB 建立新的 Project &amp;amp; Solution, “New Android Java+native package”&lt;/p&gt;  &lt;p&gt;2. Cocos2dx SDK 裡的 Cocos2dx 目錄，複製到 Project Solution 目錄中，與 Package 的 src, res 等目錄同一層。&lt;/p&gt;  &lt;p&gt;3. Solution 內 Add Project, &amp;quot;import Native Library android project&amp;quot;, 導入 Cocos2dx 的 Android.mk, (project name “cocos2dx”, 不然會新增另一個目錄)&lt;/p&gt;  &lt;p&gt;4. For Cocos2dx Project, Configuration/ Source, Additional C++ compile flags = -frtti, C++ Standard library = Static GNU libstdc++ &lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIBGhtrrJjYai1fD14cxdE_ktRanHmJOXisyZ6CoJ-lNG25FNMySb3UOHYD1rFW4I1PLL_FU_Qdv9rhdicUbVQ09jYywVLOMQ_k6rkFykDlTVL10KN1UhSoVSka8MMdClmVuWEO4rJObR_/s1600-h/image%25255B9%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoA3IGFT1DDPHsxSsVowSqjy728XMza6fxhRcHEfAe2fYj1XLvSio_cmrfg-M5V6WDJS0Rhyab2jVVX2Ct4Pb4SNvFKz-Qajqz64rEmu2WlNidtjPss8mkIQwzNiii7zyj-Z49cekwgz5b/?imgmax=800&quot; width=&quot;595&quot; height=&quot;336&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Configuration/Target, Target ABI = armeabi&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjApXkJTaCf_Zgw1bQZSXA4Fp7ngW_9e56CJoaM3kNVxyd-FpiVgBOw0olcsw5dodhri1mUCmNiUEr5_1eMIyzX1TVJrJdy9HvNZtpnmh0PsHtfruzmRByHma2lWdwlWn9nK5ht_FctQt1L/s1600-h/image%25255B10%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHQmUrPCqvm62STJ_Wx-d4S_ahVOnIxcsLHsJ7RbPYxkAPB0AB4_Jx_oyxuzY4a3JP_zPJbCoLCL0vubqm9sRUYHvr5TUXeB2FiGaxp6Fmtl03F17e8Te_LGtRVG0Cd9nKQ6ySHiTGnGYI/?imgmax=800&quot; width=&quot;592&quot; height=&quot;335&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Common/General, Target Platform = android-10 (NDK 沒有 android-10, 會自動取用到 android-9)&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipX68kNvhyphenhyphenPSIpxVM1WgZkLEoR4o1nsMtmfbVGtqbXla-GKsyg6BbEvIEJp4CWk8ZF6DObYAb9kGaMrqu59fPgQe8pyhjSXrg4gc0TfNQX973ApILFtvXLUvVtX3GRYRN5bIlKgpACN-pj/s1600-h/image%25255B14%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoOJmyyZbqyuzZeRGMLTsY0gwwlzaxVDNHxRXLpiiarLZ2U199uUvVEVc-KLKItjT-oCnPc1N6t8TBgLudahZf82TQTpGiiOeymu6TCHkUo3yWpdLjFNxOmYIwNPwi7We2X8YuxeZhIG7f/?imgmax=800&quot; width=&quot;592&quot; height=&quot;332&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;5. Cocos2dx_static 模組, Common/Compiler, Include Path 要設定相關的路徑&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX-9An9-r4bwdBf3x5Hr0wk2rIM99QfPspkoD4GzQsHDHH2rrQEC7FVK1-eB_u1VLxJUSdHEZW8KMVToXpofVLAfe2XY1nmozSm2-CMKO4WLUilUf-MZopE41JDAulOp-SirbsCh7xs4HL/s1600-h/image%25255B18%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmTy50aWwzOeB46Pl8AK2gUavTuSVU3YV7bpifpOWCgRVC60LCejACKfLh7ZKHxrF5h57i0Qw-cumZOEz_u9sYQh40IUBuj7Kwsag0smRD2TMYzd700LqO1Bj0TOWebdWUQYvJsX3KVuer/?imgmax=800&quot; width=&quot;595&quot; height=&quot;336&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Common/Linker, Linker Flags = -lGLESv2 -llog -lz -lEGL, Export Linker Flags = -llog –lz -lGLESv2&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWk1h7Cby3ZLJWM9inmf2os9HbsZ7tNKe10tkGvVYtGW7b2bqEpy67iuEHeuGy-8_5qFsFiyOrjBff7fhaFED_c5Q47Ml-tsnPN3bGjknfTQk4xwsKOJjjPb9srH4jQjmnS25Thenznp9s/s1600-h/image%25255B22%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3v_-YqCx4wGdogOvZRgBTDAxyxtQASYYhukb-5HNTV7qmreir4rwZW_uCije-Kwt7Sa3a8rmBd9MbQ2fn-hOxmBghSyCH76GOoNro_twYM61WA_tV52SA8cCM1UM4GfbHehaSxOrVf8GM/?imgmax=800&quot; width=&quot;599&quot; height=&quot;336&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;其他的可以不用改變&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;6. Package Project, Common/General, Target Platform = android-10&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOi1kZUw4vRNSGRhA_bp0cHFDqxHstiMLSVxNHHs1LN8f8S5qSrigF0wqd8p1sjG-KwccRSlJRd5AqGub6dXQ-zVx52hdXwCzlrdOXZeWZIl0S5asJZbX-v8L6lCUcgfxN6BxhydhQiErU/s1600-h/image%25255B26%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrN1EXzgI993Qedomc1usEYTCbi3KUg-Og7Oc0G4AsN3nQpLTHHJw1UhrTwu3jKLJs4ekvNJagf6oyxp0nt4XIkmxTLA163TQYPh9DhOhgMs9BYeTnU_zM3um14wOpRrR4-o2NUzevksKh/?imgmax=800&quot; width=&quot;603&quot; height=&quot;341&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Common/API Levels, Minimum API Level = 10, Target API Level = 10,&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV1lMnCLp1NzCTsxxRzIXyzJqqey6uEyzsIihvGG8GQVhWsZq1E56j_UtQSw1-V9hL26FuczAC87D1ruwDng3Mv1nNjIlF6w_DF0XFyBzw0SyMS5zM41cB8ICge1T8-qkzhSRhsC9EzuKi/s1600-h/image%25255B30%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwbAQ7YI25WuuczLH4qLu6BO4zl8qjrb2qmBxkH8y_JIdRzXKT_R89BlzluJ4DBoEOIQOrDbjAI0AaBmuc1MmsYe0Qs3WzLVYr3XQ6TLGflndE2wD1q0sIyV6IXULnS7JYw7hE8OyQKiq/?imgmax=800&quot; width=&quot;603&quot; height=&quot;338&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Configuration/Source, Additional C++ compile flags = -frtti, C++ Standard library = Static GNU libstdc++&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdCMq37NJgM4Yq5mP6OGbd7t70mV8t8CR-iByi8XzWZ6QcLmmbYkaoMYT0ENx6bOaiBctF2la9yUsWBlXimYoFfBZhlCGdTul_fGrJUOPDs_o9rhr6Qgyhppb_fBoUJdw8g98IQwm6P8xU/s1600-h/image%25255B35%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD9JGoKHFrmjmHCRm4NtV0TmuCSvgqzUTwUP7jZ2XkVtkcfq6iyeqfGk6M6CCcUI1X8yPFIUsXye_EwKomw7jCKR2UaadTYqQY4xUN8cjNHcbMJVeC2pkVawIKNQuru4vRHIx8hMR1aHfq/?imgmax=800&quot; width=&quot;602&quot; height=&quot;341&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Configuration/Target, Target ABI = armeabi&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJN_y4UdI9G4TiFq_LsMT-YoqR3jPEmGy1-qwR__AGnvWo82ASMRFUJ7ND6G23towTXjo_VueQnSMUWDzNSkdMR2Wsbtoopo96OuVJCxSZz0pG-ut2v9QUSYhHPF9ZQKgXbbUNRiKazalq/s1600-h/image%25255B39%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg126zRCrCo140ke5kz0NDF99H5Znbht3qJctM1V9vX06pAv69EwAyOVkDn8ZoVZ7HkuBKwJmDAFdgmraikb4_KiJonKs3U1L5XORHIp9KcqIZ9Ehk1nvjYr1VDPCaDT6sf46f8ZcOHpC_k/?imgmax=800&quot; width=&quot;600&quot; height=&quot;339&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Configuration/Debug, Debug Target Device 選用Device 或模擬器&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHVoK_4xp9xYp_cJLGFruv1xWoY83PO06H2wKT2wmtf1Bw00B9MLlJxPdZmYyH-NAh5igPS38AjOqKB8uslDp0gwKJdfmXFWKp4nDKQ10_N3R2ScLxP1lvRuSb2ihKnac8V30dZqbNE0vA/s1600-h/image%25255B43%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitix588bIV6Ux9TrFnRwtNay85GfKC3cDbSQJrRPM_pE1qGOHi-MDPiR71RL99KMUUn30Ldik8MANtkYlBbQ700L6xVcYhNYNNCEy7T0Gt1obu19AjzZPsVdizQdM-t0C1Z27k2WhgxHzI/?imgmax=800&quot; width=&quot;600&quot; height=&quot;334&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;7. Package Project 的 Game Main 模組, Common/General, Module Type 為Shared Library &lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1_WqltzOH6-9RPf1E2HX1yMHFTRhhB23LbLpcJJpa2z2evMgf5gtwMEIybiInxy5eB56vbCs9hUGaTHzy-XrKmm4HxUsEZMTfnM_CkXVUmnPAAv_WoZ-l_A-cvtDug_zNrhJ9w1rX01Ax/s1600-h/image%25255B47%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9m7yRyVrxo-BbQ16yaMvNbiu4rpwZE-1n54ZKiNJ6eL-Hsg5AQdEGFhe4PHEsQmegBsgm6TvqQhNrHNHit-_soeCau5AolMsELkx1fN95AdAkMF7OGr66pjZb4JX2qNPYQ4kBK3G3Xmpg/?imgmax=800&quot; width=&quot;597&quot; height=&quot;338&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Common/Compiler, Include Path 設定需要的路徑&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmCwYKi7zaajxtr-ilg2-_qYB8BPcHSwSiPSU11j0a-xHU-cWyu9anXLOsvoyHSB4_iiSpfju7OE6lp1nNdrJ2-Rw4UsDlPBxqb0a2wUtgDhE8UrnI6qqCswGQzZ1IcnCp0bwpyP-2bdvl/s1600-h/image%25255B51%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0xR78hlog3mH9tE0SeCny6H1Gz823dagKMqEFVUt7PiIuPXfJSLCiLW7HIf1hRxFAQeJph2RDL35QjG8B90yPywAfi_VOUl31GudjdoLLHvzd7hj0tfSVnAoZ4CrZLrgKRl-hmoJHXwz-/?imgmax=800&quot; width=&quot;595&quot; height=&quot;332&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;Common/Linker, Linked Static Library = libcocos2d libjpeg libpng libtiff libxml2, Linker Flags = -lGLESv2 -llog -lz -lEGL, Exported Linker Flags = -lGLESv2 -llog -lz -lEGL&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-qn5jguB70K37Waa0nQuEU7WMw5SPsKY2D_WRI5ajiI8Yz4QsRNNzmmzRbWEjeNjH5nBMbeHC15MlTmPUKyjFeDgMpArqrO0-tREJVGKQanqKlkAxF9Vq0hyphenhyphendCisiZZHMaTB6HpPBWRiJ/s1600-h/image%25255B55%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSObQVW_blfVpaK0cXN1zskKE-ZQgoZU3NsK2-Tv1M3n-E4NHG9WNK21gZrukUkXbl23LSZ_UbL_GekQAMpIMD64lPeIe2XrQXxU_tdosfSR6tR3FXCWAf_G2PVuoTZKOJgs0FjA17-ee/?imgmax=800&quot; width=&quot;593&quot; height=&quot;335&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;其他的可以不用改變&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;8. 在 Package Project 內 Add new project item, 選擇 External Static library, Item name = cocos2d,&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigD96VMKoJiwBHMkKIyzzWk1jd4jjV8fDedzXkQaYt1AxNLFZ3E8kynH7kcplHNvNjpvBFQKFKyqx9GulqRW42kkinNVu-0Vn4X9GDQNKdoAMfAL7Hn2rDI6ANGCfXdJpMFdrxdO6VM9gp/s1600-h/image%25255B59%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwEVYBdnDyCnKpDoe1Qh0lfBdzEQTxzQ2nM9bUbXc_i9X6JVNnQbwGjnuug4k2Mff6W_PfY84vaj4TTQsOxo1sk6uvU8ggfkPURiEVQ1DtYABqMyYak8l3JwxP2QjYbcvRlAD9ISloBMUx/?imgmax=800&quot; width=&quot;533&quot; height=&quot;145&quot; /&gt;&lt;/a&gt;     &lt;br /&gt;設定模組的 Property, Common/General, Module type = External static library, External module path = ../obj/local/$(TARGET_ARCH_ABI)/libcocos2d.a (Like this)&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMx9E5HzAy0PQvQ4kYbyMtbGS8RNGpLhUqUEiL4XLWLqQlp8XrWyx9NPPW1s_4-MnyERWW3jyhSQCmokebbN9AA79cLZkLU1Xu7PvvW8N2xXfcCvRBDhqP8VJ4I0Rufc5bMWLnTjnMUAFk/s1600-h/image%25255B63%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 3px 5px; border-left: 0px; display: inline; padding-right: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYQ9Bw6vKP4R7YHNwzLikRkiQ_Kr-5cJJYPoQt91_I6TGSaQ2AhEso5XhOU-Z0ZV0VHRY33QrmvDQOK9HVKVhnT5ovY1h3YWihJ-8FJxNo9IHL9FTQ1YFLiTcsoUhOc4fSUl9clEgOEcbt/?imgmax=800&quot; width=&quot;600&quot; height=&quot;339&quot; /&gt;&lt;/a&gt;    &lt;br /&gt;其他可以不須改變    &lt;br /&gt;同樣方式，import jpeg, png, tiff, webp 模組，使用在 third-party 目錄內的 .a&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;9. 把 cocos2dx\platform\android\jni 目錄裡的 .cpp，讓 GameMain 模組編譯，不要讓 cocos2d project 編譯。 cocos2dx\platform\android\src 裡的 org/cocos2dx/lib 裡的 java 檔，加入到 Package Project 的 src 目錄下。&lt;/p&gt;  &lt;p&gt;10. Sample 程式碼的 main.cpp, Classes 內的.cpp, .h, 複製進來，建在jni目錄內。Sample src 目錄內的 java 檔，複製進來。在 android package project 內建立 assets 目錄，把 Resources 內的檔案，放在目錄內。&lt;/p&gt;  &lt;p&gt;11. Solution 可以設定 Project Dependency, 然後 Build Solution。&lt;/p&gt;  &lt;p&gt;12. Done!!&lt;/p&gt;  &lt;p&gt;13. 如果使用 CocosDenshion, 類似 Cocos2d的方式加入 Solution。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2013/07/android-ndk-cocos2d-x-wingdb-mobile.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoA3IGFT1DDPHsxSsVowSqjy728XMza6fxhRcHEfAe2fYj1XLvSio_cmrfg-M5V6WDJS0Rhyab2jVVX2Ct4Pb4SNvFKz-Qajqz64rEmu2WlNidtjPss8mkIQwzNiii7zyj-Z49cekwgz5b/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-1161061568453606209</guid><pubDate>Tue, 28 Aug 2012 05:37:00 +0000</pubDate><atom:updated>2012-08-28T13:37:32.438+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>第一支 Android App 上架，從無到有的全記錄 (4)</title><description>&lt;p&gt;一個跟地圖有關的 App, 沒有地圖上的標記也是很奇怪的。所以，接下來我們要在地圖上加兩種標記。&lt;/p&gt;  &lt;p&gt;首先我們要加上 Google Map API 提供的 MyLocationOverlay。&lt;/p&gt;  &lt;p&gt;在 Main Activity 中宣告一個變數&lt;/p&gt; &lt;code&gt;   &lt;p&gt;private MyLocationOverlay m_MyLocationOverlay;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;在 onCreate 函式裡，產生這個 Overlay，並且加入到 Map View 中。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;m_MyLocationOverlay = new MyLocationOverlay(this, m_MapView);      &lt;br /&gt;m_MapView.getOverlays().add(m_MyLocationOverlay);&lt;/p&gt;    &lt;p&gt;/*m_MyLocationOverlay.runOnFirstFix(new Runnable() {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void run() {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapView.getController().animateTo(m_MyLocationOverlay.getMyLocation());       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;});*/&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;有一段程式碼註解起來了，這段程式碼的用意在，當我們取得 Location 後，把 Map View 上的地圖，搬移到我們所在的位置上。但是因為我們在 GeoUpdateListener 中也有相同的功能，所以，這段程式碼其實可有可無。&lt;/p&gt;  &lt;p&gt;接著，在 Main Activity 上，我們覆寫兩個函式。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;@Override      &lt;br /&gt;protected void onResume() {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; super.onResume();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; m_MyLocationOverlay.enableMyLocation();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; m_MyLocationOverlay.enableCompass();       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;@Override      &lt;br /&gt;protected void onPause() {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; super.onPause();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; m_MyLocationOverlay.disableMyLocation();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; m_MyLocationOverlay.disableCompass();       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;現在可以 Build 來測試看看。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzzTlttLtHtdEUbW4mQHREp8esAJHHcSfgsx4ztT8e0eDsJeJyxjxB2BF7OyDQstLRa_ytEs13_box8VT61pFvHKnnMHdPIk0BOL4S50oKeSt6DUIePrFk1EN5NlzIijDsYhHf9m14KvpY/s1600-h/device-2012-08-28-112023%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;device-2012-08-28-112023&quot; border=&quot;0&quot; alt=&quot;device-2012-08-28-112023&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK5psMk0YYT6A5rjfhM3iGZpzpZqBz2T94X3v0sQP4sRE-gy1cdkfh_KXyB_VHyRNoWCu4iZOHqBXg3ZA6KHeO0B-38-lWotJ5zIx47APMX0SKhFkllAKddCajGGHTAAeIE4iyYx8v1vZW/?imgmax=800&quot; width=&quot;299&quot; height=&quot;495&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;如果用模擬器來跑的話，記得從模擬器上送出位置。&lt;/p&gt;  &lt;p&gt;接下來，我們要來加上我們自己的標記。&lt;/p&gt;  &lt;p&gt;首先，我抓了一個免費的藍色圖釘圖示。&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvo82kKdI5AkF3rWLgdCKp8wEmAEDNog5sgZ3BgU_yjX4_FfgyIS4RStkR0Z7OwTZgPJz6CDNIUE1_RX8EP2UrkcciV6srb5TKu7qDJj-vwgFY8htqcIpqdgSwFU5upUB3BgRoy7Wm5jy-/s1600-h/pin_blue%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;pin_blue&quot; border=&quot;0&quot; alt=&quot;pin_blue&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghUxOElfECRvnZp-0eKNnQCyyWYEdB7Sqb42TvQfucPY_ChIRZMW7839pHXi5MxWnB4mJCopCaB2D50aVsr-u6jreLE_Sg6OK5uE9iSFRVFOPxgJPR81ah0i9ZFlkymtieaJxgyWr07158/?imgmax=800&quot; width=&quot;38&quot; height=&quot;38&quot; /&gt;&lt;/a&gt;加到 Android 專案的 resource 裡，名稱叫做 pin_blue。&lt;/p&gt;  &lt;p&gt;然後，我們從 Map API 中的 ItemizedOverlay 抽象介面，實做一個叫做 PriLocOverlays 的類別。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class PriLocOverlays extends ItemizedOverlay&amp;lt;OverlayItem&amp;gt;      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private static int MAXNUM = 50;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private OverlayItem m_Overlays[] = new OverlayItem[MAXNUM];       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private int m_nCount = 0;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public PriLocOverlays(Drawable defaultMarker) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; super(boundCenterBottom(defaultMarker));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated constructor stub       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; @Override      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; protected OverlayItem createItem(int i) {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return m_Overlays[i];       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; @Override      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public int size() {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return m_nCount;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public void addOverlay(OverlayItem overlay)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (m_nCount &amp;lt; MAXNUM)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_Overlays[m_nCount] = overlay;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_nCount++;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; setLastFocusedIndex(-1);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; populate();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;}      &lt;br /&gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;OverlayItem 的陣列，我們必須要自己管理。我很簡單的只是用個固定陣列來放。然後再加個記數的變數。&lt;/p&gt;  &lt;p&gt;createItem 以及 size 兩個函式是我們要實做的，就簡單的傳回陣列裡的物件跟數量就好了。要注意的是，這個 createItem 函式，並不真的需要去產生一個 Item，每次 Map View 需要更新 Overlay 時，都會呼叫這個函式。&lt;/p&gt;  &lt;p&gt;在我們自己的 addOverlayItem 內，我們需要呼叫 populate 函式，通知 Map View 來更新這個 Overlay。並且，最好是在呼叫 populate 之前，呼叫 setLastFocusedIndex(-1)，清掉之前的 Focus Item，否則咧，會因為找不到之前的 Focus Item 而讓 App Crash 的。( 我實際接到過這個問題的 Bug 回報，還好已經有神人找到問題解答了... )&lt;/p&gt;  &lt;p&gt;接著，改 Main Activity，加入 PriLocOverlays 的變數，並且在 onCreate 中建立它。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;Drawable drawable = this.getResources().getDrawable(R.drawable.pin_blue);      &lt;br /&gt;m_PrivateLocOverlay = new PriLocOverlays(drawable);       &lt;br /&gt;m_MapView.getOverlays().add(m_PrivateLocOverlay);&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;我們還需要有一個把目前位置建立成 OverlayItem 加入到 PrivateLocOverlay 裡的功能。就做在 Option Menu 裡吧...&lt;/p&gt;  &lt;p&gt;在 Main Activity 加入函式。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;@Override      &lt;br /&gt;public boolean onOptionsItemSelected(MenuItem item) {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (item.getItemId() == R.id.menu_settings)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; OverlayItem overlay = new OverlayItem(m_MyLocationOverlay.getMyLocation(), &amp;quot;Test Loc&amp;quot;, &amp;quot;&amp;quot;);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_PrivateLocOverlay.addOverlay(overlay);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //requestAddCurrentLocation();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return true;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return super.onOptionsItemSelected(item);       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;於是乎，程式跑起來就像這樣。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgrOROgU-g7xBbtdj9KT94J8UcLO_n0R-3XLGl86JeBX8FsbM-zsBPn2eHY0P6txQnyt15J4VLsZTQGCqX-3pmDOpQu8QGDb9VoZsNSooICecOtJpxDAfH4soe4A2tFpSJMYKTMzYWDn4D/s1600-h/device-2012-08-28-131318%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;device-2012-08-28-131318&quot; border=&quot;0&quot; alt=&quot;device-2012-08-28-131318&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr27wJ06wl1f46SnU9qXf8e3hZRUt6sBE01PbES3WE-ayZFAHJfssalz2U7HD7MgdpanRE7eb0HEu5FJQ_4CYwTwp9LS3ws4CO6uXy_W0k7rSUi1KRf88mhGPjJ56pcaDU5xcdhBE2bui_/?imgmax=800&quot; width=&quot;267&quot; height=&quot;443&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;呃...&lt;/p&gt;  &lt;p&gt;本來想，就先寫到這樣吧，後來又覺得該寫下這個...&lt;/p&gt;  &lt;p&gt;我們在 PriLocOverlays 類別裡，可以覆寫 onTap ( int index ) 這個函式。&lt;/p&gt;  &lt;p&gt;當地圖上的標記被點選到的時候，onTap 函式會被呼叫。這時候，我們可以用 index 取出 OverlayItem，進行處理。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;@Override      &lt;br /&gt;protected boolean onTap(int index)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; OverlayItem overlayItem = m_Overlays[index];       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Toast.makeText(m_Activity, overlayItem.getTitle(), Toast.LENGTH_LONG).show();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return super.onTap(index);       &lt;br /&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;我沒多做什麼，就是用 Toast 顯示了一下。&lt;/p&gt;  &lt;p&gt;結果就類似這樣。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5IunhCTer0kslfNSZy69okJ29C_w80IP-LxMTt0sLhccw3DP8Bk3Swk7Mx-rhqgDDlRr3VQHJs1h6EgkgOpd5knwP_JfTLDU0e-jnAJ9A6xunULriUqeHsJ1RR6A2c0z5gI2qeifuwVVh/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxZLIXD5AxjuIruhAkNOniznd0hTjQmPdxq8pV-W2MDnnV1UMUIDpSzdJZGa2Kf5A-Hat5aSbzq_LJtWbBUPE1hdCQ0Qm94mhfjHS-AbhgBsO8CBsBY3y_ixOR93Xm8-44_4BO-A956Xif/?imgmax=800&quot; width=&quot;284&quot; height=&quot;467&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/08/android-app-4.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK5psMk0YYT6A5rjfhM3iGZpzpZqBz2T94X3v0sQP4sRE-gy1cdkfh_KXyB_VHyRNoWCu4iZOHqBXg3ZA6KHeO0B-38-lWotJ5zIx47APMX0SKhFkllAKddCajGGHTAAeIE4iyYx8v1vZW/s72-c?imgmax=800" height="72" width="72"/><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-7716283010936767136</guid><pubDate>Mon, 20 Aug 2012 05:50:00 +0000</pubDate><atom:updated>2012-08-20T13:52:27.009+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>第一支 Android App 上架，從無到有的全記錄 (3)</title><description>&lt;p&gt;先再幫自己工商服務一下...&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.lancelot.privatelocationdatabase&quot;&gt;https://play.google.com/store/apps/details?id=com.lancelot.privatelocationdatabase&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;接著前兩篇的內容。&lt;/p&gt;  &lt;p&gt;可以載入地圖之後，下一個要做的事，就是抓到我們的位置，還有，把地圖移到我們所在的位置上。&lt;/p&gt;  &lt;p&gt;我們需要的是 LocationManager, LocationListener, 還有 MapController。&lt;/p&gt;  &lt;p&gt;LocationManager 的作用是定位我們現在的位置，然後再將定位的結果傳喚給 LocationListener。不過呢，LocationListener 是一個抽象類別，需要我們自己去繼承實做，主要要實做 onLocationChanged 這個函式。&lt;/p&gt;  &lt;p&gt;所以，我們先建立一個 GeoUpdateListener 類別。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;public class GeoUpdateListener implements LocationListener {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; MapController m_MapController;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; GeoPoint m_geoCurrentLoc;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; MainActivity m_Activity;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public GeoUpdateListener(MainActivity activity, MapController map_controller)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapController = map_controller;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_Activity = activity;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void onLocationChanged(Location location) {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int lat = (int) (location.getLatitude() * 1E6);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int lng = (int) (location.getLongitude() * 1E6);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_geoCurrentLoc = new GeoPoint(lat, lng);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapController.animateTo(m_geoCurrentLoc);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public void onProviderDisabled(String provider) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public void onProviderEnabled(String provider) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public void onStatusChanged(String provider, int status, Bundle extras) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO Auto-generated method stub&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;}      &lt;br /&gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;onLocationChanged 的程式碼很簡單，就是把取得來的位置，經緯度轉換成 MapController 能用的整數格式，生成 GeoPoint 物件後，交給 MapController，MapController 就會把地圖移動到我們指定的位置上。&lt;/p&gt;  &lt;p&gt;接著改 Main Activity。&lt;/p&gt;  &lt;p&gt;加入幾個 Private 變數。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;private MapController m_MapController;      &lt;br /&gt;private MapView m_MapView;       &lt;br /&gt;private LocationManager m_LocationManager;       &lt;br /&gt;private GeoUpdateListener m_GeoUpdateListener;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;在 Main Activity 的 onCreate函式裡，加入 Location Manager, Geo Update Listener, 取得 Map View, Map Controller。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapView = (MapView)findViewById(R.id.mapview);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapView.setBuiltInZoomControls(true);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //m_MapView.setSatellite(true);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapController = m_MapView.getController();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_MapController.setZoom(14); // Zoom 1 is world view       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_GeoUpdateListener = new GeoUpdateListener(this, m_MapController);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_LocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_LocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0, m_GeoUpdateListener);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // also need 3G GPS       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_LocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0, m_GeoUpdateListener);       &lt;br /&gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;那，從 Code看。&lt;/p&gt;  &lt;p&gt;Location Manager 要從 System Service 中取得。&lt;/p&gt;  &lt;p&gt;位置的提供者，有兩種，從 GPS 來，以及從手機基地台定位而來。我們可以兩種都用。所以在 requestLocationUpdates 函式裡，會有兩種參數 GPS_PROVIDER &amp;amp; NETWORK_PROVIDER。&lt;/p&gt;  &lt;p&gt;同時，我們也告訴Location Manager，位置更新的時候，請呼喚 GeoUpdateListener。&lt;/p&gt;  &lt;p&gt;程式就改到這邊。&lt;/p&gt;  &lt;p&gt;還有一個地方要更動一下。在 AndroidManifest.xml 裡，要加入兩個 Permission。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_FINE_LOCATION&amp;quot;/&amp;gt;      &lt;br /&gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot;/&amp;gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;現在我們可以做測試了。&lt;/p&gt;  &lt;p&gt;不過這次，我們想用模擬器來玩。&lt;/p&gt;  &lt;p&gt;因為，這個 App 的 Build Target 是 Google API，所以，我們必須要建立一個 Google API 的 模擬器。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA3HvrlvV_IVE1BQ31i8snuwx1Mji4JSJEUPOKI1JGdKGkQB_xQDaQEjNFTUEegokSoj6SNLHY6Q-hfqpnWdMcjN5d44rljcSO2dwupXxktyUBtIc-nRIbWEPW-kDrbdXDHjh3DPXMgilu/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqtv_cark5m-5TScCXg2ttgN2FsGvwR_jS-MZ2qOg9iGfz0vxaj8hwH0Kkide2jiLhg3wZIi5E7fElwxmsTmpYG0XQxiWSZE_vw0vaCe03pazY82mIIgAH2lxuN4gWDO7zKUIE4p2GiAMl/?imgmax=800&quot; width=&quot;354&quot; height=&quot;446&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;開啟模擬器之後，跑起 App。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiev50NJZluLjxUZnLjL08yt9M0jWXM0spcfIUkFdEGv0mrVmbzgMs4w0guzCEhybS7zkanIoQ-tA8uB8uT2Pvl_jPbKhc7b0_tk-_Snn91Qwrnp_QBWzPgklqBWkCVkkJ6a20QNHsgHG5o/s1600-h/image%25255B21%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHslF_-rflgDfvPT76LsdNgx905sDFkcz5hqjN6T4a-t4c72lZT6LWLA16rRFQQc9pK1ARoiiPuhg5nxvdIvlLWAlPeaOg88cN99r3KGaQWkNYDS0gKjZR_7CAoBfcIdjvxnT9EuaOgAAW/?imgmax=800&quot; width=&quot;419&quot; height=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;但是這樣的東西好像沒有定位的功能呢，怎麼辦?&lt;/p&gt;  &lt;p&gt;把 Eclipse IDE 上的 DDMS 打開，有個 Emulator Control 的分頁，可以找到 Location Control 的功能。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMLYoMWcJ6aaLZo9eADUFNfntRmm4PhnMVHZP9ljEuRyFwXjgGZp2EIdx48UIVzsrIprS6rr1-R_gaaPNc08joVV6NouNIQ6RcqjZrsFhUo3oymu7NDoBqTJCz1jV6cIZMZOR4Cy4tdeRk/s1600-h/image%25255B15%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFVx6qrZYMoUAYK19Ymm0HXSBl7Iwd0MwpLPx9X5a9dD61P-w6eXcynutLJUuzimiBIqupo1vP0aFwKT_bDdAyahbltxoMq-SPYpOZMu6Y4C95KcSasUWgtK8ZgStNuBN86EQaSnkXotSj/?imgmax=800&quot; width=&quot;599&quot; height=&quot;371&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;我們試試看，把 Longitude 改成 –122.08, Latitude 改成 37.42, &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAiS6SmW3QAEqzOAkYoTYY9CT0MFFnsIwQVvS5CnRKK5NBytLeNfzUpQJe7g9tLtomxNMmvqBtlH6KpEGc1zZOVtQf1XqhuP8CBzZS9X6Wyf5VIKtpB96P4uoMAzcQL9Q-nYZARIxFR9CK/s1600-h/image%25255B20%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPr-0-y7eQY2ICb3gRybQHtltVpjj18c1LUyneRMyL_Zby5xj8LFgp_-llsdoyvZkYDOGOT1YICqmrj97cqwhZp2PUJthXRmmAK-2lHp9-VTSKhzWmRB-jXm6Nvwt8x8WPaOwKjVUctjcZ/?imgmax=800&quot; width=&quot;405&quot; height=&quot;378&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;地圖就改到別的地方啦!!&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/08/android-app-3.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqtv_cark5m-5TScCXg2ttgN2FsGvwR_jS-MZ2qOg9iGfz0vxaj8hwH0Kkide2jiLhg3wZIi5E7fElwxmsTmpYG0XQxiWSZE_vw0vaCe03pazY82mIIgAH2lxuN4gWDO7zKUIE4p2GiAMl/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-2451052990212320718</guid><pubDate>Thu, 16 Aug 2012 02:40:00 +0000</pubDate><atom:updated>2012-08-16T10:40:07.883+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>第一支 Android App 上架，從無到有的全記錄 (2)</title><description>&lt;p&gt;這樣說吧， App 裡頭要使用 Google Map 的資料，需要 Google 的授權。所以， Google 要求開發者要登記一個 Google Map API 的金鑰。App 還在開發中的時候，先使用 Debug 版的金鑰就可。至於發佈版的金鑰，後面再說吧。&lt;/p&gt;  &lt;p&gt;取得金鑰前，先要簽署 Maps API。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://developers.google.com/android/maps-api-signup?hl=zh-TW&quot;&gt;Sign Up for the Android Maps API - Android Maps API - Google Code&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipaaeI-KnvttX_NhjKRSozdnZwmoq2UxuNNB66z3BGpd5dlFrnUOV2ytQ12Nyqb8dtvqkgSfVXT9Sq-wo8s01l-jJi_E9y_vAN-M7qS-MxQIEs43SU6zTU7KrHtnM7Y7wLf_4RkS6asDAK/s1600-h/image%25255B5%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOC3mffDGRsBee3GgQ6k4pNI4y66c2wXxPaiQLpD9QynDe75l98xM8ZscCaPV8XcqfJZAADpU42dLGEuxS36fLijmsNFtCT2zCuABlyqC-qUU5hzh_PHPX27fk3BqT93qSve2S0FBVaAl/?imgmax=800&quot; width=&quot;431&quot; height=&quot;454&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;打勾，填入 MD5 Fingerprint，然後按下 &amp;quot;Generate API Key&amp;quot;。&lt;/p&gt;  &lt;p&gt;MD5 Fingerprint 哪裡來??&lt;/p&gt;  &lt;p&gt;Android SDK 附有一個名稱為 &amp;quot;debug.keystore&amp;quot; 的檔案。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Windows Vista / Windows 7: &lt;code&gt;C:\Users\&amp;lt;user&amp;gt;\.android\debug.keystore&lt;/code&gt; &lt;/li&gt;    &lt;li&gt;Windows XP: &lt;code&gt;C:\Documents and Settings\&amp;lt;user&amp;gt;\.android\debug.keystore&lt;/code&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;在這個檔案的目錄內，建立一個 bat 檔。內容寫一行&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;lt;jdk path&amp;gt;\bin\keytool -list -v -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android &amp;gt;&amp;gt; debug_map_key.txt&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;&amp;lt;jdk path&amp;gt; 是 Java SDK 的安裝目錄。&lt;/p&gt;  &lt;p&gt;執行 bat 檔以後，會將輸出內容寫到 debug_map_key.txt 檔案裡。檔案裡就可以看到這麼一段 :&lt;/p&gt; &lt;code&gt;   &lt;p&gt;別名名稱: androiddebugkey      &lt;br /&gt;建立日期: 2012/1/18       &lt;br /&gt;項目類型: PrivateKeyEntry       &lt;br /&gt;憑證鏈長度: 1       &lt;br /&gt;憑證 [1]:       &lt;br /&gt;擁有者: CN=Android Debug, O=Android, C=US       &lt;br /&gt;發出者: CN=Android Debug, O=Android, C=US       &lt;br /&gt;序號: 4f162768       &lt;br /&gt;有效期自: Wed Jan 18 09:59:04 CST 2012 到: Fri Jan 10 09:59:04 CST 2042       &lt;br /&gt;憑證指紋:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MD5:&amp;#160; 1F:04:CE:54:D2:57:0D:7C:11:1F:5D:A1:B2:D6:E8:93       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SHA1: 4E:D1:A5:3E:68:F2:05:C8:09:9C:29:9C:A9:38:29:4C:3C:3B:A8:1A       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SHA256: C9:DA:67:77:3F:4B:94:F5:AE:47:7F:FF:A6:14:9C:B5:96:10:00:7E:99:C8:45:40:A3:64:9F:83:BA:12:56:D1       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 簽章演算法名稱: SHA1withRSA       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 版本: 3&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;那一行 MD5 就是我們要的。&lt;/p&gt;  &lt;p&gt;複製貼上到網頁上，按下 &amp;quot;Generate API Key&amp;quot;。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuE2VsUVtx4fjWFFrjiPH0UrZAyzwa2eWlOFkeq7D5o6wTYXH7v6l3T_F5v0a005SDR_qzlqWFuKA3QnNtO1DODbtHAojIzLO-7ffQNCqjtNRlNMT12qfyy7gYM3-U9dtzX_JMokaHGcFS/s1600-h/image%25255B11%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6Nx7vU-VgSmoREcBYNpHui6RWs9-XPOA5YY-kaaKbg7d7VMc67mZe-jbHVcKEPEQGAdjbqxuyfXt5gr_XXVSIV6MSCU0E1lPWZxGgT2y6r1FU6nO35KrFabxwvgG6eROyrcBl7XrLhmuV/?imgmax=800&quot; width=&quot;602&quot; height=&quot;275&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;到此，我們就取得金鑰了。&lt;/p&gt;  &lt;p&gt;回到 Eclipse IDE 的程式碼。&lt;/p&gt;  &lt;p&gt;在 main activity 的 layout xml 檔案裡，把 android:apiKey 那一段，&amp;quot;your key&amp;quot; 改為我們取得的金鑰。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;com.google.android.maps.MapView xmlns:android=&amp;quot;&lt;a href=&quot;http://schemas.android.com/apk/res/android&amp;quot;&quot;&gt;http://schemas.android.com/apk/res/android&amp;quot;&lt;/a&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:id=&amp;quot;@+id/mapview&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:layout_width=&amp;quot;match_parent&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:layout_height=&amp;quot;match_parent&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:apiKey=&amp;quot;0vn4fYcAmXsjC902Q8puaWZLabVkY0t5jqjRzSw&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:clickable=&amp;quot;true&amp;quot; /&amp;gt;       &lt;br /&gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;再來，因為我們需要透過 Internet 下載地圖資料，所以，要在 AndroidMenifest.xml 裡加入 Internet 的 Permission。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;現在 Build 執行看看吧...&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtHR6FVEsJAdS_2T_CsFBsC9V6R9LxNC2FSYaueaHevnsyr6oSehM_GXuljio8kYr3dYx-qiGRMWAy7ZtB8-RwfFJd-qyfm-_LeNVlS9OImhA_X9zgG9PcYEpjaV73b-uUsc8X-Tt5SQfO/s1600-h/2012-08-16_10-25-01%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;2012-08-16_10-25-01&quot; border=&quot;0&quot; alt=&quot;2012-08-16_10-25-01&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKYMxw2MhpYHT525bpJE1gueF-m5tRIyGuKv1Pdq8T8KlnbyexjXyGwtIjpJLwbluzUo7suEWIbadTIUxGXAkUyIXdmxViRmY3tMX9NYHdfO6ikRvlXv1o9XYIwzGK6SlQNmtlS1kxqsL8/?imgmax=800&quot; width=&quot;219&quot; height=&quot;386&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;看到地圖囉!!!&lt;/p&gt;  &lt;p&gt;可是看不到街道、看不到自己的位置...&lt;/p&gt;  &lt;p&gt;那是後續的工作...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/08/android-app-2.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOC3mffDGRsBee3GgQ6k4pNI4y66c2wXxPaiQLpD9QynDe75l98xM8ZscCaPV8XcqfJZAADpU42dLGEuxS36fLijmsNFtCT2zCuABlyqC-qUU5hzh_PHPX27fk3BqT93qSve2S0FBVaAl/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-3092830403774557270</guid><pubDate>Wed, 15 Aug 2012 11:15:00 +0000</pubDate><atom:updated>2012-08-15T19:15:46.933+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>第一支 Android App 上架，從無到有的全記錄 (1)</title><description>&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQD1m2nKiAaogY4KIskkuBNR2O68jQbqoRKWB5RVu6s2dO_HEdN6x1GkOHUfCGQjmtmzPPll_PE3v1Z3SrF2VLqwVjKcm76oXZCRGtaafl-2lv_ser8lFlrpFhHFeFF9oMwW828VtuDsHl/s1600-h/screen_1%25255B3%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;screen_1&quot; border=&quot;0&quot; alt=&quot;screen_1&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEeOfiTizkA-T2g_6Hozjz8q8ROAVNti9TZU1uoI9lZC7N-IDRITyrXJVNP2T9wa_yYvDVlb2tkpRzWvq3YqIobjdtfIlyk0TE-C-DPI_S4PwfwGE1xJlZD74N0LsCoB687QYHNR8qhj4a/?imgmax=800&quot; width=&quot;188&quot; height=&quot;310&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkrn8ABUc0j1cfAXq5mw0jiGXERj56oM-XIS7YQbGouyElumGofuY80s4fIPVkuuRi56lcuDqUwD445w0c3-PTdvhYKXgQgvl76jUIqYKDJUtgQqTEwl3wExbWMGBZ2e6_tEhyyMGjscJa/s1600-h/screen_2%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;screen_2&quot; border=&quot;0&quot; alt=&quot;screen_2&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi25RtKWhXVhO7B_W7J-NFzhO7P0PaoI_DVyImBKrFdLZfhb1UhitMSoOp5NV6u-DIIDCrwrnxQIvxEvs_Oydid3O0Ka42rXyFiY7IcdEWbvLqwiSNczEGz6-PJXyBIQy0YBeQl4-g016kV/?imgmax=800&quot; width=&quot;188&quot; height=&quot;307&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;這支 App 用到三個程式模組，Google 地圖、資料庫、還有廣告。&lt;/p&gt;  &lt;p&gt;App 所要達到的功能，很簡單 : &lt;/p&gt;  &lt;p&gt;當出遊或是閒晃時，走到某個值得記錄的地點，可以將它標記起來。未來再度行經附近的時候，地圖上就會標示出來。&lt;/p&gt;  &lt;p&gt;花了一陣子的業餘時間，前幾天丟到架上了。( 歡迎下載 )&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.lancelot.privatelocationdatabase&quot;&gt;https://play.google.com/store/apps/details?id=com.lancelot.privatelocationdatabase&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;好，先從 Google Map 開始。&lt;/p&gt;  &lt;p&gt;要用 Google Map 功能，先需要 Google Map 的 API。&lt;/p&gt;  &lt;p&gt;Android 雖然跟 Google 關係匪淺，但是， Android SDK 本身是不含有 Google Map 相關功能的，所以，必須要透過 Android SDK Manager 工具，下載 Google APIs。這一大包裡頭，就有 Google Map 相關的類別。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG7tEsvUIB1oZAuXorNaG1br-N6YGQu6Y-zrz5viU-XHpIrEXjH3XyXEwQN7ZqVUBIlOVVRSLGIqYVqaT1T2qbEBltaIxA7_-RvHbHpgNfIGZI1oK7oK_pypSyWoym5cAPppryE-unJXsw/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcZLdiULi5enNfCqll_sL8cHvHRy8meHGZImt-uQywer0spiIhaEf3q_objG-xLTsGyP0d-3BTI2y_0BVadsoSb3M4U8pCNiCWiGS6WCuF91nrotP2Y7w648DFA8KC8GZ13uQYD0-E84xh/?imgmax=800&quot; width=&quot;564&quot; height=&quot;403&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;接著，可以從 Eclipse IDE 建立 Android Application 專案。專案的 Build Target 要改用 Google APIs。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIPu3oUf3KSbqATDUOCZ9SsRrYWmm5ObNTWPsQO9Lmvn_CuzbdtkjXNgT15fAPLTS353t5Wm5WBhl3RSDsmolbw3s75Iy1Z8L6ckYhy8oQG_4UJ2JCaBW2BecVGE_bG9jR6EQ3kUmOjSw4/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAaOtJU1ElRVi7npxPmYnF3CZc3BhMd6LR3JJZ1yeX8ZfnWiCgMxqfa_gJqUvOJ6sKtwi3rncLLfA2sHFmTGuWUdgSE9PwyjRaz1f9XrvpRkypQy0CQPj1YsoJf9PSVICLUbkloFmMYzvw/?imgmax=800&quot; width=&quot;557&quot; height=&quot;343&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;然後應該就可以生出個預設的 Hello World 程式了。&lt;/p&gt;  &lt;p&gt;接著先在 AndroidManifest.xml 檔案中，加入 Use Library 到 Application裡。我們要使用的是 com.google.android.maps 這個 package。&lt;/p&gt;  &lt;p&gt;&lt;code&gt;&amp;lt;uses-library android:name=&amp;quot;com.google.android.maps&amp;quot;/&amp;gt; &lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqmHGRX0C0Tyvc3ipuXMTwVm_EQhZhIdyzBwYghA8hJB-ekLiYQmk_WWZtnkWXgIpgr4VuESdWL8Im2hyOR5WSTECpLDCb1NhcO87ZFn50cfs5o7nVc-1lEbL8VTOcJ2-HdBpxBu-Nrnmj/s1600-h/image%25255B12%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbARCZUkDmb4vw3ZDc61VPPmXNU-G6R2gvOC94tQAU1QpN0nhxaTQYn5vsv8fBm8CBWX_NLDhV5TwVleuNJalagKbTUGw3fTm4ZHX1OfO34G3-G9AN-8whADftdZZfDgfMrJOaoMaV1gqt/?imgmax=800&quot; width=&quot;597&quot; height=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;然後在主畫面的 layout xml 檔案裡，加入 Map View 元件。&lt;/p&gt;  &lt;p&gt;&lt;code&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;com.google.android.maps.MapView xmlns:android=&amp;quot;&lt;a href=&quot;http://schemas.android.com/apk/res/android&amp;quot;&quot;&gt;http://schemas.android.com/apk/res/android&amp;quot;&lt;/a&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:id=&amp;quot;@+id/mapview&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:layout_width=&amp;quot;match_parent&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:layout_height=&amp;quot;match_parent&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:apiKey=&amp;quot;your_key&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; android:clickable=&amp;quot;true&amp;quot; /&amp;gt;       &lt;br /&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;最後，把主要 Activity 改為從 MapActivity 繼承。&lt;/p&gt; &lt;code&gt;   &lt;p&gt;import com.google.android.maps.MapActivity;&lt;/p&gt;    &lt;p&gt;import android.os.Bundle;      &lt;br /&gt;import android.view.Menu;&lt;/p&gt;    &lt;p&gt;public class MainActivity extends MapActivity {&lt;/p&gt;    &lt;p&gt;@Override      &lt;br /&gt;public void onCreate(Bundle savedInstanceState) {       &lt;br /&gt;super.onCreate(savedInstanceState);       &lt;br /&gt;setContentView(R.layout.activity_main);       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;@Override      &lt;br /&gt;public boolean onCreateOptionsMenu(Menu menu) {       &lt;br /&gt;getMenuInflater().inflate(R.menu.activity_main, menu);       &lt;br /&gt;return true;       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;@Override      &lt;br /&gt;protected boolean isRouteDisplayed() {       &lt;br /&gt;// TODO Auto-generated method stub       &lt;br /&gt;return false;       &lt;br /&gt;}&lt;/p&gt;    &lt;p&gt;     &lt;br /&gt;}       &lt;br /&gt;&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;好了，趕快 Build 一下，看一下成果。&lt;/p&gt;  &lt;p&gt;成果是，只看到方格線，還有一個 Google 的浮水印。其他什麼都沒有。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaLFoL4_oUeZEdKOyRRI0k7xZYH64-dsJOSUdYuRjMlxsDiNfTfQSEP-Bv-S0KXBQEHvi2hK3PCjwSCsbG8-KW-qrbJpGwxnhNShBcysae077BN5ZbVi4m6QqpKHRQnn2UEl35FrjQgK6p/s1600-h/2012-08-15_19-07-01%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;2012-08-15_19-07-01&quot; border=&quot;0&quot; alt=&quot;2012-08-15_19-07-01&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwkhf0Zt32-3eqP8rbkG2q_4sAIVRDVoGEnX0VXYz9q9OIGmjzf5iNaMyDp_na1Bnid5CuI6oqk_7DtekSRixnnIdRVMW8TYkc4WcBF2x0n0K8tFow4kZG7EcbNNXftIecnEarlIq4KvgT/?imgmax=800&quot; width=&quot;226&quot; height=&quot;398&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;因為我們還有一個很重要的 Map API Key 還沒取得。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/08/android-app-1.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEeOfiTizkA-T2g_6Hozjz8q8ROAVNti9TZU1uoI9lZC7N-IDRITyrXJVNP2T9wa_yYvDVlb2tkpRzWvq3YqIobjdtfIlyk0TE-C-DPI_S4PwfwGE1xJlZD74N0LsCoB687QYHNR8qhj4a/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-814332234525372441</guid><pubDate>Wed, 09 May 2012 10:05:00 +0000</pubDate><atom:updated>2012-07-05T14:19:49.997+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>Unity3D Plug-in for Android -- Activity 擴展方法</title><description>&lt;p&gt;Unity3D 的 Android Plug-in 還有另一種實做方法。當需要使用 Android SDK 中的 Java 物件時，利用這個方法來將 Unity3D 與 Android SDK 結合是比較好的。&lt;/p&gt;  &lt;p&gt;簡單的步驟，&lt;/p&gt;  &lt;p&gt;1. 先在 Eclipse IDE 中，新建一個 Android Project。&lt;/p&gt;  &lt;p&gt;2. 在 Project 的 Property 中，點選 Java Build Path，切到 Libraries 的分頁，按鈕 &amp;quot;Add External JARs…&amp;quot;，然後選擇 Unity 安裝目錄，找到 &amp;quot;\Editor\Data\PlaybackEngines\androidplayer\bin&amp;quot; 子目錄裡的檔案 classes.jar 來加入    &lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxKLSV4McMd9qmqdSpU_UmxgaMLsoEUKrLsIj4kUyuMfCsIjFRJdoPEPriVWeWmhyWMqmpqnnhL4rc_Lo2cPQ5hn9PCOnmmTkfM1hCmpgF6b29F4cpISVmb6FXjxi1wWrn5ijcvfZyqR38/s1600-h/clip_image002%25255B5%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image002&quot; border=&quot;0&quot; alt=&quot;clip_image002&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgePG-yRnDSlTB5GmeO2eKgnDAvfBnc5RedlYv25aoTDZ9MIOmdXCUilDWATqVPx6AX1t6XXBTUS0_iqG34BphKOcN3yI6bkeewuuAlD8VqjBq-dufQBXuS9lNLwuGxO_I2e6ib9eRiGOeA/?imgmax=800&quot; width=&quot;565&quot; height=&quot;443&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;3. 修改 Activity 的 Java Code&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Activity 改成自 UnityPlayerActivity 繼承 ( import com.unity3d.player.UnityPlayerActivity )，在 Activity 的 OnCreate 函式裡，把預先產生的 setContentView() 函式呼叫刪除掉不要使用。 &lt;/p&gt;    &lt;p&gt;一個範例程式碼如下: ( UnityPlayerExtendActivity.java )      &lt;br /&gt;這個範例裡，我們不但使用了 Toast，還用到了Android SDK 中的 藍芽 API。這兩項功能，都是Unity3D無法提供的。&lt;/p&gt; &lt;/blockquote&gt; &lt;code style=&quot;width: 570px; height: 222px&quot;&gt;   &lt;p&gt;&lt;b&gt;package&lt;/b&gt; com.activity.unityextend;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;import&lt;/b&gt; com.unity3d.player.UnityPlayerActivity;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;import&lt;/b&gt; android.os.Bundle;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;import&lt;/b&gt; android.widget.Toast;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;import&lt;/b&gt; android.bluetooth.BluetoothAdapter;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;public&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; UnityPlayerExtendActivity &lt;b&gt;extends&lt;/b&gt; UnityPlayerActivity {&lt;/p&gt;    &lt;p&gt;&lt;b&gt;private&lt;/b&gt; BluetoothAdapter mBluetoothAdapter = &lt;b&gt;null&lt;/b&gt;;&lt;/p&gt;    &lt;p&gt;/** Called when the activity is first created. */&lt;/p&gt;    &lt;p&gt;@Override&lt;/p&gt;    &lt;p&gt;&lt;b&gt;public&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; onCreate(Bundle savedInstanceState) {&lt;/p&gt;    &lt;p&gt;&lt;b&gt;super&lt;/b&gt;.onCreate(savedInstanceState);&lt;/p&gt;    &lt;p&gt;//setContentView(R.layout.main);&lt;/p&gt;    &lt;p&gt;mBluetoothAdapter = BluetoothAdapter.&lt;i&gt;getDefaultAdapter&lt;/i&gt;(); &lt;/p&gt;    &lt;p&gt;&lt;b&gt;if&lt;/b&gt; (mBluetoothAdapter == &lt;b&gt;null&lt;/b&gt;) {&lt;/p&gt;    &lt;p&gt;Toast.&lt;i&gt;makeText&lt;/i&gt;(&lt;b&gt;this&lt;/b&gt;, &lt;/p&gt;    &lt;p&gt;&amp;quot;Bluetooth is not available.&amp;quot;, &lt;/p&gt;    &lt;p&gt;Toast.&lt;i&gt;LENGTH_LONG&lt;/i&gt;).show();&lt;/p&gt;    &lt;p&gt;finish();&lt;/p&gt;    &lt;p&gt;&lt;b&gt;return&lt;/b&gt;;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;&lt;b&gt;if&lt;/b&gt; (!mBluetoothAdapter.isEnabled()) {&lt;/p&gt;    &lt;p&gt;Toast.&lt;i&gt;makeText&lt;/i&gt;(&lt;b&gt;this&lt;/b&gt;, &lt;/p&gt;    &lt;p&gt;&amp;quot;Please check your BT settings.&amp;quot;, // and re-run this program &lt;/p&gt;    &lt;p&gt;Toast.&lt;i&gt;LENGTH_LONG&lt;/i&gt;).show();&lt;/p&gt;    &lt;p&gt;//finish();&lt;/p&gt;    &lt;p&gt;//return;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;另外呢，AndroidManifest.xml 這個檔案，需要調整一下。因為我們用到了藍芽功能，所以要開啟應用程式的藍芽權限。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1092wO66oQoFjj3h9OhMpF-helAeBblD62aTAtsjPNOF4_WGqqKZb93giuizYsQr8z5bfdJ2gPU5LkFhTBviMQL7XuY0QZh9qiKlwhyphenhyphencaqGeO9a-3mtDuy15XJ-6nahXpkqRahNmhkG9r/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5EpE1VAPDFEwfIhPin3ktgYpMBQFF_EXmogBzjhFo2y-ExDsCqECUdnieWzXfshDWL08FBYB8-qs2h2MfbLikdh0nhBR4Qj6KK43z3yfAB9eU13EzIilqkk3bDzJ8mi4xGqmHoGCJL1YY/?imgmax=800&quot; width=&quot;544&quot; height=&quot;212&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;4. 接著從 Eclipse IDE Export 出 jar 檔案。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2bI-xmB0n0HipqTsi2oR6YNNO36800je4xXt0UoQLnmKE7D8hyphenhyphenCZN_-hu8rWSWuzsjK8HUosKxl_eSw9AjGxiYcCLX4Zpfc6RI0OuUdXLcLHOqYmgHPMKBN1StV0ynQorCRIb7Vk-eJdi/s1600-h/clip_image002%25255B6%25255D%25255B5%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image002[6]&quot; border=&quot;0&quot; alt=&quot;clip_image002[6]&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr98Si-zxrWtRAc03otpyja6h4N1fy8_Ipg9u7Wt_-YTlVar3vWw0CSU4eDTTUJnvrxP2YKNwcB-Ony9XwRrZlmITGcZLpYFcOWhNHmWsocrO21NGXGQzDUNUD7KwKggMxuD2OsQix4hZh/?imgmax=800&quot; width=&quot;430&quot; height=&quot;454&quot; /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi619g9JMmgksdWNYETeUl8ToZlaHSCFOe4uo40dxvQWXhXmhLNG2UmWcfCm9B5xoxAcynDHlRPxCXvK8xrmRJU4K16P3i2FHxojb-GG-XLoYsxmm17YzqZa_jid9TqtsiRaJc8DRBRFV53/s1600-h/clip_image004%25255B6%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image004&quot; border=&quot;0&quot; alt=&quot;clip_image004&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLSFVcHWCKMl8cVzvMwE7V4n6kbmaWQj0kmdOKOYQbGkYptXuf64k0mfKq2IBPmFgucYsiPfTHG-E0ehkOa4M06y2WlUCkPxbFnDS6ODWhr-GeD0gYrxQg27Z4tqqMcT3jC4r5bTi8wp75/?imgmax=800&quot; width=&quot;409&quot; height=&quot;493&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;5. 下一步，開啟 Unity3D，修改 Player Settings 設定。要注意的是， Bundle Identifier 與 Minimum API Level 要與 Eclipse 上的 Android Project 相同。&lt;/p&gt;  &lt;p&gt;6. 然後將 Eclipse 的 Android Project 檔案複製到 Unity 專案的目錄下， 這裡有幾個需要複製的檔案。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0aqE4x4oOq1_hvWtaJlpRlR3N3gmX5JXX2zxSUtaB3d2QBUfPk4M1nzdsNkCyh-dRqyuCAaXVTc3E0Y1E3LVMtdAInCeD8EiMAHkzzxatDvYm7kt3EVZO4GF88X-C_DVZeWtkeeporHu7/s1600-h/clip_image008%25255B4%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image008&quot; border=&quot;0&quot; alt=&quot;clip_image008&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjosKjhvOGNAgxEoJGMKGzITUPcJYmjXF7qEN95Gjczgl6ueiCBRZrlefZe1O9z6pmXVYku2WJDMKEPd0fZJtN_CHAUpDV5ucfJdeX7FLfSdC7b_YX7YkgNR-adJLC7Z4Fs7xfPXdZJHEsr/?imgmax=800&quot; width=&quot;360&quot; height=&quot;261&quot; /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;br /&gt;a. 在 Assets 目錄下建立 Plugins 目錄，再建立 Android 子目錄。 &lt;/p&gt;    &lt;p&gt;b. 將 Android Project 中的 AndroidManifest.xml 複製到 Plugins/Android 目錄內。&lt;/p&gt;    &lt;p&gt;c. 在 Plugins/Android 目錄內建立 bin 子目錄，將 Android Project 輸出的 jar 放進來。&lt;/p&gt;    &lt;p&gt;d. 最後將 Android Project 內的 res 子目錄複製到 Plugins/Android 目錄內&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;7. 最後，從 Unity3D Build &amp;amp; Run，就可以使用 Android SDK 提供的功能了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;(Update 2012.7.5) 加入了 AndroidManifest.xml 該修改的部分&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/05/unity3d-plug-in-for-android-activity.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgePG-yRnDSlTB5GmeO2eKgnDAvfBnc5RedlYv25aoTDZ9MIOmdXCUilDWATqVPx6AX1t6XXBTUS0_iqG34BphKOcN3yI6bkeewuuAlD8VqjBq-dufQBXuS9lNLwuGxO_I2e6ib9eRiGOeA/s72-c?imgmax=800" height="72" width="72"/><thr:total>14</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-881606727753292813</guid><pubDate>Fri, 03 Feb 2012 09:22:00 +0000</pubDate><atom:updated>2012-02-03T17:22:19.098+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>Unity 3D Plug-in for Android 開發指南</title><description>&lt;p&gt;這是一個摸索筆記。&lt;/p&gt;  &lt;p&gt;以下是正文。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;一. &lt;/b&gt;&lt;b&gt;Unity3D Plug-in &lt;/b&gt;&lt;b&gt;必須知道的概念&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Unity 的 Plug-in 是以二進位存在的，所以，在不同的平台上，必須開發不同的 Plug-in，例如，在 PC Windows 平台，使用 dll 檔，在 Android 系統，使用 .so 檔。&lt;/p&gt;  &lt;p&gt;在使用 Unity 開發專案時，因為是在 PC Windows 平台上操作，所以當使用了 Android 的 .so 檔時，會造成無法在 Unity Editor 中即時操作遊戲的問題。至於是否可以有個取代方案，例如，另外寫個相同功能的 dll 檔來在 PC Windows 平台上操作，這要再做進一步測試。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;二. &lt;/b&gt;&lt;b&gt;Unity3D Plug-in &lt;/b&gt;&lt;b&gt;的安裝&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Unity 的官方文件，是建議將 Plug-in 複製到專案的 Assets/Plugins/Android 目錄下，如果沒這個目錄，就自行建立一個。&lt;/p&gt;  &lt;p&gt;所以，就是將寫好編譯好的 .so 檔，複製到這個目錄下就可。&lt;/p&gt;  &lt;p&gt;官方文件上有一個模稜兩可的說法，說 Plug-in 安裝後，Unity 會自動抓出其中的 Java Class 什麼的，不要相信它，因為完全試不出來。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;三. &lt;/b&gt;&lt;b&gt;Unity3D Plug-in &lt;/b&gt;&lt;b&gt;的使用&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;.so 檔複製到專案以後，是無法取得任何資料的。必須透過 C# Script 來載入。 官方文件中，只提供了使用 C# Script 來參考 Plug-in 的方法，找不到 Java Script 的方法，所以就先以 C# Script來做。&lt;/p&gt;  &lt;p&gt;官方網站上有一個可以參考的範例，&amp;quot;AndroidNativePlugin.zip&amp;quot;，可以下載來參考。&lt;/p&gt;  &lt;p&gt;zip 檔解開後，將 unity package import 進 Unity Editor，可以抓到 .so 檔，原始程式碼，以及使用 Plug-in 的 C# Script。 &lt;/p&gt;  &lt;p&gt;C# Script 如下 (已經改過了)&lt;/p&gt; &lt;code style=&quot;width: 571px; height: 222px&quot;&gt;   &lt;p&gt;using UnityEngine;&lt;/p&gt;    &lt;p&gt;using System.Collections;&lt;/p&gt;    &lt;p&gt;using System.Runtime.InteropServices;&lt;/p&gt;    &lt;p&gt;public class CallNativeCode : MonoBehaviour {&lt;/p&gt;    &lt;p&gt;public GUISkin mySkin;&lt;/p&gt;    &lt;p&gt;[DllImport(&amp;quot;ttt&amp;quot;)]&lt;/p&gt;    &lt;p&gt;private static extern float add(float x, float y);&lt;/p&gt;    &lt;p&gt;void OnGUI ()&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;GUI.skin = mySkin;&lt;/p&gt;    &lt;p&gt;float x = 3;&lt;/p&gt;    &lt;p&gt;float y = 10;&lt;/p&gt;    &lt;p&gt;GUI.Label (new Rect (15, 125, 450, 100), &amp;quot;add&amp;quot; + x + &amp;quot; and &amp;quot; + y + &amp;quot; equals &amp;quot; + add(x,y));&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;幾個重點:&lt;/p&gt;  &lt;p&gt;1. [DllImport(“ttt”)] : 這行程式，是負責載入 Plug-in，依照官方規定，這個Plug-in 的檔名是 libttt.so，也就是，前綴必須有”lib” 三個字母，後面是 .so 副檔名。&lt;/p&gt;  &lt;p&gt;2. private static extern float add(float x, float y); -- 這一行是宣告Plug-in中的函式。&lt;/p&gt;  &lt;p&gt;3. 載入與宣告函式完成後，在 Script 的 OnGUI 函式中，就可以使用這個函式了。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;四. &lt;/b&gt;&lt;b&gt;Android Plug-in &lt;/b&gt;&lt;b&gt;的開發&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;接著就是，.so 這個檔怎麼做出來了。&lt;/p&gt;  &lt;p&gt;.so 檔，可以視作是 Android 系統上的 Dynamic Load Library (dll)&lt;/p&gt;  &lt;p&gt;&lt;b&gt;1. &lt;/b&gt;&lt;b&gt;建立開發環境&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;一般書籍或網站上找到的 Android 應用開發，多是以 Java 環境來做的，這是無法編譯 .so 檔案的。&lt;/p&gt;  &lt;p&gt;Android 的 Development Kit 有兩種，一種是 SDK (Software Development Kit), 一種是 NDK (Native Development Kit)，編譯 .so 檔，需要 NDK。&lt;/p&gt;  &lt;p&gt;傳統的建立開發環境的方法是，要安裝 cygwin (Windows 上的 Linux 模擬器)、NDK、SDK、Eclipse IDE 等等，現在有個神人把整個開發環境整合到了 Visual Studio 2010上，所以建立開發環境的方法，就以整合 VS 2010 來做了。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://code.google.com/p/vs-android/&quot;&gt;vs-android -- Integrated development of Android NDK C/C++ software under Visual Studio&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;下載vs-android，sample solution，然後下載 Android NDK (r7 or later)，SDK，Java SDK (32 bits版)，以及 Ant。&lt;/p&gt;  &lt;p&gt;需要安裝的安裝，可以解壓縮複製的，就解壓縮複製。( Android SDK 的安裝，比較複雜些，請找資料看看 )&lt;/p&gt;  &lt;p&gt;然後要設定幾個環境變數&lt;/p&gt;  &lt;p&gt;ANDROID_HOME : Android SDK 的根目錄位置，例如 C:\Develop\android-sdks &lt;/p&gt;  &lt;p&gt;ANDROID_NDK_ROOT : Android NDK 的根目錄位置，例如 C:\Develop\android-ndk-r7&lt;/p&gt;  &lt;p&gt;ANT_HOME : Apache Ant 的目錄，例如 C:\Develop\apache-ant-1.8.2&lt;/p&gt;  &lt;p&gt;&lt;b&gt;2. &lt;/b&gt;&lt;b&gt;測試範例程式 san-angeles&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;設定完成，打開 VS 2010，載入 Sample Solution，USB接上測試用設備，Build Solution，然後就 OK 了。&lt;/p&gt;  &lt;p&gt;&amp;lt;&amp;lt; 不過，還是會碰到編譯不過的情形啦。以下是幾個可能要處理的狀況。&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;a.      &lt;br /&gt;Unable to resolve target &#39;android-4&#39;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 因為在 SDK中的 Platform 版本裡沒有安裝 API Level 4，修改 project.properties 這個檔案中的 target=android-4，改為 SDK 有安裝的API&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;b.      &lt;br /&gt;ANTBUILD : [dx] error : Could not create the Java Virtual Machine.       &lt;br /&gt;ANTBUILD : [dx] error : A fatal exception has occurred. Program will exit.       &lt;br /&gt;[dx] Error occurred during initialization of VM       &lt;br /&gt;[dx] Could not reserve enough space for object heap       &lt;br /&gt;這問題，打開 android-sdks\platform-tools 目錄中的 dx.bat 檔案，將       &lt;br /&gt;set defaultXmx=-Xmx1024M       &lt;br /&gt;改為       &lt;br /&gt;set defaultXmx=-Xmx512M &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;gt;&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;3. &lt;/b&gt;&lt;b&gt;建立要編譯 .so 檔的專案&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;因為 vs-android 的神人作者，還沒有寫好 Project Wizard，所以，要靠半手動的方式來建立新專案。&lt;/p&gt;  &lt;p&gt;簡單一點的做法是，就在範例程式 solution 下新加入一個專案，選擇 Win32 Console App，然後建立 Empty Project。&lt;/p&gt;  &lt;p&gt;Project 的名稱，以 lib 開始，符合 Unity Plug-in 的規則。例如，libunityplug1&lt;/p&gt;  &lt;p&gt;專案建立完成，開啟專案的 Property Page，點選 Configuration Manager&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfy0THXsbspwopKVtlvj8lFw7d0ihxiQYWWClP0kqGJAD5qEIMpiQhRBq-aREhH9M8CjugOvqo1dUj5B_5mLAnUtiSlAULScj4SnWEkIY5-xoPYXr0-4JyEs-E4luEuN4ozgiVQUhFGozO/s1600-h/clip_image004%25255B5%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image004&quot; border=&quot;0&quot; alt=&quot;clip_image004&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZet1UDAkS0-9qtvjNG2N-Qabp5e63bHbO-r3MY71hKwQglXA60BZB5rY6cDvYArn8h5H82poil28h6QWBvNCDhYFADsBaLujsTqbCvRumXlO0R7g4dkKzPnXfq-ABBV5SQwrkXV3_VEM7/?imgmax=800&quot; width=&quot;574&quot; height=&quot;346&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;新建立的專案還是 Win32 Platform，點選專案的 Platform 下拉箭頭，選擇 &amp;lt;&amp;lt;New&amp;gt;&amp;gt;，建立新的專案 Platform。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeZjMPAkMUNPiTHPHKGUU2jKVzXFoZt9_DQuMdQmhWnPgGWFyC_73dYNDF0f6HWF-RE1mEV9nWzNk0wVEUvgKOWuGSqbe9ZXYYJZT6BSKslZ9fLEr0CAkNQGuf90bDpNr8Y8qELnWHR_h_/s1600-h/clip_image006%25255B4%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image006&quot; border=&quot;0&quot; alt=&quot;clip_image006&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWDMkqH8nLm-r92G2svh_8sq1FKlhC7otOiQOYYLGUPUTB_Kxpqy5uMe571oJe7cZTY-Y5fE8Dv84NV5kcASweaoccol2v5cGFvvD_Ogv87nQMMzN1bZ1IniktU4xhrT22CBsuT6XqVxic/?imgmax=800&quot; width=&quot;552&quot; height=&quot;273&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Platform 選擇 Android, Copy Setting 選擇 &amp;lt;Empty&amp;gt;，底下的 Create new solution platforms 要取消打勾。&lt;/p&gt;  &lt;p&gt;然後按下 OK&lt;/p&gt;  &lt;p&gt;新專案的 Project Platform 就會改成 Android，而專案中的 Property 也會自動調整為 Android 平台相關的設定。&lt;/p&gt;  &lt;p&gt;因為要產生的是 Dynamic Library ( .so ) 檔，所以，將 Configuration Type 調整為 Dynamic Library。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS8eCVYyELPi_ONvoOKnrxTNxRo3bBvelVhllTqTSzVtIa6n57btH0igk5GIeZkRmh_POIGd1CSamZ-NgV9p2vcw25-5Wi8jZfW1nocq8Yem0s0UuP5C5LnXbOXBHVR2LVCX-tzL1Mdd-g/s1600-h/clip_image008%25255B5%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image008&quot; border=&quot;0&quot; alt=&quot;clip_image008&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYHjvPaS6tJJvmNztq66zKlBEWYE2MCEQ7Wk5QaZRgieUbsYja8uwY-FYtV2MFyztNBQPqUfBMWZbpeXeP0u0dSrjDZAKLjsVRBObP7Le5USrfP70l5nVyluwMue-rLMOYm70l7PLo3nuk/?imgmax=800&quot; width=&quot;560&quot; height=&quot;298&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;其他的 API Level, Architecture，有需要也可以改看看。&lt;/p&gt;  &lt;p&gt;然後就開始加入原始程式碼檔案吧!!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;4. &lt;/b&gt;&lt;b&gt;Plug-in &lt;/b&gt;&lt;b&gt;程式碼與使用&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;很快，隨便寫了個 .c 的程式&lt;/p&gt; &lt;code&gt;   &lt;p&gt;float multiply(float x, float y)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;return x * y;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;然後 Build 這個 libunityplug1 專案，沒問題的話，會得到 libunityplug1.so 的檔案，把 .so 檔案複製到 Unity 的 Assets/Plugins/Android 目錄下&lt;/p&gt;  &lt;p&gt;修改 Unity C# Script&lt;/p&gt; &lt;code&gt;   &lt;p&gt;[DllImport(&amp;quot;unityplug1&amp;quot;)]&lt;/p&gt;    &lt;p&gt;private static extern float multiply(float x, float y);&lt;/p&gt; &lt;/code&gt;  &lt;p&gt;然後，就可以使用這個函式了。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2012/02/unity-3d-plug-in-for-android.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZet1UDAkS0-9qtvjNG2N-Qabp5e63bHbO-r3MY71hKwQglXA60BZB5rY6cDvYArn8h5H82poil28h6QWBvNCDhYFADsBaLujsTqbCvRumXlO0R7g4dkKzPnXfq-ABBV5SQwrkXV3_VEM7/s72-c?imgmax=800" height="72" width="72"/><thr:total>12</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-5285676898747187356</guid><pubDate>Fri, 07 Oct 2011 03:24:00 +0000</pubDate><atom:updated>2011-10-07T11:24:08.096+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>Visual Studio 2010 是好物</title><description>&lt;p&gt;很久沒碰 MFC了。&lt;/p&gt;  &lt;p&gt;前一陣子 CryEngine 釋出 SDK，抓來看了以後，發現它的編輯器介面很漂亮，多翻了翻，才知道原來是用 MFC Library 做的。&lt;/p&gt;  &lt;p&gt;這下子又引起我對 MFC 的興趣。&lt;/p&gt;  &lt;p&gt;顯然 MFC 還不至於像傳說中的那麼慘。&lt;/p&gt;  &lt;p&gt;最近打算重新改寫遊戲資源檔案打包上傳的工具程式，想到了 MFC，打算拿著來試試。&lt;/p&gt;  &lt;p&gt;發現了這麼一篇 Blog&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://10rem.net/blog/2010/03/25/your-first-mfc-cplusplus-ribbon-application-with-visual-studio-2010&quot;&gt;Your First MFC C++ Ribbon Application with Visual Studio 2010&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;哦~~~&lt;/p&gt;  &lt;p&gt;MFC 做出來的應用程式介面不再那麼難看了耶~~&lt;/p&gt;  &lt;p&gt;趕快隨手很快的建了一個專案，勾選幾個項目後，完整功能的 Dock Panel, Ribbon Menu ( 還有一個 Outlook的 Navigation Bar 沒勾) 都有了...&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbd093P-wvhluASalyDM4TA_zrV96FYc_m2-hvQbtiU2kzzxkS9U30rt9ekXyGAA-NKrNEO18KzNjD3SPAE7RobJmiSu8cp-woSfNp_82MZaNrbFn0xcRJM72kj9-gZSUrlqQE2MHLohN5/s1600-h/clip_image001%25255B5%25255D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;clip_image001&quot; border=&quot;0&quot; alt=&quot;clip_image001&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkOFPn0P2iBRMN6Qt0XfHxqSutzGuJnhGbLGNy65BnS2SWwE1jltca9YOPaGwNry7Qy57MRFQIrJFhMxLEgtiUp25ms0-yBncw6CtlhI9WzOR8E-IkEkKj4JZIcg3nUUifvHXnuNNBHpYu/?imgmax=800&quot; width=&quot;553&quot; height=&quot;356&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;沒做什麼事，而應用程式看上去的專業度大大提升...&lt;/p&gt;  &lt;p&gt;VS 2010 真是好物...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/10/visual-studio-2010.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkOFPn0P2iBRMN6Qt0XfHxqSutzGuJnhGbLGNy65BnS2SWwE1jltca9YOPaGwNry7Qy57MRFQIrJFhMxLEgtiUp25ms0-yBncw6CtlhI9WzOR8E-IkEkKj4JZIcg3nUUifvHXnuNNBHpYu/s72-c?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-6179688577871072209</guid><pubDate>Tue, 19 Jul 2011 14:30:00 +0000</pubDate><atom:updated>2011-07-19T22:30:35.579+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">寫不完的遊戲引擎</category><title>圖形除錯設備</title><description>&lt;p&gt;今年 GDC 給我的一個大震撼，就是，Game Engine / Graphic Engine 裡，要加上圖形除錯功能。&lt;/p&gt;  &lt;p&gt;回頭翻了一本 3D Game Engine Architecture 的書，才發現人家早早就有說了。&lt;/p&gt;  &lt;p&gt;這些功能的用處很大，做了絕對有好處。&lt;/p&gt;  &lt;p&gt;然後發現，啊，Engine 裡頭那個顯示 Bounding Box 的物件，不就是其中一個圖形除錯物件麼?&lt;/p&gt;  &lt;p&gt;Bungie 在開發 HALO 時，連網路封包的數據與優先權都用即時圖形顯示。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_G3mdncHoO-1IWIQ-RNQND_YZi6cG8CrteMSicB2H3fHAkxqe6djXVHoWuMKElC07fx2Vbi0ZR1crnxW7o_fnV0CEmfbgo03Esok1B5TD9l-q2n0hApD7t267FiOv153CZYRipHwokqV/s1600-h/image3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmcrS76Kphpbni4Y87ck-aO7Wt1ARVwpU0xQVv5CtE5dtkTyIXW7Cv8B2HeowFTXhVD5-E8frzb7dsXYOUxycjYNAKOjc7oz8QvZn_XZn-DzalfSEnQL4YPFXwfG1w31trUV0w1pgluYGi/?imgmax=800&quot; width=&quot;575&quot; height=&quot;330&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;我們真的該把圖形除錯的功能加到 Engine 裡。&lt;/p&gt;  &lt;p&gt;我叫它做「圖形除錯設備」。 ( Graphic Debugging Facilities )&lt;/p&gt;  &lt;p&gt;首先，我把 Game Timer 做了修改。加上加速、放慢、暫停、甚至每個 Frame 更新固定時間的功能。這些在我們做 Animation 的除錯時，應該會很有幫助。另外，我還加了一個 Real Life 的 Timer，我們總還是會需要知道真實時間的吧?&lt;/p&gt;  &lt;p&gt;然後， Engine 裡面加了一整組的 Debug Drawing API，包括畫線、畫圓、畫顆 Wireframe 的球、畫個十字、畫個座標軸、顯示字串訊息在 3D 場景裡，還有一個很有用的，畫個 Frustum 出來。&lt;/p&gt;  &lt;p&gt;最後一個組件呢，就是弄了一組除錯用的 Camera 跟 Frustum。遊戲場景的攝影機，是場景管理中很重要的運算基礎，但是我們怎麼知道這些運算有沒有問題? 例如，Frustum 的 Culling 運算、遠方物件的 LOD 選擇，有了除錯 Camera 的模式，我們就可以很簡單的做檢查。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHN54NCz3nLFsttsgjOWfqUmyfjPhao1wumND_D-ehsgDOfhToSlz0UN6O9lWrQM1KPLCaBG3eJ8QRjYdDqTjDR2w9fzQPrWFKSpEE928IB2S1hUOBAbX4CqPR-3HMwHpidKVd-Hz9Ih3n/s1600-h/image%25255B5%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk-Osk8Iv0Tw6rS5wlmBGiL0hKbvG-_E5qYDtRBblPxUhVlef1MUZtZmQUzrwT_7qrHtMkOpG-4-Cz2Rj5-RcX_GPQ90KGmzjwfCPXoJHSpb-RVbHZcOT_dJiBHAt55zIuPD7j_te1cTeI/?imgmax=800&quot; width=&quot;439&quot; height=&quot;314&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hmm... 看來 Frustum 的 Culling 並沒有算得很乾淨...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/07/graphic-debugging-facilities.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmcrS76Kphpbni4Y87ck-aO7Wt1ARVwpU0xQVv5CtE5dtkTyIXW7Cv8B2HeowFTXhVD5-E8frzb7dsXYOUxycjYNAKOjc7oz8QvZn_XZn-DzalfSEnQL4YPFXwfG1w31trUV0w1pgluYGi/s72-c?imgmax=800" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-7799928981675528593</guid><pubDate>Sun, 05 Jun 2011 06:39:00 +0000</pubDate><atom:updated>2011-06-05T14:39:03.690+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>30 天打造 OS!</title><description>&lt;p&gt;其實這是我今天帶回的一本奇書，它的副標題。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSNqvIV3JO-9KmwPyWn6Xq2jLsGsZQZy96OO_7UMThyphenhyphenhjpnc0yrvuSI6sDOlIxSxIOccihlRG8_w5VVDShT0o8Aho32XJDzbS-atIWIx-gcFefAx3ipveQMp4qUJc4Olt5PD3Cs-LNzJhS/s1600-h/image%25255B3%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4DCXKx1lugWjwowe8umqlcl8DCJM7cVhEu44CcrhbfjFH6iDz90D5ueR5fr3iyB40BZpZHqu0Xnawnffk5PbApyWcRQhTcnW6wHQ_X2joW8aZIVpUbx3uP1sP1TtsTp4Fe2eAVb_F5Al/?imgmax=800&quot; width=&quot;243&quot; height=&quot;339&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(圖片來源: 博客來書籍館)&lt;/p&gt;  &lt;p&gt;日本人寫的，譯者有三位。&lt;/p&gt;  &lt;p&gt;為什麼說它是奇書 ?&lt;/p&gt;  &lt;p&gt;你看標題就知道了， 「自己做作業系統 ? 這什麼 ?」&lt;/p&gt;  &lt;p&gt;台灣的資訊相關書籍，多如過江之鯽，作業系統核心的內容已經夠硬了，還要自己寫程式來做 ? 而且一開始還是拿組合語言拼出來的開機程式，這絕對是硬派中的硬派。&lt;/p&gt;  &lt;p&gt;市場更是小之又小。&lt;/p&gt;  &lt;p&gt;幾個月前我在書店裡看到的時候，愣了一下，覺得很神奇，怎麼會有人出版這種書 ? 有個怪咖會寫這種書不奇怪，但是翻譯了出版來賣 ? 這就很匪夷所思了。&lt;/p&gt;  &lt;p&gt;就算上架了，大概也沒幾個人會在書店裡把它拿起來翻閱的吧?&lt;/p&gt;  &lt;p&gt;果然， 今天閒晃的時候又看到它，整本書還是跟新的一樣。&lt;/p&gt;  &lt;p&gt;我沒有多想，就把它買下帶回家了。&lt;/p&gt;  &lt;p&gt;這種市場小之又小的書，一不注意，就會消失在書店裡，再也找不著。&lt;/p&gt;  &lt;p&gt;話又說回來，書的封底是這麼寫的：&lt;/p&gt;  &lt;p&gt;-----&lt;/p&gt;  &lt;p&gt;可能是史上最有趣且實用的作業系統書籍！日文版已突破13刷！&lt;/p&gt;  &lt;p&gt; 這是一本兼具趣味、實用與學習性的作業系統書籍。作者以獨創手法，從電腦的構造、組合語言、C語言開始解說，讓讀者透過實作與測試學會演算法，並在自由愉悅的氛氛下，從零開始建構作業系統。&lt;/p&gt;  &lt;p&gt; 即使是初學者，也不需畏懼，因為連貓咪都能輕鬆學會自作作業系統！&lt;/p&gt;  &lt;p&gt;-----&lt;/p&gt;  &lt;p&gt;貓咪也能學會? 廣告不實...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/06/30-os.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4DCXKx1lugWjwowe8umqlcl8DCJM7cVhEu44CcrhbfjFH6iDz90D5ueR5fr3iyB40BZpZHqu0Xnawnffk5PbApyWcRQhTcnW6wHQ_X2joW8aZIVpUbx3uP1sP1TtsTp4Fe2eAVb_F5Al/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-8864037071426683981</guid><pubDate>Tue, 08 Mar 2011 14:42:00 +0000</pubDate><atom:updated>2011-03-08T22:42:39.499+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>GDC 2011 Day 5</title><description>&lt;p&gt;最後一天，算算只有四個小時的課。&lt;/p&gt;  &lt;p&gt;今天的開場，由 Bungie 的 Halo : Reach 開始。&lt;/p&gt;  &lt;p&gt;首先是 Automated Level of Detail Generation。&lt;/p&gt;  &lt;p&gt;顧名思義，就是用程式算出 LOD Mesh。裡頭的演算方法，是很不錯的想法，可以找時間來模擬嘗試看看。&lt;/p&gt;  &lt;p&gt;而除了 LOD Mesh 之外，他們還提出了一個做法 – &amp;quot;Unified material model&amp;quot;。&lt;/p&gt;  &lt;p&gt;簡單講，就是所有的 LOD Mesh 都使用同一種材質 Shader ，這樣一來，也可以提升很多效能。更重要的是，反正距離很遠、物件很小的時候，就算畫的很粗略，也不是那麼明顯...&lt;/p&gt;  &lt;p&gt;在這裡，他們也展示了一個在除錯模式下的攝影機，可以用來檢查 LOD 的變化是否如預期。&lt;/p&gt;  &lt;p&gt;Hmm… 我們似乎也該弄個 Debug Mode Camera 來了。&lt;/p&gt;  &lt;p&gt;第二段，講述的是 Halo : Reach 裡的 Effect。&lt;/p&gt;  &lt;p&gt;第一個來的 Effect，就是嚇死人的粒子系統。&lt;/p&gt;  &lt;p&gt;有多恐怖? &lt;/p&gt;  &lt;p&gt;1. 粒子的運算全部交由 GPU 計算，CPU 只決定粒子的數量。&lt;/p&gt;  &lt;p&gt;2. 在 GPU 裡計算的粒子，照樣可以跟場景中的物件計算碰撞跟彈跳。&lt;/p&gt;  &lt;p&gt;所以，只要一個 GPU Draw Call ，就可以畫出所有的粒子，而且還會有碰撞彈跳。&lt;/p&gt;  &lt;p&gt;碰撞與彈跳計算的資料來源有兩個，Depth Buffer 與 Normal Buffer。計算的概念，說穿了一點都不難，但是，要能夠想到這點，還真的是不容易。&lt;/p&gt;  &lt;p&gt;接下來的效果，都跟 Depth Buffer 有關。&lt;/p&gt;  &lt;p&gt;Bungie 給了一個結論 – &amp;quot;Depth buffer is incredibly useful&amp;quot;&lt;/p&gt;  &lt;p&gt;前兩天，岩田聰社長說 : &amp;quot;Content is KING&amp;quot;&lt;/p&gt;  &lt;p&gt;今天我們的結論是 : &amp;quot;Depth Buffer is KING&amp;quot;&lt;/p&gt;  &lt;p&gt;接下來聽了一場跟想像中的內容不太一樣的講題。&lt;/p&gt;  &lt;p&gt;本來以為他們會介紹如何處理一個龐大遊戲場景的概念與方法，結果，他們是有介紹啦，但是卻是基於他們自己的工具系統，有一點失望，不過也還是有一點收穫就是。&lt;/p&gt;  &lt;p&gt;下午聽了一場是關於拳擊遊戲裡，對於拳手的皮膚效果的處理方式，很新鮮，而且他們的專業研究，也不得不讓人佩服。&lt;/p&gt;  &lt;p&gt;過去一整個看起來像 &amp;quot;塑膠&amp;quot; 的皮膚，經過研究分析改進之後，變得非常自然。&lt;/p&gt;  &lt;p&gt;真是夠專業。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;最後，把像素拼圖的完成圖拍了下來。 ( 雖然這已經是由工作人員完成的了... )&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8FKvZT6Ri9vYVRXtnDHm3OUbpI_eGY1e0TRYlxOfLFv0hhX-eBaNhAHMZgZHQ3pobN0dt848P_DHQefEYPP-1IbT_nDZVFZgolzZDnIzg2UTYCqyJMAcVu92c9QUWxckHyJ3q-CsRLCO9/s1600-h/DSC01442%5B5%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01442&quot; border=&quot;0&quot; alt=&quot;DSC01442&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8tY68tccyCHG_fekTWlfr_7aUpFGHUJeHeChn57okAmkebMnavG1K9bCwllvGrceoDv81LVdYZ9MHIjLqfoCV-W3k1JR9CW7LdNqlEHb6Pp-B3u-qPgI320VvnrlVvVtC45KO_XdwOo6q/?imgmax=800&quot; width=&quot;510&quot; height=&quot;384&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/03/gdc-2011-day-5.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8tY68tccyCHG_fekTWlfr_7aUpFGHUJeHeChn57okAmkebMnavG1K9bCwllvGrceoDv81LVdYZ9MHIjLqfoCV-W3k1JR9CW7LdNqlEHb6Pp-B3u-qPgI320VvnrlVvVtC45KO_XdwOo6q/s72-c?imgmax=800" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-7189214967318513100</guid><pubDate>Fri, 04 Mar 2011 05:42:00 +0000</pubDate><atom:updated>2011-03-04T13:42:04.945+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>GDC 2011 Day 4</title><description>&lt;p&gt;中午又跑去任天堂的展場去玩 3DS，本來是想要玩玩薩爾達的，可是人好多擠不進去，晃了一陣，只玩到 Street Fighter。&lt;/p&gt;  &lt;p&gt;也很讚。&lt;/p&gt;  &lt;p&gt;早上第一場，去聽了 Killzone 3 有關 Occlusion Culling 的技術，基本概念也還是用個 Buffer 來記錄深度，然後做測試運算，沒什麼新的。不過說的很詳細，比起昨天用兩三張畫面帶過的那一場，好太多了。&lt;/p&gt;  &lt;p&gt;更重點是，他們做了一整套在 Occlusion Culling 上的 Debug 工具，可以很清楚看到 Occlusion Culling 計算前計算後的結果。&lt;/p&gt;  &lt;p&gt;視覺化很重要，尤其是這東西跟美術有關。&lt;/p&gt;  &lt;p&gt;接下來去聽了 Dead Rising 2 在網路功能方面的經驗分享。&lt;/p&gt;  &lt;p&gt;這遊戲好像賣的很不錯? 整場聽眾有爆滿啊...不過我很懷疑有多少人不是技術背景的，至少最後發問的人裡頭有一兩個...( 問的問題居然是遊戲的銷售量?? )&lt;/p&gt;  &lt;p&gt;網路功能，嗯，對我們在 MMO 上面已經有些經驗的人來說，這些分享的內容並沒有太多的不同。反倒是，他們也做了個 工具來監看 Traffic、監看資料同步的結果...就顯示在遊戲畫面上...Real-Time…&lt;/p&gt;  &lt;p&gt;只能說，他們真的很愛做工具。不知道是因為專業還是因為人太多?&lt;/p&gt;  &lt;p&gt;下午，有一個題目很吸引人。&lt;/p&gt;  &lt;p&gt;&amp;quot;Adaptive Order Independent Transparency&amp;quot;&lt;/p&gt;  &lt;p&gt;Render 半透明物件不用先排序。&lt;/p&gt;  &lt;p&gt;基本概念還是與 A-Buffer 有關。只不過，將 A-Buffer 的第二階段 -- 排序與組成，引入一個 &amp;quot;Visibility Function&amp;quot;，以當作權重的方式，計算半透明 Pixel 最後合成的結果。用這樣的方式，刪去耗費時間的排序工作。&lt;/p&gt;  &lt;p&gt;效能增加很多。&lt;/p&gt;  &lt;p&gt;不過這 &amp;quot;Visibility Function&amp;quot;的計算有些複雜。&lt;/p&gt;  &lt;p&gt;接下來的課程是，Bugie 講述 Halo : Reach 遊戲裡網路相關的技術分享。&lt;/p&gt;  &lt;p&gt;有一句話寫得好 : &amp;quot;Technology to help multiple players sustain the belief that they are playing a fun game together&amp;quot;&lt;/p&gt;  &lt;p&gt;他舉了兩個遊戲中的例子，來看他們把網路延遲藏的有多好。&lt;/p&gt;  &lt;p&gt;然後，又看到了 Traffic 監看的工具...也是直接顯示在遊戲畫面上...也是 Real-Time…&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3fzm5DXpzQ4sepLVfykYY1ZmkNQo97JJ6KukfNGTSxJqrQkeJLQBl4OAyoXtNLBCzGPpZ1SPgkdX8lFtKx7Q6uNm_U5Y0Fittzjr5JGWHCNrh28lfk4TjpUtJqcoeb1tMuVfho6PJ9kZ2/s1600-h/DSC01306%5B4%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;DSC01306&quot; border=&quot;0&quot; alt=&quot;DSC01306&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNfAZ90TWUlEh6OuW7uhPhNzFN6sdAySB_8-G6rO4jfw83iRAmjcQKNjpESvn4wTqaUn_JgZ_JtfYwZBzJ80vd4LUMisvZ5Fn1-WGs5nhxG6BHreYOGXKBInps53anyaHQnTY9cY5XtMuE/?imgmax=800&quot; width=&quot;532&quot; height=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;他們真的很喜歡做工具...&lt;/p&gt;  &lt;p&gt;不過，這工具應該還是有用的，至少他們抓到了一個問題: 一個還在滾動的手榴彈用了很大量的頻寬...&lt;/p&gt;  &lt;p&gt;最後一堂課程是超大的一顆地雷...&lt;/p&gt;  &lt;p&gt;又沒有其他課程好去，所以就坐著混到下課...&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;今天的像素拼圖長這樣:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhecT6OvVymLC3CRzGUBJwLmOvlcf6L-v2y16B5yaMYEw33s1STWgcVv_ULci8kipIcdc0c-PV1oAq5H1sZqZaiaYFxJWuY68IEw7dCX-4_B-nWFS2Oxw1cJl6hhs5dPkYTxkn6SnXUDN4a/s1600-h/DSC01234%5B5%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01234&quot; border=&quot;0&quot; alt=&quot;DSC01234&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjH08QkrMUMECwLDwgbSf913cslIWlA-TJcXq0gQ62uo8vTlhlJEB8_wHWnJZacRmdoWwD0jJMEDPr4gO22rCYZ8hM9nWPDNWI0x3iFY9fZZEUfDW1xW0rq5scZ3IT3wfIg6KRTgfN3CFs/?imgmax=800&quot; width=&quot;499&quot; height=&quot;375&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;昨天那個日本人做的馬力歐已經不見了，應該是工作人員把它拆了。&lt;/p&gt;  &lt;p&gt;那個蹲著在拼的，應該就是工作人員。手上有一大包同樣顏色的方塊，拼完了又去拿了一大包來拼。&lt;/p&gt;  &lt;p&gt;有工作人員做修正，那這個活動也沒什麼意思了...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/03/gdc-2011-day-4.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNfAZ90TWUlEh6OuW7uhPhNzFN6sdAySB_8-G6rO4jfw83iRAmjcQKNjpESvn4wTqaUn_JgZ_JtfYwZBzJ80vd4LUMisvZ5Fn1-WGs5nhxG6BHreYOGXKBInps53anyaHQnTY9cY5XtMuE/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-9020255914885646812</guid><pubDate>Thu, 03 Mar 2011 03:55:00 +0000</pubDate><atom:updated>2011-03-03T12:15:24.570+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>GDC 2011 Day 3</title><description>&lt;p&gt;Game Develop Conference 今天算是正式開始。&lt;/p&gt;  &lt;p&gt;一開始的盛事，就是任天堂社長岩田聰的 Keynote 演講。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG-TlIutepo5Qrl1pAd-v10NTQr4xsFXhrmKqFpG2iV-SADCClkNwzoGMisJM2Ks3808lrGQEyKdwznf5jPdgLg9a0de-EKe3BDuFDZPSNrkJGbhQ_vKFCXs-g1bbJY4cN4Jzp1RoSp0uZ/s1600-h/DSC01132%5B4%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01132&quot; border=&quot;0&quot; alt=&quot;DSC01132&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglVpM1BKGAlcOjxCq_AHh3A9J3aR5CWgbXrdikJ44twCNaXzraimn9C3HLZGLtd_aiusOKxsN0na_5Djl0SMQ-VIb5rFEjSAMOe_P6Jdqi0uBmDYqaZXcBnXbaPHhx48qcE6x_Y0cYhI2o/?imgmax=800&quot; width=&quot;440&quot; height=&quot;331&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRMIB_vUmbG8ub4Y4yrU5olZ9rEm1FIC_aVmAbQhA14wVGI-6NSM77vNHdJQznof4k4tjYCO_uxd9faAQawUebzCpt2eYE4me3PoQ_hZ1vtrwXubqtHlbJA3Je0Oz7z0UEhDZOnkyyIS7/s1600-h/DSC01134%5B5%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01134&quot; border=&quot;0&quot; alt=&quot;DSC01134&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsX_9D6ZltbWs7sRDmLK9gefWwbPTcrlMUFux1MwlNOhTrMcrXBA7YbNlk_nTl95Zf45TPgDcazYO5KEEaYaxSFDD4-R4KGd1_5T3pcGlCf8b2vBxASp6QcfABTNbDS79-D-4iMpL9X43A/?imgmax=800&quot; width=&quot;441&quot; height=&quot;331&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;說真的，日本人講的英文聽起來有難度，我想他說起來也不會簡單...&lt;/p&gt;  &lt;p&gt;所以，在他演講台的正對面有大字報...&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaXfPnZTGFtaxqcNd0i6WpgY9nB_kSv03taq8K7IXIPw-ErUV8qCRsxJvgMCuvAZDNZ5uqD4qTcjIyR6W-LTcSIXvrPVnJiLSmW8yDFmtIMUPlVBE7BS3NOJqxa7CsrhZI_Anqbe1XxhiI/s1600-h/DSC01135%5B4%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01135&quot; border=&quot;0&quot; alt=&quot;DSC01135&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoFpiy-fGg4-WbNZL0Hsl8W-hU1pzV-NR0F7VAygZtndBmKIqHBrDuny7w4lUFAIDgAIse_fSo0As3jJoFNAFLSa4qKWIQqwgaYLstVYJYkrWJAOA1nA2pDof33cMNJHhamp-IqrXHsn5i/?imgmax=800&quot; width=&quot;435&quot; height=&quot;327&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;演講主題呢，就是內容啦、創意啦、熱情啦...這些東西...&lt;/p&gt;  &lt;p&gt;一個小時的演講，中間還讓北美的任天堂主管進來工商服務一段 N3DS…&lt;/p&gt;  &lt;p&gt;N3DS&lt;/p&gt;  &lt;p&gt;真的是很讚。&lt;/p&gt;  &lt;p&gt;中午休息時間，到任天堂的展場去，搶到空位，把玩了一下 N3DS 的任天貓狗，整個裸眼 3D 的畫面效果好逼真啊...&lt;/p&gt;  &lt;p&gt;不過這個真的要親眼看，有圖就沒真相了。&lt;/p&gt;  &lt;p&gt;其他的四堂課，好像都碰到了大大小小不等的地雷，沒有什麼非常 Exciting 的東西。倒是另一位同事選到了一兩個有意思的課程。&lt;/p&gt;  &lt;p&gt;首先是 Autodesk 講他們正在進行的新計畫 -- DNA Language，用來做為 Game Runtime, Game Editor, DCC Tools 之間的資料庫管理橋樑。讓 Asset 的製作與測試，能夠有更快速順暢的 Workflow。&lt;/p&gt;  &lt;p&gt;可是，我只是想知道 Asset 的版本管理方法啊... 課程簡介上不是寫的是這個嗎? 你們不能就這樣輕輕鬆鬆帶過啊...&lt;/p&gt;  &lt;p&gt;下午，先去聽 Valve 的演講，這場技術性比較高些，可能跟這個演講者老是在玩組合語言有關。&lt;/p&gt;  &lt;p&gt;網頁： &lt;a href=&quot;http://bit.ly/hPCmVW&quot;&gt;http://bit.ly/hPCmVW&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;然後去聽了 BattleField 3 的新的場景 Culling 的方法。&lt;/p&gt;  &lt;p&gt;什麼新方法?&lt;/p&gt;  &lt;p&gt;把矩陣行列轉過來，讓 SIMD 運算比較快些，也算新方法?&lt;/p&gt;  &lt;p&gt;然後講 Software Culling，什麼? 就畫在一張比較小的 Z-Buffer 上然後做 Z-Test ?&lt;/p&gt;  &lt;p&gt;我快昏了...&lt;/p&gt;  &lt;p&gt;最後一堂課，去聽 AMD 介紹新版 PerfStudio。心得就是 : AMD 用了一張顯示卡，換到了幾十張開發者的名片...&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;今天的像素拼圖是這樣--&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP8FyE_qa1LTcohorlmdzRHsgIx4dFs08sIAAd38LhuMfSkuTEMqwMccco96PVZGIJvEJvIepyMDJrqXxkrRL7I1ELOWzvuR6zQqDjEIUI_Mb0-dG_JrhB07WDpTwbyPHJSG6jXJt7TAog/s1600-h/DSC01151%5B4%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;DSC01151&quot; border=&quot;0&quot; alt=&quot;DSC01151&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNapz8imSBu2pD7EMLqMamt91IiqNrVemKnB7fPDkF-YVY91zd15_qcKTXq5U2MxkctDu5bjnr3RVbwMIIM5v41o6GrZrFuYWsEl-p9Dke-340F6yUU-6fdZRgdGDhwiy_mDVpBh9U0r4H/?imgmax=800&quot; width=&quot;435&quot; height=&quot;327&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;那個蹲跪著在拼的應該是日本人，他也不管格子上面寫的是什麼符號，反正就是要從別的地方拆方塊下來拼馬利歐就對了。&lt;/p&gt;  &lt;p&gt;我開始覺得，每個人都想要做自己的創意，這張圖應該沒辦法完成了...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/03/gdc-2011-day-3.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglVpM1BKGAlcOjxCq_AHh3A9J3aR5CWgbXrdikJ44twCNaXzraimn9C3HLZGLtd_aiusOKxsN0na_5Djl0SMQ-VIb5rFEjSAMOe_P6Jdqi0uBmDYqaZXcBnXbaPHhx48qcE6x_Y0cYhI2o/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-3499750219521335142</guid><pubDate>Wed, 02 Mar 2011 04:31:00 +0000</pubDate><atom:updated>2011-03-03T12:17:26.190+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>GDC 2011 Day 2</title><description>&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9ofAhsuXuU-HDZp51iSLBxZ_WEjcQgsqNmBgUjk0zd9u-GNSz78Qu2oiOQEozqwtBOzI_t-1LRVFWfscIjbO212kBUfQnAeJXKAFmBknxH1lc3gfRCIJJn6PfUqaj03sKS_GFlEo5ySoY/s1600-h/DSC01131%5B5%5D.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border: 0px none; margin: 3px 5px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px;&quot; title=&quot;DSC01131&quot; alt=&quot;DSC01131&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIdWU5D1bCQUEm8xGNKS4zzj7UtiBRt_fd1W3vSQyPGIyIh_SHTo8yE9j-TtWkrdKINMOzWoC8VZUeqVDawsL-Jd55IgL-v1RnKtmmVreXtuXo2HLlB316VUfwOJH4jnhujRL34AMTKMBc/?imgmax=800&quot; width=&quot;561&quot; border=&quot;0&quot; height=&quot;421&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;這是一道壁報牆，上面的一點一點紅色藍色黃色黑色的小方塊，是由每一位 GDC 的參加者，一人一塊貼上去的。&lt;/p&gt;  &lt;p&gt;白色的格子上有小小的標示，寫著方格該貼的顏色，每一位 GDC 的參加者會拿到一塊方塊，自己對著顏色貼上去。&lt;/p&gt;  &lt;p&gt;很有意思的活動，象徵著古早時代的遊戲美術一個像素一個像素的&quot;刻點&quot;。&lt;/p&gt;  &lt;p&gt;不過那個戴帽子的老兄不知道在幹嘛，一直從別的地方把方塊拔下來黏到他要的地方去...&lt;/p&gt;  &lt;p&gt;明天再去看看完成度如何...&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;第二天的課程，選擇去微軟的 Kinect Develop Summit。&lt;/p&gt;  &lt;p&gt;據說 Kinect XDK for Windows 即將要釋出，不知道是不是表示 Kinect 可以裝在 PC 上了。這會是什麼景象?&lt;/p&gt;  &lt;p&gt;---------------------------------------------------------------------------------------------------------------------&lt;/p&gt;  &lt;p&gt;微軟還是很上道，去聽的人都能夠拿到一份光碟，所以就不用拼命低頭寫重點或是把投影片拍下來。&lt;/p&gt;  &lt;p&gt;還送了一小疊很有質感的筆記紙。&lt;/p&gt;  &lt;p&gt;一開場的簡介，快講完的時候，有這麼一段--&lt;/p&gt;  &lt;p&gt;本來完全不玩遊戲的媽媽，跟參與 Kinect 開發的兒子說，要買 Kinect 來玩，而且，現在每天玩。所以，這是一個遊戲產業的世代革命...&lt;/p&gt;  &lt;p&gt;好，這故事從 Wii 換成 Kinect，故事主角從宮本茂的老婆換成某位微軟員工的媽...&lt;/p&gt;  &lt;p&gt;老梗。&lt;/p&gt;  &lt;p&gt;Kinect 有幾個主題，Joint Filter, Gesture Detection, Speech Recognition, 還有 Mechine Learning, Neural Network。&lt;/p&gt;  &lt;p&gt;我們能說，整個系統已經不再是 true / false, 0 與 1 的思考方式，必須改用機率、權重、取樣分佈來想。&lt;/p&gt;  &lt;p&gt;而且，這樣的系統裡，取得的資料很多，資料裡的雜訊更多，如何取得能用與有用的資料，就變成是 Filter 的技術所在。&lt;/p&gt;  &lt;p&gt;Gesture Detection 也不簡單，因為每個人的姿勢手勢都不同，很多元，所以設計就變得很複雜，要考慮的狀況、要測試的條件也很多。&lt;/p&gt;  &lt;p&gt;例如，&quot;伸出你的右手&quot;。&lt;/p&gt;  &lt;p&gt;男人女人的伸手方式就不一樣了，老人與小孩的伸手方式也不會相同。&lt;/p&gt;  &lt;p&gt;這程式要怎麼寫?&lt;/p&gt;  &lt;p&gt;Hmm…&lt;/p&gt;  &lt;p&gt;Mechine Learning&lt;/p&gt;  &lt;p&gt;我們決定演算法之後，讓機器自己去決定參數與權重...&lt;/p&gt;  &lt;p&gt;不知道是不是所有的體感遊戲平台都有這樣的做法，不過對習慣於 Input 始終是 0 與 1 組成的我們來說，應該是很有挑戰性。&lt;/p&gt;  &lt;p&gt;課程結束，填了問卷交回。&lt;/p&gt;  &lt;p&gt;哇咧，今年沒有 &quot;填問卷送 T Shirt&quot; ?&lt;/p&gt;</description><link>http://lancelotdiary.blogspot.com/2011/03/gdc-2011-day-2.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIdWU5D1bCQUEm8xGNKS4zzj7UtiBRt_fd1W3vSQyPGIyIh_SHTo8yE9j-TtWkrdKINMOzWoC8VZUeqVDawsL-Jd55IgL-v1RnKtmmVreXtuXo2HLlB316VUfwOJH4jnhujRL34AMTKMBc/s72-c?imgmax=800" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-6510417360593589915</guid><pubDate>Tue, 01 Mar 2011 05:29:00 +0000</pubDate><atom:updated>2011-03-01T13:29:51.564+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>GDC 2011 Day 1</title><description>&lt;p&gt;2011 年的 GDC，是第 25 屆，不過也好像沒有特別盛大什麼的。反而是讓人感覺規模越來越小，就連報名參加所給的一個資料袋，質感都越來越糟...&lt;/p&gt;  &lt;p&gt;依照慣例，前兩天是 Tutorial 課程跟一些 Summit 演講。&lt;/p&gt;  &lt;p&gt;今天還是參加了一整天的 Tutorial，題目是 – &amp;quot;Advanced Visual Effects with DirectX 11&amp;quot;&lt;/p&gt;  &lt;p&gt;--------------------------------------------------------------------------------------------------------&lt;/p&gt;  &lt;p&gt;早上第一堂課，介紹的是 DX 11 裡的 Device Context &amp;amp; Command List，多緒繪製的架構。&lt;/p&gt;  &lt;p&gt;接下來，是 Deferred Shading 的最佳化策略。包括 Light Pre-pass, Light Geometry Optimization 幾個方法。不過，Light Pre-pass 馬上在下午的課程裡被打槍...&lt;/p&gt;  &lt;p&gt;接著是 Civilization V 。&lt;/p&gt;  &lt;p&gt;他們用了一個稱為 &amp;quot;Packetized Rendering&amp;quot; 的設計策略，將所有的 API call 包裝成一個 packet，送到 engine 去處理，每個獨立的 render job 可以降低彼此之間的關聯性，甚至沒有關聯。然後可以很自豪的說，&amp;quot;No threading bugs&amp;quot;。&lt;/p&gt;  &lt;p&gt;展示了一個很壯觀的 Screen Shot -- 滿滿畫面的兵，底下還秀了CPU 效能，12個核心同時在跑!!&lt;/p&gt;  &lt;p&gt;然後是 Dragon Age II ，介紹他們所使用的 DX11相關技術。&lt;/p&gt;  &lt;p&gt;他們主要用在 Dynamic Lighting ( Light Pre-pass method ), Tessellation, Diffusion Depth of Field (DDOF), Contact Hardening Shadows 上。&lt;/p&gt;  &lt;p&gt;從這裡開始，DDOF 就一直出現了...&lt;/p&gt;  &lt;p&gt;根據他們所說， Tessellation 是一個效能殺手。所以，只用在看得到的、很靠近攝影機的地形上。&lt;/p&gt;  &lt;p&gt;也就是，這技術並不是什麼都適用的好物...&lt;/p&gt;  &lt;p&gt;Contact Hardening Shadows 做出來的 Soft-shadow 效果，比過去用的 PCF Filtering 好非常多。DX11 SDK 上有 Sample，不過，我的電腦還是 DX10的顯卡，跑不起來，只能看靜態的圖...&lt;/p&gt;  &lt;p&gt;下午第一堂課，就由 DICE 介紹他們的大作 Battle Field 3。&lt;/p&gt;  &lt;p&gt;這遊戲，只支援 DX11，拋棄 DX9。&lt;/p&gt;  &lt;p&gt;他們說，BF3 是大作，所以可以推動 OS 以及硬體的更新。&lt;/p&gt;  &lt;p&gt;我們在旁邊，表示 .. &amp;quot;一切樂觀其成&amp;quot;...&lt;/p&gt;  &lt;p&gt;太樂觀了...&lt;/p&gt;  &lt;p&gt;BF3 的 Deferred Shading 並沒有使用 Light Pre-pass 方法，因為 Light Pre-pass 要對 Geometry render 兩個 pass，對 BF3 而言，Geometry 太多，不適用。&lt;/p&gt;  &lt;p&gt;BF3 用了一個特殊的想法。&lt;/p&gt;  &lt;p&gt;將 Screen Image 切分成幾十個 Tile，每個 Tile 用 Compute Shader 計算相關的 Light Info，這樣，據說可以計算場景裡高達 1000 個點光源...&lt;/p&gt;  &lt;p&gt;BF3 的場景裡的物件也是很多的，所以依舊存在著 Draw Call 的 Bottleneck。所以， BF3 將 Instancing 發揮到最大極限，從一個 Object 一個 Draw Call ，變成 &amp;quot;一種&amp;quot; Object 一個 Draw Call...&lt;/p&gt;  &lt;p&gt;效能大提升。&lt;/p&gt;  &lt;p&gt;最後，BF3 呼籲 : Drop DX9!!&lt;/p&gt;  &lt;p&gt;(我們還是繼續在旁邊... &amp;quot;樂觀其成&amp;quot;...)&lt;/p&gt;  &lt;p&gt;接下來是一個日本人的介紹。&lt;/p&gt;  &lt;p&gt;精神不濟加上日式發音很難懂，以致這半個多小時全部不知道什麼是什麼...&lt;/p&gt;  &lt;p&gt;然後，又來 DDOF 了。&lt;/p&gt;  &lt;p&gt;主題是 DDOF Solver，不太懂在做什麼，回去要開始找資料開始瞭解。&lt;/p&gt;  &lt;p&gt;接下來的主題是 Separable Filters。&lt;/p&gt;  &lt;p&gt;是用 Compute Shader 取代 Pixel Shader 做 Image Base Filter 的想法。&lt;/p&gt;  &lt;p&gt;舉例就舉例嘛，不知道為什麼，又拿 DDOF 來舉例...&lt;/p&gt;  &lt;p&gt;DDOF 看起來好像真的很重要...&lt;/p&gt;  &lt;p&gt;然後談到 Tessellation, Displacement Shading, 重點 : 請用在 &amp;quot;Key Assets&amp;quot; 上...&lt;/p&gt;  &lt;p&gt;最後，再經過一段冗長的 Post-Processing Performance Optimizing 演講，好不容易，下課休息。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2011/03/gdc-2011-day-1.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-5127658921689618381</guid><pubDate>Fri, 17 Dec 2010 06:07:00 +0000</pubDate><atom:updated>2010-12-17T14:08:23.963+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">寫不完的遊戲引擎</category><title>引擎中不可或缺的事件訊息系統</title><description>&lt;p&gt;嗯...對...&lt;/p&gt;  &lt;p&gt;很久沒有發文了...&lt;/p&gt;  &lt;p&gt;「懶」是唯一的解釋...&lt;/p&gt;  &lt;p&gt;前一陣子看到一個引擎中的訊息系統架構，突然間，對整個引擎的架構設計有了新的想法。或者該說，解決了我心中長久以來的難題。&lt;/p&gt;  &lt;p&gt;說穿了，不過就是事件訊息驅動式 ( Event Driven ) 的架構設計。&lt;/p&gt;  &lt;p&gt;這東西被我晾在一旁太久，已經完全忘記它的存在了。&lt;/p&gt;  &lt;p&gt;簡單舉個例子說吧...&lt;/p&gt;  &lt;p&gt;遊戲中有很多系統，會受到攝影機的位置方向的影響，例如，天空盒子 ( Sky box ) 必須隨著攝影機的位置變動位置，動態讀取的無接縫地圖系統也必須檢查攝影機的位置來決定是否讀取地圖或是釋放地圖。如果在一個單純的程序式的架構中，我們會在攝影機位置變動的時候，呼叫這兩個物件系統來做相應的更新檢查。&lt;/p&gt;  &lt;p&gt;像是這樣:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;CameraManager::UpdatePosition(Camera* camera, Vector3 pos)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; camera-&amp;gt;UpdatePosition(pos);       &lt;br /&gt;&amp;#160; skybox-&amp;gt;UpdatePosition(pos);       &lt;br /&gt;&amp;#160; seamless_world-&amp;gt;CheckLoading(pos);       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;只不過，這麼一來，我們可以非常確定的是， Camera Manager 這個物件已經跟 Skybox 、 Seamless World 分不開了。三個物件綁在一起的結果是，物件的再利用性大大降低。( 想想如果我們需要將 sky box 改為 sky doom, 又或者我們不再需要無接縫地圖的時候... )&lt;/p&gt;  &lt;p&gt;這還只是其中一個問題。&lt;/p&gt;  &lt;p&gt;另外一個問題是，在我們遊戲越做越大，引擎越寫越深入的時候，我們發現， LOD ( Level of Detail ) 的計算也需要隨著攝影機變動而更新，水面倒影效果也跟攝影機有關，粒子系統的繪製也需要攝影機的資料...&lt;/p&gt;  &lt;p&gt;於是乎，我們又把 LOD 系統、水面倒影、粒子系統全綁到了攝影機物件裡。&lt;/p&gt;  &lt;p&gt;更甚至於，第三人稱視角的遊戲裡，攝影機是跟著主角走的，所以，又把攝影機綁到了主角身上，跟著主角更新。&lt;/p&gt;  &lt;p&gt;最後的結果就是，整個引擎裡各式各樣的系統物件，因為彼此之間相互影響的關係，全部混成一團。&lt;/p&gt;  &lt;p&gt;現在換個角度，改用事件驅動來做。&lt;/p&gt;  &lt;p&gt;攝影機變動的時候，我們不管 Skybox 、 Seamless World，只送個訊息給事件系統。&lt;/p&gt;  &lt;p&gt;像是這樣:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;CameraManager::UpdatePosition(Camera* camera, Vector3 pos)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; camera-&amp;gt;UpdatePosition(pos);       &lt;br /&gt;&amp;#160; event_system-&amp;gt;Send(idCameraPositionUpdated, camera);       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;而對於 Skybox, Seamless World 來說，必須有函式負責來接收這個事件，同時，在物件的初始化的時候，必須先把這個函式登記到事件系統裡。&lt;/p&gt;  &lt;p&gt;Sky Box 的接收函式大概會長得像這樣:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;Skybox::OnCameraPositionUpdated(Camera* camera)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; UpdatePosition(camera-&amp;gt;GetPosition());       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;其他的，需要隨著攝影機更新而更新的物件，也都會有相類似的函式，同時也都需要將函式登記到事件系統中，事件系統在收到攝影機送來的事件後，就會分發事件，一一呼叫每個需要的事件處理函式。&lt;/p&gt;  &lt;p&gt;這樣子，事件系統將我們的各個物件獨立開來，減少了很多錯綜複雜的關連。&lt;/p&gt;  &lt;p&gt;更進一步來，我們可以在玩家主角的位置更新的時候，發送一個事件出來，然後在攝影機系統裡，寫個這樣的函式:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;CameraManager::OnPlayerPositionUpdate(Player* player)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; UpdatePosition(player-&amp;gt;GetPosition());       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;當然了，這樣的事件驅動架構不是沒有缺點的。缺點就是，為了遵循這個架構模式，我們必須多寫很多 code ，例如，本來可以直接在攝影機裡呼叫的函式，現在必須寫一個事件處理函式來呼叫它，而且還必須要把事件處理函式登記到系統裡，有點煩...&lt;/p&gt;  &lt;p&gt;但是多花這些工絕對是值得的...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/12/event-system-in-engine.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-27771917128150537</guid><pubDate>Fri, 11 Jun 2010 02:08:00 +0000</pubDate><atom:updated>2010-06-11T10:08:56.656+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>一個「偽」亂數的演算法</title><description>&lt;p&gt;這是前一陣子從 &amp;quot;Game Code Complete&amp;quot; 裡看到的演算法。&lt;/p&gt;  &lt;p&gt;說是「偽」亂數，因為它並不夠亂。但是它非常節省效能。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;需求是這樣:&lt;/p&gt;  &lt;p&gt;有某個數量的獎品，我們希望每次亂數取出一個來，不能重複，而且每個都要取到。&lt;/p&gt;  &lt;p&gt;演算法是這樣:&lt;/p&gt;  &lt;p&gt;假設獎品數量為 member，比 member 大的一個質數為 prime，&lt;/p&gt;  &lt;p&gt;首先先取三個亂數 RandomA, RandomB, RandomC&lt;/p&gt;  &lt;p&gt;計算&lt;/p&gt;  &lt;p&gt;Skip = RandomA * member * member + RandomB * member + RandomC&lt;/p&gt;  &lt;p&gt;取得 Skip 數值後，在每次需要取亂數數值時，&lt;/p&gt;  &lt;p&gt;nextNumber += Skip&lt;/p&gt;  &lt;p&gt;nextNumber %= prime&lt;/p&gt;  &lt;p&gt;也就是，每次計算時，把前一次的數值加上 Skip, 然後用這個質數來取餘數, 這樣算出來的 nextNumber 就絕對不會重複。當然餘數可能會比 member 數量還大，那就再計算一次，取下一個。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;看完之後，霎時間覺得很神奇，一時半刻還想不透，於是用試算表建公式來算，果然，產生了一個不會重複數字的序列。&lt;/p&gt;  &lt;p&gt;但是，從這序列也發現了缺點。就是取出來的數值是有某種規律的，而且規律很明顯。不過如果不把數列排出來，也不容易發現就是了。&lt;/p&gt;  &lt;p&gt;效能是這個演算法最大的優點，每次取亂數只需要一個加法跟一個取餘數的運算。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;再深入去看，這演算法還可以多做一些簡化。&lt;/p&gt;  &lt;p&gt;Skip 這個數值，只要取小於 prime，大於 0 ( 最好也不要等於 1 ) 的數值就可以，不需要取三個亂數再去加減乘除。&lt;/p&gt;  &lt;p&gt;取出的數值的規律是，從第一個取出的 nextNumber 開始，每次遞增 Skip 指定的數量，超過 prime 的時候，再回到 0 繼續算，而之所以會全部都選取到的原因，就是因為質數的特性 -- 只能被 1 與自己整除。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;這個演算法可以用在什麼地方呢?&lt;/p&gt;  &lt;p&gt;分配掉寶當然是不能用啦，這個數列太過規律了。但是任務物品的掉落倒是可以用得上，怪物的重生也可以用，適用的場合應該還不少。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/06/fake-random-number-algorism.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-8727234523492124272</guid><pubDate>Thu, 29 Apr 2010 07:31:00 +0000</pubDate><atom:updated>2010-04-29T18:35:15.748+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">遊戲雜記</category><title>Activision 把金雞母 Infinity Ward 送給 EA 的事件</title><description>&lt;p&gt;今天看到了這樣一篇新聞。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://g4tv.com/thefeed/blog/post/704273/Infinity-Ward-Employee-Group-Files-Lawsuit-Against-Activision-Over-Unpaid-Royalties-Alleges-Devs-Held-Hostage.html&quot;&gt;38 Infinity Wards employees and ex-employees file class action lawsuit&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;霎時間，還搞不清楚這到底是什麼，為什麼沸沸揚揚。&lt;/p&gt;  &lt;p&gt;於是開始Google搜索。&lt;/p&gt;  &lt;p&gt;原來 Infinity Ward 是製作 &amp;quot;決勝時刻:現代戰爭2&amp;quot;的研發公司，母公司是遊戲發行商 Activision Blizzard。&lt;/p&gt;  &lt;p&gt;現代戰爭2是2009年非常風光的一款遊戲，怎麼現在鬧出權利金跟獎金的糾紛來了?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;故事要從今年三月說起。&lt;/p&gt;  &lt;p&gt;三月初， Activision 以違約與不服從命令為由，強迫兩個 Infinity Ward 高高層離職。&lt;/p&gt;  &lt;p&gt;總裁 Jason West 與執行長 Vince Zampella。&lt;/p&gt;  &lt;p&gt;到底這兩人不服從什麼命令，沒人知道，但是猜測是說，Activision 希望他們繼續把現代戰爭繼續製作下去，做個沒完沒了。研發單位當然不肯。&lt;/p&gt;  &lt;p&gt;沒想到重演當年在 EA 的 2015工作室一樣的不爽事件。&lt;/p&gt;  &lt;p&gt;據說，那時候 2015工作室做了個很賣錢的&amp;quot;榮譽勳章&amp;quot;，EA 龍心大悅，希望他們一直做下去，把這個招牌賣到不能再賣為止。結果自然也是不太愉快，帶了幾個人，兩人投靠 Activision。&lt;/p&gt;  &lt;p&gt;只不過這次 Activision 更惡劣， 連該給的權利金與獎金，也一直扣著沒發放。&lt;/p&gt;  &lt;p&gt;大概是鬧得非常非常不高興，這兩人就離職了。&lt;/p&gt;  &lt;p&gt;然後，事件就一發不可收拾。&lt;/p&gt;  &lt;p&gt;四月中，同樣也是遊戲發行商的 EA，宣布成立了一個新的工作室，叫做 &amp;quot;Respawn Entertainment&amp;quot;，重生。並且由 Jason 與 Vince 兩位來帶領。&lt;/p&gt;  &lt;p&gt;隔天，報導說，首席設計師 Mackey McCandlish 與程式設計師 Jon Shiring 從 IW 離職，當時雖未明講，但猜也猜得到，去 Respawn 了，後來也得到了證實。&lt;/p&gt;  &lt;p&gt;這兩三週以來， IW 持續失血，老員工成雙成對的離職。人才流失就像潰堤一般，止都止不住。而且流失的人才還大部分都是菁英。首席軟體工程師 Francesco Gigliotti，首席動畫師 Mark Grigsby，首席角色動畫 John Paul Messerly，首席環境美術設計 Chris Cherubini，軟體工程師 Rayme C. Vinson，一堆的『首席』全都跑去了『重生』。&lt;/p&gt;  &lt;p&gt;Activision 在這幾週來，悄悄的進行組織重整，也開始對留下來的還忠誠的 IW 員工發放積欠的獎金跟權利金，但終究是喚不回 IW 員工的信任了，失血非但沒止住，IW 員工還給了 Activision 一個暱稱 -- &amp;quot;shit&amp;quot;。&lt;/p&gt;  &lt;p&gt;到今天，估計 IW 原先的員工已經有一半離職。Activision 調動了其他工作室的人到 IW 裡，希望維持住產品的開發運作，但想也知道，基本上起不了什麼作用。&lt;/p&gt;  &lt;p&gt;Activision 的某個高層，前幾天也辭去了職務 ( 不過還是以類似顧問的身分留著 )，沒講理由，大概是辭職以示負責。有人毒舌的說，「不會也是要去Respawn吧?」&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;故事寫到這邊。&lt;/p&gt;  &lt;p&gt;IW 的兩個頭子真正的離職原因是什麼很難說，也有人說是他們打算把現代戰爭這個招牌賣到別的發行商手上才被開除，但是會引發後面一連串的『首席』離職，Activision 也必有虧欠員工之處。我想權利金與獎金發放的太不乾脆，應該會是主因之一。&lt;/p&gt;  &lt;p&gt;不管怎麼說，這一場風波下來， EA 這個風評也不甚好的發行商，光是躺著就能撿到一整隊的金雞母，還不只是一兩隻而已。&lt;/p&gt;  &lt;p&gt;天上掉下來的會生金蛋的母雞，誰不帶回家?&lt;/p&gt;  &lt;p&gt;現在， EA 說的很漂亮了，完全不會干涉他們開發的內容，未來也會盡全力去發行遊戲...&lt;/p&gt;  &lt;p&gt;Activision 一個錯誤的決定，把白花花的美金平白的又還給了 EA。EA 應該是暗爽在心裡吧?&lt;/p&gt;  &lt;p&gt;(Update : 又看到幾篇精彩的歷史，修改了一些...)&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/04/activision-infinity-ward-ea.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-3332234117441097965</guid><pubDate>Fri, 02 Apr 2010 08:54:00 +0000</pubDate><atom:updated>2010-04-02T16:56:13.811+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">遊戲雜記</category><title>一年一度的愚人節歡樂日</title><description>&lt;p&gt;愚人節是很歡樂的日子。&lt;/p&gt;  &lt;p&gt;Blizzard 依照慣例出了好幾道搞笑的假新聞，國內的遊戲公司也有的開始玩起來了。&lt;/p&gt;  &lt;p&gt;Google 照例還是玩很大。&lt;/p&gt;  &lt;p&gt;MLB 也有一堆假新聞。&lt;/p&gt;  &lt;p&gt;今天看到一個說法是，「愚人節是 IT 產業的國定假日」。&lt;/p&gt;  &lt;p&gt;同事說，那我們應該放假一天的呀...&lt;/p&gt;  &lt;p&gt;來轉貼個&lt;a href=&quot;http://www.zdnet.com.tw/news/software/0,2000085678,20144894,00.htm&quot;&gt;歡度愚人節總整理&lt;/a&gt;好了。&lt;/p&gt;  &lt;p&gt;剛剛在 GameDev.net 上，看到 The Daily GameDev.net 編輯所寫的一段，算是最好的註解。&lt;/p&gt;  &lt;p&gt;他寫，&lt;/p&gt;  &lt;p&gt;If you&#39;re expecting news from today well, you can forget about it. I refuse to look at any headlines today because... well, if you don&#39;t know than you deserve what you get :P&lt;/p&gt;  &lt;p&gt;他「拒絕」在今天看任何的頭條新聞...&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/04/april-fool.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-6000386386541448195</guid><pubDate>Fri, 26 Mar 2010 03:16:00 +0000</pubDate><atom:updated>2010-03-26T11:16:23.131+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>My GDC 2010 (Day 5)</title><description>&lt;p&gt;GDC 最後一天。下午上完課，晚上就要到機場去，很操...&lt;/p&gt;  &lt;p&gt;Day 5&lt;/p&gt;  &lt;p&gt;第一堂課，本來要參加一個滿有意思的課程，但是，由於出發得較晚，結果因為人數已滿而進不去。( 我又要抱怨這糟糕的課程安排了... )&lt;/p&gt;  &lt;p&gt;跑去聽了一場比較另類的題目，&amp;quot;&lt;b&gt;Paint-by-Gender: How to Add Pink Gameplay to Your &#39;Blue&#39; Title (and Still Keep All the Boys Happy)&lt;/b&gt;&amp;quot;。&lt;/p&gt;  &lt;p&gt;意思是，如何讓你的遊戲可以受女生歡迎，男生也不會太反感。&lt;/p&gt;  &lt;p&gt;底下有Check-List&lt;/p&gt;  &lt;p&gt;Female-Friendly Checklist&lt;/p&gt;  &lt;p&gt;1. Detailed backstory for characters and the world&lt;/p&gt;  &lt;p&gt;2. Major female character(s), non-stereotypical&lt;/p&gt;  &lt;p&gt;3. In-game relationships, especially ones the player can affect&lt;/p&gt;  &lt;p&gt;4. Emotional moments&lt;/p&gt;  &lt;p&gt;5. Moral complexity in characters and situations&lt;/p&gt;  &lt;p&gt;6. Opportunities for non-violent action&lt;/p&gt;  &lt;p&gt;7. Gameplay variety that creates strategic options&lt;/p&gt;  &lt;p&gt;8. Important choices&lt;/p&gt;  &lt;p&gt;9. Meaningful victory condition&lt;/p&gt;  &lt;p&gt;其實說穿了，就是要多一點的Fu，少一點暴力，女性角色不要只是花瓶...&lt;/p&gt;  &lt;p&gt;第二堂課，去聽了模擬市民3，講述他們怎樣去模擬遊戲中的每個小人。&lt;/p&gt;  &lt;p&gt;感覺上就是，這是一個很龐大的資料驅動式系統，每個小人有 motives, traits, long-term progression, production rules, …&lt;/p&gt;  &lt;p&gt;還看到了一個2D Top-view，專門用來測試小人的生活狀況的測試工具...&lt;/p&gt;  &lt;p&gt;今天下午，GDC 到 1600 就結束，下午課程只有兩場。&lt;/p&gt;  &lt;p&gt;下午第一場去聽的是，&amp;quot;&lt;b&gt;The Rendering Tools and Techniques of Splinter Cell: Conviction&lt;/b&gt;&amp;quot;。&lt;/p&gt;  &lt;p&gt;內容主題好幾個，Occlusion Query, Cascaded Shadow Map ( 啊...又見到它了... ), SSAO…&lt;/p&gt;  &lt;p&gt;他們用的Occlusion Query方法，是改良過的 Hierarchical Z buffer。效果還不錯。&lt;/p&gt;  &lt;p&gt;Cascaded Shadow Map就不多說了。&lt;/p&gt;  &lt;p&gt;SSAO的部分，偷吃偷得很兇。完完全全是事先算好，甚至美術修過圖的一張貼圖，然後用類似 lightmap 的方式，計算貼圖軸後貼上去。效果沒差多少，但是效能差很多...&lt;/p&gt;  &lt;p&gt;( 我們來參加 GDC，簡直就是來觀摩各式各樣的偷吃步的... )&lt;/p&gt;  &lt;p&gt;最後一場，本來並沒有期待很多，不過卻真的有些收穫。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&amp;quot;Uncharted 2: HDR Lighting&amp;quot;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;一開場，講了很多 Gamma 曲線的東西，本來搞不懂是什麼，後來在朋友的 Blog 上看到 Gamma Correction 的觀念，才瞭解了。&lt;/p&gt;  &lt;p&gt;簡單說，美術製作的貼圖素材，所有的顏色與亮度數值，都不是線性的，而我們在 Pixel Shader 裡，卻拿這些數值去做線性運算，這中間就有誤差了。&lt;/p&gt;  &lt;p&gt;這就是人家比我們專業的地方，就是人家可以上台發表，我們只能在台下鴨子聽雷的差別。&lt;/p&gt;  &lt;p&gt;故事還沒完，Gamma Correction 之外，他們還做了所謂 Filmic Tonemapping 的修正，修正掉過亮以及過暗的地方。&lt;/p&gt;  &lt;p&gt;再來是SSAO。印象最深的，就是 &amp;quot;Who needs sphere? A box will do just as well&amp;quot;。&lt;/p&gt;  &lt;p&gt;用個盒子算AO就好啦。 ( 怎樣? 又觀摩到一個偷吃步... )&lt;/p&gt;  &lt;p&gt;最後呢，講述了他們的 Rendering Pass 架構，以及他們很自豪的最佳化的做法。不過，這部分完全是 PS3 硬體上的東西，真的是有看沒懂。&lt;/p&gt;  &lt;p&gt;( 就在那一瞬間， 四個 Cascaded Shadow Map 畫在一張貼圖上的畫面，又閃過在我眼前... )&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;THE END&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/03/my-gdc-2010-day-5.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-2902972569541915267</guid><pubDate>Mon, 22 Mar 2010 06:22:00 +0000</pubDate><atom:updated>2010-03-22T14:22:13.990+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>My GDC 2010 (Day 4)</title><description>&lt;p&gt;GDC 的講題，分成幾類，程式、美術、設計、製作等等，參加 GDC 的人也算是各領域的人都有了。不過，有點要注意的是，可以的話，最好不要跑到別人的場子去。&lt;/p&gt;  &lt;p&gt;例如昨天 Blizzard 的場子就是程式領域的，所以，當程式人聽到這麼重要的 Hotspot 分析工具， Designer 卻覺得 &amp;quot;not so valuable&amp;quot; 的時候，底下會響起一片 &amp;quot;你們真是不識貨啊&amp;quot; 的笑聲。&lt;/p&gt;  &lt;p&gt;不過程式人在美術人的場子裡也好不到哪裡去。根據我們美術同事轉述，以下是演講人講述在他們公司裡的對話:&lt;/p&gt;  &lt;p&gt;美術 : 「這個功能可以做嗎?」&lt;/p&gt;  &lt;p&gt;程式 : 「不行」&lt;/p&gt;  &lt;p&gt;美術 : (中指)&lt;/p&gt;  &lt;p&gt;程式 : (當作沒看見)&lt;/p&gt;  &lt;p&gt;美術 : (遞...)美鈔&lt;/p&gt;  &lt;p&gt;程式 : (眼睛上全是Dollar Sign)&lt;/p&gt;  &lt;p&gt;「兩天後，我們有了這個酷功能...」&lt;/p&gt;  &lt;p&gt;( 類似的故事好像有發生在我跟我的美術好友 Louis 的身上，不過我當然是不記得的啦... )&lt;/p&gt;  &lt;p&gt;Day 4&lt;/p&gt;  &lt;p&gt;一大早參加的課程是由冰島的 CCP (做 EVE 的那家公司)演講的題目，&amp;quot;&lt;strong&gt;Code and Complexity: Managing EVE&#39;s Expanding Universe&lt;/strong&gt;&amp;quot;，演講人是個金髮正妹的程式設計師，大清早看見金髮正妹的同行，一整個讓人神清氣爽啊...&lt;/p&gt;  &lt;p&gt;好吧，內容。&lt;/p&gt;  &lt;p&gt;內容是，EVE Online 營運了七年下來，他們怎麼去控制程式的各種版本，各種狀況。版本控制方面，用了四條 Stream—Dev, Stage, Release, Hotfix，沒有很多的分支。程式碼方面，有幾個重要的點,&lt;/p&gt;  &lt;p&gt;Think ahead – simple, clear, and clean&lt;/p&gt;  &lt;p&gt;Follow a coding standard&lt;/p&gt;  &lt;p&gt;Think big – optimize&lt;/p&gt;  &lt;p&gt;Think carefully&lt;/p&gt;  &lt;p&gt;Balance features vs. technical debt&lt;/p&gt;  &lt;p&gt;很重要的就是，不要去標新立異，寫一堆別人很難看懂的 Code，也不要去做一些技術性很高，但沒什麼用途的東西。&lt;/p&gt;  &lt;p&gt;接著下一場，全會場只有一堂課程，就是 Sid Meier 的演講。大製作人，所以逼著全部的人都要去聽。我就不多寫了，同行的 Designer 說，沒什麼新鮮的。&lt;/p&gt;  &lt;p&gt;下午第一場，聽的是&amp;quot;&lt;b&gt;Streaming Massive Environments from 0 to 200 MPH&lt;/b&gt;&amp;quot;，講的是他們的賽車遊戲，如何將賽道 Streaming。&lt;/p&gt;  &lt;p&gt;用了很多的技巧，似乎是能節省時間的技法全都用上了。LOD, 貼圖壓縮, 甚至連 Disk I/O Cache 都考慮進去了。因為有這樣的需求，所以他們自己發展了一套 Pipeline 工具。&lt;/p&gt;  &lt;p&gt;也算是很猛的啦...&lt;/p&gt;  &lt;p&gt;接著呢，不小心選到一場地雷課。聽了十分鐘就跑出來了。可是課程的安排很糟糕，又沒別的課好去，所以就又去微軟講 Windows Phone 7 的場子裡，看看還有沒有禮物可拿...&lt;/p&gt;  &lt;p&gt;本日最後一場，走到了 Intel 的場子，聽聽有沒有什麼多緒的新概念。&lt;/p&gt;  &lt;p&gt;不多。&lt;/p&gt;  &lt;p&gt;新的 Windows 作業系統裡好像有個 Slim reader/writer locks 和 Condition variables，據說比 Critical sections 還要節省資源，可以找天來試試看到底是什麼東西。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/03/my-gdc-2010-day-4.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-4153551945426961062</guid><pubDate>Sun, 21 Mar 2010 03:06:00 +0000</pubDate><atom:updated>2010-03-21T11:06:02.452+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>My GDC 2010 (Day 3)</title><description>&lt;p&gt;現在開始進入正式的 Main Conference。&lt;/p&gt;  &lt;p&gt;Day 3&lt;/p&gt;  &lt;p&gt;第一場重頭戲，就是 Blizzard 的 keynote 。鐵定會爆滿，所以我們早早就從飯店出發到會場去排隊。&lt;/p&gt;  &lt;p&gt;題目是 &amp;quot;&lt;strong&gt;Designing for Performance, Scalability &amp;amp; Reliability: StarCraft II&#39;s Approach&lt;/strong&gt;&amp;quot;&lt;/p&gt;  &lt;p&gt;一開場，先講幾個 Blizzard 的 Core Value。&lt;/p&gt;  &lt;p&gt;Gameplay first – the “invisible” tech. ( 這個尤其重要，所以放在第一個... )&lt;/p&gt;  &lt;p&gt;Think globally – games are global&lt;/p&gt;  &lt;p&gt;Commit to quality – we are all QA&lt;/p&gt;  &lt;p&gt;接下來，展示了 StarCraft II 的 Performance 分析工具。是的，這一場演講的最主要主題，就是 Blizzard &amp;quot;自己做&amp;quot; 的效能分析工具。雖然是自己做的，但是功能絕不輸專業的分析工具。&lt;/p&gt;  &lt;p&gt;( 後來想到，你們就是因為自己做這個工具，才會讓遊戲 Delay 這麼久吧? )&lt;/p&gt;  &lt;p&gt;B社抱持的想法其實也不是沒道理，因為第三方的效能分析工具很難做到即時的分析，換句話說，即使有很多分析的資料，但是依然沒辦法跟遊戲畫面或狀況結合起來，對於分析效能來講，效果總是打了折扣。&lt;/p&gt;  &lt;p&gt;所以我們就看見了，在 StarCraft II 的遊戲畫面上又多了一層效能分析的 Layer ，所有的分析曲線都能夠顯示在上面。&lt;/p&gt;  &lt;p&gt;程式團隊還另外做了一個分析地圖 Hotspot 的工具，可以讓 Designer 了解地圖的效能狀況。有人問，這東西 Designer 覺得怎樣，答案是 : &amp;quot;Not so valuable…&amp;quot;&lt;/p&gt;  &lt;p&gt;接下來，就像我之前說的，因為課程時段安排的很糟糕，我又多出了很多時間。&lt;/p&gt;  &lt;p&gt;於是跑去聽了一場主題是 &amp;quot;&lt;b&gt;The AI of BioShock 2&lt;/b&gt;&amp;quot; ，內容是跟製作流程相關的演講。&lt;/p&gt;  &lt;p&gt;幾個重點:&lt;/p&gt;  &lt;p&gt;Less document, more prototype&lt;/p&gt;  &lt;p&gt;Don’t over concept &amp;amp; over document&lt;/p&gt;  &lt;p&gt;Prototype early&lt;/p&gt;  &lt;p&gt;Prove features before enter production&lt;/p&gt;  &lt;p&gt;Work iteratively as a group&lt;/p&gt;  &lt;p&gt;下午，時間還是很多，所以到底下的展場晃了很久，看了一些有興趣的攤位。&lt;/p&gt;  &lt;p&gt;下午的最後一場，跑到了戰神III的課程去聽。主題是戰神III的影子。&lt;/p&gt;  &lt;p&gt;Cascade Shadow Map。&lt;/p&gt;  &lt;p&gt;對，又是它。&lt;/p&gt;  &lt;p&gt;也許是PS3的運算比較快，記憶體比較小的關係，這裡的 CSM 運算，跟PC上的運算有些不同，但基本理論跟演算是一樣的。&lt;/p&gt;  &lt;p&gt;而戰神III也另外做了一些最佳化的處理，減少運算量，這部分，PC上倒是也可以應用的。&lt;/p&gt;  &lt;p&gt;簡單講，兩個偷吃步。&lt;/p&gt;  &lt;p&gt;看不見的不要算&lt;/p&gt;  &lt;p&gt;看不清楚的也不要算&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/03/my-gdc-2010-day-3.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-5215604702470364784</guid><pubDate>Thu, 18 Mar 2010 08:35:00 +0000</pubDate><atom:updated>2010-03-18T16:35:55.619+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>My GDC 2010 (Day 2)</title><description>&lt;p&gt;今年的GDC是在 3/9 至 3/13 ，所以我現在寫的是回憶錄...XD&lt;/p&gt;  &lt;p&gt;Day 2&lt;/p&gt;  &lt;p&gt;早上還是待在微軟的場子裡，聽了兩堂關於 DirectCompute 以及 Tessellation 的課程。&lt;/p&gt;  &lt;p&gt;DirectCompute 主要在介紹 Compute Shader 的使用( 對..今天也還是Tutorial.. )，重點在於，Compute Shader 本身就是為了做平行化計算而生的，所以各式各樣我們在做平行化、多執行緒的程式所需要考慮到的問題，例如Shared Memory, Atomic Operation...等等，都在這裡一一出現。&lt;/p&gt;  &lt;p&gt;平行處理始終是個大課題啊...&lt;/p&gt;  &lt;p&gt;在 HDR 計算時，可以將平均亮度的計算拉到 Compute Shader 來做，這算是很好的應用了。&lt;/p&gt;  &lt;p&gt;DirectCompute 是 DX11 的規格，不過某些 DX10 顯卡已經有 Compute Shader 可用，DX10 也有函式可以呼叫來使用說。&lt;/p&gt;  &lt;p&gt;Tessellation 課程的演講人是個華人，他說大部分的 DX SDK Sample 都是他寫的。&lt;/p&gt;  &lt;p&gt;這個課程的主題，就是介紹幾個 Tessellation 的 Sample，每個 Sample就解說一下做法，然後把範例跑一跑，還不算太無聊。&lt;/p&gt;  &lt;p&gt;範例咧，在 Dx11 的 SDK Sample 裡都有。&lt;/p&gt;  &lt;p&gt;下午，微軟的課程就走到即將發表的 Windows Phone 7 作業系統上了，所以我就先到了 iPhone 的場子去。iPhone 有一場很有意思的講題 -- &amp;quot;如何讓你的 iPhone App 保持 Apple Store 的排名上&amp;quot;。&lt;/p&gt;  &lt;p&gt;答案就是，跟我們的MMO要保持在遊戲社群網站排名的手法一樣...&lt;/p&gt;  &lt;p&gt;持續的做更新&lt;/p&gt;  &lt;p&gt;節慶的時候出個更新做 in-game 活動&lt;/p&gt;  &lt;p&gt;網站上面弄點相關新聞&lt;/p&gt;  &lt;p&gt;官方人員有事沒事在社群網站上放點消息，跟玩家溝通&lt;/p&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;p&gt;MMO Game, Mobile Game, Social Game, ... 只要是在網路上玩、網路上營銷的遊戲，操作手法都極為相似啊...&lt;/p&gt;  &lt;p&gt;下午最後一堂課，又回到了微軟的場子裡，聽聽 Windows Phone 7 這個系統。&lt;/p&gt;  &lt;p&gt;微軟打算把這個系統跟 XBox Live, Windows Live Games 結合起來，然後把 Apple Store 的功能、Facebook 的社群功能全部包在這裡面...&lt;/p&gt;  &lt;p&gt;換句話說，就是整碗捧去啦...&lt;/p&gt;  &lt;p&gt;一天結束，有始有終，又填了一份問卷，又拿了一件微軟 T-Shirt&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/03/my-gdc-2010-day-2.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9004261571334633871.post-6445229291190218952</guid><pubDate>Wed, 17 Mar 2010 02:33:00 +0000</pubDate><atom:updated>2010-03-17T10:33:43.963+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">程式雜技</category><title>My GDC 2010 (Day 1)</title><description>&lt;p&gt;到了會場後的第一個感覺，就是規模縮小了。&lt;/p&gt;  &lt;p&gt;過去兩年都使用了西、南、北三個館，今年只剩下了南北兩個館做為會場。&lt;/p&gt;  &lt;p&gt;課程變少了，而且課程的安排很糟糕，常常會是，要不是這個時段沒課可上，就是想上的課衝堂衝很嚴重。例如，有個時段 Program Track 的課，只有兩堂，而另外有個時段，Program Track 的課少說有八九堂，其中NVidia跟AMD還各佔了一堂課，這是怎樣? 逼我們選邊站嗎?&lt;/p&gt;  &lt;p&gt;GDC五天，前兩天是 Tutorial &amp;amp; Summit 的課程，後三天才是正題 Main Conference。&lt;/p&gt;  &lt;p&gt;Day 1&lt;/p&gt;  &lt;p&gt;一整天待在微軟的場子裡。&lt;/p&gt;  &lt;p&gt;一入場，微軟就先發個筆、筆記紙、還有投影片檔的 CD ( 省得裡頭的人拼命把投影片拍照... )&lt;/p&gt;  &lt;p&gt;一開始，題目是VC 2010。&lt;/p&gt;  &lt;p&gt;有點鳥。&lt;/p&gt;  &lt;p&gt;不過，聽到一個很奇特的東西，&amp;quot; Move Constructor &amp;quot;。&lt;/p&gt;  &lt;p&gt;回頭翻光碟片，google了一下，原來這是C++的新規格，號稱 C++0x。VC 2010會支援全套的C++0x規格。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www2.research.att.com/~bs/C++0xFAQ.html&quot;&gt;C++0x FAQ&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Move Constructor 可以處理掉某些效能上的問題，應該是個頗實用的東西。&lt;/p&gt;  &lt;p&gt;接下來聽到的是，xperf的介紹。&lt;/p&gt;  &lt;p&gt;這是一套效能分析的工具組， Windows Performance Toolkit ，功能很強大。甚至能夠收集處理Disk I/O, seek time, content switch的資料。&lt;/p&gt;  &lt;p&gt;找時間要抓來瞧瞧。&lt;/p&gt;  &lt;p&gt;接著下午聽了一個重頭戲， Cascade Shadow Map 。&lt;/p&gt;  &lt;p&gt;只不過裡頭的內容，早就發表在 MSDN 上了。微軟還是有點混。&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ee416324%28VS.85%29.aspx&quot;&gt;Common Techniques to Improve Shadow Depth Maps&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Cascade Shadow Map 在當前，基本上已經成為影子計算的最佳解法了， God of War III 用到它，Uncharted 2 也用到它，更不要說PC上的遊戲了，WOW已經用了，你要不要跟進咧?&lt;/p&gt;  &lt;p&gt;微軟一天的課程結束，把問卷填一填，換了一件 T-Shirt。還滿好穿，不過就是大了點。&lt;/p&gt;  </description><link>http://lancelotdiary.blogspot.com/2010/03/my-gdc-2010-day-1.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item></channel></rss>