Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
idunno
Visitor

Changing From roImageCanvas to roScreen questions

It has become apparent that I will need to use roScreen in my program instead of roImageCanvas in order to speed up my program. My program makes heavy use of roImageCanvas, specifically the setLayer, clearLayer and swapLayer, in addition to the ability to setLayer something on an already occupied layer to overwrite what is already on that layer. I was wondering if there was a way for roScreen to reproduce any/all of these effects, and how I should go about changing my program to use roScreen, since I have never used it before.
0 Kudos
18 REPLIES 18
MSGreg
Visitor

Re: Changing From roImageCanvas to roScreen questions

Probably the biggest thing to realize is that if you double buffer the screen, you will have to redraw every object, every time. This will result in good clean movement if you optimize any calculations outside of the redraw loop. Double buffering is recommended so that you do not see "screen tears" during redraw, which happens when a draw occurs partially in two different frame refresh periods.

You will most likely have a similar wait() loop that checks for universal event type that differentiates press and release. If you must have faster speed, then search the forums on the wait / sleep bug on Roku 2 devices that cause an extra 15-20ms delay. It's possible to get rid of that delay by using timers and polling message port(s) in a tight loop.

I hope that helps!
0 Kudos
idunno
Visitor

Re: Changing From roImageCanvas to roScreen questions

It helps somewhat. Is there anywhere can I find a very simple example of a program using roScreen for reference?
0 Kudos
destruk
Binge Watcher

Re: Changing From roImageCanvas to roScreen questions

The 3.0 SDK has a sample roScreen app called "Snake"
0 Kudos
idunno
Visitor

Re: Changing From roImageCanvas to roScreen questions

"destruk" wrote:
The 3.0 SDK has a sample roScreen app called "Snake"

I've been looking at that one, but its still fairly complex.

I have this code that I am trying to get to work based on what I see in the snake program:

Function Main()
'look = newLook()
screen = CreateObject("roScreen", true,1280,720)
screen.DrawRect(900, 220, 235, 392)

sleep(5000)

End Function


but it keeps crashing and I get the error
Current Function:
001: Function Main()
002: 'look = newLook()
003: screen = CreateObject("roScreen", true,1280,720)
004: screen.DrawRect(900, 220, 235, 392)
005: return screen.DrawRect()
006: sleep(5000)
007:
008: End Function
Member function not found in BrightScript Component or interface. (runtime error &hf4) in ...AAdUozdQ/pkg:/source/main.brs(4)

004: screen.DrawRect(900, 220, 235, 392)
Backtrace:
Function main() As
file/line: /tmp/plugin/G...AAdUozdQ/pkg:/source/main.brs(4)

Local Variables:
global &h0020 rotINTERFACE:ifGlobal
m &h0010 bsc:roAssociativeArray, refcnt=2
screen &h0010 bsc:roScreen, refcnt=1
BrightScript Debugger>

Any suggestions?
0 Kudos
RokuChris
Roku Employee
Roku Employee

Re: Changing From roImageCanvas to roScreen questions

DrawRect() takes 5 arguments, not 4, the fifth being the color you want your rect to be. http://sdkdocs.roku.com/display/RokuSDK ... ntegerrgba
0 Kudos
RokuJoel
Binge Watcher

Re: Changing From roImageCanvas to roScreen questions

I threw together a little demo last night for you:

you can download it here: https://www.box.com/shared/93202d2c60d4bf2effd1

In terms of the SDK examples, check out BS2Dtest and simple2d for some more ideas of what you can do, including collision detection, scaling etc. There aren't yet any examples of integrating 2DAPIs with video playback, but we should have some soon.

The action takes place in the while loops:

'lets say you have a set of images you want to draw as layers. You would draw them to the screen in the order in which they should appear, and you would keep redrawing them as often as possible:

sub main()

screen=createobject("roscreen",true)
screen.setalphaenable(false)
image1=createobject("robitmap","pkg:/images/imageone.png")
image2=createobject("robitmap","pkg:/images/imagetwo.png")
image3=createobject("robitmap","pkg:/images/imagethree.png")

