2016-09-06 06:46:48

Hello everyone.

I'm back because as the title suggest, I'm still struggling quite a bit with handles. Without spoiling how it's going to work, I'm creating a sidescroller. The problem I'm having is creating multiple enemies. I have the enemy class at a functional point. Now all I need to do is be able to spawn multiple enemies.

I understand how handles work, but I'm having difficulty implementing them. If someone could show me an example of how to use a handle to spawn multiple enemies, I would be really grateful. If anyone wants to show me an example with my code how I would do what I'm asking, I'll post my source code for you to look at. Thank you.

P.S. Sorry if I have a few spelling/grammer mistakes. I'm half asleep while writing this and hoping to have a few replies when I wake up.

Source code:

https://www.dropbox.com/sh/kzelspssbw6o … OsDKa?dl=0

2016-09-06 11:17:39

What I generally do:


class enemy {
// (stuff goes here.)
}
enemy@ new_enemy() {
enemy ret;
return ret;
}

enemy@[] enemies;

void add_enemy() {
enemies.insert_last(new_enemy());
}

With properties and parameters added/modified as necessary.
The new_enemy function is one of those things you wouldn't need in almost any language other than this one. True, you wouldn't need handles in most other languages, but they do at least have relevance to C / C++ / C# / etc.

The way it would be done in the manual:

void add_enemy()
{
enemy temp;
enemies.insert_last(temp);
}

Yes, the exact details of how it decides to use handles in this case are confusing. :s

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2016-09-06 15:02:56

Hmm, interesting. Why is it that whenever I see people give examples of using a handle, they store it in an array? Is that the easiest way of doing it? Or the only way?

2016-09-06 21:16:28

Pretty much the only way if you want to have a multitude of dynamically spawnable enemies. You can then just easily loop through the entire array and say call an update method of the enemy class for all these instances that way, so that your enemies will keep updating their state and doing whatever they're supposed to be doing, no matter if you have 5 or 30 of them. Imagine the joy of writing out 30 or more specific enemy instance names manually. :-D
What if you wanted to add or remove some later? Have fun. :-)
This way, you can have varying enemy counts based on difficulty or anything along those lines.
I was also wondering this exact question myself when I was starting out with BGT a few years ago, and this was pretty much the answer I got in essence.
Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-07 00:23:33

@Lukace

Ah that makes a lot more sense. The part that confused me in the manual was when it gave an example on how to use a handle, it didn't use an array. This made me believe that arrays didn't have to be used while spawning enemies. I think I'll be able to figure the rest out from here. Thanks.

2016-09-07 12:32:23

You don't *need* arrays, but you want them. Unless you're using a language where dictionaries have an easy syntax, like Python or Javascript (in Javascript, what they call arrays have actually been dictionaries since forever). But since BGT dictionaries are considerably more cumbersome than that, you'll be wanting to use arrays quite a lot.

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2016-09-07 15:59:51

Yeah, Cae is right. There will certainly be many cases where you want to pass around just a single handle too, like when calling a specific function that uses a handle as an argument, or creating one of this kind yourself, but for what you asked about enemy handling arrays are really the best approach in BGT, I think.
Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-07 17:04:27

So, I actually have a different question. I'm trying to make it so then when standard.movement(true);, the enemy will move. Here is my code:


class enemy
{//class open
int health;
int x;
timer movement;
enemy()
{ //constructor
health = 100;
x = 100;

} //constructor

void move(bool moving)
{ //movement open



if(movement.elapsed>=250 && moving == true)
{
x--;
pool.play_1d("1.wav", p, x, false);
movement.restart();

}
} //movement close

} //class close


So, what it should do is, check to see if it's true, if it is, have it begin walking. So to test this, I assigned it so when I press 1, it executes standard.movement(true). Instead of continuously moving from right to left, it only moves one tile.

I believe it's doing this because since I have it set to true, only when I press 1, it will only execute once. Here's what I'm confused on. Once I set it to true, shouldn't it just keep looping after that? Let me know if I should explain this a bit more.

2016-09-07 17:18:31

Yeah, I'm sure that's what you want it to do, but how does the script know that? :-D By that, I mean if you have some actual loop somewhere that calls this method repeatedly, or perhaps indirectly through a main class update method of sorts. Remember, if you call a method once somewhere, if it's not inside a loop, it will not begin looping explicitly all by itself just because it somehow senses that you wish it to. :-) Besides, how would it know when to stop looping, if it controlled itself like that? :-)

Hope you see what I mean here. The tone used was intentionally light so that it could hopefully make more sense to you, it was not meant as an insult or anything, so I hope you take it for what it was meant. :-)
Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-07 21:02:05

Oh no worries man. But I actually have it looping in the main loop. That's the part that's confusing me. Any ideas?

2016-09-07 22:32:59

Oh, sorry about that wrong assumption then. I was almost sure you forgot to actually loop it, as that's what happened to me ages ago, too. :-)

In that case, are you sure there is nothing in there somewhere that would set the enemy's moving bool back to false?

