Create a new Lua file called code.lua in your Workspace/Sandbox/ folder.
Create a new local variable called fireballSprites inside the script:
001 local fireballSprites = {0, 1}The first thing we are going to do is create a table to store the two fireball sprites.
You can always preview the sprites.png file by using the Game Creator Pro's Sprite Editor. Here you can see that our first two sprites are the fireballs and the rest of the sprites come from the default.font.png file.
Create a new local variable called fireball inside the script:
002 local fireball = {
003 spriteID = fireballSprites[1],
004 x = 72,
005 y = 48,
006 flipH = false,
007 flipV = false
008 }Next, we are going to create an object that represents the final fireball we plan on animating later on in the tutorial. This table store the sprite ID to draw to the display and the horizontal and vertical flip values which are flipH and flipV.
Create a new function called Init():
009 function Init()
010
011 endThe Init() function executes when a game runs for the first time.
Add the following code to the Init() function:
010 BackgroundColor(32)For this tutorial, we'll be manually changing the background color of the display to blue which is color ID 32.
Add the following code to the Init() function:
011 DrawText("Draw Sprites", 1, 1, DrawMode.Tile, "default")Here we are displaying some text with the title of the tutorial. It uses the default.font.png file in our sandbox to render each text character to the tilemap. Since we are rendering the text to the tilemap, we won't have to redraw it on each new frame.
Create a new function called Draw():
013 function Draw()
014
015 endThe Draw() function is called on every frame after Update(). This is where our render logic goes.
Add the following code to the Draw() function:
014 RedrawDisplay()We can use the RedrawDisplay() function to clear the display and draw the tilemap to the display in a single call.
Add the following code to the Draw() function:
015 DrawSprite(fireballSprites[1], 8, 48)
016 DrawSprite(fireballSprites[2], 24, 48)The DrawSprite() function requires three arguments to work: sprite ID, Y, and Y. We are going to draw two sprites to the screen, one call for each sprite ID we defined in the fireballSprites table.
As you can see, it's straightforward to draw a single sprite to the display. Find the sprite ID you want to display and give it an X and Y position. It is essential to keep in mind that depending on the system template you are using there may be a limit to the number of sprites you can display at one time on the screen. You can always modify this value by editing the data.json file or using the Chip Editor tool in the Game Creator.
At this point, you and run the game and see our two fireballs. In the Game Creator press Ctrl + 1 to switch into play mode. You should see the following.
Here we are flipping the two fireball sprites horizontally and vertically by passing in two additional boolean values to the DrawSprite() function.
Add the following code to the Draw() function:
017 DrawSprite(fireballSprites[1], 40, 48, true, true)
018 DrawSprite(fireballSprites[2], 56, 48, true, true)By supplying a boolean for flipH and flipV we can create additional sprites from ones that already exist in memory. Instead of having 4 sprites to represent the fireball's rotation we are now only using 2 sprites which allows us to have more sprites stored in memory for other game objects. You can change the direction of a player or enemy by merely flipping their horizontal or vertical value.
You can run the game to see the new sprites on the display.
Add the following code to the Draw() function:
019 DrawSprite(fireball.spriteID, fireball.x, fireball.y, fireball.flipH, fireball.flipV)The last thing we are going to display is the final fireball game object. We'll do this by passing the fireball table properties into the DrawSprite() function. By storing a game object's values in a table, it is easier manipulate this via code as you'll see in the next few steps when we animate the fireball.
Create a new local variable called fireballAnimation inside the script:
021 local fireballAnimation = {
022 {spriteID = fireballSprites[1], flipH = false, flipV = false},
023 {spriteID = fireballSprites[2], flipH = false, flipV = false},
024 {spriteID = fireballSprites[1], flipH = true, flipV = true},
025 {spriteID = fireballSprites[2], flipH = true, flipV = true}
026 }Here we are going to create a table to store each of the four frames of animation the fireball needs to rotate. You'll see that each table stores the spriteID which comes from the fireballSprites table and the flipH and flipV values.
Add the following local variables:
027 local fireballDelay = .2
028 local fireballTime = 0
029 local fireballFrame = 1To animate the fireball, we need to keep track of a few values such as the delay between each frame, the time of the current frame and the index for the current animation frame.
Create a new function called Update():
030 function Update(timeDelta)
031
032 endThe Update() function gets called before the Draw() function and is where we store any calculations or non-visual game logic that should happen before sprites render to the display.
For this tutorial, our Update() function is going to focus on manually calculating the current fireball's animation frame.
Add the following code to the Update() function:
031 fireballTime = fireballTime + timeDeltaOn every frame, we want to add the timeDelta to the fireballTime variable we are using to keep track of how much time has passed between each frame of animation.
The timeDelta is the time between the current frame and the last frame represented in milliseconds. The game engine tracks the time it takes between each frame automatically. If your game is running at 60 fps, the timeDelta should be roughly 0.03 milliseconds. However, the timeDelta value will fluctuate depending on what is going on. When creating animations or movement, it's important to consider this value's change between frames.
Add the following condition to the Update() function:
032 if(fireballTime > fireballDelay) then
033
034 endNow we need to test if the if the fireballTime is greater than the fireballDelay.
Add the following code to the condition :
033 fireballFrame = fireballFrame + 1Since the time was greater than the delay, we can now increase the fireballFrame to the next value.
Add the following condition to the condition :
034 if(fireballFrame > #fireballAnimation) then
035 fireballFrame = 1
036 endWe only have a set number of frames, so we need to make sure to loop the animation by setting the fireballFrame value to 1 if the current frame value is greater than the total items in the fireballAnimation table.
Add the following code to the condition :
037 fireballTime = 0Finally, we need to reset our fireballTime variable back to 0 since it needs to start tracking the time for the next frame.
At this point, we have everything we need to manage our animation. This technique is a standard way to handle animation for sprites. We set a time which tracks the value between frames, a delay to know when to change the animation and a way to track the current frame of the animation. You can use this to synchronize animations between multiple sprites or use different values to track animation frame changes at different speeds.
Create a new local variable called frameData inside the condition :
039 local frameData = fireballAnimation[fireballFrame]All that is left now is to get the fireballAnimation table that contains our animation frame's values. We use the fireballFrame as the index.
Add the following code to the condition :
040 fireball.spriteID = frameData.spriteID
041 fireball.flipH = frameData.flipH
042 fireball.flipV = frameData.flipVNow that we have the values we need for the fireball's animation, we can update the fireball table, so our Draw() function displays any changes in the animation.
Congratulations on completing the Draw Sprite Tutorial. If you refresh the game, you should see all four fireball sprites and the animated fireball. Hopefully, you have learned how to use the DrawSprite() function to render graphics to the display and leverage flipping them horizontally and vertically to save space on the Sprite Chip.