質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
GLFW

GLFWは、OpenGLを使用してアプリ開発を行うためのフレームワークです。Macにも対応しているマルチプラットフォームであることが特徴。ウィンドウ管理、解像度切り替え、入力管理などの機能を持ちます。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

889閲覧

[glfw]将来性のためキー入力はどういった形で実装するべきか?オブジェクト指向が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

GLFW

GLFWは、OpenGLを使用してアプリ開発を行うためのフレームワークです。Macにも対応しているマルチプラットフォームであることが特徴。ウィンドウ管理、解像度切り替え、入力管理などの機能を持ちます。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/04/19 08:45

キー入力についてなのですが場当たりなことはせず将来性を考えた設計をする際にどうやってキー入力を実装したらいいコードになるのか知りたいです。現状はWindowクラスにウインドウコンテキスト当を管理しているのですが"ここに実装するべき"コメント部に実装するべきなのでしょうか?またゲーム内容とフレームワーク部でオブジェクト指向を分けたいのでゲームプログラム内でwindowコンテキスト変数を直接触りたくなりません。現在は描画物は一つですがGame クラスを作ってそこにゲーム内容を記述してくといった規模の大きなプロジェクトになる場合どういった手法でプロ人は実装するのでしょうか?

cpp

1//#define GLEW_STATIC //スタティックリンク 2#include <iostream> 3#include <fstream> 4#include <cstdlib> 5#include <vector> 6#include <glew/include/GL/glew.h> 7#include <glfw/include/GLFW/glfw3.h> 8 9 10 11#include "Window.hpp" 12#include "Shape.hpp" 13#include "Shader.hpp" 14 15Object::Vertex rectangleVertex[4] = 16{ 17 {-0.5f,-0.5f}, 18 {0.5f,-0.5f}, 19 {0.5f,0.5f}, 20 {-0.5f,0.5f} 21}; 22 23 24int main() 25{ 26 if (glfwInit() == GL_FALSE) 27 { 28 std::cerr << "glfw初期化失敗。" << std::endl; 29 return -1; 30 } 31 32 33 atexit(glfwTerminate); //プログラム終了時の処理を登録 34 Window window; 35 36 //OpenGL Verison 3.2 Core Profile を選択する 37 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3); 38 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,2); 39 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE); 40 glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); 41 42 Shape* shape = new Shape(2, 4, rectangleVertex); 43 44 Shader shader("Test.vert","Test.frag"); 45 shader.setBindAttribVertex(0, "Position"); 46 shader.setBindAttribFragment(0, "fragment"); 47 48 49 glClearColor(1.0, 0.0, 0.0, 1.0); //背景色 50 while (window) 51 { 52 glClear(GL_COLOR_BUFFER_BIT); //カラーバッファをクリア 53 shader.Active(); 54 55 shader.setUniform2fv("location",window.getLocation()); 56 shader.setUniform1f("scale",window.getScale()); 57 shader.setUniform2fv("size",window.getSize()); 58 59 60 61 shape->Draw(); //表示物 62 63 64 65 66 67 window.SwapBuffers(); //ダブルバッファリング 68 } 69 70} 71

cpp

1#include "Window.hpp" 2 3Window::Window(int width, int height, const char* title) 4 :window(glfwCreateWindow(width,height,title,NULL,NULL)), 5 scale(100.0f), 6 location{ 0.0f,0.0f } 7 8{ 9 if (window == NULL) 10 { 11 std::cerr << "ウインドウ生成失敗" << std::endl; 12 exit(1); 13 } 14 15 glfwMakeContextCurrent(window); //コンテキストを作成 16 17 glewExperimental = GL_TRUE; 18 if (glewInit() != GLEW_OK) 19 { 20 std::cerr << "GLFW 初期化失敗" << std::endl; 21 exit(1); 22 } 23 24 atexit(glfwTerminate); //プログラム終了時の処理を登録 25 glfwSwapInterval(1); //垂直同期 26 27 glfwSetWindowUserPointer(window, this); //このインスタンスのthis 28 29 glfwSetWindowSizeCallback(window, Resize); //ウインドウサイズを変更する時に呼び出す処理 30 glfwSetScrollCallback(window,Wheel); //マウスホイール操作時に呼び出す処理 31 32 Resize(window, width, height); 33 34} 35 36//サイズ変更 37void Window::Resize(GLFWwindow* const window, int width, int height) 38{ 39 int fbWidth, fbHeight; 40 glfwGetFramebufferSize(window, &fbWidth, &fbHeight); 41 glViewport(0, 0, fbWidth, fbHeight); 42 43 Window* const instance = (Window*)glfwGetWindowUserPointer(window); 44 45 if (instance != NULL) 46 { 47 instance->size[0] = (GLfloat)width; 48 instance->size[1] = (GLfloat)height; 49 } 50} 51 52const glm::vec2 Window::getSize() const 53{ 54 return size; 55} 56 57GLfloat Window::getScale() const 58{ 59 return scale; 60} 61 62const glm::vec2 Window::getLocation()const 63{ 64 return location; 65} 66 67 68Window::~Window() 69{ 70 glfwDestroyWindow(window); 71} 72 73void Window::Wheel(GLFWwindow* win, double x, double y) 74{ 75 Window* const instance = (Window*)glfwGetWindowUserPointer(win); 76 77 if (instance != NULL) 78 { 79 instance->scale += (GLfloat)y; 80 } 81} 82 83Window::operator bool() 84{ 85 glfwPollEvents(); //イベントを取り出す 86////////////////////////////////////////////////////////////////// 87//ここに書くべきか? 88////////////////////////////////////////////////////////////////// 89 90 //マウスをクリックしたとき 91 if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1) != GLFW_RELEASE) 92 { 93 //マウスカーソルの座標を取得 94 double x, y; 95 glfwGetCursorPos(window, &x, &y); 96 97 //マウスカーソルの正規化デバイス座標系上での座標を求める 98 location.x = (GLfloat)x * 2.0f / size.x - 1.0f; 99 location.y = 1.0f - (GLfloat)y * 2.0f / size.y; 100 } 101 102 //ESCキーを押したら強制終了 103 if (glfwGetKey(window, GLFW_KEY_ESCAPE)) 104 { 105 return false; 106 } 107 108 //ウインドウを閉じる必要があれば false 109 if (glfwWindowShouldClose(window) != 0) 110 { 111 return false; 112 } 113 else { 114 return true; 115 } 116} 117 118//ダブルバッファリング 119void Window::SwapBuffers()const 120{ 121 glfwSwapBuffers(window); 122} 123

cpp

1#ifndef ___WINDOW_HPP 2#define ___WINDOW_HPP 3 4#include <iostream> 5#include <glew/include/GL/glew.h> 6#include <glfw/include/GLFW/glfw3.h> 7#include "glm/glm.hpp" 8 9 10class Window 11{ 12public: 13 Window(int width = 640, int height = 480, const char* title = "Hello!"); 14 virtual ~Window(); 15 16 explicit operator bool(); 17 void SwapBuffers()const; //ダブルバッファリング 18 static void Resize(GLFWwindow* const window, int width, int height); //サイズ変更 19 const glm::vec2 getSize() const; 20 GLfloat getScale() const; 21 const glm::vec2 getLocation()const; 22 static void Wheel(GLFWwindow* win, double x, double y); 23 24 GLfloat scale; //ワールド座標系に対するデバイス座標系の拡大率 25 26private: 27 28 GLFWwindow *const window; //ウインドウコンテキスト 29 30 glm::vec2 size; //ウインドサイズ 31 glm::vec2 location; //図形の正規化デバイス座標上での位置 32 33 34}; 35 36#endif 37 38

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

K_3578

2021/04/19 08:50

コピペして作るのが精一杯、なんならコピペですら作れてない貴方が心配するような事じゃないでしょ。 将来性を心配するなら一度基礎から教材とかで体系的に学び直そう。 時間が本当に勿体ないよ。
退会済みユーザー

退会済みユーザー

2021/04/19 08:51

調べたことを理解しながら手打ちで実装したいのですが...
K_3578

2021/04/19 08:57

貴方、2017年からずーっと同じような質問してるでしょ?殆どはその500件以上の質問についた回答の中に 答えが詰まってる。 今でも回答してくれてる人いるけど、その人達が何を言ってるのかも理解出来てないから、 ずーっと同じようなところで躓き続ける。そりゃそうだ、基礎がわかってないのに動かして遊べる訳がない。 プロフィールに書いてるとおりだとしたら年齢も近いし、 恐らく学びたい、出来るようになりたいという気持ちだけはわかるから伝える。 頼むから基礎からやり直してくれ。多分数ヶ月もあれば学び直せるし、 間違いなく今より回答者の回答が理解出来るようになる。
m.ts10806

