import java.awt.Font; import java.util.TimerTask; import java.util.Timer; import keel.runtime.Application; import keel.runtime.KeelRuntime; import keel.runtime.ctrl.ControllerDescriptor; import keel.runtime.event.ControllerEvent; import keel.runtime.event.ControllerListener; import keel.runtime.event.KeyEvent; import keel.runtime.event.KeyAdapter; import keel.gfx.GLGraphics; import keel.gfx.GLConstants; import keelx.gfx.font.SystemFont; import keelx.gfx.image.GLImageUtil; import keelx.gfx.image.BufferedGLImage; public class Walk implements Application { private int width = 640; private int height = 480; private SystemFont font; private int fontSize = Math.min(width, height) / 16; private Camera camera; private Light light; private Cube cube; private Land land; private Material[] materials; private float speedX = 0f; private float speedY = 0f; private static final String LAND_DATA = "land.png"; public Walk() { cube = new Cube(); camera = new Camera(width / (double) height, 10, cube); light = new Light(); font = new SystemFont(new Font("System", Font.PLAIN, fontSize)); land = new Land(LAND_DATA, -cube.getScale()); materials = new Material[] { land, cube, light }; } public void keelMain(KeelRuntime runtime,String argv[]) { runtime.useController(1, ControllerDescriptor.JOYPAD_8BUTTONS); runtime.createWindow("", width, height); runtime.createGraphicsWithDefaultPixelFormat(); runtime.addControllerListener(0, new PadController()); runtime.addKeyListener(new KeyController()); runtime.run(); } public void initGraphics(GLGraphics g) { g.glViewport(0, 0, width, height); g.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); g.glEnable(GLConstants.GL_BLEND); g.glBlendFunc(GLConstants.GL_SRC_ALPHA, GLConstants.GL_ONE_MINUS_SRC_ALPHA); land.init(g); } public void update(GLGraphics g) { next(); draw(g); } public void quitRequested() { KeelRuntime.getRuntime().disposeDisplay(); System.exit(0); } private void next() { cube.move(speedX, speedY, 0); camera.move(speedX, speedY, 0); } private void draw(GLGraphics g) { g.glClear(GLConstants.GL_COLOR_BUFFER_BIT | GLConstants.GL_DEPTH_BUFFER_BIT); g.glPushMatrix(); g.glMatrixMode(GLConstants.GL_PROJECTION); g.glLoadIdentity(); camera.draw(g); g.glMatrixMode(GLConstants.GL_MODELVIEW); g.glLoadIdentity(); for (int i = 0; i < materials.length; i++) { g.glPushMatrix(); materials[i].draw(g); g.glPopMatrix(); } g.glPopMatrix(); printMessage(g, new String[] { cube.toString(), }); } private void printMessage(GLGraphics g, String[] messages) { g.glPushMatrix(); g.glMatrixMode(GLConstants.GL_PROJECTION); g.glLoadIdentity(); g.gluOrtho2D(0, width, 0, height); g.glScaled(1, -1, 1); g.glTranslated(0, -height, 0); g.glColor3d(0.0, 0.0, 1.0); int margin = fontSize / 2; int x = margin; int y = height - (margin + fontSize) * (messages.length - 1) - margin; g.glEnable(GLConstants.GL_TEXTURE_2D); for (int i = 0; i < messages.length; i++) { font.draw(messages[i], x, y, g); y += fontSize + margin; } g.glDisable(GLConstants.GL_TEXTURE_2D); g.glPopMatrix(); } class KeyController extends KeyAdapter { public void keyPressed(KeyEvent ev) { switch (ev.getKeyCode()) { case KeyEvent.VK_LEFT: speedX = 1.0f; break; case KeyEvent.VK_RIGHT: speedX = -1.0f; break; case KeyEvent.VK_UP: speedY = -1.0f; break; case KeyEvent.VK_DOWN: speedY = 1.0f; break; case KeyEvent.VK_ADD: camera.narrower(); break; case KeyEvent.VK_SUBTRACT: camera.wider(); break; default: break; } } public void keyReleased(KeyEvent ev) { switch (ev.getKeyCode()) { case KeyEvent.VK_LEFT: speedX = 0.0f; break; case KeyEvent.VK_RIGHT: speedX = -0.0f; break; case KeyEvent.VK_UP: speedY = 0.0f; break; case KeyEvent.VK_DOWN: speedY = -0.0f; break; case KeyEvent.VK_Q: System.exit(0); break; default: break; } } } class PadController implements ControllerListener { public void axisInclined(ControllerEvent ev) { float[] axisPoint = ev.getAxisPoint(); speedX = -axisPoint[0]; speedY = axisPoint[1]; } public void hatswitchChanged(ControllerEvent ev) { } public void buttonPressed(ControllerEvent ev) { } public void buttonReleased(ControllerEvent ev) { } } } class Land extends Material { public Land(String fileName, double aZ) { image = GLImageUtil.createBufferedGLImage(fileName); z = aZ; } public void init(GLGraphics g) { int[] ids = new int[1]; g.glGenTextures(1, ids); id = ids[0]; g.glBindTexture(GLConstants.GL_TEXTURE_2D, id); image.texImage(g); } public void draw(GLGraphics g) { int width = image.getWidth(); int height = image.getHeight(); int mul = 4; int[] enables = { GLConstants.GL_DEPTH_TEST, GLConstants.GL_TEXTURE_2D, }; for (int i = 0; i < enables.length; i++) { g.glEnable(enables[i]); } g.glBindTexture(GLConstants.GL_TEXTURE_2D, id); g.glTexParameterf(GLConstants.GL_TEXTURE_2D, GLConstants.GL_TEXTURE_MIN_FILTER, GLConstants.GL_NEAREST); g.glColor4d(1, 1, 1, 1); g.glScaled(mul, mul, 1); g.glTranslated(-width/2, -height/2, z); g.glBegin(GLConstants.GL_QUADS); g.glTexCoord2f(0, 0); g.glVertex3d(0, 0, 0); g.glTexCoord2f(mul, 0); g.glVertex3d(width, 0, 0); g.glTexCoord2f(mul, mul); g.glVertex3d(width, height, 0); g.glTexCoord2f(0, mul); g.glVertex3d(0, height, 0); g.glEnd(); for (int i = enables.length - 1; i >= 0; i--) { g.glDisable(enables[i]); } } private BufferedGLImage image; private int id = -1; private double z; } class Light extends Material { public Light() { super(10, 10,100); } private int index; private double radius = 10; private double angle = 0; private float[] ambient = {0.0f, 0.0f, 0.0f, 1.0f}; private float[] diffuse = {1.0f, 1.0f, 1.0f, 1.0f}; private float[] specular = {1.0f, 1.0f, 1.0f, 1.0f}; public void draw(GLGraphics g) { int[] enables = { GLConstants.GL_DEPTH_TEST, GLConstants.GL_LIGHTING, }; for (int i = 0; i < enables.length; i++) { g.glEnable(enables[i]); } g.glLightModeli(GLConstants.GL_LIGHT_MODEL_TWO_SIDE, 1); int light = GLConstants.GL_LIGHT0; g.glLightfv(light, GLConstants.GL_AMBIENT, ambient); g.glLightfv(light, GLConstants.GL_DIFFUSE, diffuse); g.glLightfv(light, GLConstants.GL_SPECULAR, specular); float[] position = new float[]{(float) getX(), (float) getY(), (float) getZ(), 1f}; g.glLightfv(light, GLConstants.GL_POSITION, position); g.glEnable(light); for (int i = enables.length - 1; i >= 0; i--) { g.glDisable(enables[i]); } } } class Camera extends Material { public Camera(double anAspectRatio, int aViewAngle, Material aTarget) { setXYZ(-20, 100, 100); target = aTarget; aspectRatio = anAspectRatio; viewAngle = aViewAngle; } private Material target; private double aspectRatio; private int viewAngle; public void setTarget(Material aTarget) { target = aTarget; } public void draw(GLGraphics g) { g.gluPerspective(viewAngle, aspectRatio, 1.0d, 1600.0d); g.gluLookAt( getX(), getY(), getZ(), target.getX(), target.getY(), target.getZ(), 0, 0, 1); } public void narrower() { viewAngle--; } public void wider() { viewAngle++; } public String toString() { return "View angle:" + viewAngle + " at: (" + getX() + "," + getY() + "," + getZ() + ") target: (" + target.getX() + "," + target.getY() + "," + target.getZ() + ")"; } } class Cube extends VisibleMaterial { public Cube() { setDiffuse(color[0], color[1], color[2], color[3]); setAmbient(color[0], color[1], color[2], color[3]); setScale(2); } private double[][] vertexList = { { -1, -1, -1}, { +1, -1, -1}, { +1, +1, -1}, { -1, +1, -1}, { -1, -1, +1}, { +1, -1, +1}, { +1, +1, +1}, { -1, +1, +1}, }; private int[][] faceList = { {0, 3, 2, 1}, {1, 2, 6, 5}, {5, 6, 7, 4}, {4, 7, 3, 0}, {4, 0, 1, 5}, {3, 7, 6, 2}, }; private double[][] normalList = { {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 1.0, 0.0}, }; float[] color = { 1.0f, 0.1f, 0.1f, 1.0f }; protected void surface(GLGraphics g) { g.glBegin(GLConstants.GL_QUADS); for (int i = 0; i < faceList.length; i++) { int[] face = faceList[i]; g.glNormal3dv(normalList[i]); for (int j = 0; j < face.length; j++) { int vertexIndex = face[j]; g.glVertex3dv(vertexList[vertexIndex]); } } g.glEnd(); } public String toString() { return "Cube at: (" + getX() + "," + getY() + "," + getZ() + ") width: " + getScale(); } } class VisibleMaterial extends Material { protected double scale = 1; protected float[] diffuse = { 0.8f, 0.8f, 0.8f, 1.0f }; protected float[] specular = { 0.0f, 0.0f, 0.0f, 1.0f }; protected float[] ambient = { 0.2f, 0.2f, 0.2f, 1.0f }; protected float[] emission = { 0.0f, 0.0f, 0.0f, 1.0f }; protected float shininess = 0.0f; protected int[] enables = { GLConstants.GL_DEPTH_TEST, GLConstants.GL_LIGHTING, }; public void draw(GLGraphics g) { for (int i = 0; i < enables.length; i++) { g.glEnable(enables[i]); } transform(g); material(g); surface(g); for (int i = enables.length - 1; i >= 0; i--) { g.glDisable(enables[i]); } } public double getScale() { return scale; } public void setScale(double newScale) { scale = newScale; } public void setDiffuse(float r, float g, float b, float a) { diffuse[0] = r; diffuse[1] = g; diffuse[2] = b; diffuse[3] = a; } public void setAmbient(float r, float g, float b, float a) { ambient[0] = r; ambient[1] = g; ambient[2] = b; ambient[3] = a; } public void setSpecular(float r, float g, float b, float a) { specular[0] = r; specular[1] = g; specular[2] = b; specular[3] = a; } public void setEmission(float r, float g, float b, float a) { emission[0] = r; emission[1] = g; emission[2] = b; emission[3] = a; } public void setShininess(float newShininess) { shininess = newShininess; } protected void transform(GLGraphics g) { g.glTranslated(getX(), getY(), getZ()); g.glScaled(scale, scale, scale); } protected void material(GLGraphics g) { g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_DIFFUSE, diffuse); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_AMBIENT, ambient); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_SPECULAR, specular); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_EMISSION, emission); g.glMaterialf(GLConstants.GL_FRONT, GLConstants.GL_SHININESS, shininess); } protected void surface(GLGraphics g) { } } class Material { public Material() {} public Material(int aX, int aY, int aZ) { this(aX, aY, aZ, 2); } public Material(int aX, int aY, int aZ, int aSpeed) { x = aX; y = aY; z = aZ; speed = aSpeed; } private double x = 0; private double y = 0; private double z = 0; private int speed = 2; public void setX(double newX) { x = newX; } public void setY(double newY) { y = newY; } public void setZ(double newZ) { z = newZ; } public void setSpeed(int newSpeed) { speed = newSpeed; } public void setXYZ(double newX, double newY, double newZ) { x = newX; y = newY; z = newZ; } public double getX() { return x; } public double getY() { return y; } public double getZ() { return z; } public int getSpeed() { return speed; } public void right() { x -= speed; } public void left() { x += speed; } public void forward() { y -= speed; } public void backward() { y += speed; } public void up() { z -= speed; } public void down() { z += speed; } public void move(double offsetX, double offsetY, double offsetZ) { x += offsetX; y += offsetY; z += offsetZ; } public void init(GLGraphics g) { } public void draw(GLGraphics g) { } }