Lua and Love2d



Lua and Love2d

0 0


lua-intro


On Github dark5un / lua-intro

Lua and Love2d

An ultra-fast path to 2D gaming...

Oh I realy wanted to make this

presentation in Love2d

So what is Lua anyway?

Lua - an extensible extension language

What?

What is Lua like?

Lua has a mix of C-like and Pascal-like syntax.

Lua is dynamically typed (like JavaScript).

Fast syntax

Spaces don't matter

Linebreaks don't matter

Indentation doesn't matter

No semicolons

On a given line, any text to the right of -- is considered a comment

Numbers.

123 and 0.456 are numbers.

Lua doesn't make a distinction between integer and real numbers.

Mathematical expressions +, -, * and / can be used on numbers.

> print(2+2)
4
> print ( 5 / 2 )
2.5
        

Booleans.

true and false are booleans.

==, >, <, >=, <= are comparison operators.

~= is "not equal" operator (instead of !=).

There are also: and, or, not.

> print(5 >= 3 and not (3 < 0))
true
> print(2.5 == 2)
false
      

Strings.

Strings represent a sequence of characters.

They can be enclosed in " (double quote) or ' (single quote) symbols (Choosing one, the other won't be considered a control symbol).

Escape symbols is done with \. Concatenation operator is .. (instead of + in some languages).

> print( "I am printin' \"My first string\"\non two lines" )
I am printin' "My first string"
on two lines
        

From Numbers To Strings

Numbers are automatically treated as strings when concatenated, but other types (such as the boolean (5 == 0) in the example below) are not - use tostring on them.

> print( "This number is " .. 5 .. " and it equals zero: " .. tostring(5 == 0))
This number is 5 and it equals zero: false
        

nil.

nil (like null in many languages) means nothing. And equals nothing except itself.

Tables.

Tables are ubiquitous in Lua.

A table is an array and a hashmap (dictionary) at the same time.

It is an ad hoc data structure.

An empty table is defined like this: {}.

Table keys can be of any type - integer, string, boolean or even another table.

> x = {}          -- Wow, we defined our first variable! Yes, it is simple like this.
> x[1] = "our first item"
> print(x[1])     -- This is how we get a value by key from the table
our first item
> x["wm"] = "awesome"
> print(x["wm"])
awesome
        

Initializing Tables

You can define a table and some initial key values simultaneously.

This is done like: y = { key = "somevalue", anotherkey = "anothervalue" }.

Comma is a separator here.

Only string keys (without quotes) are supported this way.

Lua offers one nifty mechanism for tables - you can access the values by the string key with following syntax: table.key. This creates an illusion of a data structure.

> x = {}
> x.color = "white"  -- Same as x["color"] = "white"
> print(x.color)
white
> x.wm_langs = { xmonad = "Haskell", awesome = "Lua" }
> print(x.wm_langs.awesome) -- Same as x["wm_langs"]["awesome"]
Lua
        

Nil/Empty Tables

If table doesn't have any value for the given key it means that the value equals nil.

> x = {}
> print(x.blahblah)
nil
        

Initializing Tables

You can initialize tables without specifying keys, then it will act as an array with values mapped to number keys.

> x = { "first", "second", "third" }
> print(x[2])
second
> print(x.2)     -- No, no! Only string keys can be referenced like this!
stdin:1: `)' expected near `.2'
> print(x["2"])  -- 2 and "2" are not equal, of course
nil
        

Function.

We will talk about functions later, now you should know, that any function can be assigned to a variable, passed as an argument or be returned from another function.

> ourfunction = print
> ourfunction(2+2)
4
> get_length = string.len
> ourfunction(get_length("some string"))
11
        

Variables

Lua is dynamically typed.

That means that you don't have to define the type explicitly - any variable can have any type.

Until variable gets declared it has the value nil.

To declare a variable just assign value to it.

> print(a)  -- a wasn't declared yet
nil
> a = 42
> print(a)
42
> a = "the answer is " .. a
> print(a)
the answer is 42
        

Local Variables

Whenever you assign value to a variable, it becomes visible to the whole environment.

It becomes global (you can avoid it by using modules)

To keep your variables inside use the keyword local.

With local your variable will be visible only to the block (function, control structure, file) where it is defined.

> a = 42
> if a == 42 then            -- If you press "Return" here, the next line will be 
>> local a = 10              -- preceeded with >>. This means that you are currently
>> print("Inside: " .. a)    -- inside the block (in this case, if..then block)
>> local b = 100
>> end
Inside: 10
> print(a)
42                           -- See, local binding replaced a with 10 only inside the block
> print(b)
nil                          -- And the variable b was never globally declared
        

Multiple assignment

In Lua you can assign many values to many variables at the same time. It looks like this:

> a, b, c = 1, "and", 2
> print(a..b..c)
1and2
> a, b, c = 1, "and"
> print(c)
nil      -- c hadn't got its value pair, so it was assigned to nil
> a, b, c = 5, "and", 6, "and", 7
> print(a..b..c)
5and6    -- all unused values just went to Limbo
        

Conditions

The syntax is simple: if condition then code else code end.

> food = "beans"
> if food == "cake" then
>> print("Yummy!")
>> else
>> print("Ew, I won't eat that!")
>> end
Ew, I won't eat that!
        

We can leave aside the else part if we are not interested in it.

> under_attack = true
> if under_attack then    -- Booleans can be used like this in conditions
>> print("Alarm!")
>> end
Alarm!
        

Elseif

If you want to analyze more conditions, use elseif:

> n = -42
> if n > 0 then
>> print("Positive")
>> elseif n < 0 then
>> print("Negative")
>> else
>> print("Zero")
>> end
Negative
        

Conditional loop.

Has the following syntax: while condition do code end.

> i, r = 0, ""
> while i < 10 do
>> r = r .. i
>> i = i + 1
>> end
> print(r)
0123456789
        

For loop.

To loop through a range of numbers use the folowing construct:

for var = start_num,end_num do code end.

> r = ""
> for i = 0, 9 do
>> r = r .. i
>> end
> print(r)
0123456789
        

Foreach loop.

Lua allows you iterate through a table with the following syntax:

for key_var, value_var in pairs(table_name) do code end.

> a = { red="#FF0000", yellow="#FFFF00", white="#FFFFFF" }
> for name, color_code in pairs(a) do
>> print(name .. " is " .. color_code)
>> end
yellow is #FFFF00
white is #FFFFFF
red is #FF0000
        

Ipairs

You can iterate through an "array" with ipairs.

In this case the order is guaranteed.

> a, caesar = { "veni, ", "vidi, ", "vici" }, ""
> for i, v in ipairs(a) do
>> caesar = caesar .. v    -- We just don't use the key, only value
>> end
> print(caesar)
veni, vidi, vici
        

Functions

The basic syntax for defining a function is: function_name = function(arguments) code end.

To return the value from a function use the keyword return.

> sum = function(a,b) return a + b end
> print( sum(2,2) )
4
        

Arguments

If you don't supply some arguments to a function, then they will just be assigned to nil.

> print_three_args = function(a, b, c)
>> print("First: " .. tostring(a))    -- We use tostring() here because 
>> print("Second: " .. tostring(b))   -- nil is not automatically cast
>> print("Third: " .. tostring(c))    -- when concatenated
>> end
> print_three_args(10,20)
First: 10
Second: 20
Third: nil
        

Return Values

The function can return more than one value at once.

You need to use multiple assignment to get all result values.

> sum_and_diff = function(a, b) 
>> return a+b, a-b
>> end
> x, y = sum_and_diff(5,3)
> print(x, y)   -- print() can actually handle more than one argument.
8     2         -- It prints them separated by tab.
        

Function Definition

There is a more convenient way to define functions: function function_name (arguments) code end

> function doubler (x)
>> return x * 2
>> end
> print( doubler(42) )
84
        

Nil in conditions

In conditions nil always evaluates to false.

It allows to do such witty tricks:

> f = io.open("foo.txt")  -- Trying to open some file. If the file exists, than
> if f then               -- variable f will contain some table, else f will be nil.
>> print("File exists")
>> else print("File not found") end
File not found
        

Default Arguments

