May 01, 2024, 02:51:20 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


odd movement issue

Started by J B Wood (Zumwalt), November 21, 2006, 07:21:23 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

J B Wood (Zumwalt)

My line of invaders all move in sync from left to right, when they hit the right edge of the screen, the right most invader moves left by a small amount on each run, but when the entire group hits the left wall, it acts like it should for the entire line, this problem persists.

I have combed over it a billion times in my head, it has to be something simple I am overlooking, please look at this code snippet, this is where the problem resides. I'll post a link to the application itself so you can also run the game so far to see what I am talking about.

// draw our High envaders that are live
posHigh = InvadersHighList->GetFirst();
while(posHigh != NULL)
{
pHighInvaders = InvadersHighList->GetData(posHigh);
if (pHighInvaders->x+45 > Screen_Width)
{
/* check to see if the High Invaders is to the right edge */
scrollStateHigh=1;
posHighGroup=InvadersHighList->GetFirst();
while(posHighGroup != NULL)
{
pHighInvaders = InvadersHighList->GetData(posHighGroup);
if (pHighInvaders->speed < pHighInvaders->maxSpeed)
pHighInvaders->speed += Step;
pHighInvaders->y += pHighInvaders->drop;
posHighGroup = InvadersHighList->GetNext(posHighGroup);
}
pHighInvaders = InvadersHighList->GetData(posHigh);
}
else if (pHighInvaders->x < 0)
{
/* check to see if the High Invaders is back to the left edge */
scrollStateHigh=0;
posHighGroup=InvadersHighList->GetFirst();
while(posHighGroup != NULL)
{
pHighInvaders = InvadersHighList->GetData(posHighGroup);
if (pHighInvaders->speed < pHighInvaders->maxSpeed)
pHighInvaders->speed += Step;
posHighGroup = InvadersHighList->GetNext(posHighGroup);
}
pHighInvaders = InvadersHighList->GetData(posHigh);
}

/* handle scroll state of High Invaders, either go left or go right */
switch (scrollStateHigh)
{
case 0:
pHighInvaders->x=pHighInvaders->x + pHighInvaders->speed;
case 1:
pHighInvaders->x=pHighInvaders->x - pHighInvaders->speed;
}

posHighGroup=InvadersHighList->GetFirst();
while(posHighGroup != NULL)
{
pHighInvaders = InvadersHighList->GetData(posHighGroup);
pHighInvaders->Invader.SetPosition(pHighInvaders->x,pHighInvaders->y);
if (pHighInvaders->currentHP > 0)
pHighInvaders->Invader.Draw();
posHighGroup = InvadersHighList->GetNext(posHighGroup);
}
posHigh = InvadersHighList->GetNext(posHigh);
}


Rock Ridge Farm (Larry)

Try if (pHighInvaders->x+45 > (Screen_Width - 1))
I think you have gone too far when it gets to > screen_width.

J B Wood (Zumwalt)

No difference, the issue is only with the right most invader, or which ever invader hits the right edge.
If you watch it long enough, when the first invader is pushed past the one to its left, the process repeats for the next one.

J B Wood (Zumwalt)

November 21, 2006, 09:47:29 AM #4 Last Edit: November 21, 2006, 09:49:43 AM by Jonathan (zumwalt) Wood
I broke this out into its own sub routine (need to do that anyway)
Now, if I can get the problem fixed, it will be fixed for all invader movements.

sub MoveObjectInvaders(CPointerList *objList),CPointerList*
{
pointer pos,posGroup;
sInvaders *pObject = NEW(sInvaders,1);

pos = objList->GetFirst();
while(pos != NULL)
{
pObject = objList->GetData(pos);
if (pObject->x > (Screen_Width-50))
{
/* check to see if the Invaders is to the right edge */
scrollState=1;
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
if (pObject->speed < pObject->maxSpeed)
pObject->speed += Step;
pObject->y += pObject->drop;
posGroup = objList->GetNext(posGroup);
}
}
else if (pObject->x < 0)
{
/* check to see if the Invaders is back to the left edge */
scrollState=0;
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
if (pObject->speed < pObject->maxSpeed)
pObject->speed += Step;
posGroup = objList->GetNext(posGroup);
}
}
pObject = objList->GetData(pos);
switch (scrollState)
{
case 0:
pObject->x=pObject->x + pObject->speed;
case 1:
pObject->x=pObject->x - pObject->speed;
}
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->Invader.SetPosition(pObject->x,pObject->y);
if (pObject->currentHP > 0)
pObject->Invader.Draw();
posGroup = objList->GetNext(posGroup);
}
pos = objList->GetNext(pos);
}
return (objList);
}



