Created
April 25, 2015 20:59
-
-
Save nasser/7400f6afac202b3a64d3 to your computer and use it in GitHub Desktop.
QuadC - Final
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // ECS.cpp | |
| // quadc_two | |
| // | |
| // Created by Ramsey Nasser on 4/25/15. | |
| // | |
| // | |
| //////// framework | |
| #include "ECS.h" | |
| // to add the component, extract its name and assign that index in the map | |
| // to the value of the component | |
| void ecsEntity::addComponent(ecsComponent *c) { | |
| components[c->name()] = c; | |
| } | |
| // to retrieve a component, look it up by name in the map | |
| ecsComponent* ecsEntity::getComponent(string name) { | |
| return components[name]; | |
| } | |
| // to remove a component, remove it by name from the map | |
| void ecsEntity::removeComponent(string name) { | |
| components.erase(name); | |
| } | |
| // to run an entity, loop through every component in the components map | |
| // and call run on it, passing this (the current object, an entity) to the | |
| // run method. this allows each component to modify the entity they are | |
| // attached to | |
| void ecsEntity::run() { | |
| // looping though a map, you are given key,value pairs. the begin, end, ++ | |
| // syntax here is c++ iterators, which is what you use to move through | |
| // a datastructure like a map | |
| for(auto pair = components.begin(); pair != components.end(); pair++) { | |
| // pair->first refers to the key, in our case the string that contains | |
| // the name of the component. pair->second refers to the value, in our | |
| // case the actual component object | |
| ecsComponent* theComponent = pair->second; | |
| // call run, passing the entity | |
| theComponent->run(this); | |
| } | |
| } | |
| //////// components | |
| // run method implememtation for circle draw component | |
| void ecsCircleDrawComponent::run(ecsEntity *e) { | |
| // grab the position component from the entity e, cast it to ecsPositionComponent | |
| // so c++ does not complain, then extract its position value | |
| ofVec2f p = ((ecsPositionComponent*)e->getComponent("position"))->position; | |
| // draw a circle at the position just extracted with the radius that the | |
| // circle draw component maintains | |
| ofCircle(p, radius); | |
| } | |
| // run method implememtation for chaser component | |
| void ecsChaserComponent::run(ecsEntity *e) { | |
| // grab the position component from the entity e and cast it to ecsPositionComponent | |
| ecsPositionComponent* pc = ((ecsPositionComponent*)e->getComponent("position")); | |
| // update its position value to a value between the current position value and the target | |
| // this is an implementation of linear interpolation | |
| pc->position.set(pc->position.x * speed + target.x * (1 - speed), | |
| pc->position.y * speed + target.y * (1 - speed)); | |
| } | |
| // run method implememtation for mouse control component | |
| void ecsMouseControlComponent::run(ecsEntity *e) { | |
| // grab the chaser component from the entity e and cast it to ecsChaserComponent | |
| ecsChaserComponent* chaser = ((ecsChaserComponent*)e->getComponent("chaser")); | |
| // update the target of the chaser component to the current mouse position | |
| chaser->target.set(ofGetMouseX(), ofGetMouseY()); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // ECS.h | |
| // quadc_two | |
| // | |
| // Created by Ramsey Nasser on 4/25/15. | |
| // | |
| // | |
| #ifndef quadc_two_ECS_h | |
| #define quadc_two_ECS_h | |
| #include "ofMain.h" | |
| //////// framework | |
| // forward declare ecsEntity so that ecsComponent does not freak out | |
| class ecsEntity; | |
| // base class for all components | |
| class ecsComponent { | |
| public: | |
| // every component must be able to produce its own name | |
| // the = 0 means that there is no default, and writing a | |
| // component without a name() method is an error | |
| virtual string name() = 0; | |
| // every component can optionally implement a run method | |
| // if present, it will be used to update the entity that | |
| // the component is attached to. the { } means that the | |
| // default implementation is to do nothing, and that a run | |
| // method is not required | |
| virtual void run(ecsEntity* e) { }; | |
| }; | |
| // class for all entities | |
| class ecsEntity { | |
| public: | |
| // components can be added to an entity | |
| void addComponent(ecsComponent* c); | |
| // components can be returned from an entity | |
| ecsComponent* getComponent(string name); | |
| // components can be removed from an entity | |
| void removeComponent(string name); | |
| // entities can be run, running all their components as a result | |
| void run(); | |
| private: | |
| // internally, components are maintained in a map from their name to their instance | |
| // e.g. "position" -> the actual position component object | |
| std::map<string, ecsComponent*> components; | |
| }; | |
| //////// components | |
| // position component encodes the position of an object | |
| // no run logic, just data | |
| class ecsPositionComponent : public ecsComponent { | |
| public: | |
| virtual string name() { return "position"; } | |
| ofVec2f position; | |
| }; | |
| // circle drawing component draws a circle at the position component's position | |
| // maintains radius as data | |
| class ecsCircleDrawComponent : public ecsComponent { | |
| public: | |
| virtual string name() { return "circleDraw"; } | |
| float radius; | |
| virtual void run(ecsEntity* e); | |
| }; | |
| // chaser component updates the position component's position to move closer to a target | |
| // maintains the target position and speed as data | |
| class ecsChaserComponent : public ecsComponent { | |
| public: | |
| virtual string name() { return "chaser"; } | |
| ofVec2f target; | |
| float speed; | |
| virtual void run(ecsEntity* e); | |
| }; | |
| // mouse control component upadates the chaser component to target the mouse | |
| class ecsMouseControlComponent : public ecsComponent { | |
| public: | |
| virtual string name() { return "mouse"; } | |
| virtual void run(ecsEntity* e); | |
| }; | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "ofApp.h" | |
| //-------------------------------------------------------------- | |
| void ofApp::setup(){ | |
| // create a new entity | |
| ecsEntity* e = new ecsEntity(); | |
| // create and attach a position component | |
| ecsPositionComponent* positionComponent = new ecsPositionComponent(); | |
| positionComponent->position.set(42, 13); | |
| e->addComponent(positionComponent); | |
| // create and attach a circle draw component | |
| ecsCircleDrawComponent* circleDraw = new ecsCircleDrawComponent(); | |
| circleDraw->radius = 30; | |
| e->addComponent(circleDraw); | |
| // create and attach a chaser component | |
| ecsChaserComponent* chaser = new ecsChaserComponent(); | |
| chaser->target.set(ofGetWidth(), ofGetHeight()); | |
| chaser->speed = 0.9; | |
| e->addComponent(chaser); | |
| // create and attach a circle draw component | |
| e->addComponent(new ecsMouseControlComponent()); | |
| // add the entity to app | |
| addEntity(e); | |
| // create a DIFFERENT entity | |
| ecsEntity* e2 = new ecsEntity(); | |
| // create and attach a different position component | |
| ecsPositionComponent* positionComponent2 = new ecsPositionComponent(); | |
| positionComponent2->position.set(100, 50); | |
| e2->addComponent(positionComponent2); | |
| // create and attach a different circle draw component | |
| ecsCircleDrawComponent* circleDraw2 = new ecsCircleDrawComponent(); | |
| circleDraw2->radius = 50; | |
| e2->addComponent(circleDraw2); | |
| // add the second entity to the app | |
| addEntity(e2); | |
| } | |
| // adding an entity pushes it to the entities vector | |
| void ofApp::addEntity(ecsEntity* e) { | |
| entities.push_back(e); | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::update(){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::draw(){ | |
| // every frame, loop through the entities vector and tell each entity to run | |
| for(int i=0; i<entities.size(); i++) { | |
| entities[i]->run(); | |
| } | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::keyPressed(int key){ | |
| // when a key is pressed, create a new entity and add it to the scene | |
| ecsEntity* e = new ecsEntity(); | |
| ecsPositionComponent* positionComponent = new ecsPositionComponent(); | |
| positionComponent->position.set(ofRandom(1000), ofRandom(1000)); | |
| e->addComponent(positionComponent); | |
| ecsCircleDrawComponent* circleDraw = new ecsCircleDrawComponent(); | |
| circleDraw->radius = ofRandom(50); | |
| e->addComponent(circleDraw); | |
| addEntity(e); | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::keyReleased(int key){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::mouseMoved(int x, int y ){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::mouseDragged(int x, int y, int button){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::mousePressed(int x, int y, int button){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::mouseReleased(int x, int y, int button){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::windowResized(int w, int h){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::gotMessage(ofMessage msg){ | |
| } | |
| //-------------------------------------------------------------- | |
| void ofApp::dragEvent(ofDragInfo dragInfo){ | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include "ofMain.h" | |
| #include "ECS.h" | |
| class ofApp : public ofBaseApp{ | |
| public: | |
| void setup(); | |
| void update(); | |
| void draw(); | |
| void keyPressed(int key); | |
| void keyReleased(int key); | |
| void mouseMoved(int x, int y ); | |
| void mouseDragged(int x, int y, int button); | |
| void mousePressed(int x, int y, int button); | |
| void mouseReleased(int x, int y, int button); | |
| void windowResized(int w, int h); | |
| void dragEvent(ofDragInfo dragInfo); | |
| void gotMessage(ofMessage msg); | |
| // add entity to the game | |
| void addEntity(ecsEntity* e); | |
| // the internal storage of entities | |
| std::vector<ecsEntity*> entities; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment