AGS: Can I Make an RPG with AGS?

Started by TerranRich, Mon 03/05/2004 05:56:47

Previous topic - Next topic

derboo

1. I guess that might be the only way right now, though it would be nice to be able to go with the Engine, not against it...

2. Actually, I would like to use hotspots... though it certainly would be cleaner to be able to set the hotspots in runtime, too.

Khris


derboo

#222
Actually, with the RPG Maker Engine, I'd have much more Problems to do what I'm imagining...

FIFE would be a good engine probably, but it seems far too complicated for me...

.M.M.

#223
Hi can I set one side of slider black? I have sliders fo displaying HP and Mana and they work OK, but if value is not at maximum, there is stil my red or blue background slider image. I want to right, empty side, will be black. Please, how to do it?

Khris

You can't use different colors afaik.
However, you can use buttons and draw their images on the fly.
I'm too lazy right now to provide some code, basically you use a global DynamicSprite, draw the gauge image on its DrawingSurface, then set the DynSprite as the button's image.

thom0512

I have an RPG-related question regarding a battle I am working on.  I am creating it similar to what was used in the MOTHER series.  Again, I did research this issue before I asked, and I am sure there is a much easier way to script this than the way I did, but oh well.

When my character picks a specific dialog option, he will trigger a fight and will change rooms to the "battle screen" room.  I am using default display messages to let the player know of what goes on during the battle.  I have a GUI off to the side of my room, displaying different actions for the player to pick...attack, defend, run, etc.  I made the main character's and the enemy's health bars with 4 GUIs each: full, 2/3 full, 1/3 full, and empty.  So that totals eight.  The GUIs are marked as gVitals; 1-4 is for the main character, and 5-8 is for the enemy.  Here is the basic script I have so far regarding the battle, with only the main character (Ron) being able to take damage:

function gRobber1_OnClick(GUI *theGui, MouseButton button)
{
Display("Ron throws a punch!");{
int ran=Random(2);
if (ran==0) Display("Just misses!");
else if (ran==1) Display("The robber dodges out of the way quickly!");
else Display("10 HP damage dealt to the robber!");
}
Display("The robber charges at Ron!");{
int ran=Random(2);
if (ran==0) Display("Just misses!");
else if (ran==1) Display("Ron dodges out of the way quickly!");
else Display("10 HP damage given to Ron!");
}}


Display("10 HP damage given to Ron!");{
  if (gVitals1.Visible == true) {
  gVitals1.Visible=false;
  gVitals2.Visible=true;
}
else if (gVitals2.Visible == true) {
  gVitals2.Visible=false;
  gVitals3.Visible=true;
}
else if (gVitals3.Visible == true) {
  gVitals3.Visible=false;
  gVitals4.Visible=true;
  Display("Ron loses the fight.");
  cRon.ChangeRoom(17);
}}

I realize that the bottom portion of the script technically does not fit.  I just threw it in there to show what I want to happen only when a character is hit by an attack.

I am using random effects for the moment until I think of something better.  My problem is that I want the "gVitals" to change only when the main character or the enemy takes damage, or when it is displayed that "10 HP dealt to **", etc.  Right now it just gives Ron 10 HP damage every turn he gets during the battle, and I want to fix this.  Hopefully this makes sense.

Any help would be greatly appreciated.  If I am not clear, please let me know and I'll elaborate as best as I can.  Thank you!

Khris

#226
In the function, there this line:
Code: ags
else Display("10 HP damage given to Ron!");


Replace that with:
Code: ags
  else {
    Display("10 HP damage given to Ron!");
    ron_gets_hit(10);
  }

Now put this above the function:
Code: ags
function ron_gets_hit(int damage) {
  ...
}


Put in there what you want to happen.

Btw, as explained in my previous post, you can use a single button to display a health gauge. Four GUIs is overkill.
Familiarize yourself with the DynamicSprite and DrawingSurface functions.

You'd do something like:
Code: ags
int ron_hp = 100;
DynamicSprite*ron_gauge;

function ron_gets_hit(int damage) {
  ron_hp -= damage;
  if (ron_hp < 0) ron_hp = 0;
  ron_gauge = DynamicSprite.CreateFromExistingSprite(btnHealth.NormalGraphic);
  DrawingSurface*ds = ron_gauge.GetDrawingSurface();
  ds.DrawingColor = 16; // black
  ds.DrawRectangle(0, 0, 99, 15);  // clear gauge
  ds.DrawingColor = Game.GetColorFromRGB(0,255,0); // green
  ds.DrawRectangle(0, 0, ron_hp, 15); // draw health
  ds.Release(); // end drawing
  btnHealth.NormalGraphic = ron_gauge.Graphic;
}

EDIT: fixed code


Now create a button 100 pixels wide and 15 high called "btnHealth" on a GUI.

thom0512

Thanks, KhrisMUC, for your quick response.

I got rid of the GUI health bars except for one, where I put a button on it, called btnHealth.  I only want my character to start out with 30 HP, so I am assuming that a pixel is equivalent to a hit point in this case.  So I made the button 30 pixels wide and 5 high (a "landscape" health bar).

