Jump to content
XCOMUFO & Xenocide

How Does The Game’s Basic Framework Work?


dteviot

Recommended Posts

I’ve been told that we’re using a Model-View-Controller pattern.

The model part is kind of obvious. That’s the collection of “things” that represent the game state. E.g. craft, bases, items, soldiers, etc.

However, the view and controller is not so clear.

For example, the Earthscreen is a view, but what about the options dialog? Is that a view, or part of a controller?

Or the Xnet I tried creating, is that another View, or is just part of the Earthscreen view?

 

So, the questions I’m hoping to get a bit more information about go something like:

1. What exactly is a View? (For the purposes of Xenocide)

2. How do we decide what is a view?

3. Where is our controller?

4. How is the controller connected to views?

5. What do we need to do to create a view?

6. How do we switch between views?

7. How does Python and the game's main loop fit into all this? E.g why do dialogs need to have their own stackless “threads”.

 

On a related topic, I’m currently reading through this, which is somewhat helpful in showing how Ogre, OIS and CEGUI fit together.

http://www.ogre3d.org/wiki/index.php/Practical_Application

Edited by dteviot
Link to comment
Share on other sites

Some more thought on the MVC.

 

Thinking about the model some more:

1. “GameState” is the root node for the state.

2. “GameState” can (and probably should) be broken down into smaller sets: e.g. PlanetState, Battlestate, Options.

3. PlanetState and Battlestate will each need their own GameTime.

4. Note that Model doesn’t contain just state (i.e. the information we need to save/load to file) it also needs to contain behaviour. (So possibly State in these names should be changed to Model.)

5. PlanetState and Battlestate should have update() methods. It’s inside these methods that we do the tick slicing.

 

Thinking about Views.

1. Obviously the Planetscreen is a view.

2. Similarly, the Battlescape and the Basescape will also be views.

3. X-Net should probably be a view as well.

4. As a possible rule of thumb, we should probably make all views full screen, and (where necessary) use dialogs to control the view. E.g. In the previous build, the “statistics dialog” popped up over the planetscreen. It should really be a full screen on itself. (As should the buy/sell items and research.) – We want to keep the GUI as simple as possible, as I believe this will simplify the control logic for it.

5. So, under this model the views will call into the model to change it. E.g. If the player chooses to buy an item, the view knows to go to the model and call the appropriate functions. (e.g. Check for sufficient funds, debit user’s balance, create an item, and add it to a base’s inventory.)

6. As regards the model posting any events to the current “view”. I don’t think this is going to be necessary. For nearly all views, “game time” isn’t moving. So the only changes that can happen in the model are in response to calls the view makes. So the view knows if it needs to refresh itself after making the calls. Let’s consider two cases: Adding a facility to a base, and calling the update() function on the planetscreen().

 

Adding Facility to base

1. Screen has a 3D “floorplan” image of the base, showing a 6 x 6 grid with the already constructed facilities positioned, and a set of on the Right hand side.

2. User clicks on the “add facility” button.

3. A dialog appears, giving a list of facilites that can be built. (Dialog also has a cancel button.)

4. User clicks on a facility.

5. Dialog disappears. User moves cursor over the grid. As cursor moves over each empty cell, the cell is highlighted. (Green if facility can go there, red if not.)

6. Cursor is positioned over a green cell, and left mouse button pressed.

7. View then goes to model, adds facility to base and debits available funds.

8. Base view gains “under construction” facility at that point and funds displayed on screen are updated.

 

As we’re redrawing the 3D base image with each cursor movement, there is no need to get any update messages from the model. View will be constantly reading the base for the facilities. The cost of reading the list from the model is insignificant compared to the cost of rendering the base. Updating the funds shown on the view each redraw is also negligible. So as soon as the facility is purchased, when the view is redrawn the new facility will be present, and the reduced user’s funds will be shown.

 

N.B. I have no idea how the mouse movements are being passed into the view, nor how the “select facility” dialog is being driven.

 

Calling PlanetModel.update from planetscreen

OK, so view calls the planet’s update() dialog to tell the model to advance it’s state by X game minutes. (Assume this is 60 minutes.)

