(GMS2) Spawner object doesn't spawn items - game-maker-studio-2

In GMS2 I have a spawner item with the following code:
In the create event:
timer = 0;
In the step event:
if(distance_to_object(obj_coffe_bean) > 2)
if(timer == 200) {
instance_create_layer(x, y, obj_coffe_bean, obj_coffe_bean);
timer = 0;
}
else timer++;
This works perfectly fine, coffee beans are spawned when it doesn't detect any coffee bean nearby.
The problem is that the same code doesn't work when I duplicate this object and create a spawner for another item.

The most obvious problem here would be that you are using the object index as the layer index in instance_create_layer - your code only works by chance (of there being a layer with a matching ID).

Ok, I needed to use instance_create_depth instead of instance_create_layer.

Related

GMS2, when destroying a child, all children get affected. Parent object not functioning as intended

I am having an issue with my parent object and its children.
My intention is to have an enemy spawner (child) that functions independently of other children spawners . The spawner will spawn enemies until the desired amount is reached and then be destroyed (child is destroyed). However, when I destroy an enemy spawned by my parent spawner object, all children spawners spawn an enemy instead. Example. I have two children spawnwers that spawn an enemy. When I destroy from child A, child A and B both spawn an enemy. Furthermore, when I destroy the required amount of enemies from the spawner, both A and B child spawners are destroyed except for just A child.
Below is code.
///PARENT SPAWNER OBJECT
PARENT STEP EVENT
if(enemy_dead_count <= 0){
sprite_index = sDestroyed_Ghost_Spawner;
if (sprite_index == sDestroyed_Ghost_Spawner){
if(image_index >= 9 && image_index < 10){
image_index = 9;
}
}
} else {
while(spawn_ghost == 0){
instance_create_layer(x,y+32,"Player",oEnemy_spawner_animation);
spawn_ghost += 1;
}
}
//PARENT CREATE EVENT
spawn_ghost = 0;
enemy_dead_count = 3;
The object, oEnemy_spawner_animation, is an object that scales its xscale and yscale and when reaches a desired size changes the instance to oEnemy_ghost
//ANIMATION CODE BELOW
//animator create event
image_xscale = 0;
image_yscale = 0;
//animator step event
if image_xscale <= 1 {
image_xscale += 0.008;
image_yscale = image_xscale;
} else{
image_xscale = 1;
//update yscale
image_yscale = image_xscale;
instance_change(oEnemy_ghost,true);
}
In the Enemy Parent , I wont post all the code as it is quite extensive but ill post the relevant
if(hp<=0){
instance_destroy();
with(x,y,oEnemy_ghost_spawner){
spawn_ghost = 0;
enemy_dead_count -= 1;
}
}
Above, when an enemy is destroyed, I use the with statement to spawn a new enemy.
I am targeting the child here instead of the parent , perhaps that's the problem?
I have a feeling I need to somehow tie the enemy spawned ID to the child spawner ID, but I do not know how to achieve this.
Any thoughts on how to achieve my intended functionality? How do I make my children spawners function independently of eachother?
With the with() function, you'll go through every object of that type. I think if that includes a parent, it'll affect the children as well.
A possible solution could be to:
Make another child of the current 'parent' function, and use the current parent as just a base of the enemy spawner that'll affect all enemy spawners, and not an entity of itself.
make a boolean that'll only be set to true for the parent (like isParent), and set it to false for it's children.
if you want to make each spawner unique of each other, then you could try giving them an unique ID, and inside the with() function, search for that unique ID if it's the one you're looking for.

Add CCNodes to a Parent CCNode using a for loop

-(CCNode *)createFieldNode:(NSMutableArray *)fieldArray{
CGSize winSize = [CCDirector sharedDirector].viewSize;
CCNode* stackNode= [CCNode node];
for (int i; i <=fieldArray.count; i++){
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC;
if(i!=0){
itemP=[fieldArray objectAtIndex:i-1];
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
float stackHeight=itemP.position.y+itemP.contentSize.height;
itemC.position=ccp(stackWidth,stackHeight);
}
else{
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
itemC.position=ccp(stackWidth,0);
}
//having trouble adding multiple nodes to stackNode
[stackNode addChild:itemC];
}
return stackNode;
}
I want to add CCNodes from fieldArray on to a parent CCNode "stackNode". When I use breakpoints I am able to add the CCNode at index 0 and CCNode at index 1. However the program crash at i=2. The error I receive is:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'child already added to another node. It can't be added again'
Before the crash "stackNode" has two children. I'm not adding the CCNodes one by one because I have hundreds of different arrays with many a fieldArray.count around 20. Please help I can explain more if I have been unclear.
Change the for loop start as follows :
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC; // moved out of the for loop
for (int i; i <fieldArray.count; i++){ // <- changed the end condition to avoid crash
... rest of loop
Also, in the code that creates fieldArray, make certain you have logic to ensure that there are no duplicates, otherwise you will have the same issue (but for an altogether different reason).

as3 if remove Parent Do all children get removed too?

I am loading a mc called Spiri into a mc called Box. Later I want to remove both from memory usage and off screen. I have the off screen in a tween not shown here.
If I use removeChild(box); will it also remove all Children with in?
Basically I am loading 3 movies from library with a function call. Then trying to remove them and call the same function multiple times. Which means the same movies are loaded again and again with the same names. This IS SUPPOSED TO replace the old ones but maybe its not because I am not removing them properly because by the 10th or 15th call it is getting very slow.
I am also adding an event-listener in a function too. Is that then adding a some event-Listner every single time and taking up resources as well?
It seems to be very slow after several times running a that function which makes me believe something is not getting unloaded correctly.
//I tried
box.removeChild(Spiri);
Spiri = null;
//then remove the parent like this
removeChild(box); /// but this gets an error.
again if i just do this
removeChild(Spiri); // it makes me wondering if they are getting removed.
How what is the best way to remove parent and all children in an mc?
Yes and no. The children are no longer located on the stage, but they are still children to the parent until removeChild() is called. That can be good and bad. Obviously, it is great for reusing objects but can be terrible for memory management because those objects can only be garbage collected when their parent is garbage collected. For a simple app, that is usually fine. But for something massive... not so much.
For the project I am working on now (a massive 30 page, 50,000 liner), I created a light-weight GUI framework to handle all of my DisplayObjects. Everything except basic Bitmap and Shape DisplayObjects extend a single class which extends Sprite. In that class, I have this function:
final public function destroy():void {
this.removeAllEventListeners();
var i:int, l:int, cur:DisplayObject;
l = this.numChildren;
for ( i = 0; i < l; i++ ) {
cur = this.getChildAt( i );
if ( cur is XISprite && !this.stopChildXISpriteDestroy ) {
( cur as XISprite ).destroy();
}
else if ( cur is Sprite ) {
( cur as Sprite ).removeChildren();
}
if ( cur is Bitmap && ( cur as Bitmap ).bitmapData && !this.stopBitmapDestroy ) {
( cur as Bitmap ).bitmapData.dispose();
}
if ( cur is Loader && !this.stopLoaderDestroy ) {
( cur as Loader ).unload();
}
if ( cur is Shape ) {
( cur as Shape ).graphics.clear();
}
}
cur = null;
i = l = NaN;
this.removeChildren();
}
It basically does a hard wipe of all the objects and allows me to easily qualify all children of that class for Garbage Collection. I also am keeping track of all event listeners so there is no chance at all a rogue listener could prevent GC (by calling removeAllEventListeners()). I also have some protected flags in the class that allow you to stop the destroy on a certain object type (so I can leave a SWF or an image loaded in memory if needed)
It might be overkill, but memory consumption has been an issue in this app and that function has really helped manage it. This may be more than you need, so you can just call removeChildren() with default params and it will remove all children from the parent object.
As an afterhthought: Keep your DisplayObjectContainers as simple as possible. Avoid nesting them as often as possible. The first conditional, where I call destroy on every single XISprite that is a child of an XISprite is great but it could be disastrous if there were loads and loads of XISprite children as the destroy() calls would pile up on each other and freeze the app.

CListCtrl with LVS_EX_CHECKBOXES style

I'm using CListCtrl with LVS_EX_CHECKBOXES style.
And I need to have at least two of the checkboxes were set checked at any time.
How can I do this?
First you need to trap the LVN_ITEMCHANGING notification, which is most easily done by deriving your own class from CListCtrl (for example, called CMyListCtrl) and then adding a message map entry like the following:
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
ON_NOTIFY_REFLECT(LVN_ITEMCHANGING, &CMyListCtrl::OnLvnItemchanging)
END_MESSAGE_MAP()
Then, you write the message handler like so:
void CMyListCtrl::OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult)
{
// an item has changed
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// by default, allow change
*pResult = 0;
// see if item was checked or unchecked
if ((pNMLV->uNewState & 0x2000) == 0x2000)
{
// item was checked - do anything you like here
}
else if ((pNMLV->uNewState & 0x1000) == 0x1000)
{
// item was unchecked - see how many selections we have
if (/* pseudocode */ number of selected items < 2)
{
// disallow change
*pResult = 1;
}
}
}
The condition is pseudo-code so you can decide how to keep track of the number of selections - maybe keep a count by adding code to the above method, or put a loop in there to get the check state of each item and make a tally.
I think this should give you enough to get moving, so please update your question if you get stuck further.

