Author Topic: Comparing array data  (Read 1840 times)

0 Members and 1 Guest are viewing this topic.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Comparing array data
« on: May 22, 2020, 08:12:25 am »
How would you have an array compare data against itself? I'll use some pseudo-code to explain what I've tried so far. I've been banging my head against this problem for several hours now.

To be more specific, my game has an array of spaceships that flies down the screen. If one is shot down it becomes a powerup icon. The player can collect the powerup because it is a separate object being compared against the spaceship objects.
But what I'd like to do is make it so that if an enemy spaceship is shot down, any of the other spaceships could steal that powerup if they get to it before the player does.

I tried making a second array and copying the data . . .

for i = 1 to arraydimensions
if ship(i).shotdown = 1 then
newship(i).x = ship(i).x
newship(i).y = ship(i).y
next

In theory, I'm copying the x,y coordinates of the shot down spaceship into a new array of equal dimensions named newship so I can do hit detection like this:

for i = 1 to arraydimensions
if newship(i).x <= ship(i).x + ship(i).width then   ' hit detection
powerup = 1
end if
next

So far this hasn't worked because although there are now two separate arrays, it seems to me like they're comparing the same data. If the 10th element of ship array had a value of 6 then the 10th element of newship would also have a value of 6.

To fix this, I copied the array data . . .

newship(i).x = ship(i).x
newship(i).y = ship(i).y

. . . but then changed the original values afterwards so that they would be unique.

ship(i).x = -500
ship(i).y = -500    ' puts ship coordinates off-screen and out of play.

So that now when this is run:

for i = 1 to arraydimensions
if newship(i).x <= ship(i).x + ship(i).width then   ' hit detection
powerup = 1
end if
next

at no point will the two values be the same, causing conflict.

The latest thing I've tried is this:

for i = 1 to arraydimensions
for itwo = 1 to arraydimensions
if newship(itwo).x <= ship(i).x + ship(i).width then   ' hit detection
powerup = 1
end if
next
next

. . . but that hasn't been working either.

So to recap, I have an array of ship objects. If one gets shot down, I want to copy its last-known coordinate data into a new array so I can see if any of the existing ships have collided with one of their fallen comrades.

What am I doing wrong? (Or it's possible that I'm on the right track and something else in my code is throwing me off).

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
Re: Comparing array data
« Reply #1 on: May 22, 2020, 09:17:32 am »
Could you post the code? I'm a bit confused by the need for a second array if you are using a TYPE array, which it looks like you are. A type could just include a shotdown/powerup toggle that logical operators could check and/or modify for displaying icons, plotting movement variations and determining results of collisions. Perhaps I'm just too dense to understand the approach.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Comparing array data
« Reply #2 on: May 22, 2020, 10:00:03 am »
Honestly I think posting the code would just be more confusing (my program is over 3000 lines of code long so it'd take some work to trim out only the applicable parts).

I've been trying to wrap my head around this by using a deck of cards analogy, where an array is basically a deck of cards.

So let's say I have a ship deck (array) that holds 20 cards.

I start flipping the cards over 1 at a time (for i = 1 to arraydimensions)

Let's now say that the 2nd card is "shot down" by the player and becomes a powerup.

The "player" has always been a card/object all by itself in its own stack, so it can easily be compared against any of the cards in the ship deck, including ones that have now been transformed into powerups.

But to get the other ships to be compared against the ship that is now a powerup, it seems to me that a second array is necessary.

To use the card analogy again, if in the first deck, cards 2 and 4 are "shot down", I need to somehow isolate them and then compare them against cards 1, 3 and 5 through 20.
I can't allow cards 2 and 4 to be compared against themselves in the same deck/array because that would automatically trigger a "hit detection" condition.

So now let's suppose I have a second deck of 20 blank cards.
for i = 1 to arraydimensions is basically flipping the cards over one at a time in these two decks. One deck is blank and one has data. Both decks hold 20 cards.
In the original deck, I get to card 2 with a value of 2. It is determined to be "shot down". Card 2 in the blank deck has nothing on it. I copy the value of two and hand-write it onto the second card of the blank deck.
newship(i).x = ship(i).x
So now the data has been copied. Great! But the problem here is that if I compare card 2 in both decks, the data is the same. I can't have this because it triggers a "hit detection" condition.
So after I copy the data to the blank 2 card (which now has a value of 2), I go to the original 2 card and give it a new value.
ship(i).x = -500
If we were to view the values:
newship(i).x = 2
ship(i).x = -500
So theoretically when I compare these two cards in their separate stacks, there should be no "hit detection" conflict. The values are not the same.
So now while it's fine for card 2 in the blank deck to be compared against card 2 in the original deck, I still need to get card 2 to be compared against all of the remaining cards in the original deck.

Clear as mud? No worries! Like I say this is driving me nuts trying to figure it out! :)
Take an array, isolate specific parts of that array, then compare those parts against the original array. That's essentially what I'm trying to do. How would you do that?

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Comparing array data
« Reply #3 on: May 22, 2020, 10:21:41 am »
Are your ships and so on stored in a UDT? If yes, can you add a variable that denotes the "species" of the object on hand? That's one way you can steer around objects into certain loops or branches of code.

A good rule of thumb is to structure your data in a way that algorithms can be extremely stupid.
You're not done when it works, you're done when it's right.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Comparing array data
« Reply #4 on: May 22, 2020, 11:00:20 am »
Are your ships and so on stored in a UDT?

If by UDT you mean data types, then yes, I do use those (a lot!)

For example, my "Fighter" datatype looks like this (abridged version):

Code: QB64: [Select]
  1. TYPE FIGHTERS
  2.     HEIGHT AS INTEGER
  3.     X AS INTEGER
  4.     Y AS INTEGER
  5.     XKILLBOX AS INTEGER
  6.     YKILLBOX AS INTEGER
  7.     KILLED AS INTEGER
  8.     ACTIVE AS INTEGER
  9.     ICONPICKEDUP AS INTEGER
  10.     RANDOMICON AS INTEGER
  11.  

and hit detection (between the player and a fighter) looks like this (and works perfectly fine):

Code: QB64: [Select]
  1. for inf = 1 to numfighters
  2.  
  3.         '   - player collides with destroyed fighter
  4.         IF fighters(inf).KILLED = 1 AND fighters(inf).ICONPICKEDUP = 0 AND (player.X + player.WIDTH >= fighters(inf).XKILLBOX) AND (player.X <= fighters(inf).XKILLBOX + fighters(inf).WIDTH) AND (player.Y <= fighters(inf).YKILLBOX + fighters(inf).HEIGHT) AND (player.Y + player.HEIGHT >= fighters(inf).YKILLBOX) THEN
  5.             ' [do stuff]
  6.  
  7.  

I can label things all day long. For example, if a fighter is identified as "shot down", I set fighters(inf).killed = 1 (true).

What doesn't work is if I do something like this, where I'm trying to get the fighters to "hit detect" against their fellow fighters that have been "shot down".

Code: QB64: [Select]
  1.     FOR inf = 1 TO numfighters
  2.        
  3.             IF fighters(inf).KILLED = 1 AND fighters(inf).ICONPICKEDUP = 0 AND (fighters(inf).X + fighters(inf).WIDTH >= fighters(inf).XKILLBOX) AND (fighters(inf).X <= fighters(inf).XKILLBOX + fighters(inf).WIDTH) AND (fighters(inf).Y <= fighters(inf).YKILLBOX + fighters(inf).HEIGHT) AND (fighters(inf).Y + fighters(inf).HEIGHT >= fighters(inf).YKILLBOX) THEN
  4.            
  5.             fighters(inf).ICONPICKEDUP = 1
  6.         END IF
  7.     NEXT
  8.  

And in the above example I suspect that's because I'm comparing things against themselves.

I've tried something like below where I use a second array, but that doesn't work either.

Code: QB64: [Select]
  1.  
  2.     FOR inf = 1 TO numfighters
  3.      
  4.         IF (fighters(inf).X + fighters(inf).WIDTH >= fightersicon(inf).XKILLBOX) AND (fighters(inf).X <= fightersicon(inf).XKILLBOX + fightersicon(inf).WIDTH) AND (fighters(inf).Y <= fightersicon(inf).YKILLBOX + fightersicon(inf).HEIGHT) AND (fighters(inf).Y + fighters(inf).HEIGHT >= fightersicon(inf).YKILLBOX) THEN
  5.          
  6.             fighters(inf).ICONPICKEDUP = 1
  7.         END IF
  8.     NEXT
  9.  
  10.  

Finally, I just tried this and no dice here either:

Code: QB64: [Select]
  1.     FOR inf = 1 TO numfighters
  2.         FOR i = 1 TO numfighters
  3.             IF (fighters(inf).X + fighters(inf).WIDTH >= fightersicon(i).XKILLBOX) AND (fighters(inf).X <= fightersicon(i).XKILLBOX + fightersicon(i).WIDTH) AND (fighters(inf).Y <= fightersicon(i).YKILLBOX + fightersicon(i).HEIGHT) AND (fighters(inf).Y + fighters(inf).HEIGHT >= fightersicon(i).YKILLBOX) THEN
  4.            
  5.                 fighters(inf).ICONPICKEDUP = 1
  6.             END IF
  7.         NEXT
  8.     NEXT
  9.  
  10.  

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Comparing array data
« Reply #5 on: May 22, 2020, 11:36:46 am »
Hey man,

Thanks for the elaboration. I have read and re-read your question from the top, and I think I see the pain this is causing. While there may be a way to salvage what's going on I wonder if the right approach might be something else. Are power-ups somehow considered as ships? I ask because why not simply delete a ship and create a powerup at its location? Just pluck from one array and pop it to the other.

In crappy psuedo code, the jth enemy that has a chance of generating a powerup on death this might behave like:

Code: [Select]
if (enemy(j) blowing up = true) {
  if (generate powerup = true ) {
    x0 = enemy.x
    y0 = enemy.y
    let k = newpowerup(x0, y0)
  }
  let enemy(j).alive = false
}

The powerup has an "identity" index given by k, which you can determine however you want, so long as its one k per powerup. (This can be like its position in an array.)
« Last Edit: May 22, 2020, 11:38:59 am by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Comparing array data
« Reply #6 on: May 22, 2020, 11:44:38 am »
Are power-ups somehow considered as ships? I ask because why not simply delete a ship and create a powerup at its location? Just pluck from one array and pop it to the other.

Yes! You're right! When the fighter is destroyed, it displays a "powerup" icon, but in reality it is still part of the fighter datatype.

As far as plucking from one array and putting it in the other, that's what I thought this was doing:

newship(i).x = ship(i).x

But I will definitely keep your alternate method in mind!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Comparing array data
« Reply #7 on: May 22, 2020, 11:47:49 am »
Perfect, we're on the same thread. I suppose the essence of what I'm seeing is that in

Code: QB64: [Select]
  1. newship(i).x = ship(i).x
  2.  

We don't need i on both sides. This is rather ... "rigid"? Anyway. Best of luck m8!
You're not done when it works, you're done when it's right.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Comparing array data
« Reply #8 on: May 22, 2020, 11:54:16 am »
Breakthrough!

Sorta.

I tinkered around with a few different things and go this to work:

Code: QB64: [Select]
  1.  
  2.     FOR inf = 1 TO numfighters
  3.         FOR i = 1 TO numfighters
  4.  
  5.             IF fightersicon(i).KILLED = 1 AND fightersicon(i).ICONPICKEDUP = 0 AND (fighters(inf).X + fighters(inf).WIDTH >= fightersicon(i).XKILLBOX) AND (fighters(inf).X <= fightersicon(i).XKILLBOX + fightersicon(i).WIDTH) AND (fighters(inf).Y <= fightersicon(i).YKILLBOX + fightersicon(i).HEIGHT) AND (fighters(inf).Y + fighters(inf).HEIGHT >= fightersicon(i).YKILLBOX) THEN
  6.  
  7.                 SELECT CASE fighters(inf).RANDOMICON
  8.                     CASE 1 ' speed upgrade
  9.                         eupgradespeed = eupgradespeed + 1
  10.                     CASE 2 ' width upgrade
  11.                         eupgradewidth = eupgradewith + 10
  12.                         eupgradeheight = eupgradeheight + 20
  13.                         eshotnum = eshotnum + 1
  14.                     CASE 3 TO 7 ' damage upgrade
  15.                         eupgradedamage = eupgradedamage + 10
  16.                 END SELECT
  17.                 fighters(inf).ICONPICKEDUP = 1
  18.                 fightersicon(i).ICONPICKEDUP = 1 'WORKED!!!!! but didn't upgrade shot stats
  19.             END IF
  20.         NEXT
  21.     NEXT
  22.  
  23.  

It seems like the
fightersicon(i).ICONPICKEDUP = 1 was the main thing that got it working, although there were a few other changes I had made in other subroutines.

So it appears that my idea of copying data from one array to another still works because now the powerup icons vanish from the screen when any of the other enemy fighters pass over them. Just what I was looking for!

Only issue now is that the powerups aren't activating like they should for the enemy ships. Pretty sure this will be an easy fix once I track it down.

Thanks to all so far for your help! I make a point of adding the names of people that help me to the Credits section of my game. In terms of QB64 support, I've been thankful for the help of:
FillippeHeitor
bplus
Petr
TerryRitchie
MastyGy
SMcNeill
StxAxTIC
OldMoses
TempodiBasic

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
Re: Comparing array data
« Reply #9 on: May 22, 2020, 12:58:54 pm »
I wish you luck with it, but I didn't do enough to garner a mention.

EDIT
Quote
Clear as mud? No worries! Like I say this is driving me nuts trying to figure it out! :)
Take an array, isolate specific parts of that array, then compare those parts against the original array. That's essentially what I'm trying to do. How would you do that?

I generally do a nested loop of some sort. The outer loop goes through the list, each one being active in turn and then run through the list on the inner loop, which if necessary, is contained in an IF...THEN condition that keeps the program from comparing a unit with itself and/or excluding units that are too distant for comparison. It all depends on how your units interact with each other.

I've been working on a billiards program that is deviling me on a similar issue.
« Last Edit: May 22, 2020, 01:09:16 pm by OldMoses »