class Game PHYSICS_FPS = 60.0 PHYSICS_INTERVAL = 1.0 / PHYSICS_FPS WORLD_WIDTH = 64 WORLD_HEIGHT = 16 R0 = WORLD_WIDTH / (2.0 * Math::PI) R1 = R0 + 1.0 VIEW_ROTATION_SPEED = 0.25 * Math::PI def initialize @leftover_dt = 0.0 end def opengl_context_created @world = File.read('level.txt').gsub(/\n/, '').enum_for(:each_byte).map { |b| if b == ?. then nil else :wall end } @view_angle = 0.0 glDepthFunc(GL_LEQUAL) glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) end def opengl_context_resized(w, h) @width, @height = w, h end def display(dt) _update(dt) _draw() end def text_entered(text) end def key_pressed(keycode) end def key_released(keycode) end def mouse_pressed(button) end def mouse_released(button) end def mouse_moved_by(dx, dy) end def mouse_moved_to(x, y) end def _update(dt) @leftover_dt += dt while @leftover_dt >= PHYSICS_INTERVAL do @view_angle += VIEW_ROTATION_SPEED * PHYSICS_INTERVAL if @view_angle > Math::PI then @view_angle -= 2.0 * Math::PI end @leftover_dt -= PHYSICS_INTERVAL end end def _draw() glClearColor(1.0, 1.0, 0.0, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(30.0, 8.0 / 5.0, 1.0, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt( -R0 * Math.cos(@view_angle), 6.0, -R0 * Math.sin(@view_angle), Math.cos(@view_angle), 6.0, Math.sin(@view_angle), 0.0, 1.0, 0.0) glLightfv(GL_LIGHT0, GL_POSITION, [ -1.0, -1.0, 0.0, 0.0 ].pack('f*')) angle_fraction = 2.0 * Math::PI / WORLD_WIDTH glBegin(GL_QUADS) 0.upto(WORLD_HEIGHT - 1) do |_y| y = WORLD_HEIGHT - 1 - _y 0.upto(WORLD_WIDTH - 1) do |x| i = x + _y * WORLD_WIDTH next unless @world[i] angle0 = x * angle_fraction angle1 = angle0 + angle_fraction s0 = Math.sin(angle0) c0 = Math.cos(angle0) s1 = Math.sin(angle1) c1 = Math.cos(angle1) v = [ [ c0 * R0, y , s0 * R0 ], [ c1 * R0, y , s1 * R0 ], [ c1 * R0, y + 1, s1 * R0 ], [ c0 * R0, y + 1, s0 * R0 ], [ c0 * R1, y , s0 * R1 ], [ c1 * R1, y , s1 * R1 ], [ c1 * R1, y + 1, s1 * R1 ], [ c0 * R1, y + 1, s0 * R1 ], ].map { |v| v.pack('f*') } glNormal3f(-s0, 0.0, -c0) glVertex3fv(v[0]) glVertex3fv(v[1]) glVertex3fv(v[2]) glVertex3fv(v[3]) glNormal3f(0.0, 0.0, 0.0) glVertex3fv(v[4]) glVertex3fv(v[0]) glVertex3fv(v[3]) glVertex3fv(v[7]) glNormal3f(0.0, 0.0, 0.0) glVertex3fv(v[1]) glVertex3fv(v[5]) glVertex3fv(v[6]) glVertex3fv(v[2]) glNormal3f(0.0, 1.0, 0.0) glVertex3fv(v[3]) glVertex3fv(v[2]) glVertex3fv(v[6]) glVertex3fv(v[7]) glNormal3f(0.0, -1.0, 0.0) glVertex3fv(v[5]) glVertex3fv(v[4]) glVertex3fv(v[0]) glVertex3fv(v[1]) end end glEnd() end end $game = Game.new