openFrameworksでペーパーマリオのような紙がペラッとめくれるような表現を作ってみました。最初は頑張ってピクセル処理を書いていたのですが、後輩にOpenGLのメッシュ使ったら楽じゃないですか?と言われたので、ofMeshを使っています。
だいたい、こんな感じになります。
こういう動きになるPlayerクラスを作っていきます。
Player.h
#ifndef __Player__
#define __Player__
#include "ofMain.h"
class Player{
public:
enum CDirection{RIGHT, LEFT};
static void init(string filename);
Player(); //コンストラクタ
void update(); //update内で呼ぶ関数
void draw(); //draw内で呼ぶ関数
void move(CDirection dir); //動かす方向の関数
static ofImage img; //マリオの画像
static ofMesh mesh; //画像を変形するためのメッシュ
static int imgW, imgH; //画像のサイズ
float t; //変形のための変数
};
#endif
Player.cpp
#include "Player.h"
ofImage Player::img;
ofMesh Player::mesh;
int Player::imgW;
int Player::imgH;
void Player::init(string filename){
img.loadImage(filename);
imgW = img.getWidth();
imgH = img.getHeight();
mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
for(int y=0; y<imgH; ++y){
mesh.addVertex(ofPoint(0,y));
mesh.addVertex(ofPoint(imgW,y));
mesh.addTexCoord(ofPoint(0,y));
mesh.addTexCoord(ofPoint(imgW,y));
}
}
Player::Player(){
x=ofGetWidth()/2;
y=ofGetHeight()/2;
t = -1;
bLeft = false;
}
void Player::update(){
if(bLeft) t += 0.1; //左向きならtを増やす
else t -= 0.1; //右向きならtを減らす
// tは-1〜2の間
if(t>2) t = 2;
else if(t<-1) t = -1;
}
void Player::draw(){
for (int y=0; y<imgH; ++y) {
//頂点の移動先を計算
int convert_x = (int)(sin(PI/2*MAX(-1,MIN(1,t-(float)y/imgH)))*(-imgW/2)+imgW/2); //画像の左側の点
int convert_x2 = (int)(sin(PI/2*MAX(-1,MIN(1,t-(float)y/imgH)))*imgW/2+imgW/2); //画像の右側の点
//メッシュの頂点を移動
mesh.setVertex(2*y, ofPoint(convert_x,y)); //左側の点
mesh.setVertex(2*y+1, ofPoint(convert_x2,y)); //右側の点
}
ofPushMatrix();
ofTranslate(x-imgW/2,y-imgH/2);
img.bind();
mesh.draw();
img.unbind();
ofPopMatrix();
}
void Player::move(CDirection dir){
if(dir == LEFT) bLeft = true;
else if(dir == RIGHT) bLeft = false;
}
単に全体を回転させるより、ペラッとめくれて気持ちいい表現になりました。
コメントを残す