Unity游戲開發(fā)之2048游戲的實現(xiàn)
一、前言
寫今天這篇文章的緣由,其實是來自于前段時間和粉絲的一個聊天,最近他打算參加游戲創(chuàng)作大賽,問我需要準備學習什么知識,以及參加比賽的注意事項一類:

我相信因為熱愛游戲而前來投身于U3D學習的粉絲想來不是少數(shù),興趣可以驅動學習,在完善自己心愛游戲的過程中,要不斷的去學習,不斷的提高自己。
而參與游戲設計比賽,更是提高自身技術實力、增長眼界見識的優(yōu)秀途徑,在此途中也能遇見不少志同道合的好朋友。
那今天就借此簡單的聊一下,制作一個簡單游戲需要具備哪些技術棧,以及參加這類比賽需要的知識基礎。
并且,還有休閑類游戲《2048》的實戰(zhàn)開發(fā)內(nèi)容。
二、游戲開發(fā)知識儲備
接下來就聊一下做一個游戲需要具備哪些技術棧, 因為只是面對“做出游戲”這個特定需求,所以有些技術沒有列舉出來,在開發(fā)中遇到可以再學習。
2-1技術棧
Unity3D安裝
首先,學習Unity3D你要安裝Unity3D編輯器吧,激活Unity Hub許可證。
分享 幾個下載鏈接:
當然,比較推薦是用Unity Hub下載安裝:

安裝后激活許可證,這個網(wǎng)上教程比較多,這里就不贅述了:

Unity3D編輯器布局學習
學習Unity3D編輯器,要先熟悉Unity編輯器的布局,比如菜單欄,工具欄在什么位置:
Unity入門組件學習
Unity的特色就是面向組件編程,所以對于組件的熟悉是基本的要求。
比較常用的組件有:
Audio組
- AudioSource
- AudioListener
Effects組
- ParticleSystem
- LineRenderer
- TrailRenderer
Event組
- EventSystem
- EventTrigger
- GraphicRaycaster
Layout組
- RectTransform
- Canvas
- CanvasGroup
- CanvasScaler
- AspectRatioFitter
- ContentSizeFitter
- GridLayoutGroup
- HorizontalLayoutGroup
- VerticleLayoutGroup
- LayoutElement
Mesh組
- MeshFilter
- MeshRenderer
- SkinnedMeshRenderer
- TextMeshPro-Text
Miscellaneous組
- Animator
- Animation
Nevigation組
- NavMeshAgent
- NavMeshObstacle
Physics2D組
- Rigidbody2D
- BoxCollider2D
- CapsuleCollider2D
- CircleCollider2D
- CompositeCollider2D
- EdgeCollider2D
Physics組
- Rigidbody
- BoxCollider
- CapsuleCollider
- SphereCollider
- CharacterController
- TerrainCollider
Rendering組
- Camera
- CanvasRenderer
- SpriteRenderer
- Skybox
- SortingGroup
- Light
組件比較多,但是不需要全部學習,只需要在用到的時候查看一下Unity3D手冊即可:
Unity3D中文手冊https://docs.unity.cn/cn/current/Manual/index.html
C#語言基礎
Unity3D的腳本語言是C#,隨意要做好Unity3D開發(fā),C#編程語言肯定要學的。
最基本的面向對象思想,數(shù)據(jù)類型、流程控制、數(shù)組、函數(shù)都要有一定的了解。
Unity3D-UGUI
UGUI是Unity3D的UI系統(tǒng),可以用UGUi搭建界面,然后很多的用戶交互邏輯都是在UI上完成的,所以學好UGUI是很有必要的,下面就來看一下UGUI的基本組件:
- Text
- Image
- RawImage
- Button
- Toggle
- Slider
- Scrollbar
- Dropdown
- InputField
- Canvas
- Panel
- ScrollView
數(shù)據(jù)結構
數(shù)據(jù)結構是一種具有一定邏輯關系,在計算機中應用某種存儲結構,并且封裝了相應操作的數(shù)據(jù)元素的集合。
簡單點說就是專門用于數(shù)據(jù)存儲和檢索的類。
因為做游戲開發(fā)或者其他項目都會用到對數(shù)據(jù)的操作,而數(shù)據(jù)結構就是專門用于數(shù)據(jù)存儲和檢索的類。
常見的數(shù)據(jù)結構有:
- 列表List
- 數(shù)組Array
- 字典Dictionary
- 棧Stack
- 隊列Queue
總結的技術??粗譀]有那么多,但是內(nèi)容還是很多的,比如說Unity3D的組件、C#腳本語言、UGUI系統(tǒng),每一塊拿出來都是很多的內(nèi)容。
三、休閑類游戲《2048》開發(fā)實戰(zhàn)
3-1玩法概述
開局是一個4X4棋盤,棋盤中隨機出現(xiàn)兩個數(shù)字,出現(xiàn)的數(shù)字為2或4。
玩家通過選擇上下左右四個反向,若玩家選擇的方向上有相同的數(shù)字則合并,若選擇的反向上沒有相同的數(shù)字但是有空位則移動,可以移動的同時合并,但是不可以連續(xù)合并。
若棋盤被數(shù)字填滿,無法進行移動或合并,則游戲失敗。
如果棋盤出現(xiàn)2048,則游戲勝利:

