Raven's projects

Started by Raven, November 01, 2005, 11:15:34 PM

Previous topic - Next topic

Raven

Hello everyone.

For the past week I've been experimenting with jPCT (very happy with it, actually, I'm very amazed that there aren't more people using it! Why is that??). I wanted to share with you some of my concerns regarding a system architecture for an FP(S) platform (I'd like it to be more than just a shooter (hence the parenthesis).

My end-goal is to create a first-person game, but since I haven't quite decided the game's nature/theme I'd like to begin with creating a general platform for it (that I could perhapse release under GPL for others to experiment with).

Currently I'm wondering about the following things:

1. Levels
My current architecture introduces levels as classes, for each level there is a class with the same name. The level class would store vital information like the players starting position in that level, lighting positions, etc... However, the problem is that that's a lot of information to hand sort, object positions, decorations, etc..

A partial solution to this problem would be having a certain type of signal in the level designs as pointers for a "LevelManager" which would place objects.

For example: a sphere with the texture named "PlayerPos" is actually a pointer for where the Player Starting Position should be. Levelmanager would read these pointers, and use their position to automatically instantiate and place the right types of objects, etc.. (then delete them from the world)

Theoretically, this would be possible with jPCT, yes?

2. Segmented character/player bodies

Multi-part humanoids. For an FPS game, it'd be really nice to have arms, torso, head and feet all separate objects capable of being damaged independently. However that would pose many problems: Animations for each part would have to be animated seperately and initiated at the same time when something happens to the humanoid. So it would be very hard to animate these parts independantly from eachother while the end result is supposed to act as a whole.

Can anyone think of a good way to implement a segmented-body ? There's also the question of computation, will segmented humanoids be too much for jPCT to handle?

I also noticed in another thread that Egon/Helge has been questioned before about skeletal-character physics like Half-Life uses. At the time there was no plan to implement that kind of feature. That hasn't by any chance changed, has it?  :)

3. Saving

My current thoughts on saving are by simply making the Level class, Stats class (Contains historical info about the gameplay) and Player class serializable. When continued you would simply load the classes.

Sounds a bit brute to me, but that's all I can think of.

---

Thanks for reading.
Hope you're having as much fun as I am.

Cheers,
  - Raven

EgonOlsen

Quote from: "Raven"A partial solution to this problem would be having a certain type of signal in the level designs as pointers for a "LevelManager" which would place objects....
Theoretically, this would be possible with jPCT, yes?
Yes. But i would use the name of the object, not it's texture. jPCT creates names for objects loaded from 3ds that start with the name the object has in 3ds. You may check for this name and don't merge the placeholder object to the level but replace it with the item instead.


Quote from: "Raven"
Can anyone think of a good way to implement a segmented-body ? There's also the question of computation, will segmented humanoids be too much for jPCT to handle?
Not too much to handle, but difficult to implement. It should be possible to code such a thing using IVertexControllers....but it sounds quite hard to do to me.

Quote from: "Raven"
I also noticed in another thread that Egon/Helge has been questioned before about skeletal-character physics like Half-Life uses. At the time there was no plan to implement that kind of feature. That hasn't by any chance changed, has it?  :)
The point is, that i can only do so much. Doing a good skeletal animation system is a little project of its own. To be honest, i hoped for somebody to write one on top of jPCT, releasing it to the public and letting me integrate it into the engine's core to squeeze out some additional performance...but that didn''t happen until now :wink:
To be honest, i don't recommend starting with a goal as high as this animation system because chances are that you'll never finish it. But that's just me.

Quote from: "Raven"
My current thoughts on saving are by simply making the Level class, Stats class (Contains historical info about the gameplay) and Player class serializable. When continued you would simply load the classes.

Sounds a bit brute to me, but that's all I can think of.
Don't know, should work well enough if space and/or loading times aren't important.

Raven

Quote from: "EgonOlsen"Yes. But i would use the name of the object, not it's texture. jPCT creates names for objects loaded from 3ds that start with the name the object has in 3ds. You may check for this name and don't merge the placeholder object to the level but replace it with the item instead.

Ah, I didn't know that. That's great! It'll make mapmaking a lot easier. Yeah, replacing the object is what I had envisioned.

Quote from: "EgonOlsen"
Not too much to handle, but difficult to implement. It should be possible to code such a thing using IVertexControllers....but it sounds quite hard to do to me.

Ach, that's too bad. At this point I don't think I dare venture into IVertexControllers. I'd rather get a working demo first. But thanks for clarifying this for me.

Quote from: "EgonOlsen"
The point is, that i can only do so much. Doing a good skeletal animation system is a little project of its own. To be honest, i hoped for somebody to write one on top of jPCT, releasing it to the public and letting me integrate it into the engine's core to squeeze out some additional performance...but that didn''t happen until now :wink:
To be honest, i don't recommend starting with a goal as high as this animation system because chances are that you'll never finish it. But that's just me.

I usually try and set my goals high to begin with and then tone them down as time progresses. Thanks for being honest - I was hoping someone would have a "magic solution" for accomplishing this, but given the options I won't attempt create it (Well, not yet at least  :wink: ).

I have an idea though of how to accomplish "damage" to different bodyparts; simply creating invisible 3x3x3 cube around the characters. When a character would receive damage, the cubes register where the "inflictor" came from.  For example, if a projectile hits a character in the chest, it must have passed through the middle cube -- this way we know a bit more than just that the character was hit. However, I'm unsure what kind of invisibility would be required, since I gather that invisible objects aren't processed? Maybe a dummy object cube?

EDIT: Actually, just a simple row of invisible cubes would be an improvement. One cube around the legs, one in the middle and one for the head. At least a lot simpler to implement.

Thanks for the feedback.

-Raven

EgonOlsen

It should be possible to get what you want easier IMHO. I think that you can use polygon IDs for this. For each model in question, you may determine which polygons belong to which body part. Using the PolygonManager on an untransformed/-translated object you can get the vertex coordinates in object space...and it may be possible to say that (for example) everything below y=-10 is the head, between 10 and -10 is the chest etc...that may work on most models well enough. Store this list and use a CollisionListener to get the ID of the polygon that has been hit by the collision, search your list for it and voila, you have your body part. Just an idea...
If you follow the "boxes"-approach, they don't have to be invisible all the time, just during rendering. That's what Paradroidz does to calculate collisions against a sphere even if the droids are usually none. When rendering, the droids are visible and the spheres are invisible. When doing the collision check, the spheres will become visible and invisible again after collision detection has finished. But i would head for the polygon ID way instead...should be easier and works better if you manage to assign polygons to body parts in some way.

Raven

The polygon ID plan sounds better. Thanks for the advice. This could also prove a very useful discussion for future jPCT-FPS gamemakers.

-Hrafn "Raven"

Raven

Hello again. I'm back with more pondering.

I've been developing Operatable objects -- so far so good. Objects can now perform various operations when clicked.

But I'm wondering about objects connected to eachother. For example, if a "ButtonObject" is connected to a "DoorObject" -- does anyone have a good idea as to how to assign these objects to eachother?

Better yet; Let's say I have a level with 10 doors and 10 ButtonObjects, how would be the best way to assign each ButtonObject to it's specific door?

All ideas are appreciated.

Cheers,
-Raven

rolz

object3d.addChild() ?

but i think it is good idea to create some wrapper for your game objects to separate from 3D, lets say something like this



public class GameObject {
protected Object3D object3D;
...
}

public class Door extends GameObject{
 public Door();

}

public class DoorTrigger extends GameObject{
 
 private Door myDoor;

 public DoorTrigger(Door door){
  this.myDoor = door;
 }

}
...
Regards,
Andrei

EgonOlsen

Or write yourself a GameEvent and a GameEventListener. Make the door a GameEventListener, register it on each button in question and let the button fire a GameEvent(<pressed>) to all its listeners when pressed.

Raven

Thanks for the advice guys.

I'd created a wrap for objects, but the objects extended Object3D ... I hadn't thought of the other option  :oops:

Both your ideas help a lot. Thanks. I'm going to read up on how I could implement a GameEventListener, not quite sure how that'd work yet.

Keep you posted.
Thanks again.
-Hrafn

EgonOlsen

Quote from: "Raven"Thanks. I'm going to read up on how I could implement a GameEventListener, not quite sure how that'd work yet.
Somehow like this:

GameEvent:
package framework;

public class GameEvent {
 
 public final static GameEvent BUTTON_PRESSED=new GameEvent(0);
 public final static GameEvent BUTTON_RELEASED=new GameEvent(1);
 public final static GameEvent ANOTHER_EVENT=new GameEvent(3);
 public final static GameEvent WHATEVER=new GameEvent(4);
 
 private int i=0;
 
 private GameEvent(int i) {
   this.i=i;
 }
 
 public int getID() {
   return i;
 }
}


GameEventListener:
package framework;

public interface GameEventListener {
 void eventFired(GameEvent ge);
}


Your door object:
package framework;

public class MyDoor implements GameEventListener {
 
 public void eventFired(GameEvent ge) {
   if (ge==GameEvent.BUTTON_PRESSED) {
     System.out.println("Wooosssshhh!");
   }
   if (ge==GameEvent.BUTTON_RELEASED) {
     System.out.println("SSSSHHHTTTT");
   }
 }
}


Your button:
package framework;

import java.util.*;

public class MyButton {
 
 private Set listeners=new HashSet();
 
 public void addGameEventListener(GameEventListener ge) {
   listeners.add(ge);
 }
 
 public void removeGameEventListener(GameEventListener ge) {
   listeners.remove(ge);
 }

 public void press() {
   fireEvent(GameEvent.BUTTON_PRESSED);
 }
 
 public void release() {
   fireEvent(GameEvent.BUTTON_RELEASED);
 }
 
 private void fireEvent(GameEvent ge) {
   for (Iterator itty=listeners.iterator(); itty.hasNext();) {
     ((GameEventListener) itty.next()).eventFired(ge);
   }
 }
}


How to use it:
package framework;

public class Test {
 public static void main(String[] args) {
   MyDoor door=new MyDoor();
   MyButton button=new MyButton();
   
   button.addGameEventListener(door);
   button.press();
   button.release();
 }
}


But that's just an idea. You don't have to do it that way. In fact, i'm not doing that myself in Paradroidz but using a tighter coupling. Depends on your needs...

Raven

:shock:

Holy s***, whether or not I will use this method this tutorial definately teaches me a thing or two about Java! :D

I haven't had a lot of experience with interfaces and listeners, so you just saved me about half a weeks worth of reading Helge. Awesome.

I'll be testing this asap.

Cheers,
-Raven

Raven

Thank you both, Helge and rolz -- I combined both of your ideas keeping the object3D seperate in a GameObject class wich emplements a GameEventListener. It worked like a charm, and gave me much clearer view of how to puzzle all my smaller bits together that I've been experimenting with since I starting working with jPCT.

I have another question though that is perhapse not justifyable on these forums due to the fact that it derives from my inexperience working with full scale applications and especially 3d rendering.

But well, here it goes: I'm trying to get a grip on how I'll manage the animations that follow triggering, for example, a door object. I implemented the door triggering event where the Door(Object3D) was an md2 file with an "Opening" animation. Of course, the opening animation itself was carried out in the Door object and was therefore not in consistency with the frames in the main game. To explain: initiating the door opening animation caused the animation itself too be drawn too fast for the player to see.

In the official jPCT examples, this is solved by calling doMovement() once every loop in the main gameloop, hence the animations are always consisent with the main thread.

So what I'm currently thinking is to have a GameEventManager, which would keep a listing of all GameObjects as well as an AnimationQueue: a Hashlist that contains all the objects that require animating in the next iteration of the main game loop.

The main gameloop would therefore look something like this, with the addition of soundManager:

gameloop {

while (!quit) {
player.doMovement();
GameEventManager.animationQueue(); // If there is something that requires animation
SoundManager.playSounds(GameEventManager.soundQueue()); // Play any sounds that the gameEvents emit
}
}


So, to sum up, my question basically is: is this the way to go? Or is there some other method that's better when making 3D games? For example, should I be looking into threading each type of manager so it runs independantly?

Thanks for reading and helping :)

-Raven

EgonOlsen

Quote from: "Raven"
For example, should I be looking into threading each type of manager so it runs independantly?
I'm quite busy ATM, so the short answer to this is: NOOOOO!  :wink:
Don't let another thread than your main thread manipulate your game entities (at least not as long as it affects jPCT related stuff). It may happen at any time, even when jPCT is rendering them and that will cause all kinds of wierdness which are a pain to debug. Trust me...been there, done that...
Don't manipulate the Camera, the World, an Object3D etc. from inside another thread. Don't do it. Never! jPCT has a kind of locking implemented (has to be enable explicitly) to make it pseudo-threadsave, but that dates back to the times where i thought that i might be a good idea. It isn't...