It would probably be best if you posted your entire code, or at least the enemy class and the main loop.

Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-07 22:50:06

Yeah, that's what I've been trying to figure out as well. Here's my code if you want to check it out:

https://www.dropbox.com/s/lsim1gg056da2 … le.7z?dl=0

2016-09-07 23:07:36

Oh, I see the issue now. You do call the enemy move method from inside a loop, but only when you actually press the key. That's to be expected in that case. So, I was right in a sort of way before, just expressed my point poorly.

Either give up on this approach to enemy movement entirely and make them move automatically through an if check in the loop, i.e. call the correspondingly modified move method every x milliseconds directly from within the loop, or make the bool moving argument global to the entire enemy class instead of just belonging to the move method. Like this, it's of absolutely no use to you at the moment. If you did this, you would then do the following in your main loop, besides keyboard commands:
if (standard.moving) standard.move();

It's not a very good approach but hey, it would work. I assume the entire single enemy handle called standard and the key that's supposed to trigger the looping movement are all there just for testing purposes anyway.

Hope this helps,
Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-07 23:33:46

You're exactly correct, I was just using it all for testing purposes. My end goal, since I'm still a beginner with arrays, was to press a key that spawns an enemy. Just to be sure that I got the whole handle thing down, you know? I suppose a better approach would be to just have key_1 be used to add another slot to an array?


Also, if I did make the bool moving global and I had multiple enemies spawned, would that one bool control all of them at once? In regards to if they're moving or not.

2016-09-08 12:50:33

Hi,
yeah, I suppose making the key press just spawn another enemy and add it into the array of handles would be a better approach in general.

If you made the moving boolean entirely global, then yes, it would of course control all of the enemies at once. Another possibility would be to make it a property of the enemy class instead. That way, it would be specific and separate for each instance of enemy. In any case though, there is no need to use it as an argument in the move method itself, that just provides no real use.

You could also get rid of it entirely. If you only wanted to make sure that the enemy doesn't start moving until spawned, well, then he doesn't, because since he's not there on the game board yet until he's been spawned, he can't actually move either. If you want to have other factors influencing when an enemy should start moving in the end product, you will probably need other decisions and if checks to compare more specific circumstances anyway.
For the time being, you could pretty well just check the value of the timer.

Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-08 13:49:59

Ah MK. One more question. Back in post 4, you mentioned I would have to loop the array of enemies and then call an update method. What does an update method actually call for? Because the way I'm understanding it, it's just being held in the array, but it's still carrying out it's function. I guess my question is, what would need to be updated? Thanks a lot for your help so far. Once I can get arrays and handles under my belt, I'll be able to really get working smile.

2016-09-08 14:01:25

Eh, basically, if you use an array of handles to enemy class instances which, as revealed through the previous discussion, would be the best approach to implementing a multitude of enemies, then you will have to loop through the enemy array in your main loop. The best way to do that is using an embedded for loop. To put it simply, among other instructions in your main loop, you will just be doing something through a for loop manipulating the array of enemies.

What this something is will be entirely up to you. The style I like using is doing all the subsequent instructions for individual class instances in that class's own method which I call act or update. Basically, the enemy behavior itself is not written out plain in the main loop but only in that subsequent method which is called for each enemy instance in the array through the main loop.

If the enemies' only job in the end will be to handle movement, you might as well just do that directly when looping through the array, without having to call another method of the enemy class.

Does this make more sense now?

Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-08 23:01:04

I think this does make sense. Earlier, I created a method called spawn, and all it did was add the variable standard to the array. I was wondering why it wasn't creating more enemies. What I really should do is loop standard.movement in a for loop, that way it individually executes each enemy. I'm going to try this out and I'll get back to you with my results smile. Thank you.

2016-09-09 09:55:20

Yeah, that's what I was talking about. Just do whatever you want to do with the enemies through the array. That's the point of the array being used in the first place. So, you shouldn't be doing standard.movement in your array loop, but rather enemies[x].movement. Of course, replace x with anything you feel like using to refer to the array index.

Similarly, if you want spawning to occur at a fixed time interval, just put it in your main loop as well.

Let me know how it goes.

Lukas

I won't be using this account any more or participating in the forum activity through other childish means like creating an alternate account. I've asked for the account to be removed but I'm not sure if that's actually technically possible here. Just writing this for people to know that I won't be replying, posting new topics or checking private messages until the account is potentially removed.

2016-09-12 13:25:33

Here's how I'm doing this. I'm not sure that it's right way or not, but it works. However, this example is on a 2d grid, so you have to make some changes to make it side scroller. BTW, I'm now searching for some way to make enemies of different types and different attack skills, because in this example everything derives from the same class, game_object. I'm calling my class game_object instead of enemy because I will probably use this class for other living objects, and not just enemies. Also, I've made a function which takes two arguments, the one being enemy spawn interval, and another one being number of enemy instances to spawn. I've got inspiration for spawning stuff from windows_attack code, btw.
Anyway, here's my code: https://dl.dropboxusercontent.com/u/407 … ritory.bgt