当前位置:网站首页>Lua programming learning notes

Lua programming learning notes

2022-07-07 08:15:00 tough is tough

Lua Programming learning notes

Lua The feeling of programming language is small , concise , Interpretive language , Weak type , Mainly used for game development , Embedded script development .

This learning comes from writing famine scripts , Learn with famine Lua It's definitely a good practice .

One 、 Environmental installation

First, on the official website download

Lua Download is a compressed file , Decompression is available , But you need to compile it first .
LuaContent

There is no executable program by default , You need to use commands to make .

At present src Open the terminal window under the directory , Carry out orders

make

make Then generate lua and luac Two executable programs
makeFile
So we can use Lua This executable program executes what we wrote .lua The file .

I'm using IDE yes Idea,Idea You need to write Lua You need to download a plug-in :EmmyLua
EmmyLua
Using this plug-in, you can highlight and prompt methods , Sure Tab Key auto completion .

Run after installation Lua File needs to configure the interpreter of the file .
ideaConfig
In this way, the overall development environment is well matched .


Two 、Lua Basic grammar

1. notes

Single-line comments

-- Lua  Use  `--`
print("Hello Lua")

Multiline comment

--[[  Multiline comment 1  Multiline comment 2  Multiline comment 3 ]]
print("Hello Lua")

2. identifier

Like any programming language ,Lua The identifier of is composed of letters 、 Numbers and underscores , And can't start with a number , It can't be a keyword
such as :__index

3. Variable

Lua As a weak type language , The definition of variables does not need to declare data types .

--  Integer variable  a
a = 1

--  String variable  a
a = "Test"

--  Boolean type  a
a = false

The scope of variables is global by default , Only declared as local It's the local variable

Variables in weakly typed languages are used casually , If the data type of the variable is used incorrectly , Can only be found at run time , It embodies the idea that norms are greater than conventions .

4. data type

Although the definition of variables does not need to declare data types , however Lua Generally speaking, it is divided into 8 Type of data

  • nil
  • number
  • string
  • boolean
  • function
  • table
  • userdata
  • thread

nil For null , To be an assignment nil The variable of will be cleared ,userdata and thread I haven't contacted yet , Other types only nil and table The concept of is quite special .

notes :Lua The Boolean value in is only nil and false It is the no judgment of conditional expression .

-- number Type is also true 
a = 1
if a then
    print("a yes ture")
end 

--  Function types are also true values 
function fn() 
    print("fn function ")
end
if fn then
    print("fn As long as the function is not nil It's also true ")
end 

5. Lua Operator

1) Arithmetic operator

  • + Add
  • - Subtraction
  • * Multiplication
  • / division ( Real operation , Will not take an integer ,Java inside 10/3=3, here 10/3=3.3333333333333)
  • % Seeking remainder
  • ^ Power operation ( 2^3=8.0)
  • - Minus sign , Add a negative number directly in front of the number
  • // Integer operation , This is the same Java Division of ,10/3=3

2) Logical operators

  • and Logic and computation
  • or Logic or operation
  • not Logical non operation

3) Relational operator

  • >
  • <
  • ==
  • >=
  • <=
  • ~=

Be careful Lua Is not equal to writing ~= This is a very new way of writing .

4) Other operators

Lua There's nothing like ++, -- The operation of , Be careful when cycling !

  • .. String concatenation , Same as Java Of + String concatenation
  • # Returns the length of a string or table
