Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1412012 Posts in 69461 Topics- by 58492 Members - Latest Member: Gods Of Fire

July 03, 2024, 07:38:58 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsMoonQuest
Pages: 1 ... 107 108 [109] 110 111 ... 189
Print
Author Topic: MoonQuest  (Read 1354619 times)
siskavard
Guest
« Reply #2160 on: December 17, 2013, 09:22:35 PM »

Every time I come back here to check in on Moonman, the screenshots just get more and more lush and beautiful!
Logged
kleiba
Level 2
**



View Profile
« Reply #2161 on: December 18, 2013, 11:28:47 AM »

Update: For development purposes I added a better system for spawning items and creatures. Previously I had each letter mapped to something, e.g., 't' spawned a torch, 'r' a door, etc. This became ridiculuous with lots of items, so now I just press 'q' and start typing a name of something. It also suggests and autocompletes. So to spawn a hanging lantern, I press q,h,a,tab, then enter.

Ahhh, nothing like procrastination! You must have gone through grad school, I suppose, to acquire such perfectionism!
Logged
happymonster
Level 10
*****



View Profile WWW
« Reply #2162 on: December 18, 2013, 01:05:48 PM »

Why not just use a mouse and a clickable list?
Logged
kamac
Level 10
*****


Notoriously edits his posts


View Profile
« Reply #2163 on: December 18, 2013, 01:42:50 PM »

Because when moonman gets to have more and more items, think how silly would it be to pick an item from a huge list, rather than just type it's name!

...

Well, atleast that's my point of view.
Logged

jctwood
Level 10
*****



View Profile WWW
« Reply #2164 on: December 18, 2013, 03:35:10 PM »

Can you wear the heads of the animals you kill in the game? I have always wanted to play a game where I can wear trophies rather than hang them on my wall...
Logged

eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #2165 on: December 18, 2013, 04:22:31 PM »

@kamac You're right, although a clickeable list or grid would be ok for now. I just preferred the typing approach, and I can also do item/sword*4 to spawn 4 swords.

@desiderata Sounds like a good idea. Actually I have no idea why the animal masks are in there atm, I think I got bored one day and just chucked them in there.
Logged

jctwood
Level 10
*****



View Profile WWW
« Reply #2166 on: December 18, 2013, 05:02:08 PM »

Well it would be very interesting to see some sort of wearable trophy from harder to kill animals.
Logged

Rusk
Level 1
*


View Profile
« Reply #2167 on: December 21, 2013, 06:40:34 PM »



The chairs should have seat belts. Well, hello there!
Logged
rundown
Level 5
*****



View Profile WWW
« Reply #2168 on: December 29, 2013, 11:07:24 AM »

Are you able to break the vases?
I just want to pissof the inkeeper!  Cheesy
Logged

eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #2169 on: January 02, 2014, 07:25:16 PM »

Okay, the voting is now over. I've counted everything, twice, and I have the results here.

...

In second place we have another impressive looking platformer with the creepiest ever-smiling character you'll come across, it's Moonman!


Thanks everyone who voted for MM for the best TIG devlog. It's awesome to have your support, and being voted 2nd best devlog is just awesome. Tears of Joy

I've been on a break from MM for the last couple of weeks, catching up on some gaming, and having fun playing around with Unity, Dart, and other things. 2013 was a long and tedious year for me, and I hope that in 2014 I can complete Moonman. But for the next two months at least I'll be working towards getting the feature demo/beta ready.

I hope everyone had a great new year. Beer!
Logged

_bm
Level 2
**


i'm so confused


View Profile WWW
« Reply #2170 on: January 02, 2014, 09:06:57 PM »

Oh man that's incredible!  Shocked
Good luck in 2014!
Logged

siskavard
Guest
« Reply #2171 on: January 02, 2014, 09:31:43 PM »

Congraaaats
Logged
jazz_buddha
Level 0
*



View Profile
« Reply #2172 on: January 08, 2014, 04:07:32 PM »

Great stuff, can't wait for the game to come out.
Apologies if this has already been asked, but will the game be available on linux?
Logged
kleiba
Level 2
**



View Profile
« Reply #2173 on: January 09, 2014, 01:24:54 PM »

Nicely done!

I missed the election as I was hanging out at Marsha's parents' house for a week, but you would have had my vote for sure!

Cheers, and all the best for your 2014, too.
Logged
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #2174 on: January 13, 2014, 10:44:29 PM »

@jazz_buddha Thx. It'll be released on linux eventually Smiley
@kleiba Cheers mate!

HELLO! This post has also been posted to my blog, with better code formatting.

Update: Well it's been a while, but here's my first update for 2014. I haven't touched MM code for a month but instead have been designing and implementing a cleaner and simpler entity system. I've been meaning to do this for quite a while now, but after using Unity and looking at other bits of code like entityx I decided to finally attempt it. This is helped in part by the new c++ support in VS2013. The system is also data-oriented -- all components and entities are tightly packed in memory. I use a similar free list setup as in MM. I also had to use some c++ techniques I haven't used before, such as variadic templates and typelists. But that is all behind the scenes, this is what the API looks like:

Code:
EntitySystem es;

// Create an entity
// and add some components
Entity& e = es.create();
e.add(Transform(4,5));
e.add(Health(10));
e.add(Physics(0,-10));
e.add(ShortDescription("Ben"));
e.add(Description("An architecture-obsessed programmer."));

// Create another entity
// with different components
// this time using intializer_list shorthand
Entity& chest = es.create();
chest.add(Transform(-4.5f, 0.8f));
chest.add(Inventory{
  { Item::SWORD },
  { Item::POTION, 4 },
  { Item::POTION, 3 },
  { Item::ARROW, 64 }
});

// If we need to keep a reference to an entity
// then we use ID's (uint32s)
ID chestId = chest.id;

Code:
// Then later on somewhere we can get the entity
// and do something with it, e.g.,
if (es.has(chestId)){
  Entity& ch = es.lookup(chestId);

  // Shift the chest one unit horizontally
  Transform& tr = ch.get<Transform>();
  tr.x += 1;
}

Code:
// Iterating through all entities
// can be done with a range-based for loop
for (Entity& e : es.entities()){
  std::cout << e;
}

Code:
// Likewise, we can iterate through all 
// components of a particular type. For
// example a PhysicsSystem might want to
// process all the Physics components.

for (auto p: es.components<Physics>()){
  // Apply viscocity
  p.vy *= 0.9f;
  p.vx *= 0.9f;
 
  // Move entity
  Entity& e = es.lookup(p.entity);
  Transform& tr = e.get<Transform>();
  tr.x += p.vx;
  tr.y += p.vy;
}

Code:
// Everything is done with references
// if e doesn't contain C, then
// e.get<C>() returns a blank component
// (which can be checked for validity)
Entity& e = es.lookup(id);
Health& health = e.get<Health>();
health.health = 666;
if (health){
  // It's valid
}

Code:
// Components themselves are just structs
// The CRTP gives them a unique class id
// that is used to store them in EntitySystem
struct Health: public Component<Health> {  
  float health;
  bool poisoned;
  Health(float health = 0.f, bool poisoned = false) :health(health), poisoned(poisoned){}

  std::string what() const; // human readable rep
  static const char* Name(); // name
};

Code:
// The logic of a component is implemented
// in a system. e.g., the HealthSystem might
// be responsible for decreasing a character's
// health if they are poisoned.

class HealthSystem : public ISystem {
public:
  bool implements(int componentIndex) override {
    return Health::Index()==componentIndex;
  }

  void setup(Entity& e) override {
    e.get<Health>().health = 100;
  }

  void update(EntitySystem& es, double dt) override {
    for (Health& h : es.components<Health>()){
      if (h.poisoned){
        h.health -= 0.1f * (float)dt;
        if (h.health <= 0){
          // Create KILL EVENT
        }
      }
    }
  }
};

Besides this I've also been thinking about having Script components. These will be a special type of component that uses traditional polymorphism and lambdas to offer a concise and easy way to implement special behaviours. For example, I could attach a custom c++ poison script to a entity like this:

Code:
Script* newPoisonerScript(Entity& e){
  // variables to be captured by the lambdas
  float* duration = new float(0.f);
  float* timer = new float(0.f);

  auto poisoner = new Script("poisoner");

  poisoner->destroy = [duration, timer](Entity& e){
    Health& health = e.get<Health>();
    if (health) health.poisoned = false;
    delete duration;
    delete timer;
  };

  poisoner->start = [](Entity&e){
    Health& health = e.get<Health>();
    if (health) health.poisoned = true;
  };

  poisoner->update = [timer, duration](Entity& e, double dt){
    *duration += (float) dt;
    Health& health = e.get<Health>();
    if (health){
      if (health.poisoned){
        *timer -= (float) dt;
        if (*timer < 0){
          health.health -= 1;
          *timer = 1.0f;
        }
      }
    }
  };

  poisoner->finished = [duration](Entity& e){return *duration>1.5f;};
  return poisoner;
}

Anyway, once I've finalised the new system it's going to take a couple of days to incorporate it into Moonman, but I definitely think it's worth the deviation. Basically it means that I'll turn macro'ed code that looks like this (see devlog for explanation of how it works):

Code:
ATTRIB(e, x) += 0.1f;
bool isOnGround = ATTRIB_OR(e, is_on_ground, false);
bool hasPhysics = HAS_ATTRIB(e, is_physics);

Into nicely autocompleting code that looks like this:

Code:
e.get<Transform>().x += 0.1f; 
// or with shorthand
e.transform().x += 0.1f;
// and
bool isOnGround = e.get<Physics>().isOnGround;
bool hasPhysics = e.has<Physics>();
« Last Edit: January 13, 2014, 10:57:54 PM by eigenbom » Logged

Rusk
Level 1
*


View Profile
« Reply #2175 on: January 13, 2014, 11:27:29 PM »

