Hi,
I'm trying to set up a game with a 2d plane which has a zoom with middle mouse and left/right & up down scrolling while maintaining the same downward view. Something along the line of Supreme Commander but in space.
I've started using the demo code. Hopefully I can write up somethings that I've been playing with (setting up as window, drawing various shapes, zoom, colorizing, background color etc) but I've gotten a little confused by a few things.
1) Why is the original code set up with with Y = 0 in the lower left rather than upper left?
glOrtho(0.0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight(), 0.0, 0.0, 1.0);
2) I started to implement left and right scrolling which works fine for all the objects I've drawn. Just hold your mouse on the left or right edge. But when I rotate one of the GL_QUADS it's position or rotation point gets larger and larger. While it is a cool effect, I want it to continue to spin in place. What am I'm not understanding? Conceptually I think I'm missing something.
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.openal.AL;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
/**
*
* This is a <em>very basic</em> skeleton to init a game and run it.
*
* @author $Author: spasi $
* @version $Revision: 3418 $
* $Id: Game.java 3418 2010-09-28 21:11:35Z spasi $
*/
public class game {
/** Game title */
public static final String GAME_TITLE = "My Game";
/** Desired frame time */
private static final int FRAMERATE = 60;
/** Exit the game */
private static boolean finished;
/** A rotating square! */
private static float angle;
private static float zoom = 1.0f;
private static float w = 800;
private static float h = 600;
private static int dx = 0;
private static int dy = 0;
/**
* No constructor needed - this class is static
*/
private game() {}
/**
* Application init
* @param args Commandline args
*/
public static void main(String[] args) {
try {
init();
run();
} catch (Exception e) {
e.printStackTrace(System.err);
Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
} finally {
cleanup();
}
System.exit(0);
}
/**
* Initialise the game
* @throws Exception if init fails
*/
private static void init() throws Exception {
// Create a fullscreen window with 1:1 orthographic 2D projection, and with
// mouse, keyboard, and gamepad inputs.
Display.setTitle(GAME_TITLE);
Display.setFullscreen(false);
// ** Darrin
Display.setDisplayMode(new DisplayMode(800,600)); // controls screen size otherwise takes default windows resolution
// Enable vsync if we can
Display.setVSyncEnabled(true);
Display.create();
// Start up the sound system
AL.create();
// TODO: Load in your textures etc here
// Put the window into orthographic projection mode with 1:1 pixel ratio.
// We haven't used GLU here to do this to avoid an unnecessary dependency.
// this is setting up a 2d view, not a 3d view.
// see http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight(), 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// specifies how much of the opengl panel gets painted.
glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
// enables color calls
glEnable(GL_COLOR_MATERIAL);
// sets background color
glClearColor(0.2f, 0.0f, 0.0f, 1.0f);
}
/**
* Runs the game (the "main loop")
*/
private static void run() {
while (!finished) {
// Always call Window.update(), all the time
Display.update();
if (Display.isCloseRequested()) {
// Check for O/S close requests
finished = true;
} else if (Display.isActive()) {
// The window is in the foreground, so we should play the game
userInput();
logic();
render();
Display.sync(FRAMERATE);
} else {
// The window is not in the foreground, so we can allow other stuff to run and
// infrequently update
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
logic();
if (Display.isVisible() || Display.isDirty()) {
// Only bother rendering if the window is visible or dirty
render();
}
}
}
}
/**
* Do any game-specific cleanup
*/
private static void cleanup() {
// TODO: save anything you want to disk here
// Stop the sound
AL.destroy();
// Close the window
Display.destroy();
}
private static void userInput(){
// Mouse x/y scroll
int x = Mouse.getX();
int y = Mouse.getY();
if ((x > 750) && (Mouse.isInsideWindow())){
dx += 1;
}
if (x < 50 && (Mouse.isInsideWindow())){
dx -= 1;
}
if (Mouse.isButtonDown(0)) {
System.out.println("MOUSE DOWN @ X: " + x + " Y: " + y);
}
// Mouse Zoom
int z = Mouse.getDWheel();
if (z != 0){
System.out.println("Wheel is " + z);
if (z > 0) {
zoom += -0.5;
if (zoom < 0.5)
zoom = 0.5f;
}
if (z < 0){
zoom += 0.5;
if (zoom > 6)
zoom = 6.0f;
}
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
System.out.println("SPACE KEY IS DOWN");
}
}
/**
* Do all calculations, handle input, etc.
*/
private static void logic() {
// Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
finished = true;
}
// TODO: all your game logic goes here.
angle += 1.0f % 360;
}
/**
* Render the current frame
*/
private static void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// TODO: all your rendering goes here
// Zoom
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho((w-w*zoom)/2,
zoom*w + (w-w*zoom)/2,
zoom*h + (h-h*zoom)/2,
(h-h*zoom)/2,
-1.0,
1) ;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Colorized Square
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(0.5f, 0.0f, 0.8f);
glVertex2i(-50+dx, -50);
glColor3f(0.0f, 0.0f, 0.8f);
glVertex2i(50+dx, -50);
glColor3f(1.0f, 0.0f, 0.2f);
glVertex2i(50+dx, 50);
glColor3f(0.2f, 0.5f, 0.5f);
glVertex2i(-50+dx, 50);
glEnd();
glPopMatrix();
glPushMatrix(); // Translation state
//glTranslatef((Display.getDisplayMode().getWidth() / 2)+dx, Display.getDisplayMode().getHeight() / 2, 0.0f);
//glScalef(2,2,2); // 1 = normal size 2 equals double
// glRotatef(a, 0, 1, 0); // rotation about the y-axis
// glRotatef(a, 0, 0, 1); // rotation about the z-axis
glRotatef(-angle, 0, 0, 1.0f);
glBegin(GL_QUADS);
glColor3f(0.5f, 0.0f, 0.8f);
glVertex2i(-50+dx, -50);
glColor3f(0.0f, 0.0f, 0.8f);
glVertex2i(50+dx, -50);
glColor3f(1.0f, 0.0f, 0.2f);
glVertex2i(50+dx, 50);
glColor3f(0.2f, 0.5f, 0.5f);
glVertex2i(-50+dx, 50);
glEnd();
glPopMatrix(); // Ends translation state
// why doesn't the point scale with ortho?
glPushMatrix();
//glPointSize(40); // sets point size diaeter
glEnable(GL_POINT_SMOOTH); // Makes it into a circle rather than square
glBegin(GL_POINTS);
glVertex2f(69.0f,49.0f);
glVertex2i(100,50);
glEnd();
glPopMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glBegin (GL_LINES);
glVertex2i (39, 200);
glVertex2i (75, 250);
glVertex2i (60, 200);
glVertex2i (85, 250);
glEnd();
glColor3f(0.0f, 0.0f, 1.0f);
glBegin (GL_LINES);
glVertex3f (45, 200, 0);
glVertex3f (75, 250, 0);
glVertex3f (44, 200, 0);
glVertex3f (85, 250, 0);
glEnd();
}
}
3) With my zoom code all objects shrink and increase in size except the GL_POINTS. Even if I set them to a larger size, like 40 pixels, they move but they don't actually shrink / scale when zooming out.
4) Almost all Opengl tutorials, NEHE, etc, include GLUT. Is it basically a competitor or sorts with LWJGL? They seem to have a few overlaps with mouse but they have several other features as well. Just curious why it isn't implemented with LWJGL or perhaps it is. Not quite seeing it?
5) I've been looking over
http://potatoland.org/code/gl/ and it is a really cool tutorial but there is quite a bit of code in his glApp.... have the developers thought about including some of those features? I mean the really seem important building blocks to game writing... models, fonts, camera, etc.
I appreciate any insights you may have.