網誌

【程式設計】【C#】【遊戲設計】馬力歐跳跳跳

【素材下載】

在遊戲進行時,當玩家按了空白鍵或上鍵,可以讓馬力歐角色往上跳,到頂後落地。

為了要完成這樣的動作,我們把「馬力歐角色往上跳,到頂後落地」這個動作用計時器元件來完成,將計時器元件拖曳至表單:

下一步,在計時器的Tick事件處理函式中處理馬力歐的跳躍動作:

int 角色移動量 = 15; 
private void timer1_Tick(object sender, EventArgs e)
{
    角色.Top -= 角色移動量; //向上移動,也就是往上跳的意思
    if (角色.Top < 50) 角色移動量 = 0 - 角色移動量; //當馬力歐跳到頂時,將角色移動量變負,使得馬力歐往下移動,也就是落地

    if (  (角色.Top +角色.Height + 20) > 遊戲背景.Height ) {  //當馬力歐腳著地時…,20是地上磚塊的高度              
        角色移動量 = 0 - 角色移動量; //著地時,轉變移動的方向
        timer1.Enabled = false; //計時器timer1關閉
    }
}

計時器每跳一次(一個滴答),讓馬力歐以垂直的方向移動,往上是將其Top進行減的動作,往下則是將其Top進行加的動作。

我們設置一個到頂的位置為50,當馬力歐這個角色的元件位置(Top)一直減到小於50時,表示到頂,要進行落地的處理。

落地的處理只要將角色移動量變個號就行了…

然後,落地後,就關閉掉計時器,表示停止移動。

以上是計時器處理馬力歐角色跳與落地的想法與程式作法。

接下來,就是判斷是否按了空白鍵與上鍵,是的話,就啟動計時器,由計時器每隔一段時間,進行馬力歐的垂直移動,以完成跳躍與落地的連續性動作。

if (e.KeyCode == Keys.Space || e.KeyCode == Keys.Up) //按下空白鍵或上鍵的時候…
{
    timer1.Enabled = true;     //計時器timer1打開,由計時器來負責馬力歐的跳躍與落地的位置變換
}

整支程式列表如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MarionRunRunRun
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            角色.Parent = 遊戲背景;  //將角色圖片方塊的Parent屬性設為遊戲背景圖片方塊,Parent表示上一層,父層…
            遊戲背景.BackColor = Color.Transparent; //將戲背景的BackColor設為透明,
        }

        int 移動量 = 10;

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Right && 遊戲背景.Left > (this.ClientSize.Width - 遊戲背景.Width)) //按了右鍵的話 而且 …
            {
                角色.Location = new Point(角色.Location.X + 移動量, 角色.Location.Y); //一旦角色的Parent屬性設為遊戲背景圖片時,角色圖片會跟著跑,因此,需要進行水平位置的移動,使得角色保持中間位置
                遊戲背景.Left -= 移動量; //背景向左                       
            }
            if (e.KeyCode == Keys.Left && 遊戲背景.Left < 0) //按了左鍵的話 而且 遊戲背景.Left 超過 畫面左邊的情況下
            {
                角色.Location = new Point(角色.Location.X - 移動量, 角色.Location.Y);
                遊戲背景.Left += 移動量; //背景向右                
            }
            if (e.KeyCode == Keys.Space || e.KeyCode == Keys.Up) //按下空白鍵或上鍵的時候…
            {
                timer1.Enabled = true;     //計時器timer1打開,由計時器來負責馬力歐的跳躍與落地的位置變換
            }
        }

        int 角色移動量 = 15; 
        private void timer1_Tick(object sender, EventArgs e)
        {
            角色.Top -= 角色移動量; //向上移動,也就是往上跳的意思
            if (角色.Top < 50) 角色移動量 = 0 - 角色移動量; //當馬力歐跳到頂時,將角色移動量變負,使得馬力歐往下移動,也就是落地

            if (  (角色.Top +角色.Height + 20) > 遊戲背景.Height ) {  //當馬力歐腳著地時…,20是地上磚塊的高度              
                角色移動量 = 0 - 角色移動量; //著地時,轉變移動的方向
                timer1.Enabled = false; //計時器timer1關閉
            }
        }
    }
}

 

 

課外補充

按下空白鍵…,要如何防止再次進行空白鍵的處理? 一個作法就是設置一個旗標isPressed,初值為false,進入空白鍵的判斷加上這個旗標必須為false,當進入空白鍵處理時,立刻設此旗標為true,防止再次進入。

在另一個事件KeyUp,將這個旗標設為false…

private bool isPressed = false;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if(e.KeyCode == Keys.Space && !isPressed )
    {
        isPressed = true;
        // do work
    }
}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
    if (isPressed )
        isPressed = false;
}

 

【程式設計】【C#】【遊戲設計】利用背景捲動實現遊戲場景的動態變化

馬利歐遊戲大概是最家喻互曉的遊戲了:

一般來說,遊戲由靜態的元素與動作組成:

遊戲的靜態元素:

  1. 角色
  2. 場景
  3. 阻礙物、暗樁
  4. 敵人(魔王)
  5. 蘑菇 (好、壞)

遊戲的動態元素

  1. 角色的移動、奔跑
  2. 魔王的移動、奔跑

我們要如何做這樣的遊戲呢?

我們先參考這些紙板遊戲:

一、要開始製作遊戲,我們要有角色、背景材料,所幸下面網站提供了絕佳的製作材料:

  • 遊戲資源,背景圖、角色圖(動作分解圖)、音效等遊戲資源

我們從上面的資源來準備我們要的圖、音效檔。

下載圖片,並用小畫家(或其他繪圖軟體,例PhotoShop)處理圖片,剪下需要的部份。

若圖片需要去背處理(去掉白色/其他顏色背景),在線上搜尋”線上去背”網站來處理去背的工作。

二、接下來,我們開始設計程式,開啟Visual C#。

加入PictureBox元件放置背景圖片

指定Image,載入背景圖片

設定Location為(0,0),讓PictureBox置於Form1左上角。

設定SizeMode為”AutoSize”,讓PictureBox自動設定大小為載入圖片的大小。

加入PictureBox元件放置角色圖片

指定Image,載入角色圖片,角色圖片必須為去背景圖片,才能融入背景畫面。

設定SizeMode為”StretchImahe”,讓角色圖片自動縮放為PictureBox元件的大小。

畫面如下:

此時,角色圖片雖為去背圖片,但是並未融入背景,嗯,我們要在程式加上二條指令:

private void Form1_Load(object sender, EventArgs e)
{
    角色.Parent = 遊戲背景;  //將角色圖片方塊的Parent屬性設為遊戲背景圖片方塊,Parent表示上一層,父層…
    遊戲背景.BackColor = Color.Transparent; //將戲背景的BackColor設為透明,
}

執行時,畫面就能變成完美的遊戲畫面了:

三、接下來,我們要處理奔跑的動作

我們觀察馬利歐遊戲的動作發現,馬利歐的移動分成二個部份,慢速移動與快速移動,當慢速移動時(走),是角色在畫面中移動,當快速移動時(跑),角色固定在螢幕中間,以背景左右移動的方式,產生角色奔跑的效果。

在這邊,我們要處理當玩家按了左鍵與右鍵的對應動作,當玩家按左鍵,我們移動背景圖片向右(與角色動作相反方向),產生角色向左跑的效果;當玩家按右鍵,我們移動背景圖片向左,產生角色向右跑的效果。

背景圖片向右就是將背景圖片的Left屬性加一個固定大小的移動值,比如5(要快一點的話,增量為10)。

背景圖片向左就是將背景圖片的Left屬性減一個固定大小的移動值,比如5(要快一點的話,減量為10)。

OK,了解整個動作的大概後,我們來加上程式碼在表單的KeyDown事件。

int 移動量 = 5;

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Right) //按了右鍵的話
    {
        角色.Location = new Point(角色.Location.X + 移動量, 角色.Location.Y); //一旦角色的Parent屬性設為遊戲背景圖片時,角色圖片會跟著跑,因此,需要進行水平位置的移動,使得角色保持中間位置
        遊戲背景.Left -= 移動量; //背景向左                       
    }
    if (e.KeyCode == Keys.Left) //按了左鍵的話
    {
        角色.Location = new Point(角色.Location.X - 移動量, 角色.Location.Y);
        遊戲背景.Left += 移動量; //背景向右                
    }
}

上面程式也同時處理角色的移動,原因是一旦角色的Parent屬性設為遊戲背景圖片時,角色圖片會跟著跑,因此,需要進行水平位置的移動,使得角色保持中間位置。

上面的程式,尚未處理背景捲動時,左右二邊的狀況:

因此,下面的程式處理了二邊的狀況:

int 移動量 = 10;

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Right && 遊戲背景.Left > (this.ClientSize.Width - 遊戲背景.Width)) //按了右鍵的話 而且 …
    {
        角色.Location = new Point(角色.Location.X + 移動量, 角色.Location.Y); //一旦角色的Parent屬性設為遊戲背景圖片時,角色圖片會跟著跑,因此,需要進行水平位置的移動,使得角色保持中間位置
        遊戲背景.Left -= 移動量; //背景向左                       
    }
    if (e.KeyCode == Keys.Left && 遊戲背景.Left < 0) //按了左鍵的話 而且 遊戲背景.Left 超過 畫面左邊的情況下
    {
        角色.Location = new Point(角色.Location.X - 移動量, 角色.Location.Y);
        遊戲背景.Left += 移動量; //背景向右                
    }
}

參考:

Part 1 – Movements – http://www.youtube.com/watch?v=Cc62S6…

Part 2 – Jumping – http://www.youtube.com/watch?v=X1lfRI…

Part 3 – Collision – http://www.youtube.com/watch?v=vBT5Gl…

Part 4 – Character Design – http://www.youtube.com/watch?v=EMOpp1…

「網站日誌」- 從192.192.246.169(獨立主機)轉移至wells.fgchen.com(虛擬主機)

2018/2/16 (農曆春節1/1)

心血來潮,將Wordpress從一台主機移到另一台主機(之前想做沒做,把原本獨立主機再挪出來另作他用),步驟:

  1. 將Wordpress網站建立tar ball,  tar -xvf wp.tar ./wp/8
  2. 使用wget,將網站tar檔複製到新位置
  3. 解tar ball
  4. 將資料庫中所有的表格以SQL方式匯出,檔案太大,則進mysql,以soruce wp.sql方式進行匯入。

如果Domain URL不變的話,問題比較單純,底下是url變更下的處理方式:

UPDATE wp_options SET option_value = replace(option_value, 'http://www.oldurl', 'http://www.newurl') WHERE option_name = 'home' OR option_name = 'siteurl';

UPDATE wp_posts SET guid = replace(guid, 'http://www.oldurl','http://www.newurl');

UPDATE wp_posts SET post_content = replace(post_content, 'http://www.oldurl', 'http://www.newurl');

UPDATE wp_postmeta SET meta_value = replace(meta_value,'http://www.oldurl','http://www.newurl');

