でらうま倶楽部

バカってゆうか、ゲームを作る事しか能の無いプログラマの、面白おかしな日々を綴ってみる実験。

2015年01月

emacs 新規ファイル生成時に、文字コードを強制したい

photo
コード書いとる??

ちょっと前に「emacsで.cppファイルみたく、特定のファイルを作成する時に文字コードを強制するには modify-coding-system-alist がいいよ」 と書いたのですが…これファイル生成だけじゃなくて既存のファイルにも適用されるのね…
  • 文字コードがCP932の.cppファイルを開こうとしてどーん!!
  • 文字コードがCP932の.hファイルを開こうとしてどーん!! 
つらたん。

こりゃあかんので、その機能はオフ。「明日時間を確保して検証すんべ」と、メモついでにツイッターにその旨書いて寝て起きたらなんと解決しました。@syohexさん、ありがとうございます!!

 @syohexさんがわざわざ書いてくださったのはこれです。



これに「新規ファイルの場合」という条件を追加したのが拙作。 


 
これでバッチリ!! 本当にありがとうございました。

ではまた次回!!

OpenGLでガリガリアプリを書ける GLFW 3.1 の紹介

01
コード書いとる??

先日GLFW3.1が公開されましたね。

GLFWは、OpenGLを使ったアプリを書くためのシンプルなフレームワークです。OSごとに異なるOpenGLのコンテキスト生成などを、ごく簡単に扱えるように手助けしてくれます。
  • Windows、OSX、Linuxの環境で一貫したOpenGLアプリが書ける
  • キー入力、マウス入力、GamePad入力をサポート
  • マルチモニタ対応
GLFWの機能は、OSごとに異なるデバイスなどの扱いを吸収するに留まっています。そして、専用の描画関数や画像読み込み処理などは一切用意されていません。つまり描画関連は自分でガリガリ書く必要があるのですが、結果としてOpenGLの学習にはとても向いているといえるでしょう。


今回は、3.1で追加された機能のいくつかを簡単なコードを交えながら紹介していきましょう。紹介する内容はざっと以下の通り。長いよ!!
  • ライブラリのビルド
  • Hello, GLFW3 world
  • マウスカーソルの変更
  • FileのDrop操作
  • 外部スレッドからの空イベントを受け取る
  • フレームサイズの取得
  • フローティングウインドウの生成
  • 生成時のフォーカス
  • Oculus Rift対応
  • 修飾キー付きキー入力
  • シングルバッファモード
  • 外部インクルードマクロ

ライブラリのビルド
CMakeを使ってください。GUI版が一番導入が簡単でしょう。


Hello, GLFW3 world
GLFW3での初期化〜終了はこんな感じ。楽!!
#include <GLFW/glfw3.h>


int main() {
  GLFWwindow* window;

  if (!glfwInit()) return -1;

  window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }

  glfwMakeContextCurrent(window);
  while (!glfwWindowShouldClose(window)) {

    // OpenGLでの描画処理をここに書く

    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  
  glfwTerminate();
}

マウスカーソルの変更
手軽に自前のマウスカーソルを設定可能。もちろん、元に戻す機能も用意されています。
#include <GLFW/glfw3.h>
#include <algorithm>


int main() {
  GLFWwindow* window;

  if (!glfwInit()) return -1;

  window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }

  // マウスカーソルの生成
  // RGBA 8bit per pixel
  unsigned char pixels[16 * 16 * 4];
  std::fill(std::begin(pixels), std::end(pixels), 0xff);

  GLFWimage image;
  image.width  = 16;
  image.height = 16;
  image.pixels = pixels;
  
  GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
  glfwSetCursor(window, cursor);

  
  glfwMakeContextCurrent(window);
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  
  glfwTerminate();
}

API補足
// システムのデータからマウスカーソルを生成
GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);

// 初期状態に戻す
glfwSetCursor(window, nullptr);

// 生成したマウスカーソルを破棄
glfwDestroyCursor(cursor);

前からあったけど気付いてなかったカーソルON/OFF
// マウスカーソルOFF
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);

// マウスカーソルON
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

 FileのDrop操作
プレビュワーとか作ってる人には朗報ですね。アプリウインドウにFileをDropした時のコールバックを指定できるようになりました。
#include <GLFW/glfw3.h>
#include <iostream>


// FileがDropされた時のコールバック
void dropCallback(GLFWwindow* window, int count, const char** paths) {
  for (int i = 0;  i < count;  i++) {
    // ファイルの並びはOSの仕様に準ずる
    std::cout << paths[i] << std::endl;
  }
}


int main() {
  GLFWwindow* window;

  if (!glfwInit()) return -1;

  window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }

  // FileがDropされた時のコールバックを指定
  glfwSetDropCallback(window, dropCallback);
  
  glfwMakeContextCurrent(window);
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  
  glfwTerminate();
}

