实现类似元气骑士的游戏

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43701019/article/details/88541360

个人做单机游戏的总结笔记

——类似元气骑士的2.5d游戏

移动

玩家人物移动方式:

//键盘输入控制上下左右(后期用摇杆可以不用这种方式)
horizontal = Input.GetAxisRaw("Horizontal");
vertical = Input.GetAxisRaw("Vertical");

if (Mathf.Abs(horizontal) > 0.01 || Mathf.Abs(vertical) > 0.01)
{
//记录方向 
idleH=horizontal;    
idleV=vertical;
//改变人物位置,moveSpeed为人物移动速度  
transform.Translate(new Vector3(horizontal * moveSpeed* Time.deltaTime, vertical * moveSpeed* Time.deltaTime, 0),Space.World);
}

同样方式,做敌人自动移动方式(可以加上一些检测能使得敌人更加“精明”):

//用随机数来控制上下左右
if(IsPlayer == false)      
{
  horizontal = Random.Range(-1, 2);
  vertical = Random.Range(-1, 2);
}
//改变敌人的位置
enemyPos.transform.Translate(new Vector3(horizontal * moveSpeed * Time.deltaTime, vertical * moveSpeed* Time.deltaTime, 0), Space.World); 

人物攻击

近身攻击

可以在武器加触发器(武器大小要比较统一)或者在人物身前加触发器(要用代码控制使跟人物一起移动选择)

  • 个人用第二种方式(素材在网上找比较乱,所以选择这种方式,但是感觉第一种判断比较精准,敌人与玩家类似。):
    ——玩家人物近攻攻击
    Close_Attack.cs(挂载在武器子物体下的空物体)
 void Update()
    { 
    //攻击的时候才显示
        if(!Player ._instance.isAttack )
        {
            this.gameObject.SetActive(false);
        }
    }

void OnTriggerEnter2D(Collider2D collider)
    {
       if(collider.transform.tag=="Enemy")
       {
            Enemy enemy;
            enemy = collider.GetComponentInChildren<Enemy>();                                
            enemy.LoseHP(damge);//damge为伤害值,LoseHP为敌人脚本里面的掉血函数
       }
    }

Player.cs

 //攻击范围方向
h=idleH;
v=idleV;
if (v == 1)
 {
    //相当于沿Y轴翻转
    Range_Attack.localScale = new Vector3(-  Mathf.Abs(Range_Attack.localScale.x),  Range_Attack.localScale.y,  Range_Attack.localScale.z);
     //翻转后X方向会与原来不一样
     h *= -1;
 }
