Author Topic: Quesion regarding transition between levels created with DAME.  (Read 5795 times)

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
Hi,

1- When using Complex Exporter, how would one change levels? (or as DAME calls them Groups), I tried this
currentLevel = new Level_Level2(true, onObjectAddedCallback);
but it loaded the new level OVER my current one and didn't update the hitTiles, so player and enemies were colliding with previous level's hitTiles.

2- How would I get current level's bounds? BoundsMaxX is static and stored in BaseLevel.as and is constant in levels, do I have to cast something to current Level_Level1 or something?

-tnx!
« Last Edit: Thu, Dec 1, 2011 by test84 »
blog, twitter, Check out my award winning game, Rot Gut:

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
I may have made some bad assumtions by saying rooms on the topic's name so I changed it to levels.

What I want to do is basically how to transit from a level created with DAME to another one.
blog, twitter, Check out my award winning game, Rot Gut:

XanderXevious

  • Contributor
  • ****
  • Posts: 360
  • Karma: +0/-0
    • View Profile
    • Deadly Alien Microbots
1. It depends on what exactly you want to do. But there is the destroy() function which you can call on the first level. You can also set the parentObject to a FlxGroup you yourself add to FlxG.state. In fact, I recommend this as then you can have more control in your own code about what goes on top of the level, eg UI.

2. I'm not sure why I set the bounds to be static actually. For now, unless you do a rewrite of the exporter a dirty hack would be to just look at the values of bounds after you create the level. I think in a future update I'll add a function to retrieve the bounds.

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
Thanks,

I didn't understand this part:
You can also set the parentObject to a FlxGroup you yourself add to FlxG.state. In fact, I recommend this as then you can have more control in your own code about what goes on top of the level, eg UI.

I tried this:
Code: [Select]
currentLevel.destroy();
currentLevel = new Level_Level2(true, onObjectAddedCallback);
but when it wants to draw, it gets a null on FlxGroup's draw.

And on the second note, I don't want to use a FlxState for each levels, because I have a lot of them and it would need me duplicate a lot of reduntant code.

All my levels are groups in a DAME file, my question is simply how I should load a new group/Level?
« Last Edit: Fri, Dec 2, 2011 by test84 »
blog, twitter, Check out my award winning game, Rot Gut:

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
After some more in depth debugging I think I know what causes the error.

There is a FlxGroup called "members" for current state that holds what is there to be update and such (which I think we add to via FlxG.state.add() ). So when I destroy the first level, it nullifies the first member of that FlxGroup but when I create the new level, it doesn't get replaced to that first member but gets added to the last element of "members" and when draw wants to draw elements of "members", it will the first member which is null and returns error.

So the problem I think is how to replace the newly created level into the first element of "members" OR how to completely remove the first element of "members".
( I personally believe we should do the first one in order to keep order of draw)
blog, twitter, Check out my award winning game, Rot Gut:

Alextfish

  • Active Member
  • ***
  • Posts: 174
  • Karma: +0/-0
    • View Profile
Your terminology is slightly wrong.

FlxState extends FlxGroup; so every FlxState is also a FlxGroup. Each FlxGroup has a property which is called "members". (So each FlxState has that property as well.) The "members" property is just a basic Array (the class provided by ActionScript).

If you want to directly operate on the "members" Array, you technically can - there are assorted operations you can perform on ActionScript Arrays - but it's almost always better to use the corresponding methods on FlxGroup. FlxGroup provides methods "remove", "replace" and "clear", all of which operate on the internal "members" Array, and which between them should do all you need.

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
Thanks for correcting me!
It's sad that by the time I'm getting to understand flixel, we have to ditch it and move to other technologies like HTML5/Unity/etc.

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

I believe there is a better way to do this because almost  every game has level transition, I really don't think manipulating that members array is a good idea and prefer to use a much higher level method that hopefully exists.

If not, I think I have to override destroy on my levels and then mess with that members array, hope not.
blog, twitter, Check out my award winning game, Rot Gut:

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
I finally achieved transition to the second group with:
Code: [Select]
currentLevel.destroy();
currentLevel = new Level_Level2(true, onObjectAddedCallback);
FlxG.state.members[0] = currentLevel;

But I don't like it, it doesn't seem right to me and works kinda awkward.
Do I need to destroy everything and new them all? What needs to get destroyed? Because on the new level, everything is acting weird for the most part, my weapon detaches from the player, player gets collided with particles that is not supposed to and doesn't in the first level and all these weirdness.

Do I have to destroy everything I created in Create part of my playstate and re-new them?

gOD it's complicated.

-=-=-=-=-

I really do love to hear how you guys transit between your levels in your games!
« Last Edit: Fri, Dec 2, 2011 by test84 »
blog, twitter, Check out my award winning game, Rot Gut:

Alextfish

  • Active Member
  • ***
  • Posts: 174
  • Karma: +0/-0
    • View Profile
You're right that "a much higher level method hopefully exists": it's the ones I mentioned in my last post. Rather than going FlxG.state.members[0] = currentLevel, you could use the function I mentioned in my last post: replace or remove. E.g. FlxG.state.replace(oldLevel, newLevel);

However, the questions you raise about destroying and re-creating things I agree are problematic. My game has one (very) large level, so I'm hoping to not need to do this; I have a different set of problems facing me, to do with only instantiating enemies when the player gets near, and so on. I've not established precisely how big I want my map to be, so I've not faced all these difficulties yet. It may be that I have more difficulties than you do, if I do end up having to split my map into sections, because one of the key parts of my game's gameplay is that you can revisit old locations with new capabilities.

So in other words, I'd really like to know how other people switch between DAME levels as well!

I kinda have an inkling that there isn't any one well-supported way to do it.

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
You're right that "a much higher level method hopefully exists": it's the ones I mentioned in my last post. Rather than going FlxG.state.members[0] = currentLevel, you could use the function I mentioned in my last post: replace or remove. E.g. FlxG.state.replace(oldLevel, newLevel);

I couldn't get it to work, I tried this
Code: [Select]
FlxG.state.replace( currentLevel, tempLevel);but it whines that parameters should be FlxBasic, which is BaseLevel. Then I tried casting:
Code: [Select]
FlxG.state.replace( FlxBasic(currentLevel), FlxBasic(tempLevel));but it can't be upcasted to FlxBasic.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
However, the questions you raise about destroying and re-creating things I agree are problematic. My game has one (very) large level, so I'm hoping to not need to do this; I have a different set of problems facing me, to do with only instantiating enemies when the player gets near, and so on. I've not established precisely how big I want my map to be, so I've not faced all these difficulties yet. It may be that I have more difficulties than you do, if I do end up having to split my map into sections, because one of the key parts of my game's gameplay is that you can revisit old locations with new capabilities.

So in other words, I'd really like to know how other people switch between DAME levels as well!

I kinda have an inkling that there isn't any one well-supported way to do it.

Yes but there are common practices, like what to destroy and what not to.
I mean I am doing something totally wrong here, my player collides with particles that it doesn't in the first level ! There should be a big common practice here and then, as you said, some practices that one has to find out for his own kind of game. Like do you have to destroy everything you create in your Create() procedure or not, etc.

Besides, I'm using DAME's unaltered exporter, as alot of guys do and being DAME very popular and most games having more than one level, it's not unrealistic to expect some common knowledge on this.
blog, twitter, Check out my award winning game, Rot Gut:

tkshredder

  • Member
  • **
  • Posts: 20
  • Karma: +0/-0
  • Hit the ground running, with a plan
    • View Profile
    • panyamedia.com
Thanks for posting this discussion, I'm just about getting to this point in my game. If I figure out any other methods for switching levels, I'll add it here.

Previously ran into a similar issue when I had two levels running concurrently: picture a platform game where going in doors would take the player to another connected level - then could either travel back through the entry door, or go in a different door. At any given moment, the player was in level A or B, only I had to basically keep everything in memory, since if the player acquired a special pickup, the game needed to keep track if the player left the area, went to the other level, then came back again. This was done in Flixel 2.35, but I believe the underlying core of the mechanism would still work in 2.50.

Anyway, that's a little off topic, but if anyone wants to see the code for that, PM me and I'll send it over.

XanderXevious

  • Contributor
  • ****
  • Posts: 360
  • Karma: +0/-0
    • View Profile
    • Deadly Alien Microbots
If any of you guys ever come up with a better exporter or a few methods I can add to the existing one (without breaking backwards compatibility) then I'll be happy to add it. As you can expect I have less time to look at the exporters than I do with DAME itself so I'm sure they need a bit of love.

