Pages: [1] 2
  Print  
Author Topic: draw_healthbar() function  (Read 6161 times)
Offline (Unknown gender) TrieBr
Posted on: December 07, 2009, 01:24:44 AM

Member
Joined: Dec 2009
Posts: 8

View Profile Email
I have seen Enigma around for quite a while now. Today I finally decided to try it out, and frankly I'm quite speechless. Anyway.. I don't want to ramble on about how much I like Enigma, but I would like to show you a function I created, and share it with you.

I have created a draw_healthbar() function, and from what I can see, its identical the Game Makers function (I'm hoping someone can prove me otherwise!).

So, open up "SHELL\Graphics_Systems\GMstdraw.h" and add the following function:

Code: [Select]
int draw_healthbar(double x1,double y1,double x2,double y2,double amount,double backcol,double mincol,double maxcol,int direction,int showback,int showborder)
{
    if (amount > 100){ amount = 100; }
    if (amount < 0){ amount = 0; }
    if (!(direction > -1 && direction < 4)) { direction = 0; }
        enigma::untexture();
            glPushAttrib(GL_CURRENT_COLOR);
                glBegin(GL_LINE_LOOP*showborder | GL_QUADS * !showborder );
                  glColor4f(__GETR(0)/255.0,__GETG(0)/255.0,__GETB(0)/255.0,enigma::currentcolor[3]);
                    glVertex2f(x1,y1);
                    glVertex2f(x2,y1);
                    glVertex2f(x2,y2);
                    glVertex2f(x1,y2);
                glEnd();
        if (showborder>0)
        {
            x1+=1;
            y1+=1;
        }
        if (showback>0)
        {
            glBegin(GL_LINE_LOOP | GL_QUADS );
              glColor4f(__GETR(backcol)/255.0,__GETG(backcol)/255.0,__GETB(backcol)/255.0,enigma::currentcolor[3]);
                glVertex2f(x1,y1);
                glVertex2f(x2,y1);
                glVertex2f(x2,y2);
                glVertex2f(x1,y2);
            glEnd();
        }
        switch (direction)
        {
         case 0:
            x2 = x1+((x2-x1)*(amount/100));
         break;
         case 1:
            x1 = x2-((x2-x1)*(amount/100));
         break;
         case 2:
            y2 = y1+((y2-y1)*(amount/100));
         break;
         case 3:
            y1 = y1+((y2-y1)*((100-amount)/100));
         break;
        }
        double colDraw = mincol;
        int Rl,Gl,Bl,Rh,Gh,Bh;
        Rh = __GETR(maxcol);
        Gh = __GETG(maxcol);
        Bh = __GETB(maxcol);
        Rl = __GETR(mincol);
        Gl = __GETG(mincol);
        Bl = __GETB(mincol);
        Rl = (int)(Rl + ((Rh-Rl)*(amount/100)));
        Gl = (int)(Gl + ((Gh-Gl)*(amount/100)));
        Bl = (int)(Bl + ((Bh-Bl)*(amount/100)));
        colDraw = ((Bl<<16)|(Gl<<8)|Rl);
            glBegin(GL_LINE_LOOP | GL_QUADS );
              glColor4f(__GETR(colDraw)/255.0,__GETG(colDraw)/255.0,__GETB(colDraw)/255.0,enigma::currentcolor[3]);
                glVertex2f(x1,y1);
                glVertex2f(x2,y1);
                glVertex2f(x2,y2);
                glVertex2f(x1,y2);
            glEnd();
        if (showborder>0)
        {
            glBegin(GL_LINES);
              glColor3f(0,0,0);

                switch (direction)
                {
                 case 0:
                     glVertex2f(x2,y2);
                     glVertex2f(x2,y1);
                 break;
                 case 1:
                     glVertex2f(x1,y1);
                     glVertex2f(x1,y2);
                 break;
                 case 2:
                     glVertex2f(x2,y2);
                     glVertex2f(x1,y2);
                 break;
                 case 3:
                     glVertex2f(x1,y1);
                     glVertex2f(x2,y1);
                 break;
                }
            glEnd();
        }

        glPopAttrib();
    return 0;
}

Also, don't forget to add
Quote
int draw_healthbar(double x1,double y1,double x2,double y2,double amount,double backcol,double mincol,double maxcol,int direction,int showback,int showborder)
to your fnames.txt file.

I would love to hear comments and criticism! My function looked quite lenghty compared to the other drawing functions, so I may have done it rather inefficiently. I would definitely love to hear your comments on how I can compact it a little bit more.


I would also like to add that I'm very new to this forum. If I have posted this in the wrong section, please forgive me and kindly move it  :)

Logged
Offline (Male) Josh @ Dreamland
Reply #1 Posted on: December 07, 2009, 02:42:36 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Glad you liked ENIGMA. ^_^

Anyway, the function looks sound, aside from a few things I'd const.
Code: [Select]
        int Rl,Gl,Bl,Rh,Gh,Bh;
        Rh = __GETR(maxcol);
        Gh = __GETG(maxcol);
        Bh = __GETB(maxcol);
        Rl = __GETR(mincol);
        Gl = __GETG(mincol);
        Bl = __GETB(mincol);
        Rl = (int)(Rl + ((Rh-Rl)*(amount/100)));
        Gl = (int)(Gl + ((Gh-Gl)*(amount/100)));
        Bl = (int)(Bl + ((Bh-Bl)*(amount/100)));

I would make that snippet
Code: [Select]
        const int
        Rh = __GETR(maxcol),
        Gh = __GETG(maxcol),
        Bh = __GETB(maxcol),
        RL = __GETR(mincol),
        GL = __GETG(mincol),
        BL = __GETB(mincol);
        const int
        Rl = (int)(RL + ((Rh-RL)*(amount/100))),
        Gl = (int)(GL + ((Gh-GL)*(amount/100))),
        Bl = (int)(BL + ((Bh-BL)*(amount/100)));

The compiler would probably take care of all that anyway, even if left inline, so it doesn't really matter.
Come to think of it, that's probably the most efficient code I've had submitted. (Sorry, Retro. I won't hold frac() against you)/

Oh, one more thing. Your switch statement. Find out which direction GM defaults.

I'm personally tickled to see another someone's taken interest in the program, especially one that knows some C++. (Or, perhaps is brave enough to use GML knowledge to make a C++ function).

Out of curiosity, are you working with the code that comes with R3 or the code from the SVN repo? Judging by the __, I'd say it's the R3 version. In either case... When I get home, I'll take a closer look at your function and see about incorporating it into R4. I'll credit your current username for it; if you want it under a different name, let me know.

(And yes, those of you who are elitist and don't consider one function a significant contribution, I know it's not much relative to the entire project. However, it's nothing to sneeze at, and if we had 900 more people like Revel, the project would be done already.)
« Last Edit: December 07, 2009, 02:45:07 PM by Josh @ Dreamland. » Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TrieBr
Reply #2 Posted on: December 07, 2009, 06:50:42 PM

Member
Joined: Dec 2009
Posts: 8

View Profile Email

Glad you liked my contribution! You are correct when you say I am using R3. I didn't find out about the SVN until afterward which I may get later.  ::)

Oh, one more thing. Your switch statement. Find out which direction GM defaults.
GM defaults to direction 0. The thought never passed through my mind to use the default case, but the code is already included to make it default to 0:
Code: [Select]
if (!(direction > -1 && direction < 4)) { direction = 0; }..Though its probably a lot less efficient then using a default case. I'll probably edit the code later tonight with your suggestions.

Quote
I'll credit your current username for it; if you want it under a different name, let me know.
It probably doesn't matter, but my full name is Brad Triebwasser, just in case the credit list follows a specific format  :)


I really hope I can make some more contributions! I'll probably keep posting some functions that aren't being developed according to progress page. Again, this is a wonderful project  ;)
« Last Edit: December 07, 2009, 09:00:49 PM by Revel » Logged
Offline (Male) RetroX
Reply #3 Posted on: December 07, 2009, 07:50:22 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Speaking of Switch, Josh, does ENIGMA have a working switch() for strings, yet?
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Female) IsmAvatar
Reply #4 Posted on: December 08, 2009, 01:14:19 AM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 891

View Profile Email
I think the progress page is pretty outdated. Josh is making the CFile parser largely so that he can automate the progress page.
Logged
Offline (Unknown gender) TrieBr
Reply #5 Posted on: December 08, 2009, 01:22:41 AM

Member
Joined: Dec 2009
Posts: 8

View Profile Email
I think the progress page is pretty outdated. Josh is making the CFile parser largely so that he can automate the progress page.

I've noticed. Even though I am on R3 rather than the SVN, I have noticed a lot of functions are marked as complete, but aren't actually implemented (in my version anyway) and vise versa.

I would love to work on the ini file functions, since I created created a nice DLL for Game Maker that worked with ini files and was quite successful. I could easily implement the C++ code into ENIGMA.

Logged
Offline (Male) Josh @ Dreamland
Reply #6 Posted on: December 08, 2009, 05:28:30 AM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Retro:
I think on account of my own forgetfulness, ENIGMA doesn't have any form of working switch(). It replaces them with some functions that I *believe* were never implemented. But if I did implement those three functions, it'd work. I believe GM switch() statements share complexity with a string of if()s, so that's what ENIGMA does. Ideally, I want to optimize the code, only replacing switch with if()s when I can't tell that all case labels and the input are integers.

Revel:
I'd love that. I made some kind of text file implementation that I never documented (in any form, I mean), but I never did do INI. Is your code GPL?
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) score_under
Reply #7 Posted on: December 08, 2009, 12:21:21 PM

Member
Joined: Aug 2008
Posts: 308

View Profile
Hm, does declaring the int as const allow for any real optimization?
Logged
Offline (Male) Josh @ Dreamland
Reply #8 Posted on: December 08, 2009, 04:29:12 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Supposedly. I don't know the particulars.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TrieBr
Reply #9 Posted on: December 08, 2009, 07:13:02 PM

Member
Joined: Dec 2009
Posts: 8

View Profile Email
Quote
I'd love that. I made some kind of text file implementation that I never documented (in any form, I mean), but I never did do INI. Is your code GPL?

I have a few questions. How would I be able to throw an error (eg. if you try and do operations without opening the ini file first)? Secondly, how could I define a global variable? Would I just declare it in the enigma namespace? For example, ini_open() could set a global variable such as "iniOpen = true", and later functions could check if "iniOpen = true" before doing operations. I haven't really looked at the whole structure of ENIGMA, since I have just been experimenting with simple functions...

Edit:
Yes my code is GPL  ;)
Logged
Offline (Male) Josh @ Dreamland
Reply #10 Posted on: December 08, 2009, 09:24:06 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Use show_error as GM defines it. I'm not sure how liberally that function is implemented in R3, but it'll be alive in full force for R4. If nothing else, implement it yourself in your code (int show_error(string e,int fatal) { cout << "error: "<<e<<endl; return fatal; }), and I will make sure it doesn't throw a linker error before R4 is released (Or you can, really. I trust you'll know how).

