Giter Site home page Giter Site logo

berry's Introduction

Tiled Image Texturepacker Image

Tiled version Texturepacker version Solar2D version GitHub contributors GitHub last commit GitHub pull requests GitHub issues Average time to resolve an issue GitHub

Berry

Berry is a simple Tiled Map loader for Corona SDK. Berry is also able to load and use TexturePacker sprites inside a Tiled map.

Screenshot of berry in action

berry supports only part of functionality offered to user by Tiled Map Editor. This includes tile and object layers, tilesets and collections of images. Neverthless it can be extended by using custom properties and executing custom code to gain more flexibility and control.

Tested with Tiled v1.2.0

List of supporting features for Tiled:

  • File Exensions - only JSON map files
  • Map Types - Orthogonal, Isometric, and Isometric Staggered
  • Tilesets - Collections of images and Tileset images
  • TexturePacker Tilesets - Images and lua files created from TexturePacker
  • Layers - Object and Tile layer types, horziontal and vertical offsets
  • Object - x/y flipping and re-centering of anchorX/anchorY for Corona
  • Shapes - Rectangle and polygon shapes with fillColor and strokeColor
  • Text - Text objects, horziontal alignment, word wrap, fonts, and colors
  • Physics - Rectangle and polygon shapes and objects
  • Animation - Tile Animation Editor support for objects
  • Properties - Property copying for objects, tiles, layers, and maps
  • Pivot Joints - Support by plugin**

Quick Start Guide

local berry = require( 'pl.ldurniat.berry' )
local map   = berry:new( filename, tilesetsDirectory, texturePackerDirectory )
-- If you use composer you will need it as well
scene.view:insert( map ) 

filename

The filename specify path to file with map.

Saved Map

tilesetsDirectory

Most of the time you will store your maps and images/tilesets in a directory. The tileSetsDirectory parameter overides where berry looks for images.

local map = berry.new( 'scene/game/map/level1.json', 'scene/game/map' ) -- look for images in /scene/game/map/

texturePackerDirectory

If you wish to use TexturePacker with Berry you can load the sprites several ways.

  1. Place the TexturePacker images and lua files inside the same directory as tilesetsDirectory and it will load them automatically
  2. Use the texturePackerDirectory to select the directory the TexturePacker images and files are located.
  3. Use map:addTexturePack( image_path, lua_path ) to load each texture pack individually.

Method 1 and 2 assume by default that the image file and the lua file have the same name. (ex. items.png and items.lua) If the files are named differently from one another, then the sprites will need to be loaded via method 3. (ex. items.png and weapons.lua)

To insert a loaded texture pack sprite into the map use map:addSprite( layer, image_name, x, y )

map

The map object is display group. All objects are inserted into this group. The map object exposes methods to manipulate and find layers, objects and tiles.

map.designedWidth and map.designedHeight are the width and height of your map as specified in tiled's new map options. The map will be centered on the screen by default.

Character in game

Extensions

map:extend( types )

The extend() function attaches a lua code module to a image object. You can use this to build custom classes in your game.

Custom Properties

The most exciting part of working in Tiled & Corona is the idea of custom properites. You can select any image object on any object layer in Tiled and add any number of custom properties. berry will apply those properties to the image object as it loads. This allows you to put physics properties, custom draw modes, user data, etc. on an in-game item via the editor.

Custom Properties

Properties inheritance

Berry also applies the tile properties and layer properties and add these to the image object. Properties are assigned in prioirty:

  1. Object
  2. Tile
  3. Layer

If the same property amongst these is present when inheriting, the property with the highest priority gets assigned.

  -- Object inherits from tile and layer
  Object.foo = 31
  Tile.foo = 'Huzah'
  Layer.foo = true
  print(Object.foo) -- 31

  -- Pretend Object didn't have a foo property
  Object.foo = nil
  Tile.foo = 'Huzah'
  Layer.foo = true
  print(Object.foo) -- Huzah

  etc.

Physics

One special custom property is hasBody. This triggers berry to add a physics body to an object/tile and pass the rest of the custom properties as physics options. Rectangle bodies are currently supported by default, adding a radius property will give you a round body. More complicated shape you can obtain by using the Collision Editor. No all shapes are supported.

Setting a hasBody property

An object's bodyType property may be set as dynamic, static, or kinematic. If it is not set, it will default to dynamic.

There is full support for every type of Corona Physic Properties. This also includes Collision Filters as well. To enable a filter just set the custom property for maskBits, categoryBits, or groupIndex and it will be applied directly to a physics object.

Animation

Tiled has an animation editor to bring images to life. Berry has several features to take advantage of this. By adding certain properties to a tile in the editor the animation can be configured. These properties are the same as they are to configure CoronaSDK sprites:

  • name (name of the animation)
  • time (time of the animation, 1000 = 1 second)
  • loopCount (optional) (number of times to loop the animation, defaults is 0 for infinite)
  • loopDirection (optional) (how to play the animation, default is forward)

Note - CoronaSDK does not support individual frame durations for animations.

Instead Berry calculates the sum of all the frame durations for an animation and uses it for the time variable. Every frame will play at the same average duration. If a time custom property is given, it will use this to calculate animation time instead.

Another special property is isAnimated. Without it, none of the animations will play by default. isAnimated can be set to true or false for the map, layer, object, or tile. Inheritance rules applies to this property in order of prioirty:

  1. Object
  2. Tile
  3. Layer
  4. Map (*note - only isAnimated property is checked and inherited for map)

Some examples of this behavior:

  -- Example 1 --> only the map is set to true
  Map.isAnimated = true  
  -- Result = all animations will play

  -- Example 2 --> map is set to false and objects set to true
  Map.isAnimated = false
  Object1 -- no isAnimated property set
  Object2.isAnimated = true
  -- Result = Object 2 animation plays, Object 1 does not 

  -- Example 3 -->
  Map -- not set
  Layer1.isAnimated = true 
    Object1 -- not set
    Object2.isAnimated = false
  Layer2.isAnimated = false
    Object3 -- not set
    Object4.isAnimated = true
  Layer3 -- not set
    Object5
  -- Result = Object 1 and 4 animations plays, Object 2, 3, and 5 does not

Setting a isAnimated property

Example

See Sticker-Knight-Platformer-for-Berry

What's next

  • Support for hex maps
  • Collision filter
  • Parallax effect
  • Camera effect
  • Support for external tilesets
  • Support for multi-element bodies

Images

All images come from

Donations

If you think that any information you obtained here is worth of some money and are willing to pay for it, feel free to send any amount through paypal. Thanks :)

paypal

Contributing

If you have any idea, feel free to fork it and submit your changes back to me.

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Acknowledgements

berry is inspired by projects like ponytiled and lime.

berry's People

Contributors

ldurniat avatar outlawgametools avatar timothymtorres avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

berry's Issues

Add basic documentation

I noticed the doc folder is gone. Not sure if that was intentional or not, but I think the project could benefit from some basic documentation. You should also include documentation for what properties a object/layer/map table contains. This will be useful for when people are creating (whatever kind of) objects to look at a table they can reference.

Ie.

    local fake_object_json_data = {
      gid = 1075,
      height = 32,
      width = 32,      
      name = "foo",
      rotation = 0,
      type = "blah",
      visible = true,
      x = 0, 
      y = 0,
      properties = {},
    }

Add TexturePacker support

So I'm looking to tackle this feature in PR #1 but some things definitely need to be taken into consideration.

The way a lua TP sprite is used is through the following methods:

local lua_sheet = require("path_to_TP_lua_file")  (ie. require("my-PC.project.image.lua"))
local image_file = "path_to_image_file" (ie.  my-PC/project/image.png)
local sprite_name = "name_of_sprite_you_wanna_use"

local sprite_frame = lua_sheet:getFrameIndex(sprite_name)

local imageSheet = graphics.newImageSheet( image_file, lua_sheet:getSheet() )
local sprite = display.newImage( layer, image_sheet, sprite_frame)  

Not too complex really. Although to implement this into Berry some consideration needs to be taken.

We need to require the lua_sheet somewhere and save it. Do the same with the image_file. The sprite_name will be used to locate the frame index of the sprite. Those three things are needed to add an object to berry.

If we add a addImageSheet method to berry, it should save the image sheet somewhere that is only used for texture packer sprites. Since the sprites don't have anything to do with gid, I don't think they should be grouped with Tiled image sheets, but it might be possible. Maybe have a variable like, map.TP_imagesheets or something. We also may want to save the lua file somewhere to map as well. (ie. map.TP_lua_files)

Once we have a method that adds our imagesheet our next step would be:

local imageSheet = map:addImageSheet(image_dir, lua_sheet)  -- returns an imagesheet

At this point I assume myself and other users who are planning to use this feature will have multiple texturepacker image sheets and sprites loaded. Therefore we need a universal lookup across all imagesheets to find the frameIndex for a sprite name. (Ie. if you load 3 imagesheets and lua files, we need to search for a sprite name across all of these) So we would need to add another method to berry getSpriteFrame. It would look like:

-- this assumes the imageSheet was added like so, map.TP_imagesheets[name] = lua_sheet

function Map:getSpriteFrame(sprite_name)
	local spriteFrame
	for name, info in pairs(map.TP_imagesheets) do
		spriteFrame = info:getName(sprite_name)
		if spriteFrame then return spriteFrame end
	end
end

Then if we combine all the above adding a sprite using Texture packer should be simple.

local imageSheet = map:addImageSheet(image_dir, lua_sheet)
local sprite_frame = mapt:getSpriteFrame(sprite_name)
local sprite = display.newImage( layer, image_sheet, sprite_frame)  

I will play around with coding this over the week, but my time is constrained currently. Adding these features turned out to be way more work than I initially thought!

Add support for Lua map files

Tiled allows a user the feature to export the map as either a JSON or lua file. Seems kinda silly that a lua library doesn't support a lua format. With that said, I'm not sure how much work it would take to incorporate this feature.

Move example files to repo or folder

Another useful suggestion. Definitely should consider making the example map, Corona files, etc. all in their own repo or folder perhaps. The main directory should just be berry.lua, the plugins folder, and the README.

If the code is put into an example repo, it will have to constantly updated as Berry as fixed or improvements added to it. This may be time consuming, but probably not.

Fix animations not working properly

So it appears that the animation code is broken. Not sure if it was like this initially or because of some changes I made earlier. Regardless, here is what is happening.

In the README.md it says it’s possible to animate a sprite with the custom property isAnimated for either an object or a layer. The object creation code checks for these properties successfully. The problem is that neither the object nor the layer contains the needed sprite data to animate the object. This is because when you use Tiled’s Animation Editor it exports all the animation data to the tileset. Thus, the object/layer needs to be linked to the tileset somehow.

Luckily it shouldn’t be too hard to fix. In fact, there doesn’t even need to be a isAnimated property at all. I can simply check if the object gid is present in the map.cache.animations table. If it is, then it’s an animated sprite automatically.

Maybe an older version of Tiled had different data structure for its animation stuff? That could be why it’s not working now.

Fix map example

Whenever I load level.json from Tiled I get this,

screenshot 1

I'm currently using Tiled v1.1.5 I think this problem is due to the images not being in the same directory as the json file.

Refactor map.image_cache

So a lot of data has been crammed into this table and I think it’s getting very crowded. It’s time to cleanup and arrange the data into sub-tables. Also I’m going to change the variable name from image_cache to cache because initially it was for only images but I started to put more and more data types in there. It currently contains the following data:

  • Texturepacker sheets and names
  • Tile GIDs for image sheets and image paths
  • Animation sequences for sprite sheets
  • Tileset info and image sheets

All of these types of data need to be put into separate tables and referenced appropriately.

Apply Tiled properties directly to tables

So I’m overhauling how berry does property management for all types of containers: Objects, Layers, Maps, Tilesets, etc.

My goal is to copy properties directly to their designated tables instead of having to do weird lookups. Going to try my best to remove the findProperty function as it will be deprecated and no longer needed.

Separate Berry from Lime2DTileEngine fork

Unless you are planning to merge Berry into Lime2D later on at some point, I would recommend you make Berry a stand-alone repo. I’m also pretty sure the original author of Lime2D is inactive and wouldn’t be able to accept a merge even if that’s the route you want to take.

I would do this for two primary reasons:

  • Berry was rewritten from scratch basically. It no longer has much resemblance to Ponytiled or Lime2D. (Although I would def give them credit in the README)
  • Contributors for code (including yourself) get to have their commits appear in their profile. This doesn’t happen for repos that are forks.

This blog post has some really good information that goes into detail about forks.

You will have to contact GitHub support and tell them you want to detach the fork and make it a stand-alone repository.

Fix label plugin

So while I was overhauling the plugin system I noticed something. The label plugin has many of the variables referenced incorrectly.

Not just that the map.extension property is not even used in Map:extend. I’ll fix them, but it may take me a day or two.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.