Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

save result of a collision in .json table
Started by quinohp Nov 24 2019 12:03 PM

- - - - -
15 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Hi, sorry for my English language.
I try to save in table.jason the result of a collision
 
local function onLocalCollision( self, event )
    if ( event.phase == "began" ) then
	
        print( event.other.name .. ": collision began with => " .. self.name )
    
	end
end
This is the result you print on the console:
 
20:56:00.167  4: collision began with => four
20:56:00.537  7: collision began with => seven
 
How can I insert it into a .json table?
 
I've tried it that way, but it doesn't insert what I want:
 
local s = {} 


local function onLocalCollision( self, event )
    if ( event.phase == "began" )
	
        s = {event.other.name} 
        loadsave.saveTable(s, "table.json", system.DocumentsDirectory)
	end
end

this is the result of the table:  ["7"]

 

I want to print, this or something: {"four":4 , "seven": 7}

 
Cheers!!
 


[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,534 posts
  • Enterprise

You want to create a Lua table based on key-value pairs instead of an indexed array.

 

local s = { four = 4, seven = 7 }

 

or something like that. You can also use strings instead of variables, which may work better for what you're doing:

 

local  s = { ["four"] = 4, ["seven"] = 7 }

 

Both are identical internally, but since you're trying to use values from the collision, you may want something like:

 

local s = { event.self = event.other.name }

 

But this is going to overwrite with each collision. Why do you need to save this? Do you need a collision history or just the latest collision?

 

Rob



[TOPIC: post.html]
#3

carloscosta

[GLOBAL: userInfoPane.html]
carloscosta
  • Contributor

  • 674 posts
  • Corona SDK

What's your propose with that json table? What will you do with it? without seeing the rest of your code or what it's for it's difficult to give you advice, because maybe the problem is not the json table. never needed one in 7 years, wonder why you do.

 

just seeing you code, "onLocalCollision" will be executed two times to get 4 and 7. so it should be saved in 2 different levels.

it should be saved in something like this:

local json=require("json")

local s={}
s[#s+1]={}
s[#s]["four"]=4
s[#s+1]={}
s[#s]["seven"]=7

for i=1,#s do
	for n,m in pairs (s[i]) do
		print (n,m)
	end
end


print (json.encode(s))

using your code it should be something like this:

local s = {} 
local function onLocalCollision( self, event )
    if ( event.phase == "began" )
		s[#s+1]={}
        s[#s][self.name] = {event.other.name} 
        
	end
end

why you save on a table each time you get a collision? it will the slowest approach ever that way.

 

why not save it on a memory table first, and when you leave the screen or you know the game is over. just save the table to a json file or to a sqlite table. Like i said without more information you gave it's hard to give you the best advice.



[TOPIC: post.html]
#4

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Hello again, thanks for your interest.
I want to use this collision for a game that I am creating, it is a multiplication made by the player of 4 x 7 = 28 which is the number that has the exit door of a level of the game. The doll has to find the two boxes (4 and 7) and put them on the two objects for the collision (four and seven), when this occurs, the door will open with a condition:
 
local s = {}
s = loadsave.loadTable ("table.json", system.DocumentsDirectory)
if four == 4 and seven == 7 then
   --execute the action
 
... I guess there will be another easier way, but this is the one that occurred to me.
 
This is full script:
 

local loadsave = require("savecollision")
local physics = require("physics")
-------------------------------------------------CREATE JSON FILE-------------------------------------------------------------------
function fileExists(fileName, base)
  assert(fileName, "file name missing")
  local base = base or system.DocumentsDirectory
  local filePath = system.pathForFile( fileName, base )
  local exists = false
 
  if (filePath) then
    local fileHandle = io.open( filePath, "r" )
    if (fileHandle) then
      exists = true
      io.close(fileHandle)
    end
  end
 
  return(exists)
end

  local s = {} 

	  s.seven = 0
  	  s.four = 0
      loadsave.saveTable(s, "table.json", system.DocumentsDirectory)
--------------------------------------------------------------------------------------------------

physics.start()
physics.setGravity(0,9.8)

local ground = display.newRoundedRect(0,0,900,20,3); 
ground:setFillColor(0.89, 0.498, 0.263)
ground.x = 300
ground.y = 800
physics.addBody( ground, "static", { friction=1.0} )
 
local myTarget = display.newRoundedRect(100,300,69,69,3)
myTarget:setFillColor(100,100,100)
myTarget.name = "4"
physics.addBody(myTarget, { density=2, friction=0.5, bounce=0.2} )

 
local myTarget1 = display.newRoundedRect(180,100,69,69,3)
myTarget1:setFillColor(100,100,100)
myTarget1.name = "7" 
physics.addBody(myTarget1, { density=2, friction=0.5, bounce=0.2} )

 
local myObject = display.newRoundedRect(50,50,67,67,3); 
myObject:setFillColor(0,0,255)
myObject.x = 100
myObject.y = 755
myObject.name = "four" 
physics.addBody( myObject, "static")
myObject.isSensor = true

local myObject2 = display.newRoundedRect(50,50,67,67,3); 
myObject2:setFillColor(0,0,255)
myObject2.x = 180
myObject2.y = 755
myObject2.name = "seven" 
physics.addBody( myObject2, "static")
myObject2.isSensor = true
 
local function onLocalCollision( self, event )
    if ( event.phase == "began" ) then 
	
        local s= {event.other.name , self.name}	
        loadsave.saveTable(s, "table.json", system.DocumentsDirectory)
	end
end
 
myObject.collision = onLocalCollision 
myObject:addEventListener( "collision", myObject )

myObject2.collision = onLocalCollision 
myObject2:addEventListener( "collision", myObject2 )

jump.JPG



[TOPIC: post.html]
#5

carloscosta

[GLOBAL: userInfoPane.html]
carloscosta
  • Contributor

  • 674 posts
  • Corona SDK

i didn't forget about you, just don't have time right now to proper answer you.

You could improve your code doing some functions to create your objects. I remade your code to show you that, but right now I'm struggling with some corona issues myself so I will back here when I can.



[TOPIC: post.html]
#6

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Corona Geek

  • 1,103 posts
  • Corona SDK

Also, it is always better to write dynamic functions that can adapt.

 

In your example, you have a case of "4 x 7 = 28" and if that works, great, but what if you want to create another level that has different numbers? If you create dynamic functions that you can just use to create your levels, you'll be saving yourself a lot of time and headache, all the while making your game easier to manage and expand.



[TOPIC: post.html]
#7

pixec

[GLOBAL: userInfoPane.html]
pixec
  • Enthusiast

  • 99 posts
  • Corona SDK

Playing with json in here is pure overkill, go with normal tables, or rather make switch states where u check if correct box is in correct place, if all match, then go

[TOPIC: post.html]
#8

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Ok, carloscosta.

 

Doing it with json is because I don't know it any other way since 4 with four and 7 with seven would not collide at the same time, but if I make two collisions separately, one for 4 with four and one for 7 with seven, I would send them to the table.json and then rescue the result with a condition that would give me 28.



[TOPIC: post.html]
#9

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Corona Geek

  • 1,103 posts
  • Corona SDK

It really sounds like you should find another way to go about this.

 

For instance, a simpler approach would be to just create a table that contains a reference to each object that you expect to collide. Then, whenever a new collision begins, you set that object's collision state to true and then you'd loop through that table to see if every other collision is true as well. Then, whenever a collision ends, you'd set that object's collision state back to false.

 

Here's some pseudo code:

local collisions = {}
collisions["target1"] = false
collisions["target2"] = false

function collisionListener( ... )
    if event.phase == "began" then
        -- write a condition here where "if self.name == event.other.name then" to check that correct box touches.
        collisions[event.other.name] = true -- if correct boxes hit then set it to true in the collisions table.
        -- now you can loop through the collisions table to see if all are true, if yes, then you've got a solution.
    elseif event.phase == "ended" then
        collisions[event.other.name] = false -- collision only ends if the object moves out of position.
    end 
end

If you need to save your progress for when the player may close the app, then use json for storing data during that time. You should not be using json to go through collisions as they occur because it is very cumbersome and slow, drains more battery than necessary, etc.


  • pixec likes this

[TOPIC: post.html]
#10

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Hi XeduR, thanks for replying.
I have never worked with memory tables, I will have to catch up. I tried the collision with your code but I don't receive an answer.
 
I have planned to make two collisions separately and then rescue the result from the table.json:
 
local function onLocalCollision4( self, event )

		local phase, other = event.phase, event.other

       if  phase == "began" and event.other.name == "4" then
	
	 s.four = 4
	 loadsave.saveTable(s, "table.json", system.DocumentsDirectory)
	
	end
end

local function onLocalCollision7( self, event )

		local phase, other = event.phase, event.other		

       if  phase == "began" and event.other.name == "7" then
        
	 s.seven = 7
	 loadsave.saveTable(s, "table.json", system.DocumentsDirectory)
	   
	end
end


[TOPIC: post.html]
#11

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Corona Geek

  • 1,103 posts
  • Corona SDK

My code was just pseudo code, it still needs work to get it to actually work (especially in your specific project).

 

What you are doing with json is essentially:

1) Put collision event's information to a Lua table,
2) Take contents of that Lua table,
3) Store it in a JSON file,
4) Read that JSON file,
5) Place those contents to a Lua table.

You are essentially running a lap around the block just to get to where you were and wasting resources in doing so.



[TOPIC: post.html]
#12

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

OK, I will follow your advice XeduR, in reality I can save work and time in the future.
Cheers


[TOPIC: post.html]
#13

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Following the advice of XeduR, I have improved my code, I think I am on the right track now, although I think it can be reduced to a single collision function, this is my script:


local physics = require("physics")

-------------------------------------------------CREATE TABLE-------------------------------------

local t = {}
t["four"] = false
t["seven"] = false

  print ( t.four )
  print ( t.seven)
  
--------------------------------------------------------------------------------------------------

physics.start()
physics.setGravity(0,9.8)

local ground = display.newRoundedRect(0,0,900,20,3); 
ground:setFillColor(0.89, 0.498, 0.263)
ground.x = 300
ground.y = 800
physics.addBody( ground, "static", { friction=1.0} )

local box = display.newRoundedRect(50,50,67,67,3); 
box:setFillColor(0.918, 0.71, 0.075)
box.x = 500
box.y = 755

local box2 = display.newRoundedRect(50,50,67,67,3); 
box2:setFillColor(0.118, 0.58, 0.075)
box2.x = 600
box2.y = 755
 
local myTarget = display.newRoundedRect(100,300,69,69,3)
myTarget:setFillColor(100,100,100)
myTarget.name = "4"
physics.addBody(myTarget, { density=2, friction=0.5, bounce=0.2} )
 
local myTarget1 = display.newRoundedRect(180,100,69,69,3)
myTarget1:setFillColor(100,100,100)
myTarget1.name = "7" 
physics.addBody(myTarget1, { density=2, friction=0.5, bounce=0.2} )
 
local myObject = display.newRoundedRect(50,50,67,67,3); 
myObject:setFillColor(0,0,255)
myObject.x = 100
myObject.y = 755
myObject.name = "four" 
physics.addBody( myObject, "static")
myObject.isSensor = true

local myObject2 = display.newRoundedRect(50,50,67,67,3); 
myObject2:setFillColor(0,0,255)
myObject2.x = 180
myObject2.y = 755
myObject2.name = "seven" 
physics.addBody( myObject2, "static")
myObject2.isSensor = true

local function onLocalCollision4( self, event )

local phase, other = event.phase, event.other

       if  phase == "began" and event.other.name == "4" then
        
	print( self.name .. ": collision began with " .. event.other.name )
	
         box.y=200
	 t.four = 4

	end
end

local function onLocalCollision7( self, event )

local phase, other = event.phase, event.other

       if  phase == "began" and event.other.name == "7" then
        
	print( self.name .. ": collision began with " .. event.other.name )
	
	 t.seven = 7
	 
	print ( t.four )
        print ( t.seven)
	
	if (t.seven * t.four) == 28 then

         box2.y = 200
		 
	  table.remove( t )
      table.remove( t, pos )	
	  
       end
	end
end

myObject.collision = onLocalCollision4 
myObject:addEventListener( "collision", myObject )

myObject2.collision = onLocalCollision7 
myObject2:addEventListener( "collision", myObject2 )

This is the reading of the console to verify that everything went well:

 

12:21:44.998  false
12:21:44.998  false
12:21:46.485  four: collision began with 4
12:21:46.797  seven: collision began with 7
12:21:46.797  4
12:21:46.797  7
 
I don't know if with this I delete the table, I don't know how to represent it in the console:
table.remove( t )
table.remove( t, pos )


[TOPIC: post.html]
#14

carloscosta

[GLOBAL: userInfoPane.html]
carloscosta
  • Contributor

  • 674 posts
  • Corona SDK

Just remade your boxes creation code so you can see that your approach is far from optimized.

 

There are infinite ways of doing it, I just made one so you can learn from:

 

My main file is:

display.setDefault( "anchorX", 0 )
display.setDefault( "anchorY", 0 )

local boxes=require ("boxes")

local _H=display.contentHeight
local groundHeight=20

local boxClass=boxes.Box() -- creates the ground class
local boxGroundInstance=boxClass.new({x=0, y=display.contentHeight-40, height=20, width=display.contentWidth, bodyType="static", body={friction=1.0}, name="ground", isSensor=false}) -- creates the ground object

-- create the boxes that are used to check position
local boxInstance1=boxClass.new({x=50,y=_H-40-69, name="four", color={0.7,0.7, 0.7,1}, width=69, height=69, radius=3,  bodyType="static", isSensor=true})
local boxInstance2=boxClass.new({x=200,y=_H-40-69, name="seven", color={0.7,0.7, 0.7,1}, width=69, height=69, radius=3,  bodyType="static", isSensor=true})

-- create the boxes that fall from the sky
local boxInstance3=boxClass.new({x=50,y=300, name="four", color={0,0, 1,1}, width=67, height=67, radius=3, isSensor=false, colision=true, body={ density=2, friction=0.5, bounce=0.2}})
local boxInstance4=boxClass.new({x=200,y=50, name="seven", color={0,0, 1,1}, width=67, height=67, radius=3, isSensor=false, colision=true, body={ density=2, friction=0.5, bounce=0.2}})

My boxes.lua file:

local physics = require("physics")
physics.start()
physics.setGravity(0,9.8)

local boxes={}

function boxes.Box()
	local height=20
	local _M = {
		x=0,
		y=display.contentHeight-height,
		width=display.contentWidth,
		height=height,
		radius=0,
		name="",
		color={0.89, 0.498, 0.263, 1},
		body=nil,
		anchorX=0,
		anchorY=0,
		bodyType="dynamic",
		isSensor=false,
		colision=false,
	}
	local mt = { __index = _M }
	
	function _M.delete(self)
		display.remove(self.view)
        self.view=nil
		self=nil
	end
	
	local function onLocalCollision( self, event )
		if ( event.phase == "began" ) then 
			-- do whatever you want here
		end
	end

	local instance = {}
	function instance.new(params)
		params=params or {}
		setmetatable(params, mt)
		params.view=display.newRoundedRect( params.x, params.y, params.width, params.height, params.radius)
		params.view.name=params.name
		params.view:setFillColor(unpack(params.color))
		params.view.anchorX=params.anchorX
		params.view.anchorY=params.anchorY
		
		physics.addBody(params.view, params.body )
		params.view.isSensor=params.isSensor
		params.view.bodyType=params.bodyType
		
		if params.colision==true then
			params.view.collision = onLocalCollision 
			params.view:addEventListener( "collision", params.view )
		end
		
		
		return params
	end
	return instance
end

return boxes

my build.settings

--
-- For more information on build.settings, see the Project Build Settings guide at:
-- https://docs.coronalabs.com/guide/distribution/buildSettings
--

settings =
{
	orientation =
	{
		-- Supported values for orientation:
		-- portrait, portraitUpsideDown, landscapeLeft, landscapeRight
		default = "portrait",
		supported = { "portrait", "portraitUpsideDown"},
	},

	--
	-- Android section
	--
	android =
	{
		usesPermissions =
		{
			"android.permission.INTERNET",
		},
	},

	--
	-- iOS section
	--
	iphone =
	{
		xcassets = "Images.xcassets",
		plist =
		{
			UIStatusBarHidden = false,
			UILaunchStoryboardName = "LaunchScreen",
		},
	},

	--
	-- Plugins section
	--
	plugins =
	{

	},

	--
	-- Project section
	--
	excludeFiles =
	{
		-- Exclude unnecessary files for each platform
		all = { "Icon.png", "Icon-*dpi.png", "Images.xcassets", },
		android = { "LaunchScreen.storyboardc", },
	},
}

My config.lua

-- Hard code the following without using Corona APIs.

application = 
{
	content = 
	{
		scale = "adaptive",
		fps = 60,

		imageSuffix =
		{
			["@2x"] = 1.5,
			["@3x"] = 2.5,
		}
	},
	notification =
    {
        iphone =
        {
            types = { "badge", "sound", "alert" }
        },
		 google =
        {
            projectNumber = ""
        },
    }
}




[TOPIC: post.html]
#15

carloscosta

[GLOBAL: userInfoPane.html]
carloscosta
  • Contributor

  • 674 posts
  • Corona SDK

I didn't made any code for the collisions because you need first to learn the basics. And creating objects are the one to learn first.

 

You don't need to learn metatables and if this code is more that you can take. just ignore the meta tables.. and create normal variables to default values, I used meta only for that.

 

Your objects can move back from the check box position? if so the variable that controls the collision needs to be reset when moved away.



[TOPIC: post.html]
#16

quinohp

[GLOBAL: userInfoPane.html]
quinohp
  • Enthusiast

  • 44 posts
  • Corona SDK

Ok, thank you very much carloscosta for bothering you with me, your code is very organized and it has helped me a lot, I create the objects with Tiled Map Editor and import them in the style of the game "Sticker Knight Platformer":

	local filename = event.params.map or "scene/game/map/level_001.json"
	local mapData = json.decodeFile( system.pathForFile( filename, system.ResourceDirectory ) )
	map = tiled.new( mapData, "scene/game/map" )
so that my game recognizes the collision objects I will create a box.lua as you indicate.
 
Greetings and thanks



[topic_controls]
[/topic_controls]