Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers AppGameKit Corner / Hi guys, im making space invaders, some basic questions about sprite collision

Author
Message
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 2nd Jul 2018 12:00 Edited at: 2nd Jul 2018 12:14
Hello everyone,

Im onto my second project on AGK. I'm very much a beginner at coding, this is my first time using functions. If anyone has any criticism of the way I'm coding please post it up, I would love to learn the easier/smarter way to do things.

I've written 1 level of a space invaders style game, where the player can shoot up to 4 bullets.

I'm having a little trouble with the killed enemy sprites still colliding with the bullets. I'm not sure what the command is to turn off collision detection when I turn the sprite to invisible. Or would I be better off deleting the sprite and then only checking for collision if it exists?

All the code and media is below.

Attachments

Login to view attachments
kaband
15
Years of Service
User Offline
Joined: 22nd May 2003
Location: Chicago
Posted: 2nd Jul 2018 20:35 Edited at: 2nd Jul 2018 20:37
I have a game that I'm working on - not Space Invaders, but close enough. I also use getspritecollision to check each bullet against the active "invaders" (baddies in my case). If there is a collision, I delete the sprite then mark the invader as inactive, so I don't check it again in the future - only checking those sprites that Active = 1. If you do GetSpriteCollision against a sprite that has been deleted you will get an error. Small example below. There may be a better way, but from a performance perspective, I have plenty of FPS. I cap it at 60. You could also just move all the sprites offscreen after it gets hit. SetSpritePosition(invaderSpriteID,8000,8000) then clean them up after the level is over.

Phaelax
DBPro Master
15
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 2nd Jul 2018 21:33 Edited at: 9th Jul 2018 13:02
Simple, stop checking the sprite for collision.

Right here you're checking every sprite no matter what:


You could delete the sprite whenever it's killed, but I think it would be better if you unloaded them when the level ended. Plus, it wouldn't work with the current structure of your game. Your enemies are sprites 2-11, but what happens in the above code if you kill off number 7? If the sprite is deleted, your loop will still try to check collision with it but you'll get an error because it won't exist.

What you need to do is flag an enemy (or bullet) as active or inactive. I see where you use setSpriteActive, but that only stops the animations and physics from updating and doesn't remove it from collision detection. But we can use this still by checking if it's active BEFORE calling the collision.




Personally, I'd suggest ditching the way you've managed your sprites, relying on the indices like that, which you have enemy sprites as 2-11. It's not easy to reference what those numbers are. A UDT would improve this a lot. You also load the player's bullets in a function called loadEnemies(), functionally fine but is misleading when reading code. Use variables instead of just numbers, as it will make coding way easier. I mean, what's easier to remember? What number references the red tree sprite in a game? Or have a variable called redTreeSprite which is assigned that sprite number?

Another tidbit is to look at cloneSprite(). If your enemies all use the same image, you can clone the sprite instead of creating new ones. It's a little more efficient in terms of loading speed and memory usage.

Containing your enemy data (including sprite IDs) in a UDT structure will help you manage the sprites better. Plus it'll be easier to track what you have in the array. Your code shouldn't need to change much between levels if you set everything up right. Maybe setting a different sprite image or number of enemies, but the loading code should stay roughly the same and be reusable (the beauty of functions).

Here's a rough example demonstrating some of the things I've mentioned.
Tiled TMX Importer V.2
XML Parser V.2
Base64 Encoder/Decoder
Purple Token - Free online hi-score database
Legend of Zelda

"I like offending people, because I think people who get offended should be offended." - Linus Torvalds
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 4th Jul 2018 15:42
WOW.

That is some really really great advice.

I will re-write the program and reupload using UDT's. Lots of learning
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 6th Jul 2018 23:01
Ok i've been staring at the code you have written and I have some questions if you have the time.

1) Why does variable _spr_enemy have underscores?

2) In this part below, what does the x*64,100 do?
for i = 1 to 10
    invaders.insert(makeEnemy(x*64, 100))
next i

Thanks
IronManhood
4
Years of Service
User Offline
Joined: 6th Feb 2015
Location: US
Posted: 6th Jul 2018 23:34
1) Adding underscores to a variable name does nothing other than improving readability. So essentially, it's just a programmers preference as it doesn't affect the code in any way.

2) I think you need to change the x to an i, looks like a typo:
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 7th Jul 2018 20:13
Thanks for clearing that part up.
lastly, why does it have the i*64 , 100 in the line? What do those numbers do?
IronManhood
4
Years of Service
User Offline
Joined: 6th Feb 2015
Location: US
Posted: 8th Jul 2018 00:02
The MakeEnemy( x, y ) function creates a new sprite and sets its position to the x and y parameters. MakeEnemy() simply returns the user defined type and then it's inserted into the invaders user defined type array. The variable "i" is incremented on every iteration of the for loop until it reaches 10 then the for loop is exited. "i * 64" is used to set the position of the newly created sprites on the x axis. "i" changes on every iteration of the for loop and this results in a series of sprites in the horizontal direction on screen.

x = 1 * 64 = 64
x = 2 * 64 = 128
x = 3 * 64 = 192
x = 4 * 64 = 256
x = 5 * 64 = 320
x = 6 * 64 = 384
x = 7 * 64 = 448
x = 8 * 64 = 512
x = 9 * 64 = 576
x = 10 * 64 = 640

"100" sets the "y" axis of the new sprites position.
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 8th Jul 2018 16:05
Cool . That make a lot of sense.

I noticed that there are 4 pieces of information in the Invaders user type. When you called the makenemeies function, you let it know that 2 of those pieces of information are x=i*64 and y=100.

There doesn't appear to be anything in the code which says that these values should be x and y, instead of the variables active and ID.

How does the makenemies function know that those are meant to be for x and y?
Phaelax
DBPro Master
15
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 9th Jul 2018 13:09
Quote: "1) Why does variable _spr_enemy have underscores?"


Quote: "1) Adding underscores to a variable name does nothing other than improving readability"


Exactly. I use underscores for Global variables. I also prefix it with "spr" so I know it's a sprite number. With my naming scheme, I can look at this and know this variable contains a sprite ID number and is a global.

Quote: "2) In this part below, what does the x*64,100 do?
for i = 1 to 10
invaders.insert(makeEnemy(x*64, 100))
next i
"


Oops, yea it was a typo and should have been i*64. All this does is space out the enemies every 64 pixels.

Quote: "lastly, why does it have the i*64 , 100 in the line? What do those numbers do?"

Look at my function header for makeEnemy(), it explains what the parameters are.

Quote: "There doesn't appear to be anything in the code which says that these values should be x and y, instead of the variables active and ID.

How does the makenemies function know that those are meant to be for x and y?"


If you look at the function, it explains the enemy is initialized with a position. The UDT called Invader contains variables for storing these values. MakeEnemy(x,y) will create a new variable of type "Invader", store the X and Y values in it that were passed into the function, mark the enemy as active, and assign a sprite ID. All this is store in that custom UDT format. Then the function returns that variable where it is inserted into the array which stores all enemies.
Tiled TMX Importer V.2
XML Parser V.2
Base64 Encoder/Decoder
Purple Token - Free online hi-score database
Legend of Zelda

"I like offending people, because I think people who get offended should be offended." - Linus Torvalds
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 26th Jul 2018 03:29
Thanks for your continuing help.

I have started playing again, took a few weeks off.

I have another question about this line of code from your example


Global _Spr_Enemy = createSprite(loadimage("basicenemy.png"))

It doesnt work when i compile it , I get the error
variable default value must be an integer literal or constant.
Supertino
1
Years of Service
User Offline
Joined: 22nd Jun 2017
Location: Behind you!
Posted: 26th Jul 2018 09:51 Edited at: 26th Jul 2018 09:51
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 28th Jul 2018 12:41 Edited at: 29th Jul 2018 17:27
Hey dudes.

I have been using the UDT as suggested, thanks for the help.

There is one problem

The ID being inserted into the array is coming back as 0000. I have been trouble shooting by adding a while loop and printing the ID, and checking each ID as it is created. They are being created as the right ID number, it is only when it gets passed back that the n.id changes from 10001,10002,10003 etc to all of them being 0.

This is why i have added the while getrawkeypressed for spacebar and the print and sync commands. I literally watch n.id change from 10002 to 0 when it becomes fastenemy[i].id

Again this could be really simple but this is my first time using functions that return a value, also my first time using variables that are equal to a command that returns a number. So I could have seriously botched it and not know.

puzzler2018
User Banned
Posted: 28th Jul 2018 12:46 Edited at: 28th Jul 2018 12:46
Lets have a look at your makefast() function, it will be something in there

Edit - doh - i see the function - ignore me been a long week
puzzler2018
User Banned
Posted: 28th Jul 2018 12:51 Edited at: 28th Jul 2018 12:54
as far as i can understand the "n" is a local variiable in the makefast() function and anything defined in there will always stay in there

Make Fastenimies a global or create N at the top and pass it through the function



or



Not tested

but something along those lines
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 28th Jul 2018 13:08 Edited at: 29th Jul 2018 17:26
Jus tested making fastenemies Global.

the fastenemies.id values still become 0. Very interesting that the x and yvalues are preserved but the id value becomes 0!

EDIT

Just tested making n a global array prior to using it in the function. It also changed the IDs to 0!

puzzler2018
User Banned
Posted: 28th Jul 2018 13:50 Edited at: 28th Jul 2018 13:55
Try this



In the array declaration you put [6] - if use insert then need to be empty so just use []

You would have seen the results if looked at 7,8,9,10 in the array - cause you started the array off with 6 the first 6 will be all empty and then inserts to 7,8,9,10 ect

hope that helps

Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 28th Jul 2018 14:49 Edited at: 29th Jul 2018 17:26
IT WORKED!

Also when checking I made the for i=0 to 5 instead of 1 to 6. (I was getting an error for array length out of bounds)
puzzler2018
User Banned
Posted: 28th Jul 2018 14:52 Edited at: 29th Jul 2018 07:18
always put .length on any for loops

JLMoondog
Moderator
10
Years of Service
User Offline
Joined: 18th Jan 2009
Location: Paradox
Posted: 28th Jul 2018 21:46 Edited at: 28th Jul 2018 21:48
Hey Thomas+others, make sure you put all code within the code brackets and AppGameKit using the AGKcode brackets which includes syntax highlighting. Which you can select just above the reply post emoji's, between the spoiler and video buttons. This rule has been recently added to the AUP, so this is just a friendly warning. Thanks!
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 29th Jul 2018 17:28
Groovy i just edited the posts so now they are all in code brackets
Thomas John Gorham
User Offline
Joined: 23rd Jun 2018
Location:
Posted: 31st Jul 2018 10:33


Hello everyone. So there it is. My second project with AppGameKit is finished. Or as finished as I want to go I think I've learnt what I wanted to learn. It's interesting you can see how the naming of variables changed as I listened to people in the thread, and the way collision detection and everything is handled after learning about UDTs. Thanks everyone for your help, the next thing I want to make is an infinity runner, this one I want to be downloadable and playable on phones so I will give it a main menu and highscore and all that.

See you on the next project
Phaelax
DBPro Master
15
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 31st Jul 2018 12:38 Edited at: 31st Jul 2018 12:38
Nevermind.
Tiled TMX Importer V.2
XML Parser V.2
Base64 Encoder/Decoder
Purple Token - Free online hi-score database
Legend of Zelda

"I like offending people, because I think people who get offended should be offended." - Linus Torvalds

Login to post a reply

Server time is: 2019-03-23 16:52:06
Your offset time is: 2019-03-23 16:52:06