Game Development Community

Player movement

by Ron Yacketta · in Torque Game Engine · 08/20/2002 (4:36 pm) · 27 replies

All,

I have been caught up in playing the likes of Dungeon Siege and NeverWinter Nights. Just recently I got this fire inside to add clickable movements to TGE, that is click a location on the screen and the player will move to it.

I started to dig around the AI code for some clues, but man that is a muck in their ;)

I was wondering if we could open up some dicussion regarding this topic? I am sure other game types (especialy RPG's MMORPG's etc) would be interested in this.

So, to start this off. What do you think would be the most sane/TGE conforming way to add such a thing to TGE?

Regards,
Ron
Page «Previous 1 2
#1
08/20/2002 (5:36 pm)
Hey, Ron! Long time no see. :)

There's a resource on AI in Torque that includes a "go to waypoint" function. You might be able to spawn a special waypoint at the mouse-click location, tell the AI to go there, then remove the waypoint when it reports it's done.

What sort of project is this? I might be able to help a bit more with some details of how the UI will work.

-Corvi
#2
08/20/2002 (6:39 pm)
Corvi,

Long time no see? hrmm sounds like I should know you ;)
anyways, this is not for any project; just an idea I had after playing the previous mentioned games.

I will have to take a look at the AI code, but in my non AI mind to me anything regarding AI would not affect a real player.. seeing that AI is just that artificial ;)

Regards,

Ron
#3
08/20/2002 (9:58 pm)
I was fairly active on the HL Coders list, as were you. :)

Well, the usage would depend on what sort of project you're working on, but an indirect interaction method might work. As opposed to the typical FPS where you directly control yourself, you "instruct" the player object to move around and interact with the environment. If you wanted to do something like NWN or DS, it'd make a lot of sense to actually have the player AI-controlled and have you as sort of a detached observer, giving it commands instead of controlling it directly. Of course, NWN gave you the option of controlling the player directly, so you'd need to code both interfaces, but the FPS one is already done for you. :)

-Corvi
#4
08/21/2002 (5:30 am)
Ah!

Yes, now I remember :) welcome to the world of TGE and idie development! TGE definatly gives us (developers) much much more freedom than a HL SDK would ever be able to.

Yes, you are right regarding NWN and DS. I would need to make the player control an AI bot of sorts. Hrmm, might need to change quit a bit of code to accomplish this one (well scripting mostly).

Drop me an email some time Corvi!

Regards,

Ron
#5
08/28/2002 (3:29 pm)
*bump*

Anyone else have any ideas here? I am sure their are several projects that would love to have such a thing written up in the resources.

Regards,

Ron
#6
08/30/2002 (9:28 am)
O.K
After some digging around and general horse play I decided to go postal on this ;)

Here is what I found:

Player movement is actualy initiated in ProcessList::advanceObjects() within this bit of code

while ((obj = list.mProcessLink.next) != &list) {
      obj->plUnlink();
      obj->plLinkBefore(&head);

      // Each object is either advanced a single tick, or if it's
      // being controlled by a client, ticked once for each pending move.
      if (obj->mTypeMask & ShapeBaseObjectType) {
         ShapeBase* pSB = static_cast<ShapeBase*>(obj);
         GameConnection* con = pSB->getControllingClient();
         if (con && con->getControlObject() == pSB) {
            Move* movePtr;
            U32 m,numMoves;
            con->getMoveList(&movePtr, &numMoves);
            for (m = 0; m < numMoves && pSB->getControllingClient() == con; )
               obj->processTick(&movePtr[m++]);
            con->clearMoves(m);
            continue;
         }
      }

the key section of code is
if (con && con->getControlObject() == pSB) {
            Move* movePtr;
            U32 m,numMoves;
            con->getMoveList(&movePtr, &numMoves);
            for (m = 0; m < numMoves && pSB->getControllingClient() == con; )
               obj->processTick(&movePtr[m++]);
            con->clearMoves(m);
            continue;
         }

This will either call into AIConnection::getMoveList() or GameConnection::getMoveList() based on the obj (con).

What I think (could be way off here) needs to be done is add some code to GameConnection to support the passing in the coords from script.

I have also noticed that their is actualy nothing passed between server/client in way of actual movement coords, everything is dynamicly created.

when one presses "w" on the keyboard a function is fired that sets mForwardAction to 1 this in turn sets mMove.y to 1 in GameConnection::getNextMove(). inside Player::updateMove() this vaule is used to detrmine player movement/velocity etc (yes, I generalised this part; could use more specifics).

So, I think i will need todo some re-tooling in the GameConnection code to support mouse controled player movement.

Anyone else have any thoughts on this? (Rick? Mark? Tim?)

Regards,

Ron
#7
08/30/2002 (10:00 am)
If it was going to be a 3rd person where the control is like an iso RPG or RTS game, I would reccomend completely rehauling how input is given to the player, or just spawn bots for everyone. If you think about it, it makes the most sense just to use AIs.
#8
08/30/2002 (11:22 am)
Ron, I'd think about how the AI is driving the player models right now. I dont think its necassarily good to have an AI version of GameConnection to feed moves into the move list, but its as good a way as any to tell your character "move here".

I'd basically overhaul the AI connection stuff as it is, make a "AI player" class thats simply derived from player and doesnt require a "game connection". Then once you can tell the AIPlayer "go here" your set.

Phil.
#9
08/30/2002 (12:46 pm)
personally, though again I'd note I'm not *YET* a TGE developer, I'd approach the RPG/MMPORPG relm of things (combat, player movement etc.) by not actually HAVING a player, and rather having a "dumb AI" bot that wouldn't do anything unless you told it to... rather similar to unit controls in a RTS game. I'd think that would be FAR easier.

Just my two cents,
Jeff
#10
09/03/2002 (11:37 am)
Ron,
I was thinking about this, and I suppose that the best way is to use an AIPlayer also for the player, indeed in DS you can select a character and control it while the others are controlled by the AI, so every characters is AI controlled. At the moment I have implemented a basic A* pathfinding that works only with the terrain, then I'll move on to this subject and I'll see what I can do, because my goal is to create a classic RPG with this engine.
Davide
#11
09/03/2002 (11:49 am)
I found an issue with using AIPlayer and not sure (yet) how to resolve it.

in game.cs I change the CreatePlayer from using Player() to AIPlayer(), then comment out a coupld of those set lines (seeing AIPlayer dose not have them, yet ;) )

All foes well, except when the bot is put in game you see nothing ;) except the last loading screen. i am trying to track down where in the player code that the loading screen goes to the way side and the actualy ingame view is seen. I think it is addtoscene(), but have not had the time to run in debug mode and test that theory.

-Ron
#12
09/03/2002 (12:35 pm)
Just to add my $.02:

I think you're going in the right direction - use the AI player to actually move your player around. You'll want 2 connections in this case - the AIConnection that manages the player movement and the GameConnection that the human player talks over. The control object for the GC is just the observer camera, and the control object for the AIC is the player object.

All you need to do from here is hook up mouse clicks on the screen with orders for the player to move. Probably the easiest way to do this is to create a subclass of EditTSCtrl for your play view rather than GameTSCtrl. EditTSCtrl has methods for processing 2D mouse moves/clicks to 3D rays - just collide the rays with the world to find out where to move the player to. Then create a client to server event for each click command, and from the server tell the AI connection where to go.
#13
09/03/2002 (12:48 pm)
Mark,

Firstly thanks for the reply! was hoping that someone in the know would stick their nose in ;)

I follow the AIConnection portion of your thread, and agree entierly. I am not following the GameConnection part, maybe its my lack of TGE knowledge or ever better lack of C++ exp ;)

When I change the Player() to AIPlayer() in createplayer it is actualy creating an AIPlayer with a AIConnection correct? (instance of, that is) I have followed the flow in the engine code through GameProccess to GameConnection to GameConnectMovement (is that the right name? *shrug*) etc. with AIPlayer the calls actualy are passed out to AICOnnection for GetMoveList, GetMoes etc.

So, basicly I am just that deaf, dumb blind kid that sure can play some pinball....

On to the camera information, I need to track all that down. I am not sure where the ObserverCamera comes into play as well as the ACI (or was it AIC) camera you speak of comes into play either.

I thought of using EditTSCtrl vice the Game one, but decided to stick with the Game one until I get the darn bot in the game and see whats going on. I am pretty sure that I am kicking down the right door, just need to get some bigger boots.

-Ron
#14
09/03/2002 (12:49 pm)
A quick thought:

For click-based movement, I'm not sure how much of the existing functionality you need. For instance, advanced physics could well be redundant, much as they are in controlling units in an RTS game. Designing your networking model with cimple click-to-move movement model in mind could likely simplify things to the extent where you could fit literally several hundred people on a server with little slowdown.

Also, any lag in using such a model would be largely invisible to the end-user, because if the client knows the target (waypoint) that the other [player-controlled AI char] is heading to, client-side prediction will greatly minimize the visual effects of lag.

