Jump to content
  • Advertisement
Sign in to follow this  
Horscht

2D platformer screen/section management and transitions (like Megaman)

This topic is 1925 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My current super primitive amateurish system works like this:

I have a GameState class which just calls update() and render() on all child objects like the player, level, later enemies and so on.

then there is a Player class and a Level class which in turn has a list of LevelSections, this is the class that holds the tiles, renders the tiles, provides methods to access the tiles like GetTileAt(x,y).

The Level class provides the same methods and redirects it to the section the player is currently in.

Tile coordinates start at 0,0 for every section and each section has it's own x,y start position, so when the player is at the last tile of the current section i should be able to iterate through all sections and check if there is a section which has the coordinates of the next tile, right?

Player is at tile 30,20, 31,20 doesn't exist so i iterate through the list of all sections and see if there is one which has the start coordinates 31,xxx and then initiate the mysterious "scrollover-mechanism". Does this sound like a plan?...

 

My player currently gets a pointer to the level like this:

// GameState.cpp

GameState::GameState()
{
	level = new Level();
	player = new Player(level);
}

So now player has access to level and can call it's GetTileAt(x,y) method for colission detection and so on.

Just by the way, what if the level also needs access to the player? At the time the level gets instanciated the player doesn't exist yet...

In the Level class I do everything using a pointer to the current section.

Like so:

// Level.cpp

Tile* Level::GetTile(int x, int y)
{
	return currentSection->GetTile(TL_FOREGROUND, x, y);
}

void Level::Render()
{
	currentSection->Render();
}

And so on...

This works fine if I wanted to stay in one section forever and never be able to go to the next one, but that's not really what I want smile.png

As soon as the player reaches the end of one section, player control should be suspended and the screen should scroll over to the next section, but the player also has to move and play walking animations or not depending on if he is in the air or ground or whatever.

 

How do I do that? Where should the code go that moves the "camera"?

Currently it's in GameState::Render() like this:

void GameState::Render()
{
	RECT pBB = player->GetBoundingBox();
	Vector2D pMid;
	pMid.x = (float)(pBB.left + (pBB.right - pBB.left) / 2);
	pMid.y = (float)(pBB.top + (pBB.bottom - pBB.top) / 2);

	int levelWidth = level->GetWidth();
	int levelHeight = level->GetHeight();

	int minPlayerXOffset = (int)(pMid.x - g_window_width/2);
	int maxPlayerXOffset = (levelWidth - g_window_width);
	if(minPlayerXOffset < 0) minPlayerXOffset = 0;
	if(minPlayerXOffset > maxPlayerXOffset) minPlayerXOffset = maxPlayerXOffset;

	level->Render(minPlayerXOffset);
	player->render(minPlayerXOffset, dt);
}

How do the classes need to interact to make this work?

Should the GameState check if the player is on the edge and if so, call player->SuspendControl() and move the player every frame over to the next section until the transition is complete? But that sounds like it should be in the player class itself. Or maybe the player should have a different state, but I don't know how to implement that, with lot's of switch cases? If elses scattered throughout the update() and render() methods? A different update() and render() for every state()? What would be a good way to do that? I thought maybe with a function pointer that gets passed a different method like this:

// Player.cpp

Player::Player()
{
	_update = &Player::StateDefaultUpdate;
	_render = &Player::StateDefaultRender;
}

void Player::Update(float dt)
{
	(this->*_update)(dt);
}

But how should I organize this? Put it all in the same file or in different ones?

I have absolutely NO IDEA... I wish there was more information on the internet on how to program more complex games than tic tac toe or a jump'n'run that only has one screen and fit in one file. All the open source games I looked at are a THOUSAND times more complicated than what is taught in books and tutorials sad.png

StateManagers, ScreenManagers, BlablaHandler, MovementComponent, blablabla... none of this is explained anywhere. It's like it's expected of me to come up with these myself. But for me that's like coming up with something like calculus from scratch on my own...

I have so much I don't know I don't even know where to start or what questions to ask hahahhaa....

Hopefuly some of you will understand what I am trying to do and can give me some tips on how to do it.

Here's a video of the game I'm trying to copy if you don't already know it:

Book recommendations for getting into more sophisticated game programming or whatever also highly appreciated.

I attached my current sourcecode for the involved classes if you wanna take a look at the actual code.

It's ugly but I wanna get it working first before I clean it up. No need for nice and good to read code that doesn't work smile.png

