Sign in to follow this  
zuluu

AS3 Player level progression bar

Recommended Posts

I'm trying to make a Player level bar to show whenever experience is gained, it will show progress.

Like this,

|/////----| where //// is experience progress and the --- are the space left to level up.

As of now, I'm using an object Shape to represent the bar and scaleX but that's when things got really complicated.

So here's the code segment.

totalXP += Math.floor(playerLvl + 300 * Math.pow(2, playerLvl/ 7));
lvlExperience = Math.floor(totalXP / 4);

 

So the level pyramid goes like:

playerLvl 1 - 83 lvlExperience
playerLvl
2 - 174 lvlExperience
playerLvl
3 - 276 lvlExperience and so fourth.

 

The lvlbar:

var int:someWidth;
var int:someHeight;
lvlbar.graphics.beginFill(0x00FF00, 1);
lvlbar.graphics.drawRect(0, 0, someWidth, someHeight);
lvlbar.graphics.endFill();
addChild(lvlbar);

 

So I have a variable that counts the experience, and if the experience is greater than lvlExperience then playerLvl increases.

experience += 5;
if (experience > lvlExperience)
{
playerLvl++;
lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;

 

The problem with this is that lvlbar.scaleX will change lvlbar.someWidth to show the shape's X coordinate to be at 83, then at 174 and eventually covering the whole X-axis of the screen. I want to cap it to show only at a fixed X coordinate, at 100 for example, at the left side of the screen. Which means that the lvlbar will increment from X = 0 to X = 100 and then start over again at 0 when the Player has leveled up. So then I tried another formula:

lvlbar.scaleX = experience / 100;

 

But then it doesn't work either because experience will be automatically greater than 100 after level 2, which won't reset the progress lvlbar back at 0. How can I get lvlbar to show the experience progress but have it scaled every time the player levels up?

Would there be another way/alternative to show the Player's level progress? Is there another formula that can wrap this around?

Share this post


Link to post
Share on other sites

Take smaller steps in deriving the value to draw:

def ComputeBase(player_level):
    return ...  # Lowest number of points for a player at 'player_level'

base_level = ComputeBase(current_player_level)
highest_level = ComputeBase(current_player_level + 1) - 1
points_at_level = highest_level - base_level
fraction = (experience - base_level) / points_at_level

draw(0.. somewidth * fraction)
Edited by Alberth

Share this post


Link to post
Share on other sites

 

Take smaller steps in deriving the value to draw:

def ComputeBase(player_level):
    return ...  # Lowest number of points for a player at 'player_level'

base_level = ComputeBase(current_player_level)
highest_level = ComputeBase(current_player_level + 1) - 1
points_at_level = highest_level - base_level
fraction = (experience - base_level) / points_at_level

draw(0.. somewidth * fraction)

So I've tried plugging in the values but I got a bit more confused at the end. Currently what I have in order to gain experience is by hitting enemies with a bullet and each time it hits, the player gains +5 experience. 

The collision code to detect the enemy and missile is a bit chunky so I'll skip that, but the code below the collision statement goes:

experience += 5; // so each time the player kills an enemy, experience = experience + 5;

output = Math.floor(playerLvl+300*Math.pow(2,playerLvl/7)); // just some formula that calculates a steady experience curve
lvlExperience = Math.floor(output / 4); // So this will give the total experience required for next level, ie, playerLvl = 1 requires 83 experience to level up at 2.
if (experience >= lvlExperience)

{
   playerLvl++;
   lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;

so if I use:

fraction = (experience - base_level) / points_at_level

That means that for an example:

fraction = (5 - 83) / (174 - 83);
fraction = -78 / 91

I could use Math.absolute for the numerator but I don't understand why experience has to minus base_level? 

For the variable someWidth, this value represents how much it's size will show and lvlbar.scaleX will scale.
So if:

someWidth = 1;

Then depending on the value of lvlbar.scaleX, for example, 

lvlbar.scaleX = 5; // This will show the width of the Shape lvlbar, so every increment of lvlbar.scaleX = 5 will increase someWidth by 1 until someWidth reaches to 100.

lvlbar.scaleX is the only method I know of that can change the width of an object to show the progress bar.  
 

Edited by zuluu

Share this post


Link to post
Share on other sites
So I've tried plugging in the values but I got a bit more confused at the end.

Plugging in values without understanding what you're doing is a very good way to get very confused. Do yourself a big favour, and stop doing that.

 

If you don't understand something, stop plugging, and start thinking what you're missing, or what exactly is not making sense. Try to find an answer to that problem first, before trying to use it. It may seem like a longer route, but you'll gain much more understanding of it all, so if there is a problem later (that you have to debug), or when you need something similar in the future again, it's much simpler to reproduce and adapt to the new situation.

 

Now, on to your problem.

if (experience >= lvlExperience)
{
   playerLvl++;
   lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;

This makes no sense to me. Why are you doing "lvlbar.scaleX = 0;" sometimes, and then always "lvlbar.scaleX = experience;" ?

Didn't you say experience only increases, while the level bar should increase up to some width? So how does "lvlbar.scaleX = experience;" do that? I don't see how it ever can.

 

It looks to me like you are having several conflicting ideas here. On the one hand, it's the length of the bar, on the other hand, it's experience, but not really. If code is wrong, don't keep it, at least comment it out, so it doesn't affect your results any more, but best is complete removal. Wrong code doesn't deserve to live, not even as comment.

 

What may help here is to make a list of variables, and write down what they mean, and perhaps what the valid range of values is. That may give you a more solid foundation for your calculations.

 

 

Your fraction calculation is messed up, because your ComputeBase doesn't do what I said it should do:

fraction = (experience - base_level) / points_at_level

That means that for an example:

fraction = (5 - 83) / (174 - 83);
fraction = -78 / 91

You return the wrong value from ComputeBase. I said "Lowest number of points for a player at 'player_level'" I would hope that is 0 for the first level, rather than 83. The fraction then becomes (5-0)/(83-0) = 5/83

Edited by Alberth

Share this post


Link to post
Share on other sites

 

So I've tried plugging in the values but I got a bit more confused at the end.

Plugging in values without understanding what you're doing is a very good way to get very confused. Do yourself a big favour, and stop doing that.

 

If you don't understand something, stop plugging, and start thinking what you're missing, or what exactly is not making sense. Try to find an answer to that problem first, before trying to use it. It may seem like a longer route, but you'll gain much more understanding of it all, so if there is a problem later (that you have to debug), or when you need something similar in the future again, it's much simpler to reproduce and adapt to the new situation.

 

Now, on to your problem.

if (experience >= lvlExperience)
{
   playerLvl++;
   lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;

This makes no sense to me. Why are you doing "lvlbar.scaleX = 0;" sometimes, and then always "lvlbar.scaleX = experience;" ?

Didn't you say experience only increases, while the level bar should increase up to some width? So how does "lvlbar.scaleX = experience;" do that? I don't see how it ever can.

 

It looks to me like you are having several conflicting ideas here. On the one hand, it's the length of the bar, on the other hand, it's experience, but not really. If code is wrong, don't keep it, at least comment it out, so it doesn't affect your results any more, but best is complete removal. Wrong code doesn't deserve to live, not even as comment.

 

What may help here is to make a list of variables, and write down what they mean, and perhaps what the valid range of values is. That may give you a more solid foundation for your calculations.

 

 

Your fraction calculation is messed up, because your ComputeBase doesn't do what I said it should do:

fraction = (experience - base_level) / points_at_level

That means that for an example:

fraction = (5 - 83) / (174 - 83);
fraction = -78 / 91

You return the wrong value from ComputeBase. I said "Lowest number of points for a player at 'player_level'" I would hope that is 0 for the first level, rather than 83. The fraction then becomes (5-0)/(83-0) = 5/83

 

 

Ah I see, that makes a lot more sense now. Sorry about that, I believe I rushed things through without understanding the context of it.
 


This makes no sense to me. Why are you doing "lvlbar.scaleX = 0;" sometimes, and then always "lvlbar.scaleX = experience;" ?

Didn't you say experience only increases, while the level bar should increase up to some width? So how does "lvlbar.scaleX = experience;" do that? I don't see how it ever can.



So lvlbar is a rectangle shape that represents and draws out the progress bar of the player's level. The width of it represents how big the rectangle's width is. So what lvlbar.scaleX does, it changes the width of the rectangle so if I were to increase the value of lvlbar.scaleX, the rectangle's width will be bigger and thus showing the shape as a progress bar.

let's say someWidth = 1;
and lvlbar.scaleX = experience;

The rectangle is merely a pixel, can't see much so it'll be a completely empty rectangle. When experience increases, then lvlbar.scaleX will change someWidth of lvlbar to be bigger in it's width, which will help me represent how a player levels when experience is accumulated.

To my understanding so far, because I have experience to only increment by 5 each time which means the lvlbar will grow 1 px size each time. The problem is that I need this lvlbar to only show it's width from 0 to 100 only. Such that it will represent how a progress bar does when a player level's up. The progress resets.

So that's when:

 if (experience >= lvlExperience)

{
   playerLvl++;
   lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;

As experience accumlates, if it's greater than the required lvlExperience then player has leveled up and resets the lvlbar.scaleX back to 0. If we don't reset it back to 0, the rectangle shape will continuously grow across the screen covering the important details of the game. 

This is what's conflicting because I don't know/can't think of any way to show the lvlbar from x = 0 to x = 100 only and lvlbar.scaleX is the only method that allows me to change the width of the shape during run time. 

Edited by zuluu

Share this post


Link to post
Share on other sites
 if (experience >= lvlExperience)
{
   playerLvl++;
   lvlbar.scaleX = 0;
}
lvlbar.scaleX = experience;
As experience accumlates, if it's greater than the required lvlExperience then player has leveled up and resets the lvlbar.scaleX back to 0. If we don't reset it back to 0, the rectangle shape will continuously grow across the screen covering the important details of the game.

 

Ah right. I see your intention, but unfortunately, this is not doing any good.
 
To understand, assume you have a nice wooden chair. It has a nice white colour. You also have 2 colours of paint, white and black, and you hired a very fast painter. She can paint the entire chair in 1 micro-second, that is, in 1/1000000th of a second, REALLY fast thus. Now, usually she paints the chair white, so what you see is a white chair.
 
Every now and then however, she first paints it black, and then immediately paints it white again. The question is, do you ever see a black chair?

(Think of an answer now)

 

 

 

 

The answer to that question is "no". Your eyes aren't fast enough to see it. The colour of the top-level layer paint always wins.
 
The same thing happens with

lvlbar.scaleX = 0; // The 'if' was true, and I am interested only in how 'lvlbar.scaleX' changes, so I removed everything else.
lvlbar.scaleX = experience;

You assign 0, and then immediately assign "experience". Do you ever see that 0? Nope, while the value is 0 for a fraction of a second (if the compiler didn't delete the statement), the last assigned value wins, just like the last painted colour on the chair wins.
You can try by deleting the "lvlbar.scaleX = 0;" statement, it shouldn't make any difference whatsoever.

 

let's say someWidth = 1;
and lvlbar.scaleX = experience;

The real problem is however in the last line. You want "lvlbar.scaleX" to run from 0 to 100 (or so), while "experience" runs from 0 to somewhere near infinity.
Making "lvlbar.scaleX" equal to "experience" won't ever work, as the upper limits are not the same.

Your idea is however (as far as I understand it), that the level bar shows the experience for the current level only, while the "experience" variable is the total experience of the player over all levels.
(the name of the "experience" variable is a bit misleading here, perhaps "total_experience" or "summed_experience" or so would be better??)

In other words, you need a conversion from total experience to 'experience at this level'. This is what my "ComputeBase" did. It computes the lowest amount of experience for the current level.

lowest_experience_at_level = ComputeBase(playerLvl);
experience_at_current_level = experience - lowest_experience_at_level;

At the first level, 'lowest_experience_at_level' is 0, making 'experience_at_current_level' the same as 'experience'.

When you reach the upper limit of 'lvlExperience', the 'playerLvl' increases (with your 'if'), ComputeBase computes 83 (iirc) instead of 0, and 'experience_at_current_level = experience - lowest_experience_at_level;' becomes 'experience - 83', which is again the amount of experience at the (new) current level.

 

If you cannot see (and perhaps also if you do see, just as an exercise), write a small program (less than 50 lines, usually) with only a small while loop, that increases experience by, say, 5 each iteration, and updates all the variables, and print the experience, playerLvl, lowest_experience_at_level, and experience_at_current_level. I often write such simple test programs, to check it is really working as intended. It works nicely, as it concentrates on the experience and player levels, without having to drag all the other code of the game around. Modifications are fast and easy that way.

 

The other point is that the amount of experience needed to level up increases. That means that the upper limit of 'experience_at_current_level' increases at higher levels. To fix, you need to scale your 'experience_at_current_level' to the width of the level bar. That's what my fraction code does. The fraction runs from 0 to 1 (floating point) for each level, by multiplying by the desired max width of the level bar you get a number between 0 and your maximum.

See if you can figure it out, and let me know :)

Edited by Alberth

Share this post


Link to post
Share on other sites

Wow, you sir are a genius! It works! I used your ComputeBase, and the formula, and then used lvlbar.scaleX = fraction * 100

So the rectangle will go from x = 0 to x = 100 from my if statement. Wow I'm still amazed how simple this was. You know, I was once told that, we should never make simple things complicated, we should make complicated things simple. I over complicated everything haha while you had the solution from the very beginning. Thank you so much! I hope everyone who come across this thread will realise how to solve a problem with your methods and philosophy!

Share this post


Link to post
Share on other sites

Ha, glad you got it working!

 

Wow, you sir are a genius!
Well, not really, my not so secret weapon is math, simple linear computations with +, -, and *  :)

 

Your trouble was making the assumption "lvlbar.scaleX = experience" somewhere much earlier in time, and from there you stayed on that path, fiddling around to make it work, which would never have given a good result, since your basic assumption was wrong.

People have a natural tendency not to leave a path they chose in the past. Learning programming is to a large part learning that anything can be wrong, including ideas you had a some time ago, or paths you are on, that seemed good.

Recognizing for yourself that you are in such a situation is more tricky though, it needs the experience of being there, a couple of times :)

 

I came in new, without knowledge of your assumptions, ideas, and paths you had chosen. In that situation it is much simpler to point at a different direction that should work at first sight (I didn't have to un-assume "lvlbar.scaleX = experience" first).

Getting you "unstuck" from your chosen path was more work :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this