[work 102] Black & White Arrows

[work 102] Black & White Arrows

Movie

Source code

about

  • 黒白の矢印

file

  • 上部にあるファイル名が表示されているボタンを押すと、表示されるファイルが切り替わります
  • 別ウィンドウ表示したい時や行番号などが無いRawMode表示したい時は、コード内右上のボタンを押してください(ボタンはマウスオーバーすると表示されます)
#include "ofMain.h"
#include "ofApp.h"

//================================
int main( ){

    // 4K:4096x2160
    // 2K:2048x1080
    // FullHD:1920x1080
    // HD:1440x1080
    // HD720p:1280x720
    // DVD:720x480
    // setup the GL context
    ofSetupOpenGL(1280, 720, OF_WINDOW);

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp( new ofApp());

}
#pragma once

#include "ofMain.h"

#include "Tile.hpp"


class ofApp : public ofBaseApp{
public:
    ofApp();
    ~ofApp();
    
    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 mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
    
private:
    std::shared_ptr<Tile> tile;
};
#include "ofApp.h"


ofApp::ofApp(){
    
}

ofApp::~ofApp(){
    
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    ofSetFrameRate(fps);
    ofBackground(255);
    ofSetBackgroundAuto(true);
    ofSetVerticalSync(true);
    
    tile = make_shared<Tile>();
    tile->setup();
}

//--------------------------------------------------------------
void ofApp::update(){
    tile->update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    tile->display();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if (key == 's') {
        ofImage img;
        img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
        img.save("screenshot.png");
    }
}
#ifndef Tile_hpp
#define Tile_hpp

#include <stdio.h>
#include "ofMain.h"

struct TileSettings {
    int col;
    int row;
    ofVec2f from;
    ofVec2f to;
    ofVec2f current;
    ofVec2f dir;
    bool wrap;
    ofColor color;
    bool arrowHead;
};

enum MoveDir {
    TILE_UP = 0,
    TILE_DOWN,
    TILE_LEFT,
    TILE_RIGHT,
    TILE_PAUSE
};

struct Command {
    MoveDir dir;
    std::vector<int> pos;
};


class Tile {
public:
    Tile();
    ~Tile();
    void setup();
    void update();
    void display();
    
private:
    void setTo(MoveDir dir, std::vector<int> position);
    
    int colMax, rowMax;
    float tileSize;
    
    std::vector<TileSettings> tile;
    std::list<Command> cmd;
};
#endif /* Tile_hpp */
#include "Tile.hpp"



Tile::Tile()
{
    
}


Tile::~Tile()
{
    
}


void Tile::setup()
{
    colMax = 6;
    rowMax = 6;
    tileSize = 100;
    bool black = true;
    
    for (int i = 0; i < colMax; i++) {
        bool head = true;
        for (int j = 0; j < rowMax; j++) {
            TileSettings ts;
            ts.col = i;
            ts.row = j;
            ts.from = ofVec2f(tileSize / 2 + (tileSize * i), tileSize / 2 + (tileSize * j));
            ts.to = ts.from;
            ts.current = ts.to;
            ts.dir = ofVec2f(0, 0);
            ts.wrap = false;
            if (black) {
                ts.color = ofColor(0);
            } else {
                ts.color = ofColor(255);
                ts.color.a = 0;
            }
            
            ts.arrowHead = head;
            head = !head;
            
            tile.push_back(ts);
        }
        black = !black;
    }
}


void Tile::update()
{
    int step = ofGetFrameNum() % (int)(ofGetTargetFrameRate() / 2);
    
    ofSetRectMode(OF_RECTMODE_CENTER);
    if (step != 0) {
        for (TileSettings &ts : tile) {
            ofVec2f to;
            ofVec2f d;
            if (ts.wrap) {
                to = ts.from + ts.dir * tileSize;
            } else {
                to = ts.to;
            }
            d = to - ts.from;
            float scale = ofMap(step, 0, (int)(ofGetTargetFrameRate() / 2) - 1, 0, 1);
            ts.current = ts.from + d * scale;
        }
    } else {
        Command c;
        float p = ofRandom(1);
        
        if (p < 0.25) {
            c.dir = TILE_UP;
        } else if (p < 0.5) {
            c.dir = TILE_DOWN;
        } else if (p < 0.75) {
            c.dir = TILE_LEFT;
        } else {
            c.dir = TILE_RIGHT;
        }
        
        std::vector<int> pos;
        if (c.dir == TILE_UP || c.dir == TILE_DOWN) {
            std::vector<int> col {0, 2, 4};
            pos = col;
        } else {
            std::vector<int> row {0, 1, 2, 3, 4, 5};
            pos = row;
        }
        int idx = (int)ofRandom(pos.size());
        c.pos.push_back(pos.at(idx));
        pos.erase(pos.begin() + idx);
        
        idx = (int)ofRandom(pos.size());
        c.pos.push_back(pos.at(idx));
        
        cmd.push_back(c);
        cmd.push_back(c);
        
        setTo(cmd.front().dir, cmd.front().pos);
        cmd.pop_front();
    }
}


void Tile::display()
{
    ofRectangle window;
    window.setFromCenter(ofGetWidth() / 2 - (tileSize / 2), ofGetHeight() / 2, colMax * tileSize, rowMax * tileSize);
    ofVec2f offset = ofVec2f(window.getTopLeft().x + (tileSize / 2), window.getTopLeft().y);
    
    ofPushMatrix();
    ofTranslate(offset);
    ofFill();
    for (TileSettings ts : tile) {
        ofSetColor(ts.color);
        if (ts.arrowHead) {
            ofVec2f p0, p1, p2;
            p0.x = ts.current.x;
            p0.y = ts.current.y - (tileSize / 2);
            p1.x = ts.current.x - tileSize;
            p1.y = ts.current.y + (tileSize / 2);
            p2.x = ts.current.x + tileSize;
            p2.y = ts.current.y + (tileSize / 2);
            ofDrawTriangle(p0, p1, p2);
        } else {
            ofDrawRectangle(ts.current, tileSize, tileSize);
        }
        
        if (ts.wrap) {
            ofVec2f from = ts.to - ts.dir * tileSize;
            ofVec2f current = from + (ts.current - ts.from);
            if (ts.arrowHead) {
                ofVec2f p0, p1, p2;
                p0.x = current.x;
                p0.y = current.y - (tileSize / 2);
                p1.x = current.x - tileSize;
                p1.y = current.y + (tileSize / 2);
                p2.x = current.x + tileSize;
                p2.y = current.y + (tileSize / 2);
                ofDrawTriangle(p0, p1, p2);
            } else {
                ofDrawRectangle(current, tileSize, tileSize);
            }
        }
    }
    ofPopMatrix();
    
    // Mask
    ofSetColor(255);
    ofBeginShape();
    ofVertex(0, 0);
    ofVertex(ofGetWidth(), 0);
    ofVertex(ofGetWidth(), ofGetHeight());
    ofVertex(0, ofGetWidth());

    ofNextContour(true);
    
    ofVertex(window.getTopLeft());
    ofVertex(window.getTopRight());
    ofVertex(window.getBottomRight());
    ofVertex(window.getBottomLeft());
    ofEndShape();
}


void Tile::setTo(MoveDir dir, std::vector<int> position)
{
    for (TileSettings &ts : tile) {
        ts.wrap = false;
        ts.from = ts.to;
        ts.current = ts.from;
    }
    
    if (dir == TILE_DOWN) { // Down
        for (int pos : position) {
            for (TileSettings &ts : tile) {
                if (ts.col == pos) {
                    ts.dir = ofVec2f(0, 1);
                    if (ts.row == rowMax - 1) {
                        ts.row = 0;
                        ts.wrap = true;
                    } else {
                        ts.row++;
                    }
                    ts.to = ofVec2f(tileSize / 2 + (tileSize * ts.col), tileSize / 2 + (tileSize * ts.row));
                }
            }
        }
    } else if (dir == TILE_UP) { // Up
        for (int pos : position) {
            for (TileSettings &ts : tile) {
                if (ts.col == pos) {
                    ts.dir = ofVec2f(0, -1);
                    if (ts.row == 0) {
                        ts.row = rowMax - 1;
                        ts.wrap = true;
                    } else {
                        ts.row--;
                    }
                    ts.to = ofVec2f(tileSize / 2 + (tileSize * ts.col), tileSize / 2 + (tileSize * ts.row));
                }
            }
        }
    } else if (dir == TILE_RIGHT) { // Right
        for (int pos : position) {
            for (TileSettings &ts : tile) {
                if (ts.row == pos) {
                    ts.dir = ofVec2f(1, 0);
                    if (ts.col == colMax - 1) {
                        ts.col = 0;
                        ts.wrap = true;
                    } else {
                        ts.col++;
                    }
                    ts.to = ofVec2f(tileSize / 2 + (tileSize * ts.col), tileSize / 2 + (tileSize * ts.row));
                }
            }
        }
    } else if (dir == TILE_LEFT) { // Left
        for (int pos : position) {
            for (TileSettings &ts : tile) {
                if (ts.row == pos) {
                    ts.dir = ofVec2f(-1, 0);
                    if (ts.col == 0) {
                        ts.col = colMax - 1;
                        ts.wrap = true;
                    } else {
                        ts.col--;
                    }
                    ts.to = ofVec2f(tileSize / 2 + (tileSize * ts.col), tileSize / 2 + (tileSize * ts.row));
                }
            }
        }
    } else { // Pause
        // do nothing
    }
}

Link to the reference page

ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。

categoryAPI/Lib
c++std::vector
openframeworksofRectangle
openframeworksofNextContour

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode