I think for tonight’s live stream (9 PM GMT-4), I will be continuing sound integration by adding sound effects to in-game objects.
This will involve creating some sound components, a sound system, etc… good ECS stuff.
I will also have to make some test objects + a test tool for placing them to be able to place some sound-producing objects into the world to test. That’s probably where I will start the night so that I have some test objects to work with for the other parts.
I’ll also go over the changes I made on top of what was done last week to make it “Real” after kind of hacking it in last session.
Made it as far as getting some test objects scripted for placing+manipulating a “speaker” test object… and getting the base entity container hooked up to detect those entities. I’ll add chapters to the video in a minute.
Next week I’ll be finishing that out with actually playing the sound properly filtered by distance from player, etc… that seemed like a deep enough topic that it would be good to go into instead of just cutting/pasting it all from a different class.
I have a few questions, not directly related to the sound system though.
1- Is there a reason you are not defining the default components in the object type definition script? So whenever you want to instantiate a new object you could just call createEntity(typeName, position).
2- Which system(s) listens for the ObjectTypeInfo component and what it does?
3- Also, in the video, you set an ObjectTypeInfo(“Speakers”) component for the speaker entity when placing it with the sound wand, but I do not see where you have defined the “Speakers” type in the script. Is it perhaps registered previously?
By the way, will be very interested in a technical live stream talking about the object type definitions, how they are structured, how the object type hierarchy works, what createType method does behind the scene, how you are instantiating them, what the “typeVars” are for and how they are different from components.
In the video it may have been hard to see but there is a big FIXME comment that I mention about how I need to standardize object creation.
No system “listens” for the component but it’s how the object action stuff finds the object type so it knows what actions there are. It’s what associated an entity with those createType(“Foo”) things defined in scripts.
I did not define it yet. I think I mentioned that in passing. I’m giving it a type but the type doesn’t exist yet. Not mentioned is that it will pick up the default object type which does have some basic actions.
I’ll keep in mind to maybe do one someday. Mostly I’m trying to keep it semi-interesting for Mythruna players while still getting a little technical because that’s what I’m working on right now. Not sure I’m being successful at either.
typeVars contains runtime variables associated with the type itself. Types are defined at runtime and are not stored as entities. (They are not game objects.) So you can think of it like class variables… the things that exist for every Axe or every Sword and not just a particular instance of Axe or Sword. It would be wasteful to store that information on every instance.
The object action system is part of MOSS and so will be open sourced. Mythruna defines a relatively thing groovy API on top of that which gives the createType() closure and some others. Basically it creates and registers an ObjectType (Java class) which can have a list of actions and super types.
I will definitely be providing more information on that as I get closer to releasing MOSS publicly next year.
I’m curiuos, in your case, would it be inside the ObjectType script where you also defined the actions or it will be in a separate place?
Can game systems use those typeVars?
Am I understanding it right that at runtime there is just one instance of an ObjectType class created per type name and not per entity instance, right? Or let me ask it like this, if you have 100 entities in the scene that all have the same type, then they all will use the same reference to the ObjectType class instance for running actions. Yes?
By the way, do you have an abstraction class for “GameObject” in your ES approach?
In my case I have an abstract class “GameObject”. For each object type I extend GameObject and there I register actions and set components. Do you think this is a bad practice from ES perspective?
For example here is how CarrotPlant object looks like:
public class CarrotPlant extends GameObject {
public static final int ID = 6002;
private int stage;
/**
* Called once, if there is no ObjectType component presents on the entity. (when the object is spawned)
*/
@Override
public void setupPersistentData(EntityId id, EntityData ed) {
ed.setComponents(id,
ObjectType.create(ID, CarrotPlant.class.getSimpleName(), ed),
new GrowthPercentage(0),
new GrowthStage(0)
);
}
@Override
public void initialize(EntityId id, EntityData ed, GameSystemManager manager) {
super.initialize(id, ed, manager);
setComponents(
ViewType.create(FarmPlant.class.getSimpleName(), ed),
ModelInfo.create("Models/FarmPlant/2.j3o", ed),
new GrowthSpeed(1000)
);
stage = getComponent(GrowthStage.class).getValue();
if (stage == 3) {
setComponent(new PickupRadius(0.4f));
}
// Register actions
register(OnGrowth.class, onGrowth);
register(Take.class, take);
}
OnGrowth onGrowth = percent -> {
if (percent == 100) {
setComponents(new PickupRadius(0.4f), new GrowthStage(stage = 3));
} else if (percent >= 60) {
if(stage != 2) setComponent(new GrowthStage(stage = 2));
} else if (percent >= 10) {
if(stage != 1) setComponent(new GrowthStage(stage = 1));
}
};
Take take = takenBy -> {
if (stage == 3 && getComponent(Decay.class) == null) {
systems.get(GameObjects.class).get(takenBy).ifPresent(Inventory.class, inv -> {
inv.add(Carrot.class, 3);
setComponent(new Decay());
});
}
};
}
Yes, that’s basically what I’m doing in the video. Defining actions on the SoundWand ObjectType.
Yeah, it’s just a hashmap on ObjectType.
There is an ObjectTypeRegistry the contains all of the ObjectType instances. So, yes, if I have a hundred axe entities then there is only one “Axes” ObjectType.
But also not: the ObjectType stuff not ES-specific. It doesn’t know anything about entity systems or groovy, etc… That stuff can be integrated separately.
No. Things are just entities. I don’t really have a use for bringing back OOP Java objects into it.
Even when default components it’s likely to just be another action to init an entity… maybe a list of components in the typeVars. I’ve only had to create two objects in scripts so far so I’ll decide when I have a few more different use-cases.
For reference, here is a bit of the base type that other types can inherit from to get a standard ‘name’ property and a standard ‘Look’ action: https://imgur.com/zrxJ8ma.png
Note: some of that API will get cleaned up more at some point as I’m not really happy with the templating.
But any ObjectType with that type as one of its super types will let me do obj.name to get the name and call obj.run(“Look”) to send the description to the player.
Edit: you can also see all of the commented out logging as I wrestled with closure environment.
Ok, things get more clear to me now. Thanks for your help.
Byt the way, sound was missing in my game as well, following your devlog video I got excited and went ahead and added the sound state into my game as well. Looking forward to watch the next stream