This is where you might want to start looking at how classes work. You can make your own "object" as a class that has its own surface. The class code can be in your included .nut - then you can create as many instances of that class as you want.
Here's an example:
class ArtAndText {
surface = null //the surface we create that will hold our objects
art_obj = null //an art object we will add to the surface
text_obj = null //a text object we will add to the surface
constructor( x, y, width, height, parent = ::fe ) {
//create the surface - parent could be another surface - if the parent isn't given, it creates its own surface using fe.add_surface
surface = ( parent == ::fe ) ? parent.add_surface(::fe.layout.width, ::fe.layout.height) : parent.add_surface(parent.width, parent.height)
create( x, y, width, height)
}
function create( x, y, width, height) {
//create the art and text objects
art_obj = surface.add_artwork("snap", 0, 0, surface.width, surface.height)
text_obj = surface.add_text("[Title]", 0, 0, surface.width, 50)
//set the surface position
set_pos( x, y, width, height)
}
function set_pos(x, y, width, height) {
surface.x = x
surface.y = y
surface.width = width
surface.height = height
}
}
That class can now be instantiated just like other objects in attract mode:
local myObject = ArtAndText(50, 50, 320, 240)
//we can access the functions in the class
myObject.set_pos(100, 100, 320, 240)