[attachment=17248:Code.zip]

Share this post


Link to post
Share on other sites
Advertisement

I'm writing a Mega Man clone right now and have implemented the screen transitions. You can see videos with the transitions here:

 

 

The way that I implemented it is to split up the level in to rectangular "rooms". When two rooms connect it gives you an opportunity to perform a transition. Each room has a list of "Transition Regions" which are more-or-less just a rectangle and a transition direction. So if Mega Man is in room #1 then I only check if he's touching transition regions from that room. Once he touches one, a transition is triggered and once it finishes he is now in a different room. Once you're in a different room you only need to check for collisions between transition regions in that room. This allows you to implement both one-way and two-way transitions and prevents you from constantly transitioning back-and-forth in some other cases.

 

Rather than using magic tiles or "outside of the map" triggers, I would suggest you use a method as I described. It's not a lot of work and it's flexible. I came up with this solution after asking the same question on the Game Development Stack Exchange site: http://gamedev.stackexchange.com/questions/6712/mega-man-style-screen-scrolling-design.

 

Essentially the design looks something like this:

 

yO7jT.png

 

As for "where does the code that does the camera movement go", well, that's up to you. I have a class where the "game play" takes place and I handle the screen scrolling there. When you collide with a transition region it sets a flag that says "a transition is happening now". When that flag is true the screen scrolls to the next room. Once you get to the next room it sets the "transition is happening now" flag to false. That way you can "disable" game play while the transition is happening.

 


Should the GameState check if the player is on the edge and if so, call player->SuspendControl() and move the player every frame over to the next section until the transition is complete?

 

That's what I do when my "transition is happening now" flag is true. I don't think it's the Player's responsibility to know about transition movements -- something else should do that.

Edited by Maxamor

Share this post


Link to post
Share on other sites

Awesome, that's exactly what I'm trying to do too, you even made your code available on github, big thanks for that!

I also found another one a while ago (https://github.com/Tesserex/C--MegaMan-Engine) but both are a little over my head sad.png

How do I progress from simple games to something like this? This is on a whole different level than what is taught anywhere.

The thing I'm having the most trouble with and I think is the most important thing is the software engineering part. Code design, structuring, architecture, whatever it's called.

Hopefully I can learn something from reading your code, but I never know where to start and how it all works together when there are already 100 files.

 

I thought that my "Transition Regions" would just be the edge of the map, or maybe the last column/row of the tile array that doesn't get drawn or something like that.

If I then want to stop the player from going back I could just make those tiles solid in the next room. But I still don't know how to do the actual scrolling.

Which class should check where the player is and when to initiate the transition? The GameState? The Level? The Player?

I guess all the classes do their scrolling in their own way, but how do the classes know when the transition is over and gameplay should resume?

 

 

Share this post


Link to post
Share on other sites

How do I progress from simple games to something like this? This is on a whole different level than what is taught anywhere.

 

Most large things start off small and grow large over time.

 

 

 

But I still don't know how to do the actual scrolling.

Which class should check where the player is and when to initiate the transition? The GameState? The Level? The Player?

 

 

 

I like to think of the player and enemies as puppets, and the level is a stage -- without a puppet master they don't do much. I would put this logic in the GameState or whatever "knows" about both the player and the level.

 

In my game, a "Room" is essentially the same as your "LevelSection" idea. When the player collides with a transition region, a change is made to signal that a "transition" is happening, then the game figures a few things out:

  • The direction of the transition (upwards, rightwards, downwards, leftwards)
  • The position of the next room

If you know both of these things, then it's pretty easy to decide what to do next. While the "transition is happening now" flag is true you shift the camera a little bit in the direction of the next room. For Mega Man, according to my measurements, the camera moves 4 pixels-per-frame horizontally or 3 pixels-per-frame vertically while transitioning (at 60 frames per second). As you move the camera, you'll eventually move all the way to the next room -- so you basically just keep moving until you've positioned the camera exactly where you want it. Once the camera has moved to the desired location you unset the "transition is happening now" flag and everything goes back to normal. Since you know the position of the room and the position of the camera it is easy to tell when you've hit your goal.

 

As for moving the player, you do the same thing as with the camera but with a smaller amount of movement. I let my "game state" perform this movement -- my player object doesn't know its being moved because it isn't being updated during transitions.

 

Obviously, my actual implementation is a bit more complex than what is explained above -- but at the highest level that's what happens.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!