Need help making TV static class more efficient

Hey all,

I wrote some code to handle making TV-like static.

I stat by drawing a white background and then create a series of black squares over the white. When I refresh I randomly set the black squares to be either visible or not visible.

I pass in a size to be used for the black squares. If I use a width of 2 in a static window that’s 320x320 then it runs fine but doesn’t look very real. If I set it to 1 pixel wide then it runs very slowly, but it looks like it will be a great (and realistic) effect!

Anyways I’m wondering if anyone has any suggestions on how to improve the performance of my static class?

One thing I’ve thought about is not trying iterate through every square but randomly select a few and toggle them, but I have doubts that this will look as good.

Here is the class “Graphics_StaticWindow.lua”:
[lua]local static = {}

local staticWindow = display.newGroup()
local getRand = math.random
local background
local blackDots = {}
local dotCountHorizontal
local dotCountVertical

local function newBlackSquare( blackDotSize )
local blackDot = display.newRect( 0,0,blackDotSize,blackDotSize )
blackDot:setFillColor( 0,0,0 )
return blackDot
end

static.newStaticWindow = function( width,height,dotSize )
staticWindow.windowWidth = width or 480
staticWindow.windowHeight = height or 320
staticWindow.blackDotSize = dotSize or 2

dotCountHorizontal = math.floor( staticWindow.windowWidth/staticWindow.blackDotSize )
dotCountVertical = math.floor( staticWindow.windowHeight/staticWindow.blackDotSize )
local currentDotX, currentDotY = 0,0

background = display.newRect( 0, 0, staticWindow.windowWidth, staticWindow.windowHeight )
background:setFillColor( 255,255,255 )
staticWindow:insert( background )

for row = 1, dotCountVertical do
blackDots[row] = {}
for col = 1, dotCountHorizontal do
blackDots[row][col] = newBlackSquare( staticWindow.blackDotSize )
blackDots[row][col].x = currentDotX
blackDots[row][col].y = currentDotY
currentDotX = currentDotX+staticWindow.blackDotSize
staticWindow:insert( blackDots[row][col] )
end
currentDotX = 0
currentDotY = currentDotY+staticWindow.blackDotSize
end
return staticWindow
end

static.refresh = function( )
local rand
for row = 1, dotCountVertical do
for col = 1, dotCountHorizontal do
rand = getRand( 1,100 )
blackDots[row][col].isVisible = (rand>50)
end
end
end

return static[/lua]

And how it’s used in the game:
[lua]local static = require( “Graphics_StaticWindow” )
local staticWindow = static.newStaticWindow( 320,320, 2)
group:insert( staticWindow )[/lua]

Then I refresh it by calling this in an “enterFrame” listener
[lua]static.refresh( )[/lua] [import]uid: 181948 topic_id: 35590 reply_id: 335590[/import]

If I understand what you’re doing you’re drawing/refreshing 320x320 black squares, which is over 100,000 display objects. Even if half of them are transparent that’s still a huge number of objects to update and your frame rate will be very low. If you haven’t tried your code on a device yet you’ll probably be surprised by how low the frame rate will be.

I would suggest just drawing 3-5 different images of static at the size of the effect you are trying to create. Then just display those images one after the other in a loop. Most any device will have no problem animating a few 320x320 display objects at 30 or even 60 fps. [import]uid: 9422 topic_id: 35590 reply_id: 141454[/import]

Great I’ll try that- thanks!
[import]uid: 181948 topic_id: 35590 reply_id: 141461[/import]

If you want the static to play as a layer underneath another graphic layer, like the frame of a TV set, another way to do it would require only a single image of static.

You could create the image of the tv with a transparent hole for the static image, then put the static as a layer underneath that. If you made the image somewhat bigger than the hole, say 10%, you could randomly “jitter” the position of the image a few pixels in any direction on every frame. You’d have to make sure you don’t jitter the image past the 10% extra edge. [import]uid: 9422 topic_id: 35590 reply_id: 141465[/import]

Not entirely sure what you’re trying to create - but in one app I wanted to create an effect that looked like when you put a VHS on pause. I managed to grab a PSD from the internet and played around with the alpha/layer settings - the overall effect was exactly what I needed.

Not sure if that helps or not. [import]uid: 33275 topic_id: 35590 reply_id: 141504[/import]

@HardBoiledIndustries:

Thanks for your suggestions! I ended up making several frames and looping through them like you said. You could tell it was looping so I then randomly added X/Y inversion to the frames. You can still tell that there are a finite set of outcomes but only if you really watch it.

@SegaBoy:

Are you talking about the two static-y lines that come up when you pause a VHS tape? I’m not going for that effect but it would still be interesting to see how you did it!
[import]uid: 181948 topic_id: 35590 reply_id: 141509[/import]

@Segaboy

Do you have a link to the app? I’d like to see the final result (or just post a pic here). [import]uid: 51654 topic_id: 35590 reply_id: 141523[/import]

For what it’s worth, here’s how I got a static effect. I made a small noise texture, then just treated it as a sprite, with four frames. I then tiled it across the screen, giving random rotations of 90 degrees, then just playing the sequence. There’s a small amount of repetition, but most people wouldn’t notice. An easy way to solve that would to obviously just use a larger texture, so therefore, less tiling.