else
    Range_Attack.localScale = new Vector3( Mathf.Abs(Range_Attack.localScale.x, Range_Attack.localScale.y, Range_Attack.localScale.z);
//选择攻击范围,使保持在人的正前方    
float angle = Vector2.Angle(-Vector2.right, new Vector2(h, v));
Range_Attack.rotation = Quaternion.Euler(0, 0, angle);
  • 第一种方法(自己想了一下,挺简单的,可能有点不完善,控制位置变化就在武器跟随部分完成):
    ——玩家人物近攻攻击
    首先给武器加个触发器(可以用胶囊体触发器),脚本如下:
    AttackRange.cs(挂载在武器子物体下的空物体)
 void Update()
    { 
    //攻击的时候才显示
        if(!Player ._instance.isAttack )
        {
            this.gameObject.SetActive(false);
        }
    }

void OnTriggerEnter2D(Collider2D collider)
    {
       if(collider.transform.tag=="Enemy")
       {
            Enemy enemy;
            enemy = collider.GetComponentInChildren<Enemy>();                                
            enemy.LoseHP(damge);//damge为伤害值,LoseHP为敌人脚本里面的掉血函数
       }
    }

远程攻击

—— 玩家人物远程攻击

  • Player.cs
if(weapontype==“Gun”)//远程攻击
        {       
            //实例化出子弹(bullet为做好的子弹prefab)
            GameObject bullets = GameObject.Instantiate(bullet, new Vector3(transform.position.x, transform.position.y, 0), Quaternion.identity);
             //给予子弹人朝向的方向一个速度,BulletSpeed为子弹飞行速度   
            bullets.GetComponent<Rigidbody2D>().velocity = new Vector2(idleH * BulletSpeed, idleV * BulletSpeed);        
         }
  • Bullet.cs(挂载在子弹的脚本,加个刚体和触发器。)
void OnTriggerEnter2D(Collider2D collider)
    {    
        switch(collider.transform.tag)
        {
            case "Enemy":
                Enemy enemy;
                enemy = collider.GetComponentInChildren<Enemy>();                                
                enemy.LoseHP(damge);//damge为伤害值,LoseHP为敌人脚本里面的掉血函数
                Destroy(this.gameObject);                                    
                break;        
            case "Obstacle": 
            //如果是可以破碎的障碍物可以当作敌人处理。    
            case "Wall":
                Destroy(this.gameObject);
                break;          
        }
    }

——敌人远程攻击

  • ShootEnemy.cs
public virtual  void Attack()//用虚方法可以再其他远程攻击的敌人改变子弹发射方式
    {
        GameObject bullets = GameObject.Instantiate(bullet, new Vector3(transform.position.x,.transform.position.y, 0), Quaternion.identity);
        //给予子弹向玩家方向一个速度,BulletSpeed为子弹飞行速度      
        bullets.GetComponent<Rigidbody2D>().velocity = ((PlayerPos-transform.position).normalized *BulletSpeed);
    }
  • Bullet_En.cs(挂载在敌人子弹的脚本,加个刚体和触发器。)
void OnTriggerEnter2D(Collider2D collider)
    {    
        switch(collider.transform.tag)
        {
            case "Player":
                //用获取Player或者人物作为单例模式,直接调用。因为人物就一个可以用单例,敌人有多个用单例会混乱。
                Player player;
                player= collider.GetComponentInChildren<Player >();                                
                player.LoseHP(damge);//damge为伤害值,LoseHP为人物脚本里面的掉血函数
                Destroy(this.gameObject);                                    
                break;        
            case "Obstacle": 
            //如果是可以破碎的障碍物可以当作人物处理。    
            case "Wall":
                Destroy(this.gameObject);
                break;          
        }
    }

敌人追随

private void OnTriggerStay2D(Collider2D collider)
 {  
    if (collider.tag == "Player")
    {
       //获取角色位置  
       PlayerPos = collider.transform.position;
       //敌人走到一定位置就不在走了,也可以不设置     
       if ((PlayerPos - enemyPos.transform.position).magnitude > distance)
       {
           //获取x,y方向
           horizontal = (PlayerPos.x - enemyPos.transform.position.x)%2;
           vertical = (PlayerPos.y - enemyPos.transform.position.y)%2;             
        }              
     }
 }
private void OnTriggerEnter2D(Collider2D collider)
{
    if (collider.tag == "Player")
       IsPlayer = true;          
}
private void OnTriggerExit2D(Collider2D collider)
{
    if (collider.tag == "Player")      
        IsPlayer = false;               
}
 //
           

武器追随

——武器适合向上并且刀锋向左(远程近程都是),这个是武器随着你控制人物的移动朝向而旋转。

  • 更多武器旋转方式:https://blog.csdn.net/weixin_43701019/article/details/98533603
//武器追随
if (! isAttack )
        {
            //人物移动才更新位置
            if( horizontal != 0 || vertical != 0)
               m_mousePosition = new Vector3( horizontal,  vertical, 0);     
            // 武器朝向角度        
            float m_weaponAngle = Vector2.Angle(Vector2.up, m_mousePosition);
            if (0 < m_mousePosition.x)
                m_weaponAngle = -m_weaponAngle;
            //判断武器正反
            //scale的x要为正数
            if (m_weaponAngle > 0 &&WeaponPos.transform.localScale.x < 0)
            {
                WeaponPos.transform.localScale = new Vector3(-WeaponPos.transform.localScale.x, WeaponPos.transform.localScale.y, WeaponPos.transform.localScale.z);
            }
            //scale的x要为负数
            else if (m_weaponAngle < 0 &&  WeaponPos.transform.localScale.x > 0)
            {
                WeaponPos.transform.localScale = new Vector3(-WeaponPos.transform.localScale.x, WeaponPos.transform.localScale.y, WeaponPos.transform.localScale.z);
            }
            else if ((m_weaponAngle == 0 || m_weaponAngle == 180) &&  WeaponPos.transform.localScale.x < 0)
            {
                WeaponPos.transform.localScale = new Vector3(- WeaponPos.transform.localScale.x,  WeaponPos.transform.localScale.y, WeaponPos. transform.localScale.z);
            }
            //近攻武器竖直,如果枪横抬。
            if (weaponType == "Axe")
            {
                if (0 < m_mousePosition.x)
                    m_weaponAngle = -(-m_weaponAngle - 90);
                else
                    m_weaponAngle -= 90;
            }
            // 变换最终角度
            transform.eulerAngles = new Vector3(0, 0, m_weaponAngle);
        }
//人物攻击执行攻击效果        
//近攻武器用旋转来做攻击效果
else  if (weaponType == "Axe" && isAttack)
{
//获取武器现在的旋转
weaAngle = weaponObj.transform.localEulerAngles.z ;
//判断武器现在向的是左边还是右边
//左边
if (weaponObj.transform.localScale.x > 0)
  {
    //攻击角度,Ang为砍到最终的角度
    angZ = Mathf.Lerp(angZ,  Ang, Time.deltaTime* angSpeed  );
    weaponObj.transform.rotation = Quaternion.Euler(new Vector3(0, 0, weaAngle + angZ));
    //砍到终点,停止攻击
    if (Ang- angZ<1)
         StopAttack();
  }
  //右边
else
  {
   //攻击角度,Ang为砍到最终的角度
     angZ = Mathf.Lerp(angZ,  Ang, Time.deltaTime* angSpeed);
     weaponObj.transform.rotation = Quaternion.Euler(new Vector3(0, 0, weaAngle - angZ));
    //砍到终点,停止攻击
     if (Ang-angZ< 1)
         StopAttack();
  }
}

人物无敌状态

——受伤之后一段时间无敌并闪烁

//用枚举来列出人物状态,根据需求还能加入其他状态
public  enum State
    {
        Playing, Unmatching
    }

//人物现处于哪个状态
private State state = State.Playing;
public State States
   {
        get {
            return state;
        }
        set {
            state = value;
        }
    }

//用协程来实现无敌的闪烁
IEnumerator    Unmatch()
    {        
        if (hp > 0)
        {
            int i = 0;
            //闪烁的频率为0.2秒,无敌时间为2秒。
            while (i < 10)
            {
                spriteRen.enabled = !spriteRen.enabled;
                i++;
                yield return new WaitForSeconds(0.2f);
            }            
            state = State.Playing;           
        }        
         StopCoroutine("Unmatch");        
    }
    
//给外部来调用协程    
public void  StartUnmatch()
    {
        StartCoroutine("Unmatch");
    }

摇杆(参考网上的)

——这是摇杆的组成
图片

  1. joystickwin是最外层的半透明圈圈。
  2. border是位置记录,放在内圈的边上,用来获取半径
  3. p-dap是最主要的,首先在其挂载一个脚本和一个事件触发器(设置如图)
    在这里插入图片描述
    脚本如下:
//虚拟方向按钮初始位置
    public Vector3 initPosition;
    //虚拟方向按钮可移动的半径
    public float r;
    //border对象
    public Transform border;
    public Player PlayerObj;
  
    void Start()
    {        
        //获取border对象的transform组件
        border = GameObject.Find("border").transform;
        initPosition = GetComponentInParent<RectTransform>().position;
        r = Vector3.Distance(transform.position, border.position);
    }
    //鼠标拖拽
    public void OnDragIng()
    {    
        //如果鼠标到虚拟键盘原点的位置 < 半径r
        if (Vector3.Distance(Input.mousePosition, initPosition) < r)
        {
            //虚拟键跟随鼠标
            transform.position = Input.mousePosition;           
        }
        else
        {
            //计算出鼠标和原点之间的向量
            Vector3 dir = Input.mousePosition - initPosition;
            //这里dir.normalized是向量归一化的意思,实在不理解你可以理解成这就是一个方向,就是原点到鼠标的方向,乘以半径你可以理解成在原点到鼠标的方向上加上半径的距离
            transform.position = initPosition + dir.normalized * r;          
        }
       PlayerObj .horizontal  = (transform.position.x - initPosition.x) / r;
       PlayerObj.vertical  = (transform.position.y - initPosition.y) / r;
         
    }
    //鼠标松开
    public void OnDragEnd()
    {   
        //松开鼠标虚拟摇杆回到原点
        transform.position = initPosition;
        PlayerObj.horizontal = PlayerObj.vertical = 0;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43701019/article/details/88541360