外部スレッドからの空イベントを受け取る
glfwWaitEventsを使うと、なんらかの入力イベントを受け取るまで待機します。これを別スレッドからの空イベントでキックできるようになりました。
#include <GLFW/glfw3.h>
#include <iostream>
#include <thread>
#include <chrono>


int main() {
  GLFWwindow* window;

  if (!glfwInit()) return -1;

  window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }
  
  // 3秒待ってから空イベントを投げる
  std::thread thd([]{
      std::this_thread::sleep_for(std::chrono::seconds(3));
      glfwPostEmptyEvent();
    });

  thd.detach();

  glfwMakeContextCurrent(window);
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);

    // 外部イベント待ち
    // キーやマウス入力、glfwPostEmptyEventで待機解除
    glfwWaitEvents();

    std::cout << "WOW!!" << std::endl;
  }
  
  glfwTerminate();
}

フレームサイズの取得
ウインドウを生成した時の上下左右の余白のサイズを取得できるようになりました。
#include <GLFW/glfw3.h>
#include <iostream>


int main() {
  GLFWwindow* window;

  if (!glfwInit()) return -1;

  window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }

  glfwMakeContextCurrent(window);

  int left, top, right, bottom;
  
  glfwGetWindowFrameSize(window,
                         &left, &top, &right, &bottom);

  std::cout << left << "," << top << "," << right << "," << bottom << std::endl;
  
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);

    glfwPollEvents();
  }
  
  glfwTerminate();
}

フローティングウインドウの生成
常にTopに居座るウインドウを生成できるようになりました。複数のウインドウを扱うアプリで活用できそうですね。
#include <GLFW/glfw3.h>


int main() {
  if (!glfwInit()) return -1;
  
  GLFWwindow* window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }


  // ウインドウを生成するときのHintを指定
  glfwWindowHint(GLFW_FLOATING, GL_TRUE);

  GLFWwindow* sub_window = glfwCreateWindow(256, 128, "Floating Test", nullptr, nullptr);
  if (!sub_window) {
    glfwTerminate();
    return -1;
  }

  
  glfwMakeContextCurrent(window);
  
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);

    glfwPollEvents();
  }
  
  glfwTerminate();
}

生成時のフォーカス
複数のウインドウを生成するような状況で、生成時のフォーカスの有無を指定できるようになりました。
#include <GLFW/glfw3.h>


int main() {
  if (!glfwInit()) return -1;
  
  GLFWwindow* window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }


  // ウインドウを生成するときのHintを指定
  glfwWindowHint(GLFW_FLOATING, GL_TRUE);
  // 生成時は非アクティブ
  glfwWindowHint(GLFW_FOCUSED, GL_FALSE);

  GLFWwindow* sub_window = glfwCreateWindow(256, 128, "Floating Test", nullptr, nullptr);
  if (!sub_window) {
    glfwTerminate();
    return -1;
  }

  
  glfwMakeContextCurrent(window);
  
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);

    glfwPollEvents();
  }
  
  glfwTerminate();
}

Oculus Rift対応
とても詳しいドキュメントが追加されました。これまでよりええ感じに扱えるそうな。

修飾キー付きキー入力
キー入力のコールバックに、修飾キー付きが追加されました。助かりますな。
#include <GLFW/glfw3.h>
#include <iostream>


void inputProc(GLFWwindow* window, unsigned int codepoint, int mods) {
  // codepoint 入力文字(Unicode)
  // mods      修飾キー
  //             GLFW_MOD_SHIFT
  //             GLFW_MOD_CONTROL
  //             GLFW_MOD_ALT
  //             GLFW_MOD_SUPER  
  std::cout << codepoint << "," << mods << std::endl;
}


int main() {
  if (!glfwInit()) return -1;

  GLFWwindow* window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }
  
  glfwMakeContextCurrent(window);

  // キー入力のコールバックを指定
  glfwSetCharModsCallback(window, inputProc);
  
  while (!glfwWindowShouldClose(window)) {
    glfwSwapBuffers(window);
    
    glfwPollEvents();
  }
  
  glfwTerminate();
}

シングルバッファモード
フレームバッファを1枚だけ作って描画するモードが追加されとります。なんともマニアックなw
#include <GLFW/glfw3.h>


int main() {
  if (!glfwInit()) return -1;

  // シングルバッファモード
  glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
  
  GLFWwindow* window = glfwCreateWindow(640, 480, "Simple example", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return -1;
  }
  
  glfwMakeContextCurrent(window);
  
  while (!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT);

    // シングルバッファなので、OpenGLの実行を明示的に行う必要がある
    glFlush();

    glfwPollEvents();
  }
  
  glfwTerminate();
}

