Pages: [1] 2 3 ... 10
  Print  
Author Topic: Tiering vs Components  (Read 17931 times)
Offline (Male) Josh @ Dreamland
Posted on: May 08, 2010, 12:37:01 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
It looks like it's time once again for a poll.
Before voting, give Miky / Rusky a chance to present their idea of a Component system, as applicable to ENIGMA.
If you have a separate proposal, post it in the same format as I am about to post mine. This format should include the following:

- Code for an object called object0 containing a local "my_local"
----- This should include ALL code required to include necessary locals, particularly those needed throughout the rest of this demonstration
- Code for a simple collision function, check_collision(int id), returning bool, utilizing these hypothetical functions:
----- get_object_by_id(int), returning whatever the system requires (probably a pointer)
----- check_rotated_rectangle(x,y,bbox_left,bbox_right,bbox_top,bbox_bottom,image_angle); returning bool
- A create event code that shows message "Hello, world! I am at (<x>,<y>)", as it will look when compiled.

My code will have the official names in it, except where a substitute has been given above explicitly. It doesn't really matter what return types are if not specified.

DO NOT vote before a similar description is available for the Component system.

Moreover, I'd say requesting additional code on the behalf of either/any party is fair game.
« Last Edit: May 08, 2010, 12:41:46 PM by Josh @ Dreamland » Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) Josh @ Dreamland
Reply #1 Posted on: May 08, 2010, 12:41:48 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Tier System

Instantiable code:
Code: [Select]
struct ultimate_tier : collision_tier //This includes collision and all lower tiers
{
  //worthless locals shared by all objects go here.

  ultimate_tier(): collision_tier() { } //takes care of id and object_index, which are const; myevent_create is in this case inherited from the first tier.
  ultimate_tier(const unsigned ID, const int ObjectID): collision_tier(ID,ObjectID) { } //takes care of id and object_index, which are const
}

struct OBJ_object0 : ultimate_tier //This again includes collision and all lower tiers
{
  var my_local; //Here is the local we're using
 
  enigma::variant myevent_create();
 
  OBJ_object0(): ultimate_tier() { myevent_create(); } //takes care of id and object_index, which are const; myevent_create is in this case inherited from the first tier.
  OBJ_object0(const unsigned ID, const int ObjectID): ultimate_tier(ID,ObjectID) { myevent_create(); } //takes care of id and object_index, which are const
}

Collision code:
Code: [Select]
#include "collision_tier.h"
bool check_collision(int id)
{
    object_basic *o = get_object_by_id(int); //Fetch an instance of a pointer to the type of the lowermost tier from the instance array
    object_collision *c = (object_collision*) o; //Assume that it contains locals for our tier.
    return check_rotated_rectangle(c->x,c->y,c->bbox_left,c->bbox_right,c->bbox_top,c->bbox_bottom,c->image_angle); //Check and return
}

Create event code:
Code: [Select]
enigma::variant OBJ_object0::myevent_create()
{
  show_message("Hello, world! I am at (" + string(x) + "," + string(y) + ")");
}
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) Rusky
Reply #2 Posted on: May 08, 2010, 01:28:06 PM

Resident Troll
Joined: Feb 2008
Posts: 960
MSN Messenger - rpjohnst@gmail.com
View Profile WWW Email
Component System

Code: [Select]
struct SpriteComponent {
  virtual ~SpriteComponent(int _x, int _y) : x(_x), y(_y) {}
  virtual void draw() = 0;
 
  int x, y;
  int bbox_left, bbox_right, bbox_top, bbox_bottom;
  int image_angle, image_alpha; // ...
};

struct RasterSprite : public SpriteComponent {
  RasterSprite(Sprite& s, int x, int y) : sprite(s), SpriteComponent(x, y) {}
  void draw(); // pretend this
  Sprite& sprite;
};

Code: [Select]
struct CollisionComponent {
  virtual ~CollisionComponent() {}
  virtual bool check_collision(int id) = 0;
};

struct Colligma : public CollisionComponent {
  Colligma(SpriteComponent& s) : sprite(s) {}
  bool check_collision(int id);

