Author Topic: game loops and information screens  (Read 8328 times)

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
game loops and information screens
« on: February 27, 2013, 04:35:50 PM »
Another newbie question here. I've been able to import a sprite-font, get a basic @ moving around the screen in response to key presses or automatic animation. 

As a complete newbie to game programming, I'm now trying to figure out the fine points of the game loop.  I'm using Python with the pyglet library and it implements its own game loop which you can attach event handlers to.  What I'm now scratching my head over is how to architect the program so that it can have alternate "screens" like an inventory screen.  When you guys do this in your games, do you implement each screen with its own game loop, and switch between them somehow?  Or do you use one game loop with "if/then" statements to correctly implement events/graphics for whichever screen is active?  Or is there some other way that's more sensible than either of these?  I don't need python-specific answers, just looking for the general idea.

ExtremoPenguin

  • Newcomer
  • Posts: 19
  • Karma: +0/-0
    • View Profile
    • Entropy Interactive
Re: game loops and information screens
« Reply #1 on: February 27, 2013, 05:16:27 PM »
There are a lot of ways to do this. What you are making is a finite state machine. A search of the web should give you lots of results (just search "game finite state machine"). The way I would do it is by making a "game state" class then sub-classing that for each of my different screens. The main game loop keeps a reference to the current state and calls methods such as "update" and "draw" on that state. Inside each game state, you have all of your logic specific to that screen including when to switch to a different game state.

Omnomnom

  • Rogueliker
  • ***
  • Posts: 79
  • Karma: +0/-0
    • View Profile
    • Email
Re: game loops and information screens
« Reply #2 on: February 27, 2013, 09:11:55 PM »
I don't know if there's a more sensible way but I use the "one game loop with "if/then" statements to correctly implement events/graphics for whichever screen is active"

Only one input-accepting UI screen (inventory, character, item details) can be visible at once.

In the drawing part of the loop I first draw the map. If any UI screen is visible I draw that over the map.

In the keyboard event handling part of the loop, I check to see if a UI screen is visible. If one is then I redirect all keyboard events to the handler for that screen.

So each screen has it's own handler. Pretty much all handlers handle the escape key which makes the UI screen invisible and so keyboard control reverts back to the main handler.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: game loops and information screens
« Reply #3 on: February 27, 2013, 09:17:26 PM »
I have a feeling that the finite state machine idea could be the way to go... I like that it reminds me of Markov chains from probability theory and simulation.  But to really do it right I need to figure out how to do object-oriented programming in this language... it's been years since I did anything like that.  I've got about 10 more chapters of "Learning Python" before I get to that section!

ExtremoPenguin

  • Newcomer
  • Posts: 19
  • Karma: +0/-0
    • View Profile
    • Entropy Interactive
Re: game loops and information screens
« Reply #4 on: February 27, 2013, 11:14:38 PM »
You don't need to use objects, the solution is just a bit more elegant that way. You can use an integer to represent which state you are in, then, as Omnomnom said, you can use an if or switch statement to call the appropriate logic and drawing functions for that state.

george

  • Rogueliker
  • ***
  • Posts: 201
  • Karma: +1/-1
    • View Profile
    • Email
Re: game loops and information screens
« Reply #5 on: February 28, 2013, 12:01:53 AM »
Indeed, with Python you definitely don't need to use classes or anything like that, and it might even be easier at first if you ignore them.

When you're starting out feel free to just define global variables (datastructures like dictionaries, lists, strings, what have you) and use those freely in functions throughout your program.

You'll see people rail against this but it probably won't matter for the size of programs you're writing at this stage, and it'll definitely be easier to focus on the basics -- data, and functions. Might even be beneficial later on too. I think a lot of people go overboard on OO.
« Last Edit: February 28, 2013, 12:05:06 AM by george »

guest509

  • Guest
Re: game loops and information screens
« Reply #6 on: February 28, 2013, 05:23:09 AM »
  Agree with George. Totally.

wire_hall_medic

  • Rogueliker
  • ***
  • Posts: 160
  • Karma: +0/-0
    • View Profile
Re: game loops and information screens
« Reply #7 on: February 28, 2013, 05:36:48 AM »
I like to compartmentalize, so that when I go bug hunting I know where to look.  What I do is each panel handles it's own painting and key events, and the main graphics loop only calls the active panel.

The engine class is global, so any part of the program can make stuff happen.  For example the inventory panel can tell the engine to put an item at the player's feet when he drops something from his backpack.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: game loops and information screens
« Reply #8 on: February 28, 2013, 05:42:33 AM »
Thanks all.  I think I can figure the OO thing out... part of the reason for this project is as a way to learn Python and re-learn OO programming.  But I will probably do some kludges with global variables too.  I noticed the 7DRL competition is coming up in a couple weeks, so I'm going to try and learn some things that I can re-use then.  Completing a tiny game will be a big help in motivating me to keep going, I think.

Omnomnom

  • Rogueliker
  • ***
  • Posts: 79
  • Karma: +0/-0
    • View Profile
    • Email
Re: game loops and information screens
« Reply #9 on: February 28, 2013, 01:08:21 PM »
I like to compartmentalize, so that when I go bug hunting I know where to look.  What I do is each panel handles it's own painting and key events, and the main graphics loop only calls the active panel.

The engine class is global, so any part of the program can make stuff happen.  For example the inventory panel can tell the engine to put an item at the player's feet when he drops something from his backpack.

Exactly the same. Engine global variable feels dirty everytime I use it but it works. Avoids passing numerous parameters everywhere.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: game loops and information screens
« Reply #10 on: March 01, 2013, 08:38:50 PM »
The solution I'm going with, if anybody else is interested or searches for this problem:

Pyglet allows me to "push" and "pop" sets of event handlers to the window as a package (not one by one) so I figured out a really easy way to make it work:  one class for each game mode contains the event handlers I need in that mode.  I transition from one mode to the other by doing:
window.pop_handlers()  # remove the current handlers
window.push_handlers(NewModeClass())  # add new handlers

The "return True" line in each handler ends the handling of an event.  By omitting it, events can fall down to the next handler on the stack.  So you could have a game mode "on top" of another game mode but not disabling it.  In a city-builder game for example you might want to add a new keyboard event handler when the "build road" option is clicked, but without disabling the screen draw and map-scrolling keys in the main game mode.

A tiny demo.  All this does is print a red "@" on the screen and accept key presses until ESC is pressed, then switch to "blue mode" with a blue "@" which also listens for an ESC and switches back to red mode.
Code: [Select]
import pyglet
from pyglet.window import key
pyglet.resource.path = ['resources','resources/tiles']
import modules.tiles # imports the ascii tileset and provides functions for generating colored tiles and turning text strings into tile/sprite sequences

window = pyglet.window.Window()

red_atsign = pyglet.sprite.Sprite(modules.tiles.generate_colored_tile(ord("@"),fg_color=b'\xff\x00\x00'),x=window.width//2, y=window.height//2)
blue_atsign = pyglet.sprite.Sprite(modules.tiles.generate_colored_tile(ord("@"),fg_color=b'\x00\x00\xff'),x=window.width//2, y=window.height//2)

class BlueGame(object):
    def on_key_press(self,symbol,modifiers):
        if(symbol==key.ESCAPE):
            print("ESC pressed in BLUE mode")
            window.pop_handlers()
            window.push_handlers(RedGame())
        else: print('Key pressed in BLUE mode')
        return True
    def on_draw(self):
        window.clear()
        blue_atsign.draw()
        return True

class RedGame(object):
    def on_key_press(self,symbol,modifiers):
        if(symbol==key.ESCAPE):
            print("ESC pressed in RED mode")
            window.pop_handlers()
            window.push_handlers(BlueGame())
        else: print('Key pressed in RED mode')
        return True
    def on_draw(self):
        window.clear()
        red_atsign.draw()
        return True

window.push_handlers(RedGame())
pyglet.app.run()
This code requires pyglet and my "tiles" module, which generates the colored @ sprites.
« Last Edit: March 01, 2013, 08:42:39 PM by joeclark77 »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: game loops and information screens
« Reply #11 on: March 02, 2013, 02:32:11 PM »
If the game is strictly turn based you don't need a regular event loop. As an example the only event loop in Teemu is the one in get key routine and it's required only, because SDL has a event loop system. In other words the event loop is isolated to get key, it's not the same thing as game loop which controls the actions of gameplay.