This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
CrazedProgrammer's profile picture

Surface API 1.6.2

Started by CrazedProgrammer, 15 March 2015 - 08:19 PM
CrazedProgrammer #1
Posted 15 March 2015 - 09:19 PM
The Surface API is a really powerful drawing API for ComputerCraft.
It uses the least amount of drawing calls possible to reduce lag and tearing.
It is compatible with all displays, but if the display only supports black and white
then you can only use colors.black and colors.white.
A surface is a texture that you can draw to.
It has 3 layers: the character, background color and text color layer.
The data of those 3 layers are stored in one sequential buffer so it uses the least amount of RAM.
Surfaces are wrapped in tables with the width, height, buffer and functions in it.
There are many useful functions, such as: clearing the surface, drawing text, pixels, lines, rectangles, scaling surfaces and more!
You can also load and save surfaces with the NFP format for the built-in paint,
or the more advanced NFT format which also supports text for programs such as NPaintPro and Sketch.
This is a complete replacement for the build-in paintutils API and maybe even the term API.
There is no error checking to keep the performance high, so if you get errors check if you have correct inputs.

You can download the source here: (34.35kb)
pastebin get 5YWfPd8Z surface
All functions are documented here:
https://github.com/CrazedProgrammer/SurfaceAPI/wiki (click on the function name to get to the documentation)

And then you can simply load it using os.loadAPI:

os.loadAPI("surface")
This program will display Hello, world! for two seconds with an orange background and blue text:

-- Loads the surface API
os.loadAPI("surface")
-- Creates a new surface to draw on:
-- surface.create(width, height, char, backcolor, textcolor)
local surf = surface.create(51, 19, " ", colors.orange, colors.blue)
-- Draws text at the desired location:
-- surf:drawText(x, y, text, backcolor, textcolor)
surf:drawText(3, 3, "Hello, world!")
-- Draws the surface to the screen:
-- surface.render(surface, display, x, y, sx1, sy1, sx2, sy2)
surf:render(term)
-- Waits for two seconds
os.sleep(2)
Screenshot:


Surfaces also support transparency.
Because surfaces have 3 layers, you can choose which layers you change by nil-ing out the ones you don’t.
For example if you only want to change the background color:

surf:drawPixel(3, 3, nil, colors.black)
If you want to overwrite all layers then you can set surf.overwrite to true.

surf.overwrite = true

Here is an example of what you can do with the scaling and rotating algorithm:

-- Loads the surface API
os.loadAPI("surface")
-- Creates an orange surface
local surf = surface.create(51, 19, " ", colors.orange, colors.white)
-- Loads a picture of mario from the file mario.nft
local surf2 = surface.load("mario.nft")
-- Draws a small mario
surf:drawSurfaceScaled(2, 2, 7, 9, surf2)
-- Draws a normal mario
surf:drawSurface(11, 2, surf2)
-- Draws a rotated mario
surf:drawSurfaceRotated(33, 10, 7, 9, 0.4, surf2)
-- Draws the surface to the computer display
surf:render(term)
-- Waits for two seconds
os.sleep(2)
Screenshot:


If you want to save disk space, you can delete functions that you don’t use in the API code.
However, some functions require other functions to function.
You can view the dependencies in the function documentation.

Changelog:
Version 1.6.2:
- Fixed term.scroll, term.clearLine and term.setCursorBlink from surf:getTerm
Version 1.6.0:
- Added surf:drawHLine and surf:drawVLine
- Added the ability to remove functions from the API code to save disk space (look at the function documentation for dependencies)
- Removed all global references (surface.*) so you can load the API as something else than "surface" or load it locally
Version 1.5.3:
- Fixed surf:render function
Version 1.5.2:
- Big performance improvements (about 80% on surf:render)
Version 1.5.1:
- Fixed surf:drawArc, surf:drawPie and surf:fillPie using inverted angles
Version 1.5.0:
- Added surf:getBounds
- Added surf:copy
- Added surf:getTerm
- Added surf:drawRoundedRect and surf:fillRoundedRect
- Added surf:drawArc
- Added surf:drawPie and surf:fillPie
- Added surf:shader
- Added surf:shift
- Fixed a couple bugs
Version 1.4.0:
- Completely rewritten and optimized
- New version numbering and variable: surface.version
- Added surf:drawRoundRect and surf:fillRoundRect
Version 1.3:
- Added term.blit support
- surf:render no longer throws an error with transparent surfaces
- Added a new image format: SRF (only uses hex characters and underscores)
- Added surface.loadString and surf:saveString
- Added surf:drawLines
- Added surf:drawTriangles and surf:fillTriangles
Version 1.2:
- Added surf:drawSurfaceRotated
Version 1.1:
- Replaced surf:drawToDisplay with surf:render
- Added surf:setBounds
- Added surf:drawTriangle and surf:fillTriangle
- Added surf:drawEllipse and surf:fillEllipse
- Added surf:floodFill

