Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Lua Game Development Cookbook
Lua Game Development Cookbook

Lua Game Development Cookbook: Over 70 recipes that will help you master the elements and best practices required to build a modern game engine using Lua

eBook
$29.99 $43.99
Paperback
$54.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Lua Game Development Cookbook

Chapter 1. Basics of the Game Engine

In this chapter, we will cover the following recipes:

  • Preparing a basic file structure for the game engine
  • Making a stack
  • Making a queue
  • Making a prioritized queue
  • Extending ipairs for use in sparse arrays
  • Creating Lua modules
  • Handling errors with pcall, xpcall, and assert
  • Using Lua with existing projects written in C/C++
  • Getting LuaSDL for libSDL 1.2
  • Designing the main application loop with LuaSDL

Introduction

Almost every game uses a game engine to help developers in video game production. It is usually used as a base platform for the game and manages all important functions from 2D/3D graphics, physics, sound effects, and network communication to artificial intelligence, scripting, and support for various software/hardware platforms. Using the scripting language in games has gained a lot of attention in the last decade mainly because it allows you to create game prototypes faster, easier, and it's an important part of the so-called modding support for the game community.

For instance, you can look at Quake game from the id software company, which uses its own scripting language Quake C and is one of the reasons why there are so many mods for this game. However, the source code for this language must be compiled before using. Depending on the project size this means a significant amount of time spent between feature implementation and testing. The Lua language can be used without prior compilation, which allows developers to test out their code right away.

The first game that used the Lua language for scripting was Grim Fandango from the company LucasArts. It was successfully used in further major game titles and today it can be commonly found in many multiplatform and mobile games.

Modern game engines are one of the most complex applications that are used. This leads to the situation where game developers use game engine as a black box without knowing how it actually works. For certain game titles, this might work out quite well. However, if you want to make a quick game prototype with certain features that are not present in the game engine, you'll most probably have to write your own game engine extension or find a workaround.

Lua language is fast and mature enough to be used as a game engine base language. Time-critical portions of a code can be written in C or C++ language and accessed via a Lua/C language interface. With this approach, you can view the Lua language as a high-level glue for the game engine process design.

This book will use Lua 5.1 version mainly because it's well supported and the existing code can be ported into a newer version with minor changes. Another reason behind this choice is that Lua 5.1 API is used in LuaJIT which is Just-In-Time implementation of Lua language. It's generally regarded as a faster version of the Lua language, which gives you speed comparable to compiled C code.

Lua language itself doesn't provide access to graphical output, sound devices or even input devices except basic I/O file interface. This shortcoming can be overcome with the use of LuaSDL binding to libSDL multimedia library that gives us the power to access all the devices needed to create a game with graphics and sounds. Installation and use of this library binding will be contained in this chapter.

It's always good practice to maintain a consistent file structure in any project. The Lua language doesn't formally specify modular structure and it's often the case when each module uses its own style of module specification. This results in namespace conflicts and unpredictable behavior.

The first part of this chapter will cover the preparation of a modular file structure for your application, implementation of the most common data structures, and error handling.

The second half of this chapter will deal with more advanced stuff such as writing and using the Lua modules and using libSDL multimedia library to develop interactive applications in Lua.

Preparing a basic file structure for the game engine

When programming a larger project, it's always important to keep it maintainable. One of the common practices is to keep a modular structure. Modular structure can be achieved by keeping files separated in certain directories.

Lua language uses a require function to include modules in your script files. This function uses a default list of paths where it tries to find the module file. The Lua modules can be written as plain Lua scripts or use a form of binary library, which is OS and CPU architecture dependent. This is especially troublesome if want to include binary libraries for all supported operating systems and CPU architectures in one project.

A default set of paths might not always be appropriate for your project, mainly if you bundle many third-party modules with it.

This recipe shows how to set up the Lua interpreter so that it can find correct files in a systematic and user-definable way. This recipe should be used at the beginning of your main Lua script file so that further calls to the require function in Lua will use your file path structure.

Getting ready

You can use a directory structure as shown in the following diagram. If you intend to implement your application for multiple platforms, always divide platform-specific files into separate directories.

Getting ready

The Lib directory contains all the Lua module files and binary libraries.

However, each operating system uses its own file naming convention for binary libraries. The Lua language doesn't have an easy way to obtain the OS name. For this purpose, you can download and use the Lua script module os_name.lua from https://gist.github.com/soulik/82e9d02a818ce12498d1.

You should copy this file into your project directory so that the Lua interpreter can find it.

How to do it…

The require function in the Lua language uses a set of default paths defined in package.path and package.cpath string variables. With your new directory structure, you'd have to change those two variables manually for each operating system, which could be cumbersome.

Instead, you can define a Lua script to build up these two string variables from a generic list of paths for both Lua script files and binary libraries.

In the first step, you need to create a list of directories:

-- A list of paths to lua script modules
local paths = {
  '{root}/{module}',
  '{root}/lib/{module}',
  '{root}/lib/external/{module}',
  '{root}/lib/external/platform-specific/{platform}/{module}',
}
-- A list of paths to binary Lua modules
local module_paths = {
  '?.{extension}',
  '?/init.{extension}',
  '?/core.{extension}',
}

Strings enclosed with curly brackets will be substituted with the following values:

Name

Value

root

This is the application's root directory

platform

This is the current platform

module

This is the module's file path

extension

This is the module's filename extension, which is platform dependent

Binary module filename extensions that are platform dependent are also set in a table:

-- List of supported OS paired with binary file extension name
local extensions = {
  Windows = 'dll',
  Linux = 'so',
  Mac = 'dylib',
}

Now, you need to set root_dir which is the current working directory of the application and the current platform name as follows:

-- os_name is a supplemental module for
-- OS and CPU architecture detection
local os_name = require 'os_name'

-- A dot character represent current working directory
local root_dir = '.'
local current_platform, current_architecture = os_name.getOS()

local cpaths, lpaths = {}, {}
local current_clib_extension = extensions[current_platform]

Before you start building the path list, you need to check whether the current platform has defined binary module extensions as follows:

if current_clib_extension then
  -- now you can process each defined path for module.
  for _, path in ipairs(paths) do
    local path = path:gsub("{(%w+)}", {
      root = root_dir,
      platform = current_platform,
    })
    -- skip empty path entries
    if #path>0 then
      -- make a substitution for each module file path.
      for _, raw_module_path in ipairs(module_paths) do
        local module_path = path:gsub("{(%w+)}", {
          module = raw_module_path
        })
        -- add path for binary module
        cpaths[#cpaths+1] = module_path:gsub("{(%w+)}", {
          extension = current_clib_extension
        })
        -- add paths for platform independent lua and luac modules
        lpaths[#lpaths+1] = module_path:gsub("{(%w+)}", {
          extension = 'lua'
        })
        lpaths[#lpaths+1] = module_path:gsub("{(%w+)}", {
          extension = 'luac'
        })
      end
    end
  end
  -- build module path list delimited with semicolon.
  package.path = table.concat(lpaths, ";")
  package.cpath = table.concat(cpaths, ";")
end

With this design, you can easily manage your module paths just by editing paths and module_paths tables.

Keep in mind that you need to execute this code before any require command.

How it works…

This recipe builds content for two variables that are used in the require function—package.path and package.cpath.

Both variables use a semicolon as a delimiter for individual paths. There's also a special character—the question mark which is substituted with the module name. Note that the path order might not be as important in this case as with our default list of paths. The path order might cause problems if you expect to use a module out of the project directory structure. Therefore, a customized set of paths from this recipe should always be used before the default set of paths.

The Lua language allows the use of hierarchical structure of modules. You can specify a submodule with package names delimited by a dot.

require 'main_module.submodule'

A dot is always replaced with the correct directory separator.

Making a stack

Stack data structure can be defined in the Lua language as a closure that always returns a new table. This table contains two functions defined by keys, push and pop. Both operations run in constant time.

Getting ready

Code from this recipe will be probably used more than once in your project so that it can be moved into the Lua module file with similar algorithms. The module file can use the following structure:

-- algoritms.lua

-- Placeholder for a stack data structure code 

return {
  stack = stack,
}

This module structure can be used with algorithms from other recipes as well to keep everything organized.

How to do it…

The following code contains a local definition of the stack function. You can remove the local statement to make this function global or include it as part of the module:

local function stack()
  local out = {}
  out.push = function(item)
    out[#out+1] = item
  end
  out.pop = function()
    if #out>0 then
      return table.remove(out, #out)
    end
  end
  out.iterator = function()
    return function()
      return out.pop()
    end
  end
  return out
end

This stack data structure can be used in the following way:

local s1 = stack()
-- Place a few elements into stack
for _, element in ipairs {'Lorem','ipsum','dolor','sit','amet'} do
  s1.push(element)
end

-- iterator function can be used to pop and process all elements
for element in s1.iterator() do
     print(element)
end

How it works…

Calling the stack function will create a new empty table with three functions. Push and pop functions use the property of the length operator that returns the integer index of the last element. The iterator function returns a closure that can be used in a for loop to pop all the elements. The out table contains integer indices and no holes (without empty elements). Both the functions are excluded from the total length of the out table.

After you call the push function, the element is appended at the end of the out table. The Pop function removes the last element and returns the removed element.

Making a queue

The queue data structure can be constructed in a similar way as a stack with the table.insert and table.remove functions. However, this will add unnecessary overhead because each element insertion at the beginning of the list will need to move other elements as well. A better solution is using two indices that indicate the beginning and the end of the list.

Getting ready

The code from this recipe can be placed into the algorithms.lua file as in the Making a stack recipe.

How to do it…

The queue data structure will consist of a constructor that returns a new table with three functions: a push, a pop, and an iterator. The resulting table uses the modified version of the length operator to get the right length of the queue:

local function queue()
  local out = {}
  local first, last = 0, -1
  out.push = function(item)
    last = last + 1
    out[last] = item
  end
  out.pop = function()
    if first <= last then
      local value = out[first]
      out[first] = nil
      first = first + 1
      return value
    end
  end
  out.iterator = function()
    return function()
      return out.pop()
    end
  end
  setmetatable(out, {
    __len = function()
      return (last-first+1)
    end,
  })
  return out
end

A new queue data structure can be created by calling the queue function:

local q1 = queue()
-- Place a few elements into queue
for _, element in ipairs {'Lorem','ipsum','dolor','sit','amet'} do
  q1.push(element)
end

-- You can use iterator to process all elements in single for loop
for element in q1.iterator() do
  -- each queue element will be printed onto screen
  print(element)
end

How it works…

This algorithm uses a pair of integer indices that represent positions of the first and the last element of the queue. This approach provides element insertion and deletion in constant time. Because the original length operator isn't suitable for this case, a modified one is provided.

The iterator function creates a new closure that is used in a for loop. This closure is called repeatedly until the pop function returns an empty result.

Making a prioritized queue

A prioritized queue or simple priority queue extends basic queue with the entry sorting feature. Upon entry insertion, you can set what will be the priority of the entry. This data structure is often used in job queuing where the most important (highest priority) jobs must be processed before the jobs with lower priority. Priority queues are often used in artificial intelligence as well.

This version of the prioritized queue allows you to obtain entries with minimal or maximal priority at constant time. Element priority can be updated. However, priority queue insertion, update, and removal might use linear time complexity in worst case scenarios.

There are two rules that should be noted:

  • Each entry of this queue should be unique
  • The order of retrieving elements with the same priority is not defined

Getting ready

This recipe will use the following shortcuts:

local ti = table.insert
local tr = table.remove

-- removes element from table by its value
local tr2 = function(t, v)
  for i=1,#t do
    if t[i]==v then
      tr(t, i)
      break
    end
  end
end

It's recommended to put it all together in one Lua module file.

How to do it…

The priority queue can be defined as in the following code:

return function pqueue()
  -- interface table
  local t = {}

  -- a set of elements
  local set = {}
  -- a set of priority bags with a elements
  local r_set = {}
  -- sorted list of priorities
  local keys = {}

  -- add element into storage, set its priority and sort keys
  --  k - element
  --  v - priority
  local function addKV(k, v)
    set[k] = v
    -- create a new list for this priority
    if not r_set[v] then
      ti(keys, v)
      table.sort(keys)
      local k0 = {k}
      r_set[v] = k0
      setmetatable(k0, {
        __mode = 'v'
      })
    -- add element into list for this priority
    else
      ti(r_set[v], k)
    end
  end

  -- remove element from storage and sort keys
  local remove = function(k)
    local v = set[k]
    local prioritySet = r_set[v]
    tr2(prioritySet, k)
    if #prioritySet < 1 then
      tr2(keys, v)
      r_set[v] = nil
      table.sort(keys)
      set[k] = nil
    end
  end; t.remove = remove

  -- returns an element with the lowest priority
  t.min = function()
    local priority = keys[1]
    if priority then
      return r_set[priority][1] or {}
    else
      return {}
    end
  end

  -- returns an element with the highest priority
  t.max = function()
    local priority = keys[#keys]
    if priority then
      return r_set[priority][1] or {}
    else
      return {}
    end
  end

  -- is this queue empty?
  t.empty = function()
    return #keys < 1
  end
  -- simple element iterator, retrieves elements with
  -- the highest priority first
  t.iterate = function()
    return function()
      if not t.empty() then
        local element = t.max()
        t.remove(element)
        return element
      end
    end
  end
  -- setup pqueue behavior
  setmetatable(t, {
    __index = set,
    __newindex = function(t, k, v)
      if not set[k] then
        -- new item
        addKV(k, v)
      else
        -- existing item
        remove(k)
        addKV(k, v)
      end
    end,
  })
  return t
end

How it works…

This priority queue algorithm uses three tables: set, r_set, and keys. These tables help to organize elements into so-called priority bags. The first one, set contains elements paired with their priorities. It's also used when you try to obtain element priority from the queue. The second one, r_set contains priority bags. Each bag represents a priority level. The last one keys contains a sorted list of priorities, which is used in the extraction of elements from a minimal or maximal priority bag.

Each element can be inserted in a way similar to the Lua table with the exception that the inserted element is used as a key and priority is stored as a value:

priority_queue[element] = priority

This form of access can be used to update element priority. Elements with minimal or maximal priority can be extracted using the min or max function respectively;

local min_element = priority_queue.min()
local max_element = priority_queue.max()

Note that elements remain in the priority queue until you delete them with the remove function;

priority_queue.remove(element)

Priority queue can be queried with the empty function that returns true if there's no element in the queue;

priority_queue.empty()

You can use the iterator function in for loop to process all queue elements sorted by their priority:

for element in priority_queue.iterator() do
  -- do something with this element
end

Extending ipairs for use in sparse arrays

The ipairs function in the Lua language is used to iterate over entries in a sequence. This means every entry must be defined by the pair of key and value, where the key is the integer value. The main limitation of the ipairs function is that the keys must be consecutive numbers.

You can modify the ipairs function so that you can successfully iterate over entries with integer keys that are not consecutive. This is commonly seen in sparse arrays.

Getting ready

In this recipe, you'll need to define our own iterator function, which will return every entry of a sparse array in deterministic order. In this case, the iterator function can be included in your code as a global function to accompany pairs and ipairs functions; or you can put it in a Lua module file not to pollute the global environment space.

How to do it…

This code shows a very simple sparse array iterator without any caching:

function ipairs_sparse(t)
  -- tmpIndex will hold sorted indices, otherwise
  -- this iterator would be no different from pairs iterator
  local tmpIndex = {}
  local index, _ = next(t)
  while index do
    tmpIndex[#tmpIndex+1] = index
    index, _ = next(t, index)
  end
  -- sort table indices
  table.sort(tmpIndex)
  local j = 1

  return function()
    -- get index value
    local i = tmpIndex[j]
    j = j + 1
    if i then
      return i, t[i]
    end
  end
end

The following lines of code show the usage example for iteration over a sparse array;

-- table below contains unsorted sparse array
local t = {
  [10] = 'a', [2] = 'b', [5] = 'c', [100] = 'd', [99] = 'e',
}
-- iterate over entries
for i, v in ipairs_sparse(t) do
  print(i,v)
end

How it works…

The Lua language uses iterator functions in the control structure called the generic for. The generic for calls the iterator function for each new iteration and stops when the iterator function returns nil. The ipairs_sparse function works in the following steps:

  1. It builds a new index of keys from the table.
  2. It sorts the index table.
  3. It returns a closure where each call of the closure returns a consecutive index and a value from the sparse array.

Each call to ipairs_sparse prepares a new index table called index. The index consists of (integer, entry) pairs.

Creating Lua modules

The Lua language doesn't impose strict policies on what a module should look like. Instead, it encourages programmers to find their own style depending on the situation.

Getting ready

In this recipe, you will create three versions of a module that contains one local variable, one variable accessible from outside the module, one function that returns a simple value, and a function that uses a value from the current module.

How to do it…

There are three types of modules that are commonly used:

  • A module that returns a table as a module interface
  • A module in the form of an object
  • A module in the form of a singleton object

The first case is used mostly with modules that contain an interface to third-party libraries. The second type of module is used less often, but it's useful if you need multiple instances of the same object, for example, a network stack. The last one uses a similar approach as in the previous case, but this time there's always only one instance of the object. Many games use the singleton object for the resource management system.

A module that returns a table as an interface

In this case, the module uses locally defined variables and functions. Every function intended for external use is put into one table. This common table is used as an interface with the outer world and is returned at the end of the module:

-- module1.lua
local var1 = 'ipsum'
local function local_function1()
  return 'lorem'
end

local function local_function2(self)
  return var1 .. self.var2
end
-- returns module interface
return {
  lorem = local_function1,
  ipsum = local_function2,
  var2 = 'sit',
}

A module in the form of an object

This module type doesn't manipulate the global namespace. Every object you create uses its own local namespace:

-- module2.lua
local M = function()
  local instance
  local var1 = 'ipsum'
  instance = {
    var2 = 'sit',
    lorem = function()
      return 'lorem'
    end,
    ipsum = function(self)
      return var1 .. self.var2
    end,
  }
  return instance
end

return M

A module in the form of a singleton object

This is a special case of object module. There is only one and the same object instance:

-- module3.lua
local instance

local M = function()
  if not instance then
    local var1 = 'ipsum'
    instance = {
      var2 = 'sit',
      lorem = function()
        return 'lorem'
      end,
      ipsum = function(self)
        return var1 .. self.var2
         end,
    }
  end
  return instance
end

return M

How it works…

Modules are used with the require function that registers them in the global table modules.loaded. This table contains the compiled code of every module used and ensures that each module is loaded only once.

Object modules return a local variable M, which contains an object interface. However, you can use any other name for this variable. Choosing between tables or closure as object contained is mostly a matter of application design.

Variable var1 is always hidden from the outside world and can be changed only by the exposed function. Variable var2 is freely accessible and can be modified anytime.

The following lines of code show the usage patterns for all three types of module:

local module1 = require 'module1'
local module2 = require 'module2'
local module3 = require 'module3'
-- create two instances of module2
local module2_A = module2()
local module2_B = module2()
-- try to create an instance of module2 twice
local module3_A = module3()
local module3_B = module3()

-- usage of a module with interface table
print('Module 1 - Before:', module1:lorem() .. module1:ipsum())
module1.var2 = 'amet'
print('Module 1 - After:', module1:lorem() .. module1:ipsum())

-- usage of a module in a form of an object
print('Module 2a - Before:', module2_A:lorem() .. module2_A:ipsum())
module2_A.var2 = 'amet'
print('Module 2a - After:', module2_A:lorem() .. module2_A:ipsum())
print('Module 2b - After:', module2_B:lorem() .. module2_B:ipsum())

-- usage of a module in a form of a singleton object
print('Module 3a - Before:', module3_A:lorem() .. module3_A:ipsum())
module3_A.var2 = 'amet'
print('Module 3a - After:', module3_A:lorem() .. module3_A:ipsum())
print('Module 3b - After:', module3_B:lorem() .. module3_B:ipsum())

Handling errors with pcall, xpcall, and assert

By default, the Lua language uses its internal error function. If an error occurs, Lua will usually abort code execution and put the error message with trace back into the standard error output. You can override the standard behavior with the pcall and xpcall functions. The main difference between these two functions is that pcall will return the status code and error message as the second return value, and xpcall will use the user-defined error function.

This way you can catch nonfatal errors and emulate the try and catch block.

Getting ready

This recipe will show error handling on a simple function that can exit prematurely with the error message:

 local function f1(a, b)
  assert((a == 1), "The first parameter must be equal to 1")
  print(b)
  return a+1
end

How to do it…

Here's how you can catch a nonfatal error with pcall by emulating the try and catch block:

function try(fn, catch_fn)
  local status, msg = pcall(fn)
  if not status then
    catch_fn(msg)
  end
end

try(function()
  f1(2, 3) -- this will throw "an exception"
end, function(e)
  print('An exception occured:', e)
  error('Throw exception')
end)

The next recipe shows how to create your own specialized xpcall2 function that can handle input parameters for a function:

local function xpcall2(fn, ...)
  local arg = {...}
  return xpcall(
    -- function wrapper to pass function arguments
    function(...)
      return fn(unpack(arg))
    end,
    -- error function
    function(msg)
      return debug.traceback(msg, 3)
    end
  )
end

print(xpcall2(f1, 2, 'a'))

How it works…

The whole principle of the try and catch block emulation in Lua relies on the pcall function that catches the error message and pushes it into the catch block function.

The only weakness of this approach is that you can't get more information because you're handling errors outside of the scope of where the error occurred.

This issue can be solved with xpcall which handles error before stack unwinding so you can use the debug library to get more information about the error.

Xpcall2 works as a wrapper function that not only passes parameters into protected function calls, but also handles getting the trace back with the debug.traceback function and returns results or a status code with an error message.

Using Lua with existing projects written in C/C++

The Lua language provides a set of API functions for communication between C/C++ and the Lua programming language. You can use these functions in your C code after you include the lua.h header file or lua.hpp for C++ source code. You can rely on this set of functions, but sooner or later you'll see that there are certain usage patterns which can be used to simplify your C/C++ code or just simply make it more readable and error prone. This is especially true if you want to expose C++ objects and structures to the Lua language environment.

Fortunately, there is the Lutok2 library to help you with that. It consists of a set of header files and a freely based previous project called Lutok from Julio Merino.

This chapter will cover how to use Lutok2 library as the C++ API library for the Lua language and as a C++ class wrapper so that you can easily manage making your own extensions in the future. You'll also see that this library is used in many other libraries to cover access to multimedia devices from the Lua language.

Getting ready

The first thing you need to do before starting is to get the Lua binary library and the header files. After this step, you can download the Lutok2 header files and use them in your project.

On Windows:

  1. Download the Lua binary files from https://code.google.com/p/luaforwindows/downloads/list.
  2. Download and unzip the Lutok2 source code from https://github.com/soulik/lutok2/archive/master.zip or get a clone of the repository with the git command:
    git clone https://github.com/soulik/lutok2.git
    

On Linux:

  1. Use your package manager to install the Lua developer package or build the Lua binary library from source code at http://www.lua.org/ftp/lua-5.1.5.tar.gz.
  2. Download and unzip the Lutok2 source code from https://github.com/soulik/lutok2/archive/master.zip or get a clone of the repository with the git command:
    git clone https://github.com/soulik/lutok2.git
    

In both cases, you'll need the C++ compiler that can handle C++11 version of the standard C++ language. You can use clang or gcc compiler under the Unix-like environment, or the recent version of Microsoft Visual C++.

How to do it…

In the following steps, you'll see most common scenarios of using the Lua language in your C/C++ project. Most of the Lutok2 code samples are paired with equivalent Lua C API code so that you can see what the equivalent C code looks like without using the Lutok2 library.

Initializing the Lua state

This is how you initialize a Lua state with Lutok2:

#include <lutok2/lutok2.hpp>

int main(int argc, char ** argv){
  lutok2::State state;
  return 0;
}

This is how you do the same with Lua C API:

#include <lua.hpp>

int main(int argc, char ** argv){
  lua_State * state = luaL_newstate();
  return 0;
}

Creating a Lua module in C/C++

With Lutok2:

#include <lutok2/lutok2.hpp>

using namespace lutok2;
   
   /* A function to be exposed should always use following form:
    * Input argument : A reference to Lutok2 State object
    * Output variable: An integral number of return values
    */ 
int lua_example_myfunction(State & state){
  // C/C++ code to be invoked
  return 0;
}

extern "C" LUA_API int luaopen_example(lua_State * current_state){
  State * state = State(current_state);
  Module myModule;
  /* Expose lua_example_myfunction function in
   * Lua language environment.
   * Key value represents a function name in Lua.
   * Value should always be a function pointer.
   */
  myModule["myfunction"] = lua_example_myfunction;
  
  /* This module will return a Lua table
   * that exposes all functions listed in myModule.
   */
  state->stack->newTable();
  state->registerLib(myModule);
  return 1;
}

With Lua C API:

#include <lua.hpp>

static int lua_example_myfunction(lua_State * L){
  return 0;
}

static const struct luaL_Reg module[] = {
  {"myfunction", lua_example_myfunction},
  {NULL, NULL}
};

extern "C" LUA_API int luaopen_example(lua_State * L){
  lua_newtable(L);
  luaL_register (L, NULL, module);
  return 1;
}

Passing variables from C/C++ into the Lua environment

With Lutok:

int lua_example_myfunction(State & state){
  void * userData = (void*)123456789;
  Stack * stack = state->stack;

  stack->push<bool>(true);
  stack->push<int>(12345);
  stack->push<LUA_NUMBER>(12345.6789);
  stack->push<const std::string &>("A text");
  stack->push<void*>(userData);
  stack->newTable();
    stack.setField<bool>("boolean", false);
    stack.setField<int>("integer", (int)12345);
    stack.setField<LUA_NUMBER>("number", (lua_Number)12345.6789);
    stack.setField<const std::string &>("string", "A text");
    stack.setfield<void *>("userData", userData);
  return 6;
}

With Lua C API:

static int lua_example_myfunction(lua_State * L){
  void * userData = (void*)123456789;
  lua_pushboolean(L, (int)true);
  lua_pushinteger(L, 12345);
  lua_pushnumber(L, 12345.6789);
  lua_pushstring(L, "A text");
  lua_pushlightuserdata(L, userData);
  lua_newtable(L);
    lua_pushboolean(L, (int)false);
    lua_setfield(L, -2, "boolean");
    lua_pushinteger(L, 12345);
    lua_setfield(L, -2, "integer");
    lua_pushnumber(L, 12345.6789);
    lua_setfield(L, -2, "number");
    lua_pushstring(L, "A text");
    lua_setfield(L, -2, "A text");
    lua_pushlightuserdata(L, userData);
    lua_setfield(L, -2, "userData");
  return 6;
}

Passing variables from the Lua environment to C/C++

To get a variable from the Lua environment, you need to call the corresponding Lua C API function lua_to*, for example, lua_tointeger(L, index). You can use the corresponding version of the luaL_check*(L, index) function to obtain a value with additional checks for the correct data type.

Lutok2 provides a similar mechanism where you can use a template form of the to function:

state.stack->to<DATA_TYPE_NAME>(index);

The part DATA_TYPE_NAME presents a name of the target data type and the index value is a position of the variable in the registry. The first function parameter is at index 1. The second one is at index 2, and so on.

The example code for Lutok2 C++ API is as follows:

int integerValue = state.stack->to<int>(1);

The example code for the plain Lua C API is as follows:

int integerValue = luaL_checkinteger(L, 1);

Making the C++ class accessible from Lua with Lutok2

Let's assume that your class is defined in the ExampleObject.hpp header file. In this minimal case, the class contains one numerical property and one member function that returns a string value. The header file will contain the following lines of code:

#ifndef EXAMPLE_OBJECT_H
#define EXAMPLE_OBJECT_H

#include <string>

class ExampleObject {
public:
  int x;
  inline const std::string helloWorld(){
    return "Hello world";
  }
};
#endif

Now, you'll need to create a class declaration and implementation of the C++ class wrapper. You should always use a reasonable name for the wrapper class so that it is clear what class is actually handled. This example uses the name LuaExampleObject.

The header file will be called LuaExampleObject.hpp and it will contain a declaration for the LuaExampleObject class. This header file contains the following lines:

#ifndef LUA_EXAMPLE_OBJECT_H
#define LUA_EXAMPLE_OBJECT_H

#include "ExampleObject.hpp"

class LuaExampleObject : public Object<ExampleObject> {
public:
  explicit LuaExampleObject(State * state) :
    Object<ExampleObject>(state){
    /* Properties handle access to member variables
     * with getter and setter functions
     */
    LUTOK_PROPERTY("x", &LuaExampleObject::getX, &LuaExampleObject::setX);
    // Methods allow you to call member functions
    LUTOK_METHOD("helloWorld",
      &LuaExampleObject::helloWorld);
  }
  
  ExampleObject * constructor(State & state, bool & managed);
  void destructor(State & state, ExampleObject * object);
  int getX(State & state, ExampleObject * object);
  int setX(State & state, ExampleObject * object);
  int helloWorld(State & state, ExampleObject * object);
};
#endif

The implementation file will be called LuaExampleObject.cpp and it will consist of the main code that handles access to member variables and functions:

#include <lutok2/lutok2.hpp>
using namespace lutok2;

#include "LuaExampleObject.hpp"

ExampleObject * LuaExampleObject::constructor(State & state, bool & managed){
  return new ExampleObject;
}

void LuaExampleObject::destructor(State & state, ExampleObject * object){
  delete object;
}

int LuaExampleObject::getX(State & state, ExampleObject * object){
  state.stack->push<int>(object->x);
  return 1;
}

int LuaExampleObject::setX(State & state, ExampleObject * object){
  if (state.stack->is<LUA_TNUMBER>(1)){
    object->x = state.stack->to<int>(1);
  }
  return 0;
}

int LuaExampleObject::helloWorld(State & state, ExampleObject * object){
  state.stack->push<const std::string &>(object->helloWorld());
  return 1;
}

Furthermore, to finish while process, you'll need to register a Lua interface. This is usually done during the module initialization routine. The following code sample shows how to prepare a C++ source file with module initialization. This module will return a table that is used in the Lua script as an interface to create an instance of ExampleObject. Note that this module doesn't register itself in the global variable space. This is currently the preferred way of using modules in the Lua language.

The main module file will be called ExampleModule.cpp and will consist of the following lines:

#include <lutok2/lutok2.hpp>
using namespace lutok2;

#include "LuaExampleObject.hpp"

extern "C" LUA_API int luaopen_example(lua_State * current_state){
  // State object is freed automatically after Lua state closes!
  State * state = new State(current_state);
  Stack * stack = state->stack;

  // Prepare main module interface table
  stack->newTable();
  
  /* Object interface registration always returns Lua function
   * with object constructor.
   */
  state->registerInterface<LuaExampleObject>(
    "LuaExample_ExampleObject");
  /* A new instance of ExampleObject can be obtained by
   * calling ExampleObject function from main interface table.
   */
  stack->setField("ExampleObject");
  return 1;
}

Now, you can include all source code in your C++ project in your favorite IDE and compile them into the binary library.

Don't forget to move the resulting binary library with the module to the working directory with your Lua script or anywhere the Lua interpreter can find it.

Finally, your Lua script will look like this:

local exampleModule = require 'Example'

local example_object = exampleModule.ExampleObject()
example_object.x = 5
print(example_object.x)
print(example_object.helloWorld())

This will create a new ExampleObject instance, sets and gets content of member variable; in the final step, it calls the member function that returns a string value.

How it works…

The Lutok2 library contains most of the commonly used Lua C API functions while sanitizing access to class objects.

The core of this library is divided into two sections:

  • Functions that manage Lua states and Lua modules
  • Functions that manage Lua stack content

All Lutok2 classes are encapsulated in Lutok2 namespace, so there should be no naming conflicts with other libraries. It contains automatic management of the Lua state for these use cases:

  • Lua modules
  • A standalone application that creates a Lua state during runtime

Class wrapper objects use the template form of lutok2::Object as a generic base class that handles most of the work in order to register the class interface in the current Lua environment. The template parameter is mandatory and specifies what class will be wrapped.

lutok2::Object<CLASS_NAME>

The constructor of the class wrapper must always be present, as it defines what methods or properties will be available in the Lua environment. It's called automatically during interface registration. The body of the constructor usually consists of several macros that specify the class members. There are two macros you can use, which are as follows:

  • LUTOK_METHOD(LUA_NAME, FUNCTION)
  • LUTOK_PROPERTY(LUA_NAME, FUNCTION, FUNCTION)

The member functions are defined by their name as a string value and a function pointer. The member variables use a similar notation while using two function pointers. The first one points to the getter function that returns a value of the member variable. The second one points to the setter function that sets the value of the member variable. If you don't want to allow the member variable modification, you can use the pointer to the nullMethod function instead of your own setter function. This will effectively block any changes to the member variable from the Lua script.

Another part of the C++ class wrapper is the functions that manage object instance creation and destruction—constructor and destructor. The constructor method is called when you actually call the object constructor in the Lua environment and it gives you space to actually create a new object instance. There's a reference to the managed argument, which you can change to the false value if the object instance is managed elsewhere. This will also cause that destructor method won't be called upon garbage collection in the Lua environment:

CLASS_NAME * constructor(State & state, bool & managed);

The destructor method is called when the object is freed in the Lua environment during garbage collection. This is the place where you can clean up and free up the object's instance:

  void destructor(State & state, CLASS_NAME * object);

Getting LuaSDL for libSDL 1.2

LuaSDL is a binding to the famous libSDL 1.2 multimedia library. LuaSDL provides an interface not only to libSDL itself but also to the SDL_image, SDL_mixer, SDL_net, SDL_ttf, and SDL_gfx libraries.

Getting ready

The LuaSDL module depends on many external libraries. To make the module preparation easier, there's a LuaSDL project repository at GitHub with support for the CMake building system. This project repository contains all the necessary external libraries, which make module building process a breeze.

You'll need to have the following software installed to successfully build the LuaSDL module:

  • The git version control system is available at https://git-scm.com/
  • The CMake building system version 3.1 or newer is available at http://www.cmake.org/
  • The C/C++ compiler, Microsoft Visual Studio, GCC, and clang are supported
  • The Netwide Assembler—NASM (optional) used only for CPU-specific optimizations is available at http://www.nasm.us/

How to do it…

The building process of LuaSDL is the same on both Windows and Linux operating systems with minor differences:

  1. Download the LuaSDL source code with the git command:
    git clone --recursive https://github.com/soulik/LuaSDL.git
    
  2. You need to create an empty working directory, which will contain the project and binary files:
    mkdir LuaSDL/build
    cd LuaSDL/build
    
  3. Now, you can run the CMake building tool to prepare the project files or to make further changes to the building configuration:
    cmake ..
    
  4. After successful preparation of the building environment, you can either open the project file in your IDE or simply run the make command to start the compilation depending on the compiler of your choice:
    • For Microsoft Visual Studio—use the luasdl.sln file
    • For Linux users—use the make command
  5. The successful compilation will result in binary files stored in the bin and lib directories.

Note that Microsoft Visual Studio will generate the .dll binary files in the bin directory, whereas, Linux users will find the same binary files in the lib directory. You can copy all the binary files into one directory where your Lua application resides. This will ensure that the Lua interpreter finds all the necessary binary modules.

There's more…

LuaSDL uses libSDL 1.2, which is more than 5 years old. Despite being no longer maintained, the LuaSDL package is considered as stable.

LuaSDL2 is being developed at the time of writing. You can access the source code from GitHub at https://github.com/soulik/LuaSDL-2.0.git.

Designing the main application loop with LuaSDL

LuaSDL offers an event-based application design. LibSDL uses a window to capture input events. Without it, you wouldn't be able to detect key strokes, mouse movement and, of course, you will be without any graphical output.

Getting ready

Before running your Lua script with LuaSDL, make sure you've got the LuaSDL module with all the dependencies in the same directory. However, you can always override the PATH environmental variable so that your application can find the necessary libraries. Note that the path environment variable is managed in the operating system and it's not for the Lua module location!

How to do it…

First, you must load the LuaSDL module file. If this step fails, you are either missing the correct libSDL library or one of the dependencies:

require 'LuaSDL'

You can define your own assertion check function with the optional SDL error reporting:

function SDL_assert(condition, msg)
  local msg = (msg and msg .. ": " .. SDL.SDL_GetError())
  return assert(condition, msg)
end

You have to set up the default window parameters as follows:

local window_x_pos = 128
local window_y_pos = 128
local window_width = 640
local window_height = 480
local window_bpp = 0
local window_flags = 0

LuaSDL must be initialized with SDL.SDL_Init before any use:

SDL_assert(SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING) >= 0, "Couldn't initialize SDL")

LuaSDL places the window randomly upon creation. You can override this by setting the environmental variable SDL_VIDEO_WINDOW_POS:

SDL.SDL_putenv(string.format("SDL_VIDEO_WINDOW_POS=%d,%d",window_x_pos, window_y_pos))

To set a window caption, you have to call the SDL.SDL_WM_SetCaption function:

SDL.SDL_WM_SetCaption("LuaSDL Example", "Example")

Now, you can create a window with the SDL.SDL_SetVideoMode function, which returns the SDL_Surface object as a userdata:

local screen = SDL_assert(SDL.SDL_SetVideoMode(window_width, window_height, window_bpp, window_flags))

You can use the event loop invariant or just use a break statement on the application exit:

local running = true

It's more efficient to use the table of event functions than the usual approach with the if, elseif, and else statements. Each table key is an integer constant in this case:

local events = {
  [SDL.SDL_MOUSEMOTION] = function(event_struct)
    local event_struct = event_struct.motion
    -- do something when this event occurs
  end,
  [SDL.SDL_MOUSEBUTTONDOWN] = function(event_struct)
    local event = event_struct.button
  end,
  [SDL.SDL_MOUSEBUTTONUP] = function(event_struct) 
    local event = event_struct.button
  end,
  [SDL.SDL_KEYDOWN] = function(event_struct) 
    local event = event_struct.key
    local key = event_struct.keysym.sym
  end,
  [SDL.SDL_KEYUP] = function(event_struct) 
    local event = event_struct.key
    local key = event_struct.keysym.sym
  end,
  [SDL.SDL_VIDEORESIZE] = function(event_struct) 
      local event = event_struct.resize
  end,
  [SDL.SDL_QUIT] = function(event_struct) 
      running = false
  end,
}
-- prepare local instance of SDL_Event object
local local_event = SDL.SDL_Event_local()

while (running) do
  -- check for events in the poll
  if (SDL.SDL_PollEvent(local_event)~=0) then
    local event_fn = events[local_event.type]
    if type(event_fn)=='function' then
      event_fn(local_event)
    end
  end
end

The SDL.SDL_Quit function ensures that all the temporary objects are freed upon application exit:

SDL.SDL_Quit()

How it works…

Using the LuaSDL library must follow a certain pattern to ensure correct management of resources and events. Events are used as a primary source of information about user interaction with your application. The LuaSDL library can detect mouse movement, keyboard input, change of application window size, and a request to close your application.

The whole process of event processing uses event polling where you use the SDL.SDL_PollEvent function in each step of the main application loop to obtain information about the event that has occurred. This function may return a value 0 if there are no events to process. In this case, you can use this free time to process game logic. This recipe uses a skeleton table for event processing functions called events.

The most important event, SDL.SDL_QUIT, is received when the user closes the application window. You should clean up all the resources and LuaSDL state as well. Don't forget to use the SDL.SDL_Quit function before exiting your application to ensure all the previously used memory is freed.

Left arrow icon Right arrow icon

Description

This book is for all programmers and game enthusiasts who want to stop dreaming about creating a game, and actually create one from scratch. The reader should know the basics of programming and using the Lua language. Knowledge of the C/C++ programming language is not necessary, but it's strongly recommended in order to write custom Lua modules extending game engine capabilities or to rewrite parts of the Lua code into a more efficient form. Algebra and matrix operations are required in order to understand advanced topics in Chapter 4, Graphics – Legacy Method with OpenGL 1.x-2.1 and Chapter 5, Graphics – Modern Method with OpenGL 3.0+. Sample demonstrations are coupled with binary libraries for Windows and Linux operating systems for convenience.

Who is this book for?

This book is for all programmers and game enthusiasts who want to stop dreaming about creating a game, and actually create one from scratch.

What you will learn

  • Set up OpenGL graphics along with GLSL shaders
  • Use lighting and graphical effects
  • Create animated game characters using Box2D library
  • Load and use textures, fonts, and 3D models
  • Design and implement a graphical user interface
  • Integrate simple Artificial Intelligence for pathfinding
  • Implement networking support
  • Use data structures in programming
Estimated delivery fee Deliver to Taiwan

Standard delivery 10 - 13 business days

$12.95

Premium delivery 5 - 8 business days

$45.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jul 28, 2015
Length: 360 pages
Edition : 1st
Language : English
ISBN-13 : 9781849515504
Languages :
Concepts :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Taiwan

Standard delivery 10 - 13 business days

$12.95

Premium delivery 5 - 8 business days

$45.95
(Includes tracking information)

Product Details

Publication date : Jul 28, 2015
Length: 360 pages
Edition : 1st
Language : English
ISBN-13 : 9781849515504
Languages :
Concepts :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 136.97
L÷VE for Lua Game Programming
$32.99
Learning game AI programming with Lua
$48.99
Lua Game Development Cookbook
$54.99
Total $ 136.97 Stars icon
Banner background image

Table of Contents

10 Chapters
1. Basics of the Game Engine Chevron down icon Chevron up icon
2. Events Chevron down icon Chevron up icon
3. Graphics – Common Methods Chevron down icon Chevron up icon
4. Graphics – Legacy Method with OpenGL 1.x–2.1 Chevron down icon Chevron up icon
5. Graphics – Modern Method with OpenGL 3.0+ Chevron down icon Chevron up icon
6. The User Interface Chevron down icon Chevron up icon
7. Physics and Game Mechanics Chevron down icon Chevron up icon
8. Artificial Intelligence Chevron down icon Chevron up icon
9. Sounds and Networking Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.3
(6 Ratings)
5 star 83.3%
4 star 0%
3 star 0%
2 star 0%
1 star 16.7%
Filter icon Filter
Top Reviews

Filter reviews by




CPallini Oct 01, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book covers a very appealing topic: game development with Lua.Leveraging on libSDL, OpenGL and several other libraries, illustrates, in the formof recipes, many techniques required to build yourself a game, game engine orprototype.Since the topic is wide and deep, it is a condensed book, rich of content inrelatively few pages: from directory organization, module and error handling, Luainteraction with C++, to game UI, physics, AI, sound and network communication,passing for the event driven SDL game loop, OpenGL (both the older immediate mode and the moremodern shading language).I found most of the content interesting, some recipes a bit difficult tounderstand at first (in my opinion delaying the explanation in 'how it works'section is a bit confusing), neverhtless worthy to be studied.A relatively good knowledge of Lua is required to fully understand the recipes(while proficience with modern C++ would help for actual game development).The approach is pragmatic and you have to use the companion code in order toappreciate the book and start experimenting (I should say compiling myself therequired libraries was not exactly 'a breeze' like the author claims in the book).All in all it is a solid, pragmatic, fairly advanced book: enough to make youappreciate the efforts required in game development and possibly desire to deepenyour knowledge about the related problems and techniques.
Amazon Verified review Amazon
Julie Blanchard Feb 07, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Bought for my sons Christmas presentHe loves it
Amazon Verified review Amazon
Dan Kosko Nov 27, 2019
Full star icon Full star icon Full star icon Full star icon Full star icon 5
quick delivery. just as described. good job
Amazon Verified review Amazon
Kiffin Gish Oct 27, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
If you've ever fantasized about creating your own fancy game but never was able to get beyond the basics, then this is the right place to begin. Starting with the first chapters, you become more familiar with the Lua programming language and what goes into a powerful gaming engine. Slowly but surely, your learn how Lua provides the ideal playground to build up a solid platform of modules and components that can be combined nicely. It's not just about the complex concepts that go into designing games but also the choice of the right programming language and how to use it effectively. By the end of the book you start mastering the more difficult concepts and can deal with all the fancy algorithms that go into good game making.
Amazon Verified review Amazon
Joel A. Sundquist Apr 19, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Great lua book. Even if you are not developing games it has some helpful performance tips
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact [email protected] with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at [email protected] using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on [email protected] with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on [email protected] within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on [email protected] who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on [email protected] within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela