pingus-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Document, v.02


From: John August
Subject: Document, v.02
Date: Thu, 8 Apr 2004 16:40:57 +1000
User-agent: Mutt/1.0.1i

People,

Here's v.02 of the document. I've still included some detail of the
Clan Lib interface, as it did become important when I was investigating
timing issues.

Ah, it would have been great to have a document like this when I was
first picking through the code !

Yes, it could do with a good deal of improvement, but this certainly
seems true to me.

John August.

--

Pingus, a code description / narrative , V.02

# Getting information

Quite apart from gdb, strace (and perhaps, DRT), a good way to get an idea
of what pingus does when it starts is to use the command line :

./pingus --debug actions 

# Introduction

We categorise pingus operations into several stages :

1. Setting up the screen from the description files. [some coverage]

2. Having the scenario run, involving :

   -generating pingus [some]
   -developing those pingus [some]
   -noting whether they have died or exited, finishing the level [nothing]

3. User interaction

   -cosmetic interaction (action boxes highlighting when the mouse is
    over them; the target pingu highlighting with a box around it) [none]
   -music (which is non interactive) [none]     
   -cursor state (being set to one of the left actions) [a little]
   -setting a characteristic to a pingu [some]
   -game level operations : pause, exit [none]
   -setting up the buttons and using ClanLib [some]

# Directory Structure 

The following exists below src :

.:
./actions:
./caimagemanipulation:
./colliders:
./editor:
./editorobjs:
./gui:
./input:
./input/axes:
./input/buttons:
./input/pointers:
./input/scrollers:
./movers:
./particles:
./sound:
./win32:
./worldmap:
./worldobjs:
./worldobjs/entrances:
./worldobjsdata:

Here's some more detail :

.:

The main code

./actions:

The files here are called for each state a pingu are in, as part of the
periodic update

./caimagemanipulation:

?

./colliders:

?

./editor:

The editor ?

./editorobjs:

?

./gui:

Elements of the screen setup are contained here

./input:
./input/axes:
./input/buttons:
./input/pointers:
./input/scrollers:

These directories setup the user inputs

./movers:

?

./particles:

?

./sound:

Sound - presumably includes Music ?

./win32:

Windows compatibility

./worldmap:

These are files representing the island, which coordinates the 
introductory levels

./worldobjs:
./worldobjs/entrances:
./worldobjsdata:

Background objects. I don't understand what the difference between
./worldobjs: and ./worldobjsdata: is.

./data is one level below src, and contains :

./controller
./data
./demos
./images
./levels
./music
./prefabs
./sounds
./themes
./worldmaps

And are not covered in detail at this point.

./levels contains :

./multiplayer:
./playable:
./test:
./tutorial:
./volcano:
./wip:

Which contain the xml files for the different levels. It would seem the
most interesting directory is 'playable'.

# Update

Every active object in the background, and every pingu, has a method 
Update(). This is called by the main program for every such object in
order to advance the game.

# Setting up the screen

In order to set up a screen, you have the background, the buttons on the
left, the buttons at the bottom (fast, pause, exit) and the pingu generator.

pingus_main.cxx is where the interesting action starts.  The
coordinating routine is PingusMain::start_game () ;

First there is initial setup and registration.  After identifying the
level file to load, pingus instantiates the class :

new StartScreen(PLFResMgr::load_plf_from_filename(levelfile)),
                 true);

Which sets up the screen with the given "levelfile", an xml description of
that level. (There are also .plf files, pingus level files, which might be
used in 0.6.1)

This load_plf_from_filename provides a pointer to that file, and deals with
caching.

The class GUIScreen is a Screen with a GUI manager. StartScreen is an 
object of the GUIScreen type, and an instance is generated by the code
above.

start_screen.cxx contains a description of the StartScreen object, the
corresponding method to the code above [I think] is repeated below :

StartScreen::StartScreen(PLFHandle arg_plf)
  : plf(arg_plf)
{
  StartScreenComponent* comp = new StartScreenComponent(plf);
  gui_manager->add(comp);
  gui_manager->add(new StartScreenOkButton(this));
  gui_manager->add(new StartScreenAbortButton(this));
}

arg_plf is equal to plf, this is set in
PingusLevelDesc::PingusLevelDesc, this is a naming convention to
seperate an argument variable from a member variable

Note that calls are made to StartScreenComponent, StartScreenOkButton
and StartScreenAbortButton.

StartScreenComponent is a GUI component that represents the background of
the StartScreen; it would seem that this is a string of references from
the setup file which coordinates what finer-detail elements appear on 
the StartScreenComponent.

The relevant StartScreenComponent method appears to be :

StartScreenComponent::StartScreenComponent(PLFHandle p)
  : plf(p)
{
  background = Sprite("menu/startscreenbg", "core");
  background.set_align_center();
  time_str = GameTime::ticks_to_realtime_string(plf->get_time());
}

The PLFHandle is a pointer to a PLF object, and holds all the
information needed for a level, gameobjects, time, name, etc.
Startscreen uses it to present that information and passes it further
down to the PingusGameSession, which then starts the level.

# WorldObjs

Files in the worldobs directory are called as part of the process of
parsing the level description file.

Worldobjs includes active objects, such as a conveyor belt and spike.

# Parsing the xml file 

[where this section fits in, and where it is called from, is not known ]

PLF::create() is a dispatch function to allow the use of different level
formats, not needed at the moment, but was [?] needed at the point where
pingus switched from .plf to .xml.