  SpriteComponent& sprite;
  Sprite& mask_index;
};

// moved check_collision into the collision component
// it uses the sprites instead of manually unpacking all the fields
// check_rotated_rectangle would probably be part of Colligma
// you could replace it with a vector collision system in another component
bool Colligma::check_collision(int id) {
  Object& o = get_object_by_id(id);
  return check_rotated_rectangle(o.collision.sprite, sprite);
}

Code: [Select]
struct Object {
  Object(const unsigned _id, const int obj, SpriteComponent& s, CollisionComponent& c) : id(_id), object_index(obj), sprite(s), collision(c) {}
  virtual ~Object() {}
 
  int& x() { return sprite.x; }
  int& y() { return sprite.y; }
  // the rest of the accessors go here
 
  unsigned id, const int object_index;
  SpriteComponent& sprite;
  CollisionComponent& collision;
};

// just... pretend we have a real SpriteComponent implementation
struct OBJ_object0 : public Object {
  OBJ_object0(int x, int y, const unsigned id, const int obj) : sprite(enigma::get::my::sprite::somehow, x, y), collision(sprite), Object(id, obj, sprite, component) {}
  variant myevent_create();

  RasterSprite sprite;
  Colligma collision;

  var _my_local;
  var& my_local() { return _my_local; }
};

variant OBJ_object0::myevent_create() {
  show_message("Hello world! I am at(" + string(x()) + ", " + string(y()) + ")");
}
« Last Edit: May 09, 2010, 06:49:06 PM by Rusky » Logged
Offline (Male) retep998
Reply #3 Posted on: May 08, 2010, 01:30:05 PM

Member
Location: Where else?
Joined: Jan 2010
Posts: 248
MSN Messenger - retep998@charter.net AOL Instant Messenger - retep998 Yahoo Instant Messenger - retep998
View Profile Email
I understand Josh's code.
I don't understand Rusky's code.
Therefore I vote for tier system.
Logged
Offline (Male) Rusky
Reply #4 Posted on: May 08, 2010, 01:34:07 PM

Resident Troll
Joined: Feb 2008
Posts: 960
MSN Messenger - rpjohnst@gmail.com
View Profile WWW Email
I understand my abacus.
I don't understand my TI-83.
Therefore my abacus is better.
Logged
Offline (Male) RetroX
Reply #5 Posted on: May 08, 2010, 01:34:53 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Rusky, this is C++.

Not Java.

Java teaches people terrible programming techniques and is therefore terrible
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Male) Rusky
Reply #6 Posted on: May 08, 2010, 01:35:27 PM

Resident Troll
Joined: Feb 2008
Posts: 960
MSN Messenger - rpjohnst@gmail.com
View Profile WWW Email
I wrote C++ with great programming techniques. What's the problem?
Logged
Offline (Male) Josh @ Dreamland
Reply #7 Posted on: May 08, 2010, 01:40:40 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Problems:
- Lots of "pretending," which I will assume can be overlooked.
- "sprite.x", "sprite.y"; am I to traverse every pointer in the system to determine what locals are implemented? In the tier system, I just check ancestors, which is natural. Here, it seems I'm expected to check all members, too.

Perhaps it's also good to show an instance_create(), which is generated code. For this, we can assume the constructor takes an X and Y parameter as well as the other two (instance_create is designed for a 2D system, hence parameters X and Y), and adds the instance into the network for execution. If this is incompatible with a component system, give an alternative.

instance_create(): Tier System

Code: [Select]
void instance_create(int x, int y, int id)
{
  switch (id)
  {
    case object0:
        new OBJ_object0(x,y,enigma::max_id++,id);
      break;
  }
}

« Last Edit: May 08, 2010, 01:42:24 PM by Josh @ Dreamland » Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) Rusky
Reply #8 Posted on: May 08, 2010, 01:44:47 PM

Resident Troll
Joined: Feb 2008
Posts: 960
MSN Messenger - rpjohnst@gmail.com
View Profile WWW Email
-Eh, you did more pretending. You didn't even show the actual collision tier.
-x and y are built-ins. You can either 1) move them back out into Object or 2) parse them into sprite.x and sprite.y. As you saw, all non-built-ins go in OBJ_object0 exactly like your system.
-What does instance_create have to do with this? I just left off the constructor overload, which shouldn't matter because you just pretended it and it's not crucial to the component idea.
Logged
Offline (Male) Josh @ Dreamland
Reply #9 Posted on: May 08, 2010, 01:48:52 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Here is the snippet, as functions right now in ENIGMA:
Code: [Select]
#ifndef _COLLISIONS_OBJECT_H
#define _COLLISIONS_OBJECT_H

#include "transform_object.h"

namespace enigma
{
  struct object_collisions: object_transform
  {
    //Bit Mask
      var mask_index;
      var  solid;
   
    //Bounding box
      var bbox_top;
      var bbox_bottom;
      var bbox_left;
      var bbox_right;
   
    //Constructors
      object_collisions();
      object_collisions(unsigned, int);
      virtual ~object_collisions();
  };
}

#endif

I can not move them back into Object, as that will create an access problem and/or screw up your component. They will be accessing different instances of like-named variables.
How do I know they are sprite.x and sprite.y? What tells me that?
Yes, that was obvious.

Also, instance_create shows me from where you are exhuming the initial parameters to your constructors.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) RetroX
Reply #10 Posted on: May 08, 2010, 01:55:27 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
I wrote C++ with great programming techniques. What's the problem?
No, you didn't.

Creating loads of objects purely for organization is not good programming technique.

There are easier, more efficient ways of organizing things, and in fact, it removes readability rather than adds it.
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Unknown gender) Micah
Reply #11 Posted on: May 08, 2010, 02:00:13 PM

Resident Troll
Joined: May 2008
Posts: 129

View Profile
There are easier, more efficient ways of organizing things, and in fact, it removes readability rather than adds it.
Please show us these ways, retaining the flexibility of this one and adding readability as you claim they do.
Logged
Offline (Male) Josh @ Dreamland
Reply #12 Posted on: May 08, 2010, 02:01:01 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Retro: The point only seems to be organization on this level; this is about adding and removing functionality with as little a ripple as possible.

So yes, I'm still waiting on an explanation for the origin of "sprite." and the constructor parameters in all that mess.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) luiscubal
Reply #13 Posted on: May 08, 2010, 04:01:38 PM
Member
Joined: Jun 2009
Posts: 452

View Profile Email
Both systems are pretty simple to understand:

Josh's tiers: Think of a stack of pizzas. Each pizza is functionality. The graphics pizza, the collisions pizza, etc. On top of everything, you can put your object pizzas.
Removing/Replacing tiers in the middle might be problematic, although Josh seems to consider those problems edge cases and, therefore, unlikely to be harmful and/or too much inconvenient.

Rusky's components: Instead of pizzas on top of each other, think a bunch of blocks side by side. Because they are not on top of each other, they will not fall if you take on from the middle.
On top of those blocks is the object block.
Rusky's system is designed so that replacing blocks is embarrassingly easy(and removing blocks isn't too complex), this at the expense of a few extra CPU cycles, which Rusky seems to consider irrelevant because CPU cycles are very fast and, therefore, the difference is unlikely to be noticeable.

Code: [Select]
Creating loads of objects purely for organization is not good programming technique.I have to disagree. Abstractions are part of computer science and engineering.
Otherwise, we would still be coding the computer directly, without programming languages not even kernels.
Logged
Offline (Male) Rusky
Reply #14 Posted on: May 08, 2010, 04:08:59 PM

Resident Troll
Joined: Feb 2008
Posts: 960
MSN Messenger - rpjohnst@gmail.com
View Profile WWW Email
Added the id stuff and a bit of sprite implementation. I don't see why that confused you.

Retro: The *Component classes are interfaces. They're just there to be the parent of all possible implementations. A sprite component could hold a DX handle, a GL handle, some vector data, etc. and implement its draw method accordingly.

Individual objects (like OBJ_object0) create their own components as members or on the heap or wherever you want. They get passed to Object's constructor, and other Object constructor parameters go directly there along with them rather than being passed up through all the tiers.
Logged
Pages: [1] 2 3 ... 10
  Print