Older version downloads:
1.5.3: pastebin get J2Y288mW surface
1.4.0: pastebin get vm1y156i surface
1.3: pastebin get ajFj7yNK surface
1.2: pastebin get hwAbAgLD surface
1.1: pastebin get AmmVZusd surface
1.0: pastebin get g87xZ4dA surface

If you have any suggestions, bug reports or questions then please leave a reply or send a PM.
Edited on 07 June 2016 - 07:14 PM
InDieTasten #2
Posted 15 March 2015 - 09:25 PM
Looks nice, although I don't have any applications of this
CrazedProgrammer #3
Posted 15 March 2015 - 09:31 PM
Looks nice, although I don't have any applications of this
Thanks!
This API is mainly intended for advanced GUIs and games, so if you ever make such a program
it's way easier to use this API than the term API :D/>
Edited on 15 March 2015 - 08:31 PM
Exerro #4
Posted 15 March 2015 - 09:35 PM
Great API, great documentation. This is awesome.

Things you could add:
- Stencils (limit the area you can draw to)
- Flood fill
- :drawEllipse() and :drawPolygon()
- Improve rendering to
– a) Only draw changes
– b ) Draw more than one pixel at a time if it has the same background colour and text colour.
Edited on 15 March 2015 - 08:36 PM
CrazedProgrammer #5
Posted 15 March 2015 - 09:44 PM
Great API, great documentation. This is awesome.

