Example Lua Game

Let’s take a look at building a very simple game. We’ll be rebuilding the Sprite Stress Test Demo which highlights the sprite rendering limitation of Pixel Vision 8.

image alt text

By default, the Display Chip can only handle displaying a set number of sprites at the same time based on the system template you choose. We'll create a loop that attempts to render more sprites than the system can handle. The outcome is that additional draw calls are ignored and the engine maintains its optimal performance.

Here is the full Lua script:

local delay = 0
local delayTime = 2
local totalSprites = 200
local char = nil
local x = 0
local y = 0
local width = 0
local height = 0
function Init()
local displaySize = Display()
width = displaySize.x
height = displaySize.y
end
function Update(timeDelta)
delay = delay + timeDelta
if(delay > delayTime) then
BackgroundColor(math.random(0, 14))
delay = 0
end
end
function Draw()
Clear()
for i=0,totalSprites,1 do
char = string.char(math.random(33, 126))
x = math.random(0, width)
y = math.random(0, height)
DrawText(char, x, y, DrawMode.Sprite, "large", 15)
end
end

Let’s walk through the code to see how it uses Pixel Vision 8’s sprite drawing APIs. First, create a new project and call it SpriteStressTest.

image alt text

Next, open up the code.lua file, select all of the code by pressing Ctrl + A, and then delete it. Now we can start coding from scratch. These are some variables we'll use for performing the stress test.

local delay = 0
local delayTime = 2
local totalSprites = 200
local char = nil
local x = 0
local y = 0
local width = 0
local height = 0

The Init() method is part of the game's lifecycle and called a game starts. We are going to use this method to configure background color and get a reference to the display’s dimensions.

function Init()

It's best to define this outside of the for loop since we only need to set the value once.

local displaySize = Display()
width = displaySize.x
height = displaySize.y

Now we just need to end the Init() function.

end

The Update() method is part of the game's life cycle. The engine calls Update() on every frame before the Draw() method. It accepts one argument, timeDelta, which is the difference in milliseconds since the last frame. We are going to use this timeDeltavalue to keep track of the time before changing the background color.

function Update(timeDelta)

We start by adding the timeDelta to the delay.

delay = delay + timeDelta

Next, we will need to test if the delay value is greater than the delayTimevariable we set up at the beginning of our class.

if(delay > delayTime) then

After the appropriate delay, we can change the background color to a random value. We'll cap this between 0 and 14.

BackgroundColor(math.random(0, 14))

There are 16 colors in Pixel Vision 8’s palette starting at 0 and well save the last color to use for our sprites later on.

image alt text

We need to reset the delayso we can start tracking it again in the next frame.

delay = 0

Now we just need to close the condition and the function.

end
end

The Draw() method is part of the game's life cycle. It is called after Update() and is where all of our draw calls should go. We'll be using this to render sprites to the display.

function Draw()

Clearing the display on each frame is important. Since we are not using a tilemap, we can directly clear the display by calling the Clear() method.

Clear()

The following loop will create a random x and y value based on the display's dimension, then we’ll draw a sprite to the screen. It will also pick a random character by converting an ASCII value to its corresponding string value.

for i=0,totalSprites,1 do
char = string.char(math.random(33, 126))
x = math.random(0, width)
y = math.random(0, height)
DrawText(char, x, y, DrawMode.Sprite, "large", 15)
end

As you can see, we are drawing individual characters to the screen. We’ll be using the large.font.png file for each sprite. It’s important to note even though the Font Chip and Sprite Chip store their sprites in separate memory blocks, any sprite draw call will be limited by the maximum draw calls per frame which we’ll talk about in a little bit.

Now, the only thing left is to can close the draw function call.

end

At this point, if you run the game by pressing Ctrl + R, it will display all 200 sprites.

image alt text

The default Pixel Vision 8 game template doesn’t have a cap on the number of sprites it can draw to the screen. Let’s open up the data.json file and make one modification.

If you have the Pro Tools installed, you’ll have access to the Chip Editor. Simply click on the GPU chip, and change the Draws value from 0 to 64.

image alt text

If you do not have the Pro Tools, you can manually make this change by modifying the SpriteChip’s maxSpriteCount value. Change the 0 to 64

image alt text

Now if you rerun the game after saving and closing the data.json file, you’ll see that PV8 will only draw 64 sprites at any one time.

image alt text

You can continue to play around with this number to see how it affects drawing sprites to the display. At this point, you should have a basic understanding of a game’s lifecycle, as well as how Pixel Vision 8’s most common APIs work.