外部インクルードマクロ
OpenGL関連のヘッダファイル(glu.hとかglext.h)のインクルードの順番に悩むのですが、そのへんちゃんと対応されていました。これは助かる。
// 必要に応じてglext.hとかgl3ext.hとかをインクルード
#define GLFW_INCLUDE_GLEXT

//glu.hをインクルード
#define GLFW_INCLUDE_GLU


ざっと駆け足でGLFW3.1の新機能をいくつか紹介しました。このほかの機能を知りたい場合はリリースノートを読んでみてください。


ではまた次回!!!.!
 



C++のtypeidで謎の挙動に遭遇

コード書いとる??

C++のtypeidで謎の挙動に遭遇したのでそのメモ。

#include <iostream>
#include <vector>
#include <memory>


struct Hoge {
  enum  { Fuga };

  virtual void f() {}
};

std::vector<Hoge*> data;


struct Fuga : public Hoge {
  void f() {
    for (auto p : data) {
      if (typeid(*p) == typeid(Fuga)) {
        //                      ↑ struct Fuga
        std::cout << "Fuga" << std::endl;
      }
    }
  }
};

struct Piyo : public Hoge {
  void f() {
    for (auto p : data) {
      if (typeid(*p) == typeid(Fuga)) {
        //                      ↑ enum Hoge::<unnamed>::Fuga
        std::cout << "Fuga" << std::endl;
      }
    }
  }
};


int main() {
  data.push_back(new Fuga());
  data.push_back(new Piyo());

  for (auto p : data) {
    p->f();
  }
}

これ、ビルドは通るけど期待した結果が得られない。

コメントに書いてあるように、Piyo::f内のtypeidにenumの値が渡されているのが原因。

とくに警告も出ない…

VisualStudio2013、Xcode6、共に同じ結果。

なんだろ。これに関するC++の規格 or 仕様があるのかしらん…

江添さんからコメント頂きました。 多謝!!

  • struct Fugaは自身の注入されたクラス名がHoge::Fugaを隠すので、Fuga::fの中における名前Fugaは、struct Fugaになります。

    一方、Piyoの方は、名前空間スコープのFugaより、クラススコープにあるHogeから継承した名前Fugaのほうが優先されるので、Piyo::fにおける名前FugaはHoge::Fugaになります。

    typeid(::Fuga)とすればenumeratorのFugaではなくなる。

ではまた次回!!
記事検索
電子書籍発売中

「チュートリアル形式で始めるOpenAL」
サウンド怖くない。C++による8つのチュートリアルで始めるOpenALプログラミング。さああなたも、自作アプリに魅力的な音効を添えてみませんか??
⇒Kindle版 ⇒iBooks版


「iPhoneアプリ『ういろう』のレシピ」
ゲームってどうやって作ってるの?? 拙アプリ『ういろう』の製作過程を本にまとめました。もちろんソースコードつき
⇒Kindle版 ⇒iBooks版


『チュートリアル形式で始めるOpenGL[2D編]』
OpenGL怖くない。C++による16のチュートリアルで始めるOpenGLプログラミング[2D編]。さああなたも、ゲーム作りを始めてみませんか?
⇒Kindle版 ⇒iBooks版
自作ゲーム配信中

『Puzzle & Monarch』
「君主候補となって国作り!! ただし制限時間は90秒。」森を作って道をつないで...あなただけの国を作ってみませんか??
⇒AppStore


『BRICK & TRIP』
咄嗟の判断に、あなたの指先はついてこれるか?! 爽快フリックアクション!! 様々な難関をくぐり抜けて旅の終着点を目指そう!!
⇒AppStore


『ういろう』
名古屋土産ういろうがiPhoneで大活躍?! 白ういろうを守れるのはあなただけ。ひゅーん、ぼよよーん!!
⇒AppStore ⇒LITE版


『こなへん』
ヒマラヤ山脈、大西洋、世界で一番深い湖… それって地球のどこにあるのか知ってるかな?『全方位直感地理クイズ』という新ジャンルに挑戦!あ、それ。地球をくーるくるw
⇒AppStore ⇒LITE版


『GEOSPOT』
ヒマラヤ山脈、大西洋、世界で一番深い湖… それって地球のどこにあるのか知ってるかな?『全方位直感地理クイズ』という新ジャンルに挑戦!あ、それ。地球をくーるくるw
⇒Windows ⇒Mac


『TieGunner』
マウス片手に大宇宙へ飛び立とう!『しっぽシューティング』というジャンルを作って頂きました^^; WinでもMacでも動きます。ソースもあるでよw
⇒Windows ⇒Mac
QRコード
QRコード
  • ライブドアブログ