刚开始接触unity 3d,现在要从头学起,模仿《别踩白块》做一个游戏。下面开始正文了。
在做之前,先想好需要哪些界面。需要一个开始界面和一个游戏界面。由于刚开始,先做的是游戏界面。截图如下:
用了一个面板做天空北京,一个球体做地面,摄像机角度调整好,有那么一点3D的感觉。将整个游戏场景放在一个空对象GameUI中,方面后面的编程。
固定场景搞定,下面开始动态的游戏物体--黑白块了。游戏素材有黑块和白块两种,但是在搭建场景的过程中,发现黑块的坐标有问题,没办法,将黑块托给一个空游戏物体,调整好坐标。下面,根据开始的分析,需要六行四列黑白块同时出现在屏幕上。(这一点,需要根据自己搭建的场景来判断,具体的数量,自己把握)。现在,在场景视图中调整块的位置,找一下规律:每行的块的坐标有什么规律,每列的块的坐标有什么规律(因人而异)。注意,由于要做的是3D的游戏,所以每行块都有一定的角度偏移,这个也要考虑。如下如所示:
这一点,主要是为了动态根据预制体生成黑白块确定坐标。好了,我本人的绑定黑白块的代码如下:
using UnityEngine;
using System.Collections;
public class Block : MonoBehaviour {
//判断块是否可以踩
public bool cantTouch = false ;
// Use this for initialization
//x,y,z偏移量
//初始化,基准坐标
private float px = -0.5f;
private float py = 0.15f;
private float pz = -6.3f;
private float rx = -54.5f;
private GameController gameController;
//行列索引
public int columnIndex;
public int rowIndex;
void Start () {
gameController = GameObject .FindObjectOfType<GameController> ();
}
//按键,开始游戏
// Update is called once per frame
void OnMouseDown () {
// print ("Block OnMouseDown");
gameController.Select(this);
}
//设置方块位置
public void SetPosition(int columnIndex,int rowIndex){
this .rowIndex =rowIndex ;
this .columnIndex = columnIndex ;
gameObject .transform .position =
new Vector3 (px +columnIndex *0.25f,py +rowIndex *0.275f, pz + rowIndex*0.2f);
// new Vector3 (px +columnIndex *0.25f,py +rowIndex *0.3f, pz + rowIndex*0.2f);
gameObject .transform .eulerAngles = new Vector3 (rx + rowIndex*4.5f,0,0);
//new Vector3 (rx + rowIndex*5f,0,0);
}
//色块往下移动一行
public void MoveDown(){
SetPosition (columnIndex ,rowIndex -1);
}
}
首先,确定左下角块的初始位置。使用行列索引来确定每一个块。在SetPosition()函数中,确定每个块的坐标。之后,将黑白块分别做成prefab,将上面的脚本分别绑定给它们。
游戏界面做好了,现在开始做开始界面。使用NGUI来做开始界面。最后的效果图如下:
主要的按钮有四个,最上面的是开始按钮,下面的从左到右分别是more(连接到互联网)、声音开关和排行按钮,这四个使用的是Button。隐藏有得分条、时间条、gameover和排名,这四个是显示作用,使用的是Label。
顺便说一下NGUI的使用。
首先要导入NGUI,这个自己从网上找吧,很多的。导入之后,project视图中会出现NGUI。之后,将需要使用的图片放在一个文件夹,在放在NGUI下面的Resources文件夹下。在resources文件夹下用鼠标全选需要使用的照片,然后点击菜单栏NGUI->open->Atlas Maker,如图,点击create。
使用的时候,NGUI->create->sprite,这样,所有的sprite都会在camera目录下,如图:
创建好sprite之后,选中,在右边的inspector中UISprite选项里面,点击Atlas,选择先前创建的Atlas,然后,点击Sprite,选择需要的图片。这样,就可以在场景视图中调节了。另外,如果要做的是按钮,需要给它添加一个碰撞体,在inspector视图中的最下面Add componet ,physics。注意,添加碰撞体后,一定要调节碰撞体的大小,确保可以完全覆盖sprite。还要在project视图中搜索UIbuttonmessage脚本,然后绑定给需要的sprite,如图:
注意图中的标记,在UIButton Message中,将按钮要执行的动作的脚本的绑定物体拖给target,将要执行的动作的函数拖给function name。
上面介绍的是做按钮。如果要做显示条的话,先拖一个sprite到camera下,调整大小,再在NGUI->create->Label创建一个label,覆盖sprite。之后,可以像操作label一样操作了。
回归正题。我在hierarchy视图中创建了一个空游戏对象GameController来控制所有的游戏逻辑,所有的游戏逻辑都在脚本GameController中。所有的代码如下:
using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour {
//得分
public static int score = 0;
//public int i=0;
//是否播放音乐
public bool baudio = true ;
//是否计时
// public bool CountTime = false ;
//时间
public float jishi= 0.0f;
//第几次按下
//public bool presscount = false ;
// public static bool ShowScore = false ;
//Time GameTime = Time.time ;
//开始界面
public GameObject StartUI;
//游戏界面
public GameObject GameUI;
//分数条
public GameObject Score;
public UILabel ScoreLabel;
//游戏结束
public GameObject GameOver;
//容器,盛放生成的块
public GameObject container;
//排名
public GameObject Paiming;
public UILabel PaimingLabel;
//时间条
public GameObject shitiao;
public UISprite shijiantiao;
//游戏音乐控制
public GameObject Shuta;
public GameObject Playa;
//白块和黑块
public GameObject whiteBlock;
public GameObject blackBlock;
//动态数组,存放块
private ArrayList blocks;
// 进入游戏界面
public void EnterGameUI () {
//初始化jishi
jishi = 0.0f;
// print("more");
//关闭开始界面,打开游戏界面
StartUI.SetActive(false);
GameUI.SetActive(true);
//开始游戏
StartGame ();
}
//开始游戏
private void StartGame(){
// Adunion4Unity.Instance.showInterstitialAd(Adunion4Unity.IAD_TYPE_GAMESTART);
// CountTime = true ;
//显示时间条,分数,GameOver关闭
shitiao .SetActive (true);
GameOver .SetActive (false );
Score .SetActive (true);
//初始化时间条长度
shijiantiao.fillAmount = 1f;
//初始化六行块
blocks = new ArrayList();
for (int rowIndex=0; rowIndex <6; rowIndex ++) {
AddBlock(rowIndex);
}
}
//在指定的行添加一行色块
void AddBlock(int rowIndex){
//随机生成列数
int columnIndex = Random .Range (0,4);
for(int i=0;i!=4;++i){
GameObject o;
if(i==columnIndex){
o = Instantiate(blackBlock) as GameObject;
}
else {
o = Instantiate (whiteBlock) as GameObject;
}
o.transform .parent = container .transform ;
Block b = o.GetComponent<Block>();
b.SetPosition(i,rowIndex);
blocks.Add(b);
}
}
//点击块,进行游戏
public void Select(Block block){
//播放音乐
if(baudio){
audio .Play();
}
//判断踩的是不是最下面一行的块
if(block.rowIndex==0){
//踩黑块
if(block.cantTouch){
score +=1;
for(int i=0;i<blocks.Count;i++){
Block b = (Block)blocks[i];
b.MoveDown();
if(b.rowIndex ==-1){
blocks.RemoveAt(i);
Destroy (b.gameObject);
i--;
}
}
//在最上面添加一行
AddBlock(5);
}
else{
// Adunion4Unity.Instance.showInterstitialAd(Adunion4Unity.IAD_TYPE_GAMEGIFT);
//读取游戏分数值
int i=PlayerPrefs.GetInt("score",0);
//print(score);
//如果分数比读取的大的话,将score写入
if(score>i){
// print(score);
PlayerPrefs.SetInt("score",score);
}
//清理,返回开始界面
Clean ();
GameUI .SetActive (false);
StartUI.SetActive (true);
GameOver .SetActive (true );
// Score.SetActive(false);
Score .SetActive (false );
shitiao .SetActive (false);
ScoreLabel .text = "Score:";
// goshow=true;
// print("failed");
}
}
//显示分数
ShowScore();
}
//清理游戏状态
void Clean(){
for(int i=0;i<blocks.Count;i++){
Block b = (Block)blocks[i];
blocks.RemoveAt(i);
Destroy(b.gameObject);
i--;
}
score = 0;
}
//显示分数条
void ShowScore(){
ScoreLabel.text="Score:"+score;
}
//播放音乐
void PlayAudio(){
baudio = false ;
Shuta .SetActive (false);
Playa .SetActive (true );
}
//关闭音乐
void shutAudio(){
baudio = true ;
Shuta .SetActive (true);
Playa .SetActive (false);
}
//计时,时间条变化,超过20s,游戏结束,返回开始界面
void Update(){
// jishi ++;
//计时
jishi += Time.deltaTime;
//时间条
shijiantiao.fillAmount -=0.05f*Time.deltaTime;
// if(CountTime){
// if(Time.realtimeSinceStartup>=15){
if(jishi>=20){
int i=PlayerPrefs.GetInt("score",0);
if(score>i){
PlayerPrefs.SetInt("score",score);
}
Clean ();
GameUI .SetActive (false);
StartUI.SetActive (true);
GameOver .SetActive (true );
Score .SetActive (false );
shitiao .SetActive (false);
ScoreLabel .text = "Score:";
// CountTime = false ;
}
// }
//获取键值,如果按下返回键,退出游戏
if(Input.GetKeyDown(KeyCode.Escape))
Application.Quit();
}
//显示排名
void ShowPaiming(){
int score;
score=PlayerPrefs.GetInt("score",0);
Paiming.SetActive(true);
PaimingLabel.text ="HIGH: "+score ;
// print(score);
}
//链接网页
void More(){
Application.OpenURL("http://www.hao123.com");
}
//排名
void PaimingBtn(){
Paiming.SetActive(false);
}
}
最后,游戏工程和最后的apk文件都在下面: http://download.csdn.net/detail/longfeiah/8565119