Skip to content

Instantly share code, notes, and snippets.

@DanielVF
Created October 26, 2008 23:42
Show Gist options
  • Save DanielVF/19971 to your computer and use it in GitHub Desktop.
Save DanielVF/19971 to your computer and use it in GitHub Desktop.
-- Learning both Lua, and OpenGL. Probably NOT GOOD CODE.
-- But it's pretty in action.
-- Click to add squares.
require 'luagl'
require 'luaglut'
local fps = 60
local msec = 1000 / fps
quit = false
local remap_timer = 10
local map_size = {x=640,y=480}
local screen_padding = -10
local soldiers = {}
WorldGrid = {}
function WorldGrid:init(resolution,world_size_x,world_size_y)
self.grid = {}
self.resolution = resolution
self.world_size_x = world_size_x
self.world_size_y = world_size_y
self.scale_x = world_size_x/resolution
self.scale_y = world_size_y/resolution
self.objectcell = {}
for x=0,resolution-1 do
self.grid[x]={}
for y=0,resolution-1 do
local cell = {}
cell.objects={}
cell.x=x
cell.y=y
self.grid[x][y] = cell
end
end
end
function WorldGrid:new(resolution,world_size_x,world_size_y)
o = setmetatable({},{__index=WorldGrid})
WorldGrid.init(o,resolution,world_size_x,world_size_y)
return o
end
function WorldGrid:set(object,v)
local x = math.floor(v.x / self.scale_x)
local y = math.floor(v.y / self.scale_y)
local new_cell = self.grid[x][y]
if new_cell == nil then return end
-- new object?
if self.objectcell[object] == nil then
self.objectcell[object]=new_cell
new_cell.objects[object]=true
-- moved?
elseif not (self.objectcell[object] == new_cell) then
self.objectcell[object].objects[object] = nil
self.objectcell[object] = new_cell
new_cell.objects[object] = true
end
end
function WorldGrid:neighbors(object,v)
local cell = self.objectcell[object]
local out = {}
local near_cell = nil
for x=cell.x-1, cell.x+1 do
if self.grid[x] then
for y=cell.y-1, cell.y+1 do
near_cell = self.grid[x][y]
if near_cell then
for k,v in pairs(near_cell.objects) do
if not (k==object) then
table.insert(out,k)
end
end
end
end
end
end
return out
end
function WorldGrid:dump()
print("WORLD GRID DUMP")
for x=0,self.resolution-1 do
for y=0,self.resolution-1 do
local cell = self.grid[x][y]
for k,v in pairs(cell.objects) do
print("item",x,y)
end
end
end
end
local world_grid = WorldGrid:new(10,map_size.x,map_size.y);
local function make_soldiers(x,y,x2,y2)
for i=1, 4 do
local soldier = {x=math.random(x,x2),y=math.random(y,y2)}
soldier.velocity = {x=math.random()*2-1,y=math.random()*2-1}
table.insert(soldiers,soldier)
world_grid:set(soldier,{x=soldier.x,y=soldier.y})
end
end
function scatter_soildiers()
for i,soldier in ipairs(soldiers) do
soldier.x = soldier.x + math.random(-20,20)
soldier.y = soldier.y + math.random(-20,20)
end
end
make_soldiers(40,40,map_size.x,40)
Vect = {}
function Vect.normalize(a)
local dist = math.sqrt( (a.x^2) + (a.y^2) )
if dist == 0 then return {x=0,y=1} end
return { x = a.x / dist, y = a.y / dist }
end
function Vect.multiplys(a,v)
return { x = a.x * v, y = a.y * v }
end
function Vect.plus(a,b)
return { x = a.x + b.x, y = a.y + b.y }
end
function Vect.minus(a,b)
return { x = a.x - b.x, y = a.y - b.y }
end
function draw_soldier(soldier)
if soldier.velocity.y > 0 then
glColor3d(1,0,0)
else
glColor3d(0.2,0,0)
end
glRectd(soldier.x-5,soldier.y-4,soldier.x+5,soldier.y+4)
end
function is_too_close(soldier)
local distance = 0
for i,other_guy in ipairs(world_grid:neighbors(soldier)) do
if not (other_guy == soldier) then
distance = math.sqrt((soldier.x - other_guy.x)^2 + (soldier.y - other_guy.y)^2)
if distance < 30 then
local diff = Vect.minus(soldier,other_guy)
diff = Vect.multiplys(Vect.normalize(diff),0.2)
soldier.velocity = Vect.normalize(Vect.plus(soldier.velocity,diff))
end
end
end
end
local function display_func()
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
for i,soldier in ipairs(soldiers) do
is_too_close(soldier)
if soldier.y > map_size.y + screen_padding then
soldier.velocity.y = -1
end
if soldier.y < 0 - screen_padding then
soldier.velocity.y = 1
end
if soldier.x > map_size.x + screen_padding then
soldier.velocity.x = - 1
end
if soldier.x < 0 - screen_padding then
soldier.velocity.x = 1
end
soldier.x = soldier.x + soldier.velocity.x
soldier.y = soldier.y + soldier.velocity.y
draw_soldier(soldier)
end
if remap_timer < 1 then
for i,soldier in ipairs(soldiers) do
world_grid:set(soldier,{x=soldier.x,y=soldier.y})
end
remap_timer = 10
end
remap_timer = remap_timer - 1
-- world_grid:dump()
glutSwapBuffers()
end
local function keyboard_func(key)
print(key)
if key == 27 then
quit = true
glutDestroyWindow(window)
os.exit(0)
end
end
function resize_func(w, h)
local ratio = w / h
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glViewport(0,0,w,h)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glOrtho(0, map_size.x, 0, map_size.y, 0, 1);
glEnable(GL_LEQUAL)
glEnable(GL_NORMALIZE)
end
function timer_func()
if quit then return end
glutSetWindow(window)
glutTimerFunc(msec, timer_func, 0)
glutPostRedisplay()
end
function mouse_func(button,state,x,y)
if state == GLUT_UP then
y = map_size.y- y
make_soldiers(x-5,y-5,x+5,y+5)
else return end
end
glutInit()
glutInitDisplayMode(GLUT_RGB + GLUT_DOUBLE)
glutInitWindowSize(map_size.x,map_size.y)
window = glutCreateWindow("BOB")
glutDisplayFunc(display_func)
glutKeyboardFunc(keyboard_func)
glutMouseFunc(mouse_func)
glutReshapeFunc(resize_func)
glutTimerFunc(msec, timer_func, 0)
start_time = glutGet(GLUT_ELAPSED_TIME)
glutMainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment