Flixel Forums

development => help => Topic started by: SeiferTim on Mon, Aug 3, 2009

Title: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 3, 2009
WARNING: As of Flixel version 1.40, this Tutorial is completely broken. You *might* be able to use it for earlier versions of Flixel, or as a guideline to help you get started, but I do not recommend using it at this time. Other tutorials may or may not work as well. Efforts are underway to update the tutorial, and the new version will be up on the Wiki: http://wiki.github.com/AdamAtomic/flixel (http://wiki.github.com/AdamAtomic/flixel).

Well, since I'm not really used to forums, I didn't think to set aside several threads before posting these, and all of the posts are mixed up... :P

Here's sort of a "table of contents" to help you find each section better:

=================================================================

So, Darthlupi (http://flixel.org/forums/index.php?action=profile;u=127) and I have been working on this tutorial. Its taking a little while to get it 'done', so we though we should post each part as we finish it. So here's parts 1 & 2, and 3 should be done in a day or so.

Enjoy!

Flixel Basic Game Tutorial

I: Introduction

The goal of this Tutorial is to walk you through the process of starting a very basic Flixel Platform Game, while explaining and demonstrate some of the key functions and pieces of Flixel so that you can utilize them for future projects of your own. We will also explore some of the avenues to further expand on the basic concepts to help you explore and learn on your own.

Do not be overwhelmed with any of the information in the Getting Started section.  Once you understand the basic concepts we cover there the rest of the tutorial will come together for you nicely.

The Tutorial is going to require a few things of you if you intend to get the most out it:

(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)A computer ( or a very fast abacus )(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)FlashDevelop installed and configured
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)Flash Develop Configuration Guide (http://www.flashdevelop.org/wikidocs/index.php?title=Configuration)
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)Image-editing software that can export PNGs.
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)PhotoShop (http://www.adobe.com/products/photoshop/photoshop/)(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)Gimp (http://www.gimp.org/) (Free)
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)Some understanding of programming concepts and practices.

You are not going to make the next Cave Story (http://www.miraigamer.net/cavestory/) with this tutorial. However, with some of the items presented within, and with a little ambition to learn more on your own, you should be able to create almost any type of game you want with Flixel.

II: Getting Started
1:  First, you will need to download the Flixel (http://flixel.org/) framework, and then you can proceed to step 2.
2:  Open FlashDevelop. From the menu at the top, click "Project" and choose "New Project..."
(http://timsworld.nfshost.com/images/tut_pics/NewProj.png)

3:  Choose "AS3 Project" from the list, and give your project a name, and a location. We'll be using "Tutorial" for the name of this project.
(http://timsworld.nfshost.com/images/tut_pics/newProjScreen.png)

4:  Once Flixel has finished downloading, open and extract all the files to the "src" folder within your project's folder.

5:  You can delete the Main.as file that's in your project, then make a new Class file to the "src" folder, and name it "Tutorial.as". Right-click on this file and click "Always Compile", then double-click the file to open it.
(http://timsworld.nfshost.com/images/tut_pics/AlwaysCompile.png)
      What this does is set this Class to compile when ever you press the play button or press F5.

6:  You should see something that looks like this:
      
Code: [Select]
package  
      {
          
          public class Tutorial
          {
              
              public function Tutorial()
              {
                  
              }
              
          }
          
      }
     This is the basic structure of a Class in AS3.

      You are going to want to replace package with package com.Tutorial to define the directory structure for the package.


      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:Classes are a method for making little programs that you can "call" as many times as you want and use in other parts of your code.  This is really handy in game development because game objects can be defined in separate classes and used at will.  Read More... (http://www.adobe.com/devnet/flash/quickstart/creating_class_as3/)

7:  Now, in order to tell the project that we want to use Flixel, we have to import it. So, somewhere after the first { and before "public class Tutorial", add a new line and type:
      
Code: [Select]
import com.adamatomic.flixel.*;
      For this tutorial, we're going to import everything - but in the future, you'll want to actually pick the pieces you want to use.

      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:Importing a file is basically making all of it's contents available to the rest of your program.  I this case we use the * which loads everything in the Flixel directory to be used by our game.

8:  Next, we need to define the size of the movie, so in a new line under the import, add:
      
Code: [Select]
[SWF(width = "640", height = "480", backgroundColor = "#000000")]      This tells the project that we're going to make a SWF file that is 640 pixels wide by 480 pixels high with a black background.

      Basically, you set the game's display here.  This is not the true resolution.  This is set later.  Think of this as the window size.

9:  In the next line, we'll add the preloader:
      
Code: [Select]
[Frame(factoryClass="Preloader")]      You also need to open the Preloader.as file and change the className to be the same as your Project's class, in this case:
      
Code: [Select]
className = "Tutorial";
10: Next, we need to make this class (Tutorial) into a sort of copy of the FlxGame class. To do this, we make this class an 'extension' of the FlxGame class.

      What this does it tells the project that the Tutorial Class is basically the same as the FlxGame class, but with a different name, and your own stuff added to it.

      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:Think of extending classes like drawing with tracing paper. The FlxGame class, the class being extended, is drawn on the bottom layer, and the Tutorial class is on a piece of tracing paper on top of the FlxGame class. You can see all the lines on the bottom layer, and you can draw your own lines without actually changing the bottom layer, and if some time in the future FlxGame is changed - someone draws on the bottom layer - then those changes would be added to your class without any hassle.

11: Next, we simply want to make the Tutorial constructor function within the class return data with a type of void. So change the line that says:
      
Code: [Select]
public function Tutorial() to say
Code: [Select]
public function Tutorial():void
      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:All functions need to return something. When you return void you simply returning nothing.  Keep this in mind when you start writing your own functions.

      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:This function is called a constructor. The constructor is used to setup initial behavior for a class.  Every time a class is initially called into action, the constructor fires off once. The constructor should be the first function in a  class, and shares  the name of class.  It can be used to declare variables and even call other functions or classes.

12: Since we set the Tutorial Class to ALWAYS COMPILE, the first class your program will fire off is the Tutorial class.   It's going to automatically call the Tutorial function within it, since that is the constructor of the class.

      Now we are going make use of the fact that we extended FlxGame with the Tutorial class.  To do that we are going to need to call super().  What super() does, without and other function specified, is call the constructor of the class you are extending.

      Because the Tutorial Class is an extension of FlxGame, we're going to use FlxGame's FlxGame function, it's constructor, to initialize the game.

      We do this by using "super" within the Tutorial function.

      So, underneath where it says:
Code: [Select]
public function Tutorial():void
      {
     Add this line of code:
      
Code: [Select]
super(320,420,MenuState,2,0xff000000,true,0xffffffff);      As you type this, FlashDevelop should pop up a tooltip to help you see what each parameter is.
      You can also look up the FlxGame Class in the Flixel documentation, and see something like this:
      
Code: [Select]
function FlxGame (GameSizeX : uint, GameSizeY : uint, InitialState : Class, Zoom : uint, BGColor : Number, ShowFlixelLogo : Boolean, FlixelColor : Number, FlixelSound : Class, Frame : Class, ScreenOffsetX : uint, ScreenOffsetY : uint)
      So, the first parameter we send over is "GameSizeX", or the width of the game in pixels. We defined it as 320. Next is "GameSizeY", or the height of the game in pixels, which we set to 240.

      "InitialState" is going to be the State class we want to start our game with - in our case it will be "MenuState" - we'll need to create this later. "Zoom" we've set to 2, which is going to make everything we put in our game twice as big. "BGColor" is the background color of our game. We set it to black. Colors in Flixel are usually expressed in this way: "0xAARRGGBB" where "AA" is the "alpha transparency", "RR" is red, "GG" is green, and "BB" is blue. Next, "ShowFlixelLogo" is set to "true", and the "FlixelColor" is set to white. When the game starts, we want to see the Flixel logo as white on black. The other parameters are optional, so we're not going to pass them.

13: On the next line, we'll add the "help" command to tell our players what buttons do what:
Code: [Select]
help("Jump", "Shoot", "Nothing");      So X = Jump, C = Shoot, and the mouse does nothing for right now.

      The help information is all built into FlxGame.as that we are extending.  We will not be covering modifying Flixel classes in this doc.  Feel free to experiment with them on your own later.

14: We're almost done with the initial setup. We need to setup our "MenuState" Class next. Add a new folder to the "com" folder, and name it "Tutorial". Add a new Class to this folder, and name is "MenuState.as", and then, in your Tutorial.as file - right underneath your "import", add a new line and enter:
Code: [Select]
import com.Tutorial.MenuState;
Save everything, and we're done with this class file!

      If you test your project (F5), it should run correctly, and show you the Flixel logo, but then give you an error because we haven't set up the MenuState file all the way yet.

      If you get any other errors before that, check through the steps above and make sure you didn't miss anything. Once you've got it working, move on to the next section!

As of right now, your complete Tutorial.as file should look like this:
Code: [Select]
package  
{
    import com.adamatomic.flixel.*;
    import com.Tutorial.MenuState;
    
    [SWF(width="640", height="480", backgroundColor="#000000")]
    [Frame(factoryClass="Preloader")]
    public class Tutorial extends FlxGame
    {
        
        public function Tutorial():void
        {
            super(320,240,MenuState,2,0xff000000,true,0xffffffff);
            help("Jump", "Shoot", "Nothing");
        }
        
    }
    
}
Title: Re: Basic Game Tutorial
Post by: HI5 Studios on Tue, Aug 4, 2009
I get this error C:\Documents and Settings\Kojo Amanquah\Desktop\game\Tutorial\src\Tutorial.as(: col: 10 Error: Syntax error: expecting rightbrace before extends. What did I do wrong?

What did I do wrong?
Title: Re: Basic Game Tutorial
Post by: hima on Tue, Aug 4, 2009
Thank you very much for this tutorial. I cannot wait for the next one :)
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Tue, Aug 4, 2009
I get this error C:\Documents and Settings\Kojo Amanquah\Desktop\game\Tutorial\src\Tutorial.as(8): col: 10 Error: Syntax error: expecting rightbrace before extends. What did I do wrong?
Sorry, I'm not sure. Could you post your code?
Title: Re: Basic Game Tutorial
Post by: nitram_cero (2bam) on Tue, Aug 4, 2009
Widely explained tutorial, the detail and non-difficult-language is amazing (specially the tips)

It is definetly a great tool to learn why the examples (Mode, Edgecrement) do what they do!
Not just a "Flixel" tutorial but an AS3 tutorial also.

Congratulations!
Title: Re: Basic Game Tutorial
Post by: george on Tue, Aug 4, 2009
agreed, good job!
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Tue, Aug 4, 2009
Thank you very much for this tutorial. I cannot wait for the next one :)
Widely explained tutorial, the detail and non-difficult-language is amazing (specially the tips)

It is definetly a great tool to learn why the examples (Mode, Edgecrement) do what they do!
Not just a "Flixel" tutorial but an AS3 tutorial also.

Congratulations!
agreed, good job!
Thanks, thanks and thanks!
The next installment *should* be ready sometime today - I have to play with it a bit, and proofread a few times... is there any particular item you would like us to cover?
Title: Re: Basic Game Tutorial
Post by: HI5 Studios on Tue, Aug 4, 2009
C:\Documents and Settings\Kojo Amanquah\Desktop\game\Tutorial\src\Tutorial.as(8): col: 10 Error: Syntax error: expecting identifier before extends.

What is an identifier?
Title: Re: Basic Game Tutorial
Post by: hima on Tue, Aug 4, 2009
@HI5Studios
Please copy and paste your code to http://pastebin.com so that it'll be easier for us to help you fix the problem :)

@SeiferTim
I think the idea behind how the flixel framework works would be nice so we can see the big picture and where we're going. I personally would like to know more about State and how each gamestep in flixel work.  :D
Title: Re: Basic Game Tutorial
Post by: george on Wed, Aug 5, 2009
yes, I would like something of a big picture as well. To be honest I don't have a really good idea of what the main game update loop looks like, whether it is event-based or polling or what, or how to integrate things I might want to do like timed events, periodic functions, etcetera.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Thu, Aug 6, 2009
yes, I would like something of a big picture as well. To be honest I don't have a really good idea of what the main game update loop looks like, whether it is event-based or polling or what, or how to integrate things I might want to do like timed events, periodic functions, etcetera.
I don't know if we'll be able to help too much with that. We're aiming for a fairly simple, easy to follow tutorial to help get people in the door. Essentially, the compleat tutorial is going to show how to create the MenuState, the PlayState, and how to create the player sprite, draw a level on the screen, create enemies, power-ups, track health/score, and player death/win. If anyone wants to contribute an explanation or an aside beyond what we come up with, feel free to PM it to me, and I can add it to the tutorial.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Thu, Aug 6, 2009
OKay, here's the next part of the tutorial!

III: Creating the Menu:

Now that we have your project starting properly, it's time to move on to making your first State - specifically a FlxState for your main Menu.

Before we jump into creating a state we should first explain what a state is used for.  States are Classes that are used primarily as central control points for the different portions of your game.  They handle the creation of new drawing surfaces, adding in game objects, changing scores, displaying menus, etc.

In this tutorial we are going to create two basic states.  The MenuState, and the PlayState.  The MenuState we will use to create a simple menu for the game, and the PlayState will house all of the logic for object creation, score keeping, and collision checking.

      
(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:You can kind of think of States as separate race-tracks that are adjacent to each other. When the player starts the game, they will start on the MenuState track, and they will drive around and around in circles on that track. When we switch to the PlayState, they will teleport over to the PlayState track, which is larger and has more checkpoints and obsticles than the MenuState. When the player dies or quits the game, they get teleported back to the MenuState track, until they want to start playing again.  You can have a large number of different states for your game, if you want - you can have a menu state, a load screen state, the game state, an inventory state, etc.

    If any of this confuses you, you will feel better once we dig in and start going over the states.  If at the end you are still confused, consume the pill that comes with this tutorial, and everything will feel much better.

The Menu State

1:  Since you already created a new class named MenuState earlier, FlashDevelop has created the basic framework for you. Open up this file now, and you'll see the following:
      
Code: [Select]
package  
      {
        
          public class MenuState
          {
              
              public function MenuState()
              {
                  
              }
              
          }
          
      }
2:  Like all AS3 classes you will want to define your package and import any classes you will need, so change the first part to look like this:
      
Code: [Select]
package com.Tutorial
      {
          import com.adamatomic.flixel.*;

3:  Next, we want this class to extend FlxState. Remember extending a class that you imported allows your to make a new Class based off of the one you are extending. Change
Code: [Select]
public class MenuState to say:
      
Code: [Select]
public class MenuState extends FlxState
4:  Next, we need to define our Constructor. Now, in this case, because we are using this State as a Menu, we want to 'take over' the Constructor function for FlxState entirely.  To do this, replace
Code: [Select]
public function MenuState()
      {
with this:
      
Code: [Select]
override public function MenuState():void
              {

5:  Next, we're going to display the name of our game on the Menu, with something that tells the player how to start the game. When you have a better grasp of using Sprites, sounds, and special effects, you can put a logo or something else on the menu screen. For now, we'll just use the FlxText Class. Within the MenuState Constructor, add this code:
      
Code: [Select]
this.add(new FlxText(0,(FlxG.width/2) - 80, FlxG.width, 80, "Flixel Tutorial Game", 0xffffffff, null, 16,"center")) as FlxText;
      Lets take a look at what this is doing.
      First, "this.add()" is essentially saying "take something and attach it to 'this'". "This" is sort of a shortcut to refer to the current object in AS3. In our case, "This" refers to the instance of MenuState that is currently open and running through this Constructor.

      Now, we're also passing it an object. The "new FlxText()" is going to create a new FlxText object. We're going to pass it some parameters, and then our new FlxText object is going to be attached to our MenuState.
      By looking up the FlxText Class and it's constructor in the Documentation (http://www.ivansafrin.com/nanodoc/flixel/), we can see what parameters it's expecting:

      
Code: [Select]
function FlxText (X : Number, Y : Number, Width : uint, Height : uint, Text : String, Color : uint, Font : String, Size : uint, Justification : String, Angle : Number)
      We're passing: 0,(FlxG.width/2) - 80, FlxG.width, 80, "Flixel Tutorial Game", 0xffffffff, null, 16,"center", which should place our text, "Flixel Tutorial Game", in white, at the center of the screen (roughly).

6:  Lets also tell the player how to start the game. In a new line right under our other text, add:

      
Code: [Select]
this.add(new FlxText(0, FlxG.height  -24, FlxG.width, 8, "PRESS X TO START", 0xffffffff, null, 8, "center"));
      This should add the text "PRESS X TO START" near the bottom of the screen in white, and in a smaller point size. That's all we want to do in MenuState's Constructor.

7:  We now need to tell the game what to do each time it 'updates'. Most programs have some sort of system loop that is always running while the program is running - usually a large number of iterations per second. This loop, in its simplest form, goes something like this:
      
Code: [Select]
Start:
      wait for something to happen
      Go back to start

      In our case, Flixel's game loop is mostly going to be handling a lot of stuff for us, so we won't have to worry about it, but we do want to be able to do things while this loop is running, so we use the "update" function.

      Essentially, Flixel is going to call "update" every loop iteration, and we can choose to have things happen within the update function if we want. For the MenuState, we're simply going to wait for the Player to press X. Add this code after the Constructor, and before the last "}" in the class:
      
Code: [Select]
override public function update():void
              {
                  if (FlxG.kA)
                  {
                      FlxG.flash(0xffffffff, 0.75);
                      FlxG.fade(0xff000000, 1, onFade);
                  }
                  
                  super.update();
              }

      We're adding a whole function at once, but don't worry, it's pretty simple.

      First, we're going to "override" the "update" function that's in FlxSprite - this means that instead of FlxSprite's update being called, we're saying "use MenuSprite's update instead".

      Next, we ask if FlxG.kA is True or not. FlxG is Class in Flixel that handles a lot of general pieces all at once. kA is a variable that tracks wether or not the "A" Key is pressed or not (in Flixel, the "A" key is "X" on the keyboard, and the "B" key is "C"). Whenever the player has pressed the "A" key, FlxG.kA is going to be True. When the player lets go of the key, kA will be False.

      So, we're asking "is FlxG.kA True?" if it is, ie, the player has pressed the letter X on their keyboard, we're going to perform the next section of code.

      Regardless of if kA is true or not, we're going to call the "super.update()" function, which basically says: "now call the "update" function of whatever class I'm extended from".

      So, if X is pressed, and kA is true, then we're going to do two things.
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)First, we're going to call the FlxG "flash" function, which is going to flash the color white on the screen, then we're going to fade to black, via the "fade" function.(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)When the fade is complete (which should take 1 second), we're going to call the "onFade" function, which we'll write next.

8:  Underneath the constructor, we add a new function:
      
Code: [Select]
private function onFade():void
      {
      FlxG.switchState(PlayState);
      }

      This function will be called after the fade command is finished. All it will do is switch the current state from MenuState to PlayState.

9:  We can go ahead and create the PlayState file - add a new Class file to your com/tutorial folder, and name it PlayState.as.

So, lets review: when the player starts the game, its going to initialize itself and then enter the MenuState:
(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)When the MenuState loads, its going to put the text on the screen and then wait for the player to press the A button (X on the keyboard).(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)Once the player presses the button, it will Flash white, then fade to black.(http://timsworld.nfshost.com/images/tut_pics/bullet_black.png)As soon as it finishes fading, it's going to switch the game's state from MenuState to PlayState - which will be where all our game logic is.

            Make sense?

If you try out your game now, you'll be able to see the menu come up, and flash/fade when you press X. After that will be an error because we haven't finished with the PlayState yet... we'll get to that in the next section.

So your MenuState.as file should look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    
    public class MenuState extends FlxState
    {
        
        override public function MenuState():void
        {
            this.add(new FlxText(0, (FlxG.width / 2) - 80, FlxG.width, 80, "Flixel Tutorial Game", 0xffffffff, null, 16, "center")) as FlxText;
            this.add(new FlxText(0, FlxG.height  -24, FlxG.width, 8, "PRESS X TO START", 0xffffffff, null, 8, "center"));
        }
        
        override public function update():void
        {
            if (FlxG.kA)
            {
                FlxG.flash(0xffffffff, 0.75);
                FlxG.fade(0xff000000, 1, onFade);
            }
            
            super.update();
        }
        private function onFade():void
        {
            FlxG.switchState(PlayState);
        }
    }
  

Stay tuned for the next part where we discuss the PlayState, and creating your Sprites!
Title: Re: Basic Game Tutorial
Post by: Aractes on Thu, Aug 6, 2009
This is a really helpful tutorial and easy to follow. but i have two questions. in part two, can you clarify the preloader part, i was having trouble making it work. and the second, in part three, you import two different files to use,  one was adobe.utils.custumactions, what was the point or use of importing that?
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Thu, Aug 6, 2009
This is a really helpful tutorial and easy to follow. but i have two questions. in part two, can you clarify the preloader part, i was having trouble making it work. and the second, in part three, you import two different files to use,  one was adobe.utils.custumactions, what was the point or use of importing that?

1:
You shouldn't need to do anything more than I described:
Quote
In the next line, we'll add the preloader:
     
Code: [Select]
[Frame(factoryClass="Preloader")]
     You also need to open the Preloader.as file and change the className to be the same as your Project's class, in this case:
     
Code: [Select]
className = "Tutorial";
It works perfectly fine for me. You just need to make sure the that Preloader.as file that comes with Flixel is in the same directory as your Tutorial.as, and make sure you change the className in the file.

2:
Actually, you don't need that include, I'll fix it. Thanks!
Title: Re: Basic Game Tutorial
Post by: Aractes on Fri, Aug 7, 2009
alright
this confused me A LOT.
when i was doing part three and tried to compile the game, the text wouldnt appear.
then when i copied and pasted the final code from the forum, it worked all of a sudden. i switched back to what i wrote, didnt work. so i checked for 10-15 minutes everysingle part to the codes in the forum, everything was the same, but it still didnt work. any ideas?

heres what i have for the Tutorial.as (It may be different now cause i was fiddling around with these trying to figure out what was wrong)
Code: [Select]
package
{

import com.adamatomic.flixel.*;
import com.Tutorial.MenuState;

[SWF(width = "640", height = "480", backgroundColor = "#000000")]
public class Tutorial extends FlxGame
{
public function Tutorial(): void
{
super(320, 240, MenuState, 2, 0xff000000, true, 0xffffffff);
help("Jump", "Shoot", "Nothing");
}
}
}

and the code for MenuState.as
Code: [Select]
  package com.Tutorial
{

import com.adamatomic.flixel.*;

public class MenuState extends FlxState
{
override public function MenuState(): void
{
this.add(new FlxText(0, (FlxG.width / 2) - 80, FlxG.width, 80, "Flixel Tutorial Game", 0xffffffff, null, 16, "centre")) as FlxText;
this.add(new FlxText(0, FlxG.height -24, FlxG.width, 8, "PRESS X TO START", 0xffffffff, null, 8, "centre"));
}

override public function update(): void
{
if (FlxG.kA)
{
FlxG.flash(0xffffffff, 0.75);
FlxG.fade(0xff000000, 1, onFade);
}
super.update();
}
private function onFade(): void
{
FlxG.switchState(PlayState);
}
}
}

and a third thing, i still cant get the preloader working. is it sapposed to be in a specific file of some sort or what?

i appreciate any help for my questions.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Fri, Aug 7, 2009
alright
this confused me A LOT.
when i was doing part three and tried to compile the game, the text wouldnt appear.
then when i copied and pasted the final code from the forum, it worked all of a sudden. i switched back to what i wrote, didnt work. so i checked for 10-15 minutes everysingle part to the codes in the forum, everything was the same, but it still didnt work. any ideas?

heres what i have for the Tutorial.as (It may be different now cause i was fiddling around with these trying to figure out what was wrong)
Code: [Select]
package
{

import com.adamatomic.flixel.*;
import com.Tutorial.MenuState;

[SWF(width = "640", height = "480", backgroundColor = "#000000")]
public class Tutorial extends FlxGame
{
public function Tutorial(): void
{
super(320, 240, MenuState, 2, 0xff000000, true, 0xffffffff);
help("Jump", "Shoot", "Nothing");
}
}
}

and the code for MenuState.as
Code: [Select]
  package com.Tutorial
{

import com.adamatomic.flixel.*;

public class MenuState extends FlxState
{
override public function MenuState(): void
{
this.add(new FlxText(0, (FlxG.width / 2) - 80, FlxG.width, 80, "Flixel Tutorial Game", 0xffffffff, null, 16, "centre")) as FlxText;
this.add(new FlxText(0, FlxG.height -24, FlxG.width, 8, "PRESS X TO START", 0xffffffff, null, 8, "centre"));
}

override public function update(): void
{
if (FlxG.kA)
{
FlxG.flash(0xffffffff, 0.75);
FlxG.fade(0xff000000, 1, onFade);
}
super.update();
}
private function onFade(): void
{
FlxG.switchState(PlayState);
}
}
}

and a third thing, i still cant get the preloader working. is it sapposed to be in a specific file of some sort or what?

i appreciate any help for my questions.
Ah.... I think I see the problem.

I take it you're from outside the US? ;)

It would help if you pasted the error you were getting - when I run your code, I get:
Code: [Select]
[Fault] exception, information=ArgumentError: Error #2008: Parameter align must be one of the accepted values.Look in the documentation under FlxText - the FlxText constructor says:
Code: [Select]
Justification: String
Valid strings include "left", "center", and "right"
If you look at your code, you have "centre" instead of "center".


As far as your Preloader issue is concerened, I don't really know what could be happening... I have the Preloader.as file in the same directory as my Tutorial.as file, and the Preloader.as file just looks like this:
Code: [Select]
package { import com.adamatomic.flixel.data.FlxFactory; public class Preloader extends FlxFactory { public function Preloader():void {

className = "Tutorial";
super();

}}}
Then I link to it within Tutorial.as as described above, and it works. I didn't have to do anything special.
Title: Re: Basic Game Tutorial
Post by: Aractes on Fri, Aug 7, 2009
ill try it again
hopefully it works this time

Ok, i got it to work this time, and it was the center thing. but i still cant get the stupid preloader to work, its not like there are any errors that are reported. the game still run but it goes from the Flixel logo, striaght to the menu.
Title: Re: Basic Game Tutorial
Post by: hima on Fri, Aug 7, 2009
How big is your game? If you run from your HDD, could it be that it is so fast that you didn't get to see the preloader :O?
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Fri, Aug 7, 2009
Yeah, the preloader should run before the Flixel logo, and it's only going to show for as long as it takes to load the game into memory - small games are going to load very fast...
Title: Re: Basic Game Tutorial
Post by: Aractes on Fri, Aug 7, 2009
well i only have the parts like in tutorial.

and it appears that hima was right
its there but its too fast that you only see a glimpse
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Fri, Aug 7, 2009
well i only have the parts like in tutorial.

and it appears that hima was right
its there but its too fast that you only see a glimpse

I wouldn't say that it's 'too fast' ;) You certainly don't want a preloading screen to take 5, 10, 15+ seconds if the rest of your file would only take .01 seconds to load.
Title: Re: Basic Game Tutorial
Post by: ahref on Sat, Aug 8, 2009
Can i make a suggestion that this topic be split in two One for discussion and one for the actual tutorial :D
Title: Re: Basic Game Tutorial
Post by: Adam Atomic on Sat, Aug 8, 2009
Once it looks like its a pretty sound/solid tutorial for most new users I'm going to dedicate an actual page to it, instead of just the forum posts :)
Title: Re: Basic Game Tutorial
Post by: pian0 on Mon, Aug 10, 2009
Have you considered something like a Wiki for Flixel developers? I think that would be a handy resource for us to share information and improve tutorials like this.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 10, 2009
Have you considered something like a Wiki for Flixel developers? I think that would be a handy resource for us to share information and improve tutorials like this.
Wikis are fun. One of the things I've discovered while working on this tut is that nanodoc does not have a way to link to a specific 'page', since it's all in one page... a wiki would make it easy to link directly to the page for FlxG.follow, or whatever...
'Course, someone(s) would have to work on it and maintain it, which can be a pain...
Title: Re: Basic Game Tutorial
Post by: Adam Atomic on Mon, Aug 10, 2009
Yea a wiki might be kind of a cool thing, I've never set one up or administered one though, and initial setup with all the documentation would defintiely be a chore
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 10, 2009
Here's comes part IV! It's a big one... are you ready?

IV: Getting Ready for the PlayState

As you now know, the MenusState will call the PlayState Class when you press 'X', so we're going to need to build our PlayState Class. The Playstate Class is where all of the game objects are added, and to some degree, controlled. This State is going to load, hold, and control all of the assets we need for the game - sound, scores, sprites, blocks objects etc, as well as maintain their position and behaviors.

Before we create this wonderful Class file, we should create some content to add to it.

The first two pieces we will need to create to add to our PlayState are a Tilemap for the floors and walls, and a Player object to jump around on them.

The Player

For our Tutorial, and probably for most games made with Flixel, you're going to be dealing with "Sprites". Essentially, a sprite is simply an object that will be on the screen for the player to interact with in some way. The little guy that the player moves and jumps and collects stuff is the Player sprite. Enemies that the Player can collide with are also sprites. For the most part, Sprites behave independently of one another (except when colliding), but we have to define how each type of sprite will move, look, and interact with the game.

To create our Player Class, we want to first create the graphics for our Player. Open up your Image Editor, and create a new document that is 128 x 16 pixels. Our Player is not going to be a 128 pixel wide graphic on the screen - he's only really going to be 16 x 16, however, Flixel makes it very easy to create animations by splitting up images into equal-size squares. We're going to create 8 frames of our player's animation.

You can learn and practice making sprites, but its more of an art than a science. Here's the graphic Darthlupi created for this tutorial, feel free to use it or copy it:
(http://timsworld.nfshost.com/images/tut_pics/Player.png)

Lets break down this image so we can see what we actually have:
(http://timsworld.nfshost.com/images/tut_pics/ninja_pic.png)

When this graphic is going to be loaded into Flixel, it will be assigned a number for each 16x16 block, starting at 0 - which you can see above.


If you want to, you can make your own graphic for your player that has more or less frames, just make sure you have frames to use for all of the above animations.

If you look in your project's directory, under "data", you'll probably see a lot of files there. Those are all from Mode, the demo game that comes with Flixel. You can safely remove all of those files, since we'll be making all of our own files for this Tutorial.

Save your player's sprite graphic to this folder ("data") as "Player.png"

Creating the Player Class File

Now that we have our Player Graphic, we need to build an object to contain all of our Player's information. This will be the Player Class.

The Player Class is going to serve a couple of purposes. We're going to create a Class that contains within it all of the stuff that makes up the player: Health, animations, movement, etc. This will give us lots of control over how the player's sprite behaves and is controlled.

1:  Start by creating a new Class file in the com\Tutorial directory, name it "Player.as"

2:  Import Flixel's stuff:
Code: [Select]
import com.adamatomic.flixel.*;
3:  Tell this Class to extend the FlxSprite class:
Code: [Select]
extends FlxSprite
4:  We're only going to embed one file right now:

Code: [Select]
[Embed(source='../../data/Player.png')] private var ImgPlayer:Class;
5:  Next we need to define some variables. We want to set some constants to be used later on in the code:
Code: [Select]
private var _move_speed:int = 400;
private var _jump_power:int = 800;   
private var _max_health:int=10;
And we also want to set a counter which we will use to 'flash' the player for a few seconds after they get hurt:
Code: [Select]
private var _hurt_counter:Number = 0;
6:  Next, we need to setup the constructor for this class. When we create a new Player object we want to be able to pass the X and Y coordinates where the player should start. So, change
Code: [Select]
public function Player() to say
Code: [Select]
public function Player(X:Number,Y:Number):void
7:  On the first line inside the Constructor, we need to call the constructor of the FlxSprite class this class is extended from:

Code: [Select]
super(ImgPlayer, X, Y, true, true); If you look up the definition of FlxSprite in the documentation, you'll see that we're passing the image to use for this sprite, the x and y coordinates for this sprite, and we're setting "animated" and "reverse" to True.

8:  Next, we're going to initialize our player with a bunch of information. The FlxSprite class is already setup with a lot of variables that we can use for various things:
Code: [Select]
//Max speeds
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            //Set the player health
            health = 10;
            //Gravity
            acceleration.y = 420;           
            //Friction
            drag.x = 300;
            //bounding box tweaks
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;

Now, we're adding bunch of stuff at once. Basically, what we're saying is this: when we create a Player object in our game, we're going to send it the X, Y coordinates where we want the Player to start on the screen, and then we're going to se all of these variables to these specific values instantaneously and before the Player can do anything else.
We're setting the speed of the player first, then the starting health of the player. Next the strength of gravity on the player, and the amount of friction. The Bounding box tweaks sort of shrink the boundaries of the sprite to better fit the size of the graphic so that if it collides with a wall, it will look better.

9:  Next we want to setup our sprites animations. We're going to use a Flixel Function called "addAnimation" to do this.

Remember when we were creating our player's graphic, and we layout which frame would be used for what? Well, here's where we define them:
Code: [Select]
addAnimation("normal", [0, 1, 2, 3], 10);
addAnimation("jump", [2]);
addAnimation("attack", [4,5,6],10);
addAnimation("stopped", [0]);
addAnimation("hurt", [2,7],10);
addAnimation("dead", [7,7,7],5);

10:  Finally, we'll set "facing" to True, which says that the player is facing to the right:
Code: [Select]
facing = true; and that's it for the constructor.

11: Now we need to override the FlxSprite "update" function. After the constructor, we'll add a new function with this code:
Code: [Select]
override public function update():void
{
}

Inside this function, we're going to do a couple of things in order:



12: So, to check if the player is dead or not is simple:
Code: [Select]
if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }

FlxSprite has a "dead" variable which is true when the sprite's health is brought to 0. All this check is saying is:
If this sprite (the player) is marked as "dead", check to see if it's finished animating. If it is done animating, set this sprite's 'exists' property to false, which will remove it from the game. If the sprite is still animating, simply call the FlxSprite update function, and in either case, exit this function without going through the rest of the code.

13: Next, we know that if the player got past the first if statement that the player is still alive. When the player gets hurt by an enemy, we want a few things to happen: we want him to lose a health point, and then we want him to be invincible for a few seconds so that the player can get their bearing.

Our _hurt_counter variable is going to be used to find out if the player should be 'invincible' or not. Later on, when the player gets hurt, the _hurt_counter is going to be set to 1. Here we want to simply reduce the amount of time left on the counter:
Code: [Select]
if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }

(http://timsworld.nfshost.com/images/tut_pics/bullet_error.png)Important:Notice instead of simply subtracting from _hurt_counter we are using some funky FlxG.elapsed*3 thing.  Why is that you ask?  FlxG.elapsed is a variable that represents REAL time in seconds ( or fractions of a second ) since the last FULL GAME FRAME.  We do this to keep everything that needs to remain accurate for every computer, no matter how fast, since it is time based.

If we simply subtracted 0.1 from _hurt_counter that would happen much faster for a very fast computer than a slower one because the faster computer.  We multiple FlxG.elapsed * 3 because we want the timer to go down a bit faster.  It is still accurate since still using the amount of time since the last frame!

14: Getting keyboard input is a very important part of the Player object.  The Flixel Class FlxG handles this for you by either setting the following boolean variables to true or false for pressed or not pressed:


There is also a function that checks to see if a key has just been pressed this once:
FlxG.justPressed(FlxG.B)


(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:If you want to dig in deeper or change the keys you will need to look at the FlxGame Class, and look at it's onKeyUp and onKeyDown functions to see how they assignment of keys works in Flixel.

Now that you know which variables to check for to see if you are pressing a key, let's use it to move the player about.

15: First we check to see if the left arrow or right arrow is pressed and we set the direction the sprite is facing using facing.  Then we set the movement on the X axis using velocity.x.

The variable velocity.x represents how much to move along the x axis when the FlxSprite is updated.  Notice that we use _move_speed * FlxG.elapsed again when set the velocity.x.  Since we are again doing a calculation that adds over time, we are using the FlxG.elapsed variable make sure we are using the time since the last frame was drawn to keep it accurate for all computers.

Code: [Select]
if(FlxG.kLeft)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
            else if (FlxG.kRight)
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;               
            }

16: What is a platform game without jumping?

Code: [Select]
if(FlxG.justPressed(FlxG.A) && velocity.y == 0)
            {
                velocity.y = -_jump_power;
            }
     
   
17: Next, we want to handle Animations. In Flixel, all we need to do is tell the sprite to "play" the animation we named in the constructor depending on what's going on:
 
Code: [Select]
if (_hurt_counter > 0)
            {
                play("hurt");
            }
            else           
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                       play("normal");
                    }
                }
            }


18: Next we need to call update() on the FlxSprite Class that Player extends to update position and animation.
Code: [Select]
            super.update();
        }

19: The hurt function is a public function in the FlxSprite class that we want to change a little, so here we override it and add our changes.  We are simply adding the _hurt_counter = 1 in the event the player's hurt function called.  Also, we call the FlixelSprite's hurt function that we are overriding so we don't exlude anything that is in there.

Code: [Select]
        override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }       
}
       

That's it!  That is the player object, for now!

Your code should look like this:

Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
   
    public class Player extends FlxSprite
    {
        [Embed(source='../../data/Player.png')] private var ImgPlayer:Class;
       
        private var _move_speed:int = 400;
        private var _jump_power:int = 800;   
        private var _max_health:int = 10;
        private var _hurt_counter:Number = 0;
       
        public function Player(X:Number,Y:Number):void
        {
            super(ImgPlayer, X, Y, true, true);//Max speeds
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            //Set the player health
            health = 10;
            //Gravity
            acceleration.y = 420;           
            //Friction
            drag.x = 300;
            //bounding box tweaks
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;addAnimation("normal", [0, 1, 2, 3], 10);
            addAnimation("jump", [2]);
            addAnimation("attack", [4,5,6],10);
            addAnimation("stopped", [0]);
            addAnimation("hurt", [2,7],10);
            addAnimation("dead", [7, 7, 7], 5);
        }
   
        override public function update():void
        {

            if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }
            if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }

            if(FlxG.kLeft)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
            else if (FlxG.kRight)
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;               
            }
            if(FlxG.justPressed(FlxG.A) && velocity.y == 0)
            {
                velocity.y = -_jump_power;
            }
            if (_hurt_counter > 0)
            {
                play("hurt");
            }
            else           
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                       play("normal");
                    }
                }
            }

            super.update();
        }

        override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }       
    }
}
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 10, 2009
Tilemaps - Creating the Game World