During this period of time a number of events might happen. Let’s assume during this time 3 things happen.

1. Game time has advanced.

2. A human craft moves 1000km

3. A previously undetected UFO moves into the radar range of a base.

4. A build project in a workshop finishes.

 

1 is trivial, as with funds in the basescreen, fetching and drawing game time (and funds) is negligible. So we just do that each frame.

 

2 is also trivial. The planetscreen is redrawn each frame, and the view will fetch the position of each craft from the model before rendering the craft to the globe. There is no need for any sort of notification.

 

3 is more complicated. Showing the UFO on the globe would be handled in the same way as the craft. Each frame we fetch all the “spotted” UFOs and their positions from the model and draw them in the correct position. However, we will probably also want to pop up some sort of message box to tell the player that a new UFO has been spotted. It occurs to me that the simplest solution is we have a “user notification queue” which we post this event to.

The simplest model we have a list of strings, which the view checks the last step of its “render” operation. If there are any events, the view stops game time and shows each string in turn in a message box. The user can then issue any appropriate orders and restart gametime.

 

4 is similar to 3, model puts a notification in the list, and carries on.

 

Obviously, instead of a simple “list of strings” we could add additional information to the list and have the view itself change. E.g. we could add additional information to say “this is a research event”, and offer the user the option of going to the research screen on the message box.

 

Also, we may want to add the “popup the message box” and “switch views” logic to the controller, rather than have that in the view.

 

Planetscreen – passing events back to view.

 

 

Other

I’m not sure how CEGUI and IOS hook into the system to work, and how CEGUI provides dialogs on top of “screens”.

 

 

 

As regards the Controller part, I had previously stated the core loop looks like this:

while(!finished)
{
model.update(real time that has passed since last time through the loop);
view.render(real time that has passed since last time through the loop);
}

 

However, on further reflection, I think that the update call really needs to go to the view(), then the view can decide the correct model update calls to make. E.g. If the planetscreen view is showing, it knows to call planetstate.update(). Or, if XNet was showing, then there is no need to update anything in model() – at least not in response to time. Although we might want to update the image that is rendered. E.g. allow the image to rotate slowly.

 

So, what I’m thinking is that the main loop needs to know which view is the “current view”, and it dispatches the calls to this “current view”. So main loop looks more like:

while(!finished)
{
View& view = ViewManager.getCurrent();
view.update(real time that has passed since last time through the loop);
view.render(real time that has passed since last time through the loop);
}

Link to comment
Share on other sites

I think it's a jolly good foundation for structure.

 

 

>>2. “GameState” can (and probably should) be broken down into smaller sets: e.g. PlanetState, Battlestate, Options.

 

I think it absolutely should be separated. First of all, Battlestate is a wholy different game on the inside than Planetstate; they definitely should be separated. And Options are not related to game state in any way, it's more Enginestate, so to say. :)

Link to comment
Share on other sites

Additional thoughts about my previous post:

 

The view and controller can be implemented as a state machine, where the view is the state, and the controller is the “engine”. N.B. a View is not necessarily a screen.

Thus, on the planetscreen, clicking the “XNet” button should result in a “go to the XNet screen” event being sent to the controller.

Modelling the controller/view as a state machine is not new, the previous framework attempted this. But the Boost::StateMachine was used, and it had implementation issues.

The previous suggestion about how the model sends events to the controller is insufficient. Two cases that I did not consider are what happens if we cross an end of the month, or a human craft gets into attack range of a UFO. In both cases controller needs to leave the planetscreen, and move to a different one. Either the end of month screen, or the aeroscape screen.

I believe that the state machine model will still work with these cases. But, we have a complication that the state machine needs to have an event queue, so that it can handle the case of multiple events being generated by a planetModel.update() call.

This is a bit different to the usual state machine, as normally a they are in one state, they receive a single event, and migrate to a second state. Then they receive another event, and move to a third state and so on.

My plan for dealing with this is as follows:

  1. Assume the planetsceen has placed an “aeroscape battle” and an “end of month” event in the queue.
  2. The controller gets the “aeroscape battle” from the queue, closes the planetscreen and opens the aeroscape.
  3. While in the aeroscape, the user will press various buttons. (which potentially bring up dialogs.) At the end of the areoscape, the user closes the screen.
  4. At this point, the controller returns to the planetscreen.
  5. And the controller checks the “update() events queue” to see if there’s anything there.
  6. It finds the “end of month” event, so switches to the “end of month” screen.
  7. User closes this screen
  8. Controller goes back to planetscreen, and checks the queue again.
  9. Nothing there, so planetscreen resumes.
  10. This means that we need an “update events queue” that is separate from the other “queue” that is used pass “state transition events” to the controller. Either that, or we need a way to tag the events in the queue, and have the controller scan the queue in priorty order. However, as I think it’s only going to be update() calls that will generate multiple events, it’s probably simpler if the queue only handles those sorts of events.

Some other things to note, while the view calls the model’s update() function with a period of time, the model DOES NOT HAVE TO UPDATE the model’s state by that much game time. E.g. Assume the view tells the model to update by a day. (Actually the view calls the model saying “update the model with the passing of X real time seconds.” The model converts the real time into a matching period of game time, and uses that.)

 

If the model determines that a UFO will be attacked 2 minutes in, then the model only needs to update its state by 2 minutes and then return. However, EVERYTHING in the model must be updated by the same amount. E.g. even if the first thing done in the model’s update was testing for UFO attacks, we must update research, construction, other craft’s positions etc. by 2 minutes before returning.

 

Where to from here? Well, assuming we’re all in agreement, I think the next step is to draw up the state chart for the views. (Which I believe someone started on a long time ago.) As I think we want a UI that resembles X-COM, if someone could tell me where I can find a set of screenshots showing all the screens from X-COM, I’m willing to try and put together the state chart. (Unfortunately, I don’t have a copy of X-COM.)

Edited by dteviot
Link to comment
Share on other sites

I am not shure, but isnt the Aeroscape a dialog? I am not even shure if time is really paused during aircombat. I will try to find out. At least it should be possible to have multiple aircombat dialogs on screen.

 

Where to from here? Well, assuming we’re all in agreement, I think the next step is to draw up the state chart for the views. (Which I believe someone started on a long time ago.) As I think we want a UI that resembles X-COM, if someone could tell me where I can find a set of screenshots showing all the screens from X-COM, I’m willing to try and put together the state chart. (Unfortunately, I don’t have a copy of X-COM.)

I know that you can find many of the screens while searching google or on Fan-Sites but i try to get all of them together tonight, and put them online. (And wasting hours of precious sleep while playing the game ;-))

 

greets

Lars

Link to comment
Share on other sites

I am not sure, but isnt the Aeroscape a dialog? I am not even shure if time is really paused during aircombat. I will try to find out. At least it should be possible to have multiple aircombat dialogs on screen.

Yes, it is a dialog. However, I believe that it has its unusual behaviour so that you can get several interceptors to attack a UFO simultaneously. Basic steps go something like, when first craft reaches UFO, you minimize the dialog (which means "follow that UFO") you then wait until the next plane reaches attack range. Repeat until you have up to four planes ready to attack. You then open one of the dialogs and start the attack.

 

I think we can dispense with the dialogs, if we provide an "escort" or "wingman" mission for a craft. So, to have multiple human craft intercept a UFO, process would be

1) assign one craft to intercept UFO.

2) assign other craft as wingmen to the interceptor.

3) the wingmen will head towards/follow the interceptor

4) the interceptor will head towards the UFO, then follow the UFO.

5) When all wingmen arrive, all the craft attack the UFO. This would be the point where the aeroscape opens.

 

Where to from here? Well, assuming we’re all in agreement, I think the next step is to draw up the state chart for the views. (Which I believe someone started on a long time ago.) As I think we want a UI that resembles X-COM, if someone could tell me where I can find a set of screenshots showing all the screens from X-COM, I’m willing to try and put together the state chart. (Unfortunately, I don’t have a copy of X-COM.)

I know that you can find many of the screens while searching google or on Fan-Sites but i try to get all of them together tonight, and put them online. (And wasting hours of precious sleep while playing the game ;-))

 

greets

Lars

Thanks, bit of a funny story here. I did have a copy of X-Com (and TFTD & Appoc) but I loaned them to my brother's girlfriend (along with a number of other games) and then they broke up. Do you have any idea how hard it is to get your stuff back in that situation? Especially when she lives in the USA, and you live in New Zealand?

Link to comment
Share on other sites

  • 4 weeks later...

OK, in an earlier post I suggested the main loop should look something like this:

 

while(!finished)
{
Screen& screen = ScreenManager.getCurrent();
screen.update(real time that has passed since last time through the loop);
screen.render(real time that has passed since last time through the loop);
}

 

However, this model is too simple.

Firstly, there’s no “process user’s input” step. Logically, this should to be done by the screen (because what the inputs do depends on the current screen), and it should be done before the screen updates. (As the user’s commands may change what the update should do.)

 

while(!finished)
{
Screen& screen = ScreenManager.getCurrent();
screen.handleUserInput(input);
screen.update(real time that has passed since last time through the loop);
screen.render(real time that has passed since last time through the loop);
}

 

The next issue is how do we swap screens? We need to swap screens because either

  1. The user has asked for a screen change, or
  2. An event has occurred during the update that requires a screen change. (e.g. Craft reaches a mission site.)

If the user asked for the change, things are a bit complicated because we’re IN the screen.handleUserInput () function, and we want to destroy the screen we’re currently in and replace it with another. A possible solution is:

 

The ScreenManager class has a function setScreen(screen, screenState), which screen::update() calls. However, the call doesn’t replace the screen, instead it records a “request to change”. Then, in the main loop, when handleUserInput() returns, we replace the screen.

 

 

while(!finished)
{
Screen* screen = ScreenManager.getCurrent();
screen->handleUserInput(input);
screen = ScreenManager.replaceScreen();
screen->update(real time that has passed since last time through the loop);
screen->render(real time that has passed since last time through the loop);
}

class ScreenManager
{
// member vars
Screen* currentScreen;
Screen* nextScreen;
ScreenState* state

// member functions
setScreen(_screen, _screenState) 
   { 
		nextScreen = _screen; 
		state = _screenState; 
	}
Screen* replaceScreen()
{
	if (nextScreen != null)
	{
		currentScreen = nextScreen;
		currentScreen.setState(state);	
		nextScreen = null;
	}
	return currentScreen;
}
}

 

The reason for the screenState object is that some screens may need to configure themselves. E.g. The base information screen needs to know what base to show information for. X-Net needs to know which item it should be displaying. (Geoscape and Battlescape probably need to store the viewing position.)

 

Therefore, we have a ScreenState class that holds this information, with derived classes where necessary for holding extra information.

Some additional thoughts:

  1. As we go through some of the screens in a “stack” like fashion. That is, we open a screen, and then when we’re done with it we return to the previous one, we might want to allow the ScreenManager to handle this “stack”.
  2. Following from above, the screen class should have a getState() function that returns a ScreenState object that can be used to restore a screen’s state when it’s “restored off the stack” .
  3. Note, this is still a state machine design, as the current screen holds the logic for which screen will be shown next. (Even if the IMPLEMENTATION of the “go back to previous screen” is in the ScreenManager, it’s the screen that decides to do it.)
  4. I’ve previously discussed having a “queue” to hold screens to show because of events. As I believe we will do this at the start of each loop, in the getCurrent() call, we need to flush all queued user input when the screen changes.
  5. The above represents my thoughts on how we would ideally do this sort of stuff. With our current assemblage of stackless python, IOS, ogre, CEGUI & c++, I’m really not sure how it all connects.

Edited by dteviot
Link to comment
Share on other sites

while(!finished)
{
Screen* screen = ScreenManager.getCurrent();
screen->handleUserInput(input);
screen = ScreenManager.replaceScreen();
screen->update(real time that has passed since last time through the loop);
screen->render(real time that has passed since last time through the loop);
}

class ScreenManager
{
// member vars
Screen currentScreen;
Screen nextScreen;
ScreenState state

// member functions
setScreen(_screen, _screenState) { nextScreen = _screen; state = _screenState; }
Screen* replaceScreen()
{
	if (newScreen != null)
	{
		currentScreen = nextScreen;
		currentScreen.setState(state);	
		nextScreen = null;
	}
	return currentScreen;
}
}

 

The reason for the screenState object is that some screens may need to configure themselves. E.g. The base information screen needs to know what base to show information for. X-Net needs to know which item it should be displaying. (Geoscape and Battlescape probably need to store the viewing position.)

 

Therefore, we have a ScreenState class that holds this information, with derived classes where necessary for holding extra information.

Some additional thoughts:

  1. As we go through some of the screens in a “stack” like fashion. That is, we open a screen, and then when we’re done with it we return to the previous one, we might want to allow the ScreenManager to handle this “stack”.
  2. Following from above, the screen class should have a getState() function that returns a ScreenState object that can be used to restore a screen’s state when it’s “restored off the stack” .
  3. Note, this is still a state machine design, as the current screen holds the logic for which screen will be shown next. (Even if the IMPLEMENTATION of the “go back to previous screen” is in the ScreenManager, it’s the screen that decides to do it.)
  4. I’ve previously discussed having a “queue” to hold screens to show because of events. As I believe we will do this at the start of each loop, in the getCurrent() call, we need to flush all queued user input when the screen changes.
  5. The above represents my thoughts on how we would ideally do this sort of stuff. With our current assemblage of stackless python, IOS, ogre, CEGUI & c++, I’m really not sure how it all connects.

 

Couple of questions and comments:

  1. I assume that in your last code block you ment to say 'if (nextScreen != Null)' as newScreen isn't defined
     
  2. Is this still being discussed, and/or are we waiting for a prototype or something?
     
  3. Should someone (like myself) work on a framework/interface to use in python (Like a BaseWindow with a show() and destroy() functions)? Once you finalize what is needed we can adjust the BaseClass and all the other screens should fall into place.

EDIT: :doh: I misread dteviot's code. It was doing what I was wanting to do (just in a different fashion than I would have done it :) )

Edited by Pi Masta
Link to comment
Share on other sites

Couple of questions and comments:
  1. I assume that in your last code block you ment to say 'if (nextScreen != Null)' as newScreen isn't defined

Correct. I've amended my post.

 

  1. Is this still being discussed, and/or are we waiting for a prototype or something?
  2. Should someone (like myself) work on a framework/interface to use in python (Like a BaseWindow with a show() and destroy() functions)? Once you finalize what is needed we can adjust the BaseClass and all the other screens should fall into place.

The answer is, this is how I would design the framework.