But jus in case it helps in the exporter you can specify 2 extra classes which alter the inheritence structure. You can specify the "Base Class Extends" which Base Class will itself derive from, and an intermediate class (which will come between the level class and the base class. In a test game I'm toying around with I actually have this structure of inheritence:

Level_XXX (exported) extends LevelData (code only) extends BaseClass extends FlxGroup.

So basically, in my LevelData class I can put in intermediate code which will override little things that I want to be different for my own game. You could possibly put in your own destroy code there to do specific things like level transitions.

What's more, when I add levels, I don't have to add them to the state directly. I can pass in a group which I can add them to, in this case lyrStage:

Code: [Select]
var currentLevel:LevelData = new Level_MainTower(false, onObjectAddedCallback, null);
currentLevel.setup(levels, lyrStage, onObjectAddedCallback);
FlxG.state.add(lyrStage);

Personally, I use this method because I don't like adding to the state directly. I prefer to have more control over where things go in the display hierarchy.

I just tested this with a remove and it worked perfectly. So here's how I handle level transitions in my PlayState (I'm running from the old flixel so I can't vouch for this in the latest version):

Code: [Select]
// Need a reference to the level we load so that GetLevelClassFromName works.
private static var TowerRoom:Level_TowerRoom = null;

public static function GetLevelClassFromName(name:String):Class
{
try
{
var className:String = "com.Exported.Level_" + name;
var ClassReference:Class = getDefinitionByName( className ) as Class;
return ClassReference;
}
catch ( error:Error)
{
}
return null;
}

public function LoadLevel(name:String):void
{
try
{
var ClassReference:Class = GetLevelClassFromName(name);
if ( ClassReference )
{
var nextLevel:LevelData = new ClassReference(false, onObjectAddedCallback);
nextLevel.setup(levels, lyrStage, onObjectAddedCallback);
// Each level has a PlayerGroup, sometimes empty, just for placing the player in,
// to ensure that it's z position is correct.
if ( nextLevel["PlayerGroup"] != null )
{
if ( _player.Level["PlayerGroup"] != null )
{
var oldGroup:FlxGroup = _player.Level["PlayerGroup"];
oldGroup.remove(_player, true);
}
var newGroup:FlxGroup = nextLevel["PlayerGroup"];
newGroup.add(_player, true);
}
lyrStage.remove(_player.Level);
_player.Level = nextLevel;
FlxG.followBounds(BaseLevel.boundsMinX + 1, BaseLevel.boundsMinY + 1, BaseLevel.boundsMaxX - 1, BaseLevel.boundsMaxY - 1);
}
}
catch ( error:Error)
{
}
}
« Last Edit: Tue, Dec 6, 2011 by XanderXevious »

photonstorm

  • Administrator
  • Key Contributor
  • *****
  • Posts: 1502
  • Karma: +1/-0
    • View Profile
    • Photon Storm
test84 - I'm running out of time to write a detailed reply here, but I thought I'd do the following for you (and anyone else reading) instead:

Here is the full source code to Cat Astro Phi.

It's Flixel 2.3, but the techniques I used for changing level, object/class structure, weapons, achievements, Registry, etc are all the same. So there might be something you can get from it!

http://sandbox.photonstorm.com/catastrophi/CatAstroPhi_Source.zip
http://www.photonstorm.com



"Tell me and I will forget, show me and I might remember, involve me and I will understand" - Confucius

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
@ Rich:
Oh, you didn't have to! Thanks so much! wow.

@ Charles:
I'm writing a long reply but don't want to pop anything here, I'll reply in a few days.
blog, twitter, Check out my award winning game, Rot Gut:

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
Charles, I've read your post like 50 times already but I can't my head around it. Would you please be a little more specific and tell me in steps what I should do?

One of the reasons is that whenever I load a level, it instantly gets created on the screen and I cannot store it on a variable or FlxGroup or anything in that matter, and I have no idea what to put in those intermediate classes.
blog, twitter, Check out my award winning game, Rot Gut:

c023-DeV

  • Game Artisan
  • Active Member
  • ***
  • Posts: 176
  • Karma: +0/-0
    • View Profile
    • DeV-ZoO
If it helps in any way:
I am using a registry to save a number of the current level then I add +=1 to that number on the end level event and then I reset my playstate. In my playstate I have a case switch to load the level depending on the number in the registry.... works for my case... if registry.currentlevel == 1 ... blah blah and I save all cross level data in the registry.
If you aint got no dedication, you won't get no education!

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
If it helps in any way:
I am using a registry to save a number of the current level then I add +=1 to that number on the end level event and then I reset my playstate. In my playstate I have a case switch to load the level depending on the number in the registry.... works for my case... if registry.currentlevel == 1 ... blah blah and I save all cross level data in the registry.

Did you make your levels with DAME?
blog, twitter, Check out my award winning game, Rot Gut:

c023-DeV

  • Game Artisan
  • Active Member
  • ***
  • Posts: 176
  • Karma: +0/-0
    • View Profile
    • DeV-ZoO
Yes, complex exporter.
If you aint got no dedication, you won't get no education!

test84

  • Key Contributor
  • *****
  • Posts: 1328
  • Karma: +0/-0
  • ت
    • View Profile
    • My personal site.
Yes, complex exporter.

Thanks, I'll consider it.

I'm really eager to hear Charles's reply over it, there should be good reasons why he and rich don't use simple methods such as this.
blog, twitter, Check out my award winning game, Rot Gut:

c023-DeV

  • Game Artisan
  • Active Member
  • ***
  • Posts: 176
  • Karma: +0/-0
    • View Profile
    • DeV-ZoO
they do use that method, that's where I looked them up ;)
If you aint got no dedication, you won't get no education!