diff --git a/README.md b/README.md index 362dfbe..4ba4a1d 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ PROGRAMMING INTERFACE Drawing functions: * fill(r,g,b,alpha): select the drawing color. +* filled(filled): set the filled state (true or false) * background(r,g,b): paint the whole background with the specified color. * rect(x,y,width,height): draw a rectangle at x,y (left-bottom corner). * ellipse(x,y,width,height): draw an ellipse centered at x,y. @@ -57,7 +58,22 @@ Drawing functions: * text(x,y,string): print the specified text at x,y using a bitmap font. * triangle(x1,y1,x2,y2,x3,y3): draw a triangle with the specified vertex. * getpixel(x,y): return the red,gree,blue value of the specified pixel. -* sprite(file,x,y,[rotation],[antialiasing]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default false). +* polygon(xv, yv): draw a polygon using a table of X values and a table of Y values. + +Sprite functions: + +* sprite(file,[x,y,[rotation],[antialiasing]]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default false). + +Returns a sprite userdata object, with the following functions + +* getHeight(): returns the height of the sprite. +* getWidth(): returns the height of the sprite. +* getTiles(): returns x,y for the number of tiles horizontally and vertically. +* setTiles(x,y): set the number of tiles horizontally and vertically. +* getTileSize(): return w,h for the size of a tile, calculated from the width and height of the image divided by the number of tiles horizontally and vertically. +* getTileNum(): returns the number of tiles. +* tile(x,y,tileNum,[rotation],[antialiasing]): draw a tile using tileNum at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default: false). +* draw(x,y,[rotation],[antialiasing]): draw sprite at coordinates with the specified rotation (in degrees, default 0) and antialiasing (default: false). Control functions: diff --git a/editor.c b/editor.c index 5bcf8bd..b1cb7eb 100644 --- a/editor.c +++ b/editor.c @@ -374,7 +374,7 @@ void editorDrawCursor(void) { y -= E.margin_top; if (!(E.cblink & 0x80)) drawBox(E.fb,x+charmargin,y, x+charmargin+FONT_KERNING-1,y+FONT_HEIGHT-1, - 165,165,255,128); + 165,165,255,128,1); E.cblink += 4; } @@ -412,25 +412,25 @@ void editorDrawChars(void) { } void editorDrawPowerOff(int x, int y) { - drawEllipse(E.fb,x,y,12,12,66,66,231,255); - drawEllipse(E.fb,x,y,7,7,165,165,255,255); - drawBox(E.fb,x-4,y,x+4,y+12,165,165,255,255); - drawBox(E.fb,x-2,y,x+2,y+14,66,66,231,255); + drawEllipse(E.fb,x,y,12,12,66,66,231,255,1); + drawEllipse(E.fb,x,y,7,7,165,165,255,255,1); + drawBox(E.fb,x-4,y,x+4,y+12,165,165,255,255,1); + drawBox(E.fb,x-2,y,x+2,y+14,66,66,231,255,1); } void editorDrawSaveIcon(int x, int y) { - drawBox(E.fb,x-12,y-12,x+12,y+12,66,66,231,255); - drawBox(E.fb,x-1,y+7,x+1,y+11,165,165,255,255); - drawEllipse(E.fb,x,y,4,4,165,165,255,255); + drawBox(E.fb,x-12,y-12,x+12,y+12,66,66,231,255,1); + drawBox(E.fb,x-1,y+7,x+1,y+11,165,165,255,255,1); + drawEllipse(E.fb,x,y,4,4,165,165,255,255,1); } void editorDraw() { - drawBox(E.fb,0,0,E.fb->width-1,E.fb->height-1,165,165,255,255); + drawBox(E.fb,0,0,E.fb->width-1,E.fb->height-1,165,165,255,255,1); drawBox(E.fb, E.margin_left, E.margin_bottom, E.fb->width-1-E.margin_right, - E.fb->height-1-E.margin_top,66,66,231,255); + E.fb->height-1-E.margin_top,66,66,231,255,1); editorDrawChars(); editorDrawCursor(); /* Show buttons */ @@ -473,24 +473,38 @@ void editorMouseClicked(int x, int y, int button) { } else if (x >= E.margin_left && x <= E.fb->width-1-E.margin_right && y >= E.margin_bottom && y <= E.fb->height-1-E.margin_top) { - int realheight = E.fb->height - E.margin_top - E.margin_bottom; - int realy = y - E.margin_bottom; - int row = (realheight-realy)/FONT_HEIGHT; - int col = (x-E.margin_left)/FONT_KERNING; - int filerow = E.rowoff+row; - int filecol = E.coloff+col; - erow *r = (filerow >= E.numrows) ? NULL : &E.row[filerow]; - - E.cblink = 0; - if (filerow == E.numrows) { - E.cx = 0; - E.cy = filerow-E.rowoff; - } else if (r) { - if (filecol >= r->size) - E.cx = r->size-E.coloff; - else - E.cx = filecol-E.coloff; - E.cy = filerow-E.rowoff; + if (button == 4) { + if (E.rowoff) { + E.rowoff--; + if (E.cy < E.screenrows - 1) E.cy++; + } + } + else if (button == 5) { + if (E.rowoff + E.screenrows < E.numrows) { + E.rowoff++; + if (E.cy > 0) E.cy--; + } + } + else { + int realheight = E.fb->height - E.margin_top - E.margin_bottom; + int realy = y - E.margin_bottom; + int row = (realheight-realy)/FONT_HEIGHT; + int col = (x-E.margin_left)/FONT_KERNING; + int filerow = E.rowoff+row; + int filecol = E.coloff+col; + erow *r = (filerow >= E.numrows) ? NULL : &E.row[filerow]; + + E.cblink = 0; + if (filerow == E.numrows) { + E.cx = 0; + E.cy = filerow-E.rowoff; + } else if (r) { + if (filecol >= r->size) + E.cx = r->size-E.coloff; + else + E.cx = filecol-E.coloff; + E.cy = filerow-E.rowoff; + } } } } @@ -500,6 +514,7 @@ void editorMoveCursor(int key) { int filecol = E.coloff+E.cx; int rowlen; erow *row = (filerow >= E.numrows) ? NULL : &E.row[filerow]; + int temp; switch(key) { case SDLK_LEFT: @@ -534,6 +549,61 @@ void editorMoveCursor(int key) { } } break; + case SDLK_PAGEUP: + if (E.rowoff) { + E.rowoff -= E.screenrows - 1; + if (E.rowoff < 0) { + E.rowoff = 0; + E.cy = 0; + } + } + else { + if (E.cy > 0) E.cy = 0; + } + break; + case SDLK_PAGEDOWN: + if (E.rowoff + E.screenrows - 1 < E.numrows) { + E.rowoff += E.screenrows - 1; + if (E.rowoff + E.screenrows - 1 > E.numrows) E.cy = E.numrows - E.rowoff - 1; + } + else { + E.cy = E.numrows - E.rowoff - 1; + } + break; + case SDLK_HOME: + if (E.modifiers & CTRL_MASK) { + E.rowoff = E.coloff = E.cy = E.cx = 0; + } + else { + if (row && filecol != 0) { + temp = getFirstNonSpace(row); + if (temp > -1) { + if (filecol > temp) { + E.cx = temp; + E.coloff = 0; + } + else { + E.cx = E.coloff = 0; + } + } + } + } + break; + case SDLK_END: + if (E.modifiers & CTRL_MASK) { + E.rowoff = E.numrows - E.screenrows; + E.cy = E.screenrows - 1; + E.coloff = E.cx = 0; + } + else { + if (row && filecol < row->size) { + if (row->size - E.screencols + 1 > 0) { + E.coloff = row->size - E.screencols + 1; + } + E.cx = row->size - E.coloff; + } + } + break; } /* Fix cx if the current line has not enough chars. */ filerow = E.rowoff+E.cy; @@ -549,6 +619,16 @@ void editorMoveCursor(int key) { } } +int getFirstNonSpace(erow *row) { + int i; + for (i = 0; i < row->size; i++) { + if (row->chars[i] != ' ' && row->chars[i] != '\t') { + return i; + } + } + return -1; +} + int editorEvents(void) { SDL_Event event; int j, ksym; @@ -578,6 +658,24 @@ int editorEvents(void) { E.key[ksym].counter = 1; E.key[ksym].translation = (event.key.keysym.unicode & 0xff); } + switch(ksym) { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + E.modifiers |= SHIFT_MASK; + break; + case SDLK_LCTRL: + case SDLK_RCTRL: + E.modifiers |= CTRL_MASK; + break; + case SDLK_LALT: + case SDLK_RALT: + E.modifiers |= ALT_MASK; + break; + case SDLK_LMETA: + case SDLK_RMETA: + E.modifiers |= META_MASK; + break; + } break; } break; @@ -586,6 +684,24 @@ int editorEvents(void) { case SDL_KEYUP: ksym = event.key.keysym.sym; if (ksym >= 0 && ksym < KEY_MAX) E.key[ksym].counter = 0; + switch(ksym) { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + E.modifiers &= ~SHIFT_MASK; + break; + case SDLK_LCTRL: + case SDLK_RCTRL: + E.modifiers &= ~CTRL_MASK; + break; + case SDLK_LALT: + case SDLK_RALT: + E.modifiers &= ~ALT_MASK; + break; + case SDLK_LMETA: + case SDLK_RMETA: + E.modifiers &= ~META_MASK; + break; + } break; /* Mouse click */ case SDL_MOUSEBUTTONDOWN: @@ -610,6 +726,10 @@ int editorEvents(void) { case SDLK_RIGHT: case SDLK_UP: case SDLK_DOWN: + case SDLK_PAGEUP: + case SDLK_PAGEDOWN: + case SDLK_HOME: + case SDLK_END: editorMoveCursor(j); break; case SDLK_BACKSPACE: @@ -618,7 +738,6 @@ int editorEvents(void) { case SDLK_RETURN: editorInsertNewline(); break; - case SDLK_HOME: case SDLK_LSHIFT: case SDLK_RSHIFT: case SDLK_LCTRL: @@ -699,4 +818,5 @@ void initEditor(frameBuffer *fb, int mt, int mb, int ml, int mr) { E.dirty = 0; E.filename = NULL; memset(E.key,0,sizeof(E.key)); + E.modifiers = 0; } diff --git a/editor.h b/editor.h index cfa6fe3..739a2fb 100644 --- a/editor.h +++ b/editor.h @@ -28,6 +28,12 @@ #define HL_FUNCDEF_COLOR {255,255,255} #define HL_LIB_COLOR {255,0,255} +/* Key Held Modifier Bit Masks */ +#define CTRL_MASK (1<<0) +#define SHIFT_MASK (1<<1) +#define ALT_MASK (1<<2) +#define META_MASK (1<<3) + typedef struct erow { int size; /* Size of the row, excluding the null term. */ char *chars; /* Row content. */ @@ -56,6 +62,7 @@ struct editorConfig { erow *row; /* Rows */ time_t lastevent; /* Last event time, so we can go standby */ keyState key[KEY_MAX]; /* Remember if a key is pressed / repeated. */ + unsigned int modifiers; /* Key modifiers held. CTRL & SHIFT & ALT & META */ int dirty; /* File modified but not saved. */ char *filename; /* Currently open filename */ frameBuffer *fb; /* Framebuffer */ @@ -76,4 +83,6 @@ void editorClearError(void); int editorFileWasModified(void); void editorRun(void); +int getFirstNonSpace(erow *row); + #endif /* EDITOR_H */ diff --git a/examples/flames.lua b/examples/flames.lua index f2ff89c..acc1d22 100644 --- a/examples/flames.lua +++ b/examples/flames.lua @@ -10,6 +10,7 @@ function setup() refreshCount = 0 skipCount = 0 Flames = { } + filled(false) for i=1,MaxFlames do x = math.random(WIDTH/3) + (WIDTH/3) @@ -26,9 +27,11 @@ function draw() background(0,0,0) for i,f in pairs(Flames) do if f.l > 35 then + filled(true) fill(255, 255, 255, 0.9) minMove = 0 elseif f.l > 30 then + filled(false) fill(255, 255, 192, 0.8) minMove = 1 elseif f.l > 20 then diff --git a/framebuffer.c b/framebuffer.c index 65ced77..24b6e3d 100644 --- a/framebuffer.c +++ b/framebuffer.c @@ -34,6 +34,7 @@ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen) { SDL_initFramerate(&fb->fps_mgr); /* Load the bitmap font */ bfLoadFont((char**)BitmapFont); + gfb = fb; return fb; } @@ -51,22 +52,40 @@ void drawHline(frameBuffer *fb, int x1, int x2, int y, int r, int g, int b, int hlineRGBA(fb->screen, x1, x2, fb->height-1-y, r, g, b, alpha); } -void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha) { - filledEllipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); +void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha, char filled) { + if (filled) + filledEllipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); + else + ellipseRGBA(fb->screen, xc, fb->height-1-yc, radx, rady, r, g, b, alpha); } -void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha) { - boxRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); +void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha, char filled) { + if (filled) + boxRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); + else + rectangleRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } -void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha) { - filledTrigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); +void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha, char filled) { + if (filled) + filledTrigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); + else + trigonRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, x3, fb->height-1-y3, r, g, b, alpha); } void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha) { lineRGBA(fb->screen, x1, fb->height-1-y1, x2, fb->height-1-y2, r, g, b, alpha); } +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha, char filled) { + int i; + for (i=0; iheight-1-yv[i]; + if (filled) + filledPolygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); + else + polygonRGBA(fb->screen, xv, yv, n, r, g, b, alpha); +} + /* ============================= Bitmap font =============================== */ void bfLoadFont(char **c) { /* Set all the entries to NULL. */ @@ -105,7 +124,8 @@ void bfWriteString(frameBuffer *fb, int xp, int yp, const char *s, int len, int * the same interface with load81.c. */ #define SPRITE_MT "l81.sprite_mt" -void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa) { +/* +void spriteBlit(frameBuffer *fb, sprite *sprite, int x, int y, int angle, int aa) { SDL_Surface *s = sprite; if (s == NULL) return; if (angle) s = rotozoomSurface(s,angle,1,aa); @@ -113,24 +133,62 @@ void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa) SDL_BlitSurface(s, NULL, fb->screen, &dst); if (angle) SDL_FreeSurface(s); } +*/ + +void spriteBlit(frameBuffer *fb, sprite *sp, int x, int y, int tileNum, int angle, int aa) { + SDL_Surface *s = sp->surf; + if (s == NULL) return; + + if (tileNum >= 0) { + SDL_Rect dst = {x, fb->height-1-y - sp->tileH, sp->tileW, sp->tileH}; + SDL_Rect src = {(tileNum%sp->tileY) * sp->tileW, (tileNum / sp->tileY) * sp->tileH, sp->tileW, sp->tileH}; + if (angle) { + SDL_Surface *temp = SDL_CreateRGBSurface(SDL_SWSURFACE, sp->tileW, sp->tileH, fb->screen->format->BitsPerPixel, 0, 0, 0, 0); + SDL_Surface *tempRot; + SDL_BlitSurface(s, &src, temp, NULL); + tempRot = rotozoomSurface(temp,angle,1,aa); + SDL_BlitSurface(tempRot, NULL, fb->screen, &dst); + SDL_FreeSurface(tempRot); + SDL_FreeSurface(temp); + } + else { + SDL_BlitSurface(s, &src, fb->screen, &dst); + } + } + else { + SDL_Rect dst = {x, fb->height-1-y - s->h, s->w, s->h}; + if (angle) s = rotozoomSurface(s,angle,1,aa); + SDL_BlitSurface(s, NULL, fb->screen, &dst); + if (angle) SDL_FreeSurface(s); + } +} + /* Load sprite. Return surface pointer and object on top of stack */ -void *spriteLoad(lua_State *L, const char *filename) { - SDL_Surface **pps; +sprite *spriteLoad(lua_State *L, const char *filename) { + sprite *pps; /* check if image was already loaded and cached */ lua_getglobal(L, "sprites"); lua_getfield(L, -1, filename); if (lua_isnil(L, -1)) { /* load image into surface */ - SDL_Surface *ps = IMG_Load(filename); - if (ps == NULL) { + sprite ps; + ps.surf = IMG_Load(filename); + if (ps.surf == NULL) { luaL_error(L, "failed to load sprite %s", filename); return NULL; } + ps.w = ps.surf->w; + ps.h = ps.surf->h; + ps.tileX = 0; + ps.tileY = 0; + ps.tileW = ps.w; + ps.tileH = ps.h; + /* box the surface pointer in a userdata */ - pps = (SDL_Surface **)lua_newuserdata(L, sizeof(SDL_Surface *)); + pps = (sprite*)lua_newuserdata(L, sizeof(sprite)); *pps = ps; /* set sprite metatable */ @@ -142,34 +200,92 @@ void *spriteLoad(lua_State *L, const char *filename) { lua_setfield(L, -4, filename); } else { /* unbox surface pointer */ - pps = (SDL_Surface **)luaL_checkudata(L, -1, SPRITE_MT); + pps = (sprite *)luaL_checkudata(L, -1, SPRITE_MT); } - return *pps; + return pps; } int spriteGC(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - if (pps) SDL_FreeSurface(*pps); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + if (pps) SDL_FreeSurface(pps->surf); return 0; } int spriteGetHeight(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - lua_pushnumber(L, (*pps)->h); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->h); return 1; } int spriteGetWidth(lua_State *L) { - SDL_Surface **pps = (SDL_Surface **)luaL_checkudata(L, 1, SPRITE_MT); - lua_pushnumber(L, (*pps)->w); + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->w); return 1; } +int spriteGetTiles(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileX); + lua_pushnumber(L, pps->tileY); + return 2; +} + +int spriteSetTiles(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + pps->tileX = lua_tonumber(L, 2); + pps->tileY = lua_tonumber(L, 3); + pps->tileW = pps->w / pps->tileX; + pps->tileH = pps->h / pps->tileY; + return 0; +} + +int spriteGetTileSize(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileW); + lua_pushnumber(L, pps->tileH); + return 2; +} + +int spriteGetTileNum(lua_State *L) { + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + lua_pushnumber(L, pps->tileX * pps->tileY); + return 1; +} + +int spriteDrawTile(lua_State *L) { + int x, y, tileNum, angle, antialiasing; + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + x = lua_tonumber(L, 2); + y = lua_tonumber(L, 3); + tileNum = lua_tonumber(L,4); + angle = luaL_optnumber(L,5,0); + antialiasing = lua_toboolean(L,6); + spriteBlit(gfb, pps, x, y, tileNum, angle, antialiasing); + return 0; +} + +int spriteDraw(lua_State *L) { + int x, y, angle, antialiasing; + sprite *pps = (sprite *)luaL_checkudata(L, 1, SPRITE_MT); + x = lua_tonumber(L, 2); + y = lua_tonumber(L, 3); + angle = luaL_optnumber(L,4,0); + antialiasing = lua_toboolean(L,5); + spriteBlit(gfb, pps, x, y, -1, angle, antialiasing); + return 0; +} + static const struct luaL_Reg sprite_m[] = { - { "__gc", spriteGC }, - { "getHeight", spriteGetHeight }, - { "getWidth", spriteGetWidth }, - { NULL, NULL } + { "__gc", spriteGC }, + { "getHeight", spriteGetHeight }, + { "getWidth", spriteGetWidth }, + { "getTiles", spriteGetTiles }, + { "setTiles", spriteSetTiles }, + { "getTileSize", spriteGetTileSize }, + { "getTileNum", spriteGetTileNum }, + { "tile", spriteDrawTile }, + { "draw", spriteDraw }, + { NULL, NULL } }; void initSpriteEngine(lua_State *L) { diff --git a/framebuffer.h b/framebuffer.h index 0a20367..741f515 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -21,6 +21,8 @@ typedef struct frameBuffer { FPSmanager fps_mgr; } frameBuffer; +frameBuffer *gfb; + /* Frame buffer */ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen); @@ -28,19 +30,30 @@ frameBuffer *createFrameBuffer(int width, int height, int bpp, int fullscreen); void setPixelWithAlpha(frameBuffer *fb, int x, int y, int r, int g, int b, int alpha); void fillBackground(frameBuffer *fb, int r, int g, int b); void drawHline(frameBuffer *fb, int x1, int x2, int y, int r, int g, int b, int alpha); -void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha); -void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); -void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha); +void drawEllipse(frameBuffer *fb, int xc, int yc, int radx, int rady, int r, int g, int b, int alpha, char filled); +void drawBox(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha, char filled); +void drawTriangle(frameBuffer *fb, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b, int alpha, char filled); void drawLine(frameBuffer *fb, int x1, int y1, int x2, int y2, int r, int g, int b, int alpha); +void drawPolygon(frameBuffer *fb, Sint16* xv, Sint16* yv, int n, int r, int g, int b, int alpha, char filled); /* Bitmap font */ void bfLoadFont(char **c); void bfWriteChar(frameBuffer *fb, int xp, int yp, int c, int r, int g, int b, int alpha); void bfWriteString(frameBuffer *fb, int xp, int yp, const char *s, int len, int r, int g, int b, int alpha); +typedef struct sprite { + int w; + int h; + int tileX; + int tileY; + int tileW; + int tileH; + SDL_Surface *surf; +} sprite; + /* Sprites */ -void spriteBlit(frameBuffer *fb, void *sprite, int x, int y, int angle, int aa); -void *spriteLoad(lua_State *L, const char *filename); +void spriteBlit(frameBuffer *fb, sprite *sp, int x, int y, int tileNum, int angle, int aa); +sprite *spriteLoad(lua_State *L, const char *filename); void initSpriteEngine(lua_State *L); #endif /* FRAMEBUFFER_H */ diff --git a/load81.c b/load81.c index 0450cdb..08af1bf 100644 --- a/load81.c +++ b/load81.c @@ -135,6 +135,11 @@ int fillBinding(lua_State *L) { return 0; } +int filledBinding(lua_State *L) { + l81.filled = lua_toboolean(L,-1); + return 0; +} + int rectBinding(lua_State *L) { int x,y,w,h; @@ -142,7 +147,7 @@ int rectBinding(lua_State *L) { y = lua_tonumber(L,-3); w = lua_tonumber(L,-2); h = lua_tonumber(L,-1); - drawBox(l81.fb,x,y,x+(w-1),y+(h-1),l81.r,l81.g,l81.b,l81.alpha); + drawBox(l81.fb,x,y,x+(w-1),y+(h-1),l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -153,7 +158,7 @@ int ellipseBinding(lua_State *L) { y = lua_tonumber(L,-3); rx = lua_tonumber(L,-2); ry = lua_tonumber(L,-1); - drawEllipse(l81.fb,x,y,rx,ry,l81.r,l81.g,l81.b,l81.alpha); + drawEllipse(l81.fb,x,y,rx,ry,l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -166,7 +171,7 @@ int triangleBinding(lua_State *L) { y2 = lua_tonumber(L,-3); x3 = lua_tonumber(L,-2); y3 = lua_tonumber(L,-1); - drawTriangle(l81.fb,x1,y1,x2,y2,x3,y3,l81.r,l81.g,l81.b,l81.alpha); + drawTriangle(l81.fb,x1,y1,x2,y2,x3,y3,l81.r,l81.g,l81.b,l81.alpha,l81.filled); return 0; } @@ -212,6 +217,49 @@ int backgroundBinding(lua_State *L) { return 0; } +int polygonBinding(lua_State *L) { + Sint16* polyBufferX; + Sint16* polyBufferY; + + if (!(lua_gettop(L) == 2 && lua_istable(L,-1) && lua_istable(L,-2))) { + programError("Invalid arguments for polygon"); + return 0; + } + + int size = (int)lua_objlen(L,-1), i=0; + polyBufferY = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + while(lua_next(L,-2) != 0) { + polyBufferY[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; + } + + lua_pop(L,1); + + if (size != (int)lua_objlen(L,-1)) { + programError("Array size mismatch in call to polygon"); + return 0; + } + polyBufferX = (Sint16*)malloc(size * sizeof(Sint16)); + lua_pushnil(L); + i=0; + while(lua_next(L,-2) != 0) { + polyBufferX[i++] = (Sint16)lua_tonumber(L,-1); + lua_pop(L,1); + if (i > size) break; + } + + drawPolygon(l81.fb, polyBufferX, polyBufferY, size, l81.r, l81.g, l81.b, l81.alpha, l81.filled); + + free(polyBufferX); + free(polyBufferY); + return 0; +} + + + + int getpixelBinding(lua_State *L) { Uint32 pixel; Uint8 r, g, b; @@ -255,15 +303,16 @@ int getpixelBinding(lua_State *L) { int spriteBinding(lua_State *L) { const char *filename; int x, y, angle, antialiasing; - void *sprite; + sprite *sprite; filename = lua_tostring(L, 1); - x = lua_tonumber(L, 2); - y = lua_tonumber(L, 3); + x = luaL_optnumber(L, 2, -1); + y = luaL_optnumber(L, 3, -1); angle = luaL_optnumber(L,4,0); antialiasing = lua_toboolean(L,5); sprite = spriteLoad(L,filename); - spriteBlit(l81.fb, sprite, x, y, angle, antialiasing); + if (x >= 0 && y >= 0) + spriteBlit(l81.fb, sprite, x, y, -1, angle, antialiasing); return 1; } @@ -339,7 +388,7 @@ void showFPS(void) { if (!elapsed_ms) return; snprintf(buf,sizeof(buf),"FPS: %.2f",(float)(l81.epoch*1000)/elapsed_ms); - drawBox(l81.fb,0,0,100,20,0,0,0,255); + drawBox(l81.fb,0,0,100,20,0,0,0,255,1); bfWriteString(l81.fb,0,0,buf,strlen(buf),128,128,128,255); } @@ -413,6 +462,7 @@ void initConfig(void) { l81.r = 255; l81.g = l81.b = 0; l81.alpha = 255; + l81.filled = 1; l81.L = NULL; l81.luaerr = 0; l81.opt_show_fps = 0; @@ -475,6 +525,8 @@ void resetProgram(void) { /* Register API */ lua_pushcfunction(l81.L,fillBinding); lua_setglobal(l81.L,"fill"); + lua_pushcfunction(l81.L,filledBinding); + lua_setglobal(l81.L,"filled"); lua_pushcfunction(l81.L,rectBinding); lua_setglobal(l81.L,"rect"); lua_pushcfunction(l81.L,ellipseBinding); @@ -493,6 +545,8 @@ void resetProgram(void) { lua_setglobal(l81.L,"getpixel"); lua_pushcfunction(l81.L,spriteBinding); lua_setglobal(l81.L,"sprite"); + lua_pushcfunction(l81.L,polygonBinding); + lua_setglobal(l81.L,"polygon"); initSpriteEngine(l81.L); diff --git a/load81.h b/load81.h index 7f62925..249819d 100644 --- a/load81.h +++ b/load81.h @@ -15,6 +15,7 @@ struct globalConfig { /* Runtime */ int r,g,b; int alpha; + char filled; int fps; long long start_ms; long long epoch;