Verge 4 API Proposal -------------------- This very very very work-in-progress idea for the API in a potential Verge 4, if there were to be one. I'm attempting NOT to reinvent the wheel too much, but improve the performance, flexibility and stability of engine available for rapid-prototyping, based on the lessons learned from old Verge generations and other similar engines. As much as possible, old or existing code will be utilized. Here are some of the things I plan on using: * Inspiration: - Verge3 - salvaging good parts, keeping mild support for old things so stuff like maped3 can be used until an actual editor is made. - ika (andy's game engine) - fury2 (kael's engine) - plum (my unfinished Lua engine) - trouser (my unfinished engine I made in highschool for An Epic of Gladiatorial Proportions) * audiere for audio (not FMOD - since module playback is crappy, and because it is proprietary) * corona for images * zziplib for packfile support - plain zips, none of this weird blobbed VPK stuff - might allow .zips to be named .vpk to make them less easy to be edited, but no planned support for the old bad format. - I actually have file interfaces written for zziplib to play nice with audiere/corona, meaning no temp files needed (Verge 3 uses temporaries, which is bad, considering it doesn't work if the current directory is read-only). * zlib for compression * Lua for scripting (not VergeC) * OpenGL for rendering (not DirectDraw, which is deprecated and screws up Aero) * Either going to use epsilon (andy's lib with Windows and X support -- trying this first) - OR - SDL (as a fallback, because I hate some of SDL's shortcomings, like the inability to resize a window without nuking the GL context, and the retarded changing of the mouse cursor when visible) for input/windowing/OpenGL management. Not decided yet. Hey you! -------- I'm looking for people who'd want to help me do this! This is an insane amount of code to do by myself. Even if I'm not reinventing the wheel ENTIRELY, it's a lot of crap, and I don't have time for it all on my own. If you desire a good engine, or contributing to an engine that could become good, then help me out. I'd prefer if that any changes to the API are discussed before committed. By providing this API, it is my hope that it can be split up between people and done faster. It'll also make it easier to see any oversights, and get a general impression of how the end-product will be used. I'd also like feedback, and would be willing to hear discussions from people who can't necessarily help through C++ code, but know what they want from a game engine. There is a repository at: http://github.com/Bananattack/verge2d Also please talk to me through MSN (overkill9999@hotmail.com), AIM (Minimum Overkill), IRC (irc.lunarnet.org as Overkill), or email. Okay, now, I present you with the planned library: Table of Contents ----------------- 1. General a. Classes * v4.Vector b. Functions 2. Graphics a. Classes * v4.Canvas * v4.Image * v4.AnimationSheet * v4.AnimationTable * v4.Animator * v4.TileAnimator * v4.Font * v4.Primitive * v4.Camera * v4.RenderList b. Polygon Primitives * v4.Line * v4.Triangle * v4.Rectangle * v4.Polygon * v4.Ellipse c. Image Primitives * v4.Sprite * v4.TileMap * v4.Text d. Functions e. Constants * v4.Alignment * v4.BlendMode 3. Audio a. Classes * v4.SoundEffect * v4.Audiostream 4. Filesystem and IO a. Functions b. Implementation Notes 5. World a. Classes * v4.Map * v4.Entity * v4.VSP 6. Input a. Button * v4.Button * v4.Control b. Keyboard c. Mouse d. Joystick e. Built-in Controls 1. General ---------- 1.a. Classes ------------ * v4.Vector: Creates a 2-dimensional vector, which is a numeric pair (x, y). Constructor: v4.Vector(x, y) Creates a vector from the two numeric components passed. Attributes: self.x -> number Returns the first item in the pair. self.y -> number Returns the second item in the pair. Methods: Maybe later. 1.b. Functions -------------- v4.ShowPage() Refreshes the screen and updates a bunch of engine state, such as controls. v4.Sleep(centiseconds) Rests the CPU for a short amount of time. v4.GetTime() Gets the amount of time elapsed since program start. 2. Graphics ----------- 2.a. Classes ------------ * v4.Canvas: A software image stored in regular memory. Allows simple off-screen manipulations. Constructors: v4.Canvas(string filename) Load an image from disk. v4.Canvas(v4.Vector size) Creates an image with the given size. v4.Canvas(v4.Canvas canvas) Copies the canvas given. Attributes: self.size -> v4.Vector The size of the canvas. Methods: Yeah, it'll have some. Note to self: use Plum/ika/Verge/fury2 blitters so I don't write an entire software blitter lib from scratch. * v4.Image: A hardware image stored in video memory. Constructors: v4.Image(string filename) Load an image from disk. v4.Image(v4.Canvas canvas) Create an image from a copy of the given canvas. Attributes: self.size -> v4.Vector The size of the image. * v4.AnimationSheet: A hardware image with frame information. Constructors: v4.AnimationSheet(string filename, v4.Vector size[, boolean padding]) Create an animation sheet from the given file with specified frame sizes and optional padding. v4.AnimationSheet(v4.Canvas canvas, v4.Vector size[, boolean padding]) Create an animation sheet from the given canvas with specified frame sizes and optional padding. v4.AnimationSheet(v4.Image image, v4.Vector size[, boolean padding]) Create an animation sheet from the given image with specified frame sizes and optional padding. Attributes: self.frameSize -> v4.Vector The size of each frame in the sheet. self.sheetSize -> v4.Vector (read-only) The size of the entire sheet. * v4.AnimationTable: A collection of animations that can be stepped through. Constructors: v4.AnimationTable({ string label = string strand } strands) Create a table of mapping animation strings each to a label. Methods: self:Get(string label) -> string Gets the strand associated with the given label, or nil on failure. self:Set(string label, string strand) Sets the strand associated with the given label. self:Remove(string label) Removes the strand associated with the given label. self:Clear() Clears all strands from the animation table. * v4.Animator: An object that can step through a strand of frames in an animation sheet. Constructor: v4.Animator([string strand]) Creates an animator, using the optional strand to iterate over. Attributes: self.strand -> string self.position -> number self.wait -> number self.frame -> number Methods: self:SwitchStrand(string label) Switches to the strand associated with the given label in the animation sheet. self:Update() Steps through an animation. * v4.TileAnimator: An object that steps over all strands of frames in an animation sheet at once. Used to reindex tiles as necessary. No strands in the sheet may use the same tile index, or this is an error. This is verified on construction. Additionally, the strands should cycle for animations to loop. Constructor: v4.TileAnimator(v4.AnimationTable table) Creates a tile animator, using the animation table as a reference. Read constraints to the sheet above. Method: self:Update() Steps through all tile animations at once. * v4.Font: A font that is constructed from specially arranged sheet of glyphs in ASCII order. Constructors: v4.Font(string filename) Loads a font. Attributes: self.size -> v4.Vector (read-only) The size of each cell in the font. self.subsets -> number Number of font subsets, making it possible to have multiple sets or colorizations of glyphs within a single font. Methods: self:EnableVariableWidth() Enables variable width mode, causing unused pixel space in font glyphs to be collapsed. This makes it so rather than monospace text, you can have text with glyphs of varying size. * v4.Primitive: An object that can be drawn directly to the screen. This is an abstract concept, the real primitives are subtypes of this. Attributes: self.angle -> number in radians The angle to rotate the primitive by. self.scale -> v4.Vector The ratio to resize this primitive by. self.center -> v4.Vector The center of the shape. self.blendMode -> v4.BlendMode The blend mode of the rendering. May be one of v4.BlendMode's members: Add, Subtract, Alpha, Opaque. Methods: self:Render([camera]) Draws the primitive to the screen, optionally using the camera as a reference point, and clipping to screen edges. self:SetOverallColor(number color) Changes the overall color, used throughout the entire shape Subtypes: v4.Triangle, v4.Rectangle, v4.Polygon, v4.Line, v4.Ellipse * v4.Camera: An object used to find positions Constructors: v4.Camera() v4.Camera(number x, number y) v4.Camera(v4.Primitive) Attributes: camera.x -> number (alias for camera.position.x) camera.y -> number (alias for camera.position.y) camera.angle -> number in radians camera.position -> v4.Vector camera.scale -> v4.Vector camera.target -> v4.Primitive * v4.RenderList A collection of primitives that are to be rendered to the screen. This is more efficient than sending the primitives individually! This is due to shared transformation/rotation/scaling of a camera reference, and better GPU pipelining. It does not invoke the primitives' render methods through Lua, and instead uses lower-level invokations. Constructors: v4.RenderList(v4.Primitive primitive) v4.RenderList({v4.Primitive} primitives) Create a render list containing the given list of primitives Methods: self:Add(v4.Primitive primitive) self:Add({v4.Primitive} primitives) Adds the list of primitives to the end of the render list. self:Get(number index) -> v4.Primitive Gets the primitive at the given index of the render list. self:Set(number index, v4.Primitive value) Replaces the primitive at the given index of the render list with the specified value. self:Remove(number index) Removes the primitive at the given index, decreasing the numbering of the entries after it. self:Clear() Clears all primitives from the render list. self:Size() -> number Gets the number of primitives in this list. self:Render([camera]) Draws the render list to the screen, optionally using the camera as a reference point, and clipping to screen edges. Example: local poly = v4.Poly({ v4.Vector(4, 0), v4.Vector(0, 4), v4.Vector(8, 4) }, v4.RGB(0, 0, 255), false) local rect = v4.Rect(v4.Vector(0, 0), v4.Vector(50, 50), v4.RGB(255, 0, 0), true) local spr = v4.Sprite(v4.Vector(0, 0), v4.Image('hero.png')) local renderList = v4.RenderList({poly, rect, spr}) renderList:Render() 2.b. Polygon Primitives ----------------------- * v4.Line: Extends v4.Primitive. A line connecting two points. Constructors: v4.Line(v4.Vector a, v4.Vector b, number overallColor) Creates a line of the given overall color. v4.Line(v4.Vector a, v4.Vector b, {number} colors) Like above, but takes the colors, ordered {colorA, colorB} Attributes: self.points[i] -> v4.Vector Returns the ith point in the line. * v4.Triangle: Extends v4.Primitive. A shape which has exactly three points. Constructors: v4.Triangle(v4.Vector a, v4.Vector b, v4.Vector c, number overallColor[, boolean filled]) Creates a triangle of the given overall color. v4.Triangle(v4.Vector a, v4.Vector b, v4.Vector c, {number} colors[, boolean filled]) Like above, but takes a table of 3 colors in the order { colorA, colorB, colorC } Attributes: self.points[i] -> v4.Vector Returns the ith point in the triangle. self.colors[i] -> v4.Color Returns the color of the ith vertex. self.filled -> boolean Whether or not it is filled. * v4.Rectangle: Extends v4.Primitive. A rectangle with its origin positioned at the top-left corner of the rectangle. Constructors: v4.Rect(v4.Vector position, v4.Vector size, number overallColor[, boolean filled]) Creates a rectangle of the given overall color. v4.Rect(v4.Vector position, v4.Vector size, {number} colors[, boolean filled]) Like above but takes a table of 4 colors, in clock-wise order from top-left. Attributes: self.position -> v4.Vector The corner of the rectangle. self.size -> v4.Vector The dimensions of the rectangle. self.colors[i] -> v4.Color Returns the color of the ith vertex in the rectangle, going clockwise. self.filled -> boolean Whether or not it is filled. Subtypes: v4.Sprite * v4.Polygon: Extends v4.Primitive. A shape containing multiple vertices. Constructors: v4.Polygon({v4.Vector} verts, number overallColor[, boolean filled]) Creates a polygon of the given overall color. v4.Polygon({v4.Vector} verts, {number} colors[, boolean filled]) Like above but takes a table of colors, ordered by the vertex. Attributes: self.points[i] -> v4.Vector Returns the ith point in the polygon. self.colors[i] -> v4.Color Returns the color of the ith vertex. self.filled -> boolean Whether or not it is filled. * v4.Ellipse: Extends v4.Primitive. A circular shape that has a horizontal and vertical radius. Constructors: v4.Ellipse(v4.Vector center, v4.Vector radius, number overallColor[, boolean filled]) Creates an ellipse of the given overall color. v4.Ellipse(v4.Vector center, v4.Vector radius, {number} color[, boolean filled]) Same as above, but takes a table of colors, ordered {colorInside, colorOutside} Attributes: self.radius -> v4.Vector The radius of the ellipse. self.filled -> boolean Whether or not it is filled. Returns the colors of the ellipse self.colors[i] -> v4.Color The colors used by this ellipse, ordered {colorInside, colorOutside}. 2.c. Image Primitives --------------------- * v4.Sprite: Extends v4.Rectangle. A frame of a spritesheet image drawn onto a rectangle. Fill parameter ignored. Colors, when changed, are utilized as a tint. Constructors: v4.Sprite(v4.Vector position, string image) v4.Sprite(v4.Vector position, v4.Canvas image) v4.Sprite(v4.Vector position, v4.Image image) Creates a sprite with a single frame, made from the entire image/canvas. v4.Sprite(v4.Vector position, v4.AnimationSheet sheet) Creates a sprite with a bunch of frames. Attributes: self.sheet -> v4.AnimationSheet The sheet containing the frames of the image. self.frame The frame to draw. * v4.TileMap: Extends v4.Primitive. A rectangular grid of tiles, all sharing a common image. If overall color is set, then it is used to tint the tilemap. Constructors: v4.TileMap(v4.Vector position, v4.Vector gridSize, v4.AnimationSheet sheet) Create a tilemap, using the sheet as tile indices within the map. Attributes: self.sheet -> v4.AnimationSheet The sheet containing the tiles of the image. self.tileAnimator -> v4.TileAnimator (optional) The optional tile animator associated with this sprite, that handles all animations in the tilemap's animation sheet. Remaps the tiles appearances as animation occurs. If nil, then no tile remapping is done. self.gridSize -> v4.Vector (read-only) The size of the tilemap's grid in tiles. Methods: self:GetOverallColor() -> number Return the overall color (tint) of this tilemap. self:GetTile(number x, number y) -> number Gets tile at the grid location (x, y). self:SetTile(number x, number y, number tile) Changes the tile at the grid location (x, y). * v4.Text: Extends v4.Primitive. A block of text created from a string passed to a v4.Font. Constructor: v4.Text(v4.Vector position, v4.Font font[, string message[, v4.Alignment alignment]]) Creates a text block at the given position with the given font. Message is optional and defaults to "". Alignment is optional, and defaults to v4.Alignment.Left. Attributes: self.content -> string The contents of the text block, as a string. self.font -> v4.Font The font associated with this text. self.alignment -> v4.Alignment Can be v4.Alignment.Left, v4.Alignment.Center, or v4.Alignment.Right. Methods: self:GetOverallColor() -> number Return the overall color (tint) of this block of text. self:GetLineWidth(i) -> number The width of the ith line of text in pixels. self:GetOverallWidth() -> number The width of the largest line of text in pixels. self:GetOverallHeight() -> number The height of the text in pixels. 2.d. Functions -------------- v4.RGB(number red, number green, number blue[, number alpha]) -> number Gets the color associated with the corresponding red/green/blue (and optional alpha). v4.HSV(number hue, number saturation, number value[, number alpha]) -> number Gets the color associated with the corresponding hue/saturation/value (and optional alpha). v4.GetRGBA(number color) -> number, number, number, number Gets red, green, blue and alpha channels of the color. v4.GetHSVA(number color) -> number, number, number, number Gets hue, saturation, and value as well as the alpha channel of the color. 2.e. Constants -------------- * v4.Alignment A table containing valid alignments that can be assigned to text. v4.Alignment.Left - left-justified. v4.Alignment.Right - right-justified. v4.Alignment.Center - centered. * v4.BlendMode A table containing different blending modes used by graphics routines v4.BlendMode.Add - additively blends pixels, by adding their RGB values together. v4.BlendMode.Subtract - subtractively blends pixels, by subtracting their RGB values. v4.BlendMode.Alpha - blends pixels 'normally', with alpha transparency if found. v4.BlendMode.Opaque - draw pixels with no regard to alpha channel transparency. 3. Audio -------- 3.a. Classes ------------ * v4.SoundEffect: A simple sound effect, which can be played in a pool of multiple channels. Constructors: v4.SoundEffect(string filename) Loads the sample from a file. Methods: self:Play([volume[, pan]]) Starts playing the sound in a fresh channel. self:Stop() Stops playing all the channels associated with this sound. * v4.AudioStream: A sound stream that which can be looped. Its position may also be tracked and changed. Only one instance can be played at a time. Constructors: v4.Song(string filename) Loads the sample from a file. Attributes: self.volume -> number The volume of the playback. 0 = silent, 1 = full volume self.position -> number The position in the playback. self.pan -> number The stereo panning. -1 = left speaker, 0 = center, 1 = right speaker. self.playing -> boolean self.looping -> boolean Methods: self:Play() Starts the playback. self:Stop() Stops the playback. Next call to Play will start at the beginning. self:Pause() Pauses the playback. Next call to Play will resume where it left off. 4. Filesystem and IO -------------------- 4.a. Functions -------------- v4.StripFileExtension(string filename) -> string Returns a filename with its extension stripped. v4.GetFileExtension(string filename) -> string Returns an extension extracted from a filename. v4.ListFilePattern(string pattern) -> {string} Gets an array of filenames that match a given wildcard pattern. 4.b. Implementation Notes ------------------------- * For starters, try NOT to add more new ground than is needed. * Packfiles are zips. zziplib can open and treat these like folders with ease. * Override Lua's io and os stuff with a mostly equivalent version that allows packfiles: - Why? This saves time inventing a new API - Things that will need replacement/adaptation + io library, packfile support, remove stdin/out. + print needs to go v4.log. + dofile, packfile support, remove stdin/out. + loadfile, packfile support, remove stdin/out. + require is easiest, just add an entry to package.loaders that can use a packfile-based loading function. - OS library seems harmful? But at the same time, it DOES have a few useful things. * Use LuaSocket for sockets, it already seems to do sockets right. * Maybe later add a nice set of v4 classes that do equivalent things, but for now, these seem more than adequate. 5. World -------- 5.a. Classes ------------ * v4.Map: A map that contains layered tilemaps with entities on them. Constructor: v4.Map(string filename) v4.Map(number width, number height) Attributes: Methods: * v4.Entity: An entity that can walk around a map. Constructor: v4.Entity(number x, number y, number layer, string filename) Attributes: Methods: * v4.VSP: A tileset that comes from an funky container format. Constructor: v4.VSP(string filename) Attributes: Methods: WORLD STUFF IS ALL A BIG WIP. 6. Input -------- 6.a. Classes ------------ * v4.Button A button is a simple thing that just indicates whether it is pressed or not. Attributes: self.pressed -> boolean Indicates whether a given button is pressed or not. If set to false, the key is unpressed. * v4.Control Extends v4.Button. A control encapsulates a button type that can be received from multiple different input sources. Constructors: v4.Control({v4.Button} buttons) Creates a list of buttons. User-defined button classes are also acceptable. Attributes: self.pressed -> boolean Indicates whether some button mapped to this control is pressed. Methods: self:Add(v4.Button button) Adds another button to the list. self:Remove(number i) Removes the ith button in the list. self:Get(number i) Gets the ith button in the list. self.Set(number i, v4.Button button) Changes the ith button in the control's list. 6.b. Keyboard ------------- v4.key[keyname] -> v4.Button ALSO, WALL OF KEY SCANCODES CAN GO HERE. 6.c. Mouse ---------- v4.mouse.x -> number v4.mouse.y -> number v4.mouse.wheel -> number v4.mouse.left -> v4.Button v4.mouse.middle -> v4.Button v4.mouse.right -> v4.Button 6.d. Joystick ------------- TODO, needs support for buttons, analog support, d-pad support, POV-hat, pressure-sensing shoulder triggers, shoulder buttons, blah blah. 6.e. Built-in Controls ---------------------- The following are built-in control types, because they are common in a lot of games. They are controls that are mapped to both a key and some joystick input. v4.up -> v4.Button v4.down -> v4.Button v4.left -> v4.Button v4.right -> v4.Button v4.b1 -> v4.Button v4.b2 -> v4.Button v4.b3 -> v4.Button v4.b4 -> v4.Button