'lets set up some positions for these images:
obj1={posx:200,posy:200}
obj2={posx:400,posy:400}
obj3={posx:600,posy:600}


timer=createobject("rotimespan")
timer.mark()



while timer.totalseconds() <15 'exit this loop after 15 seconds.

screen.clear(&h000000FF) 'clear screen to black
screen.setalphaenable(false) 'disable alpha for this draw, since the object is not transparent
screen.drawobject(obj1.posx,obj1.posy,image1)
screen.setalphaenable(true) 're enable for transparent images
screen.drawobject(obj2.posx,obj2.posy,image2)
screen.drawobject(obj3.posx,obj3.posy,image3)
screen.setalphaenable(false)

screen.swapbuffers() 'display the completed draw on screen

'move objects
if obj1.posx > 0 then obj1.posx=obj1.posx-1
if obj1.posy > 0 then obj1.posy=obj1.posy-1

if obj2.posx > 0 then obj2.posx=obj2.posx-1
if obj2.posy > 0 then obj2.posy=obj2.posy-1

if obj3.posx > 0 then obj3.posx=obj3.posx-1
if obj3.posy > 0 then obj3.posy=obj3.posy-1

end while


'If one of the layers has transparancy, and you want the layer below to show through the transparant section, you would enable transprancy for that image when drawing to the screen.

'Another approach with roScreen is to create Sprites, which are images designed to be moved around the screen, typically as objects in a game, but they can be used for almost anything.

'lets create some sprites. first we need to create a compositor:
compositor=createobject("rocompositor")

'now we need to tell it where to draw and the background color:
compositor.setdrawto(screen,&h000000FF)

'To create a sprite, first we create a bitmap image, as we did before
bmp1=createobject("roBitmap", "pkg:/images/alien1.png")

'then we create a region from that bitmap:
reg1=createobject("roregion", bmp1,0,0,bmp1.getwidth(),bmp1.getheight())
bmp2=createobject("roBitmap", "pkg:/images/alien2.png")
reg2=createobject("roregion", bmp2,0,0,bmp2.getwidth(),bmp2.getheight())
bmp3=createobject("roBitmap", "pkg:/images/alien3.png")
reg3=createobject("roregion", bmp3,0,0,bmp3.getwidth(),bmp3.getheight())

'from those three regions, we will create our sprites:
spr1=compositor.newsprite(200,200,reg1,0) 'create a sprite on layer 0
spr2=compositor.newsprite(250,250,reg2,1) 'create a sprite on layer 1
spr3=compositor.newsprite(350,350,reg3,2) 'create a sprite on layer 3




'to make it easier to work with them, we are going to put them into an array:

sprArr=[spr1,spr2,spr3]
'we can actually store data inside a sprite! lets put our x and y positions into an Associative Array and store in our sprite:
for each sprite in sprarr
sprite.setdata({xpos:sprite.getx(),ypos:sprite.gety()})
end for

'Ok, now lets make a little routine that moves them randomly around the screen:
bounds={}
bounds.x=screen.getwidth()
bounds.y=screen.getheight()
screen.setalphaenable(true) 'enable transparency

'Lets set up a timer to control movement:

movetimer=createobject("rotimespan")
movetimer.mark()

'lets reset the timer we used for the while loop:
timer.mark()


for each sprite in sprarr
data=sprite.getdata()
data.movex=(rnd(3)-2)
data.movey=(rnd(3)-2)
sprite.setdata(data)
movetimer.mark()
end for
while timer.totalseconds() < 60

screen.clear(&h000000ff)

if movetimer.totalmilliseconds() > 500 then
for each sprite in sprarr
data=sprite.getdata()
xr=(rnd(3)-2)
yr=(rnd(3)-2)
if xr <>0 then data.movex=xr
if yr <>0 then data.movey=yr
sprite.setdata(data)
movetimer.mark()
end for
end if

'move sprites
for each sprite in sprarr
data=sprite.getdata()
x=data.xpos
y=data.ypos
x=x+data.movex
y=y+data.movey
if x > bounds.x then x=0-sprite.getregion().getbitmap().getwidth()
if y > bounds.y then y=0-sprite.getregion().getbitmap().getheight()
if x < 0-sprite.getregion().getbitmap().getwidth() then x=bounds.x
if y < 0-sprite.getregion().getbitmap().getheight() then y=bounds.y
sprite.moveto(x,y)
sprite.setdata({xpos:x,ypos:y,movex:data.movex,movey:data.movey})
end for