Things you could add:
- Stencils (limit the area you can draw to)
- Flood fill
- :drawEllipse() and :drawPolygon()
- Improve rendering to
– a) Only draw changes
– b ) Draw more than one pixel at a time if it has the same background colour and text colour.
Thanks for the great feedback!
I will add floodfill, ellipses and polygons soon! (maybe tomorrow if the algorithms aren't that hard)
I don't know how stencils would work, so please explain :D/>
The rendering IS actually doing what you're suggesting.
It cycles through the pixels like scanlines and if a color changes (background or text), it changes the color and draws all the characters of the pixels that have come before it.
It puts the commands inside a table and then cycles through them all at once so there is minimal tearing.
Edited on 15 March 2015 - 08:54 PM
TheOddByte #6
Posted 15 March 2015 - 09:57 PM

-- Creates an orange surface
local surf = surface.create(51, 19, " ", colors.black, colors.white)
Wouldn't that be a black surface? :P/>
Anyway, haven't tested this but it looks quite good, I'm most interested in the scaling function. It also feels like some of your functions could have simpler names

drawToDisplay    > render
drawSurfacePart > drawQuad or quad

Oh, and I don't know how moderators feel, but I believe it's discouraged to post your email openly like that.
CrazedProgrammer #7
Posted 15 March 2015 - 10:08 PM

-- Creates an orange surface
local surf = surface.create(51, 19, " ", colors.black, colors.white)
Wouldn't that be a black surface? :P/>
Anyway, haven't tested this but it looks quite good, I'm most interested in the scaling function. It also feels like some of your functions could have simpler names

drawToDisplay	> render
drawSurfacePart > drawQuad or quad

Oh, and I don't know how moderators feel, but I believe it's discouraged to post your email openly like that.
Whoops! I made the documentation with mostly black surfaces, and I forgot about that one! :P/>
The surf:render() name is a great suggestion, and I'll add it in the next version (which will be out probably tommorow with floodfill, ellipses and polygons).
The surf:drawQuad() or surf:quad function doesn't really explain that it draws surfaces, I'd like to hear other people's opinions about that :D/>
The scaling algorithm is basically a nearest neighbor algorithm which I developed in maths class because I was bored.
You can look it up in the source if you want to know how it works.
The email is not my personal email, so I don't mind if people send me emails :P/>
Edited on 15 March 2015 - 09:09 PM
Exerro #8
Posted 15 March 2015 - 10:13 PM
-snip-
Thanks for the great feedback!
I will add floodfill, ellipses and polygons soon! (maybe tomorrow if the algorithms aren't that hard)
I don't know how stencils would work, so please explain :D/>
The rendering IS actually doing what you're suggesting.
It cycles through the pixels like scanlines and if a color changes (background or text), it changes the color and draws all the characters of the pixels that have come before it.
It puts the commands inside a table and then cycles through them all at once so there is minimal tearing.

In my library, it uses 'buffers' rather than 'surfaces'. There are a couple of functions…

buff:setStencil( x, y, width, height )
s = buff:addStencil( x, y, width, height )
buff:removeStencil( s )

Adding a stencil just does a bbox with the current stencil so it's the area that fits inside both stencils (the current one and added one). Remove removes the last stencil added and updates. Set just sets the stencil.

Now, if you had this:
buff:setStencil( 5, 5, 3, 3 )
then tried…
gfx2D.rectangle( 4, 4, 3, 3 ) -- after wrapping to the buffer, setting colours and characters, etc
It would only draw from 5, 5 to 6, 6 rather than 4, 4, to 6, 6 because it won't draw outside the stencil's area.

This is essential for me when writing a UI library, because scrolling frames' objects will most often try and draw where they shouldn't be allowed to, and by using stencils, it is possible to stop them drawing there.

Personally, I wouldn't use :drawQuad() and just stick to :drawSurfacePart(). I wouldn't even replace :drawSurface() with :render(), maybe just add render as an optional one like…

object.render = object.drawSurface
CrazedProgrammer #9
Posted 16 March 2015 - 03:15 PM
-snip-
Thanks for the great feedback!
I will add floodfill, ellipses and polygons soon! (maybe tomorrow if the algorithms aren't that hard)
I don't know how stencils would work, so please explain :D/>
The rendering IS actually doing what you're suggesting.
It cycles through the pixels like scanlines and if a color changes (background or text), it changes the color and draws all the characters of the pixels that have come before it.
It puts the commands inside a table and then cycles through them all at once so there is minimal tearing.

In my library, it uses 'buffers' rather than 'surfaces'. There are a couple of functions…

buff:setStencil( x, y, width, height )
s = buff:addStencil( x, y, width, height )
buff:removeStencil( s )

Adding a stencil just does a bbox with the current stencil so it's the area that fits inside both stencils (the current one and added one). Remove removes the last stencil added and updates. Set just sets the stencil.

Now, if you had this:
buff:setStencil( 5, 5, 3, 3 )
then tried…
gfx2D.rectangle( 4, 4, 3, 3 ) -- after wrapping to the buffer, setting colours and characters, etc
It would only draw from 5, 5 to 6, 6 rather than 4, 4, to 6, 6 because it won't draw outside the stencil's area.

This is essential for me when writing a UI library, because scrolling frames' objects will most often try and draw where they shouldn't be allowed to, and by using stencils, it is possible to stop them drawing there.

Personally, I wouldn't use :drawQuad() and just stick to :drawSurfacePart(). I wouldn't even replace :drawSurface() with :render(), maybe just add render as an optional one like…

object.render = object.drawSurface
Thanks for explaining how stencils work!
I think I can implement stencils with the name surf:setBounds(x1, y1, x2, y2), but it won't have a stencil stack.
I will replace surf:drawToDisplay with surf:render because it's short and makes sense.
Thanks for your opinion on surf:drawQuad :D/>
I will keep surf:drawSurfaceScaled like it is.
CrazedProgrammer #10
Posted 16 March 2015 - 09:08 PM
I have updated the Surface API to version 1.1!
I have made these changes and additions to the API:
- Replaced surf:drawToDisplay with surf:render
- Added surf:setBounds
- Added surf:drawTriangle and surf:fillTriangle
- Added surf:drawEllipse and surf:fillEllipse
- Added surf:floodFill

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.0 for some reason you can still do that:
pastebin get g87xZ4dA surface
SpencerBeige #11
Posted 16 March 2015 - 09:20 PM
resizing images? wow. anew form of amazing has come ;p
CrazedProgrammer #12
Posted 16 March 2015 - 09:26 PM
resizing images? wow. anew form of amazing has come ;p
Thanks!
I will probably add rotating surfaces soon so you can combine the two to make more forms of amazing :P/>
Geforce Fan #13
Posted 16 March 2015 - 09:31 PM
Looks nice, although I don't have any applications of this
Thanks!
This API is mainly intended for advanced GUIs and games, so if you ever make such a program
it's way easier to use this API than the term API :D/>
I think it'd be mostly useful for an OS with a lot of animations like OneOS. Or a side-scroller that has zooming.

You might want to make a makeActive() function. So, when a buffers is active, when you do something to it, it not changes variables in the buffer, but also draws it to the screen.
CrazedProgrammer #14
Posted 16 March 2015 - 09:40 PM
Looks nice, although I don't have any applications of this
Thanks!
This API is mainly intended for advanced GUIs and games, so if you ever make such a program
it's way easier to use this API than the term API :D/>
I think it'd be mostly useful for an OS with a lot of animations like OneOS. Or a side-scroller that has zooming.

You might want to make a makeActive() function. So, when a buffers is active, when you do something to it, it not changes variables in the buffer, but also draws it to the screen.
This API is mainly intended for advanced GUIs and all sorts of games (not just sidescrollers), so you're right :D/>
I won't add a function that draws automatically because it would redraw the whole surface every time a function is called.
That is not only very inefficient, but it also isn't really practical.
It is more convenient to call surf:render when you want to draw a surface to a display.
Thanks for the feedback!
Edited on 16 March 2015 - 08:40 PM
Exerro #15
Posted 16 March 2015 - 10:14 PM
This is by far the most useful API I've seen on the forums. I'm taking serious design tips from it, and I'm annoyed I didn't have these things implemented from the start of writing Nova. Rotation would be incredible to have for animations.

One quick question… How did you implement :drawTriangle()? Surely you're using the scanline method, and if so, it's not any harder to implement a :drawPolygon() function.
CrazedProgrammer #16
Posted 16 March 2015 - 11:36 PM
This is by far the most useful API I've seen on the forums. I'm taking serious design tips from it, and I'm annoyed I didn't have these things implemented from the start of writing Nova. Rotation would be incredible to have for animations.

One quick question… How did you implement :drawTriangle()? Surely you're using the scanline method, and if so, it's not any harder to implement a :drawPolygon() function.
Thank you so much!
It means a lot to me when I get feedback from people who really like my creations.
Also, your OS is one of the best, and you may modify and include the Surface API wherever you want.
As for the draw/fillTriangle functions, I've tried all three triangle drawing algorithms (scanline, barycentric and bresenham)
and the scanline and barycentric algorithms had too many artifacts.
I decided to make triangles out of normal bresenham lines.
For the fillTriangle function I used a sequential buffer containing booleans to draw the lines
and then I used scanlines to fill the space in between the two lines.
I have looked up numerous articles on how you can draw filled polygons but they are either too complicated or they have too many artifacts.
If you find a solid solution to this, I'd be really happy to include it.
I am going to work hard on implementing rotating surfaces (I've already done something like that before so it shouldn't be too hard) :D/>
CrazedProgrammer #17
Posted 18 March 2015 - 04:59 PM
I have updated the Surface API to version 1.2!
I have made one addition and that is:
- Added surf:drawRotatedSurface
You can now draw rotated surfaces!

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.1 for some reason you can still do that:
pastebin get AmmVZusd surface
CrazedProgrammer #18
Posted 06 April 2015 - 07:30 PM
I updated the Surface API to version 1.3!
I made these changes and additions to the API:
- Added term.blit support
- surf:render no longer throws an error with transparent surfaces
- Added a new image format: SRF (only uses hex characters and underscores)
- Added surface.loadString and surf:saveString
- Added surf:drawLines
- Added surf:drawTriangles and surf:fillTriangles

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.2 for some reason you can still do that:
pastebin get hwAbAgLD surface
Edited on 06 April 2015 - 05:31 PM
CrazedProgrammer #19
Posted 16 April 2015 - 07:00 PM
Since Dan fixed the term.blit function that was broken in ComputerCraft beta 1.74pr18 I've made a small fix to the Surface API.
You can download it from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to fix it without downloading the new version you just have to remove the "15 - " on lines 316 and 317.
Creator #20
Posted 16 April 2015 - 07:06 PM
This is by far the most useful API I've seen on the forums. I'm taking serious design tips from it, and I'm annoyed I didn't have these things implemented from the start of writing Nova. Rotation would be incredible to have for animations.

One quick question… How did you implement :drawTriangle()? Surely you're using the scanline method, and if so, it's not any harder to implement a :drawPolygon() function.

@awesumben every post that is about gui you ask for a triangle drawing function and a polygon drawing function. What is the math behind circles triangles and polygons in general?
CrazedProgrammer #21
Posted 16 April 2015 - 07:32 PM
This is by far the most useful API I've seen on the forums. I'm taking serious design tips from it, and I'm annoyed I didn't have these things implemented from the start of writing Nova. Rotation would be incredible to have for animations.

One quick question… How did you implement :drawTriangle()? Surely you're using the scanline method, and if so, it's not any harder to implement a :drawPolygon() function.

@awesumben every post that is about gui you ask for a triangle drawing function and a polygon drawing function. What is the math behind circles triangles and polygons in general?
Well it's mostly scanline algorithms, but I use the bresenham line algorithm and then a filling algorithm because it's pixel perfect.
It may not be the fastest way of drawing, but it doesn't have any artifacts.
Here are a few sources that may help you if you're interested in real scanline algorithms:
Sofware Rasterization Algorithms for drawing filled triangles
Triangle fillers
Polygon Fill Teaching Tool
Circle and ellipse drawing algorithm - Math Open Reference
Creator #22
Posted 16 April 2015 - 07:50 PM
Thanks a lot ;)/>
CrazedProgrammer #23
Posted 16 April 2015 - 07:51 PM
Thanks a lot ;)/>
No problem :D/>
If you want to learn even more, you can search for "<shape> fill algorithm" on Google.
I recommend learning about the Bresenham Line algorihm.
There is also lua version of the algorithm.
Edited on 16 April 2015 - 05:54 PM
CrazedProgrammer #24
Posted 25 April 2015 - 10:52 PM
I've made a small fix for the Surface API.
You couldn't save images in NFP (built-in paint) format because the colorToHex function was renamed to _colorToHex.
You can download the fix with the same download as before or you can replace colorToHex with _colorToHex on line 205.
I'm sorry for not noticing the problem before.
If you encounter any problems then please leave a reply.
LeDark Lua #25
Posted 27 April 2015 - 04:09 PM
CrazedProgrammer this looks like you programmed in GameMaker becouse of the functions, OR you made this up!
Edited on 27 April 2015 - 02:10 PM
CrazedProgrammer #26
Posted 27 April 2015 - 05:24 PM
CrazedProgrammer this looks like you programmed in GameMaker becouse of the functions, OR you made this up!
I did program in GameMaker xD
I really like how its drawing functions are laid out and that's why the names are so similar.
Edited on 27 April 2015 - 05:36 PM
CrazedProgrammer #27
Posted 27 April 2015 - 08:10 PM
I've updated the Surface API to version 1.4.0!
I made these changes and additions to the API:
- Completely rewritten and optimized
- New version numbering and variable: surface.version
- Added surf:drawRoundRect and surf:fillRoundRect

The new version numbering works like this: 1.4.0
1 - Major: Completely different, probably no backwards compatibility.
4 - Minor: A couple of new features, backwards compatible.
0 - Patch: Bug fixes / optimalizations
The new variable, surface.version, is a string that represents the version, for example "1.4.0".

Also, it is 2150 bytes smaller than version 1.3 :P/>/>

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.3 for some reason you can still do that:
pastebin get ajFj7yNK surface
Edited on 02 May 2015 - 10:15 AM
Exerro #28
Posted 27 April 2015 - 10:58 PM
As I've said before, this is great, although I think the 'drawRoundRect' function is a bit over-exaggerated (thought it might have some control over corner radius). With the exception of that, I'd love to see a :termRedirect() function that returns an object you can term.redirect() to, and arcs (drawn using either 2 points and 2 angles, or a circle centre and 2 angles) - yeah, I'm thinking pie charts…
Edited on 27 April 2015 - 08:58 PM
Creator #29
Posted 27 April 2015 - 11:25 PM
Surface is like paintutils or opengl not window api. It is like comparing tcp ip and http
syfygirl #30
Posted 27 April 2015 - 11:49 PM
oh man could you imagine a 3d engine pluggin to render objects to sprites.
CrazedProgrammer #31
Posted 28 April 2015 - 06:55 PM
Sorry, I made a typo in my last post: surface:drawFilledRect should be surface:fillRoundRect.
I've edited it by now.

As I've said before, this is great, although I think the 'drawRoundRect' function is a bit over-exaggerated (thought it might have some control over corner radius). With the exception of that, I'd love to see a :termRedirect() function that returns an object you can term.redirect() to, and arcs (drawn using either 2 points and 2 angles, or a circle centre and 2 angles) - yeah, I'm thinking pie charts…
Very good suggestions, thanks a lot!
I'll make these functions in the next update (1.5.0):
- surf:getTerm (Returns an object that you can term:redirect to. When you draw on that object it draws on the surface.)
- surf:drawPie
- surf:fillPie
- surf:drawArc
- surf:drawRoundedRect (like surf:drawRoundRect but you can specify the border radius)
- surf:fillRoundedRect

The surf:drawArc function will take a circle centre and 2 angles, not 2 points and 2 angles.
I'll release it on Sunday (may 3rd).
Edited on 28 April 2015 - 05:08 PM
CrazedProgrammer #32
Posted 28 April 2015 - 07:00 PM
Surface is like paintutils or opengl not window api. It is like comparing tcp ip and http
It is indeed like comparing HTTP and TCP/IP.
HTTP requires TCP/IP to work, but when you use HTTP you don't have to worry about TCP/IP.
The same goes for the Surface API.
The Surface API requires (actually it doesn't if you don't use surf:render) the Term API to work, but when you use the Surface API you don't have to worry about the Term API.
CrazedProgrammer #33
Posted 28 April 2015 - 07:06 PM
oh man could you imagine a 3d engine pluggin to render objects to sprites.
I could imagine it, because it really is possible.
Maybe I'll even make something like it in the future.
The surf:fillTriangle function is a pretty good triangle filler, so you don't have to worry about that.

The complicated thing is the 3D to 2D transformations.
I've tried multiple times but maybe I'm not smart enough to understand 3D Perspective Projection :P/>
CrazedProgrammer #34
Posted 01 May 2015 - 03:40 PM
I'll release it on Sunday (may 3rd).
Scrap that, I'll release it now!

I've updated the Surface API to version 1.5.0!
I've made these changes and additions to the API:
- Added surf:getBounds
- Added surf:copy
- Added surf:getTerm
- Added surf:drawRoundedRect and surf:fillRoundedRect
- Added surf:drawArc
- Added surf:drawPie and surf:fillPie
- Added surf:shader
- Added surf:shift
- Fixed a couple bugs

With the new surf:getTerm function, you can get a term object (which is fully implemented and you can term.redirect to it) from a surface
and then draw another surface on that term object using surf:render and it will be drawn on the original surface!
Now that is some inception shit!

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.4.0 for some reason you can still do that:
pastebin get vm1y156i surface

A big thanks to awsumben13 for giving great suggestions!

If you've got any bug reports, suggestions or questions then please leave a reply.
Edited on 01 May 2015 - 03:51 PM
CrazedProgrammer #35
Posted 01 May 2015 - 06:50 PM
I've made a small fix (version 1.5.1).
The surf:drawArc, surf:drawPie and surf:fillPie didn't rotate left with a bigger angle, but they rotated right.
I've fixed it by now.
You can download version 1.5.1 from the same pastebin as before:
pastebin get 5YWfPd8Z surface
CrazedProgrammer #36
Posted 02 May 2015 - 01:28 PM
I've made some optimizations (version 1.5.2).
Some functions like math.sin are localized, and I've made a colors table so that I don't have to use string.format("%x", math.log(color) / math.log(2)).
Because of this, the drawing speed has increased by 80% (using term.blit).
You can now draw to the largest possible display (164 x 81) 20 times per second (the fastest speed possible) without any lag (at least on my PC).
You can download version 1.5.2 from the same pastebin as before:
pastebin get 5YWfPd8Z surface
Bomb Bloke #37
Posted 02 May 2015 - 02:42 PM
20 times per second (the fastest speed possible)

Odds are it'll be capable of even faster speeds than that; that's just the maximum amount of time-slices ComputerCraft lets you measure out of every second, so you won't want to exceed it.

Depending on your buffering strategy, term.blit() allows you to draw pretty much anything at about the same speed as term.clear(). Beats me how fast that actually is, but you can see how code written to take advantage of it can really do some impressive things.
CrazedProgrammer #38
Posted 02 May 2015 - 04:47 PM
20 times per second (the fastest speed possible)

Odds are it'll be capable of even faster speeds than that; that's just the maximum amount of time-slices ComputerCraft lets you measure out of every second, so you won't want to exceed it.

Depending on your buffering strategy, term.blit() allows you to draw pretty much anything at about the same speed as term.clear(). Beats me how fast that actually is, but you can see how code written to take advantage of it can really do some impressive things.
It's a shame that you can't draw at anything above 20fps, but that's still enough to make impressive things.
Maybe I'll make a second visual demo to show how good it can draw to big screens.

I've fixed a BIG bug (version 1.5.3).
The surf:render function was broken for any ComputerCraft version below 1.74pre20 (a beta).
It was broken since 1.4.0 for all surfaces and 1.3 for transparent ones.
I've fixed it now.
The surf:render function now returns how many draw calls were made to the display object.
You can download version 1.5.3 from the same pastebin as before:
pastebin get 5YWfPd8Z surface
Edited on 02 May 2015 - 04:05 PM
クデル #39
Posted 06 May 2015 - 11:32 PM
This helped me out a lot, prevented a lot of hassle which is always great. Just a suggestion, it would be pretty neat if you override some of the variables in the colours api. If were people to try to use colour on a non-advanced display it would just use black and white alternatives rather than crashing.
CrazedProgrammer #40
Posted 09 May 2015 - 08:18 PM
This helped me out a lot, prevented a lot of hassle which is always great. Just a suggestion, it would be pretty neat if you override some of the variables in the colours api. If were people to try to use colour on a non-advanced display it would just use black and white alternatives rather than crashing.
Thanks!
You can still draw surfaces with only black and white colors on normal computers.
Programs that are made for color displays are not supposed to run on normal computers, mostly because of the absence of mouse events.
That's why I won't make a fix for it, but you can make a shader using the new surf:shader function to make a surface black and white if the user uses a normal computer:

if not term.isColor() then
  surf:shader(function (c, b, t) if b ~= colors.white then b = colors.black t = colors.white else b = colors.white t = colors.black end return c, b, t end)
end
CrazedProgrammer #41
Posted 12 May 2015 - 08:43 PM
I've updated the Surface API to version 1.6.0!
I've made these changes and additions to the API:
- Added surf:drawHLine and surf:drawVLine
- Added the ability to remove functions from the API code to save disk space (look at the function documentation for dependencies)
- Removed all global references (surface.*) so you can load the API as something else than "surface" or load it locally

It is also 156 bytes smaller than version 1.5.3 and the ability to remove functions can make you save up to 90% disk space.

You can download the new version from the same pastebin as before:
pastebin get 5YWfPd8Z surface
If you want to download version 1.5.3 for some reason you can still do that:
pastebin get J2Y288mW surface
CrazedProgrammer #42
Posted 14 May 2015 - 01:44 PM
I've made a small fix (version 1.6.2).
The term.scroll, term.clearLine and term.setCursorBlink from surf:getTerm didn't work properly.
I've fixed it by now.
You can download version 1.6.2 from the same pastebin as before:
pastebin get 5YWfPd8Z surface
Edited on 14 May 2015 - 12:02 PM
syfygirl #43
Posted 06 June 2015 - 12:47 AM
so it's almost like a simple opengl?
Edited on 05 June 2015 - 10:47 PM
biggest yikes #44
Posted 06 June 2015 - 01:20 AM
I must find a way to invert CraftOS now after reading the "drawSurfaceRotated" example
wilcomega #45
Posted 09 June 2015 - 12:28 PM
this is really cool, i can see me using this in the future.
if its possible you should try to make a 3D rendering engine, a basic one that supports rendering faces and primitive objects like cubes,
if you want i would like to help with that part :)/>

anyways, i have got an idea for a system where you can use multiple monitors on one system without low level program support
CrazedProgrammer #46
Posted 09 June 2015 - 05:32 PM
so it's almost like a simple opengl?
Absolutely not :P/>
It is more like HTML5's canvas element or SDL.
CrazedProgrammer #47
Posted 09 June 2015 - 05:39 PM
this is really cool, i can see me using this in the future.
if its possible you should try to make a 3D rendering engine, a basic one that supports rendering faces and primitive objects like cubes,
if you want i would like to help with that part :)/>

anyways, i have got an idea for a system where you can use multiple monitors on one system without low level program support
Thanks!

I'm currently working on something called OpenGraphics.
It will have high-speed canvases (surfaces in the Surface API) and real perspective 3D.
You will be able to remove all functions without having to worry about function dependencies.

You can already use multiple monitors on one system by drawing parts of a surface to different monitors (see the documentation of surf:render).
wilcomega #48
Posted 17 June 2015 - 07:08 PM
cant wait, from the recent tweets from dan200, we can hope for those cool icons, 3D, more MORE pixels and other cool stuff :)/>
CrazedProgrammer #49
Posted 17 June 2015 - 07:27 PM
cant wait, from the recent tweets from dan200, we can hope for those cool icons, 3D, more MORE pixels and other cool stuff :)/>
Yeah me too :D/>
It would be sooooo nice to have more pixels.
The 3D part was probably for testing the triangle/polygon filling algorithm.
I doubt it will come out in the next two months.
クデル #50
Posted 09 July 2015 - 01:21 PM
Is there a text input function or something alike? I'm using the read function and it doesn't play nicely with the Surface API, the colours don't match so their reset to defaults which is more than painful. I can't think of a good fix either, well atleast one that wouldn't require drawing individual pixels.
LeDark Lua #51
Posted 07 August 2015 - 01:10 PM
Hey crazy, just asking if you could make a rotating text. I know you cant make upside down chars but when you are rotating you can invert text you know :D/> And you can make like text sideways, and that kind of stuff. Well this would be cool.

EDIT: and you could pick the center of rotating :)/>

EDIT2: And this is very nice, it runs sooo smooth that I cant even.
Edited on 07 August 2015 - 11:23 AM
PixelFox #52
Posted 05 September 2015 - 09:53 PM
Can you make surf:invert() it inverts the surface :P/>
CrazedProgrammer #53
Posted 06 September 2015 - 10:48 AM
Can you make surf:invert() it inverts the surface :P/>
I don't know what you mean by that.
If you want to draw a surface mirrored, then you can use the surf:drawSurfaceScaled function and make x1 bigger than x2 and/or y1 bigger than y2.
funzrey_ #54
Posted 18 September 2015 - 12:41 PM
A little laggy for me (it's probably my laptop, because i normally get 10/30FPS on minecraft, and 40/70FPS on CCEmuRedux, and about 70/100 FPS on a forked version of CCLite.
CrazedProgrammer #55
Posted 19 September 2015 - 05:19 PM
A little laggy for me (it's probably my laptop, because i normally get 10/30FPS on minecraft, and 40/70FPS on CCEmuRedux, and about 70/100 FPS on a forked version of CCLite.
It was built with optimization in mind but I guess anything can be laggy.
PixelFox #56
Posted 19 September 2015 - 10:05 PM
I mean making the colors inverted. like: colors.red becomes colors.cyan
LeDark Lua #57
Posted 20 September 2015 - 07:49 AM
Or shading, like surf:shade(surf.shade.grey) and the colors change to grey and depending on the strenth it would be darker or lighter. Blue/cyan or Red/orange/pink shades is cool.
CrazedProgrammer #58
Posted 23 September 2015 - 09:37 AM
I mean like the colors inverted. like: colors.red becomes colors.cyan

surf:shader(function (c, back, t) return c, 2 ^ (15 - math.log(back) / math.log(2)), 2 ^ (15 - math.log(t) / math.log(2)) end)
Edited on 23 September 2015 - 07:42 AM
CrazedProgrammer #59
Posted 23 September 2015 - 09:45 AM
Or shading, like surf:shade(surf.shade.grey) and the colors change to grey and depending on the strenth it would be darker or lighter. Blue/cyan or Red/orange/pink shades is cool.
You can make those shaders by yourself with surf:shader, but if there is really a demand for it I can create grayscale, sepia, higher contrast and many more built-in shaders.
PixelFox #60
Posted 17 October 2015 - 11:06 PM
Is there a way to Scale AND Rotate an image?
CrazedProgrammer #61
Posted 24 October 2015 - 02:52 PM
Is there a way to Scale AND Rotate an image?
You can create a surface, scale the image on there and then draw that surface rotated.
jakejakey #62
Posted 20 October 2016 - 03:54 AM
Haven't tried the API yet and I'm considering it for an OS. Anyway, can you make it use the new expanded charset? That is if you haven't already done that.