I copied and pasted the new code into the global script and, in some instances, the room script where the function was not recognized.  The game starts out okay, but whenever I run into:

ron_gets_hit(10);

...the game crashes.  It says that the error is "null pointer referenced" and that part of the problem is this:

DrawingSurface *ds = ron_gauge.GetDrawingSurface();

...which is part of the code that I tried out.  I searched the forum for what "null pointer referenced" means but didn't find anything that helped me with this situation.  What am I doing wrong?

Khris

Ok, alternatively you could make the button 60 pixels wide, then draw to ron_hp*2.

Regarding the second problem, I was already afraid that's gonna happen.
The problem is that the DynamicSprite is null, or nothing, an empty slot, if you will, so one can't call its .GetDrawingSurface() method.

Do this: draw a properly sized sprite, a green rectangle of 30x15. Import it, then assign it as the button's normal image.
Now directly above the error throwing line, add:
Code: ags
  ron_gauge = DynamicSprite.CreateFromExistingSprite(btnHealth.NormalGraphic);

thom0512

#229
All right...I'm about there.  I'm able to have a health bar that can decrease based on the number of hit points put in a specific part of the script.  It all works fine, but my last question for now is how I am able to have the health bar run out of HP and therefore end in a "game over."  The script just keeps a single hit point in the health bar, no matter how much damage Ron takes, and I'd like to change this.

By the way, KhrisMUC, the DynamicSprite and DrawingSurface functions have been extremely useful.  I knew there was a way from the start to have a button serve as a health bar, instead of the GUIs, but there have been so many examples explained on the forum I was lost as far as how to place that into the global script.  I really appreciate the help.

Khris

No problem :)

Here's some adjusted code:
Code: ags
function ron_gets_hit(int damage) {
  ron_hp -= damage;
  if (ron_hp < 0) ron_hp = 0;
  ron_gauge = DynamicSprite.CreateFromExistingSprite(btnHealth.NormalGraphic);
  DrawingSurface*ds = ron_gauge.GetDrawingSurface();
  ds.DrawingColor = 16; // black
  ds.DrawRectangle(0, 0, 99, 15);  // clear gauge
  ds.DrawingColor = Game.GetColorFromRGB(0,255,0); // green
  if (ron_hp > 0) ds.DrawRectangle(0, 0, ron_hp, 15); // draw health        only draw health if > 0
  ds.Release(); // end drawing
  btnHealth.NormalGraphic = ron_gauge.Graphic;

  // kill ron
  if (ron_hp == 0) player.ChangeRoom(666);    // or play death animation, or ...
}

thom0512

#231
I have one last question for the moment.  The health bar is up and running and it all works great.  I would like to include some inventory items in my game that if they are used with the character, Ron gains HP.  I have created a first-aid kit, and here is the code I have to have Ron recover health, rather than lose it.

Code:
function ron_heals(int amount) { // function used to have Ron recover health
  ron_hp += amount;
  if (ron_hp < 0) ron_hp = 0;
    btnHealth.Width = ron_hp;
    ron_gauge = DynamicSprite.CreateFromExistingSprite(btnHealth.NormalGraphic);
    DrawingSurface*ds = ron_gauge.GetDrawingSurface();
    ds.DrawingColor = 16; // black
    ds.DrawRectangle(0, 0, 99, 15);  // clear gauge
    ds.DrawingColor = Game.GetColorFromRGB(0,255,0); // green
    ds.DrawRectangle(0, 0, ron_hp, 15);
    ds.Release(); // end drawing
    btnHealth.NormalGraphic = ron_gauge.Graphic;
}

The problem that I am encountering is this: When I use the first-aid kit on the character, the bar adds more green, showing that he is recovering health.  But if he takes damage after this, the healing is almost "disregarded" -- the bar lowers as if a first-aid kit weren't even used.  (Take this, for example.  Ron has 10 HP out of 30 HP.  The first-aid kit is used on him to recover 20 HP, which shows on the bar, equaling 30/30 HP.  But if he is hit after this, let's say 5 HP worth of damage, all of this "recovered" green disappears, showing in the bar that he now has 5 HP out of 30 just from that one hit.)  I hope I'm making sense.  What's the problem here?

I would really appreciate any help regarding this issue. Thanks!

Khris

First of all, it isn't necessary to use all that duplicate code, all you need to do is pass a negative value as the amount of damage.
Then you'll need an additional line after those two:
Code: ags
  ron_hp -= damage;
  if (ron_hp < 0) ron_hp = 0;

  if (ron_hp > 30) ron_hp = 30;   // add this


This should solve your other problem, too.
I'm not sure how it is caused exactly, though.

thom0512

#233
I tried your suggestion by adding the extra line of code where it was needed.  The change didn't seem to do anything, however...it just still stays the same as before. ???

And to clarify, I did get rid of that extra bit of code I had before, added the one line of code from your last post, and am inputing health as taking damage a negative value.  It still isn't working for me...

Khris