出現404 not found, 接著處理.htaccess,變更目錄 (由舊目錄改成新目錄)

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /wp
    RewriteRule ^(.*\/)?w3tc_rewrite_test([0-9]+)/?$ $1?w3tc_rewrite_test=1 [L]
    RewriteCond %{HTTP:Accept-Encoding} gzip
    RewriteRule .* - [E=W3TC_ENC:_gzip]
    RewriteCond %{HTTP_COOKIE} w3tc_preview [NC]
    RewriteRule .* - [E=W3TC_PREVIEW:_preview]
    RewriteCond %{REQUEST_METHOD} !=POST
    RewriteCond %{QUERY_STRING} =""
    RewriteCond %{REQUEST_URI} \/$
    RewriteCond %{HTTP_COOKIE} !(comment_author|wp\-postpass|w3tc_logged_out|wordpress_logged_in|wp
    RewriteCond "%{DOCUMENT_ROOT}/wp/wp-content/cache/page_enhanced/%{HTTP_HOST}/%{REQUEST_URI}/_in
    RewriteRule .* "/wp/wp-content/cache/page_enhanced/%{HTTP_HOST}/%{REQUEST_URI}/_index%{ENV:W3TC
</IfModule>
# END W3TC Page Cache core
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>

舊網站Wiki也搬移完畢!
https://fgchen.com/wiki

下關鍵字:cpanel performance tuning找到一堆效能調整文章,確有成效!

富國實驗室專題生-完全求生手冊

本文有感於我實驗室裏越來越多同學在學長姐不當的經驗傳授下,總以為專題混混就可以畢業,從來不給老師看專題整體成果,把老師當成橡皮圖章,時間到了,老師簽個名,專題就完成了,為免於誤會越來越大,特撰寫本文,請現在正在進行專題的同學,務必熟讀,並勞記於心,徹底執行。

專題是一個相當重要的實務訓練,好的專題經驗,可以帶給同學好的工作場合求生技能,也能在升學時,博得面試時,好的成績,同學務必謹慎對待。

一般來說,專題工作是一個創作型態的工作,因為有其創新的成份在,並不會有現成且一模一樣的東西可以參考,然而,天下的事情,也不是全然都沒有關聯,絕大部份的工作都有其相似的成份,這個創新的部份,就是在訓練我們在未來面對未知的問題,以有效率的方式找出當時的最佳解決,也就是,我們要解決未知的問題,從中建立起解決問題的能力。

以前,念博士班時,為了要能畢業,要從荊棘中殺出一條路來,看了很多資料,做了很多事,整個過程非常痛苦,生活中,常活在驚恐中,常有惡夢。雖然,指導老師會給方向,指導做研究的方法,但絕大部份要靠自己去做,自己歸納分析出求生之道,在做研究的所建立的能力,也就成為日後在社會工作賴以生存的技能。

清大彭明輝教授於是出了一本書,給所有的研究生一個該如何在研究叢林殺出血路的指導方針:

  • 研究生完全求生手冊:方法、秘訣、潛規則 – 彭明輝
用別人的智慧,解決自己的問題 這本書談研究生所需要知道的研究方法,包括文獻回顧、批判性思考和創新的策略——它們的步驟、要領、秘訣與潛規則。它把研究工作分成十五個步驟,並以十六章的篇幅依序討論每一個研究步驟的方法與要領,從時程的安排、選指導教授、選題目、文獻回顧、彙整批判性思考、創新的策略,以及研究的構想與規劃等,直到論文寫作與口試。 我曾把其中一小部分內容寫成〈學術文獻回顧與分析的程序與技巧〉,這篇文章傳遍海峽兩岸,網路上未經同意的轉載不計其數;北京四大高校的博士生為它舉辦了一次跨校討論會,一個學術研討會將它印給全體與會者。交通大學圖書館連續兩年邀我演講並錄影,很多實驗室都把這錄影帶列為「新生必看」。彭明輝

重點來了,本實驗室的求生術:

  • 不要在deadline前趕進度:專題是要逐日逐週逐月逐季逐學期的工作來精進,是時刻的工作,千萬不要等到deadline時,才急急忙忙把東西趕出來,通常這種趕出來的東西,不能看,品質極其低落,而且,在deadline前,指導老師沒時間改,即便是有時間改,團隊也沒時間修改;而且,修改,也不是一次的事,改個數次,也是極其自然的事,做一個負責任的個體,要學習管理時間,管理進度,管理工作,管理他人…。

 

各位專題同學千萬不要有下圖這種狀況:

 

圖出處:https://s314.siliconimg.com/kb/content_images/2013/01/18/112626/1358485484_633.jpg

專題是一種創作的過程,下圖說到,一個創作的工作過程是在東搞西搞中完成的。

「東搞西搞」原英文稿為fuck off,意思是叫人滾開,大意是我正處於高度專注工作中,不要吵我!

在接近截止日(deadline,死線)前會開始驚恐,然而,因為平時已經東搞西搞一堆東西 (當然都跟創作的東西有關),不難從這些工作整理出一個最好的組合結果,當成結案報告,而不是像上圖那樣,平時都沒在做,在接近deadline前才開始產生成果,只是,這樣的成果,通常,只是單一的,急就章的…,品質很差!

上圖來源:  https://fsv.cmoney.tw/cmstatic/notes/capture/475673/20170208171513827.jpg

適度的拖延,是「創意」的來源! 沃頓商學院教授在TED上說,如果想成為一個創意型人才,你需要有適度的拖延。

專題一旦啟動,就要像上圖那樣時時「東搞西搞」,永遠要將deadline掛在心上,事情到最後,是在驚恐中,把之前東搞西搞的工作中所得到的成果加以統整出一個像樣的結果來,也就是說,在東搞西搞的過程中,你應該不會只有得到單一個結果,到最後,把這些結果合理的變成最終的一個報告!

  • 專題工作是高投入性工作:社團活動及工讀以不影響到學業為原則,本實驗室無法接受那些工讀或社團活動佔個人生活一半以上的成員。
  • 週工作報告:每個人都要整理相關的工作記錄到週工作報告中,不要以為老師平時都沒在關心各位的專題工作,不要以為專題要meeting時,才需要進行個人的工作報告,不要以為躲在團體後面,就可以混完一個專題。本實驗室的週工作報告檔案放在老師開放的onedrive文件夾,每個專題一個獨立的文件目錄,所有組員在各自的專題目錄下,再建立一個個人的週工作報告目錄(以自己姓名為目錄名),在線上放檔案,有一個很重要的特微,檔案有建立的日期,方便我們檢核檔案的日期,不會有讓各位趁亂補文件的空間,養成寫工作週記/日記的習慣,為自已的工作建立好的工作歷史記錄,最後,寫報告就是一件簡單的整理工作。
  • 記錄與管理意見:在專題過程中,老師或其他人會給意見或看法,務必要記下來 ,也就是同學要養成做筆記的習慣,随時準備一本小冊子跟筆放在口袋或包包,隨時登記,習於用智慧型手機的同學,可用筆記軟體,隨時記錄,例如Google的Keep,與老師或其他形式的各種開會,一定要記錄記錄意見 ,不要只是一個人在記,會議中,有可能針對某位同學的指示,並且將意見填入週工作報告中,進行管理、考核!
  • 組長與組員責任:組長必須負起與老師間的溝通 (組員也可直接找老師),組員要關心彼此組員的狀況,組員若不能配合專題的工作,要好好勸他,大家是一個團隊,一定要合作無間,若溝通無效,只能請他另尋他處,千萬不要因為某些組員沒做好,而影響整組的工作。
    我只要沒公出,只要在學校,辦公室的門都會開著,隨時可來和老師討論,閒聊也行,我不會高高在上,我喜歡你們時時來聊。如果你的組員有「那些年我們遇過的七種崩潰雷組員」此文所說的任一特徵,苦勸無效,執迷不悟,請立即「揮淚斬馬謖」,否則,團隊只會走向毀滅!
  • 專題工作所需環境、工具、方法與資源:
    • 弘光Office 365:https://www.hk.edu.tw/app/super_pages.php?ID=pages12
      圖資中心已申請「微軟Office365校園版」供全校師生使用,登入網址為:https://portal.office.com/ ,請輸入您的帳號@uspace.hk.edu.tw ,密碼請輸入您的「單一入口密碼」,忘記密碼或不能登入,請洽圖資中心王文瑋#2363,謝謝~弘光科大圖資中心
    • 溝通工具:我所有的專題在Facebook社群 (請組長確認所有組員都已加入),各自專題在Line社群,所有在上面的討論要進行記錄管理。
    • 線上共享文件夾 (雲端硬碟):Office 365 Onedrive及其應用程式 (可在自己的硬碟產生同步資料夾,直接開啟本地端文件編輯),我們團隊要共同編輯專題的所有型式文件,最好的方式,使用雲端硬碟,OneDrive的好處是直接可以微軟的Office文件,格式不會跑掉。
    • 報告撰寫:使用Word,最好是2016版 (可和我們使用的Office 365完美整合)。
    • 計畫工作管理:Office 365 Planner。
    • 個人工作 (To-Do)管理:在Android上,我使用Wunderlist App,或使用Microsoft Launcher (起動器,用來取代手機預設的桌面啟動器)中的To-Do。
    • 個人行事曆管理:我使用Google的行事曆,此行事曆可用來組織團隊的行事曆,可同步大家開會的時間、報告繳交之類的事件。
    • 系統相關圖形:架構圖、ER圖、組織圖、流程圖等,使用Office Visio。
    • 文獻管理:EndNote (本校圖書館有買授權)
    • 雛形發展:Axure RP,用來發展系統的概念。
    • 程式設語言:C#,開發Windows、Web或App應用,C++開發Arduino單晶片控制版,App Inventor開發高階的App (不牽涉到底層)。
    • 程式語言開發工具:C# -> Visual Studio, Arduino C++ -> Arduino IDE, App Inventor-> JDK7/8。
    • 美工與介面:Adobe Illustrator
    • 影像處理:Adobe Photoshop
    • 3D建模:DesignSpark Mechanical (簡易上手、製作簡單模型) 、Autodesk Fusion 360 (著色、動作模擬、爆炸圖…,專業且教育版免費)。
    • 3D列印:實驗室有Prius i3、3塔 (dealta-bot)、Box三種型態的列印機,有使用需求的同學,要同我一起維護這些印表機,平時就要學習使用與維護3D印表機,不要等到要印了,才發現機器不能用,設備是我無償提供的,平時使用有問題,我會教同學如何解決問題(維護機器)。
    • 桌上型CNC:支援金屬切割。
    • 雷射切割/雕刻機:此機器本實驗室有,不過這機器有危險性,不開放任意使用。
    • 行銷網站架設:針對那些要以3D商品開發與行銷的專題,使用WordPress與Woo-commerce(有獨立的套件,不需要WordPoress)。
    • 拍照與攝影:實驗室有單眼數位相機、Sony DV
    • 資料來源:Google搜尋
    • 資源:專題進行中,若需要一些資源,實驗室有的話,由實驗室提供,若沒有的話,專題本身有經費,自行購入,沒有,再和老師討論,一是老師出,二是學校有各種計畫可申請。

做專題的一個重要意義就是十八般武藝樣樣都要學,學習解決問題的能力,培養堅持的毅力,要耐得住寂寞,別人在打games,跟妞/哥泡在一起時…,泡妞不在一時,打games也不急於一時 (周杰倫未成名前,有沈迷於電玩嗎?)。

美國影集「新聞編輯室」精彩開局:解決問題的第一步,是認知問題的所在!此影片片段戳破大家的認知,我們要好好看清自己,及所處環境的問題。

下定決心改變自己!墊底到前段的辣妹:

【程式設計】【C#】C#的變數可視範圍(SCOPE)

 

在一個程式中,變數的宣告意味著二件事:

  1. 跟系統配置一個空間,用來儲存資料
  2. 為了存取(儲存或讀取)這個變數,必須要透過一個名字,就像人一樣,出生下來就要取名字(取名字的目的,無非就是要來辨識一個人)。

另外從路的命名來看,相同的名字可以被用來命名不同地方的路,例如:

台中市有中山路、台中市裏的太平市(以前叫太平區)也有一條路叫中山路,大甲區有一條路叫中山路…

太平市、大甲區、大安區在台中市裏,用來類比程式的架構:

台中市可類比程式裏的類別,太平市、太甲區、大安區可類比程式裏的方法…

而中華民國就可類比namespace (命名空間)中的 WindowsFormsApplication1了

回到程式中來看,

在類別裏宣告的變數叫做類別的變數(在以前不是物件導向的世界時,叫做全域變數),類別變數的可視範圍遍及整個類別,類別裏的方法也能存取類別變數,方法裏宣告的變數,叫做方法變數(在以前不是物件導向的世界時,叫做區域變數),方法變數只能在宣告其變數的方法中被存取,其他方法不能存取其他方法裏的方法變數。

再下一階的變數,就是區塊變數(區塊是由左右大括弧的程式碼段落,像是if, while, do-while, for, try, catch等區塊),在一個區塊內變告的變數,僅能在該宣告其變數裏的區塊存取,區塊外不能取存取在區塊內宣告的變數。

原理講完了…,程式就簡單了!

3D立體拼圖 (雷射切割)

3D立體拼圖 (雷射切割)

3D立體拼圖 (雷射切割)

3D列印是一種加法加工法,適合製作奇形怪狀的物體,但是速度慢。

減法加工:CNC (電腦數值控制機,電腦車床)、雷射雕刻機、雷射切割機、刻印機…

在Thingiverse上下關鍵字”laser cut”,可找到許多可雷射切割的檔案,2D圖檔,非3D圖檔 (但是是3D圖)  (Adobe AI檔 或 Autocad檔)

雷射切割(機)的特色(原理,英文)

  • 精密
  • 材質:紙板、木板、壓克力板、鋁板、金屬 (大雷射功率)
  • 厚度:1, 2, 3, …. 1x mm
  • 線條約磨耗0.2mm (雷射光束切割)

 

3D列印時,若整體印有問題 (形狀有懸空時),我們可以採取分片/分件列印,再用粘合、拼接/榫接的方式,組合,但是要注意的是接合處間隙的問題,使用雷射切割,切割掉的線條剛好讓組件可以有稍微磨擦的方式進行組合,但是3D列印若只是單純用單一線條 (二片間的線條是重疊的),印出來之後,會卡不進去,因此,我們若要用3D列印組合片,必須要製造出接合處的間隙 (而此間隙又必須考量印表機/線材的特性…)。

Japanese Wood Joint

Laser cut arts

Laser cut animals

laser cut box

倫敦電話亭

 

 

meArm機械手臂

組裝成品:

本週作業:

請自選一個模型,設計繪製其可雷射切割之模型,並製作2種形式的圖檔:

  • 整體組合(3D)
  • 展開、攤開、攤平可分別列印形式

展開圖例:

 

【程式設計】【C#】乒乓遊戲

1.先將表單視窗放到最大,並將標題列隱藏

WindowState –> Maximized

FormBorderStyle –> None

 

2.2個pictureBox元件,一個是球,一個是球拍/棒

請自行Google適當的圖 (或僅設背景顏色)

3.程式一開始時,把球拍放在畫面的最下方 (表單底部)

4.使用滑鼠控制球拍的左右移動

 

程式碼-1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        int 水平位移量 = 5;
        int 垂直位移量 = 5;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            球.Left += 水平位移量;
            球.Top += 垂直位移量;

            if ((球.Top + 球.Height) >= this.ClientSize.Height || 球.Top <= 0) 垂直位移量 = 垂直位移量 * -1; //變化方向,縱向
            if ((球.Left + 球.Width) >= this.ClientSize.Width || 球.Left <= 0) 水平位移量 = 水平位移量 * -1; //變化方向,橫向

        }
    }
}

 

程式碼-2,加上棒子,並可用滑鼠來移動

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        int 水平位移量 = 5;
        int 垂直位移量 = 5;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            棒子.Top = this.ClientSize.Height - 棒子.Height;
            棒子.Left = this.ClientSize.Width/2 - 棒子.Width/2;
            //以上二行將棒子移到畫面的正中、下方處

            Cursor.Hide();//將游標隱藏起來
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            球.Left += 水平位移量;
            球.Top += 垂直位移量;

            if ((球.Top + 球.Height) >= this.ClientSize.Height || 球.Top <= 0) 垂直位移量 = 垂直位移量 * -1; //變化方向,縱向
            if ((球.Left + 球.Width) >= this.ClientSize.Width || 球.Left <= 0) 水平位移量 = 水平位移量 * -1; //變化方向,橫向

        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            棒子.Left = Cursor.Position.X; //棒子的水平位置 與 游標的水平位置聯動
        }
    }
}

 

程式碼-3,棒子擊球,並判斷球沒接到後的處理方式

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace bounceBall
{
    public partial class Form1 : Form
    {
        int 水平位移量 = 10, 垂直位移量 = 10; //控制水平與垂直的移動距離(跳5個像素)

        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //水平方向方向的判斷,右邊碰觸的判斷 + 左邊碰觸的判斷
            if ((球.Location.X + 球.Width) > this.ClientSize.Width || 球.Location.X < 0) 
                水平位移量 = 0 - 水平位移量; //正變負,負變正,也就是變換方向
            
            //上方碰觸的判斷 
            if (球.Location.Y < 0) 
                垂直位移量 = 0 - 垂直位移量; //正變負,負變正,也就是變換方向


            //棒子打中球的判斷
            if (球.Left >= 棒子.Left && 球.Left <= (棒子.Left + 棒子.Width) &&
                球.Top >= 棒子.Top - 球.Height) 
            {
                垂直位移量 = 0 - 垂直位移量; //正變負,負變正,也就是變換方向
            } 
           
            //底下是判斷球是否碰到畫面底碰部,是的話,遊戲結束
            if (球.Top + 球.Height >=  this.ClientSize.Height) //球碰到底部
            { //沒接到球…                
                timer1.Enabled = false; //關閉計時器,不要讓球繼續跑
                球.Left = 10; 球.Top = 10; //讓球回到點(10, 10)
                Cursor.Show();//讓游標顯示出來
                MessageBox.Show("你出局了!");
                this.Close(); //結束遊戲程式
            }

            //將水平位移量, 垂直位移量加到pictureBox1的X與Y
            球.Location = new Point(球.Location.X + 水平位移量, 球.Location.Y + 垂直位移量);

            /* 或者用Left和Top來移動球的位置
              球.Left += 水平位移量;
              球.Top += 垂直位移量;
             */
        }

        private void Form1_Load(object sender, EventArgs e) 
        {
            棒子.Top = this.ClientSize.Height - 棒子.Height;
            棒子.Left = this.ClientSize.Width / 2 - 棒子.Width / 2;
            //以上二行將棒子移到畫面的正中、下方處

            Cursor.Hide();//將游標隱藏起來
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            棒子.Left = Cursor.Position.X; //棒子的水平位置 與 游標的水平位置聯動
        }
    }
}

 

球出現在隨機的水平位置 +運動方向的改變 (左下方、正下方、右下方)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace bounceBall
{
    public partial class Form1 : Form
    {
        int 水平位移量 = 10, 垂直位移量 = 10; //控制水平與垂直的移動距離(跳5個像素)
        int 分數 = 0; 

        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //水平方向方向的判斷,右邊碰觸的判斷 + 左邊碰觸的判斷
            if ((球.Location.X + 球.Width) > this.ClientSize.Width || 球.Location.X < 0) 
                水平位移量 = 0 - 水平位移量; //正變負,負變正,也就是變換方向
            
            //上方碰觸的判斷 
            if (球.Location.Y < 0) 
                垂直位移量 = 0 - 垂直位移量; //正變負,負變正,也就是變換方向


            //棒子打中球的判斷
            if (球.Left >= 棒子.Left && 球.Left <= (棒子.Left + 棒子.Width) &&
                球.Top >= 棒子.Top - 球.Height) 
            {
                水平位移量 += 5;
                垂直位移量 += 5;

                垂直位移量 = 0 - 垂直位移量; //正變負,負變正,也就是變換方向
                
                分數 = 分數 + 1;
                label1.Text = "分數:" + 分數;
            } 
           
            //底下是判斷球是否碰到畫面底部,是的話,遊戲.... 
            if (球.Top + 球.Height >=  this.ClientSize.Height) //球碰到底部
            { //沒接到球…                
                timer1.Enabled = false; //關閉計時器,不要讓球繼續跑
                GameOver.Visible = true;
               

            }

            //將水平位移量, 垂直位移量加到pictureBox1的X與Y
            球.Location = new Point(球.Location.X + 水平位移量, 球.Location.Y + 垂直位移量);

            /* 或者用Left和Top來移動球的位置
              球.Left += 水平位移量;
              球.Top += 垂直位移量;
             */
        }

        private void Form1_Load(object sender, EventArgs e) 
        {
            棒子.Top = this.ClientSize.Height - 棒子.Height;
            棒子.Left = this.ClientSize.Width / 2 - 棒子.Width / 2;
            GameOver.Left = (this.ClientSize.Width - GameOver.Width) / 2;
            GameOver.Top = (this.ClientSize.Height - GameOver.Height) / 2;
            GameOver.Visible = false;

            //將球依隨機的水平位置來放
            Random Rnd = new Random(); //新建一個隨機數(Random)物件
            球.Left = Rnd.Next(10, this.ClientSize.Width - 球.Width);

            int 球的運動方式 = Rnd.Next(1, 4 ); //1:左下,2:正下方跑,3:右下(原本的方式)
            if (球的運動方式 == 1) 水平位移量 = 0 - 水平位移量;
            if (球的運動方式 == 2) 水平位移量 = 0 ;
            //if (球的運動方式 == 3)  原本的方式

            //以上二行將棒子移到畫面的正中、下方處

            Cursor.Hide();//將游標隱藏起來
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            棒子.Left = Cursor.Position.X; //棒子的水平位置 與 游標的水平位置聯動
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F1)
            {
                水平位移量 = 10;
                垂直位移量 = 10;
                分數 = 0;
                label1.Text = "分數:" + 分數;
                球.Top = 20;

                //將球依隨機的水平位置來放
                Random Rnd = new Random(); //新建一個隨機數(Random)物件
                球.Left = Rnd.Next(10, this.ClientSize.Width - 球.Width);

                int 球的運動方式 = Rnd.Next(1, 4); //1:左下,2:正下方跑,3:右下(原本的方式)
                if (球的運動方式 == 1) 水平位移量 = 0 - 水平位移量;
                if (球的運動方式 == 2) 水平位移量 = 0;
                if (球的運動方式 == 3) 水平位移量 = 10;


                GameOver.Visible = false;
                timer1.Enabled = true;
            }

            if (e.KeyCode == Keys.Escape)
            {
                this.Close();
            }

        }
    }
}

 

參考資料:

【程式設計】【C#】乒乓遊戲

 

【程式設計】【C#】籃球MVP等級計算

問題描述:
試寫一個程式,讓使用者可以輸入籃球員的得分,籃板,助攻、抄截、失誤等五個數值。並依(得分*1+助攻*2+籃板*2+抄截*2)-(失誤*2)的公式取得此籃球員MVP數值。大於45分以上為A級球員,35~44分為B級球員,25~34之間為C級球員,低於25分為D級球員。

輸入說明:
每一組需要輸入五個正整數,依序分別代表:平均得分、籃板數、
助攻數、抄截數、失誤數。

輸出說明:
以MVP數值對應球員等級。

例:

輸入:20 12 15 6 3

輸出:A

程式列表: