I have a class called LoaderAnimation, which basically displays a sequence of 112 images when particles on the screen are hovered.
I was initially creating a loader animation inside a particle class, but every time I would create 25 particles it meant that 112 * 25 = 2800 images would be loaded on memory. Which is very inefficient.
The problem is that the loader animation has some logic when hovering and not hovering on the particles. If the user finishes the loader animation, it should trigger and action that reveals a menu. If the user hovers but doesn't finish the loader animation it should be reseted.
So here is the code for LoaderAnimation class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#pragma once
#include "ofMain.h"
class LoaderAnimation {
public:
LoaderAnimation();
void setup();
void update();
void draw(float &_x, float &_y);
vector <ofImage> loaderImages;
bool hasPassedValue, isLoadingCompleted, bFrameIndependent;
float rotationSpeed, sequenceFPS;
int frameIndex, appFPS;
unsigned int rotationCounter;
private:
};
#include "LoaderAnimation.h"
LoaderAnimation::LoaderAnimation(){
}
//-------------------------------------------------------------------
void LoaderAnimation::setup(){
ofDirectory dir;
int nFiles = dir.listDir("assets/9_loader");
if(nFiles) {
for(int i=0; i<dir.numFiles(); i++) {
// add the image to the vector
string filePath = dir.getPath(i);
loaderImages.push_back(ofImage());
loaderImages.back().loadImage(filePath);
}
} else printf("Could not find image loader #1's folder (in Boid class) \n");
for(int i=0; i<loaderImages.size();i++){
loaderImages[i].resize(loaderImages[i].width/2,loaderImages[i].height/2);
}
// this toggle will tell the loader sequence
// to be indepent of the app fps
bFrameIndependent = true;
// this will set the speed to play the animation back.
// we set the default to 24fps
sequenceFPS = 0;
frameIndex = 0;
rotationCounter = 0;
rotationSpeed = 1;
isLoadingCompleted = false;
}
//-------------------------------------------------------------------
void LoaderAnimation::update(){
if( rotationCounter == 1){ // if loadeded reset values
//trigger post-load animation here
frameIndex = 0;// we reset our frameIndex here
}else if(rotationCounter == 0 && frameIndex < 112){ // if not, then we draw
frameIndex += rotationSpeed;
if(bFrameIndependent) { // calculate the frame index based on the app time
// and the desired sequence fps. then mod to wrap
} else { // set the frame index based on the app frame
// count. then mod to wrap.
frameIndex = ofGetFrameNum() % loaderImages.size();
}
}
if(frameIndex >= 111){ // if we are over the particle and we finish loading we reset some values;
rotationCounter = 1; // rotation counter is done!
isLoadingCompleted = true;
frameIndex = 0;
}
}
//-------------------------------------------------------------------
void LoaderAnimation::draw(float &_x, float &_y){
ofPushStyle();{
ofPushMatrix();
// draw the image sequence at the new frame count
ofTranslate(0,0,100 );
ofSetRectMode(OF_RECTMODE_CENTER);
ofSetColor(255,255);
loaderImages[frameIndex].draw( _x, _y, 1);
ofPopMatrix();
}ofPopStyle();
}
|
Pretty straight forward. setup() to load the images in my vector of images. update() to loop through the different images and draw() to display the images.
Now this is where the problem comes. In my particle class, I pass a pointer to the LoaderAnimation. But since multiple particles are being created through a controller class, whenever I work with the logic of the loaderAnimation doesn't work since all the particles are receiving the same pointer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
void Boid::update(LoaderAnimation *_loader){
_loader->update();
switch (boidState) {
case 0:// regular particle behavior
_loader->frameIndex = 0;
_loader->rotationCounter = 0;
break;
case 1: // hovering and loader
pos = lastPos; // we stop the particle
if( _loader->frameIndex >= 110){
boidState = 2;
}
break;
}
|
As you can see, this code doesn't work because in my controller class when I hover in particle number 1 it does change the boidState to 2, but because the other particles are in boidState 1 and contain the same loader, it won't display my animation.
Is there any design pattern or copy method that allows me to use the same instance independently. I know this sounds weird but I'm just curious. I have been reading about the singleton pattern but don't quite understand it as the examples out there are all the same. I'm more than open to other algorithmic solutions for this problem.