Now we need something for the player to stand on. Make a new image document that's 48x16 Pixels. We're going to keep it simple and just make 2 different 16 x 16 block sprites:
(http://timsworld.nfshost.com/images/tut_pics/Tiles.png)

You might not realize it, but the first tile we want to keep 'blank'.
The first tile is *not* going to collide with sprites, but the rest are. In the future, you can make some neat effects by having more than 1 non-colliding tile.

Tiles work similarly to the Player's graphics: every square block will be assigned a number, starting at 0. You can make as many tiles as you want. Save this file as "Tiles.png" in the data directory.

Next, we're going to create our Tilemap. There's already a great tutorial on how to do this here (http://flixel.org/forums/index.php?topic=211.0). Using a tilemap is a simple way to create a map that looks the way you want. When you setup your map, we're going to want to make it twice as wide and tall as the game screen, so make sure you define the tile size as 16 x 16 and that you want your map to be 40 x 30 tiles in size.
(http://timsworld.nfshost.com/images/tut_pics/mappy_new_map.png)

Once you start your new map, Import your tiles.png file, and go wild! Just make sure that there are no gaps along the edge of the map - we don't want anywhere where the player can leave the map.
(http://timsworld.nfshost.com/images/tut_pics/mappy_screen.png)

Once you finish making your map, save it, and then you can choose "Custom->Export Flixel Tilemap". Name it "map.txt" and save it to your src\data directory. When it asks for a number to adjust the tiles by, leave it at "-1".

And there you go! You now have everything ready to start setting up the PlayState!

Setting up the PlayState

The PlayState is going to be our State that says: "The player is currently playing the game", ie, they're not on the MenuScreen, etc.

1:  You should already have the PlayState.as file in your com\Tutorial directory, open it up now.

2:  First, import the Flixel library right after the initial package declaration:
Code: [Select]
import com.adamatomic.flixel.*;
3:  Extend PlayState by adding
Code: [Select]
extends FlxState to the end of the public class declaration.

4:  Next, we need to Embed the assets we want to use in the state. In our case we want to embed 2 files: the Tiles.png and the Map.txt. In a new row after the Class declaration add:
Code: [Select]
[Embed(source = '../../data/Tiles.png')] private var ImgTiles:Class;
[Embed(source = '../../data/map.txt', mimeType = "application/octet-stream")] private var DataMap:Class;
What this does is actually include a file into the finished SWF file that's created, while assigning it a name so it can be accessed programattically. We can do this for images, sounds, and much more later on.

5:  We also need to define 2 of the objects that are going to live in our PlayState: the Player and the map. Flixel has a class called FlxTilemap which lets you pass it a map (like the one we created with Mappy), and some other parameters and then draws them on the screen. When we define a variable to hold the FlxTilemap, we can also do some other things (like test collision) with that Object. The Player object is going to be a Player class, which we created earlier. In a new row right beneath the Embeds, add:
Code: [Select]
private var _p:Player;
private var _map:FlxTilemap;

6: Finally, we're going to define 3 FlxLayers to hold display our items in. FlxLayers let you specify the order that you want to display your graphics in. Anything placed in the topmost layer will be shown abover everything in the other layers.
Code: [Select]
public static var lyrStage:FlxLayer;
        public static var lyrSprites:FlxLayer;
        public static var lyrHUD:FlxLayer;

7: Now, within the PlayState constuctor, the first thing we want to do is call the FlxState constructor by saying:
Code: [Select]
super();.

8: Next, we need to initialize some of our variables that we defined earlier:
First, the layers:
Code: [Select]
lyrStage = new FlxLayer;
            lyrSprites = new FlxLayer;
            lyrHUD = new FlxLayer;
This is telling the system to make a new FlxLayer object for each of our layers, and assign them to the variables we specified.

9: Next, we're going to set up the Player object:
Code: [Select]
_p = new Player(48, 448);[./code]
this is just saying that our _p variable is going to be a player object, and it's going to start at 28,29 on the map.

10: Now we're going to attach the player to the Sprites layer:
[code]lyrSprites.add(_p);

11: Next, we want the game's camera to follow the player. We do that by using the FlxG function: "follow". We will also want to set some options related to the camera to give the player a smoother experience:
Code: [Select]
FlxG.follow(_player,2.5);
            FlxG.followAdjust(0.5, 0.5);
            FlxG.followBounds(1,1,640-1,480-1);

12: Next, we're going to create our Tilemap object, and place it into lyrStage:
Code: [Select]
_map = new FlxTilemap(new DataMap, ImgTiles, 1);
            lyrStage.add(_map);

13: Finally, we attach our layers (in order) to the State:
Code: [Select]
this.add(lyrStage);
            this.add(lyrSprites);
            this.add(lyrHUD);

You may notice that we did not put anything into lyrHUD - we'll add score and health to that layer later on.

14: Now we need to override the update function of FlxState, so add this function to PlayState:
Code: [Select]
override public function update():void
        {
            super.update();
            _map.collide(_p);
        }
This should make some sense to you by now: we're calling the FlxState's update function first, and then we're telling Flixel to collide our Player object with our tilemap object.

Once this is done, you can test your project, and you should be able to run around the map you created!

At this point, your PlayState.as file should look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;

    public class PlayState extends FlxState
    {
        [Embed(source = '../../data/Tiles.png')] private var ImgTiles:Class;
        [Embed(source = '../../data/map.txt', mimeType = "application/octet-stream")] private var DataMap:Class;
       
        private var _p:Player;
        private var _map:FlxTilemap;
       
        public static var lyrStage:FlxLayer;
        public static var lyrSprites:FlxLayer;
        public static var lyrHUD:FlxLayer;
       
        public function PlayState():void
        {
            super();
           
            lyrStage = new FlxLayer;
            lyrSprites = new FlxLayer;
            lyrHUD = new FlxLayer;
           
            _p = new Player(48, 448);
            lyrSprites.add(_p);

            FlxG.follow(_p,2.5);
            FlxG.followAdjust(0.5, 0.5);
            FlxG.followBounds(1,1,640-1,480-1);
           
            _map = new FlxTilemap(new DataMap, ImgTiles, 1);
            lyrStage.add(_map);
           
            this.add(lyrStage);
            this.add(lyrSprites);
            this.add(lyrHUD);
        }
       
        override public function update():void
        {
            super.update();
            _map.collide(_p);
        }
    }   
}

Tune in for our next installment when we add Enemies and Collision![/code]
Title: Re: Basic Game Tutorial
Post by: george on Mon, Aug 10, 2009
great work guys!
Title: Re: Basic Game Tutorial
Post by: HI5 Studios on Mon, Aug 10, 2009
@hima pastebin did not help me fiigure out what an identifier is because my question has not been answered can someone in the on this post tell me what I did wrong? Error below

(8): col: 10 Error: Syntax error: expecting identifier before extends.
Title: Re: Basic Game Tutorial
Post by: hima on Mon, Aug 10, 2009
@hima pastebin did not help me fiigure out what an identifier is because my question has not been answered can someone in the on this post tell me what I did wrong? Error below

(8): col: 10 Error: Syntax error: expecting identifier before extends.
Pastebin is used to paste the code and then you post the link to the code so people can see your code and check where's the error at. You could also post the code here too.


Also, yayh for the new tutorial chapter! This one is quite a long one and more than I expect! Will be trying it this afternoon :)
Title: Re: Basic Game Tutorial
Post by: HI5 Studios on Tue, Aug 11, 2009
Okay I changed my code for tutorial.as and now I get this error

8: col: 35 Error: The definition of base class FlxGame was not found.
Title: Re: Basic Game Tutorial
Post by: darthlupi on Wed, Aug 12, 2009
We are getting pretty close to finishing the section on enemy objects, and once we have shooting for the player and the scores added we'll bundle the project in a zip file that you will be able to open and follow along with the tutorial.

That should help new people get a better handle on things as well as give you a function project start learning from.  For now, most if not all of the errors you come across can be explained through the wonder of Google.  You will definitely want to start researching these types of errors on your own, because they will always be popping up!

H15 Studios,

Make sure you are importing FlxGame properly!  It is important to understand that when you import something it then becomes available to add or extend.

Also, keep in mind that the com.whatever.whatever in it's simplest explanation is just the directory structure.

Code: [Select]
import com.adamatomic.flixel.FlxGame;
Think of this like open file com/adamatomic/flixel/FlxGame.  If the file isn't there prepare for more woes!

Make sure your package definitions and imports look like this:

Code: [Select]
package {
import com.adamatomic.flixel.FlxGame;
import com.Tutorial.MenuState;

Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Aug 12, 2009
What the what? Part V?!

V: Enemies

At this point you should start to see a game coming together.  What we are lacking is any sort of challenge or interaction, and a simple way to add challenge is with enemies.

In this section we will be setting up a very simple enemy using a new Class named Enemy that extends FlxSprite.  This Enemy class is going to be a near copy of the Player class that we already created so some portions of the class will not be covered in detail since we have already done so.

The first thing you are going to want to do is create an image file for new Enemy object with the same basic frame setup that we used for the Player.  We are doing this because for this tutorial we are going to be using the animation layout we used for the Player.
(http://timsworld.nfshost.com/images/tut_pics/Enemy.png)

Notice that this image is exactly the same as the player with little recoloring job applied.  Simple stuff right?

Alright, let get down to coding!

1:  Start by creating a new Class file in the com\Tutorial directory, name it "Enemy.as"
2:  Next we define the package structure, import all of Fixel, and set this new public class Enemy to extend Flxsprite.
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    public class Enemy extends FlxSprite
    {

3:  We will want to also embed the new image we created for this Enemy class
Code: [Select]
[Embed(source='../../data/Enemy.png')] private var ImgEnemy:Class;
4:  Next we declare our variables and define our constructor.
Code: [Select]
private var _move_speed:int = 400;
        private var _jump_power:int = 800;   
        private var _max_health:int = 10;
        private var _hurt_counter:Number = 0;
        private var _can_jump:Boolean = true;
        private var _last_jump:Number = 0;
        private var _p:FlxSprite;       
        public function Enemy(X:Number,Y:Number,ThePlayer:FlxSprite):void
        {
            super(ImgEnemy, X, Y, true, true);//Max speeds
             _p = ThePlayer;
            maxVelocity.x = 200;
            maxVelocity.y = 200;
       
  There are four differences here from how we setup out Player Class.
      We can now use it through out the class to do checks against the player!

5:  Now let's finish the Enemy's constructor.  Again, this section is exactly like the Player Class. We setup health, gravity, friction, bounding boxes for collisions, and the animations.
Code: [Select]
health = 1;
            acceleration.y = 420;           
            drag.x = 300;
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;
            addAnimation("normal", [0, 1, 2, 3], 10);
            addAnimation("jump", [2]);
            addAnimation("attack", [4,5,6],10);
            addAnimation("stopped", [0]);
            addAnimation("hurt", [2,7],10);
            addAnimation("dead", [7, 7, 7], 5);
        }

6:  Now again the first section of the update function is a carbon copy our Player Class.  First we override FlxSprite's update function, verify that this object is not "dead" and that it "exists", and setup the counter being hurt.
Code: [Select]
override public function update():void
        {
            if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }
            if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }

7:  In this next section we are going to add horizontal movement for the Enemy.  Notice that we are using the _p variable that holds the Player's id that we added to the PlayState.

What we are doing here is saying that if the Player's X coordinate is less than the Enemy's X coordinate then we need to move the Enemy to the left and change the facing for animations.
Code: [Select]
if(_p.x < x)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
If it is not, then we need to move the enemy to the right and change the facing for animations.
Code: [Select]
else
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;               
            }

8:  Jumping is pretty simple to pull off.
First, we don't want the Enemy jumping all the time - we're going to give him a little bit of a delay between jumps:
Code: [Select]
if (_last_jump > 0)
            {
                _last_jump -= FlxG.elapsed;
            }
Plus, we want to make sure the enemy is on the ground. If he's moving up or down, or if the _last_jump variable is greater than 0, we set his "_can_jump" variable to false:
Code: [Select]
if(velocity.y != 0 || _last_jump > 0)
    {
        _can_jump = false;
    }
Next, we check to see if the Enemy wants to jump.  We do this by checking to see if the Player is above the Enemy, and if the Enemy's _can_jump variable is set to true.
Code: [Select]
if(_p.y < y && _can_jump)
            {

Now we want to make that sucker jump!  We do this by setting the velocity on the up and down or Y axis to a negative number.  Notice we do not use FlxG.elapsed here because we are not adding to the jump speed over time.  Just one burst.
Code: [Select]
velocity.y = -_jump_power;Set the variable _can_jump to false to avoid the enemy trying to jump mid air, and set the _last_jump variable to 2 so that he can't jump again right away and close the if statement.
Code: [Select]
_can_jump = false;
                _last_jump = 2;
            }

9:  Set up the animations, call FlxSprite's update function, and close the update function just like you did for the Player Class.
Code: [Select]
if (_hurt_counter > 0)
            {
                play("hurt");
            }
            else           
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                       play("normal");
                    }
                }
            }
            super.update();
        }

10: Next we will want to override the hitFloor function that is part of the FlxCore Class, which FlxSprite extends.  The function is called when ever there is a collision against a block on the top side of the block.  We are overriding to set the _can_jump variable to true.  Now the Enemy can jump again!  We also want to return the value of FlxSprite's hitFloor so we call the super.hitFloor().
Code: [Select]
override public function hitFloor():Boolean
        {
            _can_jump = true;
            return super.hitFloor();
        }

11:  Finish up the Enemy Class by overriding the hurt function just like the Player Class does, and closing the Class and Package definitions.
Code: [Select]
override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }       
    }
}

This is what your final Enemy class will look like:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    public class Enemy extends FlxSprite
    {
        [Embed(source='../../data/Enemy.png')] private var ImgEnemy:Class;
        private var _p:Player;
        private var _move_speed:int = 400;
        private var _jump_power:int = 800;   
        private var _max_health:int = 10;
        private var _hurt_counter:Number = 0;
        private var _can_jump:Boolean = true;
        private var _last_jump:Number = 0;
        public function Enemy(X:Number,Y:Number,ThePlayer:Player):void
        {
            super(ImgEnemy, X, Y, true, true);//Max speeds
            _p = ThePlayer;
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            health = 1;
            acceleration.y = 420;
            drag.x = 300;
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;
            addAnimation("normal", [0, 1, 2, 3], 10);
            addAnimation("jump", [2]);
            addAnimation("attack", [4,5,6],10);
            addAnimation("stopped", [0]);
            addAnimation("hurt", [2,7],10);
            addAnimation("dead", [7, 7, 7], 5);
        }
   
        override public function update():void
        {
            if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }
            if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }
            if (_last_jump > 0)
            {
                _last_jump -= FlxG.elapsed;
            }
            if (velocity.y != 0 || _last_jump > 0)
            {
                _can_jump = false;
            }
            if(_p.x < x)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
            else
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;               
            }
            if(_p.y < y && _can_jump)
            {
                velocity.y = -_jump_power;
                _last_jump = 2;
                _can_jump = false;
            }
            if (_hurt_counter > 0)
            {
                play("hurt");
            }
            else           
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                       play("normal");
                    }
                }
            }
            super.update();
        }

        override public function hitFloor():Boolean
        {
            _can_jump = true;
            return super.hitFloor();
        }
       
        override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }       
    }
}
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Aug 12, 2009
Adding the Enemy to the Game

So now you have an enemy class, but we need to get it into the game for it to do any good (or evil, as the case may be...) so open up the PlayState.as file so we can add a few things.

1:  First, we want to define an Array to hold all of our enemies. Go up to where you defined your other variables (for _p and _map), and add a new line:
Code: [Select]
private var _e:FlxArray;Now, a FlxArray is a Class built into Flixel which is like a standard array++, it can hold just about anything, and works great. This FlxArray is going to be full of our enemies.

(http://timsworld.nfshost.com/images/tut_pics/lightbulb.png)Programming Tip:FlxArray extends Array, and it adds on a few nice touches.  One thing that does that is very helpful is that it will return the ID or Index of the object that you add to the array.  Check out how it works if you are interested by opening up the FlxArray.as Class file.

2:  Go down to the constructor, and somewhere before the end of the function (doesn't really matter where, just after you set the player object), add this code:
Code: [Select]
_e = new FlxArray;
            _e.add(lyrSprites.add(new Enemy(432, 320, _p)));

So, we're first telling Flixel that we want _e to be a new FlxArray, and then we're adding a new Enemy to the lyrSprites FlxLayer while simultaneously adding that Enemy to the _e FlxArray. 432 and 320 are the X and Y coordinates where we want to place the enemy (you may want to use different values based on your map - make sure he's not inside a wall), and _p is the player object.

3:  Now, in the update function we need to check 2 more things. First, we want to make sure all of the enemies inside our _e FlxArray (right now just one) will collide with the walls, and not fall through the floor. Then we want the enemies to damage the player if they run into each other. So add this underneath our player's collision:
Code: [Select]
FlxG.collideArray2(_map, _e);
    FlxG.overlapArray(_e, _p, EnemyHit);
So, FlxG.collideArray2 is a function that takes an object (in our case _map, our FlxTilemap), and a FlxArray (_e) and 'collides' them. Any object within _e will be unable to pass through the _map object.
FlxG.overlapArray is a similar function that takes a FlxArray (_e), and an object (_p, our Player), and if any object inside the FlxArray touches the object, it will call a function we define (EnemyHit, in our case).

4:  So, we need to add the EnemyHit function. Somewhere after the update function, and before the end of the class:
Code: [Select]
private function EnemyHit(E:Enemy, P:Player):void
        {
        }

5:  Now, before we actually handle our EnemyHit function, we need to go back to our Player.as and make a few changes. Open that file up. We're going to change _hurt_counter from Private to Public so that we can access it from outside the Player class, so change:
Code: [Select]
private var _hurt_counter:Number = 0 to
Code: [Select]
public var _hurt_counter:Number = 0.

6:  Next, we want to overide the FlxSprite's standart hurt function so that we can trigger our _hurt_counter. Somewhere before the end of the class, add:
Code: [Select]
override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }
All this is going to do, is when our player gets Hurt, it will set our _hurt_counter to 1 before calling the normal FlxSprite hurt function. That's it! Now you can go back to the PlayState.as file.

7: We're going to do a couple of things in our EnemyHit function. First, we're going to see if the player is currently hurt or not. If they are, we're not going to do anything - give the player a moment to recover:
Code: [Select]
if(P._hurt_counter==0)
{

8: If they are not hurt, then we're going to see which direction the enemy came from that hit them.
Code: [Select]
if (E.x > P.x)
                {
                    P.velocity.x = -100;
                    E.velocity.x = 100;
                }
                else
                {
                    P.velocity.x = 100;
                    E.velocity.x = -100;
                }
If the enemy came from the right, we're going to bounce the player left and the enemy right, and vice versa.

9: Finally, we're going to hurt the player by saying:
Code: [Select]
P.hurt(1); and then close your if statement and function:
Code: [Select]
}
    }

That should be it! Give your game a test and you should be able to go head-to-head against another Ninja (which you can't kill just yet...)

You might notice that after your player gets hit enough times, he'll disappear. This is because the FlxSprite.hit() function will actually reduce the player's health by the amount specified, and if it hits 0, we're removing the player from the game. Pretty neat, huh?
Next time we're going to talk about how to fight back against the enemy Ninja!

Your Player.as should now look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    public class Player extends FlxSprite
    {
        [Embed(source = "../../data/Player.png")] private var ImgPlayer:Class;
        private var _move_speed:int = 400;
        private var _jump_power:int = 800;   
        private var _max_health:int = 10;
        public var _hurt_counter:Number = 0;
        public function  Player(X:Number,Y:Number):void
        {
            super(ImgPlayer, X, Y, true, true);
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            health = 10;
            acceleration.y = 420;
            drag.x = 300;
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;
            addAnimation("normal", [0, 1, 2, 3], 10);
            addAnimation("jump", [2]);
            addAnimation("attack", [4,5,6],10);
            addAnimation("stopped", [0]);
            addAnimation("hurt", [2,7],10);
            addAnimation("dead", [7, 7, 7], 5);
            facing = true;
        }
        override public function update():void
        {
            if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }
            if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }
            if(FlxG.kLeft)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
            else if (FlxG.kRight)
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;               
            }
            if(FlxG.justPressed(FlxG.A) && velocity.y == 0)
            {
                velocity.y = -_jump_power;
            }
            if (_hurt_counter > 0)
            {
                play("hurt");
               
            }
            else           
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                        play("normal");
                    }
                }
            }
            super.update();
        }
       
        override public function hitFloor():Boolean
        {
            return super.hitFloor();
        }
       
        override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }     
    }
}