compositor.drawall() 'draw all sprites even if they have not moved or changed
screen.swapbuffers() 'swap screen buffers to display completed drawing
end while
end sub


Joel
0 Kudos
idunno
Visitor

Re: Changing From roImageCanvas to roScreen questions

Thank you, that is extremely helpful.
0 Kudos
RokuJoel
Binge Watcher

Re: Changing From roImageCanvas to roScreen questions

Here is a modified version of the same thing with video playback (video playback in motion too).:
https://www.box.com/shared/c46bb964b26f1347a41e

Note that there is now only one loop, screen.clear statements all clear to &h00000000 instead of &h000000FF

the video playback is pretty much ripped straight out of simplevideoplayer, modified to use roVideoPlayer instead of roVideoScreen.

This should supply a few minutes of annoying, but educational fun:




sub main()




screen=createobject("roscreen",true)
'**************************************

print "Displaying video: "
p = CreateObject("roMessagePort")
video = CreateObject("roVideoPlayer")



bitrates = [0]



urls = ["http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]
qualities = ["SD"]
streamformat = "hls"
title = "Apple BipBop Test Stream"
srt=""


if type(args) = "roAssociativeArray"
if type(args.url) = "roString" and args.url <> "" then
urls[0] = args.url
end if
if type(args.StreamFormat) = "roString" and args.StreamFormat <> "" then
StreamFormat = args.StreamFormat
end if
if type(args.title) = "roString" and args.title <> "" then
title = args.title
else
title = ""
end if
if type(args.srt) = "roString" and args.srt <> "" then
srt = args.StreamFormat
else
srt = ""
end if
end if

videoclip = CreateObject("roAssociativeArray")
videoclip.StreamBitrates = bitrates
videoclip.StreamUrls = urls
videoclip.StreamQualities = qualities
videoclip.StreamFormat = StreamFormat
videoclip.Title = title
print "srt = ";srt
if srt <> invalid and srt <> "" then
videoclip.SubtitleUrl = srt
end if

targetrect = { x: 300, y: 300, w: 320, h: 180 }


video.SetMessagePort(p)
video.SetDestinationRect(targetrect)
video.addContent(videoclip)
video.Play()

'*****************************************
'screen.setalphaenable(false)
image1=createobject("robitmap","pkg:/images/imageone.png")
image2=createobject("robitmap","pkg:/images/imagetwo.png")
image3=createobject("robitmap","pkg:/images/imagethree.png")

'lets set up some positions for these images:
obj1={posx:200,posy:200}
obj2={posx:400,posy:400}
obj3={posx:600,posy:600}

'**********************************setup sprites******************************

'If one of the layers has transparancy, and you want the layer below to show through the transparant section, you would enable transprancy for that image when drawing to the screen.

'Another approach with roScreen is to create Sprites, which are images designed to be moved around the screen, typically as objects in a game, but they can be used for almost anything.

'lets create some sprites. first we need to create a compositor:
compositor=createobject("rocompositor")

'now we need to tell it where to draw and the background color:
compositor.setdrawto(screen,&h00000000)

'To create a sprite, first we create a bitmap image, as we did before
bmp1=createobject("roBitmap", "pkg:/images/alien1.png")

'then we create a region from that bitmap:
reg1=createobject("roregion", bmp1,0,0,bmp1.getwidth(),bmp1.getheight())
'reg1.setalphaenable(true)
bmp2=createobject("roBitmap", "pkg:/images/alien2.png")
reg2=createobject("roregion", bmp2,0,0,bmp2.getwidth(),bmp2.getheight())
bmp3=createobject("roBitmap", "pkg:/images/alien3.png")
reg3=createobject("roregion", bmp3,0,0,bmp3.getwidth(),bmp3.getheight())

'from those three regions, we will create our sprites:
spr1=compositor.newsprite(200,200,reg1,0) 'create a sprite on layer 0
spr2=compositor.newsprite(250,250,reg2,1) 'create a sprite on layer 1
spr3=compositor.newsprite(350,350,reg3,2) 'create a sprite on layer 3




'to make it easier to work with them, we are going to put them into an array:

sprArr=[spr1,spr2,spr3]
'we can actually store data inside a sprite! lets put our x and y positions into an Associative Array and store in our sprite:
for each sprite in sprarr
sprite.setdata({xpos:sprite.getx(),ypos:sprite.gety()})
end for

'Ok, now lets make a little routine that moves them randomly around the screen:
bounds={}
bounds.x=screen.getwidth()
bounds.y=screen.getheight()
screen.setalphaenable(true) 'enable transparency

'Lets set up a timer to control movement:

movetimer=createobject("rotimespan")
movetimer.mark()

'lets reset the timer we used for the while loop:

vmovex=0
vmovey=0

for each sprite in sprarr
data=sprite.getdata()
data.movex=(rnd(3)-2)
data.movey=(rnd(3)-2)
sprite.setdata(data)
movetimer.mark()
end for
'*****************************************************************************
timer=createobject("rotimespan")
timer.mark()



while timer.totalseconds() <60 'exit this loop after 15 seconds.

screen.clear(&h00000000) 'clear screen to black
screen.setalphaenable(false) 'disable alpha for this draw, since the object is not transparent
screen.drawobject(obj1.posx,obj1.posy,image1)
screen.setalphaenable(true) 're enable for transparent images
screen.drawobject(obj2.posx,obj2.posy,image2)
screen.drawobject(obj3.posx,obj3.posy,image3)


'move objects
if obj1.posx > 0 then obj1.posx=obj1.posx-1
if obj1.posy > 0 then obj1.posy=obj1.posy-1

if obj2.posx > 0 then obj2.posx=obj2.posx-1
if obj2.posy > 0 then obj2.posy=obj2.posy-1

if obj3.posx > 0 then obj3.posx=obj3.posx-1
if obj3.posy > 0 then obj3.posy=obj3.posy-1

'move video!


'*********************move sprites*******************************

if movetimer.totalmilliseconds() > 500 then
xr=(rnd(3)-2)
yr=(rnd(3)-2)
if xr <>0 then vmovex=xr
if yr <>0 then vmovey=yr


for each sprite in sprarr
data=sprite.getdata()
xr=(rnd(3)-2)
yr=(rnd(3)-2)
if xr <>0 then data.movex=xr
if yr <>0 then data.movey=yr
sprite.setdata(data)
movetimer.mark()
end for
end if

'move sprites
for each sprite in sprarr
data=sprite.getdata()
x=data.xpos
y=data.ypos
x=x+data.movex
y=y+data.movey
if x > bounds.x then x=0-sprite.getregion().getbitmap().getwidth()
if y > bounds.y then y=0-sprite.getregion().getbitmap().getheight()
if x < 0-sprite.getregion().getbitmap().getwidth() then x=bounds.x
if y < 0-sprite.getregion().getbitmap().getheight() then y=bounds.y
sprite.moveto(x,y)
sprite.setdata({xpos:x,ypos:y,movex:data.movex,movey:data.movey})
end for
targetrect.x=targetrect.x+vmovex
targetrect.y=targetrect.y+vmovey
if targetrect.x > bounds.x then targetrect.x=0-targetrect.w
if targetrect.y > bounds.y then targetrect.y=0-targetrect.h
if targetrect.x < 0-targetrect.w then x=bounds.x
if targetrect.y < 0-targetrect.h then y=bounds.y
video.SetDestinationRect(targetrect)

compositor.drawall() 'draw all sprites even if they have not moved or changed
screen.swapbuffers() 'display the completed draw on screen
'****************************************************************





end while


end sub
0 Kudos
idunno
Visitor

Re: Changing From roImageCanvas to roScreen questions

I am learning a lot, but I still don't understand how to make sure something will be displayed in front of something else. For example, I used the roscreen clear function to set a background color, and now my video is behind the background. I can hear it and everything, and when I remove the background I can see it, so I know its there. How do I make sure that the video displays on top?
0 Kudos