Edit: Here's a short code snippet from Paradroidz' main loop. Looks similar to your approach. That doesn't mean that it's the only way to go, but it works for me.

 
             if (!gameState.showsSomeOverlay()) {

                 if (data.isAlive()) {
                    player.checkInvincible(storeTicks);
                    player.reEnergize(level, storeTicks);
                 }

                 level.updateShadowVolume();

                 eManager.enterCollisionMode();
                 player.enterCollisionMode();

                 level.processDoors(storeTicks);
                 level.processEnergyPads(storeTicks);
                 level.processDisruptors(storeTicks);

                 SimpleVector playerPos=player.getTranslation();
                 player.processProjectiles(storeTicks);
                 map.disableCollisionListeners();
                 if (data.isAlive() && !gameState.hasState(GameState.FINISHED)) {
                    move(storeTicks);
                 }

                 eManager.setPlayerPosition(playerPos);
                 eManager.calculateVisiblity(storeTicks);
                 eManager.moveEnemies(storeTicks);
                 map.enableCollisionListeners();

                 if (data.isAlive() && !gameState.hasState(GameState.FINISHED)) {
                    eManager.fireAtWill(storeTicks);
                    fire(storeTicks);
                    transfer();
                    level.setArrow(eManager.getClosestEnemyPosition(playerPos, false), storeTicks);
                 } else {
                    eManager.moveBulletsOnly(storeTicks);
                 }

                 eManager.leaveCollisionMode();
                 player.leaveCollisionMode();

                 player.processClouds(storeTicks);
                 player.synchronize();
                 level.processExplosions(storeTicks);
                 level.processBlastRings(storeTicks);
                 level.processParticles(storeTicks);

                 processCamera(storeTicks);
            }

raft

hello raven,

Quote from: "Raven"
So, to sum up, my question basically is: is this the way to go? Or is there some other method that's better when making 3D games? For example, should I be looking into threading each type of manager so it runs independantly?

as a rule of thumb, you should avoid threading whenever you can. it only complicates things and cost some performance (due to syncronization and context switching overhead). use threading where you have to do so (for example when use blocking i/o)

in karga, to simplify things, i targeted a constant fps. even collision detection and other non-render stuff doesnt cost much compared to rendering, so if i cannot reach targeted fps, i simply skip rendering for some frames and update the game state only. this method depends on measuring render time, something like this:


while (running) {
   long startTime = System.nanoTime();
   gameUpdate();
   gameRender();
   long elapsedTime = System.nanoTime() - startTime;

   if (elapsedTime < expectedElapsedTime) {
       // sleep here for some time
   } else {
       // do some gameUpdate without render
   }
}


with this approach, even on a slow machine updates stay closer to high targeted fps (50 for instance) so you can decide animation indexes etc depending on targeted fps

instead of controling animations and other things (movements etc) from a central location i've also defined a FrameListener interface which lots of my 3d objects implement. so they can 'take care of themselves'

public interface FrameListener {
   public void timeForNewFrame(/* pass here whatever you want like frame no, world etc*/);
   public void timeForRender(/* same as above */);
}



so what i do in gameUpdate and gameRender is:

private void gameUpdate() {
   for (FrameListener l : frameListeners) {
       l.timeForNewFrame(/* some parameters */ );
   }
}
private void gameRender() {
   for (FrameListener l : frameListeners) {
       l.timeForRender(/* some parameters */ );
   }
}


hope this helps :wink:

r a f t

EgonOlsen

Quote from: "raft"
instead of controling animations and other things (movements etc) from a central location i've also defined a FrameListener interface which lots of my 3d objects implement. so they can 'take care of themselves'
Yep, i'm doing it in a similar way. It's just that i have no common listener interface for that but "managers" on top of each entity-class that hold the references to all entities of a type and forces them to update/move/hide...whatever is needed. My timing works different. I'm measuring the time that has passed since the last frame in "ticks". A "tick" in Paradroidz is a 200th of a second IIRC. All my methods take these ticks as a parameter and act accordingly. For example: If i move an entity x units forward for one tick, i move it 8*x units forward if 8 ticks has passed since the last call. This has two drawbacks you have to be aware of:

1. all your algorithms have to be "tick"-able, which causes some extra work from time to time.

2. time taken in collision detection correlates with the length of the translation vector. This can cause the following: Game needs 2 ticks to update all entities, collision detection is called with 2 ticks, needs 1 tick itself due to that. So, you have 3 ticks for the next frame, call collision detection with 3 ticks, which now needs 2 ticks to complete and so on...that will result in a seconds per frame display over time. To avoid that, i'm limiting ticks to a max amount. If it superceeds this value, the game will simply slow down (i theory...it never happened for Paradroidz because collision detection is too fast)