And your PlayState.as file should look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    public class PlayState extends FlxState
    {
        [Embed(source = '../../data/Tiles.png')] private var ImgTiles:Class;
        [Embed(source = '../../data/map.txt', mimeType = "application/octet-stream")] private var DataMap:Class;
       
        private var _p:Player;
        private var _map:FlxTilemap;
        private var _e:FlxArray;
        public static var lyrStage:FlxLayer;
        public static var lyrSprites:FlxLayer;
        public static var lyrHUD:FlxLayer;
       
        public function PlayState():void
        {
            super();
           
            lyrStage = new FlxLayer;
            lyrSprites = new FlxLayer;
            lyrHUD = new FlxLayer;
           
            _p = new Player(48, 448);
            lyrSprites.add(_p);

            FlxG.follow(_p,2.5);
            FlxG.followAdjust(0.5, 0.5);
            FlxG.followBounds(1,1,640-1,480-1);
           
            _map = new FlxTilemap(new DataMap, ImgTiles, 1);
            lyrStage.add(_map);
           
            this.add(lyrStage);
            this.add(lyrSprites);
            this.add(lyrHUD);
           
            _e = new FlxArray;
            _e.add(lyrSprites.add(new Enemy(432, 320, _p)));
        }
       
        override public function update():void
        {
            super.update();
            _map.collide(_p);
            FlxG.collideArray2(_map, _e);
            FlxG.overlapArray(_e, _p, EnemyHit);
        }
       
        private function EnemyHit(E:Enemy, P:Player):void
        {
            FlxG.log(P._hurt_counter.toString());
            if (P._hurt_counter <= 0)
            {
                if (E.x > P.x)
                {
                    P.velocity.x = -100;
                    E.velocity.x = 100;
                }
                else
                {
                    P.velocity.x = 100;
                    E.velocity.x = -100;
                }
                P.hurt(1);
            }
        }
       
    }   
}
Title: Re: Basic Game Tutorial
Post by: darthlupi on Fri, Aug 14, 2009
Tim just finished part 6 - madness!

VI: Fighting back!

    Now that you have the player and the enemy on the screen, you need to give the player a way to fight back! We're going to give him some Ninja Stars too throw.

1:  First, draw a simple sprite for your Ninja Star. This doesn't have to be complicated.
- this is really trans, just put black background to see better.

(http://darthlupi.com/images/NinjaStar.png)

Name this file "NinjaStar.png", and place it in your data directory.

2:  We're also going to create a "spark" graphic for when the Star hits something.

(http://darthlupi.com/images/Spark.png)

Link to above tiny sprite: http://darthlupi.com/images/Spark.png  << Right click save as

Name this file "Spark.png" and place it in the same directory.

3:  We're going to create a new Class for our stars. Name it "NinjaStar.as", then import Flixel and make it extend FlxSprite.

4:  Right before the constructor, you're going to Embed the NinjaStar and Spark graphics:
Code: [Select]
[Embed(source = "../../data/NinjaStar.png")] private var ImgStar:Class;
        [Embed(source = "../../data/Spark.png")] private var ImgSpark:Class;

5: We're also going to setup a variable to be a FlxEmitter to give a little special effect to our star.
Code: [Select]
private var _sparks:FlxEmitter;
6:  Change the constructor's heading to look like this:
Code: [Select]
function NinjaStar(X:Number, Y:Number, XVelocity:Number, YVelocity:Number ):void
7:  Then within the constructor, we're going to call super, and then setup a few different things:
Code: [Select]
super(ImgStar, X, Y, true, true);
            
            //Basic movement speeds
            maxVelocity.x = 200;  //How fast left and right it can travel
            maxVelocity.y = 200;  //How fast up and down it can travel
            angularVelocity = 100; //How many degrees the object rotates            
            //bounding box tweaks
            width = 5;  //Width of the bounding box
            height = 5;  //Height of the bounding box
            offset.x = 6;  //Where in the sprite the bounding box starts on the X axis
            offset.y = 6;  //Where in the sprite the bounding box starts on the Y axis
            addAnimation("normal", [0]);  //Create and name and animation "normal"
            _sparks = FlxG.state.add(new FlxEmitter(0,0,0,0,null,-0.1,-150,150,-200,0,-720,720,400,0,ImgSpark,10,true,PlayState.lyrSprites)) as FlxEmitter;  
            facing = true;
            //The object now is removed from the render and update functions.  It returns only when reset is called.
            //We do this so we can precreate several instances of this object to help speed things up a little
            exists = false;
Most of this should be familiar to you from our other FlxSprites. However, the FlxEmitter is a little new. This object is going to actually create a bunch of sprites at once when we call it - using the ImgSpark graphic - to look like a little explosion of sparks. There's a lot of neat effects you can do with FlxEmitters.

8: Next, we're going to override some of the FlxSprites functions so that whenever our Star hits a wall or something, it will call the "Kill" function, and basically kill itself.
Code: [Select]
override public function hitFloor():Boolean
        {
            kill();
            return super.hitFloor();
        }
        override public function hitWall():Boolean
        {
            kill();
            return super.hitWall();
        }        
        override public function hitCeiling():Boolean
        {
            kill();
            return super.hitCeiling();
        }

9: Next, our kill function. FlxSprite has a Kill function which instantly kills the sprite, regardless of any health they might have or whatever. We're going to override this function to let our Star die in glory (using our Spark FlxEmitter):
Code: [Select]
override public function kill():void
        {
            if(dead)
                return;            
            _sparks.x = x + 5;
            _sparks.y = y + 5;
            _sparks.reset();
            super.kill();
        }
What this says is:
    If this object is already dead, don't do anything - get out. Otherwise, place our FlxEmitter object at the location of this sprite (+5 in x and y), and then "reset" our Emitter - which tells it to explode all of it's particles right then. Then we call the actual kill function of FlxSprite which will remove this sprite.

10: Finally, in order to save resources, we're going to let the system 'reuse' dead Stars and place them back in the game, so we're going to create a 'reset' function:
Code: [Select]
public function reset(X:Number,Y:Number,XVelocity:Number,YVelocity:Number):void
        {
            x = X;
            y = Y;
            dead = false;
            exists = true;
            visible = true;
            velocity.x = XVelocity; //Set the left and right speed
            play("normal"); //Play the animation
        }
This will just 'undo' all the stuff that happens when you Kill a sprite so that the game can use this Star again.

That's it for this Class! Your NinjaStar.as file should look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    
    public class NinjaStar extends FlxSprite
    {
        [Embed(source = "../../data/NinjaStar.png")] private var ImgStar:Class;
        [Embed(source = "../../data/Spark.png")] private var ImgSpark:Class;
        
        private var _sparks:FlxEmitter;
        public function NinjaStar(X:Number, Y:Number, XVelocity:Number, YVelocity:Number ):void
        {
            super(ImgStar, X, Y, true, true);
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            angularVelocity = 100;
            width = 5;
            height = 5;
            offset.x = 6;
            offset.y = 6;
            addAnimation("normal", [0]);
            _sparks = FlxG.state.add(new FlxEmitter(0,0,0,0,null,-0.1,-150,150,-200,0,-720,720,400,0,ImgSpark,10,true,PlayState.lyrSprites)) as FlxEmitter;            
            facing = true;
            exists = false;
        }
        override public function hitFloor():Boolean
        {
            kill();
            return super.hitFloor();
        }
        override public function hitWall():Boolean
        {
            kill();
            return super.hitWall();
        }        
        override public function hitCeiling():Boolean
        {
            kill();
            return super.hitCeiling();
        }
        
        override public function kill():void
        {
            if(dead)
                return;            
            _sparks.x = x + 5;
            _sparks.y = y + 5;
            _sparks.reset();
            super.kill();
        }
        
        public function reset(X:Number,Y:Number,XVelocity:Number,YVelocity:Number):void
        {
            x = X;
            y = Y;
            dead = false;
            exists = true;
            visible = true;
            velocity.x = XVelocity;
            play("normal");
        }
        
    }
    
}
Title: Re: Basic Game Tutorial
Post by: darthlupi on Fri, Aug 14, 2009
1:  We now need to change the Player.as file to allow the player to actually throw these stars. Open this file now.

2:  We need to add 2 more variables to the top of the class. First, a FlxArray which will connect to the Array we will later setup in PlayState to hold all of the stars the player throws. Then we'll also need a counter to track when the player can throw another star - we want to create a pause.
Code: [Select]
private var _stars:FlxArray;
        private var _attack_counter:Number = 0;

3:  Next, we're going to need to pass the Array of stars to the Player object when it initializes. So, change the top of the constructor class to this:
Code: [Select]
private function  Player(X:Number,Y:Number,Stars:FlxArray):void
4: Somewhere within the constructor, after "super", we need to actually connect the Stars array we pass to the Stars array we created.
Code: [Select]
_stars = Stars;
5:  Next, in the update function, we want to see if our attack counter is > 0,and if so, subtract from it to make it closer to 0. The player will only be able to throw a Star if the counter is at 0. You can place this code right around the hurt counter code:
Code: [Select]
if (_attack_counter > 0)
            {
                _attack_counter -= FlxG.elapsed*3;
            }

6:  Now we want to respond to the player pressing the attack key. Still in update, and below the other keypress checks, add this:
Code: [Select]
if(FlxG.justPressed(FlxG.B) && _attack_counter <= 0)
            {
                _attack_counter = 1;
                play("attack");
                throwStar(facing);
            }  
So what this says is: If the player presses the B Key (c), and the attack counter is 0 or less, then set the counter to 1, play the "attack" animation, and then call a function called "throwStar", passing data based on which direction the player is facing. We'll write this function later.

7:  Next, we're going to make sure the attack animation plays while the attack counter is going down. This helps show the player that they can't attack again just yet. In the update function, right beneath the _hurt_counter check to play("hurt"), we're going to add this clause to the if statement:
Code: [Select]
else if (_attack_counter > 0)
            {
                play("attack");
            }

8:  For the throwStar function, we're going to do a couple of things. First, we need it to recieve the direction we want to first determine which way to throw the star. "facing" is a variable build into FlxSprite. If an object is 'facing' to the right, then it's true, otherwise, it's false. We pass facing to this function, and use it to determine which direction the star will move.
Then we're going to see if we have any stars that we can reuse: stars that are in our array of stars, but aren't currently on the screen. If we do, we're going to use one of those stars, or we'll make a new star if we have to.
Then we set the star's velocity, and add our star to the lyrSprites layer, so it starts moving in the direction specified.
Code: [Select]
private function throwStar( dir:Boolean ):void
        {
            var XVelocity:Number;
            if (dir) XVelocity = 200;
            else XVelocity = -200;
            for(var i:uint = 0; i < _stars.length; i++)
                if(!_stars[i].exists)
                {
                    _stars[i].reset(x, y + 2,XVelocity, 0);
                    return;
                }
            var star:NinjaStar = new NinjaStar(x, y + 2, XVelocity, 0);
            star.reset(x, y,XVelocity, 0)
            _stars.add(PlayState.lyrSprites.add(star) );    
        }

That's it for the Player.as file for now! It should looks like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;

    public class Player extends FlxSprite
    {
        [Embed(source = "../../data/Player.png")] private var ImgPlayer:Class;
        private var _move_speed:int = 400;
        private var _jump_power:int = 800;  
        public var _max_health:int = 10;
        public var _hurt_counter:Number = 0;
        private var _stars:FlxArray;
        private var _attack_counter:Number = 0;
        
        public function  Player(X:Number,Y:Number,Stars:FlxArray):void
        {
            super(ImgPlayer, X, Y, true, true);
            
            _stars = Stars;
            maxVelocity.x = 200;
            maxVelocity.y = 200;
            health = 10;
            acceleration.y = 420;            
            drag.x = 300;
            width = 8;
            height = 14;
            offset.x = 4;
            offset.y = 2;
            
            addAnimation("normal", [0, 1, 2, 3], 10);
            addAnimation("jump", [2]);
            addAnimation("attack", [4,5,6],10);
            addAnimation("stopped", [0]);
            addAnimation("hurt", [2,7],10);
            addAnimation("dead", [7, 7, 7], 5);
            facing = true;
        }
        override public function update():void
        {
            if(dead)
            {
                if(finished) exists = false;
                else
                    super.update();
                return;
            }
            if (_hurt_counter > 0)
            {
                _hurt_counter -= FlxG.elapsed*3;
            }
            if (_attack_counter > 0)
            {
                _attack_counter -= FlxG.elapsed*3;
            }
            if(FlxG.kLeft)
            {
                facing = false;
                velocity.x -= _move_speed * FlxG.elapsed;
            }
            else if (FlxG.kRight)
            {
                facing = true;
                velocity.x += _move_speed * FlxG.elapsed;                
            }
            if(FlxG.justPressed(FlxG.A) && velocity.y == 0)
            {
                velocity.y = -_jump_power;
            }

            if(FlxG.justPressed(FlxG.B) && _attack_counter <= 0)
            {
                _attack_counter = 1;
                play("attack");
                throwStar(facing);

            }            
            
            if (_hurt_counter > 0)
            {
                play("hurt");
                
            }
            else if (_attack_counter > 0)
            {
                play("attack");
            }
            else            
            {
                if (velocity.y != 0)
                {
                    play("jump");
                }
                else
                {
                    if (velocity.x == 0)
                    {
                        play("stopped");
                    }
                    else
                    {
                        play("normal");
                    }
                }
            }
            super.update();
            
        }
        
        override public function hitFloor():Boolean
        {
            return super.hitFloor();
        }
        
        override public function hurt(Damage:Number):void
        {
            _hurt_counter = 1;
            return super.hurt(Damage);
        }        
            
        private function throwStar( dir:Boolean ):void
        {
            var XVelocity:Number;
            if (dir) XVelocity = 200;
            else XVelocity = -200;
            for(var i:uint = 0; i < _stars.length; i++)
                if(!_stars[i].exists)
                {
                    _stars[i].reset(x, y + 2,XVelocity, 0);
                    return;
                }
            var star:NinjaStar = new NinjaStar(x, y + 2, XVelocity, 0);
            star.reset(x, y,XVelocity, 0)
            _stars.add(PlayState.lyrSprites.add(star) );    
        }
            
    }
    
}

1:  We need to make a few changes to PlayState.as, so open that file. Somewhere in your variable declarations we want to add a new FlxArray to hold all the stars our player is going to through.
Code: [Select]
private var _pStars:FlxArray;
2:  Somewhere within the constructor, before you initialize the Player object, we want to setup this FlxArray:
Code: [Select]
_pStars = new FlxArray;
            for (var n:int = 0; n < 40; n += 1)
            {
                _pStars.add(lyrSprites.add(new NinjaStar(0,0,0,0)));
            }
We're going to set _pStars to be a new (empty) FlxArray, and then we're going to add 40 new stars to this array so that the game won't have to create them on the fly. This is the array which we checked in the Player class to see if we can reuse a star or if we need to make a new one.

3:  Next, we need to make the stars collide with our Tilemap so that they don't fly through walls. Inside the update function, after super.update(), add:
Code: [Select]
FlxG.collideArray2(_map,_pStars);This works the same as the collision with the enemies.

4: Now, we also want our stars to damage the enemies when they get hit. So we need to add an overlapArray check.
Code: [Select]
FlxG.overlapArrays(_pStars, _e, StarHitsEnemy); This works the same way that collision between the player and the enemy works - we're just going to call a different function if any star overlaps any enemy.

5:  The StarHitsEnemy function is going to be pretty straightforward - if a star collides with an enemy we want to Kill that star, and hurt that enemy. Since our enemies (right now) only have 1 health each, this will kill them, too. In the future, we could add stronger enemies that take more hits, and/or stronger weapons that deal more damage.
Code: [Select]
private function StarHitsEnemy(colStar:FlxSprite, colEnemy:FlxSprite):void
        {
            colStar.kill();
            colEnemy.hurt(1);
        }

That's it! Test out your code and you should be able to press C to kill the enemy!
Your PlayState.as should look like this:
Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;

    public class PlayState extends FlxState
    {
        [Embed(source = '../../data/Tiles.png')] private var ImgTiles:Class;
        [Embed(source = '../../data/map.txt', mimeType = "application/octet-stream")] private var DataMap:Class;
        
        private var _p:Player;
        private var _map:FlxTilemap;
        private var _pStars:FlxArray;
        
        private var _e:FlxArray;
        
        public static var lyrStage:FlxLayer;
        public static var lyrSprites:FlxLayer;
        public static var lyrHUD:FlxLayer;
        
        public function PlayState():void
        {
            super();
            
            lyrStage = new FlxLayer;
            lyrSprites = new FlxLayer;
            lyrHUD = new FlxLayer;
            
            _pStars = new FlxArray;
            for (var n:int = 0; n < 40; n += 1)
            {
                _pStars.add(lyrSprites.add(new NinjaStar(0,0,0,0)));
            }
            
            _p = new Player(48, 448, _pStars);
            lyrSprites.add(_p);

            FlxG.follow(_p,2.5);
            FlxG.followAdjust(0.5, 0.5);
            FlxG.followBounds(1,1,640-1,480-1);
            
            _map = new FlxTilemap(new DataMap, ImgTiles, 1);
            lyrStage.add(_map);
            
            this.add(lyrStage);
            this.add(lyrSprites);
            this.add(lyrHUD);
            
            _e = new FlxArray;
            _e.add(lyrSprites.add(new Enemy(432, 320, _p)));
        }
        
        override public function update():void
        {
            super.update();
            _map.collide(_p);
            FlxG.collideArray2(_map, _e);
            FlxG.overlapArray(_e, _p, EnemyHit);
            FlxG.collideArray2(_map, _pStars);
            FlxG.overlapArrays(_pStars, _e, StarHitsEnemy);
        }
        
        private function EnemyHit(E:Enemy, P:Player):void
        {
            FlxG.log(P._hurt_counter.toString());
            if (P._hurt_counter <= 0)
            {
                if (E.x > P.x)
                {
                    P.velocity.x = -100;
                    E.velocity.x = 100;
                }
                else
                {
                    P.velocity.x = 100;
                    E.velocity.x = -100;
                }
                P.hurt(1);
            }
        }
        
        private function StarHitsEnemy(colStar:FlxSprite, colEnemy:FlxSprite):void
        {
            colStar.kill();
            colEnemy.hurt(1);
        }
        
    }    
}