3-2實現(xiàn)分析
根據(jù)規(guī)則,來分析一下游戲的實現(xiàn)。
以向左移動為例:

可以看到移動后的規(guī)則:
相鄰的元素值相同則合并,然后末尾補上空元素
開頭或中間有空元素就移動到末尾
只合并一次,不會多次合并
3-3搭建場景
(1)新建項目我用的Unity 2019.4.7f1版本,模板選擇2D,設置項目名稱和位置:

(2)將圖片另存為,然后導入到項目中:

(3)在Inspector視圖中導入設置:

(4)分割圖片,點擊Sprite Editor后,會出現(xiàn)分割窗口,然后點擊Slice,選擇Grid By Cell Count,點擊Apply:

分割后:

(5)切完后,把圖集放到Resources文件夾中,沒有就新建一個,Resources文件夾在Unity中有特殊作用,可以通過腳本Resources類進行訪問。

PS:注意圖集的名字2048,稍后代碼會用到。
接著將2048_0拖入場景中,重命名為BG,設置排序層Order inLayer為-1,這樣背景就總是顯示在最下面了:

將BG拖入Project視圖,做成預制體:

同樣的操作,將2048_1拖入場景,然后重命名為Card,設置排序層為0,然后做成預制體:

將場景中的BG和Card對象刪除,我們將在后面使用實例化新建出來。
至此,我們的場景就搭建完成了,下面進行代碼的編寫。
3-4實現(xiàn)代碼
(1)首先,我們需要創(chuàng)建16個小方格作為背景,新建腳本GameManager.cs,雙擊打開腳本,編寫代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject bgSprite;//背景卡片
private Vector2 BeginPos = new Vector2(-1.5f, 1.5f);//差不多在屏幕中間
private float OffsetX = 1.1f;//xy 加個0.1 有個間隙
private float OffsetY = 1.1f;
void Start()
{
CreateBG();
}
void CreateBG()
{
GameObject BG = new GameObject("BG");//創(chuàng)建空游戲對象作為背景預制體
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Vector2 newPos = new Vector2(BeginPos.x + j * OffsetX, BeginPos.y - i * OffsetY);
Instantiate(bgSprite, newPos, Quaternion.identity, BG.transform);
}
}
}
}
將腳本附給Main Camera對象,然后將預制體BG拖到Card腳本組件的BgSprite卡槽中:

運行程序:

(2)接下來創(chuàng)建一個Card.cs腳本,主要用來管理創(chuàng)建的Card對象,找到Project視圖中的Card對象,將Card.cs腳本附加上去:

修改Card.cs腳本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Card : MonoBehaviour
{
public Sprite[] CardSprites;//讀取圖集中所有切片
private string fileName = "2048";//圖集的名字
public int _currentIndex = 0;//當前卡片的顯示編號
void Awake()
{
CardSprites = Resources.LoadAll<Sprite>(fileName);
}
//根據(jù)卡片編號修改SpriteRendere,從而改變卡片的數(shù)值
public void Generate(int index)
{
_currentIndex = index;
GetComponent<SpriteRenderer>().sprite = CardSprites[_currentIndex];
}
//合并卡片的邏輯
public void Merge()
{
_currentIndex++;
GetComponent<SpriteRenderer>().sprite = CardSprites[_currentIndex];
}
}
(3)接下來修改GameManager.cs腳本,雙擊打開腳本,修改代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject card;//卡片對象
private GameObject[,] cardList = new GameObject[4, 4];//卡片游戲對象對應的棋盤格子
private int CardNum = 0;//棋盤格子的卡片計數(shù),用于滿格后重新開始游戲
void Start()
{
CreateBG();
CreateCard();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.W))//上
{
MoveUp();
CreateCard();
}
if (Input.GetKeyDown(KeyCode.S))//下
{
MoveUp();
MoveDown();
}
if (Input.GetKeyDown(KeyCode.A))//左
{
MoveLeft();
CreateCard();
}
if (Input.GetKeyDown(KeyCode.D))//右
{
MoveRight();
CreateCard();
}
}
void CreateBG()
{
GameObject BG = new GameObject("BG");//創(chuàng)建空游戲對象作為背景預制體
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Vector2 newPos = new Vector2(BeginPos.x + j * OffsetX, BeginPos.y - i * OffsetY);
Instantiate(bgSprite, newPos, Quaternion.identity, BG.transform);
}
}
}
void CreateCard()
{
}
void MoveUp()
{
}
void MoveDown()
{
}
void MoveLeft()
{
}
void MoveRight()
{
}
}
CreateCard函數(shù)的主要實現(xiàn)思路是:
- 每次申城一個卡片時計算當前數(shù)組中的卡牌數(shù),如果大于16則游戲重置
- 否則隨機生成坐標點,判斷當前當前坐標是否有卡片,直到找到空余位置,實例化卡片
- 生成對應數(shù)字的卡片
void CreateCard()
{
CardNum = 0;
foreach (var item in cardList)
{
if (item)
{
CardNum++;
}
}
if (CardNum >= 16)
{
ResetGame();
return;
}
int X_index, Y_index = 0;
do
{
X_index = Random.Range(0, 4);
Y_index = Random.Range(0, 4);
} while (cardList[X_index, Y_index]);
Vector2 newPos = GetPosVector2(X_index, Y_index);
cardList[X_index, Y_index] = Instantiate(_card, newPos, Quaternion.identity);
if (Random.Range(0.0f,1.0f)>0.5f)
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(1);
}
else
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(2);
}
}
public Vector2 GetPosVector2(int x, int y)
{
return new Vector2(BeginPos.x + y * OffsetX, BeginPos.y - x * OffsetY);
}
void ResetGame()
{
foreach (var card in cardList)
{
if (card != null)
{
Destroy(card);
}
cardList = new GameObject[4, 4];
}
}
(4)接下來就是響應鼠標輸入,然后移動卡片了,以向上移動為例,主要邏輯思路如下:
遍歷卡片數(shù)組,尋找存在的卡片
尋找到一個存在的卡片,沿著移動方向上每一個格子做判斷,看前面是否有卡片,找到離自己最近的卡片做判斷
如果與本身卡片數(shù)值一直,則進行Card類中的Merge方法進行合并
否則,將卡片移動到該格子的臨近格子
向上移動代碼實現(xiàn)如下:
void MoveUp()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
x--;//根據(jù)方向的不同 x--是向上 x++是向下
if (x < 0 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (x >= 0 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x + 1, y] = temp;
cardList[x + 1, y].transform.position = GetPosVector2(x + 1, y);
}
}
}
}
}
}
}
向下移動:
void MoveDown()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
x++;//根據(jù)方向的不同 x--是向上 x++是向下
if (x > 3 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (x <= 3 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x - 1, y] = temp;
cardList[x - 1, y].transform.position = GetPosVector2(x - 1, y);
}
}
}
}
}
}
}
向左移動:
void MoveLeft()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
y--;//根據(jù)方向的不同 x--是向上 x++是向下
if (y < 0 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (y >= 0 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x, y + 1] = temp;
cardList[x, y + 1].transform.position = GetPosVector2(x, y + 1);
}
}
}
}
}
}
}
向右移動:
void MoveRight()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
y++;//根據(jù)方向的不同 x--是向上 x++是向下
if (y > 3 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (y <= 3 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x, y - 1] = temp;
cardList[x, y - 1].transform.position = GetPosVector2(x, y - 1);
}
}
}
}
}
}
}
運行游戲,就可以愉快的玩耍了:

到這一步,我們就完成了《2048》游戲的核心代碼實現(xiàn),但是我們的代碼只有滿格后重新開始游戲的判斷,沒有游戲完成的判斷,下面加一個游戲成功的代碼,繼續(xù)修改GameManager.cs腳本:
void CreateCard()
{
CardNum = 0;
foreach (var item in cardList)
{
if (item)
{
CardNum++;
}
}
if (CardNum >= 16)
{
ResetGame();
return;
}
int X_index, Y_index = 0;
do
{
X_index = Random.Range(0, 4);
Y_index = Random.Range(0, 4);
} while (cardList[X_index, Y_index]);
Vector2 newPos = GetPosVector2(X_index, Y_index);
cardList[X_index, Y_index] = Instantiate(_card, newPos, Quaternion.identity);
if (Random.Range(0.0f,1.0f)>0.5f)
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(1);
}
else
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(2);
}
SucceedGame();
}
void SucceedGame()
{
foreach (var item in cardList)
{
if (item.GetComponent<Card>()._currentIndex >= 11)
{
Debug.Log("游戲成功");
break;
}
}
ResetGame();
}
整體GameManager.cs腳本代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject bgSprite;//背景卡片
private Vector2 BeginPos = new Vector2(-1.5f, 1.5f);//差不多在屏幕中間
private float OffsetX = 1.1f;//xy 加個0.1 有個間隙
private float OffsetY = 1.1f;
public GameObject _card;//卡片對象
private GameObject[,] cardList = new GameObject[4, 4];//卡片游戲對象對應的棋盤格子
private int CardNum = 0;//棋盤格子的卡片計數(shù),用于滿格后重新開始游戲
void Start()
{
CreateBG();
CreateCard();
CreateCard();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.W))//上
{
MoveUp();
CreateCard();
}
if (Input.GetKeyDown(KeyCode.S))//下
{
MoveDown();
CreateCard();
}
if (Input.GetKeyDown(KeyCode.A))//左
{
MoveLeft();
CreateCard();
}
if (Input.GetKeyDown(KeyCode.D))//右
{
MoveRight();
CreateCard();
}
}
void CreateBG()
{
GameObject BG = new GameObject("BG");//創(chuàng)建空游戲對象作為背景預制體
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Vector2 newPos = new Vector2(BeginPos.x + j * OffsetX, BeginPos.y - i * OffsetY);
Instantiate(bgSprite, newPos, Quaternion.identity, BG.transform);
}
}
}
void CreateCard()
{
CardNum = 0;
foreach (var item in cardList)
{
if (item)
{
CardNum++;
}
}
if (CardNum >= 16)
{
ResetGame();
return;
}
int X_index, Y_index = 0;
do
{
X_index = Random.Range(0, 4);
Y_index = Random.Range(0, 4);
} while (cardList[X_index, Y_index]);
Vector2 newPos = GetPosVector2(X_index, Y_index);
cardList[X_index, Y_index] = Instantiate(_card, newPos, Quaternion.identity);
if (Random.Range(0.0f,1.0f)>0.5f)
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(1);
}
else
{
cardList[X_index, Y_index].GetComponent<Card>().Generate(2);
}
SucceedGame();
}
public Vector2 GetPosVector2(int x, int y)
{
return new Vector2(BeginPos.x + y * OffsetX, BeginPos.y - x * OffsetY);
}
void ResetGame()
{
foreach (var item in cardList)
{
if (item != null)
{
Destroy(item);
}
cardList = new GameObject[4, 4];
}
}
void SucceedGame()
{
foreach (var item in cardList)
{
if (item.GetComponent<Card>()._currentIndex >= 11)
{
Debug.Log("游戲成功");
break;
}
}
ResetGame();
}
void MoveUp()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
x--;//根據(jù)方向的不同 x--是向上 x++是向下
if (x < 0 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (x >= 0 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x + 1, y] = temp;
cardList[x + 1, y].transform.position = GetPosVector2(x + 1, y);
}
}
}
}
}
}
}
void MoveDown()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
x++;//根據(jù)方向的不同 x--是向上 x++是向下
if (x > 3 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (x <= 3 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x - 1, y] = temp;
cardList[x - 1, y].transform.position = GetPosVector2(x - 1, y);
}
}
}
}
}
}
}
void MoveLeft()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
y--;//根據(jù)方向的不同 x--是向上 x++是向下
if (y < 0 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (y >= 0 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x, y + 1] = temp;
cardList[x, y + 1].transform.position = GetPosVector2(x, y + 1);
}
}
}
}
}
}
}
void MoveRight()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (cardList[i, j] != null)//當找到其中的卡片后
{
GameObject temp = cardList[i, j];//保留該卡片的引用
int x = i;
int y = j;
bool isFind = false;//設置查找標識
while (!isFind)
{
y++;//根據(jù)方向的不同 x--是向上 x++是向下
if (y > 3 || cardList[x, y])//達到邊界或找到卡片后
{
isFind = true;
//判斷值是否相同,相同的話合并操作
if (y <= 3 && cardList[x, y].GetComponent<Card>()._currentIndex == cardList[i, j].GetComponent<Card>()._currentIndex)
{
cardList[x, y].GetComponent<Card>().Merge();
Destroy(cardList[i, j]);
cardList[i, j] = null;
}
else//否則移動即可
{
cardList[i, j] = null;
cardList[x, y - 1] = temp;
cardList[x, y - 1].transform.position = GetPosVector2(x, y - 1);
}
}
}
}
}
}
}
}
至此,我們的《2048》游戲就已經(jīng)完成了,愉快的玩耍吧。
以上就是Unity游戲開發(fā)之2048游戲的實現(xiàn)的詳細內(nèi)容,更多關于Unity2048游戲的資料請關注腳本之家其它相關文章!
相關文章
C#實現(xiàn)把科學計數(shù)法(E)轉化為正常數(shù)字值
這篇文章主要介紹了C#實現(xiàn)把科學計數(shù)法(E)轉化為正常數(shù)字值,本文直接給出代碼實例,需要的朋友可以參考下2015-06-06
c# 重載WndProc,實現(xiàn)重寫“最小化”的實現(xiàn)方法
在做“亦歌桌面版”的時候,發(fā)現(xiàn)當打開歌詞狀態(tài)下,用最小化隱藏窗體到托盤的話(如下code #1),在調出發(fā)現(xiàn)歌詞縮小了(雖然顯現(xiàn)的窗體大小跟剛才一樣),從這點看調用該方法其實窗體大小是改變了的(這個過程只是不可視而已)。2009-02-02

