Difference between revisions of "Tiled Map Editor"
(the page is ready :-)) |
m |
||
Line 21: | Line 21: | ||
end | end | ||
</source> | </source> | ||
+ | |||
+ | Below is the '''Tiled_Levels''' class. | ||
=== '''BUILD YOUR MAP''' === | === '''BUILD YOUR MAP''' === |
Revision as of 00:04, 27 November 2020
Here you will find various resources to help you create games and apps in Gideros Studio.
note: you may have to provide your own assets (fonts, gfx, …)
Description
On this page you will find various classes to help using Tiled Map Editor in Gideros. Enjoy :-)
Tiled Map Editor
LOAD YOUR MAP
Here is a class to load your Tiled map in Gideros.
note: world is used for Box2D (LiquidFun) or CBUMP but you can remove it and adpat to your needs
LevelX = Core.class(Sprite)
function LevelX:init()
application:setBackgroundColor(0x0)
-- the tiled world
self.tiled_level = Tiled_Levels.new(self.world, "tiled/levels/level01.lua")
self:addChild(self.tiled_level)
end
Below is the Tiled_Levels class.
BUILD YOUR MAP
Here is the class to import the levels your created in Tiled and draw them in Gideros using the RECTANGLES, POLYGONS, ELLIPSES classes you will find further below on this page.
note: don't forget to exclude from execution your level lua file (right click -> exclude from execution)
note2: those are placeholder names (bg = background layer, mg = middle ground layer...) adapt to your needs
Tiled_Levels = Core.class(Sprite)
function Tiled_Levels:init(xworld, xtiledlevelpath)
self.world = xworld
self.camera = Sprite.new()
self.bg = Sprite.new() -- bg deco
self.mg = Sprite.new() -- mg level + sensors
self.fg = Sprite.new() -- fg deco
self.camera:addChild(self.bg)
self.camera:addChild(self.mg)
self.camera:addChild(self.fg)
self:addChild(self.camera)
-- load the tiled level
local tiledlevel = loadfile(xtiledlevelpath)()
-- the tiled map size
local mapwidth, mapheight = tiledlevel.width * tiledlevel.tilewidth, tiledlevel.height * tiledlevel.tileheight
print("map size "..mapwidth..", "..mapheight, "app size "..myappwidth..", "..myappheight, "all in pixels.")
-- parse the tiled level
local layers = tiledlevel.layers
local myshape -- shapes from Tiled
local mytable -- intermediate table for shapes params
for i = 1, #layers do
local layer = layers[i]
-- *************
-- MG GAME LAYER
-- *************
if layer.name == "mg" then -- your Tiled layer name here!
local levelsetup = {}
local objects = layer.objects
for i = 1, #objects do
local object = objects[i]
local objectName = object.name
myshape, mytable = nil, nil
-- ***************
-- SHAPES
-- ***************
if objectName == "groundA" then
mytable = {color=0x00ff00, isshape=true}
else
mytable = {color=0xff0000, isshape=true}
end
levelsetup = {}
for k, v in pairs(mytable) do levelsetup[k] = v end
self:buildShapes(layer.name, object, levelsetup)
-- ***************
-- OBJECTS (players, npc, nmes...)
-- ***************
if objectName == "player1" then
self.world.player = LF_Dynamic_Player.new(
self.world,
"gfx/playable/caverman.png", "player", 6, 7,
1, 1,
nil, nil, 0, -5,
1, 0, 1,
G_BITPLAYER, playercollisions, G_PLAYER)
self.world.player.body:setPosition(object.x, object.y) -- position the body, the bitmap will follow in enterframe
self.mg:addChild(self.world.player)
end
end
-- *************
-- WHAT?!
-- *************
else
print("WHAT?!", layer.name)
end
end
end
function Tiled_Levels:buildShapes(xlayer, xobject, xlevelsetup)
local myshape = nil
local tablebase = {}
if xobject.shape == "ellipse" then
tablebase = {
x = xobject.x, y = xobject.y,
w = xobject.width, h = xobject.height, rotation = xobject.rotation,
}
for k, v in pairs(xlevelsetup) do tablebase[k] = v end
myshape = Tiled_Shape_Ellipse.new(self.world, tablebase)
elseif xobject.shape == "polygon" then
tablebase = {
x = xobject.x, y = xobject.y,
coords = xobject.polygon, rotation = xobject.rotation,
}
for k, v in pairs(xlevelsetup) do tablebase[k] = v end
myshape = Tiled_Shape_Polygon.new(self.world, tablebase)
elseif xobject.shape == "rectangle" then
tablebase = {
x = xobject.x, y = xobject.y,
w = xobject.width, h = xobject.height, rotation = xobject.rotation,
}
for k, v in pairs(xlevelsetup) do tablebase[k] = v end
myshape = Tiled_Shape_Rectangle.new(self.world, tablebase)
else
print("*** CANNOT PROCESS THIS SHAPE! ***", xobject.shape, xobject.name)
return
end
myshape:setPosition(xobject.x, xobject.y)
if xlayer == "bg" then -- your Tiled layer name here
self.bg:addChild(myshape)
else -- mg = player layer + sensors layer...
self.mg:addChild(myshape)
end
end
Tiled Map Editor: OBJECT LAYER
Here are the classes to import the shapes your created in Tiled and draw them in Gideros.
note: don't forget to export your Tiled map to a lua file
RECTANGLES
Tiled_Shape_Rectangle = Core.class(Sprite)
function Tiled_Shape_Rectangle:init(xworld, xparams)
-- params
local params = xparams or {}
params.x = xparams.x or nil
params.y = xparams.y or nil
params.w = xparams.w or 32
params.h = xparams.h or 32
params.color = xparams.color or nil
params.alpha = xparams.alpha or 1
params.tex = xparams.tex or nil
params.isdeco = xparams.isdeco or nil
params.isshape = xparams.isshape or nil
params.isbmp = xparams.isbmp or nil
params.ispixel = xparams.ispixel or nil
params.scalex = xparams.scalex or 1
params.scaley = xparams.scaley or params.scalex
params.rotation = xparams.rotation or 0
params.type = xparams.type or nil -- default = b2.STATIC_BODY
params.fixedrotation = xparams.fixedrotation or nil
params.density = xparams.density or nil
params.restitution = xparams.restitution or nil
params.friction = xparams.friction or nil
params.issensor = xparams.issensor or nil
params.gravityscale = xparams.gravityscale or 1
params.BIT = xparams.BIT or nil
params.COLBIT = xparams.COLBIT or nil
params.NAME = xparams.NAME or nil
params.addenterframe = xparams.addenterframe or nil
-- image
if params.issensor then
-- no image for sensors
else
if params.isshape then
self.img = Shape.new()
self.img:setLineStyle(4, 0x0000ff, 1) -- change here (width, color, alpha)
if params.tex then
local tex = Texture.new(params.tex, false, {wrap = Texture.REPEAT})
local matrix = Matrix.new(params.scalex, 0, 0, params.scaley, 0, 0)
self.img:setFillStyle(Shape.TEXTURE, tex, matrix)
tex = nil
else
self.img:setFillStyle(Shape.SOLID, params.color)
end
self.img:beginPath()
self.img:moveTo(0, 0)
self.img:lineTo(params.w, 0)
self.img:lineTo(params.w, params.h)
self.img:lineTo(0, params.h)
self.img:lineTo(0, 0)
self.img:endPath()
if params.rotation < 0 then self.img:setAnchorPoint(0, -0.5) end
if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
self.img:setRotation(params.rotation)
self.img:setAlpha(params.alpha)
end
if params.isbmp then
if not params.tex then print("!!!YOU MUST PROVIDE A TEXTURE FOR THE BITMAP!!!") return end
local tex = Texture.new(params.tex, false)
self.img = Bitmap.new(tex)
self.img.isbmp = true
self.img.w, self.img.h = params.w, params.h
if params.rotation < 0 then self.img:setAnchorPoint(0, 0.5) end
-- if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
self.img:setAlpha(params.alpha)
tex = nil
end
if params.ispixel then
if params.tex then
local tex = Texture.new(params.tex, false, {wrap = TextureBase.REPEAT})
self.img = Pixel.new(tex, params.w, params.h)
self.img.ispixel = true
self.img.w, self.img.h = params.w, params.h
self.img:setScale(params.scalex, params.scaley)
if params.rotation < 0 then self.img:setAnchorPoint(0, -0.5) end
if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
self.img:setRotation(params.rotation)
self.img:setAlpha(params.alpha)
tex = nil
else
self.img = Pixel.new(params.color, 1, params.w, params.h)
self.img.ispixel = true
self.img.w, self.img.h = params.w, params.h
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
self.img:setAlpha(params.alpha)
end
end
-- debug
if self.img then
if xworld.isdebug then self.img:setAlpha(0.5) end
self:addChild(self.img)
end
end
-- body
self.body = xworld:createBody { type = params.type } -- b2.STATIC_BODY, b2.KINEMATIC_BODY, b2.DYNAMIC_BODY
self.body:setGravityScale(params.gravityscale)
self.body.name = params.NAME
self.body.isdirty = false
self.body:setFixedRotation(params.fixedrotation)
local shape = b2.PolygonShape.new()
shape:setAsBox(params.w/2, params.h/2, params.w/2, params.h/2, ^<params.rotation) -- (half w, half h, centerx, centery, rotation)
local fixture = self.body:createFixture {
shape = shape,
density = params.density, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local filterData = { categoryBits = params.BIT, maskBits = params.COLBIT, groupIndex = 0 }
fixture:setFilterData(filterData)
-- clean up?
filterData = nil
fixture = nil
shape = nil
-- listeners?
if params.addenterframe then
self.world = xworld
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end
end
function Tiled_Shape_Rectangle:onEnterFrame()
-- your logic here
end
function Tiled_Shape_Rectangle:setPosition(xposx, xposy)
if self.body then
self.body:setPosition(xposx, xposy)
if self.img then self.img:setPosition(self.body:getPosition()) end
else
if self.img then self.img:setPosition(xposx, xposy) end
end
end
POLYGONS
Tiled_Shape_Polygon = Core.class(Sprite)
function Tiled_Shape_Polygon:init(xworld, xparams)
-- params
local params = xparams or {}
params.x = xparams.x or nil
params.y = xparams.y or nil
params.coords = xparams.coords or nil
params.color = xparams.color or nil
params.tex = xparams.tex or nil
params.isshape = xparams.isshape or nil
params.isbmp = xparams.isbmp or nil
params.ispixel = xparams.ispixel or nil
params.isdeco = xparams.isdeco or nil
params.scalex = xparams.scalex or 1
params.scaley = xparams.scaley or params.scalex
params.rotation = xparams.rotation or 0
params.type = xparams.type or nil -- default = b2.STATIC_BODY
params.fixedrotation = xparams.fixedrotation or true
params.density = xparams.density or nil
params.restitution = xparams.restitution or nil
params.friction = xparams.friction or nil
params.gravityscale = xparams.gravityscale or 1
params.issensor = xparams.issensor or false
params.BIT = xparams.BIT or nil
params.COLBIT = xparams.COLBIT or nil
params.NAME = xparams.NAME or nil
params.addenterframe = xparams.addenterframe or nil
-- image
if params.issensor then
-- no image for sensors
else
if params.isshape then
self.img = Shape.new()
self.img:setLineStyle(4, 0x0000ff, 1) -- change here (width, color, alpha)
if params.tex then
local tex = Texture.new(params.tex, false, {wrap = TextureBase.REPEAT})
local matrix = Matrix.new(params.scalex, 0, 0, params.scaley, 0, 0)
self.img:setFillStyle(Shape.TEXTURE, tex, matrix)
tex = nil
else
self.img:setFillStyle(Shape.SOLID, params.color)
end
self.img:beginPath()
self.img:moveTo(params.coords[1].x, params.coords[1].y)
for p = 2, #params.coords do
self.img:lineTo(params.coords[p].x, params.coords[p].y)
end
self.img:closePath()
self.img:endPath()
self.img:setRotation(params.rotation)
self.w, self.h = self.img:getWidth(), self.img:getHeight()
end
if params.isbmp then
if not params.tex then print("!!!YOU MUST PROVIDE A TEXTURE FOR THE BITMAP!!!") return end
-- calculate polygon width and height
local minx, maxx, miny, maxy = 0, 0, 0, 0
for k, v in pairs(params.coords) do
--print("polygon coords", k, v.x, v.y)
if v.x < minx then minx = v.x end
if v.y < miny then miny = v.y end
if v.x > maxx then maxx = v.x end
if v.y > maxy then maxy = v.y end
end
local pw, ph = maxx - minx, maxy - miny -- the polygon dimensions
local tex = Texture.new(params.tex, false)
self.img = Bitmap.new(tex)
self.img.isbmp = true
self.img.w, self.img.h = pw, ph
self.img:setAnchorPoint(0.5, 0.5)
if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
if params.rotation < 0 then self.img:setAnchorPoint(0.5, 1) end
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
tex = nil
end
if params.ispixel then
if params.tex then
-- calculate polygon width and height
local minx, maxx, miny, maxy = 0, 0, 0, 0
for k, v in pairs(params.coords) do
--print("polygon coords", k, v.x, v.y)
if v.x < minx then minx = v.x end
if v.y < miny then miny = v.y end
if v.x > maxx then maxx = v.x end
if v.y > maxy then maxy = v.y end
end
local pw, ph = maxx - minx, maxy - miny -- the polygon dimensions
local tex = Texture.new(params.tex, false, {wrap = TextureBase.REPEAT})
self.img = Pixel.new(tex, pw, ph)
self.img.ispixel = true
self.img.w, self.img.h = pw, ph
self.img:setAnchorPoint(0, -0.5) -- 0.5, 0.5
if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
if params.rotation < 0 then self.img:setAnchorPoint(0.5, 1) end
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
self.img:setTexturePosition(0, 0)
tex = nil
else
-- calculate polygon width and height
local minx, maxx, miny, maxy = 0, 0, 0, 0
for k, v in pairs(params.coords) do
--print("polygon coords", k, v.x, v.y)
if v.x < minx then minx = v.x end
if v.y < miny then miny = v.y end
if v.x > maxx then maxx = v.x end
if v.y > maxy then maxy = v.y end
end
local pw, ph = maxx - minx, maxy - miny -- the polygon dimensions
self.img = Pixel.new(params.color, 1, pw, ph)
self.img.ispixel = true
self.img.w, self.img.h = pw, ph
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
end
end
-- debug
if self.img then
if xworld.isdebug then self.img:setAlpha(0.5) end
self:addChild(self.img)
end
end
-- body
self.body = xworld:createBody {type = params.type} -- b2.STATIC_BODY, b2.KINEMATIC_BODY, b2.DYNAMIC_BODY
self.body:setGravityScale(params.gravityscale)
self.body.name = params.NAME
self.body.isdirty = false
self.body:setFixedRotation(params.fixedrotation)
local shape = b2.ChainShape.new()
local cs = {}
for c = 1, #params.coords do
cs[#cs+1] = params.coords[c].x
cs[#cs+1] = params.coords[c].y
end
shape:createLoop(unpack(cs)) -- XXX
local fixture = self.body:createFixture {
shape = shape,
density = params.density, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local filterData = { categoryBits = params.BIT, maskBits = params.COLBIT, groupIndex = 0 }
fixture:setFilterData(filterData)
-- clean up?
filterData = nil
fixture = nil
cs = nil
shape = nil
-- listeners?
if params.addenterframe then
self.world = xworld
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end
end
function Tiled_Shape_Polygon:onEnterFrame()
-- your logic here
end
function Tiled_Shape_Polygon:setPosition(xposx, xposy)
if self.body then
self.body:setPosition(xposx, xposy)
if self.img then self.img:setPosition(self.body:getPosition()) end
else
if self.img then self.img:setPosition(xposx, xposy) end
end
end
ELLIPSES
Tiled_Shape_Ellipse = Core.class(Sprite)
function Tiled_Shape_Ellipse:init(xworld, xparams)
-- params
local params = xparams or {}
params.x = xparams.x or nil
params.y = xparams.y or nil
params.w = xparams.w or 32
params.h = xparams.h or 32
params.steps = xparams.steps or 16 -- 24
params.color = xparams.color or nil
params.tex = xparams.tex or nil
params.isdeco = xparams.isdeco or nil
params.isshape = xparams.isshape or nil
params.isbmp = xparams.isbmp or nil
params.ispixel = xparams.ispixel or nil
params.scalex = xparams.scalex or 1
params.scaley = xparams.scaley or params.scalex
params.rotation = xparams.rotation or 0
params.type = xparams.type or nil -- default = b2.STATIC_BODY
params.fixedrotation = xparams.fixedrotation or nil
params.density = xparams.density or nil
params.restitution = xparams.restitution or nil
params.friction = xparams.friction or nil
params.gravityscale = xparams.gravityscale or 1
params.issensor = xparams.issensor or nil
params.BIT = xparams.BIT or nil
params.COLBIT = xparams.COLBIT or nil
params.NAME = xparams.NAME or nil
params.addenterframe = xparams.addenterframe or nil
-- image
if params.issensor then
-- no image for sensors
else
local sin, cos, d2r = math.sin, math.cos, math.pi / 180
if params.isshape then
self.img = Shape.new()
self.img:setLineStyle(4, 0x0000ff, 1) -- change here (width, color, alpha)
if params.tex then
local tex = Texture.new(params.tex, false, {wrap = Texture.REPEAT})
local matrix = Matrix.new(params.scalex, 0, 0, params.scaley, 0, 0)
self.img:setFillStyle(Shape.TEXTURE, tex, matrix)
tex = nil
else
self.img:setFillStyle(Shape.SOLID, params.color)
end
self.img:beginPath()
for i = 0, 360, 360 / params.steps do
self.img:lineTo((params.w / 2) + params.w / 2 * sin(i * d2r), (params.h / 2) + params.h / 2 * cos(i * d2r))
end
self.img:endPath()
self.img:setRotation(params.rotation)
end
if params.isbmp then
if not params.tex then print("!!!YOU MUST PROVIDE A TEXTURE FOR THE BITMAP!!!") return end
local tex = Texture.new(params.tex, false)
self.img = Bitmap.new(tex)
self.img.w, self.img.h = params.w, params.h
if params.rotation > 0 then self.img:setAnchorPoint(0, 0.5) end
if params.rotation < 0 then self.img:setAnchorPoint(0.5, 1) end
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
-- print("bmp", params.w, params.h)
tex = nil
end
if params.ispixel then
if params.tex then
local tex = Texture.new(params.tex, false, {wrap = TextureBase.REPEAT})
self.img = Pixel.new(tex, params.w, params.h)
self.img.ispixel = true
self.img.w, self.img.h = params.w, params.h
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
-- print("pixel", params.w, params.h, params.rotation)
tex = nil
else
self.img = Pixel.new(0xff0000, 1, params.w, params.h)
self.img.ispixel = true
self.img.w, self.img.h = params.w, params.h
self.img:setScale(params.scalex, params.scaley)
self.img:setRotation(params.rotation)
-- print("pixel", params.w, params.h, params.rotation)
end
end
-- debug
if self.img then
if xworld.isdebug then self.img:setAlpha(0.5) end
self:addChild(self.img)
end
end
-- body
self.body = xworld:createBody { type = params.type } -- b2.STATIC_BODY, b2.KINEMATIC_BODY, b2.DYNAMIC_BODY
self.body:setGravityScale(params.gravityscale)
self.body.name = params.NAME
self.body.isdirty = false
self.body:setFixedRotation(params.fixedrotation)
if params.w < params.h then -- capsule up
-- print("capsule up")
local shape = b2.CircleShape.new(params.w / 2, params.h / 2, params.w / 2) -- (centerx, centery, radius)
local shape2 = b2.CircleShape.new(params.w / 2, params.h - params.w / 2, params.w / 2) -- (centerx, centery, radius)
local shape3 = b2.EdgeShape.new(0, params.w / 2, 0, params.h - (params.w / 2)) -- (x1,y1,x2,y2)
local shape4 = b2.EdgeShape.new(params.w, params.w / 2, params.w, params.h - (params.w / 2)) -- (x1,y1,x2,y2)
local fixture = self.body:createFixture {
shape = shape,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture2 = self.body:createFixture {
shape = shape2,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture3 = self.body:createFixture {
shape = shape3,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture4 = self.body:createFixture {
shape = shape4,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local filterData = { categoryBits = params.BIT, maskBits = params.COLBIT, groupIndex = 0 }
fixture:setFilterData(filterData)
fixture2:setFilterData(filterData)
fixture3:setFilterData(filterData)
fixture4:setFilterData(filterData)
-- clean up?
filterData = nil
fixture, fixture2, fixture3, fixture4 = nil, nil,nil, nil
shape, shape2, shape3, shape4 = nil, nil, nil, nil
elseif params.w > params.h then -- capsule laid
-- print("capsule laid")
local shape = b2.CircleShape.new(params.w/2, params.h/2, params.w/2) -- (centerx, centery, radius)
local shape2 = b2.CircleShape.new(params.w - params.w/2, params.h/2, params.w/2) -- (centerx, centery, radius)
local shape3 = b2.EdgeShape.new(params.h / 2, 0, params.w - (params.h / 2), 0) -- (x1,y1,x2,y2)
local shape4 = b2.EdgeShape.new(params.h / 2, params.h, params.w - (params.h / 2), params.h) -- (x1,y1,x2,y2)
local fixture = self.body:createFixture {
shape = shape,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture2 = self.body:createFixture {
shape = shape2,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture3 = self.body:createFixture {
shape = shape3,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local fixture4 = self.body:createFixture {
shape = shape4,
density = params.density * 0.25, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local filterData = { categoryBits = params.BIT, maskBits = params.COLBIT, groupIndex = 0 }
fixture:setFilterData(filterData)
fixture2:setFilterData(filterData)
fixture3:setFilterData(filterData)
fixture4:setFilterData(filterData)
-- clean up?
filterData = nil
fixture, fixture2, fixture3, fixture4 = nil, nil,nil, nil
shape, shape2, shape3, shape4 = nil, nil, nil, nil
else -- circle
-- print("circle")
local shape = b2.CircleShape.new(params.w / 2, params.h / 2, params.w / 2) -- (centerx, centery, radius)
local fixture = self.body:createFixture {
shape = shape,
density = params.density, restitution = params.restitution, friction = params.friction, isSensor = params.issensor
}
local filterData = { categoryBits = params.BIT, maskBits = params.COLBIT, groupIndex = 0 }
fixture:setFilterData(filterData)
-- clean up?
filterData = nil
fixture = nil
shape = nil
end
-- rotation
local rot = math.rad(params.rotation)
self.body:setAngle(rot)
-- listeners?
if params.addenterframe then
self.world = xworld
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end
end
function Tiled_Shape_Ellipse:onEnterFrame()
-- your logic here
end
function Tiled_Shape_Ellipse:setPosition(xposx, xposy)
if self.body then
self.body:setPosition(xposx, xposy)
if self.img then self.img:setPosition(self.body:getPosition()) end
else
if self.img then self.img:setPosition(xposx, xposy) end
end
end