2021/04/19 09:47

他人に説明出来て初めて「理解できる」わけですが、 コード自体を適切に説明されたコメントを見たことがありません。 「やりたいこと」だけ書いてある質問ばかりです。
K_3578

2021/04/20 02:19

結局説得も通じなかった。 何年泳げもしない河を泳いで渡ろうとしてるんだ。 橋を架けろ。三回ぐらい飛び込んで渡ろうとしている間に作れる。
guest

回答1

0

ベストアンサー

私は

プロ人

とかいう者ではないので,実際上の方法を述べられる立場にありませんから,単なる思い付きのアイデアを書くことになりますが…


「ゲーム」のロジックの側から見て,(ウィンドウやら何やらが実装されている世界の側に対して)要求したい事柄を考えて(整理して)みれば良いのではないでしょうか.

例えば,

  • キー入力状態が知りたい
  • ゲーム側の都合でプログラムを終了に向かわせたい(ゲームオーバーの時とかにプログラムが終わるようにしたい)
  • ゲーム側に必要な描画手段を伝えたい(それを使って描画処理を行ってもらう)
  • etc...

だとか.

そういった要求を行うための手段(それらのための関数群であったり,インタフェースクラスだったり)にゲームロジック側からアクセスできるならば,それらが具体的にどのように実装されているのか?なんてことは,ゲームロジック側は知る必要が無いです.例えば,キー入力について言えば

C++

1//引数で指定したキーが押されているかどうかを知る手段 2bool GetKeyState( キーの種類 );

みたいな問い合わせ手段があれば,「キーの状態を実際に取得している手段は実は glfwGetKey() なる関数で,その引数には GLFWwindow* 型の何かを与える必要がある」とかいう事情を,この関数を呼ぶゲームロジック側は全く知らなくても済む.
知らなくて済むということは,ゲームロジック側の実装コードには GLFWwindow* みたいな物が現れないということ.
そしたら,

ゲームプログラム内でwindowコンテキスト変数を直接触りたくなりません

といった話が意図通りの方向に進むんじゃないでしょうか.

投稿2021/04/19 09:19

fana

総合スコア11632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/04/19 09:23

ありがとうございます。質問ですがその関数をどうやって使えるようにするかが知りたいです。、 windowクラスに記述していいのか?それとも別のやり方がるのか?それとも場合によるのか? その辺の実装周りが知りたいです。
fana

2021/04/19 09:30

ゲームロジックを実装している個所から, > bool GetKeyState( キーの種類 ); の宣言が見えるならば,あとは,「どこかに」実装があればいいだけの話. 例えばあなたのwindowクラスがメンバ関数としてこれを提供するのだとしたら, ゲームロジック側がwindowクラスを直接触る形にしてもいいかもしれないし, そうではなくてゲームロジック側はwindowクラスなんて物の存在すら知らずに済む形にしてもよい. どこはどうしたいか次第. 後者の例は,(良し悪しは別として)最も簡素な例は, 「windowクラスのインスタンスに触ることができる場所に GetKeyState() という単なる関数の実装がある」 みたいな形: static window windowInst; //window型インスタンス bool GetKeyState( キーの種類 key ){ return windowInst.GetKeyStateMethod(Key); } //この関数は単にインスタンスのメンバ関数を呼ぶだけ 関数GetKeyState()を呼ぶ側はwindowという型を知らずに済む.
退会済みユーザー

退会済みユーザー

2021/04/19 09:44

windowクラスに実装することにしました。
fana

2021/04/19 09:56

とりあえず,そのコードの「将来」のことを考えるなら, GetKeyState()みたいなのをゲームロジック側に提供するためのインタフェースクラスを用意して, windowクラスそのものとかをゲームロジック側から隠すようにしとけばいいんじゃないかな. (最も単純には,windowクラスがそのインタフェースクラスを継承する)
fana

2021/04/19 10:01

class XXXInterface{ ... }; //GetKeyState()とかをゲームロジック側に提供する用 class window : public XXXInterface { ... }; //XXXInterfaceの提供するメソッドの具体実装はwindowクラスにある とか. で,ゲームのロジック側は,プログラムのメインループから毎度呼ばれるメソッドを class GameLogic{ void Update( XXXInterfaceX & ); }; とか何とかしとけばいいんじゃない?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問