On overlap

Hi! I have a student who wants to have the snake in his game destroy when his player overlaps the snake and then hits the A key where the sword extends. It works for the first snake, but it doesn’t work for the others. Here is his code so far - https://makecode.com/_2mJRXXhmv076

What am I missing on how to fix this? Thanks in advance!

The problem is coming with the relationship between creating the snakes and checking the overlap. Because all snakes are being named “snake” when created, that name is getting passed along the chain and only applies to one snake at a time. Then, because the student is using a conditional to check for that exact name, it will only hit the one time.

The workaround would be something like I show below:

The logic for the student’s solution is sound, we just don’t appear to have a block (yet) that checks to see if a sprite is overlapping something of a kind.

Hopefully one of my colleagues will correct me if I’m forgetting something!

1 Like

Thanks so much! This is super helpful. We tried to use the on sprite of kind overlap event handler, but we had “snake” in the destroy block instead of “other sprite.” I’m glad we weren’t too far off. :slight_smile:

Me again :slight_smile: Another student has an issue I cannot solve. He is trying to make it where the “zom” is either destroyed by the player or by going off the screen, and once “zomnumber” = 0 the player should win. The program, however, isn’t showing “win” when all of the “zoms” move off the screen. We think it has to do with the on destroyed of sprite of kind zom event handler, but we can’t figure out what to do to fix it. Thanks in advance!

One thing that can be helpful in cases like this is to add in something that shows up on the screen to help with debugging - for example, adding to a score so that you can see how many sprites are destroyed.

In this case it will give a hint on what the final issue is; you’ll see that the score only goes up by 1 if you let all the zoms go off screen - perhaps most interesting is that it will only go up by 1 when the last zom goes off screen, which is a good thing to take note of as it is a common indicator for this ‘class’ of bugs. The issue here is where this block is placed:

It’s separated out after the part where the zoms are created, so it only applies to the last zom that is created. To make it work as expected, you can either put it into the two loops that create the zoms, or put it into an on created like this:

image

(note that it’s using the sprite parameter and note Zom).

Looking at it, I think the intention was for the flag to apply to the Zom kind, rather than the Zom variable. I’m a little surprised actually because I thought we rejected kinds with the same name as variables which helps in cases like this.

1 Like

Thanks! I wondered about the placement of the set auto destroy block. I pulled it out but didn’t think to change where it was located. I also mentioned to the student that I didn’t think it was best practice to have the kind named the same as the variable. I appreciate your help!!

Hi again. My student revised the program to reflect your suggestions, but he is now seeing a new problem. When the student enters a number for his enemies, it will not produce that number of enemies. So, if he enters 5 enemies, it produces 3. If he enters 77 enemies, it produces 43. So, since it won’t create the number of enemies the player enters, it will never meet the win condition. Thanks in advance for your help.

These two blocks of code aren’t playing together nicely:

It might be easier to see the problem if you look at the what the repeat {n} times block converts to in typescript:

for (let index = 0; index < ZomNumber; index++) {
    Zom = sprites.create(img`
            ...
        `, SpriteKind.Enemy)
    Zom.setPosition(3, 60)
    Zom.setVelocity(70, 0)
    pause(500)
}

The important part here is that the index < ZomNumber is re-evaluated each iteration of the loop, and since there is a pause in it, the on destroyed event has a chance to run, which is changing the value of ZomNumber. This means that when an enemy is destroyed while the loop is still producing zoms, it will not create enough zoms because it lowers the ZomNumber it is checking against. Easiest fix would be to not change the ZomNumber in the on destroyed, and instead build up another value – e.g. could add a ‘destroyed zoms’ variable to compare against ZomNumber or check if current score equals ZomNumber.

I’m somewhat inclined to call the current ‘repeat x times’ blocks buggy with this, as we could instead produce

for (let index = ZomNumber; index > 0; index--) {
    Zom = sprites.create(img`
        . . .
        `, SpriteKind.Enemy)
    Zom.setPosition(3, 60)
    Zom.setVelocity(70, 0)
    pause(500)
}

and this would then ‘just work’ as expected / wouldn’t have similar issues. That said, there’s some inertia here in that the block has been the same for several years so it might be a breaking change / etc (we could add it as a ‘new’ block that looks the same but behaves in the new way). I’ll tag in @richard here in case you have any thoughts

1 Like

yes, i’ve also thought that the repeat block was a little deceptive for this reason. in particular this piece of code is very tricky:

image

2 Likes

BTW for the curious, I ran that code 10000 times to see what the distribution would be and here it is:

1: 1005
2: 1724
3: 2127
4: 2126
5: 1518
6: 894
7: 428
8: 140
9: 37
10: 1

It made it to the end all of 1 time!

2 Likes

Yeah, that feels like a really easy piece of code to write, I’ll file it. (edit: filed here: https://github.com/microsoft/pxt-arcade/issues/5231)

1 Like

Thanks @jwunderl and @richard!

We appreciate your help!

1 Like

I noticed you and @jwunderl have the same art style in you’re profile photos who made those Profile Photos
and What art software was that?

@shakao made them!

so can i ask @shakao for the art software shakao used?