基于luaFramework_UGUI-master 使用lua实现贪吃蛇

找不到工作,开始研究lua。
看网上较少这方面的教程就写一下以供参考,顺便加深记忆。
我把需要修改的地方作一个简单介绍吧。

一 注册控制器和场景

CtrlNames = {
    Snake = "SnakeCtrl"
}

PanelNames = {
  "SnakePanel",
}
在Comman/define下注册,将你需要用到的控制器和场景写进上面的table。

注册的控制器和场景会在Logic/Game下加载,代码如下
function Game.InitViewPanels()
    for i = 1, #PanelNames do
        require ("View/"..tostring(PanelNames[i]))
    end
end 
--加载场景
    CtrlManager.Init();
    local ctrl = CtrlManager.GetCtrl(CtrlNames.Snake);
    if ctrl ~= nil and AppConst.ExampleMode == 1 then
        ctrl:Awake();
    end

function CtrlManager.Init()
    logWarn("CtrlManager.Init----->>>");
    ctrlList[CtrlNames.Snake] = SnakeCtrl.New();
    return this;
end

--加载控制器

二 场景类
-----

require "Common/define"

local gameobject;
local transform;


SnakePanel = {};
local this = SnakePanel;

function SnakePanel.Awake(obj)
  gameObject = obj;
  transform = obj.transform;

  this.InitPanel();
end

function SnakePanel.InitPanel()
  this.text = transform:FindChild("Text").gameObject;
  this.head = transform:FindChild("head").gameObject;
end

–获得场景中的控件,这里没有进行优化直接使用Find。场景是在控制类下加载出来。transform储存的是场景中名为Guicamera的相机。资源加载出来后一般是以它作为父节点。

三 控制类

require "Common/define"
require "Logic/Snake"
SnakeCtrl = {};

local this = SnakeCtrl;

local gameObject;
local transform;
local SnakeText

math.randomseed(os.time());

local SnakeTailPool = {};
local direction = {
  x = 0,
  y = 57
};
local lastDirection = { 
  x = 0,
  y = 57
};
local lastTailDirection = {
   x = 0,
   y = 0
};
local directionContorl = 1; --为1是向上 为2是向下 为3是向左 为4是向右--
local isRun = 1;
local GoldTable = {};
local directionStoreTable = {};

function SnakeCtrl.New()
  return this;
end

function SnakeCtrl.Awake()
   panelMgr:CreatePanel('Snake',this.OnCreate);
end


function SnakeCtrl.OnCreate(obj)
    gameObject = obj;
    transform = obj.transform;

  SnakeCtrl.AddTail(); --给尾巴--

  SnakeText = gameObject:GetComponent('LuaBehaviour');
  SnakeText:AddText(SnakePanel.text);
  coroutine.start(this.Move);
  UpdateBeat:Add(this.Update);
end

function SnakeCtrl.Move()
  while isRun>0 do
  if direction.x==0 and direction.y>0 then
    directionContorl = 1;
  end

  if direction.x==0 and direction.y<0 then
    directionContorl = 2;
  end

  if direction.y==0 and direction.x<0 then
    directionContorl = 3;
  end

  if direction.y==0 and direction.x>0 then
    directionContorl = 4;
  end

  SnakeCtrl.NewGold();

  SnakePanel.head.transform:Translate(direction.x,direction.y,0);

  if #SnakeTailPool ~= 0 then
    for i = 1,#SnakeTailPool do
      if SnakeTailPool[i].go~=0 then
         SnakeTailPool[i]:Move();
        -- LuaFramework.Util.Log("SnakeID"..i);
      end
    end

    for i = 1,#SnakeTailPool do
      if SnakePanel.head.transform.x == SnakeTailPool[i].position.x and SnakePanel.head.transform.y == SnakeTailPool[i].position.y then 
      LuaFramework.Util.Log("SnakeDead");
      end
      directionStoreTable[i].x = SnakeTailPool[i].direction.x;
      directionStoreTable[i].y = SnakeTailPool[i].direction.y;
    end
      SnakeCtrl.CheckGold(SnakePanel.head.transform.localPosition.x,SnakePanel.head.transform.localPosition.y);

    for i = 1,#SnakeTailPool-1 do

      if SnakeTailPool[i+1].direction.x ~= directionStoreTable[i].x or SnakeTailPool[i+1].direction.y ~= directionStoreTable[i].y then
        if i + 1 <= #SnakeTailPool then
          SnakeTailPool[i+1]:ChangeSwitch(directionStoreTable[i].x,directionStoreTable[i].y);
          LuaFramework.Util.Log("SnakeID"..i);
          LuaFramework.Util.Log(directionStoreTable[i].x..directionStoreTable[i].y);
        end
      end
    end
  end
      if lastDirection.x ~= direction.x or lastDirection.y ~= direction.y then
        lastDirection.x = direction.x;
        lastDirection.y = direction.y;
      if #SnakeTailPool ~=0 then
         SnakeTailPool[1]:ChangeSwitch(direction.x,direction.y);
         directionStoreTable[1].x = direction.x;
         directionStoreTable[1].y = direction.y;
      end
  end
  coroutine.wait(0.8);
end
end

function SnakeCtrl.Update()
    local keyCode = UnityEngine.KeyCode;
  if Input.GetKeyDown(keyCode.W) then 
     Util.Log("w");
     if (directionContorl~=2) then
     direction.x = 0;
     direction.y = 57;
     end   
  end

  if Input.GetKeyDown(keyCode.A) then 
    if (directionContorl~=4) then
    direction.x =-57;
    direction.y = 0;
    end
    Util.Log("a");
  end

  if Input.GetKeyDown(keyCode.D) then 
    if(directionContorl~=3) then
    direction.x = 57;
    direction.y = 0;
    end
    Util.Log("d");
  end

  if Input.GetKeyDown(keyCode.S) then 
    if(directionContorl~=1) then
    direction.x = 0;
    direction.y = -57;
    end
    Util.Log("s");
  end
end


function SnakeCtrl.NewGold()
    resMgr:LoadPrefab('snake',{'GoldPrefab'},this.CreateGold);
end

function SnakeCtrl.CreateGold(goes)
   local go = GameObject.Instantiate(goes[0]);
   local randomController = true;
   local x; 
   local y;

   while randomController do
      x = math.random(-5,5)*57;
      y = math.random(-5,5)*57;
      if #GoldTable ~= 0  then
        for i = 1,#GoldTable do
          if GoldTable[i][2] ~= x or GoldTable[i][3] ~=y then
            randomController = false;
          else
            randomController = true;
            break;
          end 
         end
      else 
          randomController = false;
      end
   end
   go.transform:SetParent(gameObject.transform);
   go.transform.localPosition = Vector3.New(x,y,0);
   table.insert(GoldTable,1,{go,go.transform.localPosition.x,go.transform.localPosition.y,go.transform.localPosition.z});
end

function SnakeCtrl.CheckGold(x,y)
  if #GoldTable ~= 0 then
     for i = 1,#GoldTable do
       if GoldTable[i][2] == x and GoldTable[i][3] == y then
         GameObject.Destroy(GoldTable[i][1]);
         table.remove(GoldTable,i);
         SnakeText:AddText(SnakePanel.text);
         SnakeCtrl.AddTail();
         break;
       end
     end
  end
end

function SnakeCtrl.AddTail()
  if #SnakeTailPool == 0 then
    local snake = Snake:New(SnakePanel.head.transform.localPosition.x,SnakePanel.head.transform.localPosition.y,direction.x,direction.y);
    table.insert(SnakeTailPool,#SnakeTailPool+1,snake);
    table.insert(directionStoreTable,#directionStoreTable+1,{x=direction.x,y=direction.y});
  else  
  local n = #SnakeTailPool;
 local snake=Snake:New(SnakeTailPool[n].position.x,SnakeTailPool[n].position.y,SnakeTailPool[n].direction.x,SnakeTailPool[n].direction.y);
    table.insert(SnakeTailPool,#SnakeTailPool+1,snake);
  end
    resMgr:LoadPrefab('snake',{'BodyPrefab'},this.CreateTail);
end

function SnakeCtrl.CreateTail(objs)
  local n = #SnakeTailPool;
  SnakeTailPool[n].go = GameObject.Instantiate(objs[0]);
  SnakeTailPool[n].go.transform:SetParent(transform);
  if n ~= 1 then
  SnakeTailPool[n].position.x = SnakeTailPool[n].position.x - SnakeTailPool[n].direction.x;
  SnakeTailPool[n].position.y = SnakeTailPool[n].position.y - SnakeTailPool[n].direction.y;
  table.insert(directionStoreTable,#directionStoreTable + 1,{x = SnakeTailPool[#SnakeTailPool].direction.x,y =SnakeTailPool[#SnakeTailPool].direction.y});
  end
  SnakeTailPool[n].go.transform.localPosition = Vector3.New(SnakeTailPool[n].position.x,SnakeTailPool[n].position.y,0);
end

逻辑其实挺简单,头节点移动后通知下一个节点改变,通过每一次移动的时候前一个节点和后一个节点方向如果不同就让后一个节点方向与前一个节点相同,逻辑上的困难点是如何在线程上实现,因为前一个节点会使后一个节点发生变化会导致后面节点一连串的改变,比如节点是abcdefg,a发生改变那么会使bcdefg发生改变,我只希望b发生改变的话就需要一个table储存 发生改变前的方向,就不会导致连锁反应。顺便一提57是我的每一个贪吃蛇节点期望距离。PS 应该用一个变量存储。。。
很多知识点比如如何在lua内与C#通信是在
https://zhuanlan.zhihu.com/p/21386682 学习到的,我就不在此赘述。不过有一点需要特别注意。
resMgr:LoadPrefab(‘snake’,{‘BodyPrefab’},this.CreateTail); 使用这个方法是会有延迟即调用createTail至完成是有延迟的,原因是luaFramework框架加载assetbundle使用了协程。

四 逻辑层

require "Common/define"

Snake = {

};

Snake.__index = Snake;

function Snake:Move()
      self.go.transform:Translate(self.direction.x,self.direction.y,0);
      self.position.x = self.direction.x + self.position.x;
      self.position.y = self.direction.y + self.position.y;
end

function Snake:ChangeSwitch(directionX,directionY)
     self.direction.x = directionX;
     self.direction.y = directionY;
end


function Snake:New(x,y,directionX,directionY)
      local self = {direction = {x = 0,y = 0},position = {x = 0,y = 0},ChangeMoveRecord = {},go = 0,directionX = 0,directionY = 0,switch = false,timer = 0,lastDirectionX,lastDirectionY,nowDirectionX = 0,nowDirectionY = 0};
      setmetatable(self,Snake);
      self.direction.x = directionX;
      self.direction.y = directionY;
      self.position.x = x;
      self.position.y = y;
      self.lastDirectionX = directionX;
      self.lastDirectionY = directionY;
      self.switch = false;
      self.timer = 0;
    return self;
end

关于table类的使用和继承在网上有资料就不赘述了。

五 C#

public void AddText(GameObject go)
        {
            if (go == null) return;
            string textStr = go.GetComponent<Text>().text;
            string regex = @"\d+$";
            Regex rgClass = new Regex(regex, RegexOptions.Singleline);
            Match match = rgClass.Match(textStr);
            int i = 0;
            if (match.Length != 0)
            {
                i = int.Parse(match.Value);
                i++;

            }
            {
                i = 0;
            }
            go.GetComponent<Text>().text = "得分:" + i.ToString();
        }

关于得分 使用了正则表达式

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
自动生成绑定代码文件,非反射调用 大量内建基础类型支持,如枚举,委托,事件,Type, 数组,迭代器等 支持多种协同形式 支持所有unity内部类导出,支持委托类型导出 支持导出自定义,跳过某个空的基类,修改导出名称等 支持扩展函数自定义导出, 比如DoTween 支持值类型Nullable导出,包括Nullable等 支持Lua中function转委托,可以区分需要不同委托的参数的重载函数 支持c# LuaFunction对象转委托,简化调用方式。 支持无GC的多参数调用形式 支持重载函数自动折叠, 如:Convert.ToUInt32只导出double参数的函数 支持重载函数自动排序, 如:参数个数相同, object参数执行级最低, 不会出现错误匹配情况 支持导出函数重命名, 可以分离导出某个重载函数(可以导出被折叠掉的函数) 支持使用编辑器类改写导出规则 支持this数组访问,索引为int可以通过[]访问,其他可使用.get_Item或者.this:get()访问数组成员 支持委托(事件)+-lua function。支持通过函数接口的Add和Remove委托操作 支持静态反射操作, 形式同c# 支持peer表,可在lua端扩展导出的userdata 支持自定义struct压入和读取,做到无GC,并且结构成员无类型限制, 参考例子24 支持preloading, 可以通过requie后绑定wrap文件 支持int64, uint64 大量的lua数学类型,如Quaternion, Vector3, Mathf等 包含第三方lua扩展,包括luasocket, struct, lpeg, utf8, pb等库 当lua出现异常,能够同时捕获c#端和lua端堆栈,便于调试 print信息,在编辑器点击日志, 能自动打开对应lua文件 支持unity所有版本 支持Lua hook C#相代码实现,一定程度上支持利用Lua代码修改C#端代码的bug(暖更新使用说明)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值