多摩美 - “iTamabi” – iPhoneアプリ開発プロジェクト 2010
openFrameworks for iPhone:時計をつくる
今日の内容
- iPhoneで時計をつくってみる
- openFrameworksで、現在の時刻の取得は簡単に実現可能
- あとは、その数値を使って、いろいろな表現を試す
時刻の取得
- openFrameworksでは、現在の時間、分、秒を取得する関数が用意されている
- だたし、この時間はiPhone (シミュレータの場合はMac) の時計を参照しているので、常に正確とは限らない
- 時刻を取得する関数
- ofGetHours(); – 「時」を取得 (0〜24)
- ofGetMinutes(); – 「分」を取得 (0〜60)
- ofGetSeconds(); – 「秒」を取得 (0〜60)
サンプル1:時刻を表示する
- まずは簡単に、取得した時刻を文字で表示してみる
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0,0,0); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ //秒の取得 int s = ofGetSeconds(); //分の取得 int m = ofGetMinutes(); //時の取得 int h = ofGetHours(); //文字で表示する ofSetColor(255, 255, 255); string time = ofToString(h, 0) + ":" + ofToString(m, 0) + ":" + ofToString(s, 0); ofDrawBitmapString(time, 10, 20); } //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプル2:デジタル時計
- フォントを読み込んで、きれいな文字で表示
- 時、分、秒ともに、値が10以下の時は、左に0を追加して2桁表示にする
testApp.h
#pragma once #include "ofMain.h" #include "ofxiPhone.h" #include "ofxiPhoneExtras.h" class testApp : public ofxiPhoneApp { public: void setup(); void update(); void draw(); void exit(); void touchDown(ofTouchEventArgs &touch); void touchMoved(ofTouchEventArgs &touch); void touchUp(ofTouchEventArgs &touch); void touchDoubleTap(ofTouchEventArgs &touch); void lostFocus(); void gotFocus(); void gotMemoryWarning(); void deviceOrientationChanged(int newOrientation); ofTrueTypeFont verdana; };
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0,0,0); //フォントを読み込み verdana.loadFont("verdana.ttf",36, true, true); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ string s, m, h; ofSetColor(255, 255, 255); //秒を読み込み、10以下の場合には左に0づめで2桁に if (ofGetSeconds()<10) { s = "0"+ofToString(ofGetSeconds(), 0); } else { s = ofToString(ofGetSeconds(), 0); } //分を読み込み、10以下の場合には左に0づめで2桁に if (ofGetMinutes()<10) { m = "0"+ofToString(ofGetMinutes(), 0); } else { m = ofToString(ofGetMinutes(), 0); } //時を読み込み、10以下の場合には左に0づめで2桁に if (ofGetHours()<10) { h = "0"+ofToString(ofGetHours(), 0); } else { h = ofToString(ofGetHours(), 0); } //読み込んだフォントで、時刻を表示 string time = h + ":" + m + ":" + s; verdana.drawString(time, 50, ofGetHeight()/2); } //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプル3:アナログ時計(簡易版)
- 取得した時刻から、アナログ時計を作成する
- 時針、分針、秒針のそれぞれの角度を求める
- 時針:12時間で360°変化する。1時間あたりの変化は、360 / 12 = 30°
- 時刻から時針の角度を求める
- 現在の時刻(時) x 30
- 分針:60分で360°変化する。1時間あたりの変化は、360 / 60 = 6°
- 時刻から分針の角度を求める
- 現在の時刻(分) x 6
- 秒針:60秒で360°変化する。1時間あたりの変化は、360 / 60 = 6°
- 時刻から秒針の角度を求める
- 現在の時刻(秒) x 6
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0, 0, 0); ofEnableSmoothing(); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ //時刻を取得 int s = ofGetSeconds(); int m = ofGetMinutes(); int h = ofGetHours()%12; //時計の大きさを設定 float clockSize = ofGetWidth()/2 - 20; //背景に円を描く ofSetColor(255, 255, 255); ofNoFill(); ofTranslate(ofGetWidth()/2, ofGetHeight()/2); ofSetLineWidth(3); ofSetCircleResolution(64); ofCircle(0, 0, clockSize); //秒針 ofPushMatrix(); ofRotateZ(s*6.0); ofSetLineWidth(1); ofLine(0, 0, 0, -clockSize); ofPopMatrix(); //分 ofPushMatrix(); ofRotateZ(m*6.0); ofSetLineWidth(2); ofLine(0, 0, 0, -clockSize); ofPopMatrix(); //時針 ofPushMatrix(); ofRotateZ(h*30.0); ofSetLineWidth(4); ofLine(0, 0, 0, -clockSize*0.75); ofPopMatrix(); } //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプル4:アナログ時計(完成版)
- 作成したプログラムの表示と実際のアナログ時計と比べてみる
- なにか違いはないだろうか?
- 分が切り替わった瞬間の動き
- 時間が切り替わった瞬間の動き
- 実際の時計
- 時針、分針も常にゆっくりと動いている
- 時刻が変化した瞬間に動くのではなく、ゆっくりと移動して、気がつくと角度が変化している
- 実際の分針
- 秒の影響を受けている
- 毎秒あたり、1/60の影響 (1分 = 60秒なので)
- m = m + (s/60);
- 実際の時針
- 分の影響を受けている
- 毎分あたり、1/60の影響 (1時間 = 60分なので)
- h = h + (m/60);
- 分針と時針の補正をしたアナログ時計に修正する
- 文字盤を追加
- 角度を変更しながら、一定間隔に目盛を刻んでいく
- 小さな目盛:6度づつ
- 大きな目盛:30度づつ
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0, 0, 0); ofEnableSmoothing(); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ //時刻を取得 //秒を取得 float s = ofGetSeconds(); //秒の影響を加えた、分の算出 float m = ofGetMinutes() + (s/60.0); //分の影響を加えた、時の算出 float h = ofGetHours()%12 + (m/60); //時計の大きさ float clockSize = ofGetWidth()/2 - 20; //座標全体を中心に移動 ofTranslate(ofGetWidth()/2, ofGetHeight()/2); //時計の背景 ofSetColor(127,127,127); ofFill(); //分の目盛を描く for (int i=0; i<60; i++) { ofRotateZ(6); ofCircle(clockSize, 0, 2); } //時の目盛を描く for (int i=0; i<12; i++) { ofRotateZ(30); ofCircle(clockSize, 0, 4); } ofSetColor(255, 255, 255); ofNoFill(); //秒針 ofPushMatrix(); ofRotateZ(s*6.0); ofSetLineWidth(1); ofLine(0, 0, 0, -clockSize); ofPopMatrix(); //分 ofPushMatrix(); ofRotateZ(m*6.0); ofSetLineWidth(2); ofLine(0, 0, 0, -clockSize); ofPopMatrix(); //時針 ofPushMatrix(); ofRotateZ(h*30.0); ofSetLineWidth(4); ofLine(0, 0, 0, -clockSize*0.75); ofPopMatrix(); } //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプル5:大きさによる時間の表現
- 時刻の数値をより自由な発想で使用してみる
- 時、分、秒、ミリ秒の値で半径を変化させながら、円を描いてみる
- 大きさによる時計
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0, 0, 0); ofEnableSmoothing(); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ //時刻を取得 int ms = ofGetElapsedTimeMillis() % 1000; int s = ofGetSeconds(); int m = ofGetMinutes(); int h = ofGetHours(); //円の最大の大きさを設定 float circleSize = ofGetHeight()/8; ofSetColor(127, 127, 127); //ミリ秒 ofCircle(ofGetWidth()/2, ofGetHeight()/8*7, ms/1000.0*circleSize); //秒 ofCircle(ofGetWidth()/2, ofGetHeight()/8*5, s/60.0*circleSize); //分 ofCircle(ofGetWidth()/2, ofGetHeight()/8*3, m/60.0*circleSize); //時 ofCircle(ofGetWidth()/2, ofGetHeight()/8, h/24.0*circleSize);} //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプル6:位置による時間の表現
- 時、分、秒、ミリ秒の値で位置を変化させながら、直線を引いてみる
testApp.h
#pragma once #include "ofMain.h" #include "ofxiPhone.h" #include "ofxiPhoneExtras.h" class testApp : public ofxiPhoneApp { public: void setup(); void update(); void draw(); void exit(); void touchDown(ofTouchEventArgs &touch); void touchMoved(ofTouchEventArgs &touch); void touchUp(ofTouchEventArgs &touch); void touchDoubleTap(ofTouchEventArgs &touch); void lostFocus(); void gotFocus(); void gotMemoryWarning(); void deviceOrientationChanged(int newOrientation); ofTrueTypeFont verdana; };
testApp.mm
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofBackground(0, 0, 0); ofEnableSmoothing(); ofSetBackgroundAuto(false); ofEnableAlphaBlending(); verdana.loadFont("verdana.ttf",12, false, true); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ //背景 ofSetColor(0, 0, 0, 15); ofRect(0, 0, ofGetWidth(), ofGetHeight()); //時刻を取得 int ms = ofGetElapsedTimeMillis() % 1000; int s = ofGetSeconds(); int m = ofGetMinutes(); int h = ofGetHours(); //枠 ofSetColor(63, 63, 63); ofSetLineWidth(1); ofLine(0, ofGetHeight()/4, ofGetWidth(), ofGetHeight()/4); ofLine(0, ofGetHeight()/2, ofGetWidth(), ofGetHeight()/2); ofLine(0, ofGetHeight()/4*3, ofGetWidth(), ofGetHeight()/4*3); //線の位置で時間を表現 ofSetColor(255, 255, 255); ofSetLineWidth(3); //ミリ秒 verdana.drawString(ofToString(ms, 0), ms/1000.0*ofGetWidth()+4, ofGetHeight()/8+6); ofLine(ms/1000.0*ofGetWidth(), 0, ms/1000.0*ofGetWidth(), ofGetHeight()/4); //秒 verdana.drawString(ofToString(s, 0), s/60.0*ofGetWidth()+4, ofGetHeight()/8*3+6); ofLine(s/60.0*ofGetWidth(), ofGetHeight()/4, s/60.0*ofGetWidth(), ofGetHeight()/2); //分 verdana.drawString(ofToString(m, 0), m/60.0*ofGetWidth()+4, ofGetHeight()/8*5+6); ofLine(m/60.0*ofGetWidth(), ofGetHeight()/2, m/60.0*ofGetWidth(), ofGetHeight()/4*3); //時 verdana.drawString(ofToString(h, 0), h/24.0*ofGetWidth()+4, ofGetHeight()/8*7+6); ofLine(h/24.0*ofGetWidth(), ofGetHeight()/4*3, h/24.0*ofGetWidth(), ofGetHeight()); } //-------------------------------------------------------------- void testApp::exit(){ } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプルファイルのダウンロード
今日とりあげた全てのサンプルは、下記よりダウンロードすることができます。