Page 4 of 5

Posted: Sat Jan 20, 2007 10:24 am
by dajt
Another day (or two), another Oolite hack.

I like the idea of being able to switch off and turn the ship with thrusters to reorient and then light the engines up again, but I have not been able to get to grips with the flight code to implement it (and I've tried a couple of times). It probably isn't too hard but I find it a confusing area of the source.

I also like the idea of having thrusters to give the linear adjustments as opposed to pitch, roll, and yaw. This would make manual docking a lot easier.

And all the talk in the ZZ Haul with freighters and cargo canisters etc is also pretty interesting.

Anyway, for laughs I've spent a couple of evenings integrating the ODE physics engine into Oolite. First I made it control the station rotation because that seemed the easiest thing to do. Now I have it controlling the player's ship (other ships use the standard flight model).

So your ship is now "fully newtonian" as in FE2/FFE. It has the main engines at the back and pitch and roll thrusters. To slow down you have to flip over and use the main engines to go against your current velocity.

As you can imagine it is a pig to fly. But perhaps there are routines that could be added to make it easier, like automatic damping of the roll and pitch at the press of a button, and limiting the top velocity so it can't get out of hand, and something like desired speed and powerful retro thrusters (movable nozzles on the main engines?) to assist slowing down so you don't have to flip over.

The only cool thing about this flight model at present is you can match the station's rotation when docking and not have to keep pressing the roll button. I think you can turn the dampers off which would also achieve this, but I don't know how. The source certainly has conditional statements for the dampers.

I really wanted to do it to explore cooler freighters and stuff - ODE allows for entities to be joined together with various types of joints. And it's just occured to me that I could let Oolite control the main ship's velocity and keep updating ODE with that, and let it propagate the changes through the towed objects.

Anyway, I don't think this is a serious option for the game because (a) even though the ODE interface is in C, I still have to compile Oolite with a C++ compiler to get everything going far as I can tell [*], and (b) the updates are pretty jittery, probably because Oolite is using metres as units which makes all the numbers big and ODE's integrator likes them around 0.0 - 1.0. The suggested fix is to scale the physics modelling units and display units, but I'm not that enthusiastic.

[*] Meaning remember the upset when I have tried to use other C++ libs like FTGL and libnoise. Why did Apple have to use Obj-C as their preferred language!?!? If Oolite was written in C++ we'd have masses of extra code easily available to us.

Posted: Sat Jan 20, 2007 11:44 am
by Dr. Nil
:D

The reports of anything done to the code or experiments carried out are my favorite posts on this BB.

I don't really know how realistic physics Oolite could get and still remain playable. Frontier things that I'd like to see before realistic flight physics are:

The Galaxy. It gave the game so much more depth than the 8 flat boards with all systems colonized.

The variable jump ranges from ship to ship.

The in-system 3D maps with planets and moons and stations, where you could zoom down an find individual stations and target them for:

The autopilot. Which could handle anything even:

Landing on planets.

But that might require more realistic scales of astronomical bodies, which would very likely demand scaling up the systems a lot which might in turn require in-system jumps or multiple witchpoint buoys in each system or some other solution (like Frontier used the speeding up of time).

Ehm. Just thinking aloud. The best thing would IMO be the galaxy. I imagine the current eight flat galaxy boards could become eight quadrants making up a 2x2x2 cube of quadrants in an not entirely unfashionable arm of the Milky Way.

Posted: Sat Jan 20, 2007 11:49 am
by LittleBear
I'd really like to see landing on planets. Oolite does change the sky to blue when you are very close to the planet and with heat shields you can fly about a bit before you blow up. But I guess this would be a pretty major bit of coding.

Posted: Sat Jan 20, 2007 11:57 am
by Dr. Nil
LittleBear wrote:
I'd really like to see landing on planets. Oolite does change the sky to blue when you are very close to the planet and with heat shields you can fly about a bit before you blow up. But I guess this would be a pretty major bit of coding.
That's the beauty of wish lists. We're allowed to put more on them, than we can realistically expect to ever get :)

I have no idea of how hard it would be to implement, not being a coder myself.