At this point, you can try to add some more enemies to the game to see how it works. We're next going to cover how to give the enemies stars to throw as well.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 17, 2009
VII: More Stars!

    So now we want the enemies to start throwing their own stars at the player. For the most part this is going to work just like adding the Player's stars, except we want the computer to trigger them itself. Fortunately, we can re-use the NinjaStar class we already wrote, we just need to hold stars thrown by the enemies in a new array to track their collision separately.

1:  Let's start with PlayState.as. Go ahead and open this up now.

2:  Add a new variable declaration to define our enemy star array:
Code: [Select]
private var _eStars:FlxArray;
3:  Right beneath where we build our initial stars for the player we want to do the same for the enemy stars:
Code: [Select]
_eStars = new FlxArray;
            for (var en:int = 0; en < 40; en += 1)
            {
                _eStars.add(lyrSprites.add(new NinjaStar(0,0,0,0)));
            }

4:  In the place where you add your enemy, we need to now also pass it the _eStars array (we'll change the enemy class later to allow this).
Code: [Select]
_e.add(lyrSprites.add(new Enemy(432, 320, _p, _eStars)));
5:  Next, we need to make sure the enemy stars collide with the wall and the player. Inside the update function add:
Code: [Select]
FlxG.collideArray2(_map, _eStars);
            FlxG.overlapArray(_eStars, _p, StarHitsPlayer);

6:  Now we need to add the StarHitsPlayer function:
Code: [Select]
private function StarHitsPlayer(colStar:FlxSprite, P:Player):void
        {
            if (P._hurt_counter <= 0)
            {
                if (colStar.x > P.x)
                {
                    P.velocity.x = -100;
                }
                else
                {
                    P.velocity.x = 100;
                }
                P.hurt(1);
                colStar.kill();
            }
        }
This is basically going to work the same as when the player runs into an enemy: if the player's not still recovering from being hurt, then it's going to be knocked back depending on which way the star came from, and then take 1 damage while the star is destroyed.

That's it for this file!
Next we want to make the Enemy class be able to actually throw stars when they see the Player.

1:  Open up Enemy.as.

2:  First we want to add a variable to attach to the stars array in the PlayState, so add this declaration:
Code: [Select]
private var _eStars:FlxArray;
3:   We also want a counter to prevent the enemy from attacking all the time, so add this declaration:
Code: [Select]
private var _attack_counter:Number = 0;
4:  Next, we need to change the constructor to accept the star FlxArray, so change the top of the constructor to:
Code: [Select]
public function Enemy(X:Number,Y:Number,ThePlayer:Player, EnemyStars:FlxArray):void
5:  Within the constructor, right after "super()", add this:
Code: [Select]
_eStars = EnemyStars;
6:  Next we want to check the attack counter and if it's more than 0, reduce it closer to 0. In the update function, after we check if the enemy's dead or not, add:
Code: [Select]
if (_attack_counter > 0)
            {
                _attack_counter -= FlxG.elapsed*3;
            }

7:  Now we want to see if we should and can throw a star. Still in update, add this code:
Code: [Select]
if(_attack_counter <= 0 && _p.y > y - 1 && _p.y < y + 1)
            {
                _attack_counter = 2;
                play("attack");
                throwStar(facing);
            }   

8:  Now we need to change our logic to show animations around to look like this:
Code: [Select]
if (_hurt_counter > 0)
            {
                play("hurt");
            }
            else           
            {
                if (_attack_counter > 0)
                {
                    play("attack");
                }
                else
                {
                    if (velocity.y != 0)
                    {
                        play("jump");
                    }
                    else
                    {
                        if (velocity.x == 0)
                        {
                            play("stopped");
                        }
                        else
                        {
                           play("normal");
                        }
                    }
                }
            }

9:  Finally we need to add our ThrowStar function:
Code: [Select]
private function throwStar( dir:Boolean ):void
        {
            var XVelocity:Number;
            if (dir) XVelocity = 150;
            else XVelocity = -150;
            for(var i:uint = 0; i < _eStars.length; i++)
                if(!_eStars[i].exists)
                {
                    _eStars[i].reset(x, y + 2,XVelocity, 0);
                    return;
                }
            var star:NinjaStar = new NinjaStar(x, y + 2, XVelocity, 0);
            star.reset(x, y,XVelocity, 0)
            _eStars.add(PlayState.lyrSprites.add(star) );   
        }

That's all! If you test it out, you'll see that the enemy Ninja now throw stars back at you!
With a few small changes to your NinjaStar.as and your 2 ThrowStar functions, you can easily make it so that your player can differentiate between stars thrown by the player and stars thrown by the enemy. I'll leave that to you to figure out.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 17, 2009
VIII: Keeping Score
Now that we can kill enemy Ninja (and they can kill us), it might be a good idea to add a way to see how much health the player has left, as well as give them a score for killing enemies.
Flixel already has variables built in for score and health, all we need to do is access them and show them.

Score

1:  Open up the PlayState.as file.

2:  We're going to add a FlxText object which will show the player's score. So add this variable declaration:
Code: [Select]
private var _scoreDisplay:FlxText;
3:  Within the constructor somewhere, we want to define the scoreDisplay object and set it to never scroll.
Code: [Select]
scoreDisplay = new FlxText(FlxG.width - 50, 2, 48, 40, FlxG.score.toString(), 0xffffffff, null, 16, "right");
            _scoreDisplay.scrollFactor.x = _scoreDisplay.scrollFactor.y = 0;
            lyrHUD.add(_scoreDisplay);

4:  Now, within our update function, we want to change the score text, but ONLY if its been changed. So, at the very top of the update function (before super()) add this:
Code: [Select]
var _old_score:uint = FlxG.score;
5: Next, near the end of the update function (after ALL of the collision checks) add this:
Code: [Select]
if(_p.dead) FlxG.score = 0;
            if(_old_score != FlxG.score)
            {
                _scoreDisplay.setText(FlxG.score.toString());
            }
This just says: If the player's dead, make his score = 0. Then, if the score has been changed since last time, show the new score in the scoreDisplay object.

So, how do we actually change the score? Well, when an enemy dies, we want to give the player 10 points, so we're going to override the Kill function within the enemy class.

1:  Open up Enemy.as, and go all the way to the bottom to add this function:
Code: [Select]
override public function kill():void
        {
            if (dead)
                return;
            FlxG.score += 10;
            super.kill();
        }
All this says is that when this enemy is going to die, give the player 10 points (As long as it's not already dead).

That's it! Give it a try.

Health

So now we just want to let the player know how close they are to being dead. We're going to show a bunch of hearts at the top of the screen, and every time the player gets hurt, one of the hearts will be emptied.

1:  First, open up your drawing program and make a simple heart sprite - make one sprite for 'full' heart, and one for 'empty'.  Name this file "hearts.png".
(http://timsworld.nfshost.com/images/tut_pics/hearts.png)

2:  Next open up PlayState.as, and embed our heart image:
Code: [Select]
[Embed(source = '../../data/hearts.png')] private var ImgHearts:Class;
3:  We're going to add a FlxArray to hold our hearts.
Code: [Select]
private var _hearts:FlxArray;
4:  Next, go into the constructor and somewhere after we initialize the player, add this code to show all the hearts:
Code: [Select]
_hearts = new FlxArray();
            var tmpH:FlxSprite;
            for (var hCount:Number = 0; hCount < _p._max_health; hCount++)
            {
                tmpH = new FlxSprite(ImgHearts, 2 + (hCount * 10), 2, true, false);
                tmpH.scrollFactor.x = tmpH.scrollFactor.y = 0;
                tmpH.addAnimation("on", [0]);
                tmpH.addAnimation("off", [1]);
                tmpH.play("on");
                _hearts.add(lyrHUD.add(tmpH));
            }
So what this does is loop through based on the players maxHealth variable and adds a 'full' heart to the screen. In the spot that says: "(hCount * 10)", keep in mind that the graphic I posted above is set to have 2 8x8 hearts. If your image is a different size, you might want to change this value.

5:  Now we want to update our hearts if the player ever gets hurt. So go into our Update function and place this at the top (before super()):
Code: [Select]
var _old_health:uint = _p.health;
6: After super() and after all the collision checks, we want to see if the player's health changed - and if it did, we're going to redraw our hearts to show all the ones that are 'empty':
Code: [Select]
if(_p.health != _old_health)
            {
                for(var i:Number = 0; i < _p._max_health; i++)
                {
                    if (i >= _p.health)
                    {
                        _hearts[i].play("off");
                    }
                    else
                    {
                        _hearts[i].play("on");
                    }
                }
            }

The final thing you want to do is to open up Player.as and change "_maxHealth" from "private" to "public", and then that's it! Now you can watch your Ninja's health fall away with each hit!
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Aug 17, 2009
So... we're getting close to being done with out tutorial... our next plan is to show how to make enemy spawners... and then...? What else do you guys want to know?
Title: Re: Basic Game Tutorial
Post by: darthlupi on Tue, Aug 18, 2009
Alright!  We completed the next section, and at this point there should be enough detailed information for you to be able to create your own little game.

IX: Spawning Enemies
Sure, you can populate your levels with pre-placed enemies, but what if you want your enemies to constantly flood onto the screen? Well, we're going to add some enemy spawn-points to do just that!

1. First thing to do is to create a new class named Spawner that extends FlxSprite, and imports all of Flixel, as usual.

Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    
    public class Spawner extends FlxSprite
    {

2. Create and embed a new image to represent the Spawner on the screen.  In this example we are using an image that looks like a doorway to the BEYOND.

(http://darthlupi.com/images/Spawner.png)

Code: [Select]
       [Embed(source = '../../data/Spawner.png')] private var ImgSpawner:Class;

3. As you should know by now, we are going to need to declare some variabless.  This Class will need variables  to reference the Player, the Enemies, and EnemyStars that are all created in the PlayState.  Also , we are setting up another counter for Enemy creation.

Code: [Select]
       private var _p:Player;
        private var _e:FlxArray;    
        private var _eStars:FlxArray;        
        private var _create_counter:Number = 5;

4. Now we setup our Constructor allowing for the passing of the Player, Enemies FlxArray, and EnemyStars arrays from the PlayState to the private variables we declared above.

Code: [Select]
 
        public function Spawner(X:Number, Y:Number, Enemies:FlxArray,ThePlayer:Player,Stars:FlxArray):void
        {
            super(ImgSpawner, X, Y, true, true);
            _e = Enemies;
            _p = ThePlayer;
            _eStars = Stars;
        }


5. The update function should be VERY familiar to you by this point.  So  familiar, in fact, the following explanation may induce vomiting.  As you can see, we are overriding FlxSprite's update function, calling the parent Class FlxSprite's update function, and then we have a counter that runs every five seconds and calls the function spawn to create new baddies!
  
Code: [Select]
 
        override public function update():void
        {
            super.update();
            
            if (_create_counter > 0)
            {
                _create_counter -= FlxG.elapsed;
            }    
            if(_create_counter <= 0)
            {
                _create_counter = 5;
                spawn();
            }            
        }
 
 

6. The spawn function works very similiar to the ninja star creating functions you setup for the Player and Enemy Classes.  It loops through all indexes in the _e FlxArray which will contain all of the enemies, and then either resets them if they are there and exist is false, or it adds a new Enemy to that array!


Code: [Select]
   
        private function spawn():void
        {
            for (var i:uint = 0; i < _e.length; i++)
            {
                if(!_e[i].exists)
                {
                    _e[i].reset(x, y);
                    return;
                }
            }
            var enemy:Enemy = new Enemy(x, y , _p,_eStars);
            _e.add(PlayState.lyrSprites.add(enemy) );    
        }        
        
    }
    
}


If you are a super genius, then you will rememb that we never added a reset function the Enemy class!  How can we reset the Enemy in this Spawner Class if it doesn't exist?  Why, we create the reset function!

1. Add this to  your Enemy class after the last function. That last function should be the override of the kill function.

Code: [Select]
       public function reset(X:Number, Y:Number):void
        {
            x = X;
            y = Y;
            dead = false;
            exists = true;
            visible = true;
            play("normal");
        }


Finally, in order to create the Spawner object you will need to modify the PlayState class, so go ahead and open up your PlayState class for editing and do the following:

1.  We will first want to declare a new FlxArray to contain any Spawners you would like to create.

Code: [Select]
       private var _spawners:FlxArray;

2.  The last thing to modify in the PlayState class is adding a Spawner to a layer.  We need to pass in the FlxArray that contains the Enemies, the variable representing the Player, and finally the FlxArray that holds the EnemyStars.  To do this we have to add the following the very end of the PlayState constructor.

Code: [Select]
           _spawners = new FlxArray;
            _spawners.add(lyrStage.add(new Spawner(432, 320, _e,_p,_eStars)));  

Run it, and enjoy the many new enemies!

This is what your final Spawner class will look like:

Code: [Select]
package com.Tutorial
{
    import com.adamatomic.flixel.*;
    
    public class Spawner extends FlxSprite
    {
        [Embed(source = '../../data/Spawner.png')] private var ImgSpawner:Class;
        
        private var _p:Player;
        private var _e:FlxArray;    
        private var _eStars:FlxArray;        
        private var _create_counter:Number = 5;
        
        public function Spawner(X:Number, Y:Number, Enemies:FlxArray,ThePlayer:Player,Stars:FlxArray):void
        {
            super(ImgSpawner, X, Y, true, true);
            _e = Enemies;
            _p = ThePlayer;
            _eStars = Stars;
        }
        
        override public function update():void
        {
            super.update();
            
            if (_create_counter > 0)
            {
                _create_counter -= FlxG.elapsed;
            }    
            if(_create_counter <= 0)
            {
                _create_counter = 5;
                spawn();
            }              
            
        }
        
        private function spawn():void
        {
            for (var i:uint = 0; i < _e.length; i++)
            {
                if(!_e[i].exists)
                {
                    _e[i].reset(x, y);
                    return;
                }
            }
            var enemy:Enemy = new Enemy(x, y , _p,_eStars);
            _e.add(PlayState.lyrSprites.add(enemy) );    
        }        
        
    }
    
}
Title: Re: Basic Game Tutorial
Post by: mhughson on Wed, Aug 19, 2009
Sorry if this was covered already (didn't read the whole thread) but why not post a SWF file of the game after each stage of the tutorial?  I don't really want to do the whole tutorial, but I'm curious what this thing actually looks like!

Nice work either way though!
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Aug 19, 2009
We're planning on posting the final version into the first thread after we finish the last section.
Title: Re: Basic Game Tutorial
Post by: luc on Sun, Sep 6, 2009
Really nice tutorial.
I had no problem following it. I'm no coder at all, just trying from time to time.

Just found two typos :
on the Tilemaps chapter in the final example code there's an extra character

Code: [Select]
public function PlayState():void
        {
            super();
            
            lyrStage = new FlxLayer;
here ------>   &nbsp;   lyrSprites = new FlxLayer;

and chapter 8 on Keeping Scores. part 3 an underscore is missing
Code: [Select]
here -----> "_" scoreDisplay = new FlxText(FlxG.width - 50, 2, 48, 40, FlxG.score.toString(), 0xffffffff, null, 16, "right");
            _scoreDisplay.scrollFactor.x = _scoreDisplay.scrollFactor.y = 0;
            lyrHUD.add(_scoreDisplay);

> would be nice to learn about the process to create an element to trigger. Like a "finish line" in order to load a following stage or a specific tile/platform which is giving points by jumping on it.
> persistent Hi-Scores table (Kongregate api might help if I don't know about programming?)
> how to add sounds.
> How to force the scrolling of the stage (like in Canabalt).

even now it's pretty complete to build simple games.
I will dig the forums and try to figure things out on my own, at least I can mode the graphics :)
Thanks a lot for sharing such usefull ground base knowledge !
Title: Re: Basic Game Tutorial
Post by: Rolpege on Mon, Sep 7, 2009
How about adding support for multiple levels?
Title: Re: Basic Game Tutorial
Post by: ricardo_sdl on Mon, Sep 7, 2009
I couldn't use the mappy to create the tileset in the part IV of the tutorial. I've got an alert message saying:
libpng12.dll and zlib.dll missing for PNG.
BMP file is compressed.
BMP file is not correct clour depth.
I tried to use the png provided in the tutorial. Anyone can help me?
Thanks in advance.
Title: Re: Basic Game Tutorial
Post by: genocyber on Mon, Sep 7, 2009
Hola

http://www.dlldump.com/download-dll-files.php/dllfiles/L/libpng12.dll/download.html

http://www.dll-files.com/dllindex/dll-files.shtml?zlib

de aqui puedes bajarlos.
Title: Re: Basic Game Tutorial
Post by: ricardo_sdl on Tue, Sep 8, 2009
I'm using ubuntu here (8.10) and I'm running the mappy on wine. Has anyone created one file for the the tutorial that I can download? Thanks!
Title: Source code download
Post by: patrickespake on Fri, Sep 11, 2009
Hi,

Do you can available the source code for download?

Thanks.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Fri, Sep 11, 2009
No... the idea is that you could follow through the tutorial and build the source yourself. At the end of each section, the complete source for any modified files should be there that you could copy/paste if you want...
Title: Re: Basic Game Tutorial
Post by: jellybit on Thu, Sep 17, 2009
I sent a private message, but then I checked my outbox and it says there are no messages sent.  I'm thinking there could be an error with the forum so I'll post this here.

I'm following the Basic Game Tutorial (THANK YOU VERY MUCH FOR THIS, SEIFERTIM!), but I think I've run into a couple of errors that I've fixed.  I say "I think" because it's possible I missed an instruction.  The first issue is that in Part II, the tutorial has the user type this line:

Code: [Select]
super(320,420,MenuState,2,0xff000000,true,0xffffffff);
The 420 should be 240, I believe, because the code has it double itself into 480.  Also, it has the user type in this line:

Code: [Select]
public class Tutorial
when it should be this line:

Code: [Select]
public class Tutorial extends FlxGame
This error is a big deal because I couldn't even run the code without adding that "extends FlxState" to the end.  It should be noted that in the full code list at the end of the section, this part is correct (which is how I figured out my problem).  I see other people have had problems running, and this may be why.

Also, a very minor error in this part:

Quote
Now we are going make use of the fact that we extended FlxGame with the Tutorial class.  To do that we are going to need to call super().  What super() does, without and other function specified, is call the constructor of the class you are extending.

Did you mean "another" instead of "and other"?  Also, is it important at all that it's called "super"?  Was that just a random name or does it do other things?  Maybe those last questions are outside of the scope of the tutorial, but it helps me to remember the function.

Thanks again for the tutorial, SeiferTim!  I'll keep going with it.  I'm just starting on Part III.

EDITED: Corrected the "extends FlxGame" lines in my own correction post.
Title: Re: Basic Game Tutorial
Post by: Merve on Thu, Sep 17, 2009
You're right about the first comment (at least it's correct in the copy/paste code at the bottom of that segment) but wrong about the menustate code.
Here's the quote:
OKay, here's the next part of the tutorial!
3:  Next, we want this class to extend FlxState. Remember extending a class that you imported allows your to make a new Class based off of the one you are extending. Change
Code: [Select]
public class MenuState to say:
     
Code: [Select]
public class MenuState extends FlxState
Title: Re: Basic Game Tutorial
Post by: jellybit on Fri, Sep 18, 2009
Darnit!  Sorry and thanks.  That was my mistake.  What I MEANT to say was that it only says to type (again in Part II):

Code: [Select]
public class Tutorial
when it should be

Code: [Select]
public class Tutorial extends FlxGame
This gave me errors and refused to run until I saw in the full code that it extends FlxGame.
Title: Re: Basic Game Tutorial
Post by: new-at-flying on Sat, Sep 19, 2009
Hi, I don't understand step 10:

10: Next, we need to make this class (Tutorial) into a sort of copy of the FlxGame class. To do this, we make this class an 'extension' of the FlxGame class.

How do you do that? How do you make this extention?
Title: Re: Basic Game Tutorial
Post by: Gigaclon on Sat, Sep 19, 2009
change
Code: [Select]
public class Tutorialinto
Code: [Select]
public class Tutorial extends FlxGame
Title: Re: Basic Game Tutorial
Post by: new-at-flying on Sun, Sep 20, 2009
change
Code: [Select]
public class Tutorialinto
Code: [Select]
public class Tutorial extends FlxGame

I did do that, I get this:

Code: [Select]
\src\Tutorial.as(8): col: 35 Error: The definition of base class FlxGame was not found.
public class Tutorial extends FlxGame
^
Build halted with errors (fcsh).
Title: Re: Basic Game Tutorial
Post by: Merve on Sun, Sep 20, 2009
Did you import the flixel package? If you didn't then it doesn't know what a FlxGame is  ;)

Code: [Select]
import com.adamatomic.flixel.*;
Title: Re: Basic Game Tutorial
Post by: new-at-flying on Sun, Sep 20, 2009
Did you import the flixel package? If you didn't then it doesn't know what a FlxGame is  ;)

Code: [Select]
import com.adamatomic.flixel.*;

I did, this is my code...

Code: [Select]
package  
{
    import com.adamatomic.flixel.*;
    import com.Tutorial.MenuState;
    
    [SWF(width="640", height="480", backgroundColor="#000000")]
    [Frame(factoryClass="Preloader")]
    public class Tutorial extends FlxGame
    {
        
        public function Tutorial():void
        {
            super(320,240,MenuState,2,0xff000000,true,0xffffffff);
            help("Jump", "Shoot", "Nothing");
        }
        
    }
    
}

Can someone who did this tutorial already post me the source, to see where I'm going wrong..?
Title: Re: Basic Game Tutorial
Post by: Gigaclon on Sun, Sep 20, 2009
Where is that file. By default it looks for the packages by looking in the current directory. Try placing the file in the flixel directory or copying the com folder from the flixel directory into the same directory as the file
Title: Re: Basic Game Tutorial
Post by: new-at-flying on Mon, Sep 21, 2009
Ok i got it sorted.
Title: Re: Basic Game Tutorial
Post by: Mr.PepperDragon on Mon, Sep 21, 2009
Hi, this is a great tutorial : )
I'm a total beginner,so naturally I run into problems ; ) (like this one )
I'm having some trouble with the camera, I'm using your settings, the camera follows the player, but when the player stops, the camera scrolls so the middle of the gamescreen is in focus(leaving the character on one edge of the screen). Can somebody point me in any direction to look for what could have gone wrong? ( l'm using 1.25 of Flixel and my tilemap is 96 tiles and 32 high,and I'm using 16x16pixel tiles) I tried some things with the different follow things, but didnt have any success. Help would be greatly appreciated : )

Edit : Okay, I solved it after an hour by simply copying the source code ..but I'm still clueless what caused that ; )
Title: Re: Basic Game Tutorial
Post by: aeklad on Mon, Sep 21, 2009
I had this same problem it turned out to be an entry error you may have done the same thing.
In the line:

scoreDisplay = new FlxText(FlxG.width - 50, 2, 48, 40, FlxG.score.toString(), 0xffffffff, null, 16, "right");

I had entered FlxG.width " = 50 "instead of " - 50 " and it caused the same problem that you described.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Sep 21, 2009
Hi, this is a great tutorial : )
I'm a total beginner,so naturally I run into problems ; ) (like this one )
I'm having some trouble with the camera, I'm using your settings, the camera follows the player, but when the player stops, the camera scrolls so the middle of the gamescreen is in focus(leaving the character on one edge of the screen). Can somebody point me in any direction to look for what could have gone wrong? ( l'm using 1.25 of Flixel and my tilemap is 96 tiles and 32 high,and I'm using 16x16pixel tiles) I tried some things with the different follow things, but didnt have any success. Help would be greatly appreciated : )

Edit : Okay, I solved it after an hour by simply copying the source code ..but I'm still clueless what caused that ; )

Yeah, most of the time it's going to come down to a simple typo.
This is one of the reasons why I opted not to provide all the files in one down loadable package - by going through and entering it yourself, hopefully, you can not only get a feel for what each line of code is doing, but also see what errors have an effect on your project.
Title: Re: Basic Game Tutorial
Post by: udp11 on Tue, Sep 22, 2009
Should I create new AS3 project or a new AS3 project with a preloader?


Because If I create new AS3 project there is no Preloader.as file in it.

I fail at the start....
Title: Re: Basic Game Tutorial
Post by: Merve on Tue, Sep 22, 2009
A new AS3 project. Then put everything from the flixel zip directly into the src folder. Flixel provides the preloader.

Try and get mode (the built in game) working before attempting this tutorial though  ;)
Title: Re: Basic Game Tutorial
Post by: udp11 on Tue, Sep 22, 2009
Yeah :p I got that Mode game working before starting this tutorial, Ill guess Ill need to read tutorial one more time :)

And Are all files in same package, because when I was c/p finished code of each class, some had package com.Tutorial, and some didn't.


Odd, sometime it compiles fine, but there is nothing on screen, just white background, and sometimes, I get this error:

Code: [Select]
Error: Unable to resolve a class for include: com.Tutorial:Main.
Build halted with errors (fcsh).
Title: Re: Basic Game Tutorial
Post by: Merve on Tue, Sep 22, 2009
If nothing is appearing onscreen, not even the Flixel logo, then the preloader isn't working correctly. To get it working you need to have the main document class finished, the preloader.as has to point to it and you need at least a shell of a mainstate.

Also, with regards to were to put files, copy all the flixel stuff to the src folder, delete mode.as and add your own main document class (in this case Tutorial.as), after that all class files you create should go in com.Tutorial

edit: that should be
Code: [Select]
include com.Tutorial.Main;
//not
include com.Tutorial:Main;
Title: Re: Basic Game Tutorial
Post by: NemoStein on Tue, Sep 22, 2009
Whoa... Great Tutorial!!

I'm thinking about the question "What do you want to know" and found out that I wanna know how to put sound in it and change levels...

I think that I can dig through this forum behind some piece of information, but this tuto is so good that I want to see the way that you will lead us in this branch (sound and levels) too...

Thank you for the effort...
Title: Re: Basic Game Tutorial
Post by: Mr.PepperDragon on Wed, Sep 23, 2009
I hope nobody minds that I ask this in this thread(the question seems to be too simple for it's own thread), but what is the simplest way to just check if something has collided with  like a wall?(From within the Player.as)
What I understand is that a a collision will run hitWall() for example, but that brings the player to a stop.
(so I cannot do an if(hitWall()) because the this will run the hitWall in flxSprite that sets velocity to 0)
Thanks : )
Title: Re: Basic Game Tutorial
Post by: Titch on Wed, Sep 23, 2009
HitWall doesn't RUN the collision, it just detects it. If the sprite acctually collides or not depends on if HitWall returns a true or false. If you did something like this:

override public function hitWall ():boolean
{
//Your collision actions here.
return false;
}

The  the core Flixel engine wouldn't stop the sprite and you could set your own programmed reaction.
Title: Re: Basic Game Tutorial
Post by: Merve on Wed, Sep 23, 2009
Or you could use overlaps instead of collide

I'm not sure why you would want to check if something has collided with a wall from within the Player.as but you would have to pass the player a reference of the current state.
Title: Re: Basic Game Tutorial
Post by: Mr.PepperDragon on Wed, Sep 23, 2009
Thanks for the help, I guess I know what I have to look for now.
What I am trying to do is that when a player jumps to a wall, it grabs to it, and when you press jump again it jumps off from the wall, so I ( probably)  need to set some things when the player is colliding with something and set that back when the player is not.
Title: Re: Basic Game Tutorial
Post by: Titch on Wed, Sep 23, 2009
Ah well then you would want to do something like

Code: [Select]
private var m_wallHang:Boolean;
override public function hitWall()
{
if (velocity.y != 0 && !m_wallHang)
{
m_wallHang = true
velocity.y = 0;
}
}

And then add another if into the the update that checks to see if m_wallHang is enabled when the player hits jump.
Title: Re: Basic Game Tutorial
Post by: Mr.PepperDragon on Wed, Sep 23, 2009
Awesome, thanks : )
I'm able to jump from wall to wall now.
Title: Re: Basic Game Tutorial
Post by: aeklad on Sat, Sep 26, 2009
Great Tutorial!!  I worked through this tutorial over the past week and was able to learn quite a bit.  Though I have a long way to go. 

I was able to figure out how to put in some basic music and sounds.  And I changed up the graphics.

If you want to see how it came out you can look at it here:
http://home.comcast.net/~aeklad/
Title: Re: Basic Game Tutorial
Post by: undercooled on Mon, Oct 5, 2009
Nice Tutorial! Thank you.

I add a double jump mod, but it moves a little bit weird sometime...

In Player.as:

In Class declaration, I add a jump flag to check whether the player is already in the second jump:
Code: [Select]
private var _second_jump:Boolean = false;
In update method, I add:
Code: [Select]
if (FlxG.justPressed(FlxG.A))
{
if (_second_jump)
{
velocity.y -= _jump_power; // double the jump
flicker(.15);
_second_jump = false;
} else if (velocity.y == 0)
{
velocity.y = -_jump_power;
_second_jump = true;
}
}

It works ok, but in some situation the second jump doesn't work properly. :(
Title: Re: Basic Game Tutorial
Post by: nitram_cero (2bam) on Mon, Oct 5, 2009
Check if your y velocity is not to slow (you could be double jumping because of a double key press)
Check something like "if vely < 0 or vely > 10"

Otherwise the code looks cool!

Regards!
Title: Re: Basic Game Tutorial
Post by: undercooled on Tue, Oct 6, 2009
Check if your y velocity is not to slow (you could be double jumping because of a double key press)
Check something like "if vely < 0 or vely > 10"

Otherwise the code looks cool!

Regards!

I changed the check, now it works better, thanks for the tip! ;D

Code: [Select]
if ((velocity.y <0 || velocity.y > 10) && _second_jump)


Title: Re: Basic Game Tutorial
Post by: beef on Sat, Oct 10, 2009
[EDIT]  :D Wow, so I had Flixel 1.21...I could've sworn I had downloaded 1.25 :-\

So don't mind me...
Title: Re: Basic Game Tutorial
Post by: undercooled on Sat, Oct 10, 2009
 = means you put some value on some variable.

lefthand == righthand means you compare whether the left hand side value is equal to the right hand side.

It seems that you didn't import the Flixel package at the begin of Player.as.
Title: Re: Basic Game Tutorial
Post by: beef on Sat, Oct 10, 2009
= means you put some value on some variable.

lefthand == righthand means you compare whether the left hand side value is equal to the right hand side.

thanks! ;D
Title: Re: Basic Game Tutorial
Post by: Fugitive of Physics on Wed, Oct 14, 2009
I can't even get past part 2. It seems to be having problems importing this.
Code: [Select]
com.adamatomic.flixel.*;It's almost as if it doesn't recognize what the .*; thing means, because in the suggestion box, it refers to files in the folder, but doesn't import all of them when I use that command.
Title: Re: Basic Game Tutorial
Post by: Dak on Wed, Oct 14, 2009
First off, I'd like to thank you guys for putting this Tutorial together. I certainly find this better to start with than the more traditional "Hello World" route.  ;)

After going through the first part of the tutorial I have come across an error message that arrived not in Flash Develop, but after the flash player had opened. Here is the error message from the Adobe Flash Player 10 window:
Code: [Select]
ReferenceError: Error #1065: Variable Mode is not defined.
at global/flash.utils::getDefinitionByName()
at com.adamatomic.flixel.data::FlxFactory/onEnterFrame()[C:\FlixelDev\Tutorial Projects\BasicGame\src\com\adamatomic\flixel\data\FlxFactory.as:101]

After looking at it with my cursory knowledge of this art, I thought it might be my flixel version. But I have 1.25. I also thought I may have installed Flash Develop, Java, or configured the flex sdk incorrectly. But after re-installing and re-downloading everything I have found this error a second time.

I can post the code if you'd like, though I also tried this with a copy from your example at the end of the first section and met with the same results. Let me know what I can do, so far I'm pretty much dead in the water.

Thanks again!
Title: Re: Basic Game Tutorial
Post by: Fugitive of Physics on Wed, Oct 14, 2009
Dak: Try going to Project>Properties and changing the Test Movie setting to play in new tab. That always works for me.
Title: Re: Basic Game Tutorial
Post by: Dom2D on Wed, Oct 14, 2009
Exact same thing as Dak happening here. :(
Title: Re: Basic Game Tutorial
Post by: biomechanic on Thu, Oct 15, 2009
Dak & Dom2D:
You have missed instruction 9 (changing className in Preloader.as).

I can't even get past part 2. It seems to be having problems importing this.
Code: [Select]
com.adamatomic.flixel.*;It's almost as if it doesn't recognize what the .*; thing means, because in the suggestion box, it refers to files in the folder, but doesn't import all of them when I use that command.
My guess: you put the line in a wrong place.
Posting additional info about your problem, like error messages and relevant source code, will help us help you.
Title: Re: Basic Game Tutorial
Post by: Dom2D on Thu, Oct 15, 2009
Oh. Right. Sorry about that. :(
Title: Re: Basic Game Tutorial
Post by: Fugitive of Physics on Thu, Oct 15, 2009
Here's my code.
Code: [Select]
package 
{
import com.adamatomic.flixel.*;
import com.Tutorial.MenuState;
[SWF(width = "640", height = "480", backgroundColor = "#000000")]
[Frame(factoryClass="Preloader")]
public class Tutorial
{

public function Tutorial() : void
{super(320, 420, MenuState, 2, 0xff000000, true, 0xffffffff);
help("Jump", "Shoot", "Nothing");

}

}

}

I've tried different things like moving files around and such, and it gives me different error messages depending on what I do. If I follow the tutorial exactly, I get
Code: [Select]
C:\computer\files\and\other\unimportant\stuff\Desktop\New Project\src\Tutorial.as(11): col: 53 Error: Incorrect number of arguments.  Expected no more than 0.
{super(320, 420, MenuState, 2, 0xff000000, true, 0xffffffff);
^
C:\Documents and Settings\Jeremy.SLOWCOMPAQ\Desktop\New Project\src\Tutorial.as(12): col: 3 Error: Call to a possibly undefined method help.
help("Jump", "Shoot", "Nothing");
^
Build halted with errors (fcsh).
Title: Re: Basic Game Tutorial
Post by: Dak on Thu, Oct 15, 2009
Code: [Select]
{super(320, 420, MenuState, 2, 0xff000000, true, 0xffffffff);
Looks like you have an extra '{' in front of the super.

Also, thanks for telling me that I missed the uploader.as. I Though I uh... uhm...  ya know... did. that. !CURSE MY EYES  :P
Title: Re: Basic Game Tutorial
Post by: Fugitive of Physics on Thu, Oct 15, 2009
I removed it and its corresponding '}' and received this message:
Code: [Select]
C:\Documents and Settings\Jeremy.SLOWCOMPAQ\Desktop\New Project\src\Tutorial.as(11): col: 2 Error: A super statement can be used only inside class instance constructors.
super(320, 420, MenuState, 2, 0xff000000, true, 0xffffffff);
^
Build halted with errors (fcsh).
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Thu, Oct 15, 2009
You're not extending FlxGame.
Code: [Select]
public class Tutorial extends FlxGameHmm...seems step 10 in the tutorial is messed up...
Title: Re: Basic Game Tutorial
Post by: Socapex on Fri, Oct 16, 2009
Hello, I would like to thank you ALOT for this tutorial, it helped me so much getting around flixel. I don't know if your still open for suggestions, but as someone else mentioned, it would be nice to see how to end a level, and then start another one (I guess you change PlayState?). If you want to go deeper, unlocking levels could add them to the MenuState... So a way to save the current accomplished levels in cache would be sweet. A kinda teleporter would also be nice. Thank you again for the tutorials!!!!
Title: Re: Basic Game Tutorial
Post by: Fugitive of Physics on Mon, Oct 19, 2009
I got it working. The problem was that my computer was making another folder when I extracted the flixel .zip file. I guess that's never happened to other users before so it wasn't taken into account, or I was just being an idiot and everybody else figured that out for themselves. Anyway, thanks for the tutorial.
Title: Re: Basic Game Tutorial
Post by: fruki on Mon, Oct 26, 2009
First: Great Tutorial! I love it. Easy, direct and simple. Had no problem following it.

Second: Doubts  ;D

Q1: I want to get rid of the nasty effect of having a bunch of enemies ocuppying the same space. I tried doing this:

Code: [Select]
override public function update():void
{
       ...
       //Enemy collision with Enemy
       FlxG.overlapArrays(_enemies, _enemies, EnemyHitsEnemy);
       ...
}

...

private function EnemyHitsEnemy(E1:Enemy, E2:Enemy):void
{
E1.collide(E2);
}

It does work... sort of. Sometimes it works great and sometimes it doesnt.  :-\

Q2. Are there any restrictions in using the sprites in this tutorial for commercial purpouses?

[EDIT]
Q3. I'm the only one with a black bar at the bottom?
http://flixel.org/forums/index.php?topic=69.msg329#msg329 (http://flixel.org/forums/index.php?topic=69.msg329#msg329)

Thanks!  ;D
Title: Re: Basic Game Tutorial
Post by: increpare on Tue, Oct 27, 2009
just want to say: thanks for this; I found it helpful.
Title: Re: Basic Game Tutorial
Post by: psychobob on Tue, Oct 27, 2009
Very helpful indeed,
Yet I just was wondering why when checking if the ennemy wants to jump we use:

if(_p.y < y && _can_jump)

... this works alright but doesn't it mean if _p.y(players y) <(is lower) y(than this objects(enemy)y)
Changing it around has the opposite effect of what I'd expect... It's probably pretty simple yet this has me kinda confused.


Thanx fruki
that should be quite helpful.. :P
Title: Re: Basic Game Tutorial
Post by: fruki on Tue, Oct 27, 2009
Very helpful indeed,
Yet I just was wondering why when checking if the ennemy wants to jump we use:

if(_p.y < y && _can_jump)

... this works alright but doesn't it mean if _p.y(players y) <(is lower) y(than this objects(enemy)y)
Changing it around has the opposite effect of what I'd expect... It's probably pretty simple yet this has me kinda confused.

In ALL computer graphics (well almost all) the point (0,0) is in the left-up corner of the screen and the y is positive GOING DOWN;

Maths:
     ^
+y |
     |
     |
0,0|_______> +x

Computer:
0,0_________> +x
    |
    |
    |
+y|

so that statement reads:

if _p.y(player) <(is farther from the ground) y(than this objects(enemy)y)
Title: Re: Basic Game Tutorial
Post by: h3r3j3 on Fri, Oct 30, 2009
Loved the tutorial, thank you guys!!

I used to work with AS2 but thanks to your tutorial I'm beggining to understand AS3  :)
Title: Re: Basic Game Tutorial
Post by: MRKSTWRT on Sat, Nov 7, 2009
I'm not sure if this has been mentioned by anyone yet but:

Code: [Select]
private function EnemyHit(E:Enemy, P:Player):void
        {
if(P._hurt_counter == 0)
{
...
}
        }

should probably be:

Code: [Select]
private function EnemyHit(E:Enemy, P:Player):void
        {
if(P._hurt_counter <= 0)
{
...
}
        }

unless i'm missing something, but it's pretty likely that _hurt_counter will become a value below zero before it stops decreasing, causing that statement to evaluate to false when it shouldn't.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Sun, Nov 15, 2009
100th reply!!

I set up a new blog covering your tutorial and all the Flx classes.  Check it out if you like:

http://barnabybyrne.blogspot.com/2009/11/running-through-basic-game-tutorial-on.html

Badger
 8)



Hm.
So, you took all the stuff that darthlupi and I wrote for this tutorial, and copy/pasted it to your blog without checking to see if it was alright?
Interesting.
Title: Re: Basic Game Tutorial
Post by: bobbybaker82 on Mon, Nov 16, 2009
100th reply!!

I set up a new blog covering your tutorial and all the Flx classes.  Check it out if you like:

http://barnabybyrne.blogspot.com/2009/11/running-through-basic-game-tutorial-on.html

Badger
 8)
Hm.
So, you took all the stuff that darthlupi and I wrote for this tutorial, and copy/pasted it to your blog without checking to see if it was alright?
Interesting.


Don't you think it would have been easier to just take 2 seconds and look at his blog before jumping down his throat?  :-\

Title: Re: Basic Game Tutorial
Post by: bobbybaker82 on Mon, Nov 16, 2009
Let's just hope it was a misunderstanding :) Happens to the best of us. :)
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Mon, Nov 16, 2009
Badger: Thank you for removing the content. The thought that you were intending to use this content for financial gain was only a small fraction of the reason why I was not happy with your approach... there's a whole list of issues that immediately sprang to mind while I was skimming over the post on your blog, but they irrellevant now.

I am flattered you found our tutorial useful. The biggest piece of advice I can give you for the future would be to just ask. either in a PM or in this thread or whatever... I would still have said "no", but we might have discussed some alternatives, and at the very least all this forumdrama would have been avoided...

Good luck on your site - continue to write your own articles, and I'll read them.
Title: Re: Basic Game Tutorial
Post by: PlayOrDie on Mon, Nov 16, 2009
No problem, I am sorry if it came across in the wrong way.  There was an element of me wanting to suprise you (in a good way), but also a little hesitance I guess as I was not sure how you would feel about it.

Anyway I meant well, and seeing it from your point of view, I can totally understand how it must have been alarming to see your own tutorial headings and a bunch of adsense on there.

And it is only fair that I remove all your code etc. which I have absolutely done.

I'm sure we've all considered the possibility of making money out of blogs, well although I have thought about it, I quite honestly don't expect to.  The adsense on there is really just delusions of grandeur, though I do feel that I have the ability to do technical writing of sorts.

By the way I meant what I said, your tutorial really is good and has helped a lot already.  I never wanted to do more than explain the logic behind the code in it, but that's not really for me to do I guess..however everything that I wanted to say applies to Mode as well, like changing state, and examining all the clsases in it, so I am dissecting that instead now.  Thanks for saying that you will take a look as I try and add to it.
Title: Re: Basic Game Tutorial
Post by: increpare on Mon, Nov 16, 2009
hugs all round  :)
Title: Re: Basic Game Tutorial
Post by: PlayOrDie on Mon, Nov 16, 2009
Yeah my approach was wrong, and there was no real need to do a tutorial on a well explained tutorial. Lol. I do understand stuff better now, so good times.  :)
Title: Re: Basic Game Tutorial
Post by: BullitSpeed on Wed, Nov 18, 2009
Just finished the tutorial.  Infinite thanks for this.  It helped me gain a beginning grasp on Flixel far more quickly.  Next, I plan on really digging into the Flixel classes now to try to understand why they do what they do in the tutorial source.  And then I've got to check out BFlixel...  A lot to take in, but it's going fast.