GTK+ - How to listen to an event from within a method?

I'm writing an application that runs an algorithm, but allows you to 'step through' the algorithm by pressing a button - displaying what's happening at each step.
How do I listen for events while within a method?
eg, look at the code I've got.
static int proceed;
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0) continue;
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
button2Event(GtkWidget *widget)
{
proceed = 1;
}
This doesn't work because it's required to exit out of the button1 method before it can listen for button2 (or any other events).
I'm thinking something like in that while loop.
while(proceed == 0)
{
listen_for_button_click();
}
What method is that?
The "real" answer here (the one any experienced GTK+ programmer will give you) isn't one you will like perhaps: don't do this, your code is structured the wrong way.
The options include:
recommended: restructure the app to be event-driven instead; probably you need to keep track of your state (either a state machine or just a boolean flag) and ignore whichever button is not currently applicable.
you can run a recursive main loop, as in the other answer with gtk_main_iteration(); however this is quite dangerous because any UI event can happen in that loop, such as windows closing or other totally unrelated stuff. Not workable in most real apps of any size.
move the blocking logic to another thread and communicate via a GAsyncQueue or something along those lines (caution, this is hard-ish to get right and likely to be overkill).
I think you are going wrong here:
while(proceed == 0)
{
listen_for_button_click();
}
You don't want while loops like this; you just want the GTK+ main loop doing your blocking. When you get the button click, in the callback for it, then write whatever the code after this while loop would have been.
You could check for pending events & handle the events in while loop in the clicked callback. Something on these lines:
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0)
{
/* Check for all pending events */
while(gtk_events_pending())
{
gtk_main_iteration(); /* Handle the events */
}
continue;
}
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
This way when the events related click on the second button is added to the event queue to be handled, the check will see the events as pending and handle them & then proceed. This way your global value changes can be reflected & stepping should be possible.
Hope this helps!
If you want to do it like this, the only way that comes to my mind is to create a separate thread for your algorithm and use some synchronization methods to notify that thread from within button click handlers.
GTK+ (glib, to be more specific) has its own API for threads and synchronization. As far as I know Condition variables are a standard way to implement wait-notify logic.

Resources