FlashPunk Forums

September 02, 2010 *
News:
 



Pages: [1] 2 3 ... 5
  Print  
Author Topic: Platform Tutorial [FP0.87]  (Read 6188 times)
Noel
===========
****
Posts: 330



View Profile WWW Email
« on: January 10, 2010 »

Platformers are probably going to be one of the big things made with Flash Punk + Flash Develop, so I thought it might be handy to create a small tutorial on how to go about building a basic one.

This tutorial uses Flash Punk V0.87
If you are using an outdated version you will need to download V0.87. If you're using a new version (such as FP1.00) check out this topic.

INTRODUCTION
This tutorial will show you how to create a platform game in Flash Develop, with AS3 and Flash Punk. This tutorial assumes that you have already set up Flash Develop, with the Flex compiler and properly downloaded the Flash Punk library. If you have not done so, go here.

This tutorial also assumes that you have a basic understanding of how to code with AS3. If you no absolutely nothing about how AS3 in Flash Develop works, this may not be the best tutorial for you.

The first two "parts" sort of go through what's explained in the basic tutorial, but I thought I should add this in anyway just to make sure things are clear when you're starting up the project.

The final product will look something similar to this

Alrighty, onto the tutorial

PART I: SETUP
Step 1:
Create a new project and title it whatever you want. I'd just go with something like "platform or "platformer". Once you've done this put the Flash Punk code into the project folder, and set main.as to "Always Compile" (by right clicking main.as).

Now, go to Project>>Properties and set it to run in Flash Player 10, and let's also resize the room to 320x240 (800x600 is too big).

Once you've done all this, open up main.as and replace any code in there with the following:

Code:
package
{
import punk.core.*;

[SWF(width = "640", height = "480")]

public class Main extends Engine
{
public function Main()
{
showSplash(0x202020, 0xFF3366, .5, false);
super(320, 240, 60, 2,  World);
}
}
}

If you went through the basic tutorial you'll already know this part, and the next little bit.

Step 2:
We now want to create the level.as, which will load up our main level in the game. First, lets create a new folder in our project and call it the "game" folder, which will hold all of our main game scripts. Once you've done that (by right clicking the project and Add>>New Folder) we'll want to add a new class called "Level.as" into our newly made game folder.