This was noticeable in Serious Sam; despite the crappy netcode, the clientside prediction was very good, since the AIs all had simple behaviors -- charge the user. They were basically guided missiles with very simple physics. So two people could play a coop map with 50 or 60 monsters on screen at once, and get maybe 5ms or 10ms worth of extra lag, and no apparent lag.
#15
09/04/2002 (6:09 am)
O.K I am even closer now (Thanks MarkF!!!)
I have changed Player() to AIPlayer in game.cs (not a good idea it seems though). I also change the control object from %player to %this.camera. This has allowed me to actualy get "into" the game ;) I just have no clue where the darn bot is *snicker* I actualy do not think he is even in the game, seein that it can not locate the 3 set functions (setTransForm etc) that is associated with %player.

I realy think that either (1) I need to keep Player() or (2) add the required functions to AIPlayer(). I was thinking of just using the mPlayer class member of AIPlayer, which would point to Player. Everything I have tracked so far leads me back to needing a Player() object.

Is their a way to expose mPlayer to the scripting engine? so one could do a %player.mPlayer.setTransfor() (where %player is a AIPlayer() )

Regards,

Ron
#16
09/04/2002 (2:43 pm)
Ok Ron, I did it... but I don't like it, at the moment it's a sort of hack but you can came with others idea if you see what I have done, so ... let's begin:

First, I have added the code that came with www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2173 then modify the onMouseDown function with this:
function PlayGui::onMouseDown(%this)
{
   // mouseVec = vector from camera point to 3d mouse coords (normalized)
   %mouseVec = %this.getMouse3DVec();
   // cameraPoint = the world position of the camera
   %cameraPoint = %this.getMouse3DPos();

   commandToServer('SelectObject', %mouseVec, %cameraPoint);

   //find the intersection with the terrain
   %selectRange = 200;
   %mouseScaled = VectorScale(%mouseVec, %selectRange);
   %rangeEnd = VectorAdd(%cameraPoint, %mouseScaled);

   %searchMasks = $TypeMasks::TerrainObjectType;

   %scanTarg = ContainerRayCast (%cameraPoint, %rangeEnd, %searchMasks);

   if (%scanTarg)
   {
      echo("PlayGui::onMouseDown %scanTarg:" @ %scanTarg);
      %targetObject = firstWord(%scanTarg);
      //Get the mouse coordinates
      %pos =  getWord(%scanTarg,1) SPC getWord(%scanTarg,2) SPC getWord(%scaTarg,2);
   }

   %cg = clientGroup.getCount();
   %selObj = 0;
   for (%c = 0; %c<%cg; %c++)
   {
    %client = clientGroup.getObject(%c);
    %sO = %client.getSelectedObj();
    if (%sO!=0)
    {
     %selObj = %sO;
    }
   }
   
   if (%selObj!=0)
   {
    %client = %selObj.client;
    if (%client.getClassName() $= "AIPlayer") //just to be sure that is an AIPlayer
    {
     %client.setMoveDestination(%pos);
     %client.move();
    }
   }
  
}

Run Torque demo, open the console and create a bot with something like this:
$Bot = aiAddPlayer(Bot);
Close the console and click on the AIPlayer to select it and then click on the terrain and the player will go to that location.
Note:
I think this isn't the best way, it can be done better, I have to find a way to eliminate the Player and use only the AIPlayer. Another thing that I don't understand is why every AIPlayer is handled like a remote connection from a client, I don't know much about networking but I don't think that AIPlayers used as NPC, have to be handled like clients.
Ok, let me know what you think.
Davide
#17
09/18/2002 (10:35 am)
Now that TimG stole my thunder and release AIPlayer.cc/h (snicker), I have moved onto phase two of this miny project.

I am now in the process of getting the camera to becontroled via the mouse, that is the cursor will be displayed at all times in game. When you move the mouse it will in turn move the camera accordingly.

So far I have removed the noCursor from PlayGui.gui and others. The cursor is displayed, but now I need to walk down the path to get the mouse movement applied to the camera. I have searched through guiCanvas, camera and winWindow files. made a change or two here and their, but nothing has seemed to work.

At first, it looked like the lockMouse() needed to be called; seeing that the mouse is locked when not in observer/fly mode, but this was a bust.

If you have any ideas let me hear them ;)

-Ron
#18
09/19/2002 (10:20 am)
Hi Ron,
I have already done this, and I have found a better solution for the player movement that use the normal game conncection.
I'll send it to you soon.
#19
09/20/2002 (6:34 am)
Davide,

works like a champ especialy when it is coupled with the change I sent you via email lastnight.

All the changes were applied to classes derived from their original class except for the gameConnection changes. This aids in the update/migration with CVS.

-Ron
#20
09/20/2002 (7:14 am)
Mind to share your solutions, folks? ;)
Not that I really need them for my projects, but would be interesting to check out... :)
Page «Previous 1 2