--- /dev/null
+*.o
+*.d
+*.swp
+game
+*.exe
+*.dll
--- /dev/null
+src = $(wildcard src/*.c)
+obj = $(src:.c=.o)
+dep = $(src:.c=.d)
+bin = game
+
+warn = -pedantic -Wall
+dbg = -g
+
+CFLAGS = $(warn) $(opt) $(dbg) $(inc) $(def) -MMD
+LDFLAGS = $(syslib) $(libgl)
+
+sys := $(shell uname -s | sed 's/MINGW.*/mingw/')
+ifeq ($(sys), mingw)
+ syslib = -mwindows
+ libgl = -lopengl32 -lfreeglut
+
+ obj = $(src:.c=.w32.o)
+ dep = $(src:.c=.w32.d)
+ bin = game.exe
+else
+ libgl = -lGL -lGLU -lglut
+endif
+
+$(bin): $(obj)
+ $(CC) -o $@ $(obj) $(LDFLAGS)
+
+-include $(dep)
+
+%.w32.o: %.c
+ $(CC) -c $< $(CFLAGS) -o $@
+
+.PHONY: clean
+clean:
+ rm -f $(obj) $(bin)
+
+.PHONY: cross
+cross:
+ $(MAKE) CC=i686-w64-mingw32-gcc sys=mingw
+
+.PHONY: cross-clean
+cross-clean:
+ $(MAKE) sys=mingw clean
--- /dev/null
+#include <GL/gl.h>
+#include "game.h"
+
+int game_mx, game_my, game_mstate[3];
+int game_win_width, game_win_height;
+float game_win_aspect;
+
+int game_init(void)
+{
+ glClearColor(0.3, 0.3, 0.3, 1);
+ return 0;
+}
+
+void game_shutdown(void)
+{
+}
+
+void game_display(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+ game_swap_buffers();
+}
+
+void game_reshape(int x, int y)
+{
+ game_win_width = x;
+ game_win_height = y;
+ game_win_aspect = (float) x / y;
+ glViewport(0, 0, x, y);
+}
+
+void game_keyboard(int key, int press)
+{
+ if(!press) return;
+
+ switch(key) {
+ case 27:
+ game_quit();
+ break;
+ }
+}
+
+void game_mouse(int bn, int st, int x, int y)
+{
+ game_mx = x;
+ game_my = y;
+ if(bn < 3) {
+ game_mstate[bn] = st;
+ }
+}
+
+void game_motion(int x, int y)
+{
+ game_mx = x;
+ game_my = y;
+}
--- /dev/null
+#ifndef GAME_H_
+#define GAME_H_
+
+enum {
+ GKEY_ESC = 27,
+ GKEY_DEL = 127,
+ GKEY_F1 = 256,
+ GKEY_F2, GKEY_F3, GKEY_F4, GKEY_F5, GKEY_F6, GKEY_F7,
+ GKEY_F8, GKEY_F9, GKEY_F10, GKEY_F11, GKEY_F12,
+ GKEY_UP, GKEY_DOWN, GKEY_LEFT, GKEY_RIGHT,
+ GKEY_PGUP, GKEY_PGDOWN,
+ GKEY_HOME, GKEY_END,
+ GKEY_INS
+};
+
+extern int game_mx, game_my, game_mstate[3];
+extern int game_win_width, game_win_height;
+extern float game_win_aspect;
+
+int game_init(void);
+void game_shutdown(void);
+
+void game_display(void);
+void game_reshape(int x, int y);
+void game_keyboard(int key, int press);
+void game_mouse(int bn, int st, int x, int y);
+void game_motion(int x, int y);
+
+/* defined in main.c */
+void game_swap_buffers(void);
+void game_quit(void);
+
+#endif /* GAME_H_ */
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <GL/glut.h>
+#include "game.h"
+
+static void idle(void);
+static void keydown(unsigned char key, int x, int y);
+static void keyup(unsigned char key, int x, int y);
+static void skeydown(int key, int x, int y);
+static void skeyup(int key, int x, int y);
+static void mouse(int bn, int st, int x, int y);
+static int translate_skey(int key);
+
+
+int main(int argc, char **argv)
+{
+ glutInit(&argc, argv);
+ glutInitWindowSize(1280, 800);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+ glutCreateWindow("raydungeon");
+
+ glutDisplayFunc(game_display);
+ glutIdleFunc(idle);
+ glutReshapeFunc(game_reshape);
+ glutKeyboardFunc(keydown);
+ glutKeyboardUpFunc(keyup);
+ glutSpecialFunc(skeydown);
+ glutSpecialUpFunc(skeyup);
+ glutMouseFunc(mouse);
+ glutMotionFunc(game_motion);
+
+ if(game_init() == -1) {
+ return 1;
+ }
+ atexit(game_shutdown);
+ glutMainLoop();
+ return 0;
+}
+
+void game_swap_buffers(void)
+{
+ glutSwapBuffers();
+ assert(glGetError() == GL_NO_ERROR);
+}
+
+void game_quit(void)
+{
+ exit(0);
+}
+
+
+static void idle(void)
+{
+ glutPostRedisplay();
+}
+
+static void keydown(unsigned char key, int x, int y)
+{
+ game_keyboard(key, 1);
+}
+
+static void keyup(unsigned char key, int x, int y)
+{
+ game_keyboard(key, 0);
+}
+
+static void skeydown(int key, int x, int y)
+{
+ int k = translate_skey(key);
+ if(k >= 0) {
+ game_keyboard(k, 1);
+ }
+}
+
+static void skeyup(int key, int x, int y)
+{
+ int k = translate_skey(key);
+ if(k >= 0) {
+ game_keyboard(k, 0);
+ }
+}
+
+static void mouse(int bn, int st, int x, int y)
+{
+ game_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
+}
+
+static int translate_skey(int key)
+{
+ switch(key) {
+ case GLUT_KEY_LEFT:
+ return GKEY_LEFT;
+ case GLUT_KEY_UP:
+ return GKEY_UP;
+ case GLUT_KEY_RIGHT:
+ return GKEY_RIGHT;
+ case GLUT_KEY_DOWN:
+ return GKEY_DOWN;
+ case GLUT_KEY_PAGE_UP:
+ return GKEY_PGUP;
+ case GLUT_KEY_PAGE_DOWN:
+ return GKEY_PGDOWN;
+ case GLUT_KEY_HOME:
+ return GKEY_HOME;
+ case GLUT_KEY_END:
+ return GKEY_END;
+ case GLUT_KEY_INSERT:
+ return GKEY_INS;
+ default:
+ if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
+ return key - (GLUT_KEY_F1 + GKEY_F1);
+ }
+ }
+
+ return -1;
+}