Link to my project
I have been working on this game for several months off and on and have come to a bit of a plateau in terms of development.
I've ran into several issues and it is becoming increasingly more complicated and harder to expand. My original vision was to test my ability to code an advanced project that would be fun to play. I definitely modeled this game off the roguelite game "Brotato" as it seemed simple enough while leaving plenty of room for challenge. I got a fluid movement system working, a sort of camera system, and many other tiny details that took me longer than I'd like to admit. I just recently implemented enemies, so they have very primitive tracking towards the player and no collision (so they pile up on each other). The enemy health system is the thing that's giving me trouble currently, as it's inconsistent and janky. I feel like I could very well be doing things wrong fundamentally on this project, because I don't know how I'm going to fix this and then add a player health system, collisions between enemies, let alone different modifications, weapons, enemies, leveling, or even just a basic gameplay loop. Any advice would be greatly appreciated.
What exactly are you having trouble with? Getting enemy health working? Getting player health working? Adding collisions? We can't really help if you don't have a specific thing you want help with right now. It can also help if you explain what you're currently doing to try and achieve it.
I want to know if there's a better way to do enemy health, the way I have it only somewhat works, it subtracts from the enemyhp local variable which seems to work independent from the enemy clones, but it has to wait until not touching bullet to not instantly kill the enemy. This is a problem if you have a fast firerate, as it will not subtract health because it is always in contact with at least one bullet. Any suggestions?
(note: most variables are located on the stage for you to mess with)
You could try despawning/deleting the bullets when they reach the witch:
(my [neighbours V]) is a handy block for accomplishing this.
Oh ok! I had looked at my neighbors but couldn't figure out how it worked. I guess it lists all the sprites in order of how far away they are? Also if that is how it works would it not detect the background as the closest sprite? I will have to try this out. Will edit with the result once I get back home.
That is correct.
It will, that is why we look for the closest sprite that is a clone of the sprite "Bullet" (aka it's parent is the sprite "bullet"). This is accomplished with the "find first item" block.
I did what you said, and it works great! Only thing is I want to understand how this works a little better, as it seems to be pretty damn useful. I understand finding the first item in my neighbors, and that we look for the closest sprite that's a clone of the sprite "Bullet", but could you explain a bit more how this script works:
ask () for my (parent) = object (Bullet)
What happens when you leave that ask field blank? and then doesn't the = operator block output a true/false? if so, how would that be a valid entry to a list search? Sorry if these are dumb questions, I just wanna push the boundaries of what I know in "Snap!".
the blank field will be replaced with whatever item of (my [neighbors]) is currently being checked.
the find first item block actually expects a true/false expression, because basically what it does is it goes through all the list items, one by one, and tests the expression with said list item as an input. if it returns false, then it moves on to the next item, otherwise, if it returns true, it will stop checking for list items and will output the list item that the expression returned true for.
tl;dr the find first item block tests that expression returns true for each item.
Does this make more sense to you?
The find first item iterates through the list (in this case, the neighbours) until it finds an item which fits the given requirement (in this case, it's parent is the bullet sprite).
Empty slots are filled automatically to help beginners understand, just like +3=5 is the same as x+3=5.
that actually does make a lot of sense. How did you figure out when you could leave things blank? This specific use case definitely is gonna help alot for lots of different things in this project, but how on earth did you figure out leaving stuff blank would ask the first item in my neighbors?
Well, it all began when I learned about rings from the Snap! manual. Things like:
are much simpler examples of how this works. From there, it was a small leap to understand this:
And as time has gone by using empty slots has become second nature to me. But sometimes it helps to name the inputs, especially when you don't want empty slots to be automagically filled.
If you want to understand the script a bit better, you might want to consider turning on visible stepping. Pull the slider in visible stepping all the way down, and slowly click through using the repurposed pause button to see what is actually going on.
In terms of the find first item block specifically, here are some simple examples:
Note the difference between FIND FIRST and KEEP:
PS: Empty slot filling is the reason why ALL menus have an empty slot option.
PPS: Sorry that I didn't explain in as much detail earlier - I wasn't sure how much you already knew ;).
Wow, this all actually helps a ton. Thanks for taking the time to explain!
The only other problem I have now that I'd like to ask (I know I'm going way past just one thing, this is just really helpful) is how I would start going about adding a slight barrier around the centers of the enemies so they don't bunch together. If it was just based off their sprite art, I would probably change them all to little balls or something. Is there a way to add collisions like that where they have a sort of hitbox that's seperate from their art? This sounds like it'd be quite complicated to do, but I thought I'd throw it out there since I probably won't find the answer myself anytime soon.
Again, thanks for the help this genuinely has gotten me to think about snap! differently and understand it more, definitely is gonna streamline stuff in the future.
As far as I know, that is the best way to go. But, you could make a second clone which looks like a witch and follows the hitbox, covering it up (this will double the number of clones you'll need, so if you plan on lots of enemies, this might slow down Snap!/your game). Alternatively, you could make a hitbox costume and only switch to it when you are checking for collisions, and then switch back once you are done. If you can manage do this fast enough or if you use the warp{ } block (which suspends screen updates, among other things) the costume switch won't even be visible on the screen.
If you just want to have circle hitboxes, then the best thing would actually be to use the ([distance V] to [ V]) block. If you stick a sprite in the second slot, and this can also be an item from (my [neighbors V]) , it will calculate the distance between the sprite that ran the script and the one in the input. Here's why distance is important to this. Distance between 2 points is always the radius of a circle, aka, the center to the edge of a circle. If you take the distance, subtract the hitbox radius of the current sprite, you get the distance from the center of the other sprite to this sprite. You can then subtract the radius of the other sprite hitbox to get the distance between the two hitboxes. If the value is negative, then the hitboxes are overlapping, and if it's positive, they're not.
Here's a script that demonstrates this
I knew there had to be a better way. I've only ever tried to make this kind of project in Scratch, which doesn't have "distance to", so it slipped past my radar. Nice work!
Well, it's already super easy to calculate the distance, it's just the pythagorean theorem, a^2 + b^2 = c^2, aka ([sqrt V] of ((((x2) - (x1)) ^ (2)) + (((y2) - (y1)) ^ (2))))
You're right. I guess it was the collisions that were easier to code by simply using a costume... It has been too long since I've used Scratch.