Did you declare ron_hp outside the function?
By putting this above it:
Code: ags
int ron_hp = 30;


thom0512

I checked, and I already had that line up above the function.  I'm not sure what I am missing.  If you don't mind, let me show you what I've got so far.

This is the code I have in the global script.

Code: ags

int ron_hp = 30;
DynamicSprite*ron_gauge;

function ron_gets_hit(int damage) 
{
  ron_hp -= damage;
  if (ron_hp < 0) ron_hp = 0;
  if (ron_hp > 30) ron_hp = 30;
  ron_gauge = DynamicSprite.CreateFromExistingSprite(btnHealth.NormalGraphic);
  DrawingSurface*ds = ron_gauge.GetDrawingSurface();
  ds.DrawingColor = 16; // black
  ds.DrawRectangle(0, 0, 99, 15);  // clear gauge
  ds.DrawingColor = Game.GetColorFromRGB(0,255,0); // green
  if (ron_hp > 0) ds.DrawRectangle(0, 0, ron_hp, 15); // draw health        only draw health if > 0
  ds.Release(); // end drawing
  btnHealth.NormalGraphic = ron_gauge.Graphic;
}


This is the code I have for a first-aid kit to recover health (with a sound playing when that happens).

Code: ags

function cRon_UseInv()
{
  if (cRon.ActiveInventory == iFirstaidkit) { // use first-aid kit on self
    PlaySound(19);
    ron_gets_hit(-20);
    cRon.LoseInventory(iFirstaidkit);
  }
}


...and here is an example of Ron taking damage from the first example I could find from my game (with the first code listed above shown at the top of the room script).

Code: ags

function hStove_Interact()
{
  cRon.Walk(269, 179, eBlock);
  cRon.LockView(15);
  cRon.Animate(2, 1, 0, eBlock);
  cRon.UnlockView();
  PlaySound(17);
  ron_gets_hit(15);
{
  if (ron_hp == 0){
    cRon.Say("&93 Uhh...");
    cJon.Say("Ron?");
    PlaySound(11);
    cJon.LockView(17);
    cRon.LockView(16);
    cJon.Animate(0, 0, eOnce);
    cRon.Animate(2, 1, 0, eBlock); // catch on fire
    cJon.UnlockView();
    cRon.UnlockView();
    cRon.ChangeRoom(17);} // obvious game-over
  if (ron_hp > 0){
    cRon.Say("&91 Ouch!");
    cRon.Say("&92 I know better than to touch a hot stove.");
    cJon.Say("Oh, c'mon Ron...");
    cJon.Say("That's so HOKEY!");
    cJon.Say("Getting burned by a stove?");
    cRon.FaceLocation(268, 0, eBlock);
    Wait(80);
    cRon.FaceLocation(268, 194, eBlock);
    } 
  }
}


The animation pretty much shows Ron catching on fire from the stove once his HP has reached zero, or at least, that's how I'd like it to work.  The same problem seems to be here: I touch the stove and lose 15 HP.  Using the first aid kit (recovering 20 HP, but really only going to 30 HP, the maximum) I touch the stove again and Ron loses all of his health instead of another 15 HP.  What am I missing?

Khris

Here's an actually tested version of the main function:
Code: ags
function ron_gets_hit(int damage) {
  ron_hp -= damage;
  if (ron_hp < 0) ron_hp = 0;
  if (ron_hp > 30) ron_hp = 30;
  ron_gauge = DynamicSprite.Create(30, 15);
  DrawingSurface*ds = ron_gauge.GetDrawingSurface();
  ds.DrawingColor = 16; // black
  ds.DrawRectangle(0, 0, 29, 14);  // clear gauge
  ds.DrawingColor = Game.GetColorFromRGB(0,255,0); // green
  if (ron_hp > 0) ds.DrawRectangle(0, 0, ron_hp-1, 14); // draw health        only draw health if > 0
  ds.Release(); // end drawing
  btnHealth.NormalGraphic = ron_gauge.Graphic;
}


Apart from some minor coordinate correction, the main fix is the line used to create the new sprite; I didn't assign a properly sized sprite to the button in the editor (and neither did you, I assume), and thus the sprite was too small and had wrong colors (my guess is AGS used the blue cup sprite 0).

Zachski

Actually, I have a question.

I'd like to do a semi-RPG combat style similar to that of Quest for Glory 1 (the VGA version).

With some personal tweaks, of course, which I'll figure out later.

Before I go charging into this and end up with a broken battle system and a mess of code, what should I do and what should I avoid?  I understand that it's gonna require some animate commands and checking for variables and stuff...

Khris

Do:
-write nicely structured, properly indented, commented code
-use fitting variable names

Avoid:
-starting off unless you've got fair programming and AGS experience

On a slightly more serious note:
QFGs battle system is not _that_ hard to emulate, since it's relatively simple and uses real-time.
But it's still going to be a good deal of semi-complex coding.

Takyon

If you knew the program well enough could you make a game to the standard of say monkey island 3 or broken sword 1/2? Hypothetically...
ghost.

SMF spam blocked by CleanTalk