Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411500 Posts in 69373 Topics- by 58428 Members - Latest Member: shelton786

April 25, 2024, 12:10:34 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsLeilani's Island
Pages: 1 ... 5 6 [7] 8 9 ... 67
Print
Author Topic: Leilani's Island  (Read 411721 times)
Crabby
Level 2
**



View Profile
« Reply #120 on: August 13, 2015, 05:22:42 PM »

A rideable Maca would be really cool.
Just imagine Leilani riding with that. And her spin dash could be more powerful with the Maca friend she has.
and it would just be adorable.  Smiley
Just my two cents.
This looks wonderful.
Logged

Working on something new!
Follow me @CrabbyDev.
ThilDuncan
Level 0
***


Indie Developer at Ghost Town Games


View Profile WWW
« Reply #121 on: August 14, 2015, 09:18:17 AM »

Love catching up with Leilani, great work Ishi! Always love how crisp and polished your work is, can't believe I still haven't played it yet - must rectify that as soon as possible! :D
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #122 on: August 14, 2015, 12:26:32 PM »

Love catching up with Leilani, great work Ishi! Always love how crisp and polished your work is, can't believe I still haven't played it yet - must rectify that as soon as possible! :D

Thanks! And yeah I've been wanting to have another good multiplayer session on Overcooked. Hope to see you at CB2 Indies again soon!

A rideable Maca would be really cool.
Just imagine Leilani riding with that. And her spin dash could be more powerful with the Maca friend she has.
and it would just be adorable.  Smiley
Just my two cents.
This looks wonderful.

Hehe, yep that would be adorable! It might be a bit too much work to add as a game mechanic, but I do like the idea of Leilani having a buddy Smiley

Tiled in C++

Someone asked me about how I use Tiled in C++ so here's a quick overview. I don't often go into code stuff so it may be interesting.

For the actual parsing of the XML files I use tinyxml. It's been a long time since I used tinyxml directly though - I wrote my own wrapper class called EasyXML that really simplifies traversing the files and pulling out values/attributes.

For reading Tiled maps specifically, my gameplay code never deals directly with reading the XML file. I have a whole series of classes that represent the entire Tiled map data, so I have one common bit of code that loads the entire Tiled map at once and fills in all these classes. Various bits of gameplay code can then make use of the data later.

I'm not sure if I 100% support all the features of Tiled yet but my classes are:

TiledBase - most of the other classes derive from this one. This provides common features like width, height, and a property list (most things in the editor can be given arbitrary properties).
TiledMap - contains all tilesets and layers.
TiledImage - basically just a filename.
TiledLayerBase - object layers and tile layers both derive from this.
TiledObjectLayer - a layer containing a list of objects.
TiledObject - these are the objects that are in object layers. Can be rectangle, polyline or polygon.
TiledTileLayer - a layer containing an array of tiles.
TiledTile - contains the ID for a tile.
TiledTileset - contains an image and array of tiles.
TiledProperty - a name + value pair.

Now some examples of bits of code to give an idea how it looks.

Creating the TiledMap: I load the file with EasyXML and pass that in. The EasyXML loader gets passed around to all of the Tiled classes which load their individual bits. You can imagine replacing EasyXML with any xml parsing system. Epileptic

Code:
cEasyXML loader(pGrid->pSections[section].pFilename);
pSection->pTiledMap = new cTiledMap(&loader);

TiledMap constructor: it loops through all the items in the root of the Tiled XML file, and creates tilesets, tile layers or object layers.

Code:
cTiledMap::cTiledMap(cEasyXML *pLoader)
: cTiledBase(pLoader)
{
pLoader->ReadyLoop();
while(pLoader->ContinueLoop())
{
const char *pTagName = pLoader->GetTagName();

if(!strcmp(pTagName, "tileset"))
{
cTiledTileset *pTileset = new cTiledTileset(pLoader);
Tilesets.push_back(pTileset);
}
else if(!strcmp(pTagName, "layer"))
{
cTiledTileLayer *pLayer = new cTiledTileLayer(pLoader);
TileLayers.push_back(pLayer);
Layers.push_back(pLayer);
}
else if(!strcmp(pTagName, "objectgroup"))
{
cTiledObjectLayer *pLayer = new cTiledObjectLayer(pLoader);
ObjectLayers.push_back(pLayer);
Layers.push_back(pLayer);
}
}
}

