This tutorial series will be about creating a very basic JRPG engine using FlashPunk. At the end of it all, you’ll be able to have an animated player sprite walking around a tilemap, much similar to old Zelda games, or Final Fantasy games.
I myself haven’t finished my engine yet, so please be patient for follow up tutorials. I don’t claim that this is the “right” way of implementing a JRPG engine, it’s just the way I came up with. Also, I recommend that you follow the series in order, because the posts build up on each other.
If you’re completely new to FlashPunk, please work through these beginner tutorials. You’ll of course need the FlashPunk library, and I recommend you use the IDE FlashDevelop. What I’m about to explain here isn’t that hard to do though, so by all means, don’t feel intimidated.
In this first tutorial, I’ll explain how to add an animated player entity to the world that can be moved around and updates its animation accordingly. The complete FlashDevelop project can be downloaded here.
So let’s start.
First, we create the Engine class “Main.as”:
The width and height are set so that they are clean multiples of 48, which is the tile size I’ll be using in this tutorial. I got jerky behavior when I went for 640×480. We set the FP.world to our World “Game.as”, which is shown in the next snippet. We’ll put the Game.as file into a subfolder in the src folder called “worlds”.
Before we do anything more in the Game class, we move on to creating our first entity, the Player class, which we’ll put into the subfolder “entities”. The player character uses a so-called sprite sheet. Sprite sheets are images that contain single frames laid out in sequence, which are to be read by the game engine.
Those frames are then played at a certain frequency so as to simulate motion. Create a folder “assets” in the main project folder and a subfolder “gfx”. There, put this image file. Call it “player.png”
Ok, there’s a lot going on in this code.
First off, we load our spritesheet into the class using the Embed, that defines the relative filepath to the player.png file. This is then stored in the PLAYER constant (which doesn’t have to be a constant, by the way) of type CLASS.
We define the width and height of all the frames, stored in SPRITE_WIDTH and SPRITE_HEIGHT. Look at the dimensions of the spritesheet. 184 pixels is a clean multiple of 23 and 112 is a clean multiple of 28.
I’ll explain why this is important in a moment. We create the playerSpritemap instance of type SpriteMap, which is used to store the entire Spritemap of the player character, and to become the graphic property of the Entity superclass. The Spritemap constructor method takes the PLAYER constant that is the raw spritesheet, and the dimensions of frames SPRITE_WIDTH and SPRITE_HEIGHT. It splits the sprite sheet image into many 23×28 sub-images, which are all frames, and puts them into an array. This is why we want clean multiples in the sprite sheet itself, to avoid any problems in the Spritemap.
We then define a speed limit and the curAnimation variable of type String. The speed limit is used to define the speed of the player. Speed means change of position per frame each for the X and Y axis. The curAnimation variable stands for “current animation” and is a String that stores the label of the current frame sequence (which motion) is currently played.
In the constructor, we immediately call the setupSpritesheet() function. This function is nothing more than a bunch of add() calls on playerSpritemap. The add call is used to define an animation by saying a) what name is should have, b) what frames should be played, c) the framerate of playing the animation and d) if the animation should loop or just play once. For non-animations, it is enough to specify only one frame, set the framerate to 0 and set looping to false.
For example, the “walk_down” animation consists of the first 8 frames of the sprite sheet. Each frame has
an index, and they start with 0, so the first frame has index 0, and so on. I’m sure this is nothing too hard to grasp.
We set the graphic of the Player class as the Spritemap, and then play the initial animation that we defined with curAnimation, which we set to “stand_down”. You get the idea now, yes?
After that we set the initial position of the player (or rather the coordinates of the upper left corner) using the Point instance we obtain as a parameter. Nothing too fancy there. We define input labels. Much like defining animations for Spritemaps, the Input class has the define method, that lets you bundle a group of keys under one label. So that later, when you do your input checks, you just have to check for the label, and the underlying class does the work of looking up exactly which keys are to be checked. This allows for customizable control schemes. (Courtesy of Shroom)
The update function is overridden and gets called each new frame of the general game loop. This is the place where we handle our input for the player. The player input governs the movement and animation. For example, if I press the button for moving right, I want the x coordinate to increase, as well as play the “walk_right” animation. We set 2 boolean variables, which will help us determine if there was any movement at all, because if that’s the case, we want to display one of the animations for idle standing around.
Following this is a bunch of if else calls that all check whether a particular key is being pressed. The function call Input.check(“walk_left”) for example returns true if the player pressed the A key or left arrow key during the current frame, which were defined to stand for the “walk_left” input label. If it is pressed, we want to increase the x coordinate by the players speed property (for moving left, we just substract speed from the x property, and so on). We then set curAnimation to “walk_right”. It would’ve been better to check first if the curAnimation is already “walk_right” and only if it wasn’t, to call the playerSpritemap.play() method, but this way, the code is less cluttered.
The else case is only entered if neither of the A or D keys is being pressed, in which case we can rule out
any horizontal movement, so that’s why set it to false.
The same procedure is used for vertical movement. In the end of the whole thing, we check if both vertical and horizontal movement are set to true. If they’re both not, then we can say that the player isn’t moving at all, so we check the last animation and set the relating idle animation. (i.e. for “walk_up”, we now display the idle counter part “stand_up”.
Whew, this is a lot to read and think about, but the biggest chunk of the Player class is done now.
Now we move on to implement the player into the game world!
Open up Game.as and update it to be like this:
It’s pretty self-explanatory at this point. We add a property “player” of the Player class we just created, instantiate it in the World’s constructor method while giving it its initial starting position as a Point. Then we call the add() method of the World class to add the player entity to the “stage”.
Tada! I hope you enjoyed the first part of the tutorial. To learn how to load OGMO tilemaps into the World, read the next tutorial.