diff --git a/.todo b/.todo index 271309f..3880b85 100644 --- a/.todo +++ b/.todo @@ -1,2 +1 @@ - finish bowling demo -- finish ag and std documentation diff --git a/Engine.cc b/Engine.cc index 53a1443..387bdc7 100644 --- a/Engine.cc +++ b/Engine.cc @@ -215,7 +215,7 @@ bool Engine::load(const char * program) void Engine::checkForAllHandlerFunctions() { - checkForFunction("init", init); + checkForFunction("init_event", init); checkForFunction("update_event", update); checkForFunction("update_overlay_event", update_overlay); checkForFunction("key_down_event", key_down); @@ -557,8 +557,6 @@ void Engine::drawLine(float r, float g, float b, { checkGLError(); glPushAttrib(GL_LINE_BIT | GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); glLineWidth(width); glBegin(GL_LINES); @@ -578,8 +576,6 @@ void Engine::drawRect(float r, float g, float b, glPushMatrix(); glTranslatef(x, y, 0); glRotatef(rot, 0, 0, 1); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); glBegin(GL_LINE_LOOP); glColor3f(r, g, b); @@ -601,8 +597,6 @@ void Engine::fillRect(float r, float g, float b, glPushMatrix(); glTranslatef(x, y, 0); glRotatef(rot, 0, 0, 1); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); glEnable(GL_POLYGON_SMOOTH); glBegin(GL_QUADS); glColor3f(r, g, b); @@ -620,14 +614,16 @@ void Engine::drawImage(float width, float height, float x, float y, int tex, float rot) { checkGLError(); - glPushAttrib(GL_ENABLE_BIT); + /* TODO: check following flags */ + glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_LIGHTING_BIT); glPushMatrix(); glTranslatef(x, y, 0); glRotatef(rot, 0, 0, 1); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); glEnable(GL_POLYGON_SMOOTH); glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBindTexture(GL_TEXTURE_2D, tex); glBegin(GL_QUADS); glTexCoord2f(0, 0); @@ -644,6 +640,29 @@ void Engine::drawImage(float width, float height, float x, float y, checkGLError(); } +void Engine::drawArc(float r, float g, float b, float x, float y, + float radius, float a1, float a2) +{ + a1 *= M_PI / 180.0f; + a2 *= M_PI / 180.0f; + int segments = 1 + (int) (fabsf(a2 - a1) / (M_2_PI / 16.0f)); + float step = (a2 - a1) / segments; + glPushAttrib(GL_ENABLE_BIT); + glPushMatrix(); + glTranslatef(x, y, 0); + glColor3f(r, g, b); + glBegin(GL_LINE_STRIP); + float angle = a1; + for (int i = 0; i <= segments; i++) + { + glVertex2f(radius * cos(angle), radius * sin(angle)); + angle += step; + } + glEnd(); + glPopMatrix(); + glPopAttrib(); +} + /* called by SDL when the update timer expires */ Uint32 Engine::updateCallback(Uint32 interval, void * param) { @@ -762,27 +781,28 @@ void Engine::update_overlay_event() { checkGLError(); glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - int width = m_video.getWidth(); - int height = m_video.getHeight(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, width, 0, height, -1.01, 1.01); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + int width = m_video.getWidth(); + int height = m_video.getHeight(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, width, 0, height, -1.01, 1.01); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); - lua_getfield(m_luaState, LUA_GLOBALSINDEX, - EVENT_HANDLER_AG_NAME(update_overlay)); - lua_pushnumber(m_luaState, width); - lua_pushnumber(m_luaState, height); - /* call the update_overlay function - * - pops the function ref from the stack, then the arguments */ - int s = lua_pcall(m_luaState, 2, 0, 0); - reportErrors(s); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + lua_getfield(m_luaState, LUA_GLOBALSINDEX, + EVENT_HANDLER_AG_NAME(update_overlay)); + lua_pushnumber(m_luaState, width); + lua_pushnumber(m_luaState, height); + /* call the update_overlay function + * - pops the function ref from the stack, then the arguments */ + int s = lua_pcall(m_luaState, 2, 0, 0); + reportErrors(s); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); glPopAttrib(); checkGLError(); } diff --git a/Engine.h b/Engine.h index 6eee940..1a2c841 100644 --- a/Engine.h +++ b/Engine.h @@ -151,6 +151,8 @@ class Engine float width, float height, float x, float y, float rot = 0.0f); void drawImage(float width, float height, float x, float y, int tex, float rot = 0.0f); + void drawArc(float r, float g, float b, float x, float y, + float radius, float a1, float a2); /* lua services */ int setCamera(lua_State * L); diff --git a/ag.cc b/ag.cc index 08f93b0..fdc43ec 100644 --- a/ag.cc +++ b/ag.cc @@ -23,6 +23,9 @@ namespace ag static const luaL_Reg functions[] = { { "clearEventHandler", clearEventHandler }, { "doPhysics", doPhysics }, + { "drawArc", drawArc }, + { "drawCircle", drawCircle }, + { "drawImage", drawImage }, { "drawLine", drawLine }, { "drawObjects", drawObjects }, { "drawRect", drawRect }, @@ -55,8 +58,8 @@ namespace ag { "createBoxStatic", createBoxStatic }, { "createCapsule", createCapsule }, { "createCapsuleStatic", createCapsuleStatic }, - { "createCylinder", createCylinder }, - { "createCylinderStatic", createCylinderStatic }, +// { "createCylinder", createCylinder }, +// { "createCylinderStatic", createCylinderStatic }, { "createPlane", createPlane }, { "createSphere", createSphere }, { "createSphereStatic", createSphereStatic }, @@ -478,13 +481,67 @@ namespace ag return 0; } + int drawArc(lua_State * L) + { + int argc = lua_gettop(L); + if (argc == 8) + { + bool valid = true; + for (int i = 1; i <= argc; i++) + { + if (!lua_isnumber(L, i)) + valid = false; + } + if (valid) + { + g_engine->drawArc( + lua_tonumber(L, 1), + lua_tonumber(L, 2), + lua_tonumber(L, 3), + lua_tonumber(L, 4), + lua_tonumber(L, 5), + lua_tonumber(L, 6), + lua_tonumber(L, 7), + lua_tonumber(L, 8)); + } + } + return 0; + } + + int drawCircle(lua_State * L) + { + int argc = lua_gettop(L); + if (argc == 6) + { + bool valid = true; + for (int i = 1; i <= argc; i++) + { + if (!lua_isnumber(L, i)) + valid = false; + } + if (valid) + { + g_engine->drawArc( + lua_tonumber(L, 1), + lua_tonumber(L, 2), + lua_tonumber(L, 3), + lua_tonumber(L, 4), + lua_tonumber(L, 5), + lua_tonumber(L, 6), + 0.0, + 360.0); + } + } + return 0; + } + int drawImage(lua_State * L) { int argc = lua_gettop(L); if (argc == 5 || argc == 6) { bool valid = true; - for (int i = 1; i <= 6; i++) + for (int i = 1; i <= argc; i++) if (i != 5 && !lua_isnumber(L, i)) valid = false; if (!lua_istable(L, 5)) diff --git a/ag.h b/ag.h index 8d54356..4ae18c4 100644 --- a/ag.h +++ b/ag.h @@ -34,6 +34,8 @@ namespace ag int startFrame(lua_State * L); /* 2D overlay functions */ + int drawArc(lua_State * L); + int drawCircle(lua_State * L); int drawImage(lua_State * L); int drawLine(lua_State * L); int drawRect(lua_State * L); diff --git a/doc/index.html b/doc/index.html index 1eb7394..7853454 100644 --- a/doc/index.html +++ b/doc/index.html @@ -29,6 +29,8 @@ The library functions are documented below.
  • std library
  • +
  • Lua Event Handlers
  • +
  • Key Names

  • @@ -42,16 +44,8 @@ The library functions are documented below.

    This function removes a Lua callback function from being associated with the engine event specified. -event_name should be one of the following strings: -

    +event_name should be a string containing an event name. +See Lua event handlers for a list of events.

    @@ -64,6 +58,48 @@ mode is enabled; this mode is enabled by default. See setAutoPhysics for more information.

    + +

    drawArc

    +

    ag.drawArc(r, g, b, x, y, radius, a1, a2)

    +

    +This function tells the engine to draw an arc to the screen. +The color of the arc is specified by (r, g, b). +x and y specify the coordinates of the center +of the arc. +The arc ranges from angle a1 to a2, which are +specified in degrees, going counter-clockwise from the East. +drawArc() should normally be called from the +update_overlay event handler. +

    + +
    +

    drawCircle

    +

    ag.drawCircle(r, g, b, x, y, radius)

    +

    +This function tells the engine to draw a circle to the screen. +The color of the circle is specified by (r, g, b). +x and y specify the coordinates of the center +of the circle. +drawCircle() should normally be called from the +update_overlay event handler. +

    + +
    +

    drawImage

    +

    ag.drawImage(width, height, x, y, texture, [, rot])

    +

    +This function tells the engine to draw an image to the screen. +width and height specify the size of the image, +in pixels. +x and y specify the coordinates of the center +of the image. +The image to be drawn is specified by texture, which +should be loaded by +ag.loadTexture(). +drawImage() should normally be called from the +update_overlay event handler. +

    +

    drawLine

    ag.drawLine(r, g, b, x1, y1, x2, y2 [, width])

    @@ -206,7 +242,7 @@ libraries such as
    std. This function returns a boolean value for whether or not the key given by key is currently pressed or not. key should be a string corresponding to a key name. -See keys for key names. +See Key Names for key names.

    @@ -280,16 +316,8 @@ occurs. There can be only one registered handler per event, so if a previous Lua function was registered for event_name, it will be overwritten to call the new handler. -event_name should be one of: - +event_name should be a string containing the name of the event. +See Lua event handlers for a list of event names.

    When the Lua script is initially loaded, any functions found @@ -624,6 +652,16 @@ ag.import("std")

    + +

    createPlanePointNormal

    +

    obj = std.createPlanePointNormal(x, y, z, nx, ny, nz)

    +

    +This function simply wraps +ag.createPlane() +allowing the user to specify a point on the plane with coordinates (x, y, z) +and the surface normal of the plane (nx, ny, nz). +

    +

    crossProduct

    cp = std.crossProduct(vec1, vec2)

    @@ -648,15 +686,286 @@ The indices of vec1 and vec2 should be from 1 to 3. This allows specifying a Lua array directly as a parameter to the function.

    -
    -

    createPlanePointNormal

    -

    obj = std.createPlanePointNormal(x, y, z, nx, ny, nz)

    +
    +

    pctx

    +

    pixels_x = std.pctx(percent)

    -This function simply wraps -ag.createPlane() -allowing the user to specify a point on the plane with coordinates (x, y, z) -and the surface normal of the plane (nx, ny, nz). +This function returns the number of pixels corresponding to +percent percent of the screen's X axis. +percent should be between 0.0 and 1.0.

    + +

    pcty

    +

    pixels_y = std.pcty(percent)

    +

    +This function returns the number of pixels corresponding to +percent percent of the screen's Y axis. +percent should be between 0.0 and 1.0. +

    + + +
    + +
    +

    Lua Event Handlers

    + +

    +The following is a list of all events that the Anaglym engine +handles: +

    +Lua callback functions may be registered for each of these events. +

    + +

    +When a Lua script is loaded, any defined function that matches the +name of an engine event with "_event" appended will +automatically be registered as a callback for that engine event. +For example, a function named key_up_event() in +a loaded Lua script will automatically be registered to receive +key_up event notifications. +

    + +

    +The prototypes for the Lua event handler callback functions follow. +

    + + +

    update

    +

    function update_event()

    +

    +This function is called for every frame that is drawn on the screen. +It could be called up to a few dozen times per second. +

    + +
    +

    update_overlay

    +

    function update_overlay_event(width, height)

    +

    +This function is called immediately after the update +function. +During this event, the coordinate system is reset from the normal +3D system to a 2D system. +The coordinates range from (0, 0) in the lower-left corner of the +screen to (width, height) in the upper-right corner of the screen. +In this mode, depth testing is disabled, so any graphics drawn will +"overlay" whatever is currently on the screen. +width and height contain the size of the +Anaglym engine window, in pixels. +

    + +
    +

    key_down

    +

    function key_down_event(key_name)

    +

    +This function is called when a key is initially pressed. +key_name is a string containing the name of the +key pressed. +See Key Names for a list of key names. +

    + + +

    key_up

    +

    function key_up_event(key_name)

    +

    +This function is called when a key is released. +key_name is a string containing the name of the +key released. +See Key Names for a list of key names. +

    + + +

    mousebutton_down

    +

    function mousebutton_down_event(button, x, y)

    +

    +This function is called when a mouse button is pressed. +button contains the number of the button pressed +(1: left, 2: middle, 3: right, 4: scroll wheel up, 5: scroll wheel down). +The position of the cursor when the mouse button was pressed is at +(x, y). +This position is only meaningful when the cursor is shown. +By default, it is hidden. +Cursor visibility can be toggled with the F2 key. +

    + +
    +

    mousebutton_up

    +

    function mousebutton_up_event(button, x, y)

    +

    +This function is called when a mouse button is released. +button contains the number of the button released +(1: left, 2: middle, 3: right, 4: scroll wheel up, 5: scroll wheel down). +The position of the cursor when the mouse button was released is at +(x, y). +This position is only meaningful when the cursor is shown. +By default, it is hidden. +Cursor visibility can be toggled with the F2 key. +

    + +
    +

    mouse_motion

    +

    function mouse_motion_event(x, y, xrel, yrel)

    +

    +This function is called when the mouse moves. +(x, y) specifies the position that the cursor was moved to. +This position is only meaningful when the cursor is shown. +xrel and yrel contain the relative +movement distance. +These values are meaningful regardless of the cursor visibility state. +

    + + +
    + +
    +

    Key Names

    + + + diff --git a/lib/std.lua b/lib/std.lua index 8626d73..2554cf9 100644 --- a/lib/std.lua +++ b/lib/std.lua @@ -43,3 +43,23 @@ std.createPlanePointNormal = function(x, y, z, nx, ny, nz) -- invoke the ag routine to create a plane based on a, b, c, d parameters return ag.createPlane(nx, ny, nz, nx * x, ny * y, nz * z) end + +-- Convert screen percent to pixel count along X axis +-- Input: +-- percent: percent (0.0 - 1.0) of the screen's X axis +-- Output: +-- Number of pixels corresponding to 'percent' percent of the X axis +std.pctx = function(percent) + local width = ag.getScreenSize() + return width * percent +end + +-- Convert screen percent to pixel count along Y axis +-- Input: +-- percent: percent (0.0 - 1.0) of the screen's Y axis +-- Output: +-- Number of pixels corresponding to 'percent' percent of the Y axis +std.pcty = function(percent) + local width, height = ag.getScreenSize() + return height * percent +end diff --git a/tests/ballstairs.lua b/tests/ballstairs.lua index b91bcfb..94cd6f8 100755 --- a/tests/ballstairs.lua +++ b/tests/ballstairs.lua @@ -1,5 +1,5 @@ -function init() +function init_event() arena = ag.loadModelStatic("boxarena") ball = ag.loadModel("checkerball") ball:setPosition(-7, 7.4, 12) diff --git a/tests/bowling.lua b/tests/bowling.lua index fe748c9..246ab77 100644 --- a/tests/bowling.lua +++ b/tests/bowling.lua @@ -1,5 +1,5 @@ -function init() +function init_event() local rows = 5 local offset = 1 local pin = ag.loadModel("bowling_pin", 0.5) diff --git a/tests/cannon.lua b/tests/cannon.lua index de69779..906a76c 100644 --- a/tests/cannon.lua +++ b/tests/cannon.lua @@ -1,5 +1,5 @@ -function init() +function init_event() local levels = 7 local crate = ag.loadModel("crate", 0.5) local offset = 0.5 diff --git a/tests/cratestack.lua b/tests/cratestack.lua index cbc9772..d462e90 100644 --- a/tests/cratestack.lua +++ b/tests/cratestack.lua @@ -1,5 +1,5 @@ -function init() +function init_event() crates = {} levels = 5 diff --git a/tests/imagetest.lua b/tests/imagetest.lua new file mode 100644 index 0000000..a0bd184 --- /dev/null +++ b/tests/imagetest.lua @@ -0,0 +1,17 @@ + +function init_event() + ag.import("std") + image = ag.loadTexture("transparent.png") + local crate = ag.loadModelStatic("crate") + ag.setCamera(5, -5, 5) +end + +function update_overlay_event(width, height) + local time = ag.elapsedTime() + local rot = time / 1000 * 90 + local scale = math.sin(time / 1000) * 1.5 / 2 + 1.25 + ag.drawImage(256 * scale, 256 * scale, width / 2, height / 2, image, rot); + ag.drawArc(1, 0, 0.5, width * 0.8, height * 0.8, height * 0.15, + 90, 180); + ag.drawCircle(0, 0, 1, width * 0.8, height * 0.2, height * 0.15); +end diff --git a/tests/managed_objects.lua b/tests/managed_objects.lua index 11971ae..d970933 100644 --- a/tests/managed_objects.lua +++ b/tests/managed_objects.lua @@ -1,5 +1,5 @@ -function init() +function init_event() local crate_texture = ag.loadTexture("checker.jpg") local ground = ag.createPlaneStatic(0, 0, 1, 0) ground:setColor(0.2, 1.0, 0.2) diff --git a/tests/transparent.png b/tests/transparent.png new file mode 100644 index 0000000..e811708 Binary files /dev/null and b/tests/transparent.png differ