TiledMap (and most of the other classes) inherit from TiledBase. The TiledBase constructor is responsible for loading the properties list.

Code:
cTiledBase::cTiledBase(cEasyXML *pLoader)
{
Width = pLoader->ReadInt("width");
Height = pLoader->ReadInt("height");
TileWidth = pLoader->ReadInt("tilewidth");
TileHeight = pLoader->ReadInt("tileheight");

if(pLoader->OpenElement("properties"))
{
pLoader->ReadyLoop();
while(pLoader->ContinueLoop("property"))
{
cTiledProperty *pProperty = new cTiledProperty(pLoader);
Properties.push_back(pProperty);
}

pLoader->Up();
}
}

I make good use of these properties to set all kinds of variables on different game entities. For example to alter timing sequences for things that turn on and off. TiledBase contains a number of functions for searching the properties for a specific value. It's not super fast - just a naive search through the list - but I'm never dealing with huge lists and only get these values when a level is loading.

Code:
float cTiledBase::GetFloatProperty(const char *pPropertyName, float defaultValue) const
{
for(unsigned int i(0); i < Properties.size(); ++i)
{
if(!strcmp(Properties[i]->pName, pPropertyName))
{
float result = defaultValue;
sscanf_s(Properties[i]->pValue, "%f", &result);

return result;
}
}

return defaultValue;
}

TiledLayer constructor: I have the Tiled editor configured to save the tile layers in CSV format. So I read the "data" string from the XML file and use strtok to separate the values.

Code:
cTiledTileLayer::cTiledTileLayer(cEasyXML *pLoader)
: cTiledLayerBase(pLoader)
{
pTiles = new unsigned int[Width * Height];

if(pLoader->OpenElement("data"))
{
char *pValues = pLoader->CopyTagContents();

char *pNextToken = NULL;
char *pCurrentToken = strtok_s(pValues, ",", &pNextToken);

int x(0);
int y(0);

while(pCurrentToken)
{
unsigned int tileValue = 0;
sscanf(pCurrentToken, "%u", &tileValue);

pTiles[x + y * Width] = tileValue;

++x;
if(x >= Width)
{
x = 0;
++y;

if(y >= Height)
{
break;
}
}

pCurrentToken = strtok_s(NULL, ",", &pNextToken);
}

delete[] pValues;

pLoader->Up();
}
}

The TiledTileLayer::GetTile function is also interesting - Tiled stored the horizontal/vertical flips as bit flags in the tile ID. If you don't remove them then the tile ID will be incorrect.

Code:
int cTiledTileLayer::GetTile(int x, int y, bool *pFlippedX, bool *pFlippedY)
{
if (x < 0 || y < 0 || x >= Width || y >= Height)
return 0;

unsigned int tile = pTiles[x + y * Width];

const unsigned FLIPPED_HORIZONTALLY_FLAG = 0x80000000;
const unsigned FLIPPED_VERTICALLY_FLAG   = 0x40000000;
const unsigned FLIPPED_DIAGONALLY_FLAG   = 0x20000000;

if(pFlippedX)
{
*pFlippedX = (tile & FLIPPED_HORIZONTALLY_FLAG) == FLIPPED_HORIZONTALLY_FLAG;
}

if(pFlippedY)
{
*pFlippedY = (tile & FLIPPED_VERTICALLY_FLAG) == FLIPPED_VERTICALLY_FLAG;
}

// Remove flip flags
tile &= ~(FLIPPED_HORIZONTALLY_FLAG |
FLIPPED_VERTICALLY_FLAG |
FLIPPED_DIAGONALLY_FLAG);

return (int)tile;
}

My Tiled maps use external tilesets - meaning that the tilesets are stored in a separate file, and referenced from many different maps. This makes the loading a little more awkward. What I do is, in the TiledTileset constructor, if the tileset is an external one - which is indicated by the "source" attribute - then I create a new EasyXML loader and use that for the remainder of the constructor.

The Reload function is in TiledBase, and is there to make sure that any properties that are stored in the external tileset are also loaded.

Code:
cTiledTileset::cTiledTileset(cEasyXML *pLoader)
: cTiledBase(pLoader)
, pImage(NULL)
{
FirstGID = pLoader->ReadInt("firstgid");

cEasyXML *pAlternateLoader = NULL;
const char *pExternalSourceFilename = pLoader->GetAttributeContents("source");

if(pExternalSourceFilename)
{
// Read tileset from another file
char buffer[1024];
sprintf_s(buffer, 1024, "%s/%s", pLoader->GetDirectory(), pExternalSourceFilename);

pAlternateLoader = new cEasyXML(buffer);

pLoader = pAlternateLoader;

Reload(pLoader);
}

pName = pLoader->CopyAttributeContents("name");

... etc

Phew.. hope some of that provides some useful tips for anyone wanting to load Tiled maps in C++.

Level Start

This post is a bit dry, so here's what you'll see at the start of every level! I'm trying out 60FPS gifs too.

Logged

SolarLune
Level 10
*****


It's been eons


View Profile WWW
« Reply #123 on: August 15, 2015, 07:04:49 AM »

^ That start is already excellent; if you wanted it to be a tad more crunchy, I think you could make the size of the circle tied to her height - it'd grow, shrink as she fell, and then expand faster and finish when she lands. It's already looking really good anyway, though!
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #124 on: August 16, 2015, 09:33:20 AM »

^ That start is already excellent; if you wanted it to be a tad more crunchy, I think you could make the size of the circle tied to her height - it'd grow, shrink as she fell, and then expand faster and finish when she lands. It's already looking really good anyway, though!

That's a good suggestion! Reducing it a bit first makes it more punchy when it expands. Thanks! Coffee

Logged

Storsorgen
Level 2
**


View Profile
« Reply #125 on: August 16, 2015, 09:37:24 AM »

I think it could probably expand even faster on the final push Smiley
Logged
blekdar
Level 3
***


Decisively Indecisive


View Profile WWW
« Reply #126 on: August 16, 2015, 11:48:35 AM »

Quote
I think it could probably expand even faster on the final push Smiley

+1 Seems to dragon on a bit, I'd say either double the speed or have it quickly accelerate.

Also need to say this has become one of my favorite projects to watch on here, helps that I've been on a snes era platforming kick too, but that's aside the point. Totally dig the art, mechanics, it all looks so good.
Logged

Raku
Level 10
*****


Dream's Bell


View Profile WWW
« Reply #127 on: August 17, 2015, 04:33:15 AM »

I love that, it's like she busts into the stage, and then forces the reluctant stage to exist. But I also agree I think it would look a bit better expanding much faster once she stomps
Logged

Grog
Level 1
*



View Profile
« Reply #128 on: August 17, 2015, 11:42:06 AM »

Noticed something was wrong, stared at it for a 1 minute. Realized it was too slow at the end. Realized I'm too slow and everyone has already told you. :p

I'm not sure if I've posted here at all yet, but I'm excited for your game. It looks beautiful and like a lot of fun.
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #129 on: August 21, 2015, 04:50:33 AM »

Hehe, thanks everyone for the feedback! I'm glad you all agree! Actually when I posted the previous image I was kinda thinking the end was a bit slow, but needed a bit of encouragment to make more tweaks.

I can't post a gif right now, but I've made it really snappy. Coffee
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #130 on: August 23, 2015, 02:33:08 AM »

Aloha!

Machines

Over the last couple of weeks I've been revamping the end-of-level destroy-the-machine goal. A while ago I posted this version of it:



The machine is now a battery charger - I think that gives it a clearer purpose, as even I didn't know what the satellite dish was for! The idea is that the big baddie (who I'm still working on ideas for) is sapping energy from the island.



It's also now fully destructible. Evil Hitting the weak spots will disable it and end the level. Hitting the battery totally destroys it and will give some sort of bonus.



I would still like to work on the effects for this, and the visuals for the weak spots, but for now I'm happy to have it functional.

For fun, here's the very first mockup of the machine from over a year ago. I'm glad I improved it...

Logged

grayhaze
Level 0
***



View Profile WWW
« Reply #131 on: August 23, 2015, 02:38:23 AM »

I love watching this progress. Already I get the feeling it's going to be a huge hit when you finish it, and it feels like a far more polished version of those old Nintendo platformers. Keep up the great work Ishi!
Logged

Green Gospod
Level 1
*


View Profile
« Reply #132 on: August 23, 2015, 04:35:44 AM »

Mario's end flag basically.  Tongue

Looking forward to playing the game.  Coffee
Logged
Pudgepig
TIGBaby
*


View Profile
« Reply #133 on: August 23, 2015, 04:41:37 AM »

This looks amazing,I can't wait to play it!  Smiley
Logged
Louard
Level 2
**


View Profile WWW
« Reply #134 on: August 23, 2015, 05:26:24 AM »

Yes, loving the progress on this! I like what you're going for with the end of level challenge. It's a nice little reward at the end.
Logged

-Louard
louardongames.blogspot.com
KaiTheSpy
Level 0
***


how to make the game


View Profile
« Reply #135 on: August 23, 2015, 01:32:04 PM »

This game's starting to come together really well! Can't wait to get to try it out. Hand Money Left
Logged

i am a 14 year old loser who sort of knows how to program
Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #136 on: August 24, 2015, 04:26:45 AM »

Thanks all! Smiley

Mario's end flag basically.  Tongue

Hehe, yep it is. A vertical target just works so well as a challenge in a platform game - I never thought the alternatives in other Mario games (e.g. hitting the card at the end of a SMB3 level) were as much fun.
Logged

Raku
Level 10
*****


Dream's Bell


View Profile WWW
« Reply #137 on: August 25, 2015, 03:18:08 AM »

Oof, that concept for the battery charger! Good memories of the goal challenge concept from Mario Land 2 or the goals from Donkey Kong Country 2. I love the concept of "you can just run through the exit OR you can do this trick jump and hit this target up here to get a better thing!" This game is so polished already, it's so inspiring!
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #138 on: August 27, 2015, 12:45:52 PM »

Update time!

I'm currently working on adding some interactive fruits - including the coconut I briefly showed a couple of weeks ago. There's a preview on my twitter here. I won't have any time to work over the weekend though, so it's time to show another old work-in-progress feature!

WIP: Invincibility



Invincibility is always fun - currently when Leilani turns invincible, she rolls faster, smashes through blocks without stopping and kills enemies instantly.

The main thing I like about it at the moment is the rainbow effect - it's automatically generated by combining a looping rainbow animation with the Leilani sprites. Any non-black and non-transparent pixels in the Leilani sprite are replaced.

I'm not sure yet how invincibility will be triggered, or if I'll do any Mario-style rewards for killing multiple enemies. It'll also need more shiny, sparkly effects!
Logged

Raku
Level 10
*****


Dream's Bell


View Profile WWW
« Reply #139 on: August 27, 2015, 01:28:56 PM »

Shiny Sparkly effects would definitely be welcome. Im not sure what it is about that rainbow, but it looks a little washed out to me. Maybe that's just me? maybe sparkly effects would remedy that anyway though.
Logged

Pages: 1 ... 5 6 [7] 8 9 ... 67
Print
Jump to:  

Theme orange-lt created by panic