jogl入门之简单的贪吃蛇

10年前
JOGL 是Java对于OpenGl的绑定(Java Bindings for OpenGL).
package org.ligson.jogl.test;    import java.awt.BorderLayout;  import java.awt.event.KeyEvent;  import java.awt.event.KeyListener;  import java.awt.event.WindowAdapter;  import java.awt.event.WindowEvent;  import java.util.ArrayList;  import java.util.List;  import java.util.Random;    import javax.media.opengl.GL;  import javax.media.opengl.GLAutoDrawable;  import javax.media.opengl.GLCanvas;  import javax.media.opengl.GLCapabilities;  import javax.media.opengl.GLEventListener;  import javax.swing.JFrame;    import org.ligson.jogl.test.SnakeDemo.Dir;  /*   * 事物只有一个   */  public class SnakeDemo extends JFrame implements GLEventListener, Runnable,    KeyListener {     //产生食物随机坐标   Random random = new Random();     //枚举方向   enum Dir {    UP(1), DOWN(2), LEFT(3), RIGHT(4);    final int d;      private Dir(int d) {     this.d = d;    }      public int getDir() {     return this.d;    }   }     //速度   float speed = 10.0f;   //长度   int len = 5;     // gl库的handler,相当于画笔   GL gl;   // 画布   GLCanvas canvas;   // 指定了一套OpenGL的功能:渲染内容必须支持,如色彩深度,以及立体是否已启用。   GLCapabilities capabilities;     Thread thread = new Thread(this);        //蛇集合   List<Snake> snakes = new ArrayList<Snake>();   //食物集合   List<Food> foods = new ArrayList<Food>();     public SnakeDemo() {    super("Demo4");    this.setSize(500, 500);    //屏幕中心    this.setLocationRelativeTo(null);    this.setResizable(false);      capabilities = new GLCapabilities();    canvas = new GLCanvas(capabilities);      canvas.addGLEventListener(this);      this.addKeyListener(this);    this.addWindowListener(new WindowAdapter() {     public void windowClosing(WindowEvent e) {      System.exit(0);     }    });      this.add(canvas, BorderLayout.CENTER);      thread.start();   }     @Override   public void run() {    while (true) {     try {      Thread.sleep(100);     } catch (InterruptedException e) {      e.printStackTrace();     }       canvas.display();     //检查撞击     checkHit();    }   }     @Override   public void display(GLAutoDrawable drawable) {    gl.glClear(GL.GL_COLOR_BUFFER_BIT);    gl.glClear(GL.GL_DEPTH_BUFFER_BIT);    gl.glEnable(GL.GL_DEPTH_TEST);    gl.glColor3f(1.0f, 0.0f, 0.0f);      painSnakes();    painFoods();      gl.glFlush();   }     @Override   public void displayChanged(GLAutoDrawable drawable, boolean arg1,     boolean arg2) {     }     @Override   public void init(GLAutoDrawable drawable) {    gl = drawable.getGL();    gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);      gl.glShadeModel(GL.GL_FLAT);    gl.glFrontFace(GL.GL_CW);      //初始化蛇    for (int i = 0; i < len; i++) {     Snake snake = new Snake(10.0f, 10.0f, 0.0f, i * 10.0f, Dir.UP);     snakes.add(snake);    }    //初始化食物    Food food = new Food(10.0f, 10.0f, random.nextInt(250),      random.nextInt(250));    foods.add(food);   }     @Override   public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {    if (h == 0) {     h = 1;    }      int windowWidth;    int windowHeight;      gl.glViewport(0, 0, w, h);    gl.glMatrixMode(GL.GL_PROJECTION);    gl.glLoadIdentity();      if (w <= h) {     windowWidth = 250;     windowHeight = 250 * h / w;    } else {     windowWidth = 250 * w / h;     windowHeight = 250;    }    //重新定义世界坐标系,以窗口中心为(0,0,0)    gl.glOrtho(0 - windowWidth, windowWidth, 0 - windowHeight,      windowHeight, 250.0f, -250.0f);    gl.glMatrixMode(GL.GL_MODELVIEW);    gl.glLoadIdentity();     }     public static void main(String[] args) {    SnakeDemo demo = new SnakeDemo();    demo.setVisible(true);   }     @Override   public void keyTyped(KeyEvent e) {   }     @Override   public void keyPressed(KeyEvent e) {    int key = e.getKeyCode();    switch (key) {    case KeyEvent.VK_UP:     //防止向相反方向走     if (snakes.get(0).getDir() != Dir.DOWN) {      snakes.get(0).setDir(Dir.UP);     }     break;    case KeyEvent.VK_DOWN:     if (snakes.get(0).getDir() != Dir.UP) {      snakes.get(0).setDir(Dir.DOWN);     }     break;    case KeyEvent.VK_LEFT:     if (snakes.get(0).getDir() != Dir.RIGHT) {      snakes.get(0).setDir(Dir.LEFT);     }     break;      case KeyEvent.VK_RIGHT:     if (snakes.get(0).getDir() != Dir.LEFT) {      snakes.get(0).setDir(Dir.RIGHT);     }     break;    case KeyEvent.VK_EQUALS:     len++;     break;    case KeyEvent.VK_MINUS:     len--;     if (len < 1) {      len = 1;     }     break;    default:     break;    }     }     @Override   public void keyReleased(KeyEvent e) {     }     private void painSnakes() {    int abs = len - snakes.size();    if (abs > 0) {     for (int i = 0; i < abs; i++) {      Snake lastSnake = snakes.get(snakes.size() - 1);      Snake newSnake = new Snake(10.0f, 10.0f, lastSnake.getX() + 10,        lastSnake.getY() + 10, lastSnake.getDir());      snakes.add(newSnake);     }    } else if (abs < 0) {     for (int i = 0; i < -abs; i++) {      snakes.remove(snakes.size() - 1);     }    }      for (int i = snakes.size() - 1; i >= 1; i--) {       Snake tmpSnake = snakes.get(i);     Snake prevSnake = snakes.get(i - 1);     tmpSnake.setX(prevSnake.getX());     tmpSnake.setY(prevSnake.getY());     tmpSnake.setDir(prevSnake.getDir());      }      Snake snake = snakes.get(0);    int h = getContentPane().getHeight();    int w = getContentPane().getWidth();      switch (snake.getDir().getDir()) {    case 1:     if ((snake.getY() + speed - 10.0f) > (h / 2.0)) {      snake.setY(-250.0f);     } else {      snake.setY(snake.getY() + speed);     }       break;    case 2:     if ((snake.getY() + speed + snake.getHeight()) < -(h / 2.0)) {      snake.setY(250.0f);     } else {      snake.setY(snake.getY() - speed);     }       break;    case 3:     if ((snake.getX() + speed + snake.getWidth()) < -(w / 2.0)) {      snake.setX(250.0f);     } else {      snake.setX(snake.getX() - speed);     }     break;    case 4:     if ((snake.getX() + speed - 10.0f) > (w / 2.0)) {      snake.setX(-250.0f);     } else {      snake.setX(snake.getX() + speed);     }     break;    }    snakes.set(0, snake);      for (Snake snake2 : snakes) {     snake2.pain(gl);    }   }     private void painFoods() {    if (foods.size() == 0) {     Food food = new Food(10.0f, 10.0f, random.nextInt(250),       random.nextInt(250));     foods.add(food);    }      for (Food food : foods) {     food.pain(gl);    }   }     private void checkHit() {    for (Snake snake : snakes) {     for (Food food : foods) {      if (Math.abs(snake.getX() - food.getX()) < 10.0f        && Math.abs(snake.getY() - food.getY()) < 10.0f) {       len++;       foods.remove(food);       break;      }     }    }   }  }    class Food {   private float width = 10.0f;   private float height = 10.0f;   private float x = 0.0f;   private float y = 0.0f;     public Food(float width, float height, float x, float y) {    super();    this.width = width;    this.height = height;    this.x = x;    this.y = y;   }     public float getWidth() {    return width;   }     public void setWidth(float width) {    this.width = width;   }     public float getHeight() {    return height;   }     public void setHeight(float height) {    this.height = height;   }     public float getX() {    return x;   }     public void setX(float x) {    this.x = x;   }     public float getY() {    return y;   }     public void setY(float y) {    this.y = y;   }     public void pain(GL gl) {    gl.glBegin(GL.GL_QUADS);    gl.glVertex3f(this.x, this.y, 0.0f);    gl.glVertex3f(this.x, this.y + height, 0.0f);    gl.glVertex3f(this.x + width, this.y + height, 0.0f);    gl.glVertex3f(this.x + width, this.y, 0.0f);    gl.glEnd();   }    }    class Snake {   private float width = 10.0f;   private float height = 10.0f;   private float x = 0.0f;   private float y = 0.0f;   private Dir dir = Dir.UP;     private Random random = new Random();     public Snake(float width, float height, float x, float y, Dir dir) {    super();    this.width = width;    this.height = height;    this.x = x;    this.y = y;    this.dir = dir;   }     public float getWidth() {    return width;   }     public void setWidth(float width) {    this.width = width;   }     public float getHeight() {    return height;   }     public void setHeight(float height) {    this.height = height;   }     public float getX() {    return x;   }     public void setX(float x) {    this.x = x;   }     public float getY() {    return y;   }     public void setY(float y) {    this.y = y;   }     public Dir getDir() {    return dir;   }     public void setDir(Dir dir) {    this.dir = dir;   }     public float[] getPoints() {    return null;   }     public void pain(GL gl) {    gl.glColor3f(random.nextFloat(), random.nextFloat(), random.nextFloat());    gl.glBegin(GL.GL_QUADS);    gl.glVertex3f(this.x, this.y, 0.0f);    gl.glVertex3f(this.x, this.y + height, 0.0f);    gl.glVertex3f(this.x + width, this.y + height, 0.0f);    gl.glVertex3f(this.x + width, this.y, 0.0f);    gl.glEnd();   }     public String toString() {    return "X:" + this.x + ";Y:" + this.y;     }  }