print(#"Hello")     --  Output  5

tab = {
    1,2,3}
print(tab)          --  Output 3

3、 ... and 、 Circulation and process control

Lua Loops are similar to other languages , Just pay attention to the basic format .

1. loop

Three cycles

  • while
  • for
  • repeat … until
--  Mode one  while  loop 
a = 0
while a < 10 do
    print("while loop "..a)
    a = a + 1
end

--  Mode two  for  loop 
for i = 1, 10 do
    print("for loop "..i)
end

--  Mode three  repeat  loop 
c = 0
repeat
    print("repeat loop "..c)
    c = c + 1
until c > 10

repeat … until A cycle is like Java Medium do…while loop , At least once .

2. Process control

-- if  structure 
if a>b then
    return a
end

-- if elseif else  structure 
if a > 90 then
    print(" good ")
elseif a > 80 then
    print(" good ")
elseif a > 60 then
    print(" pass ")
else
    print(" fail, ")
end

There is nothing special about circulation and process control , Note the basic format ,Lua Inside, whether function or loop control , It's all about end ending

Four 、 function

Lua Functions are special , The first encounter can return multiple values .

1. The basic definition

--  Mode one 
function f1()
    -- do something
end

--  Mode two 
local f2 = function(arg1,arg2,arg3) 
    -- do something
    return arg1,arg2,arg3
end

Lua The only function modifiers of are local Define whether it is a local function , Parameters can be chosen . It can be similar to function f2, Multiple data can be returned .

When receiving the return value of the function, you can also receive multiple variables one by one .

function f3()
    return 1,2,3
end

a,b,c = f3()
print(a,b,c)    --  Output  1,2,3

2. Variable parameters

Function receives variable parameters with built-in variables arg This needs mainly , He is a watch table

-- `...`  Represents a variable parameter 
function f4(...)
    local arg = {
    ...}

    --  Traversal mode 1 
    for k, v in pairs(arg) do
        print(k,v)
    end

    --  Traversal mode 2 
    for k, v in ipairs{
    ...} do
        print(k,v)
    end

    print(#arg)                         --  Definition  local = {...}  It can be done by  #arg  Get the number of parameters 
    print(select("#",...))       -- select("#",...)  Get the number of variable parameters 
end

f4(1,2,3,4)                             --  Finally print  4

--  Function passed as parameter 

function f5(func)
    local ret = func
    
end

notes : The key point is how to obtain variable parameters and how to obtain data

in addition ,ipairs and pairs The main difference is ipairs encounter nil Will stop , and pairs Traversal will not .

for k,v in pairs(table) do … end This is a basically fixed way to write traversal tables , similar Java Enhancement in for loop .

3. Function passed as parameter

When a function is passed as a parameter to the next function , This function can be called in the function to do some data processing

function max(a,b)
    if a > b then
        return a
    else
        return b
    end
end

function printMax(a,b,maxFunc)
    print(maxFunc(a,b))
end

printMax(2,3,max)

5、 ... and 、 Tables and arrays

Table is Lua The most commonly used data structure in , Basically, data is used through tables , But I understand it is more like a Map Containers , Store some key,value The key/value pair .

1. The basic definition

--  Arrays have no separate representation , Arrays are represented by tables , Just not key, Default key Namely 1,2,3... Continuous index 
--  A pair of curly braces means this is a table , One of the previous data types is table Table data type 
tab = {
    }

--  It can also be initialized ( Array )
fruits = {
    "apple","peach","banana"}

--  This should be considered as a table , With designated key-value The form 
table_define = {
    
    key1 = "val",
    key2 = "val2",
    key3 = "val3"
}

--  Or add data to the table 
tab["key"] = "value"

--  assignment  nil  Just empty a table 
tab = nil

--  The reference of the table is assigned to another 
newFruits = fruits
fruits = nil            -- newFruits  The table pointed to is actually still , It's just empty fruits It's just 

2. Common methods of table operation

notes :Lua The indexes in are from 1 At the beginning , instead of 0!

2.1 insert data

tab = {
    }
--  Insert the end of the table by default 
table.insert(tab,"value1")
print(tab[1])

--  Insert the specified index location 
table.insert(tab,1,"value2")

print(tab[1])

2.2 Delete data

fruits = {
    "apple", "peach", "banana", "orange"}

fruits[1] = nil
print(fruits[1])        -- nil

table.remove(fruits,2)
print(fruits[2])        -- banana

--  Remove the last data of the table by default 
table.remove(fruits)
for k,v in pairs(fruits) do
    print(v)            -- banana
end

2.3 Splice table data

tab = {
    "Lua", "C#", "Java"}

--  Splice data elements 
print(table.concat(tab))                   -- LuaC#Java

--  Specify the separator of the splice 
print(table.concat(tab," "))               -- Lua C# Java

--  Specify the separator and the data splicing within the specified index range 
print(table.concat(tab," ",2,3))           -- C# Java

2.4 Sort

tab = {
    "Lua", "C#", "Java"}

--  call table Sorting method of 
table.sort(tab)

6、 ... and 、 Modules and packages

This is the closest concept to programming development , Modularize the code , however Lua There is no real bag Module The concept of , Packages are also implemented through tables .

1. Module definition

Module = {
    }

Module.name = " Module package "

Module.func = function() 
    print(" file module.lua The function in func")
end

--  Can pass local encapsulation , Can only be called by method 
local address = "SZ"
Module.getAddress = function()
    return address
end

local func_local = function()
    print("local function ")
end

Module.getLocalFunc = function()
    func_local()
end

2. Package Introduction

The introduction of packages uses keywords require

--  Two ways of writing , And so on. module, File name ,module.lua This file was introduced 
require "module"

require("module")

--  After introducing the package, you can access the contents of the package 
print(Module.name)
Module.func()

print(Module.getAddress())
print(Module.getLocalFunc())

7、 ... and 、 Metatable

Metatable understanding is more like definition element like that , Smaller units , He allows us to define an off table behavior , Besides giving, deleting and modifying . For example, add two tables .

1. The basic definition

myTable = {
    }    --  Common watch 
myMetaTable = {
    }    --  Metatable 
--  Will return to the normal table 
myTable = setmetatable(myTable,myMetaTable) --  take myMetaTable Set to myTable The yuan table of 

getmetatable(myTable)   --  return  myMetaTable  Metatable  

2. Metamethod

2.1 __index Metamethod

When looking up key When the corresponding value is none , Then call this method to find the data in the corresponding table .

Understanding is more like an extension of ordinary tables .

other = {
    key = 3}
t = setmetatable({
    },{
    __index = other})  --  Ordinary table is empty , There are elements in the meta table  key = 3

print(t.key)    -- 3

If __index If you include a function ,Lua That function will be called ,table And keys are passed as arguments to the function .
__index Meta method to see if the elements in the table exist , If it doesn't exist , The return result is nil; If it exists, it is determined by __index Return results .

mytable = setmetatable({
     key1 = "value1" } , {
     
    __index = function(mytable,key)
        if  key == "key2" then
            return "metatablevalue"
        else
            return nil
        end
        
    end
})
print(mytable.key1,mytable.key2)
summary

Source: rookie tutorial

Lua Rules for finding a table element , In fact, it is as follows 3 A step :

  1. Find in table , If you find , Return the element , If you can't find it, continue
  2. Judge whether the table has meta table , If there is no meta table , return nil, If there is a meta table, continue .
  3. Judge whether the meta table has __index Method , If __index Method is nil, Then return to nil;
    1. If __index The method is a table , Then repeat 1、2、3;
    2. If __index Method is a function , Returns the return value of the function .

2.2 __newIndex Metamethod

__newIndex For nonexistent key Call when assigning values

mytable = setmetatable({
    key1 = "value1"}, {
    
    __newindex = function(mytable, key, value)
        rawset(mytable, key, "\""..value.."\"")
    end
})

mytable.key1 = "new value"
mytable.key2 = 4

print(mytable.key1,mytable.key2)

2.3 __tostring Metamethod

__tostring bring print(table) You can output strings instead of table references

mytable = setmetatable({
     10, 20, 30 }, {
    
  __tostring = function(mytable)
    sum = 0
    for k, v in pairs(mytable) do
                sum = sum + v
        end
    return " The sum of all elements in the table is  " .. sum
  end
})
print(mytable)

8、 ... and 、 Collaborative process

Collaborative programs are actually collaborative functions , Let the function hang halfway through the execution , Then continue to execute the following code , Only when the collaboration function is started can the collaboration function hungry code continue to be executed .

1. Common methods :

  • coroutine.create(func) Create a collaboration function , Parameter is a function
  • coroutine.resume() Start the created collaboration function , collocation coroutine.create()
  • coroutine.yield() Pause the collaboration function , Parameters can be used as the return value of the function , Same as return effect
  • coroutine.status() Check the status of the collaboration function , There are three :suspended,dead,running Pause , Death , function
  • coroutine.wrap() Same as create+resume, Create and launch , It seems that you can't continue to start after stopping
  • coroutine.running() Return to the running coroutine, A running coroutine It's just a thread

2. Classic production and consumption problems

local co

--  Every time a producer produces one, it provides it to consumers 
function productor()
    local i = 0
    while true do
        i = i + 1
        print(" Producers produce \t"..i)
        sleep(1)
        coroutine.yield(i)
    end
    print(" No product production , Producer ends ")
end

function consumer()
    while coroutine.status(co) ~= "dead" do
        print(" Consumers wake up production ")
        local status, value = coroutine.resume(co)
        print(" Consumer consumption \t"..value)
        sleep(1)
    end
    print(" Consumers know that production is over , End of consumption ")
end

function sleep(n)
    local t = os.clock()
    while os.clock() -t <=n do end
end

--  Create producer collaboration function 
co = coroutine.create(productor)
--  Start spending 
consumer()

notes :Lua Language has no native thread sleep function , The definition here is not very clear , The general understanding is os.clock Return the running time of the program , Use the time difference to judge the sleep time .

Nine 、 file IO

file IO It is divided into simple mode and complete mode , File opening is divided into :

  • r read-only , The file must exist
  • w Just write , Write in an overlay
  • a Just write , Write in an additional way
  • r+ read-write , The file must exist
  • w+ read-write , If the file exists, it will overwrite , Create if file does not exist
  • a+ read-write , Write in an additional way
  • b Binary , If you open a binary file, you need to add b
  • Represent readable and writable

1. Simple mode

--  Open a file read-only 
file = io.open("tmp.txt","r")

--  Set up io The input file for is file
io.input(file)

--  Read a line 
line = io.read()

--  When closing a file, you should also specify a file 
io.close(file)

2. Full mode

--  Open as read-only tmp.txt file 
file = io.open("tmp.txt", "r")

--  Read a line directly , no need io.input(file) Specify the input file 
line = file:read()

--  Close file 
file:close()

above read Methods read a row of data by default , You can specify read() The parameters of the function , Represents different reading methods

  • *n Read a number and return , It has to be numbers
  • *a Read the entire file
  • *| Read a line ( Default mode ) It seems that errors are always reported during the test , Unknown reason
  • number give an example :file.read(4) Specify read 4 Characters

Ten 、 object-oriented

Lua The use of object-oriented should be the ultimate form .

Object-oriented cannot escape three characteristics , encapsulation 、 Inherit 、 polymorphic .

  • encapsulation Valid encapsulation attributes , Reasonable external exposure .
  • Inherit Extension of parent attribute , For example, there is a human model , You can inherit the student object from the parent object person , Make it have some attributes and methods that people have .
  • polymorphic Multiple forms of one type , according to Java The argument is that the reference of the parent class points to the object of the child class , For example, data are animals , But it can be in different forms, such as , cat , Dogs belong to animals

object

-- Lua  It's full of table data , There is no concept of objects , So the so-called class , Objects are simulated in a form 

--  Define a Person class 
Person = {
    
   name = nil,
   age = nil
}

--  Define methods 
Person.eat = function(self)
   print(self.name.." Eating ")
end

--  call 
Person.name = " Jay Chou "
Person.age = 42
Person.eat(Person)

--  If there's another one Person object , You need to define the above again Person, So you can simulate the construction method of a class 
function Person:new(o)
   local t = o or {
    }
   setmetatable(t, {
    __index = self})
   return t
end

-- eat  Method improvement , Later programming is mostly in this form 
function Person:eat()
   print(self.name.." Eating ")
end

p1 = Person:new()
p1.name = " Huang Shengyi "
print(p1:eat())

11、 ... and 、 Famine source code Lua Study

The source code in famine is Lua file , use ECS(Entity, Components, System) frame , That is, entity 、 To form a 、 System .

This framework is different from object-oriented , It is more data oriented ;
Entity understanding is object , One by one in kind , For example, the flowers in the game 、 Pig man , Rabbits, etc , Components are behaviors , For example, flowers have collectable attributes , therefore Pickable.lua The file exists in the component code .

The system is the mechanism to control the whole game . The system doesn't care about the behavior of components , The component does not relate to what the entity is .

Definition of class in famine
class.lua file – Basically, I feel the above after reading Lua All in vain , Vomit .

-- class.lua
-- Compatible with Lua 5.1 (not 5.0).

local TrackClassInstances = false

ClassRegistry = {
    }

if TrackClassInstances == true then
   global("ClassTrackingTable")
   global("ClassTrackingInterval")

   ClassTrackingInterval = 100
end

local function __index(t, k)
   local p = rawget(t, "_")[k]
   if p ~= nil then
      return p[1]
   end
   return getmetatable(t)[k]
end

local function __newindex(t, k, v)
   local p = rawget(t, "_")[k]
   if p == nil then
      rawset(t, k, v)
   else
      local old = p[1]
      p[1] = v
      p[2](t, v, old)
   end
end

local function __dummy()
end

local function onreadonly(t, v, old)
   assert(v == old, "Cannot change read only property")
end

function makereadonly(t, k)
   local _ = rawget(t, "_")
   assert(_ ~= nil, "Class does not support read only properties")
   local p = _[k]
   if p == nil then
      _[k] = {
     t[k], onreadonly }
      rawset(t, k, nil)
   else
      p[2] = onreadonly
   end
end

function addsetter(t, k, fn)
   local _ = rawget(t, "_")
   assert(_ ~= nil, "Class does not support property setters")
   local p = _[k]
   if p == nil then
      _[k] = {
     t[k], fn }
      rawset(t, k, nil)
   else
      p[2] = fn
   end
end

function removesetter(t, k)
   local _ = rawget(t, "_")
   if _ ~= nil and _[k] ~= nil then
      rawset(t, k, _[k][1])
      _[k] = nil
   end
end

function Class(base, _ctor, props)
   local c = {
    }    -- a new class instance
   local c_inherited = {
    }
   if not _ctor and type(base) == 'function' then
      _ctor = base
      base = nil
   elseif type(base) == 'table' then
      -- our new class is a shallow copy of the base class!
      -- while at it also store our inherited members so we can get rid of them
      -- while monkey patching for the hot reload
      -- if our class redefined a function peronally the function pointed to by our member is not the in in our inherited
      -- table
      for i,v in pairs(base) do
         c[i] = v
         c_inherited[i] = v
      end
      c._base = base
   end

   -- the class will be the metatable for all its objects,
   -- and they will look up their methods in it.
   if props ~= nil then
      c.__index = __index
      c.__newindex = __newindex
   else
      c.__index = c
   end

   -- expose a constructor which can be called by <classname>(<args>)
   local mt = {
    }

   if TrackClassInstances == true and CWD~=nil then
      if ClassTrackingTable == nil then
         ClassTrackingTable = {
    }
      end
      ClassTrackingTable[mt] = {
    }
      local dataroot = "@"..CWD.."\\"
      local tablemt = {
    }
      setmetatable(ClassTrackingTable[mt], tablemt)
      tablemt.__mode = "k"         -- now the instancetracker has weak keys

      local source = "**unknown**"
      if _ctor then
         -- what is the file this ctor was created in?

         local info = debug.getinfo(_ctor, "S")
         -- strip the drive letter
         -- convert / to \\
         source = info.source
         source = string.gsub(source, "/", "\\")
         source = string.gsub(source, dataroot, "")
         local path = source

         local file = io.open(path, "r")
         if file ~= nil then
            local count = 1
            for i in file:lines() do
               if count == info.linedefined then
                  source = i
                  -- okay, this line is a class definition
                  -- so it's [local] name = Class etc
                  -- take everything before the =
                  local equalsPos = string.find(source,"=")
                  if equalsPos then
                     source = string.sub(source,1,equalsPos-1)
                  end
                  -- remove trailing and leading whitespace
                  source = source:gsub("^%s*(.-)%s*$", "%1")
                  -- do we start with local? if so, strip it
                  if string.find(source,"local ") ~= nil then
                     source = string.sub(source,7)
                  end
                  -- trim again, because there may be multiple spaces
                  source = source:gsub("^%s*(.-)%s*$", "%1")
                  break
               end
               count = count + 1
            end
            file:close()
         end
      end

      mt.__call = function(class_tbl, ...)
         local obj = {
    }
         if props ~= nil then
            obj._ = {
     _ = {
     nil, __dummy } }
            for k, v in pairs(props) do
               obj._[k] = {
     nil, v }
            end
         end
         setmetatable(obj, c)
         ClassTrackingTable[mt][obj] = source
         if c._ctor then
            c._ctor(obj, ...)
         end
         return obj
      end
   else
      mt.__call = function(class_tbl, ...)
         local obj = {
    }
         if props ~= nil then
            obj._ = {
     _ = {
     nil, __dummy } }
            for k, v in pairs(props) do
               obj._[k] = {
     nil, v }
            end
         end
         setmetatable(obj, c)
         if c._ctor then
            c._ctor(obj, ...)
         end
         return obj
      end
   end

   c._ctor = _ctor
   c.is_a = function(self, klass)
      local m = getmetatable(self)
      while m do
         if m == klass then return true end
         m = m._base
      end
      return false
   end
   setmetatable(c, mt)
   ClassRegistry[c] = c_inherited
   -- local count = 0
   -- for i,v in pairs(ClassRegistry) do
   -- count = count + 1
   -- end
   -- if string.split then
   -- print("ClassRegistry size : "..tostring(count))
   -- end
   return c
end

function ReloadedClass(mt)
   ClassRegistry[mt] = nil
end

local lastClassTrackingDumpTick = 0

function HandleClassInstanceTracking()
   if TrackClassInstances and CWD~=nil then
      lastClassTrackingDumpTick = lastClassTrackingDumpTick + 1

      if lastClassTrackingDumpTick >= ClassTrackingInterval then
         collectgarbage()
         print("------------------------------------------------------------------------------------------------------------")
         lastClassTrackingDumpTick = 0
         if ClassTrackingTable then
            local sorted = {
    }
            local index = 1
            for i,v in pairs(ClassTrackingTable) do
               local count = 0
               local first = nil
               for j,k in pairs(v) do
                  if count == 1 then
                     first = k
                  end
                  count = count + 1
               end
               if count>1 then
                  sorted[#sorted+1] = {
    first, count-1}
               end
               index = index + 1
            end
            -- get the top 10
            table.sort(sorted, function(a,b) return a[2] > b[2] end )
            for i=1,10 do
               local entry = sorted[i]
               if entry then
                  print(tostring(i).." : "..tostring(sorted[i][1]).." - "..tostring(sorted[i][2]))
               end
            end
            print("------------------------------------------------------------------------------------------------------------")
         end
      end
   end
end
原网站

版权声明
本文为[tough is tough]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207070514382607.html