Beautiful and super interesting. I have been trying a few times but never been able to write a component system that I'm happy with.

For one thing, I always end up with component.addToEntity() rather than entity.add(component). Do your store a bunch of entity "container objects" or are they generated as needed, like tellers for a component bank? Grin

The templates are something I'll have to look at as well. I've ended up with lots of typecasting everywhere.

Logged
Bandreus
Level 3
***


View Profile WWW
« Reply #2176 on: January 14, 2014, 12:55:56 AM »

Entity systems are great, but there are sooo many ways to implement them, and info available online is so scattered/unorganized, wrapping one's head around the concept can be a very hard and frustrating task.

I've been implementing my own twist on the concept in HaXe (heavily drawing from Artemis ES and HxE) in my spare time.

I'd definitely like to hear more about your own implementation (mainly thinking about the way you implement internal storing of components/systems, how you pack things for nicer memory access/cache friendliness, etc.).

Beautiful and super interesting. I have been trying a few times but never been able to write a component system that I'm happy with.

For one thing, I always end up with component.addToEntity() rather than entity.add(component). Do your store a bunch of entity "container objects" or are they generated as needed, like tellers for a component bank? Grin

The templates are something I'll have to look at as well. I've ended up with lots of typecasting everywhere.

ESs are like icecream I suppose, to everyone their favorite flavor.

Usually, you want the Entity System (i.e. the class implementing how entities, components and systems are dealt with internally) to handle coupling components to the entities owning them. Remember Entities are just a globally unique identifier, while components are entirely made up of pure data. Unless unimportant implementation aspects.

The way references to components are internally stored should be transparent to the way you use your ES's API, but for the sake of it, let's assume you use a struct akin to a dictionary. So, if you want to retrieve the Physics component for the entity 42, you would do something like (written in pseudo-pseudo-code)

Code:
myComponent = ES.getComponent(42, PhysicsComponent);

Now, it's very common to use a wrapper Class for entities, as it makes code more tidy and less verbose. So when you see something like

Code:
e = ES.getEntity(42);
e.addComponent(myComponent);

All that's really happening behind the scenes (well, at least in most implementations I've seen) is the addComponent() method from the pseudo-entity class calling the equivalent routine from the Entity System API. Something like;

Code:
Class PseudoEntity {

   Int MyEntityID;
   ES EntitySystemOwningMe;

   ...

   public function addComponent(newComponent) {
      EntitySystemOwningMe.addComponent(MyEntityID, newComponent);
   }

   ...

}

Remember an Entity is not an object, nor a class, nor anything fancy. It's just an ID (most often than not an Int, UInt, or w/e).  The PseudoEntity class is just a convenient way to access part of the architecture's functionality, and often times also to allow for more elegant code and less typing.

Again, to each their own flavor of Entity System, so don't take this short blurb as the-definitive-way-to-implementing-an-ES.
Logged

SleepyRhino
Level 0
*


View Profile
« Reply #2177 on: January 14, 2014, 07:04:48 AM »

Looks similar to the way I have implemented an ECS, found it saves so much time when prototyping new entities.

Code:
Entity* e = em->Create(Groups::Player);
e->Attach(new ControlComponent());
// So on and so on

Code:

unsigned int id = 5;
Entity* e = em.Get(id);


Code:
ControlComponet* c = e->GetComponent<ControlComponet>(Components::Control);

I do like the idea of moving my components to structs.
Logged
kleiba
Level 2
**



View Profile
« Reply #2178 on: January 14, 2014, 10:35:27 AM »

eigenbom's New Year's resolutions 2014

  • Get in shape.
  • Quit smoking.
  • Finally finish Moonman. Write new entity system.
  • Eat healthier.
  • ...

 Well, hello there!
Logged
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #2179 on: January 14, 2014, 12:23:46 PM »

For one thing, I always end up with component.addToEntity() rather than entity.add(component). Do your store a bunch of entity "container objects" or are they generated as needed, like tellers for a component bank? Grin

I basically do what Bandreus said. Off the top of my head the entity is something like:
Code:
struct Entity {
  ID id;
  ID components[MAX_COMPONENTS];
  EntitySystem* es;

  template <typename C>
  void add(C& c){
    // Index() is unique for each component class
    components[C::Index()] = es->addComponent<C>(id, c);
  }

  ...
};
And the entity system is something like..
Code:
class EntitySystem {
...
  PackedArray<Entity> entities;
  std::vector<PackedArrayBase*> components;

  template <typename C>
  ID addComponent(ID id, C& c){
    return static_cast<PackedArray<C>*>(components[C::Index()])->add(c);
  }
};
.. where there is a separate PackedArray for each component. The PackedArray itself has a simple ID based interface, and preallocates enough space for 0xffff T's.
Code:
template <typename T>
class PackedArray {
  ...
  ID add(T& t);
  void remove(ID id);
  T& lookup(ID);
};

Logged

Pages: 1 ... 107 108 [109] 110 111 ... 189
Print
Jump to:  

Theme orange-lt created by panic