Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Level module
Started by jake1987.jj Oct 03 2017 01:28 AM

- - - - -
40 replies to this topic

Best Answer Develephant , 03 October 2017 - 11:16 AM

Hi,

 

Not sure if you determined whether to use the database, but with your level structure you should probably just store it in the database as JSON.

 

As an example with your data:


local json = require("json")
local sqlite3 = require("sqlite3")

local path = system.pathForFile( "game.db", system.DocumentsDirectory )
local db = sqlite3.open( path )  

--=============================================================================
--== SAVE LEVEL DATA
--=============================================================================
local level =	{
		graphics = {
			name = "graphics",
			{
				kind = "RoundedRect",
				x      = 160,
				y      = 180,
				height = 160,
			},
		},
		physical = {
			name = "physical",
			{
				kind = "Chain",
				chain = { 140,-740, 140,-500, 380,-500, 380,-380, 140,-380 },
				connectFirstAndLastChainVertex = true
			},
			{
				kind = "Rect",
				x      = 540,
				y      = 40,
				height = 240,
			},
		},
		elements = {
			{
				name     = "finishPortal",
				x        = 700,
				y        = -780,
				radius   = 30
			},
			{
				name     = "aswa",
				x        = 200,
				y        = 110,
				directPaths   = {{x=200,y=-360}, {x=200,y=110}},
				paramsPaths   = {useDelta=false, constantTime=2200, loop = true}			
			},
		},
	}

local lvl_num = 1
local data = json.encode(level) --table to json

local query = string.format("INSERT INTO levels VALUES (NULL, %d, '%s');", lvl_num, data)
db:exec(query)

--=============================================================================
--== LOAD LEVEL DATA
--=============================================================================

local lvl_num = 1
local query = string.format("SELECT data FROM levels WHERE level=%d LIMIT 1;", lvl_num)

for row in db:nrows(query) do
  local data = json.decode(row.data) --json to table
  print(data.graphics.name) --graphics
end

db:close()

I actually just created the database using the DB Browser for SQLite tool (calling it game.db) and put it in the Corona Documents directory sandbox folder. You should be able to create the initial database structure with this query:

db:exec[[
  CREATE TABLE "levels" ( id INTEGER PRIMARY KEY AUTOINCREMENT, level INTEGER UNIQUE, data TEXT NOT NULL );
]]

-dev

[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Hello everyone

 

I need help. I've created a module for my levels, something like that:

local M = {}

local levels =  {

	--1
	{
	},

	--2
	{
	},

	--etc up to 150 (about 20.000 lines of code)
}

function M.getTotLv()

	return #levels
end

function M.getLv( num )

	return levels[num]
end

return M

Everything is fine, but when I ask about the module loaded about 3MB ..

 

This seems to me a bit too much, also because I have other modes in mind with other levels.

 

I need a way to get the number of levels and to keep it from memory after it is used

 

What is the best way to do this?



[TOPIC: post.html]
#2

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

i wouldnt hardcode level info in code but store it in a json file on disk, and load on demand.

if performance is an issue, you could store levels in batches or even separately, surely you dont need all of them available in ram.

 

come to think of it, sounds like SQLlite could do the job perfectly for you. Instant performance and simple storage.



[TOPIC: post.html]
#3

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

I would agree with @anaqim. Use SQLlite to bring in the data on demand.

 

https://docs.coronalabs.com/api/library/sqlite3/index.html

 

-dev



[TOPIC: post.html]
#4

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Sounds good. 

But should I manually convert the files from module to sql?

And then since I have nominated it is better json or sql file?



[TOPIC: post.html]
#5

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

sql will be faster and frankly, get the habit of using it as for most local info storage needs, it the better option imo.

if you can convert your data to a table, it should be simply to loop through and insert the data.

note, sql is usually a bit slower when inserting/creating new data, but for reads, it is very fast.



[TOPIC: post.html]
#6

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

You'll want to create your database using an offline tool like http://sqlitebrowser.org/

 

It's a way different approach than using json, though you could store the json string in the database record, which may give you more flexibility, but could be extra work if your json object structure changes over the course of development. You will still need some key to search against to get access to the data. A "level" id or something similar.

 

-dev



[TOPIC: post.html]
#7

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Thanks @anaqim and @Develephant for the immediate answers.

I do the tests right away.

Since we're wondering if it's best to use sql also to save app data. At the time I used json and looked good. Could I have improvements to use sql even in this case?



[TOPIC: post.html]
#8

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

As a general recommendation I would always go with a database for any data needs beyond a few objects.

 

-dev



[TOPIC: post.html]
#9

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

I understand thank you very much.
Feel I'm trying to use db but I never used sql with lua. Could you give me a straight?
I need to do a loop to store a db with the table levels and how it is...
local levels =  {

	--1
	{
		graphics = {
			name = "graphics",
			{
				kind = "RoundedRect",
				x      = 160,
				y      = 0,
				height = 520,
			},
		},
		physical = {
			name = "physical",
			{
				kind = "Chain",
				chain = { 140,260, 180,260, 180,-260, 140,-260 },
				connectFirstAndLastChainVertex = true
			},
		},
		elements = {
			{
				name     = "finishPortal",
				x        = 160,
				y        = -240,
				radius   = 30
			},
		},
	},


}

then I have to be able to read the db and put it in a lua variable? is this right or is it not better to put the db in a variable?



[TOPIC: post.html]
#10

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

As dev mentions, using the sqlitebrowser comes very handy.

 

Regarding json vs sql, well, it probably wont matter in your case here but json files have to be decoded, sql replies not.

sql lookups (select) is also blazingly fast, and you can get it sorted and filtered before you receive the data.

With json, you'll have to sort and filter it yourself.

 

If you are more confortable using json and storing files in that way, i suggest you make your test and check if it works for you, if sqlite is more unknown territory. It is absolutely nothing wrong in that approach as there are always more then one road to rome. Mind you, I dont know that much about sql databases but got sqlite3 up and running pretty fast.

 

For my current project im using mysql in the cloud, made easily accessible by the great coronium core api, which develephant just released. Cant praise it enough, really!

 

How to loop through your data and store in a database or json file is something you know better how to do, just focus on learning the storage types first.

 

Oh, becuase the sql is so fastg, you dont need to load it into a table before using it, just load on demand exactly the part you need at any given time.

 

Hope this helps

 

anaqim



[TOPIC: post.html]
#11

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Thanks very useful.
I know better use json but if sql is better always better to upgrade. I apologize for the play of words.
 
Only one last question.
If i understand with sql I can create one file with all levels? or is it always better to make a file for each level?


[TOPIC: post.html]
#12

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

No worries mate, I am by comparison to most people in here, just an amateur.

Like to help if/where i can, even if my posts sometimes get overruled by those much more proficient  :)

 

Yes the SQL is a single database file in which you create tables, or in your case probably a single table, that will keep all your levels stored.

 

Later you just ask the database to transfer level data back to your app with a select statement (look up SQLite3 on the internet), which means you only load the data you need at any given time.

 

Or you could use this link https://www.tutorialspoint.com/sqlite/

 

Cheers!



[TOPIC: post.html]
#13

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Very kind.
I immediately go to the test ;)


[TOPIC: post.html]
#14

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

dont forget coronas own sqlite3 documentation :)



[TOPIC: post.html]
#15

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Certainly he tried to analyze the various guides :)



[TOPIC: post.html]
#16

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Despite the attempts I can not put the FOREIGN KEY in the tables, sqlLite allowed it?



[TOPIC: post.html]
#17

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

you mean the normally set auto increment key? yes it should work.

in general it is good practice to have a single field in each table with an auto key, just to make sure each row is unique.

you dont add anything to it, just let it auto increase by itself.

 

if you use dbbrowser then when you add the first field, name it "key" or "id" (i prefer key), choose INTEGER and check PK (primary key) and AI (auto increment).

 

thereafter you continue to create the fields you want.

 

hope it helps :)



[TOPIC: post.html]
#18

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Thank you but in fact it is not what I was looking for...

After other searches, however, I found it

I share it if it can be useful to you too :)

https://sqlite.org/foreignkeys.html



[TOPIC: post.html]
#19

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Anyway for this time I think I used json.

I'm trying sql and it's very nice however implementing all those tables below into a database would take a long time.

	{
		graphics = {
			name = "graphics",
			{
				kind = "RoundedRect",
				x      = 160,
				y      = 180,
				height = 160,
			},
		},
		physical = {
			name = "physical",
			{
				kind = "Chain",
				chain = { 140,-740, 140,-500, 380,-500, 380,-380, 140,-380 },
				connectFirstAndLastChainVertex = true
			},
			{
				kind = "Rect",
				x      = 540,
				y      = 40,
				height = 240,
			},
		},
		elements = {
			{
				name     = "finishPortal",
				x        = 700,
				y        = -780,
				radius   = 30
			},
			{
				name     = "aswa",
				x        = 200,
				y        = 110,
				directPaths   = {{x=200,y=-360}, {x=200,y=110}},
				paramsPaths   = {useDelta=false, constantTime=2200, loop = true}			
			},
		},
	},

this is the table of a simple level and as you can see there are many nested tables ...

 

I should also retouch the code in the various modules



[TOPIC: post.html]
#20

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

oh i see, keys between tables.

whatever works and makes you happy man :)



[TOPIC: post.html]
#21

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

  Best Answer

Hi,

 

Not sure if you determined whether to use the database, but with your level structure you should probably just store it in the database as JSON.

 

As an example with your data:


local json = require("json")
local sqlite3 = require("sqlite3")

local path = system.pathForFile( "game.db", system.DocumentsDirectory )
local db = sqlite3.open( path )  

--=============================================================================
--== SAVE LEVEL DATA
--=============================================================================
local level =	{
		graphics = {
			name = "graphics",
			{
				kind = "RoundedRect",
				x      = 160,
				y      = 180,
				height = 160,
			},
		},
		physical = {
			name = "physical",
			{
				kind = "Chain",
				chain = { 140,-740, 140,-500, 380,-500, 380,-380, 140,-380 },
				connectFirstAndLastChainVertex = true
			},
			{
				kind = "Rect",
				x      = 540,
				y      = 40,
				height = 240,
			},
		},
		elements = {
			{
				name     = "finishPortal",
				x        = 700,
				y        = -780,
				radius   = 30
			},
			{
				name     = "aswa",
				x        = 200,
				y        = 110,
				directPaths   = {{x=200,y=-360}, {x=200,y=110}},
				paramsPaths   = {useDelta=false, constantTime=2200, loop = true}			
			},
		},
	}

local lvl_num = 1
local data = json.encode(level) --table to json

local query = string.format("INSERT INTO levels VALUES (NULL, %d, '%s');", lvl_num, data)
db:exec(query)

--=============================================================================
--== LOAD LEVEL DATA
--=============================================================================

local lvl_num = 1
local query = string.format("SELECT data FROM levels WHERE level=%d LIMIT 1;", lvl_num)

for row in db:nrows(query) do
  local data = json.decode(row.data) --json to table
  print(data.graphics.name) --graphics
end

db:close()

I actually just created the database using the DB Browser for SQLite tool (calling it game.db) and put it in the Corona Documents directory sandbox folder. You should be able to create the initial database structure with this query:

db:exec[[
  CREATE TABLE "levels" ( id INTEGER PRIMARY KEY AUTOINCREMENT, level INTEGER UNIQUE, data TEXT NOT NULL );
]]

-dev



[TOPIC: post.html]
#22

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

hey, i didnt know if sqlite could store json objects like mysql and mssql, now i do :)

thats absolutely the better choice in this case.



[TOPIC: post.html]
#23

jake1987.jj

[GLOBAL: userInfoPane.html]
jake1987.jj
  • Contributor

  • 211 posts
  • Corona SDK

Well this seems just fine. Great!

If I was granted a last question I would like to know whether reading json decoding consumes many resources or whether it is fast



[TOPIC: post.html]
#24

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

its fast enough and for your described purpose, you wont notice it.



[TOPIC: post.html]
#25

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

I agree with @anaqim, you won't notice it.

 

-dev




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]