I'm hoping that Guyver6 or Garo would be kind enough to explain how the framework they've implemented works, how it differs from my proposal (like whats been done, what's been done differently, what still needs to be done.) etc.

Edited by dteviot
Link to comment
Share on other sites

OK, I’ve said this before, but because no one appears to be listening I’m going to say it again.

The main reason progress on Xenocide is so slow is because we have done insufficient upfront planning/design.

Yes, I know we’ve said we will use Extreme Programming, and small incremental stages to develop Xenocide. We still need to have a “big picture plan” to make sure that each incremental stage takes us towards our goal, and not sidetracking us down a blind alley.

 

The summary of what I want to say is that our primary focus must be to complete the design document that Red Knight proposed about 6 weeks ago. http://www.xcomufo.com/forums/index.php?sh...2026989&hl=

 

As I see it, these are the big picture pieces we need before we can really start to make progress.

  1. Agreement on the Gameplay.
  2. Framework for the user interfaces.
  3. Framework for “real time” game components.
  4. The game state data model(s). Namely, the “objects” making up the game state (people, bases, weapons, craft, etc.) Their properties, responsibilities, and relationships. Note, I believe there are at least four groupings of Game state objects: Geoscape, Battlescape, AI & User Settings.

Agreement on the Gameplay

OK, we’ve all said we want to re-create X-COM, but with the more irritating bugs removed. However, this means different things to different people. So, we need to get together and decide which features are changed, and which ones are unchanged. So, we need to detail game play, at least to the level of how the features will look and act a player. (That’s why at the current time I’m trying to document what the User Interface looks like.)

 

Framework for the user interfaces/Real Time

It has already been decided that we’re using IOS for IO, Ogre for 3D graphics, CEGUI for the UI controls. We’re also using Stackless python and C++. And this is where things become unclear. My questions are:

  1. How is stackless python connected up to the screens?
  2. What steps are necessary to create a screen?
  3. Does our framework minimise the amount of work needed to build the screens?
  4. How does the “real time” couple together?
  5. Where do stackless threads fit into the UI? Into the AI? Into Real time?

None if this is helped by the fact that the people who did the stackless work (Garo & Guyver6) won’t answer these questions, and have been almost completely absent for months now. (Yes, they do turn up occasionally, but not for long, and we absences of weeks between appearances.) And as Guyver is team leader, reist and I are reluctant to try changing anything here.

 

Now, I will concede that short of a real time battlescape, the geoscape is probably the most complicated part of Xenocide, so it makes sense to try and figure that out first. However, I also think that we need to regard our current attempt at it with stackless python as a prototype and learning experience. It works (sort of) but it’s an awful mess. And it shows that Stackless python is not as clean a solution as was originally thought.

Link to comment
Share on other sites

About Gameplay Aggreements that it the whole idea of writting things down into the design document, so if you find yourself writting something about how things are going to look in the forum go and put it unedited as it is in the document... I or someone from the CTD will rearrange it to be readable when we notice the changes (use track changes in word).

None if this is helped by the fact that the people who did the stackless work (Garo & Guyver6) won’t answer these questions, and have been almost completely absent for months now. (Yes, they do turn up occasionally, but not for long, and we absences of weeks between appearances.) And as Guyver is team leader, reist and I are reluctant to try changing anything here.
I will put it in very simple terms, go and do the required changes... if you find yourself at odds with some approach, email me with the posibilities, pros and cons and we decide... simple as that.

 

Greetings

Red Knight

Link to comment
Share on other sites

:blablabla: MONSTER POST WARNING :blablabla:

 

 

As I see it, these are the big picture pieces we need before we can really start to make progress.
  1. Agreement on the Gameplay.
  2. Framework for the user interfaces.
  3. Framework for “real time” game components.
  4. The game state data model(s). Namely, the “objects” making up the game state (people, bases, weapons, craft, etc.) Their properties, responsibilities, and relationships. Note, I believe there are at least four groupings of Game state objects: Geoscape, Battlescape, AI & User Settings.

Agreement on the Gameplay

OK, we’ve all said we want to re-create X-COM, but with the more irritating bugs removed. However, this means different things to different people. So, we need to get together and decide which features are changed, and which ones are unchanged. So, we need to detail game play, at least to the level of how the features will look and act a player. (That’s why at the current time I’m trying to document what the User Interface looks like.)

 

I agree with this. I love what went on in the GUI list thread, though I wish it could be condensed down or something (like on a wiki page) because several ideas got amended or changed or re-done and can be a little confusing trying to figure out what people agree on.

 

Framework for the user interfaces/Real Time

It has already been decided that we’re using IOS for IO, Ogre for 3D graphics, CEGUI for the UI controls. We’re also using Stackless python and C++. And this is where things become unclear. My questions are:

Well, I'm going to give a shot at answering this. But I'm still the new guy and this is only what I've seen (and understood) in the code so far.

  • How is stackless python connected up to the screens?

Stackless is actually only connected to some of the screens, namely the dialogs. I'm going to use the interceptdialog.py and options.py as a reference here. Pretty much there is a 'doDialog' function called from outside, which then creates the python dialog class. It then spawns a tasklet using that class's doModal command. The doModal command does all the work like pausing the game, putting data in the widgets (for instance interceptdialog has to grab the interceptors and populate the box). Then you will see this 'modalDialog = ModalDialog(.....'. This grabs from a base 'modaldialog' class in another file and it uses the loaded CEGUI stuff to add as a child screen to the root and handle a bunch of nasty other graphics things. Then there is this:

modalDialog.show()
response = self.channel.receive()
modalDialog.hide()

Should be fairly obvious what goes on (if you know stackless), it shows the dialog, then starts recieving on the channel (which is created in the init of the class) which in turn blocks execution of doModal. Basically we're waiting on the user to do something. We've connected up events that when fired will send on the channel (if appropriate) this will continue execution of the doModal which hides the window and processes the response (if necessary).

  • What steps are necessary to create a screen?
  • Does our framework minimise the amount of work needed to build the screens?

This is in a state of flux right now as reist is in the process of moving most of the heavy work to the C++, mainly the ScreenManager. I'll see if I can gather how things will be done. The current 'screenmanager' in Python should probably be renamed to UIManager or something. It just loads the appropriate python module and class, and calls it's show function. Python handles all the CEGUI stuff and filling in the data. Currently the C++ sister classes handle the 3D Ogre stuff, scenes, view area, etc. It also exposes some function to python to control it.

 

As far as framework... there isn't much of one. (Well, there isn't much of one in Python, what reist has in C++ is great with an Iscreen, and base screen ). We really need to decide on something like that, cause it's just kind of loosely done where a screen has a show() and destroy() function (however this isnt enforced! Earthscreen currently doesn't).

  • How does the “real time” couple together?
  • Where do stackless threads fit into the UI? Into the AI? Into Real time?

All the stackless threads in the UI I discussed above. They are only used in dialog screens.

 

The AI on the other hand, uses them a lot. It kinda makes my head spin looking at it at times with all these wrappers that create a new tasklet/thread using passed in function references. Best from what I can tell there really is only 1 main tasklet being ran. It's in scheduler.py. In startup scheduler.py's start gets called which simply makes a tasklet that goes to __actor_scheduler() which goes through all the 'actors' that have registered to it (basically anything with an icon, though this is actually handled by radar.py). It schedules the actor, which seems to balance out the channel it created (every actor has its own channel I believe). Then the scheduler calls actor.tick() which unless overridden does nothing. The craftActors however override this and do the complicated 'move to target' routine, which unfortunately does not look at game time. Just moves by the arbitrary amount specified in the crafts velocity every tick.

 

Now after all these actors have done their voodoo this tasklet calls 'snake.pyos.beNice()' which basically makes it recieve on the global_niceChannel. This channel, though is kept by the C++ scheduler class. This class has a frame method that is called every frame. It mainly just rebalances channels and sends a signal on the channel when the next frame is called. I found out this can be done completely in python, but it is slower, this is the reason for the C++ class.

 

Alot of this is done in the Model section of the scripts. These are going to be coded into C++ (as far as I know), so alot of this is going to be replaced. Having said that, it really looks like python will be event-driven, both in UI and in the AI. I'm not seeing any real need for it to get called every frame. Any 'ticks' will probably be relatively lengthy. Only thing I can think that would need to be ticked is the Overall Strategic AI, or what ever that will decide what UFOs and Missions to do. I don't see a need for updating it much more than every day, maybe every hour.

 

None if this is helped by the fact that the people who did the stackless work (Garo & Guyver6) won’t answer these questions, and have been almost completely absent for months now. (Yes, they do turn up occasionally, but not for long, and we absences of weeks between appearances.) And as Guyver is team leader, reist and I are reluctant to try changing anything here.

 

Now, I will concede that short of a real time battlescape, the geoscape is probably the most complicated part of Xenocide, so it makes sense to try and figure that out first. However, I also think that we need to regard our current attempt at it with stackless python as a prototype and learning experience. It works (sort of) but it’s an awful mess. And it shows that Stackless python is not as clean a solution as was originally thought.

 

Yeah I actually do see this stackless python as more of a prototype.

 

Ok, well here's a couple ideas I just got.

 

It might not be a bad idea to try and prototype stuff in python (not necessarily stackless) first. Once we get the major kinks out of the python, move it to C++. We would probably want to establish some kind of framework/protocol for doing this so the transistion is a bit easier (components using it don't need to be rewritten to call the C++ ones).

 

What about some further documentation of the code or a better brief outline of what it does? This should go on the Wiki's I think. I suppose I could try and write up what I understand at first, you guys can edit it later. I'm not sure if I should do it on a per file basis or a per class. Probably file for now, as usually there is usually only one class in it, and if there is another its closely related.

Link to comment
Share on other sites

×
×
  • Create New...