diff --git a/resources/test.png b/resources/test.png new file mode 100644 index 0000000..a42be28 --- /dev/null +++ b/resources/test.png Binary files differ diff --git a/src/main/java/Main.java b/src/main/java/Main.java index c5a564a..d29a70c 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,120 +1,106 @@ +import entity.Const; +import entity.Image2D; +import entity.Texture; +import entity.Vec2; import org.lwjgl.glfw.*; import org.lwjgl.opengl.*; - -import org.lwjgl.Version; import views.PlayerRenderer; import static org.lwjgl.glfw.Callbacks.*; - import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.system.MemoryUtil.*; public class Main { - // The window handle - private long window; + // ウィンドウハンドル + private long hWnd; + + // private PlayerRenderer playerRenderer; + // フルスクリーン + public boolean fullScreen; - public void run() { - System.out.println("Hello LWJGL " + Version.getVersion() + "!"); - - try { - init(); - loop(); - - // Release window and window callbacks - glfwFreeCallbacks(window); - glfwDestroyWindow(window); - } finally { - // Terminate GLFW and release the GLFWerrorfun - glfwTerminate(); - glfwSetErrorCallback(null).free(); - } + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // エントリーポイント + public static void main(String[] args) { + new Main().run(false); } + //--------------------------------------------------------------- + // メイン関数 + public void run(boolean fullScreen) { + // フルスクリーンの真偽値を貰う + this.fullScreen = fullScreen; - private void init() { - // Setup an error callback. The default implementation - // will print the error message in System.err. - GLFWErrorCallback.createPrint(System.err).set(); + // 色々初期化 + initWindow(); + initRender(); - // Initialize GLFW. Most GLFW functions will not work before doing this. - if (!glfwInit()) { + playerRenderer = new PlayerRenderer("resources/test.png", new Vec2(640, 480)); + + // メインループ + while (!glfwWindowShouldClose(hWnd)) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // バッファのクリア + playerRenderer.display(); + glfwSwapBuffers(hWnd); // バッファのスワップ + glfwPollEvents(); // 入力とかイベントの取得 + } + + // 終了処理 + delete(); // デストラクタ + glfwFreeCallbacks(hWnd); // ウィンドウコールバックの解放 + glfwDestroyWindow(hWnd); // ウィンドウの破棄 + glfwTerminate(); // GLFWの破棄 + glfwSetErrorCallback(null).free(); // エラーコールバックの解放 + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // ウィンドウの初期化 + private void initWindow() { + GLFWErrorCallback.createPrint(System.err).set(); // エラーコールバックの設定 + + + // GLFWの初期化 + if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW"); - } - // Configure our window - glfwDefaultWindowHints(); // optional, the current window hints are already the default - glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after creation - glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable + // ウィンドウの設定 + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); - int WIDTH = 1280; - int HEIGHT = 960; + // ウィンドウの作成 + hWnd = glfwCreateWindow(Const.WIDTH, Const.HEIGHT, Const.TITLE_NAME, fullScreen ? glfwGetPrimaryMonitor() : NULL, NULL); + if (hWnd == NULL) + throw new RuntimeException("Failed to create the window."); - // Create the window - window = glfwCreateWindow(WIDTH, HEIGHT, "JumpGame!", NULL, NULL); - if (window == NULL) { - throw new RuntimeException("Failed to create the GLFW window"); - } - - // Escで終了 - glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> { - if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) { - glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop - } - }); - - // Get the resolution of the primary monitor - GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - // Center our window - glfwSetWindowPos( - window, - (vidmode.width() - WIDTH) / 2, - (vidmode.height() - HEIGHT) / 2 - ); - - // Make the OpenGL context current - glfwMakeContextCurrent(window); - // Enable v-sync + // ウィンドウをタゲにするのか? + glfwMakeContextCurrent(hWnd); + // v-syncの適応 glfwSwapInterval(1); - - playerRenderer = new PlayerRenderer(window); - - // Make the window visible - glfwShowWindow(window); + // ウィンドウの表示 + glfwShowWindow(hWnd); } - private void loop() { - // This line is critical for LWJGL's interoperation with GLFW's - // OpenGL context, or any context that is managed externally. - // LWJGL detects the context that is current in the current thread, - // creates the ContextCapabilities instance and makes the OpenGL - // bindings available for use. + //--------------------------------------------------------------- + // 描画プロセス初期化 + private void initRender() { GL.createCapabilities(); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 背景色設定 - playerRenderer.display(); - - // Set the clear color - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - // Run the rendering loop until the user has attempted to close - // the window or has pressed the ESCAPE key. - while (!glfwWindowShouldClose(window)) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer - - glfwSwapBuffers(window); // swap the color buffers - - // Poll for window events. The key callback above will only be - // invoked during this call. - glfwPollEvents(); - } + // OpenGLの初期化 + glEnable(GL_TEXTURE_2D); // 二次元テクスチャの有効化 + glEnable(GL_BLEND); // アルファブレンディングの有効化 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // ブレンドモードの設定 } - public static void main(String[] args) { - new Main().run(); + //--------------------------------------------------------------- + // デストラクタ + public void delete() { + playerRenderer.delete(); } - + //--------------------------------------------------------------- } \ No newline at end of file diff --git a/src/main/java/entity/Color.java b/src/main/java/entity/Color.java new file mode 100644 index 0000000..06e9572 --- /dev/null +++ b/src/main/java/entity/Color.java @@ -0,0 +1,35 @@ +package entity; + +public class Color { + private float r; + private float g; + private float b; + private float a; + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + public Color(float r, float g, float b, float a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + public float getR() { + return r; + } + + public float getG() { + return g; + } + + public float getB() { + return b; + } + + public float getA() { + return a; + } +} diff --git a/src/main/java/entity/Const.java b/src/main/java/entity/Const.java new file mode 100644 index 0000000..a877fc9 --- /dev/null +++ b/src/main/java/entity/Const.java @@ -0,0 +1,11 @@ +package entity; + +public class Const { + private Const() { + } + + public static final String TITLE_NAME = "JumpGame"; + public static final int WIDTH = 1280; + public static final int HEIGHT = 960; + public static final int DEPTH = 100; // 追加。深度 +} \ No newline at end of file diff --git a/src/main/java/entity/Image2D.java b/src/main/java/entity/Image2D.java new file mode 100644 index 0000000..1a54575 --- /dev/null +++ b/src/main/java/entity/Image2D.java @@ -0,0 +1,96 @@ +package entity; + +import static org.lwjgl.opengl.GL11.*; + +//--------------------------------------------------------------- +// +public class Image2D { + + private int id; // テクスチャのID + private Vec2 wh; // スプライトの幅高 + private Vec2 position; // スプライトの座標(画面座標) + private Color color; // スプライトの色 + private double rotation; // 回転(度) + private double scale; // 拡大 + private double alpha; // 透明度 + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // + public Image2D(Texture tex, double x, double y) { + if (tex != null) + this.id = tex.getId(); + else + this.id = 0; + + this.position = new Vec2(x, y); + this.color = new Color(1, 1, 1, 1); + + if (tex != null) + wh = new Vec2(tex.getWidth(), tex.getHeight()); + else + wh = new Vec2(30, 30); + + rotation = 0.0; + scale = 1.0; + alpha = 1.0; + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // setter + public void setRotation(double rotation) { + this.rotation = rotation; + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // + public void draw() { + // テクスチャの結合 + glBindTexture(GL_TEXTURE_2D, id); + + // 変換行列の追加 + glPushMatrix(); + + // モデルビューモード + glMatrixMode(GL_MODELVIEW); + // 行列の設定 + glLoadIdentity(); // 単位行列化 + glTranslated(position.getX(), position.getY(), 0); // 移動 + glRotated(rotation, 0, 0, 1); // 回転 + glScaled(scale, scale, 1); // 拡縮 + + // プロジェクションモード + glMatrixMode(GL_PROJECTION); + // 行列の設定 + glLoadIdentity(); // 単位行列化 + glOrtho(0, Const.WIDTH, 0, Const.HEIGHT, -Const.DEPTH, Const.DEPTH); // 正射影投影 + + // ビューポートの範囲 + glViewport(0, 0, Const.WIDTH, Const.HEIGHT); + + // ポリゴンの色 + glColor4d(color.getR(), color.getG(), color.getB(), alpha); + + // ポリゴンの作成とテクスチャの適応 + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2d(0, 0); + glVertex2d(-wh.getX() / 2, wh.getY() / 2); + glTexCoord2d(0, 1); + glVertex2d(-wh.getX() / 2, -wh.getY() / 2); + glTexCoord2d(1, 0); + glVertex2d(wh.getX() / 2, wh.getY() / 2); + glTexCoord2d(1, 1); + glVertex2d(wh.getX() / 2, -wh.getY() / 2); + glEnd(); + + // 行列の破棄 + glPopMatrix(); + + // テクスチャの解除 + glBindTexture(GL_TEXTURE_2D, 0); + } + + //--------------------------------------------------------------- +} \ No newline at end of file diff --git a/src/main/java/entity/Texture.java b/src/main/java/entity/Texture.java new file mode 100644 index 0000000..28a422e --- /dev/null +++ b/src/main/java/entity/Texture.java @@ -0,0 +1,107 @@ +package entity; + +import static org.lwjgl.opengl.GL11.*; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import javax.imageio.ImageIO; + +import org.lwjgl.BufferUtils; + +//--------------------------------------------------------------- +// +public class Texture { + + private int id; + private int width; + private int height; + private String name; + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + public Texture(String name, String path) { + this.name = name; + BufferedImage bi; + try { + // イメージファイルの読み込み + bi = ImageIO.read(new File(path)); + width = bi.getWidth(); + height = bi.getHeight(); + + // ピクセルを保存する配列の用意 + int[] pixelsRaw; + pixelsRaw = bi.getRGB(0, 0, width, height, null, 0, width); + ByteBuffer pixels = BufferUtils.createByteBuffer(width * height * 4); + + // 一ピクセルずつ読み込む + for (int i = 0; i < height; ++i) { + for (int j = 0; j < width; ++j) { + int p = pixelsRaw[i * width + j]; + pixels.put((byte) ((p >> 16) & 0xFF)); + pixels.put((byte) ((p >> 8) & 0xFF)); + pixels.put((byte) (p & 0xFF)); + pixels.put((byte) ((p >> 24) & 0xFF)); + } + } + pixels.flip(); + + // テクスチャの作成 + id = glGenTextures(); // IDの取得 + glBindTexture(GL_TEXTURE_2D, id); // IDとテクスチャデータを結合 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // 作成 + + // テクスチャの設定 + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // テクスチャの解除 + glBindTexture(GL_TEXTURE_2D, 0); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + public int getHeight() { + return height; + } + + //--------------------------------------------------------------- + public int getWidth() { + return width; + } + + //--------------------------------------------------------------- + public int getId() { + return id; + } + + //--------------------------------------------------------------- + public String getName() { + return name; + } + + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // テクスチャの使用 + public void bind() { + glBindTexture(GL_TEXTURE_2D, id); + } + + //--------------------------------------------------------------- + // テクスチャの解除 + public void debind() { + glBindTexture(GL_TEXTURE_2D, 0); + } + + //--------------------------------------------------------------- + // テクスチャの破棄 + public void delete() { + glDeleteTextures(id); + } + //--------------------------------------------------------------- +} \ No newline at end of file diff --git a/src/main/java/views/IView.java b/src/main/java/views/IView.java index 1b893e9..6a9a0e8 100644 --- a/src/main/java/views/IView.java +++ b/src/main/java/views/IView.java @@ -1,5 +1,14 @@ package views; +//--------------------------------------------------------------- +// public interface IView { + + //--------------------------------------------------------------- + // 描画 void display(); + + //--------------------------------------------------------------- + // テクスチャの開放 + void delete(); } diff --git a/src/main/java/views/PlayerRenderer.java b/src/main/java/views/PlayerRenderer.java index 2899af6..3526444 100644 --- a/src/main/java/views/PlayerRenderer.java +++ b/src/main/java/views/PlayerRenderer.java @@ -1,27 +1,41 @@ package views; +import entity.Image2D; +import entity.Texture; +import entity.Vec2; + +import java.awt.*; + import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11C.glEnable; +//--------------------------------------------------------------- +// public class PlayerRenderer implements IView { - private long window; + private Texture texture; + private Image2D img; - public PlayerRenderer(long window) { - this.window = window; + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // + public PlayerRenderer(String path, Vec2 position) { + texture = new Texture("player", path); + img = new Image2D(texture, position.getX(), position.getY()); } + //--------------------------------------------------------------- + //--------------------------------------------------------------- + // public void display() { - glfwMakeContextCurrent(window); - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glVertex2f(-0.5f, 0.5f); - glVertex2f(0.5f, 0.5f); - glVertex2f(0.5f, -0.5f); - glVertex2f(-0.5f, -0.5f); - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glEnd(); - glDisable(GL_TEXTURE_2D); + img.draw(); } + + //--------------------------------------------------------------- + // テクスチャの開放 + public void delete(){ + texture.delete(); + } + //--------------------------------------------------------------- }