仮想計算機構

IT業界と無縁な派遣社員のブログ

openFrameworks による Langton's loop


openFrameworks と C++ の勉強として、以前作成した Langton's loop の C++ 版を作成しました。openFrameworks 0.11.2 にて動作を確認しています。

プログラム

main.cpp

#include "ofMain.h"
#include "ofApp.h"

//========================================================================
int main( ){
	ofSetupOpenGL(1024,768,OF_WINDOW);			// <-------- setup the GL context
	ofRunApp(new ofApp());

}

ofApp.cpp

#include "ofApp.h"
#include <vector>
#include <map>
#include <string>
#include <types/ofColor.h>

std::vector<std::vector<int>> ofApp::loop{
		{0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0},
		{2, 1, 7, 0, 1, 4, 0, 1, 4, 2, 0, 0, 0, 0, 0},
		{2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0},
		{2, 7, 2, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0},
		{2, 1, 2, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0},
		{2, 0, 2, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0},
		{2, 7, 2, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0},
		{2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 0},
		{2, 0, 7, 1, 0, 7, 1, 0, 7, 1, 1, 1, 1, 1, 2},
		{0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0} };

// black, blue, red, green, yellow, magenta, white, cyan
std::vector<int> ofApp::colors{0x000000,0x0000FF,0xFF0000,0x008000,0xFFFF00,0xFF00FF,0xFFFFFF,0x00FFFF};

void ofApp::initField() {
	for (int i = 0; i < n_rows; i++) {
		std::vector<int> v;
		for (int j = 0; j < n_cols; j++) {
			v.push_back(0);
		}
		field.push_back(v);
		next_field.push_back(v);
	}

	int offset_x = (int)((n_rows - loop.size()) / 2);
	int offset_y = (int)((n_cols - loop[0].size()) / 2);

	for (int y = 0; y < loop.size(); y++) {
		for (int x = 0; x < loop[0].size(); x++) {
			field[y + offset_y][x + offset_x - 10] = loop[y][x];
		}
	}
}

void ofApp::loadRule() {
	ofFile file;
	file.open(ofToDataPath("rule.txt"), ofFile::ReadWrite, false);
	ofBuffer buff = file.readToBuffer();

	for (auto line : buff.getLines()) {
		std::string c = line.substr(0, 1); // center
		std::string n = line.substr(1, 1); // north
		std::string e = line.substr(2, 1); // east
		std::string s = line.substr(3, 1); // south
		std::string w = line.substr(4, 1); // west
		std::string next_c = line.substr(5, 1);
		rules[c + n + e + s + w] = next_c;
		rules[c + w + n + e + s] = next_c;
		rules[c + s + w + n + e] = next_c;
		rules[c + e + s + w + n] = next_c;
	}
}

//--------------------------------------------------------------
void ofApp::setup(){
	stop = false;
	cell_size = 10;
	n_rows = (int)(ofGetWindowHeight() / cell_size);
	n_cols = (int)(ofGetWindowWidth() / cell_size);
	initField();
	loadRule();
	ofSetBackgroundColor(ofColor::black);
}

//--------------------------------------------------------------
void ofApp::update(){
	if (stop) {
		return;
	}
	for (int y = 1; y < n_rows - 1; y++) {
		for (int x = 1; x < n_cols - 1; x++) {
			std::string c = std::to_string(field[y][x]);
			std::string n = std::to_string(field[y - 1][x]);
			std::string e = std::to_string(field[y][x + 1]);
			std::string s = std::to_string(field[y + 1][x]);
			std::string w = std::to_string(field[y][x - 1]);
			decltype(rules)::iterator itr = rules.find(c + n + e + s + w);
			if (itr == rules.end()) {
				next_field[y][x] = field[y][x];
			}
			else {
				next_field[y][x] = stoi(rules[c + n + e + s + w]);
			}
		}
	}
	// copy
	for (int y = 1; y < n_rows; y++) {
		for (int x = 1; x < n_cols; x++) {
			field[y][x] = next_field[y][x];
		}
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	ofSetColor(ofColor::white);
	ofDrawBitmapString("press s to stop / start", 30, 60);
	
	for (int y = 0; y < n_rows; y++) {
		for (int x = 0; x < n_cols; x++) {
			int state = field[y][x];
			if (state!=0) {
				ofSetColor(ofColor::fromHex(colors[state]));
				ofDrawRectangle(x * cell_size, y * cell_size, cell_size, cell_size);
			}
		}
	}
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
	if (key=='s') {
		stop = !stop;
	}
}

//--------------------------------------------------------------
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::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}

ofApp.h

#pragma once
#include "ofMain.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 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);
		
		int cell_size;
		int n_rows;
		int n_cols;
		bool stop;
		static std::vector<int> colors;
		std::vector<std::vector<int>> next_field;
		std::vector<std::vector<int>> field;
		std::map<std::string, std::string> rules;
		static std::vector<std::vector<int>> loop;
		void initField();
		void loadRule();
};

bin/data/rule.txt

bin/data 配下にセルの変換規則に関するファイルを置いておきます。

000000
000012
000020
000030
000050
000063
000071
000112
000122
000132
000212
000220
000230
000262
000272
000320
000525
000622
000722
001022
001120
002020
002030
002050
002125
002220
002322
005222
012321
012421
012525
012621
012721
012751
014221
014321
014421
014721
016251
017221
017255
017521
017621
017721
025271
100011
100061
100077
100111
100121
100211
100244
100277
100511
101011
101111
101244
101277
102026
102121
102211
102244
102263
102277
102327
102424
102626
102644
102677
102710
102727
105427
111121
111221
111244
111251
111261
111277
111522
112121
112221
112244
112251
112277
112321
112424
112621
112727
113221
122244
122277
122434
122547
123244
123277
124255
124267
125275
200012
200022
200042
200071
200122
200152
200212
200222
200232
200242
200250
200262
200272
200326
200423
200517
200522
200575
200722
201022
201122
201222
201422
201722
202022
202032
202052
202073
202122
202152
202212
202222
202272
202321
202422
202452
202520
202552
202622
202722
203122
203216
203226
203422
204222
205122
205212
205222
205521
205725
206222
206722
207122
207222
207422
207722
211222
211261
212222
212242
212262
212272
214222
215222
216222
217222
222272
222442
222462
222762
222772
300013
300022
300041
300076
300123
300421
300622
301021
301220
302511
401120
401220
401250
402120
402221
402326
402520
403221
500022
500215
500225
500232
500272
500520
502022
502122
502152
502220
502244
502722
512122
512220
512422
512722
600011
600021
602120
612125
612131
612225
700077
701120
701220
701250
702120
702221
702251
702321
702525
702720

実行結果