I pass in my List for the invader collections, it does the work, then returns the resulting list back out.
This yielded even stranger results, I'll re-upload the binary, same link can be used to download it in about 5 minutes.

J B Wood (Zumwalt)

Did a little re-aranging of some of the global variables and made them members of the structures that would normally use them.
That said, here is the latest of the sub in question, same result though, last invaders on the row 'jimmy' a little on every pass. I still need to wrap the collection of invaders in a way that they all move in sync instead of 3 seperate entities. Easy enough to do, but least of my worries right now...


sub MoveObjectInvaders(CPointerList *objList),CPointerList*
{
pointer pos,posGroup;
sInvaders *pObject = NEW(sInvaders,1);

pos = objList->GetFirst();
while(pos != NULL)
{
pObject = objList->GetData(pos);
if (pObject->x > (Screen_Width-50))
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->scrollState=1;
if (pObject->speed < pObject->maxSpeed)
pObject->speed += pObject->Step;
pObject->y += pObject->drop;
posGroup = objList->GetNext(posGroup);
}
}
else if (pObject->x < 0)
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->scrollState=0;
if (pObject->speed < pObject->maxSpeed)
pObject->speed += pObject->step;
posGroup = objList->GetNext(posGroup);
}
}
pObject = objList->GetData(pos);
switch (pObject->scrollState)
{
case 0:
pObject->x += pObject->speed;
case 1:
pObject->x -= pObject->speed;
}
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->Invader.SetPosition(pObject->x,pObject->y);
if (pObject->currentHP > 0)
pObject->Invader.Draw();
posGroup = objList->GetNext(posGroup);
}
pos = objList->GetNext(pos);
}
return (objList);
}

Ionic Wind Support Team

sInvaders *pObject = NEW(sInvaders,1);

Is a memory leak.  pObject is just a pointer and your assigning it in the GetData method.  No reason to create a NEW structure.  Just defint the pointer.

sInvaders *pObject;

You should also break from your main WHILE loop once an invader that has gone past the right edge has been found.  One question I have is what is the maximum speed value?  You are doing this test:

if (pObject->x > (Screen_Width-50))

And if true then reversing the direction.  However if the speed value isn't greater than ((screen_width-50) - pObject->x)  the test will still be true on the next iteration of this function.  In other words you will be reversing back and forth at least twice, which could explain the behaviour you are seeing.

What you really need to do is come up with a delta offset to move all of the invaders to the left once the edge has been found and then start the movements again.  That delta would be equal to ((screen_width-50) - pObject->x)+1 which would ensure that the hit test only occurs once and then the whole group starts to the right again.

Paul.



Ionic Wind Support Team

J B Wood (Zumwalt)

Max speed is 5.0f. Speed increases at a rate of 0.10f until it reaches max.
The delta is a good idea, I'll see if I can hash that out and update on results for that.
That one sub handles 4 routines during the life of a game:

// Flying Saucer
InvadersList=MoveObjectInvaders(InvadersList);
// High Invaders
InvadersHighList=MoveObjectInvaders(InvadersHighList);
// Medium Invaders
InvadersMedList=MoveObjectInvaders(InvadersMedList);
// Low Invaders
InvadersLowList=MoveObjectInvaders(InvadersLowList);

Its capibile of keeping everything moving.
The delta might help though, I'll let you know, many thanks.

J B Wood (Zumwalt)

Ok, I got it figured out:


sub MoveObjectInvaders(CPointerList *objList),CPointerList*
{
pointer pos,posGroup;
sInvaders *pObject;// = NEW(sInvaders,1);

pos = objList->GetFirst();
while(pos != NULL)
{
pObject = objList->GetData(pos);
switch (pObject->scrollState)
{
case 0:
if (pObject->x + pObject->speed) >= (screen_width-52)
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->scrollState=1;
if (pObject->speed < pObject->maxSpeed)
pObject->speed += pObject->step;
pObject->y += pObject->drop;
posGroup = objList->GetNext(posGroup);
}
}
else
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->x += pObject->speed / pObject->throttle;
posGroup = objList->GetNext(posGroup);
}
}

case 1:
if ((pObject->x - pObject->speed) <= 0)
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->scrollState=0;
posGroup = objList->GetNext(posGroup);
}
}
else
{
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->x -= pObject->speed / pObject->throttle;
posGroup = objList->GetNext(posGroup);
}
}
}

pObject = objList->GetData(pos);
posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->Invader.SetPosition(pObject->x,pObject->y);
if (pObject->currentHP > 0)
pObject->Invader.Draw();
posGroup = objList->GetNext(posGroup);
}
pos = objList->GetNext(pos);
}
return (objList);
}