> function multiplicator (x, y)
>> y = y or 2    -- If y is nil, then it will be assigned to 2
>> return x * y
>> end
> print(multiplicator(10, 3))
30
> print(multiplicator(10))
20
        

Enough about LUA...

PHEW....

LOVE2D !!!

My first game... lol

Create a main.lua file inside a dir of your choosing...

Fill it with the code below:

function love.draw()
    love.graphics.print("Hello World", 400, 300)
end          
        

The LOVE2D Basics

Callback Functions

love.load

This function gets called only once, when the game is started, and is usually where you would load resources, initialize variables and set specific settings. All those things can be done anywhere else as well, but doing them here means that they are done once only, saving a lot of system resources.

function love.load()
   image = love.graphics.newImage("cake.jpg")
   local f = love.graphics.newFont(12)
   love.graphics.setFont(f)
   love.graphics.setColor(0,0,0,255)
   love.graphics.setBackgroundColor(255,255,255)
end
        

love.update

This function is called continuously and will probably be where most of your math is done. 'dt' stands for "delta time" and is the amount of seconds since the last time this function was called (which is usually a small value like 0.025714).

function love.update(dt)
   if love.keyboard.isDown("up") then
      num = num + 100 * dt -- this would increment num by 100 per second
   end
end
        

DT?

Returns the time between the last two frames.

        dt = love.timer.getDelta( )
        

love.draw

function love.draw()
   love.graphics.draw(image, imgx, imgy)
   love.graphics.print("Click and drag the cake around or use the arrow keys", 10, 10)
end
        

love.draw is where all the drawing happens (if that wasn't obvious enough already) and if you call any of the love.graphics.draw outside of this function then it's not going to have any effect. This function is also called continuously so keep in mind that if you change the font/color/mode/etc at the end of the function then it will have a effect on things at the beginning of the function. For example:

function love.load()
   love.graphics.setColor(0,0,0)
end
function love.draw()
   love.graphics.print("This text is not black because of the line below", 100, 100)
   love.graphics.setColor(255,0,0)
   love.graphics.print("This text is red", 100, 200)
end          
        

love.mousepressed

This function is called whenever a mouse button is pressed and it receives the button and the coordinates of where it was pressed. The button can be any of the constants. This function goes very well along with love.mousereleased.

function love.mousepressed(x, y, button)
   if button == 'l' then
      imgx = x -- move image to where mouse clicked
      imgy = y
   end
end          
        

love.mousereleased

This function is called whenever a mouse button is released and it receives the button and the coordinates of where it was released. You can have this function together with love.mousepressed or separate, they aren't connected in any way.

function love.mousereleased(x, y, button)
   if button == 'l' then
      fireSlingshot(x,y) -- this totally awesome custom function is defined elsewhere
   end
end          
        

love.keypressed

This function is called whenever a keyboard key is pressed and receives the key that was pressed. The key can be any of the constants. This functions goes very well along with love.keyreleased.

function love.keypressed(key, unicode)
   if key == 'b' then
      text = "The B key was pressed."
   elseif key == 'a' then
      a_down = true
   end
end          
        

love.keyreleased

This function is called whenever a keyboard key is released and receives the key that was released. You can have this function together with love.keypressed or separate, they aren't connected in any way.

function love.keyreleased(key, unicode)
   if key == 'b' then
      text = "The B key was released."
   elseif key == 'a' then
      a_down = false
   end
end          
        

love.focus

function love.focus(f)
  if not f then
    print("LOST FOCUS")
  else
    print("GAINED FOCUS")
  end
end          
        

This function is called whenever the user clicks off and on the LÖVE window. For instance, if they are playing a windowed game and a user clicks on his Internet browser, the game could be notified and automatically pause the game.

function love.focus(f) gameIsPaused = not f end
function love.update(dt)
    if gameIsPaused then return end
    -- The rest of your love.update code goes here
end
        

love.quit

This function is called whenever the user clicks the windows close button (often an X). For instance, if the user decides they are done playing, they could click the close button. Then, before it closes, the game can save its state.

function love.quit()
  print("Thanks for playing! Come back soon!")
end          
        

Enough I think lets CODE!

THANKS!

special thanks to awesome wm wiki and love2d wiki (did you expect me to write all these alone?)

twitter: @tehn00b