多摩美 - “iTamabi” – iPhoneアプリ開発プロジェクト 2010
openFrameworks for iPhone:時計をつくる
今日の内容
- iPhoneで時計をつくってみる
- openFrameworksで、現在の時刻の取得は簡単に実現可能
- あとは、その数値を使って、いろいろな表現を試す
時刻の取得
- openFrameworksでは、現在の時間、分、秒を取得する関数が用意されている
- だたし、この時間はiPhone (シミュレータの場合はMac) の時計を参照しているので、常に正確とは限らない
- 時刻を取得する関数
- ofGetHours(); – 「時」を取得 (0〜24)
- ofGetMinutes(); – 「分」を取得 (0〜60)
- ofGetSeconds(); – 「秒」を取得 (0〜60)
サンプル1:時刻を表示する
- まずは簡単に、取得した時刻を文字で表示してみる
testApp.mm
[code language=”cpp”]
#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){
}
[/code]
サンプル2:デジタル時計
- フォントを読み込んで、きれいな文字で表示
- 時、分、秒ともに、値が10以下の時は、左に0を追加して2桁表示にする
testApp.h
[code language=”cpp”]
#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;
};
[/code]
testApp.mm
[code language=”cpp”]
#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){
}
[/code]
サンプル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
[code language=”cpp”]
#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){
}
[/code]
サンプル4:アナログ時計(完成版)
- 作成したプログラムの表示と実際のアナログ時計と比べてみる
- なにか違いはないだろうか?
- 分が切り替わった瞬間の動き
- 時間が切り替わった瞬間の動き
- 実際の時計
- 時針、分針も常にゆっくりと動いている
- 時刻が変化した瞬間に動くのではなく、ゆっくりと移動して、気がつくと角度が変化している
- 実際の分針
- 秒の影響を受けている
- 毎秒あたり、1/60の影響 (1分 = 60秒なので)
- m = m + (s/60);
- 実際の時針
- 分の影響を受けている
- 毎分あたり、1/60の影響 (1時間 = 60分なので)
- h = h + (m/60);
- 分針と時針の補正をしたアナログ時計に修正する
- 文字盤を追加
- 角度を変更しながら、一定間隔に目盛を刻んでいく
- 小さな目盛:6度づつ
- 大きな目盛:30度づつ
testApp.mm
[code language=”cpp”]
#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){
}
[/code]
サンプル5:大きさによる時間の表現
- 時刻の数値をより自由な発想で使用してみる
- 時、分、秒、ミリ秒の値で半径を変化させながら、円を描いてみる
- 大きさによる時計
testApp.mm
[code language=”cpp”]
#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){
}
[/code]
サンプル6:位置による時間の表現
- 時、分、秒、ミリ秒の値で位置を変化させながら、直線を引いてみる
testApp.h
[code language=”cpp”]
#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;
};
[/code]
testApp.mm
[code language=”cpp”]
#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){
}
[/code]
サンプルファイルのダウンロード
今日とりあげた全てのサンプルは、下記よりダウンロードすることができます。