They did have the ability to land on planets together with the one-big-galaxy in Frontier which came on a 720k (or whatever was the capacity) disk.

Posted: Sat Jan 20, 2007 10:27 pm
by dajt
Dr. Nil wrote:
The Galaxy. It gave the game so much more depth than the 8 flat boards with all systems colonized.
This has always been high on my list too, but it hard to do. The Oolite code is so centred on the Elite galaxy generation algorithm that you have to rewrite most of the non-graphics part of the game to get rid of it. I've considered it, but you're really rewriting the game, and if I did that I'd start again in C++ and make it not so Mac centric just porting the entity classes. I have been so tempted to do this, so many times, but I am experienced enough to know I probably wouldn't get 10% done.
Dr. Nil wrote:
The in-system 3D maps with planets and moons and stations, where you could zoom down an find individual stations and target them for:

The autopilot. Which could handle anything even:

Landing on planets.
Aside from the landing on planets bit this has also been high on my wishlist, and a start was made with the sun-distance engine mod. But again, big change.

The landing on planet thing is a big job. Libnoise would be able to help out by generating more and more detailed textures as you got closer, but it would be too slow. To generate the textures you see in the demos takes in the order of 10 mins for me.
Dr. Nil wrote:
Ehm. Just thinking aloud. The best thing would IMO be the galaxy. I imagine the current eight flat galaxy boards could become eight quadrants making up a 2x2x2 cube of quadrants in an not entirely unfashionable arm of the Milky Way.
I had a very similar thought just yesterday about transforming the 8 flat "galaxies" into some 3-d representation that didn't break the game's back-story too much!

Posted: Sun Jan 21, 2007 12:31 am
by DaddyHoggy
@dajt

If you're poking round in the code and people are coming up with wish lists - I have but one - sort out why there are problems with displaying multiple mission briefs when they occur from concurrently running OXPs - LittleBear has asked people to uninstall Thargon Wars and/or finish Military Ships oxps when playing Assassins - all because Oolite fluffs [seemingly randomly] which briefs it shows and which it doesn't if multiple oxps ask for mission screens at the same time. I can see that with progressively more oxps coming online which, because of your fab javascript implementation of scripts (which can/will lead to increasingly more clever/complicated/persistant oxps) that this will become more of a problem not less.

So, if your rummaging and happen to notice why this happens and can fix it, that would be great. I have lots of ideas for indefinitely running oxps (of which Snoopes will be just the first) but no point in even starting to script them if this particular problem is not sorted.

Cheers,

DaddyH

Posted: Sun Jan 21, 2007 12:47 am
by dajt
I have been thinking about this as I'm working on the JavaScript stuff and I think it is something to do with the fact the mission screen is not "modal". That is, the game keeps running and evaluating all the scripts while showing the screen. This means all the scripts are evaluated during one script checking cycle, and so the last one to set the contents of the mission screen is the one that "wins".

I considered changing the mission screen to be modal but this would be a pretty big change, break all current scripts, and lose features like the animated ship models.

There may already be a way around it by using proper conditions and scripts ensuring they leave the mission_choice string unset when they're done with it. I'll have a play around and see if I can make it work.

Another thing that might work is to use a common mission variable to say "I have set the mission screen, you'll have to wait". That way all OXPs can agree to use that mission var to avoid contention. This should work now.

EDIT

OK, here is an example of using a shared mission var to check for mission screen contention. It seems to work. The script is in OOS format because it takes me too long to write them in PLIST format.

The mission screens appear in order of oxp1, oxp1_a, oxp2.

There is still a problem in that they don't appear immediately after one another - each mission screen appears in the next script checking loop. So even though a mission screen will appear, the player might still miss it because they were not docked long enough for it to appear, or might not flick around the docked screens enough to cause the script checking to happen again before launching.

Code for OXP1:

Code: Select all

oxp1
if mission_screen_taken equal YES then
	if gui_screen_string equal GUI_SCREEN_MISSION then
		// do nothing - just here to get the else because there is no "not equal" comparator
		testForEquipment: EQ_FUEL
	else
		debugMessage: oxp1 resetting mission screen variable
		reset: mission_screen_taken
	endif
endif

if mission_screen_taken undefined and mission_oxp1_state undefined then
	setGuiToMissionScreen
	addMissionText: oxp1
	set: mission_screen_taken YES
	set: mission_oxp1_state A
endif

if mission_screen_taken undefined and mission_oxp1_state equal A then
	setGuiToMissionScreen
	addMissionText: oxp1_a
	set: mission_screen_taken YES
	set: mission_oxp1_state B
endif
Code for OXP2:

Code: Select all

oxp2
if mission_screen_taken equal YES then
	if gui_screen_string equal GUI_SCREEN_MISSION then
		// do nothing - just here to get the else because there is no "not equal" comparator
		testForEquipment: EQ_FUEL
	else
		debugMessage: oxp2 resetting mission screen variable
		reset: mission_screen_taken
	endif
endif

if mission_screen_taken undefined and mission_oxp2_state undefined then
	setGuiToMissionScreen
	addMissionText: oxp2
	set: mission_screen_taken YES
	set: mission_oxp2_state A
endif

Posted: Sun Jan 21, 2007 10:35 am
by dajt
aegidian wrote:
2. Yaw boosters - ArcElite had these as a reward for a mission (which one and the details - I'm not sure), I don't think they're necessary - but would add them if enough people asked.
Given this is something Giles okayed all that time ago I have checked code into the trunk to enable yaw to be used.

You don't need special equipment to do it at present, I just wanted to get the working code in there. It should be trivial to change it to require "yaw boosters" although I can't see why any spaceship wouldn't have them as standard.

I didn't do anything for joystick or mouse control, or the Mac. Adding the necessary code to the Mac part of PlayerEntity (Controls).m should be trivial.

If someone adds the Mac code, I'd like to know what the Mac keycodes for the numeric keypad 1 & 3 keys are (the default keys I've used for yaw). I just used keycodes 310 and 311 because they were free - I have no idea what keys they represent on a Mac!

Posted: Sun Jan 21, 2007 2:52 pm
by DaddyHoggy
@dajt - thanks for looking at the mission screen issue - I'm sure that your technique can be put into new long term oxps and old ones tweaked to incorporate it.

Perhaps some nice Admin-types can take your relevant text and make it a sticky in the expansion section?

We might as well start the ball rolling sooner rather than later!

Thanks

DaddyH

Posted: Sun Jan 21, 2007 4:33 pm
by Cmdr Wyvern
dajt wrote:
Given this is something Giles okayed all that time ago I have checked code into the trunk to enable yaw to be used.

You don't need special equipment to do it at present, I just wanted to get the working code in there. It should be trivial to change it to require "yaw boosters" although I can't see why any spaceship wouldn't have them as standard.

I didn't do anything for joystick or mouse control, or the Mac. Adding the necessary code to the Mac part of PlayerEntity (Controls).m should be trivial.

If someone adds the Mac code, I'd like to know what the Mac keycodes for the numeric keypad 1 & 3 keys are (the default keys I've used for yaw). I just used keycodes 310 and 311 because they were free - I have no idea what keys they represent on a Mac!
Neat.

Now what parts of the code do I hack to make this work with my 4-axis joystick?

Posted: Mon Jan 22, 2007 7:16 am
by drumz
I'm kind of working on the joystick/yaw code. Coding-wise I'm treating it more like thrust than roll/pitch, which I think will work. So far I've modified the following files:

Core/PlayerEntity (Controls).m
Core/PlayerEntity.h
Core/PlayerEntity.h
SDL/JoystickHandler.m
SDL/JoystickHandler.h

If I get anything that works I'll post the diffs to rev 773.

Edit: Oh yeah, I'm working on the Linux source.

Posted: Mon Jan 22, 2007 7:54 am
by TGHC
Welcome aboard Drumz, great first post, thanks for contributing!

Posted: Mon Jan 22, 2007 2:29 pm
by Dr. Nil
@dajt: I had some very similar ideas for a temporary solution to the mission screen problem.

Sometimes I can almost be tempted to think that we do not get the ideas, but rather act as agents for their realization :roll:
dajt wrote:
I've considered it, but you're really rewriting the game, and if I did that I'd start again in C++ and make it not so Mac centric just porting the entity classes. I have been so tempted to do this, so many times, but I am experienced enough to know I probably wouldn't get 10% done.
Now if we could only get 19 more coders with your skills to work together then you'd only have to commit to half that ;)

Thanks for any work done on the code. Remember to keep the work load and speed at the level where it feels good.

@drumz: TGHC said it. Great first post.

Posted: Mon Jan 22, 2007 5:53 pm
by drumz
YES!!

Joystick support for yaw is working (sort of). It's actually backwards right now, and I managed to clobber the keyboard control somehow.

I'm not sure how to (or if you can) upload files as attachments here, so I'll just put the diffs in code blocks. I did

Code: Select all

diff -c file.old file.new
JoystickHandler.h

Code: Select all

*** JoystickHandler.h.old       2007-01-22 11:27:09.000000000 -0600
--- JoystickHandler.h.new       2007-01-22 00:55:40.000000000 -0600
***************
*** 27,32 ****
--- 27,33 ----
  enum {
    AXIS_ROLL,
    AXIS_PITCH,
+   AXIS_YAW,
    AXIS_PRECISION,
    AXIS_THRUST,
    AXIS_VIEW,
***************
*** 37,42 ****
--- 38,45 ----
  enum {
    BUTTON_INCTHRUST,
    BUTTON_DECTHRUST,
+   BUTTON_INCYAW,
+   BUTTON_DECYAW,
    BUTTON_SCANNERZOOM,
    BUTTON_JETTISON,
    BUTTON_COMPASSMODE,
***************
*** 127,132 ****
--- 130,138 ----
  // Roll/pitch axis
  - (NSPoint) getRollPitchAxis;

+ // Yaw axis
+ - (double) getYawAxis;
+
  // Setting button and axis functions
  - (void) setFunctionForAxis: (int)axis
                     function: (int)function
JoystickHandler.m

Code: Select all

*** JoystickHandler.m.old       2007-01-22 11:27:24.000000000 -0600
--- JoystickHandler.m.new       2007-01-21 17:31:58.000000000 -0600
***************
*** 87,92 ****
--- 87,97 ----
     return NSMakePoint(axstate[AXIS_ROLL], axstate[AXIS_PITCH]);
  }

+ - (double) getYawAxis
+ {
+    return axstate[AXIS_YAW];
+ }
+
  - (BOOL) getButtonState: (int)function
  {
     return butstate[function];
***************
*** 376,381 ****
--- 381,387 ----
           break;
        case AXIS_ROLL:
        case AXIS_PITCH:
+       case AXIS_YAW:
           if(precisionMode)
           {
              axstate[function]=axisvalue / STICK_PRECISIONDIV;
***************
*** 434,444 ****
--- 440,452 ----
           {
              axstate[AXIS_PITCH] /= STICK_PRECISIONFAC;
              axstate[AXIS_ROLL] /= STICK_PRECISIONFAC;
+             axstate[AXIS_YAW] /= STICK_PRECISIONFAC;
           }
           else
           {
              axstate[AXIS_PITCH] *= STICK_PRECISIONFAC;
              axstate[AXIS_ROLL] *= STICK_PRECISIONFAC;
+             axstate[AXIS_YAW] *= STICK_PRECISIONFAC;
           }
        }
     }
PlayerEntity (Controls)

Code: Select all

*** PlayerEntity (Controls).m.old       2007-01-22 11:27:59.000000000 -0600
--- PlayerEntity (Controls).m.new       2007-01-22 11:41:08.000000000 -0600
***************
*** 257,262 ****
--- 257,339 ----
                 }
  #endif

+ // Start Yaw control
+ #ifdef GNUSTEP
+                // DJS: Yaw can be an axis or a button. Axis takes precidence.
+          double reqYaw=[stickHandler getAxisState: AXIS_YAW];
+          double yaw_dampner = YAW_DAMPING_FACTOR * delta_t;
+          if(reqYaw == STICK_AXISUNASSIGNED || [stickHandler getNumSticks] == 0)
+          {
+             // DJS: original keyboard code
+             yawing = NO;
+             if (([gameView isDown:key_yaw_right] || joyButtonState[BUTTON_INCYAW])&&(flight_yaw < max_flight_yaw))
+             {
+                if (flight_yaw > 0.0)  flight_yaw = 0.0;
+                [self decrease_flight_yaw:delta_t*yaw_delta];
+                yawing = YES;
+             }
+             if (([gameView isDown:key_yaw_left] || joyButtonState[BUTTON_DECYAW]))
+             {
+                if (flight_yaw < 0.0)  flight_yaw = 0.0;
+                [self increase_flight_yaw:delta_t*yaw_delta];
+                yawing = YES;
+             }
+             if (!yawing)
+             {
+                if (flight_yaw > 0.0)
+                   {
+                      if (flight_yaw > yaw_dampner)    [self decrease_flight_yaw:yaw_dampner];
+                      else     flight_yaw = 0.0;
+                   }
+                if (flight_yaw < 0.0)
+                {
+                   if (flight_yaw < -yaw_dampner)   [self increase_flight_yaw:yaw_dampner];
+                   else        flight_yaw = 0.0;
+                }
+             }
+          } // DJS: STICK_NOFUNCTION else...a joystick axis is assigned to thrust.
+          else
+          {
+             if(flight_yaw < max_flight_yaw * reqYaw)
+             {
+                flight_yaw += yaw_delta * delta_t;
+             }
+             if(flight_yaw > max_flight_yaw * reqYaw)
+             {
+                flight_yaw -= yaw_delta * delta_t;
+             }
+          } // DJS: end joystick yaw axis
+ #else
+       yawing = NO;
+       if ([gameView isDown:key_yaw_left])
+       {
+               if (flight_yaw < 0.0)  flight_yaw = 0.0;
+               [self increase_flight_yaw:delta_t*yaw_delta];
+               yawing = YES;
+       }
+       else if ([gameView isDown:key_yaw_right])
+       {
+               if (flight_yaw > 0.0)  flight_yaw = 0.0;
+               [self decrease_flight_yaw:delta_t*yaw_delta];
+               yawing = YES;
+       }
+       if (!yawing)
+       {
+               if (flight_yaw > 0.0)
+               {
+                       if (flight_yaw > yaw_dampner)   [self decrease_flight_yaw:yaw_dampner];
+                       else    flight_yaw = 0.0;
+               }
+               if (flight_yaw < 0.0)
+               {
+                       if (flight_yaw < -yaw_dampner)   [self increase_flight_yaw:yaw_dampner];
+                       else    flight_yaw = 0.0;
+               }
+       }
+ #endif
+ // End Yaw control
+
+
                        //
                        //  hyperspeed controls
                        //
***************
*** 1181,1187 ****

        double roll_dampner = ROLL_DAMPING_FACTOR * delta_t;
        double pitch_dampner = PITCH_DAMPING_FACTOR * delta_t;
!       double yaw_dampner = PITCH_DAMPING_FACTOR * delta_t;

        rolling = NO;
        if (!mouse_control_on )
--- 1258,1264 ----

        double roll_dampner = ROLL_DAMPING_FACTOR * delta_t;
        double pitch_dampner = PITCH_DAMPING_FACTOR * delta_t;
!       double yaw_dampner = YAW_DAMPING_FACTOR * delta_t;

        rolling = NO;
        if (!mouse_control_on )
***************
*** 1281,1286 ****
--- 1358,1364 ----
                }
        }

+       /*
        yawing = NO;
        if ([gameView isDown:key_yaw_left])
        {
***************
*** 1306,1312 ****
                        if (flight_yaw < -yaw_dampner)   [self increase_flight_yaw:yaw_dampner];
                        else    flight_yaw = 0.0;
                }
!       }
  }
  #else         // ifdef GNUSTEP else
  - (void) pollFlightArrowKeyControls:(double) delta_t
--- 1384,1390 ----
                        if (flight_yaw < -yaw_dampner)   [self increase_flight_yaw:yaw_dampner];
                        else    flight_yaw = 0.0;
                }
!       } /**/
  }
  #else         // ifdef GNUSTEP else
  - (void) pollFlightArrowKeyControls:(double) delta_t
***************
*** 1319,1324 ****
--- 1397,1403 ----
        virtualStick.y *= sensitivity;
        double roll_dampner = ROLL_DAMPING_FACTOR * delta_t;
        double pitch_dampner = PITCH_DAMPING_FACTOR * delta_t;
+       double yaw_dampner = YAW_DAMPING_FACTOR * delta_t;

        rolling = NO;
        if (!mouse_control_on)
PlayerEntity.h

Code: Select all

*** PlayerEntity.h.old  2007-01-22 11:28:20.000000000 -0600
--- PlayerEntity.h.new  2007-01-22 00:42:54.000000000 -0600
***************
*** 126,131 ****
--- 126,132 ----

  #define ROLL_DAMPING_FACTOR                           1.0
  #define PITCH_DAMPING_FACTOR                  1.0
+ #define YAW_DAMPING_FACTOR                    1.0

  #define PLAYER_MAX_FORWARD_SHIELD             (128.0 * (shield_booster + shield_enhancer))
  #define PLAYER_MAX_AFT_SHIELD                 (128.0 * (shield_booster + shield_enhancer))
***************
*** 511,516 ****
--- 512,518 ----
    int                                         numSticks;
    JoystickHandler                     *stickHandler;
    BOOL                                                keyboardRollPitchOverride;
+   BOOL                                                keyboardYawOverride;

    // For PlayerEntity (StickMapper)
    int                                         selFunctionIdx;
PlayerEntity_StickMapper.m

Code: Select all

*** PlayerEntity_StickMapper.m.old      2007-01-22 11:28:41.000000000 -0600
--- PlayerEntity_StickMapper.m.new      2007-01-21 21:56:09.000000000 -0600
***************
*** 279,284 ****
--- 279,289 ----
                     allowable: HW_AXIS
                        axisfn: AXIS_PITCH
                         butfn: STICK_NOFUNCTION]];
+    [funcList addObject:
+       [self makeStickGuiDict: @"Yaw"
+                    allowable: HW_AXIS
+                       axisfn: AXIS_YAW
+                        butfn: STICK_NOFUNCTION]];
     [funcList addObject:
        [self makeStickGuiDict: @"Increase thrust"
                     allowable: HW_AXIS|HW_BUTTON
One note, you'll have to edit ~/GNUstep/Defaults/.GNUstepDefaults because I added YAW to an enum in JoystickHandler.h. Maybe I should have tacked it on the end.
New .GNUstepDefauts:

Code: Select all

...
        JoystickAxes = {
            0 = {
                isAxis = <*BY>;
                stickAxBt = <*I0>;
                stickNum = <*I0>;
            };
            1 = {
                isAxis = <*BY>;
                stickAxBt = <*I1>;
                stickNum = <*I0>;
            };
            2 = {
                isAxis = <*BY>;
                stickAxBt = <*I5>;
                stickNum = <*I0>;
            };
            4 = {
                isAxis = <*BY>;
                stickAxBt = <*I6>;
                stickNum = <*I0>;
            };
        };
...
Old .GNUstepDefauts:

Code: Select all

...
        JoystickAxes = {
            0 = {
                isAxis = <*BY>;
                stickAxBt = <*I0>;
                stickNum = <*I0>;
            };
            1 = {
                isAxis = <*BY>;
                stickAxBt = <*I1>;
                stickNum = <*I0>;
            };
            3 = {
                isAxis = <*BY>;
                stickAxBt = <*I6>;
                stickNum = <*I0>;
            };
        };
...
Edit: realized I needed to do "diff -c file.old file.new" instead of "diff file.new file.old"

Posted: Mon Jan 22, 2007 6:42 pm
by drumz
About editing ~/GNUstep/Defautls/.GNUstepDefaults, I forgot that you could assign axes in-game. I noticed in the code AXIS_VIEW is declared, but never used. I'd like to look into that so I can use the hat switch instead of 1,2,3,4 for the views. After, of course, I can finish the yaw stuff.