Also, good to know it's GPL.
« Last Edit: December 08, 2009, 09:26:26 PM by Josh @ Dreamland » Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TrieBr
Reply #11 Posted on: December 08, 2009, 10:15:33 PM

Member
Joined: Dec 2009
Posts: 8

View Profile Email
Use show_error as GM defines it. I'm not sure how liberally that function is implemented in R3, but it'll be alive in full force for R4. If nothing else, implement it yourself in your code (int show_error(string e,int fatal) { cout << "error: "<<e<<endl; return fatal; }), and I will make sure it doesn't throw a linker error before R4 is released (Or you can, really. I trust you'll know how).

Also, good to know it's GPL.

Ive been working on moving my code over from my DLL project over to ENIGMA. I couldn't help but notice, the file for my code is 16kb (the largest file in the "Universal_System" directory)  :( . However, my code works differently then GM. The ini file's contents are loaded into the ram for faster access (mainly because the file doesn't have to be re-parsed/rewritten for every operation). It also allows for multiple ini files to be opened at the same time. I'll probably continue just moving it over into ENIGMA, and then optimize/shorten it at a later time (if possible). The functionality seems to be working great so far  :)
Logged
Offline (Male) Josh @ Dreamland
Reply #12 Posted on: December 08, 2009, 10:48:49 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Most of the things you can do by loading it into memory can be done with BUFSIZ buffers loaded one at a time, and fseek(), but I'll trust your judgment, especially if the benchmarks are similar.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TrieBr
Reply #13 Posted on: December 08, 2009, 11:10:35 PM

Member
Joined: Dec 2009
Posts: 8

View Profile Email
Most of the things you can do by loading it into memory can be done with BUFSIZ buffers loaded one at a time, and fseek(), but I'll trust your judgment, especially if the benchmarks are similar.

I have never heard of BUFSIZ before... You would still have to parse the contents each time wouldn't you? With my method, all of the sections / keys are parsed when the file is initially opened. The sections/keys are then loaded into Section classes, which each contain a list of Keys which can then be easily modified. Once the ini file is closed (ini_close()), the ini file is then re written to the hard drive, and the memory is unloaded. Again, the drawback with this method is the number of lines required (over 600 so far), and therefore more compile time. All of this is probably unnecessary, since ini files should be used for relatively small configuration files anyway.


Edit:
I'll post the current code I have here, so you can have a look:
http://pastebin.com/m305ac32d
I know its quite messy, with no comments.. I'm relatively new with C++ so maybe I have completely missed something in terms of efficiency (since its over 650 lines).
« Last Edit: December 08, 2009, 11:23:59 PM by Revel » Logged
Offline (Male) Josh @ Dreamland
Reply #14 Posted on: December 09, 2009, 06:58:43 AM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
You know, I gave it some thought, and I think that although what you're doing wouldn't be good for small peeks into big files, it's best to do what you're doing now. You use a good deal of C methods in it, such as strcmp rather than std::string's assortment of goodies. Is this to save the eight byte prefix? I'm thinking that string::operator== may be faster than strcmp in most cases, at the cost of the eight bytes.

I'd inline swapints, but I think GCC will do that for you (Inline void instead of void).

Overall though, the code is good. You seem to have a good grasp of the language, regardless of how long you've been using it.

When you are done, you can either take a whack at this or I'll do it later, it doesn't matter: I'm thinking that to improve speed for bigger files (at the cost of a deal of memory) you could use std::map either alongside or instead of your linked list, chain. Using it as an alternative will alphabetize everything, which you may not want. Using it alongside will save on lookup (no iterating every chain).
in the class,
map<string,Section*> sections;
typedef map<string,Section*>::iterator sec_it;

Then FindSection will be
{
  sec_it it = sections.find(sectname);
  if (it != sections.end())
    return it->second;
  return NULL;
}

It'd make your life easier, anyway. If you were specifically avoiding map so it wouldn't alphabetize things, the code's basically perfect. (I can't remember if GM does so or not, sadly). One last thing I'd recommend is adding the license at the top. ;)

Oh, and I'm used to working with no comments. Your code was rather clean and easy to navigate.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Pages: [1] 2
  Print