I saw someone had mentioned they'd like to see a tutorial chapter for setting up multiple levels.  I'd definitely like to learn that too.  Between all of this and Mode, grasping Flixel is looking very promising here (I'm relatively new to AS3 Flash development in Flex Builder 3, but am learning fast and enjoying it a lot).

Cheers
 :)
Title: Re: Basic Game Tutorial
Post by: PlayOrDie on Wed, Nov 18, 2009
Just a thought, as I am planning how multiple levels can be done too, would it not be possible to set a variable currentlevel:uint=1 when you first start playing, then in your playstate.as you can tamper with:

_map = new FlxTilemap(new DataMap, ImgTiles, 12);
          
To be more like

if(currentlevel==1)
_map = new FlxTilemap(new DataMap1, ImgTiles, 12);
          
else if(currentlevel==2)
_map = new FlxTilemap(new DataMap2, ImgTiles, 12);

etc...

And also create a LevelProgressionState.as file which would increase the current level.  It would be the same as MenuState.as except "level complete prepare for next level" instead of your title screen.
          
[EDIT] I will be performing this check in 'PlayStateTiles.as' as I am using Flan now.
Title: Re: Basic Game Tutorial
Post by: iMrEuphony on Sun, Nov 22, 2009
Hey all,

First off thanks for the great tutorial.

I've had flex/flixel installed for about an hour so apologies if I've done something silly.
I'm having trouble with the code example below:

Quote from: SeiferTim
     
Code: [Select]
override public function update():void
              {
                  if (FlxG.kA)
                  {
                      FlxG.flash(0xffffffff, 0.75);
                      FlxG.fade(0xff000000, 1, onFade);
                  }
                  
                  super.update();
              }

First off Flx.kA doesn't seem to exist for me.

Quote from: Flex Builder 3
Access of possibly undefined property kA through a reference with static type Class.

And secondly, FlxG.flash is taking on the colour passed to Flx.fade.

As in, for the above code, it would flash black, and then fades to black (granted I can't see this bit, since it's already black, but I'm pretty sure that's whats happening).

Any ideas? All help would be appreciated.

Cheers,
euph
Title: Re: Basic Game Tutorial
Post by: Socapex on Sun, Nov 22, 2009
Hey guys, I just wanted to say thanks for porting the tut on the wiki. I think it's going to be way more user friendly there. Thanks again!
Title: Re: Basic Game Tutorial
Post by: Keldorn on Sat, Nov 28, 2009
First off Flx.kA doesn't seem to exist for me.

It Appears to be now  FlxG.Keys   which then you can set a certain key say. the "a" key
FlxG.keys.A

I could be wrong though, I only been using Flixel for about 1 hour.
 But I had this trouble myself doing this tutorial.
http://active.tutsplus.com/tutorials/screencasts/conquer-the-universe-with-actionscript-3-0-and-the-flixel-game-engine-part-1/

Appears many of the tutorials out there are using outdated methods.
Title: Re: Basic Game Tutorial
Post by: Keldorn on Sat, Nov 28, 2009
Hi, like above FlxG.ka is now FlxG.keys,   Can anyone say what is the alternative for FlxG.justPressed?
Title: Re: Basic Game Tutorial
Post by: NineDice on Sat, Nov 28, 2009
Hmm, perhaps I'm missing something here but I cannot seem to find the fabled Preloader.as.

It's been mentioned it "comes with Flixel". Anyone care to clarify?
Title: Re: Basic Game Tutorial
Post by: cai on Sun, Nov 29, 2009
Hmm, perhaps I'm missing something here but I cannot seem to find the fabled Preloader.as.

It's been mentioned it "comes with Flixel". Anyone care to clarify?
It seems that it is not included with Flixel on github, probably since the preloader is really part of the game, not necessarily flixel.  That said, it is available with the sample games.  Here is the Preloader.as from FlxTeroids (http://github.com/AdamAtomic/FlxTeroids/blob/master/src/Preloader.as).
Title: Re: Basic Game Tutorial
Post by: Keldorn on Sun, Nov 29, 2009
I was slamming my head last night trying to figure this out ( well not literally). If anyone else has this problem, maby this will help.   When I complied the game after creating the playstate.as and the player, the player would appear and then fall off the screen and the map would not appear.
Some of the x, y variables were incorrect in the tutorial.

Code: [Select]
FlxG.followBounds(1,1,640-1,480-1);
Should of been,
Code: [Select]
            FlxG.followBounds(1,1,320-1,240-1);
Code: [Select]
_p = new Player(48, 448);That would make the player appear out of the bounds, hence whey I would see no map and the player just falling off the streen, I change to
Code: [Select]
_p = new Player(16, 32);
So the player would appear in the corner of the map.

btw the tutorial works good so far, with the new flixel, is just that FlxG.KA   needs to be now,
FlxG.keys.X    and

Flxg.justpressed()  -> FlxG.keys.justpressed
Title: Re: Basic Game Tutorial
Post by: fedekun on Wed, Dec 2, 2009
I'm having a problem with the method 'collideArray2', it cant find it, has it changed name or something?
Title: Re: Basic Game Tutorial
Post by: gummifer on Thu, Dec 3, 2009
I'm having a problem with the method 'collideArray2', it cant find it, has it changed name or something?

I had that problem too. In the end I used a for-loop to work around it. Like this:

for (var j:int = 0; j < playersStars.length;++j) {
   map.collide(playersStars[j]);
}

It seems to work. Though I'm experiencing a bug that sometimes makes the stars explode into sparks before throw them away. Like if they collide with the ground you're standing on or something.
Title: Re: Basic Game Tutorial
Post by: Dabo on Fri, Dec 4, 2009
btw the tutorial works good so far, with the new flixel, is just that FlxG.KA   needs to be now,
FlxG.keys.X    and

Flxg.justpressed()  -> FlxG.keys.justpressed

FlxG.keys.X works fine for me, but justPressed needs a string for an argument, right? I have:

Code: [Select]
FlxG.keys.justPressed("x")
and I'm getting the error

Code: [Select]
TypeError: Error #1010: A term is undefined and has no properties.
And then there's a bunch of stuff pointing to the problem, which is the justPressed deal-i-o. Any reason why this is happening?

Title: Re: Basic Game Tutorial
Post by: Rybar on Fri, Dec 4, 2009
Code: [Select]
(FlxG.keys.justPressed("X"))  //Capital X
x (lowercase) isn't defined in FlxKeyboard.

-Ryan
Title: Re: Basic Game Tutorial
Post by: Tycho on Sat, Dec 5, 2009
Few questions.

1. I don't have the Preloader file when I make an AS3 project. Do I have to make it myself?

2. For step 10, how do you make the class an extension of FlxGame? I don't think you explained it. And do we make Preloader.as the extension or Tutorial.as?
Title: Re: Basic Game Tutorial
Post by: Austin East on Sat, Dec 5, 2009
I can't find the Preloader.as in the flixel files anywere... :-\
Title: Re: Basic Game Tutorial
Post by: Austin East on Sat, Dec 5, 2009
I can't find the Preloader.as in the flixel files anywere... :-\

Never mind, I found it. For those with the same problem, look here. http://github.com/AdamAtomic/Mode

Atleast, thats a form of the preloader.

Could you also explain step 10 in more detail? Which class do we make an extension of FLxGame? And how would I do that?
Title: Re: Basic Game Tutorial
Post by: Tycho on Sat, Dec 5, 2009
I can't find the Preloader.as in the flixel files anywere... :-\

Never mind, I found it. For those with the same problem, look here. http://github.com/AdamAtomic/Mode

Atleast, thats a form of the preloader.

Could you also explain step 10 in more detail? Which class do we make an extension of FLxGame? And how would I do that?
That is a whole game I believe. But I'm sure downloading that game's preloader would work. Though I think it would be the same as just creating a new class titled "Preloader" I just don't want to have to create a new class every time I want to make a game.
Title: Re: Basic Game Tutorial
Post by: Austin East on Sat, Dec 5, 2009
I can't find the Preloader.as in the flixel files anywere... :-\

Never mind, I found it. For those with the same problem, look here. http://github.com/AdamAtomic/Mode

Atleast, thats a form of the preloader.

Could you also explain step 10 in more detail? Which class do we make an extension of FLxGame? And how would I do that?
That is a whole game I believe. But I'm sure downloading that game's preloader would work. Though I think it would be the same as just creating a new class titled "Preloader" I just don't want to have to create a new class every time I want to make a game.

That's what I mean't ;D You could just use the preloader from Mode.
Title: Re: Basic Game Tutorial
Post by: Haledire on Tue, Dec 8, 2009
Hi, pretty new here (came across flixel only a week ago).  I've got a couple questions (sorry if I'm a bit wordy).

Since I grabbed Flixel 1.27 without realizing it, I'd been trying to work through the tutorial with it as best I could but I seem to have come to a dead spot as soon as I reached the part of the tutorial concerning implementing the jumping enemies.

Reading up on the v1.3 planning thread in the bugs forum, I see that the collidearray2 was removed entirely and the hitfloor function requires a flxcore to activate (which reading the tutorial I assume it didn't need anything at the time).  I see fedekun's solution for collidearray2 above for the attacks, but is that the same solution for the tilemap collision?  It seems odd to remove a dedicated function for tilemap collision to arrays in favor of a manual coding method.  Granted I haven't seen what the old function did (haven't looked for a download for v1.25 just yet, and I didn't see a link on the site for it).

What would I need to add to the override for hitfloor to be able to use it?  I assume it needs to know about the map?  I'm a little sketchy on OOP so I'm not sure if the function would even be able to check the map from where it's being written, or if that is even the point of concern here (I've messed with AS 2 before, lightly touched on AS3, but I never really hit situations of overrides before).

I first ran across this issue when I was looking around and came across an old post from august about a more mario-styled timing based jumping system (this one (http://flixel.org/forums/index.php?topic=256.0)) and didn't realize it was because the implementation of hitfloor had changed.  And apparently I didn't realize I left it commented out...

I was considering updating the wiki entry for this (since I see it hasn't been finished past section 3) but I don't really know the extent of the issues that the new flixel version has caused or how to fix them so... yeah... that would just be silly of me now wouldn't it...  I at least have the tutorial running to the point of having a little green ninja who can't jump...
Title: Re: Basic Game Tutorial
Post by: Curois on Tue, Dec 8, 2009
Hey Haledire,
I ran into the same problem as you did. I however am stubborn, so I just copied the CollideArray2 method from an older Flixel build, into the newer, and the game works fine after that :)
Title: Re: Basic Game Tutorial
Post by: BullitSpeed on Tue, Dec 8, 2009
Hey Haledire,
I ran into the same problem as you did. I however am stubborn, so I just copied the CollideArray2 method from an older Flixel build, into the newer, and the game works fine after that :)

haha the same moment you posted this, I posted a question about how to get around CollideArray2:

http://flixel.org/forums/index.php?topic=599.0
Title: Re: Basic Game Tutorial
Post by: Curois on Tue, Dec 8, 2009
Hahahaha so I noticed :)
I would really like some to explain to me (a AS3 noob) why the removed CollideArray2, and what the alternative is (going to be). As long as I don't understand it, I'll leave my "hack" in place ;)
Title: Re: Basic Game Tutorial
Post by: Haledire on Tue, Dec 8, 2009
quoting from the v1.3 planning thread:

4 - no need for CollideArray2() anymore, as all collision is between FlxCores and other FlxCores

Granted the Tilemap is a flxcore, but if you call out an array of another core (like the enemies in the tutorial), none of the built in collide functions seem to allow a collision to an array (only arrays to arrays) without specifically calling the cores within, so yeah - I'm just as confused.  I might have to grab that section of code in myself in the future unless I can figure out exactly what's going on.

The for loop from gummifer (I think i miscredited that before) works.  It seems the only thing different from collideArray2 is that it doesn't spend time checking to see if the Core exists.

I'm having a problem with the method 'collideArray2', it cant find it, has it changed name or something?

I had that problem too. In the end I used a for-loop to work around it. Like this:

for (var j:int = 0; j < playersStars.length;++j) {
   map.collide(playersStars[j]);
}

It seems to work. Though I'm experiencing a bug that sometimes makes the stars explode into sparks before throw them away. Like if they collide with the ground you're standing on or something.

Quote from: Flixel1.25 Code
   
Code: [Select]
static public function collideArray2(Core:FlxCore,Sprites:FlxArray):void
{
if((Core == null) || !Core.exists || Core.dead) return;
var sprite:FlxSprite;
for(var i:uint = 0; i < Sprites.length; i++)
{
sprite = Sprites[i];
if((Core === sprite) || (sprite == null) || !sprite.exists || sprite.dead) continue;
Core.collide(sprite);
}
}
Now if only I could understand what to do about the hitFloor/Wall/Roof functions to be able to properly implement any necessary update changes (I had ideas for gameplay that might require me calling the functions in some way).
Title: Re: Basic Game Tutorial
Post by: Curois on Tue, Dec 8, 2009
Now that I'm finished with the tutorial, and I got the game working (can be found at www.dandymusic.eu/ninja), I have some questions about it:

* What is the deal with _move_speed and maxVelocity.x as defined in both Player and Enemy classes? How do they interact?

Code: [Select]
             private var _move_speed:int = 400;
private var _jump_power:int = 210;   
public var _max_health:int=10;
public var _hurt_counter:Number = 0;
private var _stars:FlxArray;
                      private var _attack_counter:Number = 0;

public function Player(X:Number,Y:Number,Stars:FlxArray):void
{
super(ImgPlayer, X, Y, true, true);
_stars = Stars;
//Max speeds
                      maxVelocity.x = 1000;
                      maxVelocity.y = 1000;
                      //Set the player health
                      health = 10;
                      //Gravity
                      acceleration.y = 420;

* In the Enemy class, I changed the enemy's health to 4:
Code: [Select]
_eStars = EnemyStars;
            _p = ThePlayer;
            //Max speeds
            maxVelocity.x = 1000;
            maxVelocity.y = 200;
            [b]health = 4;[/b]
            acceleration.y = 420;
The first enemy that spawns has 4 health, all the other enemies only 1. Can anyone explain why?
Title: Re: Basic Game Tutorial
Post by: Haledire on Tue, Dec 8, 2009
I hadn't gotten to that part myself just yet, but looking at the tutorial I think I can venture a guess:

Quote from: Tutorial
1. Add this to  your Enemy class after the last function. That last function should be the override of the kill function.

Code:
Code: [Select]
        public function reset(X:Number, Y:Number):void
        {
            x = X;
            y = Y;
            dead = false;
            exists = true;
            visible = true;
            play("normal");
        }

It seems the reset code in the tutorial doesn't reset the health of the respawning ninjas (note I say RE- the code logic is that if an enemy is alive, a new one is created, but if it is killed, it is respawned to reuse that portion of the array).  If you never kill the first ninja, the new ninjas are created with proper health, but if the first one is killed, it only reappears - with 0 health.  The change you made to the health code seems to have been placed on the enemies weapons, rather than their respawn.

And on _move_speed and maxVelocity.x:

I'm assuming _move_speed is your rate of acceleration, and maxVelocity is the limit to the speed at which you can move.  You can somewhat see it with how your character starts off really slow, but given the proper motivation can zip to the wall very quickly, if only for a split second.
Title: Re: Basic Game Tutorial
Post by: Tycho on Wed, Dec 9, 2009
Still need a clearer explanation to step 10   :)
Title: Re: Basic Game Tutorial
Post by: Curois on Wed, Dec 9, 2009
I hadn't gotten to that part myself just yet, but looking at the tutorial I think I can venture a guess:

Quote from: Tutorial
1. Add this to  your Enemy class after the last function. That last function should be the override of the kill function.

Code:
Code: [Select]
        public function reset(X:Number, Y:Number):void
        {
            x = X;
            y = Y;
            dead = false;
            exists = true;
            visible = true;
            play("normal");
        }

It seems the reset code in the tutorial doesn't reset the health of the respawning ninjas (note I say RE- the code logic is that if an enemy is alive, a new one is created, but if it is killed, it is respawned to reuse that portion of the array).  If you never kill the first ninja, the new ninjas are created with proper health, but if the first one is killed, it only reappears - with 0 health.  The change you made to the health code seems to have been placed on the enemies weapons, rather than their respawn.

I'm sure the code I changed refers to the Enemies, and not their weapons (those are in the ninjastar code), but I think you could be right about the respawning part. So I'm gonna try that.
And on _move_speed and maxVelocity.x:

I'm assuming _move_speed is your rate of acceleration, and maxVelocity is the limit to the speed at which you can move.  You can somewhat see it with how your character starts off really slow, but given the proper motivation can zip to the wall very quickly, if only for a split second.

This means that if I want to make a powerup that makes the player run faster, I should change both variables right? Because if I only change the rate of acceleration, the player's speed still gets "capped" at maxVelocity.x if I'm correct.
Similarly, if I want to make a powerup that enables the player to jump higher, I have to change both the _jump_power, and maxVelocity.y, because I'd forget to change maxVelocity.y, the player would never be able to overcome the gravity enough to actually make use of a higher _jump_power. Am I correct in this?
Title: Re: Basic Game Tutorial
Post by: Haledire on Wed, Dec 9, 2009
Curois -

ah yes, i saw the indent and assumed what was under it was a code process for the stars, didn't read it right and like I said, I haven't gotten that far in the tutorial.  I'm too busy messing with the jumping physics now that I understand what to do about the override.

On the jumping, if you just want to go higher, you simply need to change the max or the power, not both.  Quite honestly, after researching the code, I'm curious as to why the jump_power variable is even necessary as implemented in this tutorial, perhaps more a visual thing than an implementation purpose.  If they expanded it into the concept of powerups I would understand better.

I'll try to explain what I mean.  Jump Power sets the velocity of the jump, but it is cut off by the maxVelocity in the calculation.  The update function of a FlxSprite sets the velocity.y to what is calculated from FlxG.computeVelocity (literally, when you send 800, the first thing that is done on the first update is that 200 is set in it's place, so the 800 was irrelevant, and merely set so that you have a number that's larger than your max to get cut down).  The next calculation sent is that same 200, subtracted by the first percentage of gravity.  So the value sent never goes above the max value in the case of this tutorial.

Essentially, you can make your initial jump power lower than your max, and make the powerup add onto the jump power to make it reach the max (or at least get closer).

Conversely, you can send the max as your current velocity, and the powerup will change the max.

Either way, you will jump higher as the decay from the slowly growing acceleration (acceleration is 0 to start, and grows at a percentage) will need more time to completely overcome your velocity.

Tycho -

I assume you're talking about the first part of the tutorial?  If so, what is meant there is that in the class declaration, you add extends FlxGame to the end of that line.  Every time in the tutorial you are asked to extend the class, it means adding the word extends and the class name mentioned at the end of the line that says "public class".  

There's a sample code at the end of that part of the tutorial to double check what you've typed is right (though if you have Flixel v1.27 or 1.28, ignore the fact that it says com.adamatomic.flixel, it's become org.flixel now).
Title: Re: Basic Game Tutorial
Post by: OnionsXD on Thu, Dec 10, 2009
This is a really good tutorial! Hope it helps a lot of people out! Sure did 4 me!!
Title: Re: Basic Game Tutorial
Post by: murkinesis on Thu, Dec 10, 2009
i just started this tutorial. I'm on page 1. Here's my code so far:

platformTest2.as
Code: [Select]
package platformTest2
{
import com.adamatomic.flixel.*;

[SWF(width = "640", height = "480", backgroundColor = "#000000")]
[Frame(factoryClass = "Preloader")]

/**
* ...
* @author Murkinesis
*/
public class platformTest2
{

public function platformTest2()
{

}

}

}

and here's the error I'm getting:

Code: [Select]
G:\Progams\Flash Develop\new projects\platformTest2\src\platformTest2.as: Error: A file found in a source-path must have the same package structure '', as the definition's package, 'platformTest2'.
Build halted with errors (fcsh).

It doesn't say WHICH file doesn't have the same package structure, so I don't know which one. Is this because I unzipped flixel into my src folder as per the instructions, and the .as files contained therein are written with different packages?
Also, why is the flixel preloader no longer packaged with Flixel?
Title: Re: Basic Game Tutorial
Post by: Haledire on Thu, Dec 10, 2009
It actually is telling you which file is wrong.  Your very first line:

package platformTest2

Since this is your main class, you don't need that platformTest2 there.  You are actually telling it to look for a sub folder called platformTest2 (which if you are following the tutorial would be in your src folder).

If you check the sample code at the end of the first post, you'll see that the package has nothing after it.

On the preloader - no idea.  You should be able to grab the preloader file from Mode (http://github.com/AdamAtomic/Mode) on github.  It may be because Adam actually made this nice little python script that builds a game class, preloader class, menustate and playstate classes that can be set up pretty easily after they're all created.  Or it could be just how ridiculously small the file really is.

The file really isn't anything special, it's a simple class extending FlxFactory with two simple lines in it:

className = "Your Game Class' Name Here";
super();

This is what the entire code of a preloader is:
Code: [Select]
package
{
import org.flixel.data.FlxFactory;
 
public class Preloader extends FlxFactory
{
public function Preloader()
{
className = "Tutorial";
super();
}
}
}
 

Per project, the only thing you change is the text sent to className.  Granted, it would help if the tutorial had the information on either where to get the file or how to create it, as it wouldn't be the most obvious thing to set up regardless how small it is.
Title: Re: Basic Game Tutorial
Post by: murkinesis on Thu, Dec 10, 2009
Tycho -

I assume you're talking about the first part of the tutorial?  If so, what is meant there is that in the class declaration, you add extends FlxGame to the end of that line.  Every time in the tutorial you are asked to extend the class, it means adding the word extends and the class name mentioned at the end of the line that says "public class". 

There's a sample code at the end of that part of the tutorial to double check what you've typed is right (though if you have Flixel v1.27 or 1.28, ignore the fact that it says com.adamatomic.flixel, it's become org.flixel now).
Still need a clearer explanation to step 10   :)

The first post in this thread, containing the tutorial, should be updated to reflect this. Many people don't know what "To do this, we make this class an 'extension' of the FlxGame class." means.

Also, why is the package org.flixel? The flixel zipfile contains a different structure: AdamAtomic-Flixel-numbers/org/flixel actually. I had issues with my import because of this. Shouldn't the tutorial reflect this structure, or shouldn't the zip file have one less folder in it (specifically the AdamAtomic folder) so that the tutorial is accurate?
Title: Re: Basic Game Tutorial
Post by: murkinesis on Thu, Dec 10, 2009
Ammending my previous post, much of the tutorial is now inaccurate.

Step 14, page 1:
Quote
Add a new folder to the "com" folder, and name it "Tutorial". Add a new Class to this folder, and name is "MenuState.as", and then, in your Tutorial.as file - right underneath your "import", add a new line...

There is no longer a com folder. Where should we put this "Tutorial" folder with the new flixel structure?

It seems like there's a lot of confusion about this recent flixel restructuring. Seems like the tutorial needs a good working-over to stay current. This tutorial is a programming foundation of people who are new to flixel, like myself. The arrival of Level Up! brought many people here, and it would be tragic if they were turned away by the frustration of following a defunct tutorial.
Title: Re: Basic Game Tutorial
Post by: xmorpher on Thu, Dec 10, 2009
The solution is simple:
Specify that this tutorial is based on version 1.26 (linking to this version) and voilá
Title: Re: Basic Game Tutorial
Post by: Haledire on Thu, Dec 10, 2009
When I first started looking at the tutorial, I didn't initially see the old downloads page link, and I was completely oblivious to the fact that I had grabbed a different version.

Really a lot of tutorials out there right now fell out of date the moment 1.27 came out late last month with it's major changes (removal of collideArray2, overhaul of collisions, file structure change, etc).  Because the download on the main page goes straight to the latest commit, the fact that most tutorials just say to "get flixel's source" will break them immediately because something could change before they even get the tutorial half completed.

http://flixel.org/forums/index.php?topic=62

Grabbing the v1.25 w/Mode version of Flixel from this page should solve problems following the tutorial as is.

This weekend if i'm not too busy fleshing out my game idea, I might start re-writing this tutorial on the wiki to match a more current version (and maybe mark and update the v1.25 one that's there as well).

murkinesis -

i usually just pull in the org section, as the first folder name is really just the name of the commit coming off of gitHub, which will change every time it gets updated.  The typical file structure you see for this sort of OOP is that what you are actually organizing is a website name. 

The reason it used to be com.adamatomic.flixel is that it was essentially reversing adamatomic.com and the package is called flixel. This is the methodology a lot of people seem to use.  In a way, it's a sort of method to mark in code "ok, this code is coming from this website, and called this name".  Basically, it's a type of copyright label in addition to a file structure.  That's why you would usually just pull in the folder that says 'org' or 'com' or 'uk' etc.
Title: Re: Basic Game Tutorial
Post by: Rybar on Thu, Dec 10, 2009
I've begun editing this version of this tutorial to match the current version of Flixel; so far only parts 1-3 have been posted by SeiferTim; If he doesn't mind, I'll start moving/editing the remaining parts as well.
Title: Re: Basic Game Tutorial
Post by: Austin East on Sat, Dec 12, 2009
So who wants to translate this into 1.40?  ;D
Title: Re: Basic Game Tutorial
Post by: BullitSpeed on Sat, Dec 12, 2009
I've begun editing this version of this tutorial to match the current version of Flixel; so far only parts 1-3 have been posted by SeiferTim; If he doesn't mind, I'll start moving/editing the remaining parts as well.


:: thumbs up ::
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Sat, Dec 12, 2009
I'm in the middle of several projects right now (3 of them Flixel games :D) but my goal is to finish converting this tutorial over to the wiki while making the necessary changes to get it back up to date with v1.41.

Anyone who wants to work on that in meantime, be my guest.
Title: Re: Basic Game Tutorial
Post by: Austin East on Sun, Dec 13, 2009
I'm in the middle of several projects right now (3 of them Flixel games :D) but my goal is to finish converting this tutorial over to the wiki while making the necessary changes to get it back up to date with v1.41.

Anyone who wants to work on that in meantime, be my guest.

Take your time. I should be studying for midterms anyways. But I was actually looking at mode's updated code to see some of the differences and I got myself near starting the playstate. From there I couldn't figure some part out :P
Title: Re: Basic Game Tutorial
Post by: Haledire on Sun, Dec 13, 2009
Heh, seems I need to start breaking apart the pages of the tutorial on the wiki.  I got to adding the stars to the player section and the text began to get cut off on the straight transfer version.

I still haven't done all the research in the current code to make the updates.  I need to look at Mode to get an idea as to how to start fixing things.  If everything's stayed consistent with the recent updates, everything regarding FlxArray has changed (since I think it was removed and replaced with flash's default Array class).  Tilemaps have undergone another new change, so I have to figure if it's effected anything beyond the fix I had read of during the 1.37 phase.

And I'm still trying to conceptualize the physics I need to deal with for my own Flixel project...
Title: Re: Basic Game Tutorial
Post by: murkinesis on Wed, Dec 16, 2009
No... the idea is that you could follow through the tutorial and build the source yourself. At the end of each section, the complete source for any modified files should be there that you could copy/paste if you want...

This is wrong. In section VII (page three) there are changes to playstate.as and enemy.as, and the complete source for modified files is NOT there for me to copy/paste. Following Seifer's instructions, I get an enemy that no longer moves, jumps, or turns to face the player, effectively breaking the enemy. Maybe you could post the source code?
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Dec 16, 2009
No... the idea is that you could follow through the tutorial and build the source yourself. At the end of each section, the complete source for any modified files should be there that you could copy/paste if you want...

As of Flixel release v1.40, and probably earlier, this tutorial is completely broken.
Efforts are underway to update for the latest version of Flixel, but it's nowhere near ready yet...

This is wrong. In section VII (page three) there are changes to playstate.as and enemy.as, and the complete source for modified files is NOT there for me to copy/paste. Following Seifer's instructions, I get an enemy that no longer moves, jumps, or turns to face the player, effectively breaking the enemy. Maybe you could post the source code?
Title: Re: Basic Game Tutorial
Post by: murkinesis on Wed, Dec 16, 2009
Sorry, I should have mentioned that I'm using flixel 1.25.

But my point is that you said the source code for changed files would be available at the end of each section, and that's not true. For people working with flixel 1.25, there's no source code for the modified files in section 7 (or section 8..). Can you post them? Or the complete source code?
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Dec 16, 2009
Sorry, I should have mentioned that I'm using flixel 1.25.

But my point is that you said the source code for changed files would be available at the end of each section, and that's not true. For people working with flixel 1.25, there's no source code for the modified files in section 7 (or section 8..). Can you post them? Or the complete source code?

No.
Title: Re: Basic Game Tutorial
Post by: BullitSpeed on Wed, Dec 16, 2009
The tutorials do work.  I went through them in November with Flixel v1.25.  I think I had to read a few of the thread comments to find minor fixes, but they were completely minor.

If at first you don't succeed, try, try again.
Title: Re: Basic Game Tutorial
Post by: murkinesis on Wed, Dec 16, 2009
That's unfortunate, Seifer. Many people are coming to this forum recently because they have heard about how powerful Flixel is and are drawn to the beginner tutorials. There are two very prominent ones, and yours is one of them.
If you're unwilling to use standard practice in programming tutorials, ie posting your code, you're turning away an unforseen crowd of people who will become frustrated when their code breaks and they have no reference. Your stubborn nature harms not only the new programmers who find this tutorial, but the Flixel community itself. Please be mature, and post your code so that those of us who are new to Flixel and/or programming can understand what we're doing.
Title: Re: Basic Game Tutorial
Post by: BullitSpeed on Wed, Dec 16, 2009
That's unfortunate, Seifer. Many people are coming to this forum recently because they have heard about how powerful Flixel is and are drawn to the beginner tutorials. There are two very prominent ones, and yours is one of them.
If you're unwilling to use standard practice in programming tutorials, ie posting your code, you're turning away an unforseen crowd of people who will become frustrated when their code breaks and they have no reference. Your stubborn nature harms not only the new programmers who find this tutorial, but the Flixel community itself. Please be mature, and post your code so that those of us who are new to Flixel and/or programming can understand what we're doing.

I'm not too thrilled with how you're demanding things of someone who donated his own time to write a thorough tutorial.  Additionally, it might be the fact that in order to really learn from these tutorials, you need to go through them and figure it out on your own.  They may not be perfect, but they are very good and helpful as-is.  If you're using Flixel v1.25, you should be able to successfully use these tutorials.
Title: Re: Basic Game Tutorial
Post by: SeiferTim on Wed, Dec 16, 2009
That's unfortunate, Seifer. Many people are coming to this forum recently because they have heard about how powerful Flixel is and are drawn to the beginner tutorials. There are two very prominent ones, and yours is one of them.
If you're unwilling to use standard practice in programming tutorials, ie posting your code, you're turning away an unforseen crowd of people who will become frustrated when their code breaks and they have no reference. Your stubborn nature harms not only the new programmers who find this tutorial, but the Flixel community itself. Please be mature, and post your code so that those of us who are new to Flixel and/or programming can understand what we're doing.

1: I'm short on time as it is - between work, a multitude of projects, the holidays, and family stuff, I haven't had nearly as much time to devote towards the Flixel community as a whole as I would like to. If it was up to me, a new, working, updated version of this tutorial would already be finished and up on the Wiki, but that's just not the case.

2: Adam has been working like a madman this past week making wide-sweeping changes to the Flixel source which not only make things better, but completely break the old stuff, and give coders many, many new options. It would be counter-productive to spend any time at all revisiting old versions when all but the very basic information is relevant today. Plus, until he settles down with the changes a bit, it's hard to keep up.

3: I no longer have the complete source for this tutorial, and going through the tutorial to try and piece together something would take far too much time and effort than I would be able to afford at this time. See #1, and, to repeat #3, why would I want to stay focused on the past?

4: I do not believe in posting the complete source for a tutorial project. If I wanted to give you a basic prototype to let you skim through it, pull it apart, and deconstruct it to learn from, well, you already have Mode, FlxInvaders, and other simple projects Adam has provided (and kept up-to-date) on the Wiki. Robert (darthlupi) and I took the time to explain in detail what each step-by-step process in the creation of a Flixel game looks like, and if I did not post source code for a given step, it was because I thought the explanation was clear or simple enough not to warrant it - and other people have commented with more and more information to assist even further than I was able to do the first time around. You can take the time to follow the tutorial, and read the other comments for more information, or you can look at an already-finished project for examples, but I'm not going to include the finished project here, in part because of this, as well as because of #3, which refers back to #s 2 and 1.

5: I can't really think of a good reason why you would want to still be using 1.25 if you're still learning Flixel - refer to #2. I'm still using 1.25 in a project that is still in development, but only because we made several changes to the actual code in Flixel, hacked together a few things, and are at the point where it makes no sense to try and update all our code - for all other projects that I'm working on, I'm using the latest version (1.4x) and you really should be trying to learn that version.

In conclusion: this tutorial is dead, I'm not going to ressurect it in any form that will work with version 1.25, and I will not post the complete source for this, or future versions, here, on the Wiki, or anywhere.  I'm looking forward to being able to start on a Wiki version of a 1.4x+ tutorial, which will allow anyone to add or tweak it to make it more accessible to everyone, while keeping it up to date all the time. The forum is not the ideal place for that type of thing - stuff gets mucked up with all the comments and flaming going on.