ShuKen
|
 |
«
Posted
2012-11-19 03:13:41 » |
|
Hi guys! I been doing some simple games on slick, and I found it very interesting. Now Im moving to libGDX, which is very similar in a few things, but...
I really like the StateBasedGame and BasicGameState of Slick2D, and been looking for something similar on libGDX. I didnt find anything beyond the ApplicationListener. Is there something similar to "slick2D -stateGame system-" or I must do it myself using ApplicationListener? In that case...I have some work to do before starting any game :S
Thanks!
|
|
|
|
namrog84
|
 |
«
Reply #1 - Posted
2012-11-19 03:28:27 » |
|
Although ApplicationListener is the default, I'd recommend doing Extend Game instead of applicationlistener. Game does extend applicationlistener
Than I would recommend instead of using 'states' is to use 'screens'
Each 'screen' has its own set of draw/render and such that you can setup similiar to how I think you want it to behave like.
Then you can call from your "game" to setScreen as a way to change between different states or screens?
This is of course if you simply want a way to seperate different screen/stages like a "intro screen" menu screen ", gameStatescreen
edit: however, there are a few things that are handled a bit differently, such as input, and utilizing the stage or other things and Gdx.input.setprocessor so some things won't be the same
|
"Experience is what you get when you did not get what you wanted"
|
|
|
ReBirth
|
 |
«
Reply #2 - Posted
2012-11-19 11:52:29 » |
|
You can create one Game class and multiple Screen classes for your state/screen.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
R.D.
|
 |
«
Reply #3 - Posted
2012-11-19 11:57:53 » |
|
The problem with screen is that it directly sets a new screen. I liked the way Slick2D did it and that is the reason why I copied it in my own engine 
|
|
|
|
ReBirth
|
 |
«
Reply #4 - Posted
2012-11-19 11:59:08 » |
|
I see no prob in directly screen set. You can still add some transition effects.
|
|
|
|
R.D.
|
 |
«
Reply #5 - Posted
2012-11-19 12:05:07 » |
|
Yes but you need to do it in the Screen class. Since moving from one screen to another might occur often it makes sense to extract the Transition in some way  If you don't need it then it's okay but let me have my cool StateBasedGame 
|
|
|
|
ReBirth
|
 |
«
Reply #6 - Posted
2012-11-19 12:08:18 » |
|
Then it is a opportunity to make a wrapper library to make it happens 
|
|
|
|
badlogicgames
|
 |
«
Reply #7 - Posted
2012-11-19 16:21:45 » |
|
We never looked at how Slick2D does things. Expecting libgdx to work like it is a bit strange 
|
|
|
|
Gjallar
|
 |
«
Reply #8 - Posted
2012-11-19 17:31:49 » |
|
I found THIS to be very helpful.
|
|
|
|
Ultroman
|
 |
«
Reply #9 - Posted
2012-11-19 17:55:29 » |
|
I don't see any reason to have a state-engine implemented in libgdx. Like many before me have said, each screen is a state. If you really want to implement a state-system, then make an AbstractScreen class which extends Screen. Give it an int STATE, which is sent as a parameter in the constructor, and you'll have a way of identifying states depending on which screen is active. If you really need to do something in your Game-class depending on which state you're in, this way you can do that, but it seems rather forced.
What exactly do you feel you're missing between using a statebased engine and screens?
As an example: I have a game-screen, which in its render() calls stage.act(), calls my own update(), renders all my game-graphics (without using the stage, but on the spritebatch from the stage), and then after all those graphics have been rendered, I call stage.draw() which draws my HUD on top of everything. (It works, but I don't know if its stupid ^^) But this way I can just have a boolean telling the game-screen whether it is paused or not. If it gets paused it runs my pause() which adds the elements of my pause-menu to the stage and sets the boolean paused to true. Then I have an if-statement around my call to update() so the game stops running if it is paused. My unpause() removes the pause-screen elements from the stage again and sets the boolean paused to false.
|
- Jonas
|
|
|
Games published by our own members! Check 'em out!
|
|
Cero
|
 |
«
Reply #10 - Posted
2012-11-19 17:58:47 » |
|
I dont even know why some of you need a screen class of whatever snippet from my current project: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public void render() { Gdx.graphics.getGLCommon().glClearColor(0.0f, 0.0f, 0.0f, 0.0f); Gdx.graphics.getGLCommon().glClear(GL10.GL_COLOR_BUFFER_BIT); spriteBatch.begin(); if (gameState == GAMESTATE.TITLE) { spriteBatch.setProjectionMatrix(hud_camera.combined); titleScreen.renderAll(spriteBatch); } else if (gameState == GAMESTATE.LEVELSELECT) { spriteBatch.setProjectionMatrix(hud_camera.combined); titleScreen.renderBG(spriteBatch); levelSelectScreen.updateAndRender(spriteBatch); } else if (gameState == GAMESTATE.INGAME) { checkIngameInputs(); computeMainGame(); adjustCamera(); camera.update(); parallax_camera.update(); bgMap.render(spriteBatch, parallax_camera);
... |
|
|
|
|
davedes
|
 |
«
Reply #11 - Posted
2012-11-19 18:06:10 » |
|
Cero - that works for simple games with three game states and small amounts of code per state. As each state grows, and as your game grows (i.e. options state, credits, intro, loading, etc) then your game will soon become a complicated mess of if-else chains and scattered logic.
EDIT: Also, it looks like you're almost following object-oriented approaches; i.e. "title.render", "levelSelect.render" -- you may as well go a step further and abstract your Screen/State system so that it's scalable and modular.
IMO it's better to design your own state system based on the specific needs of your game. Slick's transitions were nice for newbies, but pretty useless if you wanted more flexibility.
|
|
|
|
Cero
|
 |
«
Reply #12 - Posted
2012-11-19 18:38:52 » |
|
EDIT: Also, it looks like you're almost following object-oriented approaches; i.e. "title.render", "levelSelect.render" -- you may as well go a step further and abstract your Screen/State system so that it's scalable and modular.
yeah but its just a dump of that code in another class, so that the main game class isnt as convoluted. Its no special class. You could even do a static call like PointScreen.render(...) Pretty ? No, but it works well. In Libgdx / Lwjgl you can just call gl calls from where-ever anyway Cero - that works for simple games with three game states and small amounts of code per state. As each state grows, and as your game grows (i.e. options state, credits, intro, loading, etc) then your game will soon become a complicated mess of if-else chains and scattered logic.
And i would disagree from experience actually. A game doesnt have that many "screens" unless every little thing is one to you. Our big game has only: 1 2 3 4
| if (gameMode == GAMEMODE.INGAME) runNormal(); else if (isMenuGameMode()) runMenu(); else if (gameMode == GAMEMODE.GAMEOVER) runGameOver(); else if (isTitleScreenMode()) runTitleScreen(); |
every run method does computing/updating, input checks and rendering appropriate to the current state But I'm properly in the minority thinking that a couple of thousand lines per file is ok.
|
|
|
|
Nate
|
 |
«
Reply #13 - Posted
2012-11-20 05:04:12 » |
|
Keep in mind that the total number of lines of code for both Game and Screen combined are < 100 lines. You can copy/paste and go to town with customizations, or write your own. They are pretty much the minimum needed for switching between screens. Honestly in my projects I have used a customized version of them.
I have secret plans for a real screen system for libgdx. While it will be useful for switching actual game screens and logic, the real benefit is for utility. I think it will lower the bar for new users, making the library much easier to use. If you want a SpriteBatch to draw some images, you extend a SpriteBatchScreen and make use of the provided objects. If you want to use scene2d, you extend StageScreen and make use of the stage that is all set up for you. It doesn't seem like much, but this removes a lot of very common boilerplate which simplifies example code and is less daunting for new users.
Another benefit to a real screen framework is AssetManager integration. libgdx's AssetManager handles loading assets (images, sounds, etc) in a separate thread from the GL thread. If a screen describes the assets it uses, then the screen framework can automatically show an intermediary loading screen. Assets not used by the new screen are unloaded from memory, assets used in the new screen but not the old screen are loaded, and assets used by both screens are kept in memory. That last part is really neat, as you can develop screens separately, simply describe the assets used for each, and loading of assets between screens is handled efficiently.
Transitions are also related. For OpenGL ES 2, an FBO can go pretty far. For GL1 or more complex transitions, they usually need to be hand written. The framework should facilitate the LCD as well as provide easy to reuse common functionality.
|
|
|
|
ShuKen
|
 |
«
Reply #14 - Posted
2012-11-20 20:04:58 » |
|
Thanks guys for the help. Im doing some test with Game and Screen classes and works pretty well. but I found something. Im using: 1 2
| if(Gdx.input.isKeyPressed(Keys.ENTER)) game.setScreen(game.gamePlay); |
To switch from mainmenu screen to gameplay screen, and doing the same to switch from gameplay to mainmenu with: 1 2
| if(Gdx.input.isKeyPressed(Keys.ENTER)) game.setScreen(game.mainMenu); |
So...Im in mainmenu and press (and release) ENTER and, of course, goes to gameplay and then automatically goes back to mainmenu. Is there a way to clean up the Input after the ENTER key? Something like: 1 2 3 4 5
| if(Gdx.input.isKeyPressed(Keys.ENTER)){ Gdx.input.clean(); game.setScreen(game.gamePlay); } |
|
|
|
|
sproingie
|
 |
«
Reply #15 - Posted
2012-11-20 20:43:20 » |
|
You need to "edge trigger" events like that, not "level trigger" which is what you have now. Keep a set of keys that are down, update it on keydown/keyup. Only trigger your logic when the key is down and it wasn't in the set before.
|
|
|
|
Nate
|
 |
«
Reply #16 - Posted
2012-11-20 20:44:53 » |
|
An easy way is to use the method keyDown instead of polling.
|
|
|
|
sproingie
|
 |
«
Reply #17 - Posted
2012-11-20 21:00:17 » |
|
Ah of course, libgdx does all this for you. I came from LWJGL where polling is all you get, so I suspect perhaps the questioner did too ... or not, since that's often one of the first things anyone using LWJGL ends up writing
|
|
|
|
Cero
|
 |
«
Reply #18 - Posted
2012-11-20 23:42:36 » |
|
An easy way is to use the method keyDown instead of polling.
The methods are very good actually, since Libgdx I use the Listeners, with Slick I didn't ...
|
|
|
|
ReBirth
|
 |
«
Reply #19 - Posted
2012-11-21 07:27:51 » |
|
I always implement InputProcessor, then extend it for special Screen case.
|
|
|
|
|