In Level.as we want the package (at the very top) to say "package game", so we know that it's within the game folder. Once you've done that (if it already isn't there), you need to import a few things from Flash Punk:

Code:
import punk.core.Entity;
import punk.core.World;
import game.*;

We also need the level to extend world, so it's a level/room/world.
you're final level.as should now look like...

Code:
package game
{
import punk.core.Entity;
import punk.core.World;
import game.*;

public class Level extends World
{

public function Level()
{

}

}

}

Save level.as.

Step 3:
Now we're going to go back to main.as and we're going to replace "World" in the super function that is executed to Level, so that the game loads up Level at the start. The new line should look like:
Code:
super(320, 240, 60, 2,  Level, false, true);

Well we're here, we also need to import game.Level, so we can actually create it from here. So, under the line "import punk.core.*" put
Code:
import game.Level;

Save main.as, and you've should have successfully created the set up stuff for your game. Test the game, and if everything runs smoothly, continue to the next step.


PART II: WALLS
Step 1:
Before we create the player, we're actually going to make the walls that the player walks on. To start, we're going to need to create a sprite for the wall, and then create the Wall.as. First, create a wall sprite, or use the one below, and put it in the data folder in your project, and name it something like "wall.png".


The Wall Sprite

Now that the wall is in the correct place, we're going to create a Wall.as in the game folder. Do this now, and make sure the package, at the top is "package game".
After that, we're going to import flash punk's actor class, which we will be using for the wall. at the very start, right after the package line, put
Code:
import punk.Actor;
and after that, make sure the class extends Actor ("public class Wall extends Actor")

Step 2:
Next, we need to load in the sprite of the Wall. To do so, we're going to use the following code, which should go under  the Wall class (or rather within it)
Code:
[Embed(source = '../data/Wall.png')]
private var imgWall:class;


Step 3:
Now we need to set the sprite of the Wall to the sprite we just loaded in, and also set the collision area and type of the Wall, so that the player can have collisions with it. To do this, we need to add the following code to the public function Wall():
Code:
sprite = FP.getSprite(imgWall,16,16);
setHitbox(16, 16, 0, 0);
type = "Wall";

The first line here sets the sprite, and sets its width and height to 16 pixels. Then, we set the collision rectangle with a width and height of 16 pixels, starting at 0,0 on the sprite. Finally, we set the type of collision to "Wall", so we know what we're going to be running into from the player.

Finally, your Wall.as should look something like this:
Code:
package game
{
import punk.Actor;

public class Wall extends Actor
{
[Embed(source = '../data/Wall.png')]
private var imgWall:Class;

public function Wall()
{
sprite = FP.getSprite(imgWall, 16, 16);
setHitbox(16, 16, 0, 0);
type = "Wall";
}

}

}


And yay, you have the floor object working properly, though if you play you'll still see nothing as you haven't added it to the level yet.


PART III: THE PLAYER (finally..)
OK, most of the stuff you did back there you've already done in A Simple game in Flash Develop, so it's nothing new. Now, however, we're going to make the player object which should be a little interesting. The player is going to contain things like moving, jumping, variable jumping, friction, gravity, and pixel perfect collisions. So, without further talking...

Step 1: Player setup
First, we need to make the Player.as in the game folder. Do this, and make sure the package is package game. Next, import
Code:
import punk.Actor;
import punk.core.Spritemap;
import punk.util.*;
which we will need to do some things (such as using the keyboard) in the player. After you've done this, make sure that the player extends Actor.

next, we want to create two sprites: playerRight.png and playerLeft.png, that go into the data folder with Wall.png. You can either create your own sprites, or use the ones below.


playerRight.png and playerLeft.png

Once you have done this, import them just like we did with the wall, except we're going to add them as a sprite before we start executing other stuff, since we'll be changing the sprites relatively often.
So, once you've imported both your sprites and created a sprite variable for both, your code should look like so:
Code:
package game
{
import punk.Actor;
import punk.core.Spritemap;
import punk.util.*;

public class Player extends Actor
{
//load sprite and create the sprite variable
[Embed(source = '../data/playerRight.png')]
private var imgPlayerRight:Class;
private var sprPlayerRight:Spritemap = FP.getSprite(imgPlayerRight, 16, 16);

[Embed(source = '../data/playerLeft.png')]
private var imgPlayerLeft:Class;
private var sprPlayerLeft:Spritemap = FP.getSprite(imgPlayerLeft, 16, 16);



public function Player()
{

}




}

}


Step 2: The variables
Now that we have the basics of our player set up, we're going to need to create some main variables for the movement of the player. The two obvious ones are the horizontal and vertical speeds of the player. I'm going to call these variables xspeed and yspeed. The other variables you will need is an acceleration speed for the player, so he doesn't start moving at max speed as soon as you hit left or right. I'm going to call this variable aspeed, to represent acceleration speed.
We're also going to need some form of gravity, to pull the player down after he jumps, or walks off an edge. I'm going to call this gspeed to represent gravity speed. There are three more variables we now need, maximum speed, friction speed, and jump speed. They're pretty self explanatory, and I'm going to call them mspeed, fspeed, and jspeed, respectively.

You can set each of these values to whatever you want, or use the ones I set below. It's totally up to you. Either way, you should end up with something like this:
Code:
private var xspeed:Number = 0;
private var yspeed:Number = 0;
private var aspeed:Number = 0.2;
private var gspeed:Number = 0.2;
private var fspeed:Number = 0.4;
private var mspeed:Number = 1;
private var jspeed:Number = 3.6;

Alrighty, that's a lot of variables, but each one of them will be needed when we start to actually move the player around the world.

Step 3: Keyboards and setting the sprite

Now we need to set the current sprite of the player. To do this, we're simply going to set the variable sprite to sprPlayerRight, in the public Player function. We're also going to set the delay time between each frame of our image. I set mine so it ends up being about 2 loops of the animation per second, by doing delay = (30/4), since I have 4 frames, and there are 60 frames per second.

For the player, we're also going to need to set a collision rectangle, so that it can have proper collisions with the Wall. The player may not take up the whole 16x16 size of the sprite, so you may not want the collision rectangle to take up the whole area. Personally, I felt that doing something around setHitbox (12, 12, -2, -4); was relatively good. The rectangle is 12x12 pixels, leaving 2 pixels on either side empty and 4 at the top.

Next, we need to set up the keyboard input for the player. This is really simple, we're just going to make 3 inputs, left, right, and jump, which ends up looking like this:
Code:
Input.define("right", Key.RIGHT);
Input.define("left", Key.LEFT);
Input.define("jump", Key.X);

I set my jumping key to X, as I prefer that to the up arrow key, but you can set it to whatever you like.

Once you've done all this, your player function should look similar to the following:
Code:
public function player()
{
//set the sprite
sprite = sprPlayerRight;
//set the delay
delay = (30 / 4);
//collision mask....
setHitbox (12, 12, -2, -4);

//keyboard controls.
Input.define("right", Key.RIGHT);
Input.define("left", Key.LEFT);
Input.define("jump", Key.X);

}


Smiley

Step 4: Finally making the player do stuff
OK, now that we have set the sprites, made the variables, set the keyboard controls, and made our collision mask, we're FINALLY ready to make the player move around.

To start, we're going to need to override a function called update. Update is called every frame of the game, meaning that if you haven't changed the frame rate, it should be executed 60 times a second. So, add the following code below the player function:

Code:
override public function update():void
{

}

Everything we do with moving the player is going to be happening in here.

Now that we have our update function, let's check if the player is holding the left or right arrow keys, and if they are, we're going to increase, or decrease (depending on the key held) the xspeed.
To check if the right key is being held, we simply add an if statement that checks if the left key is being held, like so:
Code:
if(Input.check("right")) {

}

Now, of course, we want the xspeed to increase when we hold the right key, so we're going to put xspeed += aspeed within the brackets, so we end up with
Code:
if(Input.check("right")) {
    xspeed += aspeed;
}

Now do the same for the left key, except instead of adding aspeed, we want to subtract aspeed, since you're going in the opposite direction.

After you've completed that, you'll want check if the player is pressing the jump key. To do this, we do the same if statement as with left and right, but this time with "jump" instead. However, we don't want you to be able to press jump at any time and be able to magically jump. We only want you to jump if you're touching a wall below you. So, we want check if a wall is below us in the if statement as well, by adding an && and putting collide("Wall", x, y + 1) after it.

collide basically checks if you have a collision with a certain type at a certain position. In this case, we want to check for the wall, at our x position, and 1 pixel below us.

After we've done that, we want to actually make the player jump, so within the brackets add yspeed = - jspeed;
What this does is set the yspeed to negative jump speed (since we're going up, not down).

In the end, your jump check should look like this:

Code:
if(Input.check("jump") && collide("Wall",x,y+1)) {
    yspeed = - jspeed;
}

Bravo, we're doing well.

OK, now we're increasing the xspeed and yspeed, but we're not actually moving the player yet. Different people have different methods of doing so, but I've found it easiest, and best, to actually check every pixel before moving, creating a relatively flawless movement engine.

Now, I'm going to start with the x movement first. To check every pixel before moving it, I'm going to do this:
Code:
for (var i:int = 0; i < Math.abs(xspeed); i += 1) {
if (!collide("Wall", x + FP.sign(xspeed), y)) { x += FP.sign(xspeed); } else { xspeed = 0; break; }
}

This may look a bit complicated, so I'm going to cut it down a bit.
The first line uses a for statement. For statements basically repeat the code within the brackets until something is no longer true. In this case, we're saying repeat the following code until i is no longer smaller then the absolute value of xspeed. Incase you're unfamiliar with absolute/abs, it basically turns any negative number into a positive one. For example, abs(-7) equals 7, and abs(4.6) equals 4.6.
In this for statement, we also increase i by one every time it executes the code below, so that we don't create an infinite loop (which sucks, trust me).
The next line checks if we have a collision with a wall, at our x position plus the sign of xspeed. sign basically converts things to -1, 0, or +1. If anything is positive, it becomes 1, and anything negative becomes -1. This is useful for us since we only want to check one pixel to our right or left. If we don't collide with a wall (notice the !), then we move x left or right 1, depending on the current xpeed. If we DO hit a wall, we stop all the movement, and end the for statement.

This may sound a little confusing... Lets pretend xspeed is equal to 4. Therefore, we're going to run the code within the brackets 4 times, and each time it runs the code we're going to check 1 pixel before we move. That way, we check if each pixel is free before moving there, creating perfect collisions.


Now, moving up/down is going to work almost exactly the same way. The only real difference is we're using yspeed and moving the players y position.

Code:
for (i = 0; i < Math.abs(yspeed); i += 1) {
if (!collide("Wall", x, y + FP.sign(yspeed))) { y += FP.sign(yspeed); } else { yspeed = 0; break; }
}

Lastly, we need to make the player fall back down.. so under all this code we added, lets simply put
Code:
yspeed += gspeed;


After all of this, your Player.as should look something very close to this:
Code:
package game
{
import punk.Actor;
import punk.core.Spritemap;
import punk.util.*;

public class Player extends Actor
{
//load sprite and create the sprite variable
[Embed(source = '../data/playerRight.png')]
private var imgPlayerRight:Class;
private var sprPlayerRight:Spritemap = FP.getSprite(imgPlayerRight, 16, 16);

[Embed(source = '../data/playerLeft.png')]
private var imgPlayerLeft:Class;
private var sprPlayerLeft:Spritemap = FP.getSprite(imgPlayerLeft, 16, 16);

private var xspeed:Number = 0;
private var yspeed:Number = 0;
private var aspeed:Number = 0.2;
private var gspeed:Number = 0.2;
private var fspeed:Number = 0.4;
private var mspeed:Number = 1;
private var jspeed:Number = -3.6;

public function Player()
{
//set the sprite
sprite = sprPlayerRight;
//set the delay
delay = (30 / 4);
//collision mask....
setHitbox (12, 12, -2, -4);

//keyboard controls.
Input.define("right", Key.RIGHT);
Input.define("left", Key.LEFT);
Input.define("jump", Key.X);
}

override public function update():void
{
//move/jump
if (Input.check("right")) { xspeed += aspeed; }
if (Input.check("left")) { xspeed -= aspeed;  }
if (Input.check("jump") && collide("Wall", x, y + 1)) { yspeed = - jspeed; }

//actually move the player now
for (var i:int = 0; i < Math.abs(xspeed); i += 1) {
if (!collide("Wall", x + FP.sign(xspeed), y)) { x += FP.sign(xspeed); } else { xspeed = 0; break; }
}
for (i = 0; i < Math.abs(yspeed); i += 1) {
if (!collide("Wall", x, y + FP.sign(yspeed))) { y += FP.sign(yspeed); } else { yspeed = 0; break; }
}
                        yspeed += gspeed;

                }



}

}


You're probably anxious to test your game now, so let's take a small break from the player, and work on creating the world.
Logged

Portfolio | (I'm Noel, AKA Drazzke)
Noel
===========
****
Posts: 330



View Profile WWW Email
« Reply #1 on: January 10, 2010 »

PART IV: THE WORLD
OK, we now have a player that can move left and right, and jump, and we also have Walls, so we're ready to test out all this stuff now.

There are a lot of different ways we can create the level/world. One way is to simply place each Wall tile by tile, though this can take a painstakingly long time, and is (in my opinion) very frustrating. What I usually do is create an array that stores where objects are, and then run through it on the level creation and place Walls and other objects where it says (using numbers to represent different objects).

For this tutorial, we're going to use that method, as to be totally honest with you, I don't really know a better way of making the level, though you can see some other peoples techniques here.

Step 1: Making the array
Open up Level.as again, since this is where we're going to create our level. For your convenience, I've created an empty level array so you don't have to make one yourself. This array should go under the public class Level.

Code:

private var level1:Array = new Array(
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
);

That's a pretty big array. In this case, the room is 320x240, and the tiles are 16x16, making a 20x15 grid. Really, that's not too bad, but if you created a really large room, you're array would be come big, fast.. so this method really only works for small rooms.

Step 2: Creating the objects

OK, once we've added this array, we're going to add some code to a new function called init. Actually, we're going to be overriding init, so when you create the init function, it should look like so:
Code:
override public function init():void
{

}

Within this, we're going to go through the massive array and place Walls and the player where we tell it to. So, before we do that, create a little map for yourself in the array. Replace the 0's with 1's where you want the player to start (there should only be one 1), and replace the 0's with 2's where ever you want a Wall (there can be multiple 2's).

Now we're going to create some variables that are needed. The first variable is width, which is the width (in tiles) of the room. In our case, unless you made the room smaller, width should be set to 20. We're also going to create a variable called tile, which should equal 16, unless you changed the size of the wall or player sprites from 16 to something different. After that, we're going to create two more variables, row and xx, both of which should be 0.

Next, we have the code that goes through the array.. and it looks like...
Code:
for (var i:int = 0; i < level1.length; i += 1) {
if (i / width == int(i / width)) { row += 1; }
xx = (i - (row-1) * width) * tile;

var e:Entity
if (level1[i] == 1) {
add(e = new Player());
e.x = xx;
e.y = (row-1) * tile;

}
if (level1[i] == 2) {
add(e = new Wall());
e.x = xx;
e.y = (row-1)*tile;
}
}


I'll take this line by line.
On the first line we see another for statement. In this case, we repeat the following code until i is larger then the level length.
On the next line, we check what row we're currently on. This is pretty simple.. If i/width is equal to an integer of i/width, then we add another row. For example, if i=19, then i/width is not equal to int(i/width), as i/width would be something like 0.99 and int(i/width) would be 1. However if i = 20, then i/width would equal int(i/width).
Next, we find the current x value of the tile we're looking at. Basically, we take the current row, multiply it by the width, and remove that from i. We then multiply it by the tile width so it's the actual x value, and not the number of the tile.

After this, we create a new variable that will temporarily store the objects we create as we place them. Then, we check if the current tile is a Wall or a Player, add them, and set their correct x and y values.


Your final level.as should look like...
Code:
package game
{

import punk.core.Entity;
import punk.core.World;
import game.*;


public class Level extends World
{

public var level1:Array = new Array(/*LEVEL ARRAY.. not going to include that again*/);


public function level()
{

}

override public function init():void
{
var row:int = 0;
var xx:int = 0;
var width:int = 20;
var tile:int = 16;
for (var i:int = 0; i < level1.length; i += 1) {
if (i / width == int(i / width)) { row += 1; }
xx = (i - (row-1) * width) * tile;

var e:Entity;
if (level1[i] == 1) {
add(e = new Player());
e.x = xx;
e.y = (row-1) * tile;

}
if (level1[i] == 2) {
add(e = new Wall());
e.x = xx;
e.y = (row-1) * tile;
}
}

}

}

}

You've now created a map! Congrats.

Test the game, and you should now be able to run around and jump.. though you may notice you wont stop after moving, or hit a maximum speed.. That comes in the next part.

PART V: MORE PLAYER
OK, now that we have a world that we can move around in, we want to be able to stop the player, have a maximum speed, have variable jumping, and also change the direction of the sprite/stop the animation when we're not moving!

Step 1: Friction
When the player isn't holding down left or right, we want to make the player slow down. So, open up Player.as again, and after we make the player fall with gravity, add this code:
Code:
if (!Input.check("right") && !Input.check("left")) {
xspeed -= FP.sign(xspeed) * fspeed;
if (Math.abs(xspeed) <= 0.2) { xspeed = 0; }
image = 0;
}

First we check if the player isn't holding left and right. If they're not, we decrease the xspeed with fspeed (or increase, if the xspeed is negative). Then, to stop any shifting/shaking we check if xspeed is close to 0, and if it is, we simply set it to 0. Finally, we set image to 0. image is a Flash Punk variable that sets the current frame of the sprite of an Actor. We set it to 0 so it looks like the player is standing.

Step 2: Maximum speed
If the player holds left or right for a little while, we'll eventually start going really fast. To stop this, we're going to add maximum speed.
Code:
if (Math.abs(xspeed) > mspeed) { xspeed = FP.sign(xspeed) * mspeed; }

With this code we check if the absolute value of xspeed is larger the mspeed. If it is, we set xspeed to positive or negative mspeed, depending on what xspeed currently is. This way, there is no way xspeed can be larger the mspeed.

Step 3: Variable Jumping
Variable jumping is really, really easy. All we're going to do is check if the player is holding jump while the player object is moving up. If he's not, then we're just going to add some more gravity to make it fall faster.

Code:
if (!Input.check("jump") && yspeed < 0) {
yspeed += gspeed;
}
So now, if the player is not holding jump, the object will fall twice as fast.


Step 4: changing the sprite
Lastly, you may have noticed that the player didn't change direction... This is an easy fix.
When you hit the left/right key, simply put sprite = sprPlayerRight or sprite = sprPlayerLeft after the xspeed is increased. This way, as soon as the player hits left/right, the sprite is changed.


FINISHED!!

Yay, you've now created a basic platform game, with friction and acceleration, jumping and variable jumping, gravity, sprite changing, and a lot more. I hope this tutorial helped you understand how to make a platform game in Flash Punk!

Your game should now look something similar to this.

Download
Source files for the game, with Flash Develop project files.

.zip: Download [72KB]
.rar: Download [70KB]




Notes/Other
I wrote this late at night, so there were most probably some bugs, but I believe I have fixed them all now. If you see anything wrong, please PM me or post here. Overall though, I believe everything works.

Feel free to expand on this tutorial once you've finished, or use the created game for whatever you want. I don't really care. Tongue


Cheers,
Drazzke.  Wink
Logged

Portfolio | (I'm Noel, AKA Drazzke)
blackmoon
--------------

Posts: 2



View Profile
« Reply #2 on: January 10, 2010 »

hello

i am really new to this as3 topic and flashdevelop.
i followed this tutorial and liked it. i think i understand the most of it.

but there is a problem so i can't test it.
when i change "world" into "level" in the main.as and want to test it i get this error.

..\test\Main.as(12): col: 27 Error: Access of undefined property level.
super(800, 600, 60, 2, level, false, true);
^
Build halted with errors (fcsh).   Cry

can you please help me?
Logged
BorrisMoose
....................
*
Posts: 25


View Profile Email
« Reply #3 on: January 10, 2010 »

You need to write level exactly as you named your class, so if you called it Level.as then write Level instead of level.
Logged
blackmoon
--------------

Posts: 2



View Profile
« Reply #4 on: January 10, 2010 »

well,

i've allready done this but it didn't change anything.
i think it must be some stupid mistake i made.

Main.as

package
{
   import punk.core.*;
   
   [SWF(width = "800", height = "600")]
   [Frame(factoryClass = "punk.core.Factory")]
   
   public class Main extends Engine
   {
      public function Main()
      {
         super(800, 600, 60, 2, Level, false, true);
      }
   }
}


level.as
package game
{
   
   import punk.core.Entity;
   import punk.core.World;
   import game.*;
   
   
   public class Level extends World
   {
      
      private var level1:array = new array(//you know what comes here);
      
      public function level()
      {
         
      }
      
      override public function init():void
      {
         var row:int = 0;
         var xx:int = 0;
         var width:int = 50;
         var tile:int = 16;
         for (var i:int = 0; i < level1.length; i += 1) {
            if (i / width == int(i / width)) { row += 1; }
            xx = (i - (row-1) * width) * tile;
            
            var e:Entity;
            if (level1 == 1) {
               add(e = new Player());
               e.x = xx;
               e.y = row * tile;

            }
            if (level1 == 2) {
               add(e = new Wall());
               e.x = xx;
               e.y = row*tile;
            }
         }

      }
      
   }

}


wall.as
package game
{
   import punk.Actor;
   
   public class wall extends Actor
   {
      [Embed(source = '../images/Wall.png')]
        private var imgWall:class;
      
      public function wall()
      {
         sprite = FP.getSprite(imgWall, 16, 16);
            setCollisionRect(16,16,0,0);
            setCollisionType("Wall");
      }
      
   }

}


player.as
package game
{
   import punk.Actor;
   import punk.core.SpriteMap;
   import punk.util.*;
   
   public class Player extends Actor
   {
      //load sprite and create the sprite variable
      [Embed(source = '../images/playerRight.png')]
         private var imgPlayerRight:Class;
         private var sprPlayerRight:SpriteMap = FP.getSprite(imgPlayerRight, 16, 16);
         
      [Embed(source = '../images/playerLeft.png')]
         private var imgPlayerLeft:Class;
         private var sprPlayerLeft:SpriteMap = FP.getSprite(imgPlayerLeft, 16, 16);
         

      
      public function Player()
      {
            //set the sprite
            sprite = sprPlayerRight;
            //set the delay
            delay = (30 / 4);
            //collision mask....
            setCollisionRect(12, 12, 2, 4);
   
            //keyboard controls.
            Input.define("right", Key.RIGHT);
            Input.define("left", Key.LEFT);
            Input.define("jump", Key.X);
      }
      
      override public function update():void
      {
         //move/jump
         if (Input.check("right")) { xspeed += aspeed; }
         if (Input.check("left")) { xspeed -= aspeed; }
         if ((Input.check("jump") && collide("Wall", x, y + 1)) { yspeed = - jspeed; }
         
         //actually move the player now
         for (var i:int = 0; i < Math.abs(xspeed); i += 1) {
            if (!collide("Wall", x + FP.sign(xspeed), y)) { x += FP.sign(xspeed); } else { xspeed = 0; break; }
         }
         for (i = 0; i < Math.abs(yspeed); i += 1) {
            if (!collide("Wall", x, y + FP.sign(yspeed))) { y += FP.sign(yspeed); } else { yspeed = 0; break; }
         }
yspeed += gspeed;

}
         

      
   }

}
Logged
BorrisMoose
....................
*
Posts: 25


View Profile Email
« Reply #5 on: January 10, 2010 »

Level should be in lowercase as you named it level.as. Also in the level.as file you have missed a closing bracket when declaring your array. On the line private var level1:array.

EDIT: OK, I just realised what you did there, ignore what I said about the bracket

EDIT2: Found the problem. You have named the file level.as, but called the class Level. You then try to construct level which does not exist. Change the line
Code:
public class Level extends World

to
Code:
public class level extends World
Logged
Noel
===========
****
Posts: 330



View Profile WWW Email
« Reply #6 on: January 10, 2010 »

OK, I have updated the tutorial today, to include downloads and fix some of the typos and bugs I had made last night.
I believe the error you are getting is because you don't have import game.Level at the top of the main.as (my fault, I forgot to add that in the tutorial). If you do that, and then have the correct name for everything, you should be good.

Cheers.
Logged

Portfolio | (I'm Noel, AKA Drazzke)
Carnivac
....................
*
Posts: 42



View Profile WWW
« Reply #7 on: January 12, 2010 »

How do you make it so it only jumps once per press of either jump button instead of holding down one of them making the character jump over and over?
Logged

BorrisMoose
....................
*
Posts: 25


View Profile Email
« Reply #8 on: January 12, 2010 »

There is an input pressed command in FlashPunk, just make sure that is set to false before allowing your player to jump.

Code:
if ((!Input.pressed("key") && Input.check("key"))
{
//jump code
}
Logged
Carnivac
....................
*
Posts: 42



View Profile WWW
« Reply #9 on: January 12, 2010 »

I tried adding that in but it doesn't seem to work.  The character still repeatedly jumps after landing if holding either jump key down.

Code:
//jumping
if ((!Input.pressed("up") && Input.check("up")) || (!Input.pressed("altUp") && Input.check("altUp")))
{
if (collide("floor", x, y + 1)) {
yspeed = -3.5;
}
}

if (!Input.check("up") && !Input.check("altUp") && yspeed < 0) {
yspeed += gspeed;
}

Have I put it in wrong?
Logged

easyname
....................
*
Posts: 40



View Profile Email
« Reply #10 on: January 12, 2010 »

Code:
//jumping
if ((Input.pressed("up") || Input.pressed("altUp")) && collide("floor", x, y + 1)
{
yspeed = -3.5;
}

if (!Input.check("up") && !Input.check("altUp") && yspeed < 0) {
yspeed += gspeed;
}
Should work I think.

Input.pressed only returns true if the key was pressed that frame, so what you were doing was only jumping if the key wasn't pressed that frame, which basically meant you jumped a frame late and still repeatedly jumped when holding down the jump button.
Logged
Carnivac
....................
*
Posts: 42



View Profile WWW
« Reply #11 on: January 12, 2010 »

Cheers, that works fine! 
Logged

Gornova81
===========
****
Posts: 271



View Profile WWW
« Reply #12 on: January 26, 2010 »

HI!
I've followed your tutorial and all works fine Cheesy
Some tips to make it more understable (IMHO):

- not say:

Code:
public var level1:Array = new Array(/*LEVEL ARRAY.. not going to include that again*/);

but include a simply "square room level", is strange to see nothing on screen first time, when i've copy/paste zero-array Cheesy

- "all in one line code" is not so clear, so for example:

Code:
if (Math.abs(xspeed) > mspeed) { xspeed = FP.sign(xspeed) * mspeed; }

could be

Code:
if (Math.abs(xspeed) > mspeed) {
   xspeed = FP.sign(xspeed) * mspeed;
}

- when it's written:

Code:
private var jspeed:Number = 3.6;

after in copy-past code is

Code:
private var jspeed:Number = -3.6;

jump-speed must be negative, right?


anyway, thanks for your tutorial!!!
Logged

Sos
--------------

Posts: 7


:]


View Profile Email
« Reply #13 on: January 26, 2010 »

Neat, I'm liking FP even more now Smiley
Logged
Jim
....................
*
Posts: 26


Yep, thats what she said


View Profile
« Reply #14 on: January 26, 2010 »

Really helpful thanks.
Logged
Pages: [1] 2 3 ... 5
  Print  
 
Jump to:  

Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC