11. 销毁方块的随机加成,结算面板结算与游戏界面完善
Hi I'm Shendi
初始化
在上一节中制作了分数部分,在游戏开始时应初始化分数,至于子弹,10秒后自动销毁,就不用手动去销毁了
在 Main 的 StartGame 中增加以下代码
score = 0;
scoreObj.GetComponent<Text>().text = "";
击碎方块的随机加成
根据之前的策划,在销毁方块后有概率获得随机加成
在上部分中已经将销毁方块的结算处理作为一个单独的函数在 Main 中,于是只需要在 Main 中的 KillBox 处理即可
首先销毁方块是有概率获取随机加成,概率就50%吧,随机0-1,值为0则代表获取加成
之前策划有四种加成,同样通过随机数随机选择,按顺序,0-攻击翻倍,1额外金币,2冷却减半,3地图拉长
- 攻击翻倍(1-10秒随机)
- 额外金币(1-15随机)
- 冷却减半(1-10秒随机)
- 地图拉长(将所有地面方块往下拉一排,最后一排消失)
代码如下
/** 消灭一个方块时触发,消灭方块的结算 */
public void KillBox()
{
// 获取随机分数
score += Random.Range(1, 16);
// 渲染
scoreObj.GetComponent<Text>().text = "分数:" + score;
// 是否获取随机加成
if (Random.Range(0, 2) == 0)
{
switch (Random.Range(0, 4))
{
// 攻击翻倍(1-10秒随机)
case 0:
break;
// 额外金币(1-15随机)
case 1:
break;
// 冷却减半(1-10秒随机)
case 2:
break;
// 地图拉长(将所有地面方块往下拉一排,最后一排消失)
case 3:
break;
}
}
}
攻击翻倍
随机1-10秒有效期,于是需要做个计时变量,50为1秒,变量不为0代表当前已有攻击翻倍效果
在编写之前先在 Player 中定义以下变量
/** 角色的武器 */
public Weapon weapon;
State 中的 PlayerInit 代码如下,这样就可以通过角色拿到当前武器实例了
public static GameObject PlayerInit()
{
playerInstance = GameObject.Instantiate(player);
playerInstance.GetComponent<Player>().weapon = GameObject.Instantiate(playerWeapon, playerInstance.transform).GetComponent<Weapon>();
return playerInstance;
}
攻击力数值在武器内,武器在角色内,于是 Main 中代码如下
定义变量
/** 记录的最开始的攻击 */
private float buffAttack;
/** 攻击翻倍剩余时间,0代表没有 */
private float buffAttackTotol = 0;
增益处理
// 攻击翻倍(1-10秒随机)
case 0:
if (buffAttackTotol <= 0)
{
var weapon = State.playerInstance.GetComponent<Player>().weapon;
buffAttack = weapon.attack;
weapon.attack *= 2;
}
buffAttackTotol = Random.Range(1, 11) * 50;
break;
FixedUpdate 中计时与移除增益处理
// 加成部分
if (buffAttackTotol > 0)
{
if (--buffAttackTotol == 0)
{
// 移除加成
State.playerInstance.GetComponent<Player>().weapon.attack = buffAttack;
}
}
显示状态
当增益部分计时不为0则在游戏界面中显示 攻击翻倍:剩余时间
在 PageGame - Canvas 处右键 UI - 文字,放在界面的右边,调整位置大小颜色字体大小,居中字体等,效果如下
在 Main 中定义变量
/** 攻击翻倍的ui物体 */
public GameObject buffAttackObj;
在 Main 的 FixedUpdate 中处理显示与隐藏,代码如下
// 加成部分
if (buffAttackTotol > 0)
{
buffAttackObj.SetActive(true);
buffAttackObj.GetComponent<Text>().text = "攻击翻倍:" + (buffAttackTotol / 50) + " 秒";
if (--buffAttackTotol == 0)
{
// 移除加成
State.playerInstance.GetComponent<Player>().weapon.attack = buffAttack;
}
}
else
{
buffAttackObj.SetActive(false);
}
运行游戏,攻击方块,即可有几率看到右边出现buff的文字了
额外金币
同攻击翻倍一样,额外金币在游戏结束后会进入结算
在 Main 中定义以下变量
/** 额外金币 */
public float buffGold = 0;
/** 额外金币的ui物体 */
public GameObject buffGoldObj;
在开始游戏时需要将额外金币初始化
// 额外金币
buffGold = 0;
buffGoldObj.GetComponent<Text>().text = "额外金币:0";
在Unity中将物体拖入到摄像机的Main脚本中
Main 的 KillBox 部分代码如下
// 额外金币(1-15随机)
case 1:
buffGold = Random.Range(1, 16);
buffGoldObj.GetComponent<Text>().text = "额外金币:" + buffGold;
break;
冷却减半
同攻击翻倍,复制一下即可
Main中定义变量
/** 记录的最开始的冷却 */
private float buffCool;
/** 冷却减半的剩余时间,0代表没有 */
public float buffCoolTotol = 0;
/** 冷却减半的ui物体 */
public GameObject buffCoolObj;
Main 的 FixedUpdate 部分
if (buffCoolTotol > 0)
{
buffCoolObj.SetActive(true);
buffCoolObj.GetComponent<Text>().text = "冷却减半:" + (buffCoolTotol / 50) + " 秒";
if (--buffCoolTotol == 0)
{
// 移除加成
State.playerInstance.GetComponent<Player>().weapon.cool = buffCool;
}
}
else
{
buffCoolObj.SetActive(false);
}
Main 的 KillBox 部分
// 冷却减半(1-10秒随机)
case 2:
if (buffCoolTotol <= 0)
{
var weapon = State.playerInstance.GetComponent<Player>().weapon;
buffCool = weapon.cool;
weapon.cool /= 2;
}
buffCoolTotol = Random.Range(1, 11) * 50;
break;
效果如下
地图拉长
这部分和其他加成不一样,是对最后一排的方块进行销毁
这就需要获取到最后一排的所有物体,然后进行销毁,获取底部坐标,遍历所有方块,Y轴在最后一排则直接销毁
摄像头大小是5,就是说顶部是5,底部是-5,而方块大小0.5,轴为中心,那么方块在底部就是 -4.75
于是最后一排的 y 为 -4.75 ~ -4.25,y 小于 -4.7 则销毁
代码如下
// 地图拉长(将所有地面方块往下拉一排,最后一排消失)
case 3:
for (var i = 0; i < boxs.transform.childCount; i++)
{
var childBoxs = boxs.transform.GetChild(i);
for (var j = 0; j < childBoxs.childCount; j++)
{
var box = childBoxs.GetChild(j);
var y = box.position.y;
if (y <= -4.7)
{
Destroy(box.gameObject);
KillBox();
}
}
}
break;
游戏界面完善
除了之前显示的信息外,还应该显示时间,在左上角显示即可,其余的比如销毁方块数...都可以做,但没什么太大的必要,这里就加个时间,新增一个UI文本来显示时间,效果如下
在 Main 中记录时间
/** 游戏时间 */
public int time;
void FixedUpdate() {
if (State.isGameStart && !State.isGamePause)
{
if (time++ % 50 == 0)
{
timeObj.GetComponent<Text>().text = (int)(time/50) + "s";
}
}
}
开始游戏时初始化
public void StartGame()
{
time = 0;
timeObj.GetComponent<Text>().text = "0s";
}
将游戏对象拖到摄像机的 Time Obj 处即可
结算面板
结算面板包含标题,分数,分数转换金币数与额外金币数,时间
Main 中新增变量
/** 结算面板的文本 */
public Text settleScore;
public Text settleGold;
public Text settleTime;
拖入对应元素到摄像机的Main脚本
在游戏结束弹出结算面板前设置内容,在之前 State 中定义过 Settle 函数用于处理结算,于是在游戏结束时调用此函数即可,Main中游戏结束部分
public void StopGame()
{
State.isGameStart = false;
State.isGamePause = false;
State.Settle();
// 显示结算面板,隐藏暂停面板
panelSettle.SetActive(true);
panelPause.SetActive(false);
Time.timeScale = 0;
}
在 State 中定义金币属性
/** 当前金币 */
public static int gold = 0;
State 中 Settle 增加金币,设置结算面板内容
/** 结算 */
public static void Settle()
{
int scoreGold = Main._instance.score / 50, resultGold = (int) (scoreGold + Main._instance.buffGold);
Main._instance.settleGold.text = "金币:" + resultGold + "(" + scoreGold + " + " + (int)(Main._instance.buffGold) + "(格外))";
gold += resultGold;
Main._instance.settleScore.text = "得分:" + Main._instance.score;
Main._instance.settleTime.text = "时间:" + (int)(Main._instance.time/50) + "秒";
}
最终效果如下
本文链接:https://sdpro.top/blog/html/article/1071.html
♥ 赞助 ♥
尽管去做,或许最终的结果不尽人意,但你不付出,他不付出,那怎会进步呢?