Here’s the code if you’re interested

[code]
local staticOptions =
{
width = 128,
height = 128,
numFrames = 4,
sheetContentWidth = 256,
sheetContentHeight = 256
}

local rotationTable = {
[1] = 90,
[2] = 180,
[3] = 270
}

local staticSequenceData = {
{name = “animate”, start = 1, count = 4, time = 500},
}

local staticSheet = graphics.newImageSheet(“Assets/Gfx/static.png”, staticOptions)

drawNoise = function()
local noiseGroup = display.newGroup()

for y = 0, 3 do
for x = 0, 7 do
local staticNoise = display.newSprite(noiseGroup, staticSheet, staticSequenceData)
staticNoise.alpha = 0.25
staticNoise.rotation = rotationTable[math.random(1,3)]
staticNoise.x = 0+staticNoise.contentWidth*0.5+(x*128)
staticNoise.y = 64+staticNoise.contentHeight+(y*128)
staticNoise:play()
end
end

return noiseGroup
end
[/code] [import]uid: 88980 topic_id: 35590 reply_id: 141566[/import]

@dan.hunter:

Thanks, that’s very similar to what I ended up doing except I use the static’s x+y scale to flip them (although your way may be more efficient).
[import]uid: 181948 topic_id: 35590 reply_id: 141579[/import]

If I understand what you’re doing you’re drawing/refreshing 320x320 black squares, which is over 100,000 display objects. Even if half of them are transparent that’s still a huge number of objects to update and your frame rate will be very low. If you haven’t tried your code on a device yet you’ll probably be surprised by how low the frame rate will be.

I would suggest just drawing 3-5 different images of static at the size of the effect you are trying to create. Then just display those images one after the other in a loop. Most any device will have no problem animating a few 320x320 display objects at 30 or even 60 fps. [import]uid: 9422 topic_id: 35590 reply_id: 141454[/import]

Great I’ll try that- thanks!
[import]uid: 181948 topic_id: 35590 reply_id: 141461[/import]

If you want the static to play as a layer underneath another graphic layer, like the frame of a TV set, another way to do it would require only a single image of static.

You could create the image of the tv with a transparent hole for the static image, then put the static as a layer underneath that. If you made the image somewhat bigger than the hole, say 10%, you could randomly “jitter” the position of the image a few pixels in any direction on every frame. You’d have to make sure you don’t jitter the image past the 10% extra edge. [import]uid: 9422 topic_id: 35590 reply_id: 141465[/import]

Not entirely sure what you’re trying to create - but in one app I wanted to create an effect that looked like when you put a VHS on pause. I managed to grab a PSD from the internet and played around with the alpha/layer settings - the overall effect was exactly what I needed.

Not sure if that helps or not. [import]uid: 33275 topic_id: 35590 reply_id: 141504[/import]

@HardBoiledIndustries:

Thanks for your suggestions! I ended up making several frames and looping through them like you said. You could tell it was looping so I then randomly added X/Y inversion to the frames. You can still tell that there are a finite set of outcomes but only if you really watch it.

@SegaBoy:

Are you talking about the two static-y lines that come up when you pause a VHS tape? I’m not going for that effect but it would still be interesting to see how you did it!
[import]uid: 181948 topic_id: 35590 reply_id: 141509[/import]

@Segaboy

Do you have a link to the app? I’d like to see the final result (or just post a pic here). [import]uid: 51654 topic_id: 35590 reply_id: 141523[/import]

For what it’s worth, here’s how I got a static effect. I made a small noise texture, then just treated it as a sprite, with four frames. I then tiled it across the screen, giving random rotations of 90 degrees, then just playing the sequence. There’s a small amount of repetition, but most people wouldn’t notice. An easy way to solve that would to obviously just use a larger texture, so therefore, less tiling.

Here’s the code if you’re interested

[code]
local staticOptions =
{
width = 128,
height = 128,
numFrames = 4,
sheetContentWidth = 256,
sheetContentHeight = 256
}

local rotationTable = {
[1] = 90,
[2] = 180,
[3] = 270
}

local staticSequenceData = {
{name = “animate”, start = 1, count = 4, time = 500},
}

local staticSheet = graphics.newImageSheet(“Assets/Gfx/static.png”, staticOptions)

drawNoise = function()
local noiseGroup = display.newGroup()

for y = 0, 3 do
for x = 0, 7 do
local staticNoise = display.newSprite(noiseGroup, staticSheet, staticSequenceData)
staticNoise.alpha = 0.25
staticNoise.rotation = rotationTable[math.random(1,3)]
staticNoise.x = 0+staticNoise.contentWidth*0.5+(x*128)
staticNoise.y = 64+staticNoise.contentHeight+(y*128)
staticNoise:play()
end
end

return noiseGroup
end
[/code] [import]uid: 88980 topic_id: 35590 reply_id: 141566[/import]

@dan.hunter:

Thanks, that’s very similar to what I ended up doing except I use the static’s x+y scale to flip them (although your way may be more efficient).
[import]uid: 181948 topic_id: 35590 reply_id: 141579[/import]