PLF::create() calls XMLPLF:XMLPLF, which then calls XMLPLF::parse_file()
[xml_plf.cxx], which reads a xml level file and fills a PLF object with
the given information.

This information is used to do things like load up the action
bar from the <action-list> segment of the xml description.

# Pingus state

As detailed in the file pingu.hxx, pingus have several states. One is the
main action of that pingu, called when it is updated.

You also have some variables which act if the pingu is set with a property.
Eg fall_action is the action if the pingu falls. Normally, this is set to
zero, and no change in action status takes place. However, if it is set
to floater, when the faller action notes the speed has built up, because
the fall_action is set, it changes to a floater.

Similarly for wall_action : this starts off unset, and when a pingu hits
a wall, it only means it turns around. But, if this value is set the 
pingu can start climbing the wall.

The change of pingu state is initated through a call to
Pingu::request_set_action (PinguAction* act) in pingu.cxx. "act" has
both a target state and a context. For "stored" states like floater
and climber, the context is FALL_TRIGGERED or WALL_TRIGGERED, and the
appropriate value is set.

However, many action changes do not represent a stored state, rather they
are initiated just at the correct moment (eg diggers, miners, jumpers).
These target states have the INSTANT context, and the main action of the
pingu is changed.

[At this stage, the link of how a mouse click in the right location changes
the current "set state" through the toolbar on the left, and how the mouse
click is sent to the correct pingu and request_set_action is called, is
not described ]

# Pingus development and actions

The Class PinguHolder has a list of all pingus, including those dead and
alive.  Code in worldobjs/entrance.cxx, which runs the entrance, calls
Pingu* pingu = world->get_pingus()->create_pingu(data->pos,
data->owner_id); from the routine Entrance::create_pingu () in order to
create pingus.

The method Entrance::create_pingu () is itself called from
Entrance::update () when a pingu is ready.

Each pingu is in one of several states (blocker, walker, climber) etc, as
described above, and the associated code for each state is contained in
the "actions" directory.

When the Update method for a given pingu is called, it calls the Update
method in the corresponding action file.

We consider the Walker case as an example.  A comment for the Walker::Update()
code, contained in actions/walker.cxx, is repeated below :

/* How should this code work?

  1) Check that the Pingu stands still on ground, if not turn it into
  a faller or drown. The reason we do so, is that we catch situations
  where a digger or a similar action removed the ground under the
  walker.

  2) If pingu is still on ground, we can preprare the next step

  3) Check if up-hill or down-hill is required
  */

In order to perform the above activity, the code checks what is present
one pixel to five pixels below the pingu; if not solid, it calls
pingu->set_action(Actions::Faller); and becomes a faller.

If a step is made, the code calls pingu->set_pos; an example when the x and y
locations are set is : pingu->set_pos(pingu->get_x() + pingu->direction,
pingu->get_y() - possible_y_step);

Each pingu action has a draw method, which draws the particular case of
pingu - walking left, walking right, and also incorporates any additions
to the graphic.

Now considering the "faller" code (actions/faller.cxx) - the pingu falls
without incident until it has reaches a reached a critical velocity.
Then, request_fall_action is called. This turns the faller into a floater,
or lets the faller continue falling. (this means the call is not made when the
pingu "falls" just a litte when it goes over a step.)

Regardless, when the faller has ground beneath it, it turns back into a
walker or dies because it impacts with too great a velocity.

# User inputs

[The link between these inputs and the way that clicks change states in
the program is not yet known]

In gui/screen_manager.cxx, ScreenManager::display () calls 
input_controller = new Input::Controller(controller_file); in order to
instantiate a controller.

The routine above calls Countroller::Controller (line 48) in
input/controller.cxx.

This routine checks through the xml file, and generates buttons based on
its content. Line 69 starts a while loop, which checks each of the cases
and calls PointerFactory, ScrollerFactory or ButtonFactory as appropriate.

But here we concentrate on ButtonFactory; for instance, line 108 creates
an "action-down", presumably an action on a click.

input/button_factory.cxx contains the routine Button* ButtonFactory::create,
called by line 108 of the previous routine. As we're focusing on a mouse
button, we see that line 51 calls mouse_button.

this is line 99 of the same file, Button* ButtonFactory::mouse_button ;
this routine calls MouseButton(button).

This is contained in input/buttons/mouse_button.cxx . We see from line 35
that it attaches CL_Mouse::sig_button_press and CL_Mouse::sig_button_release.

Importantly, this is the connection between Pingus and the ClanLib driver
for the mouse buttons.

The general ClanLib operation runs by polling, and it is necessary to call
the ClanLib update method.

This is found in, for example gui/screen_manager.cxx :

      // Let ClanLib fetch events
      CL_System::keep_alive ();

There is a time delay in dealing with events, as the events are only updated
as rapidly as this is called.

For some reason, the graphics updates without any noticeable time delay -
eg ticks appear on the button boxes, or the button boxes are highlighted.

# Clan Lib Interface, and X Window contact

While it is possible to edit Pingus without knowledge of the details of
the interface, it can be interesting to have some idea of where the code
"makes contact" with the X Window interface.  This section is mostly
optional, but such knowledge may be important when timing issues are
addressed (as compared to general hacking).

As noted, Pingus attaches CL_Mouse::sig_button_press and
CL_Mouse::sig_button_release; this is the connection between Pingus and
the ClanLib driver for the mouse buttons.

It is in the (ClanLib) file Display/Input/X11/mouse_x11.cpp that the routine
make contact with the underlying XWindow.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]