UPDATE: Please note that SGDK has been updated since this video was created. If you are using a version of SGDK newer than 1.7, then please write "SPR_init();" instead of "SPR_init(0, 0, 0);" and it should compile fine :)
As usual, feel free to ask any questions in the comments. I will be spending the rest of the weekend working on the SotN game, but will check back for any issues later. I was pretty damn tired when I edited this, so I hope there aren't any mistakes :) Hope every has a great weekend!
Maybe to explain why #define is more suitable here: A #define is a preprocessor directive, which gets replaced by the value given to it during compilation. So basically, the #define is just a method to make something more human readable and make it easier to understand. This kind of technique saves valuable RAM space, since the value isn't stored in RAM but instead directly written to the variable already declared. The const int would declare 16Bit space in RAM and a read from it will copy the value from it to somewhere else, while the #define is just a number in your assembler code. On the other hand, you can't overwrite a #define with another value ;)
Thanks for the explanation. In the videos I try to strike a balance between explaining things without getting too bogged down in technical stuff, but I appreciate it when people add knowledge in the comments, so thanks - I often end up learning something myself! :)
@@PigsysRetroGameDevTutorials Yeah, getting the balance right is kinda hard. But there are some crucial basics people have to go through in order to understand what they are doing properly, so I thought it's better to explain this a bit, because it could save a lot of RAM and a lot of headache :) Would be nice to see some inline ASM or real ASM programming, but I guess this is way too complicated for most people without programming knowledge :D
Great, great, great. This series is awesome. I'm planning on starting a little project now, so I'm getting back into programming thanks to you, man. I really, really appreciate your efforts publishing these tutorials. Thank you very much!
This is becoming an epic series already, thank you so much for the knowledge and breaking the information down more simply. Keep up the amazing work. Also that first track sounds so familiar but I can't place it, what's it from? 🤣 Good luck with adding more to SOTN. 💜
I really appreciate these videos when it comes to the Genesis and one thing I finally understand is how the Genesis can use sprites as small as 8x8 and as large as 32x32 making it the most customizable 16-bit sprite system of that era by comparison to the Turbo Grafx 16 and Super Nintendo. Out of curiosity I ran your SOTN Christmas demo in an emulator called Exodus that includes sprite outlining in it's debugging mode so you can see where and what the sprites are doing in real time. It was neat seeing that the trees in the background weren't part of the tile maps like I had assumed and actually were sprites. But what was even more fascinating was how Alucard's sprite was constructed. Instead of it being assigned to the same sprites, every single frame of his animation seemed pieced together with different meta sprites in creating his whole image. Was that something you had to do by hand or was it something that's automatically part of the SGDK? I saw this sprite swapping not only with your game but pretty much every genesis game I loaded would seemingly or dynamically shuffle around meta sprites on a frame by frame basis. The Mesen Sour emulator has that same debugging feature of outlining sprites and since it supports GB/GBC, NES, PC Engine, and SNES I saw the same style of sprite shuffling with those systems as well. 😃
This is awesome. At some point (I know is getting ahead of myself here) if you could teach us the way to duplicate character slots to create blank ones and add new characters to preexisting games as well? I'd love to see or maybe even attempt a mashup of all Sega characters in Bare Knuckle III. And they're big names they got under their belts too from the Genesis Era... Michael Jackson, Bruce Lee, a custom Joe Montana sprite or something... Joe Musashi, Sonic (and Friends), etc. Also don't know if that would be the appropriate approach with what I asked above... But I hope you still get what I mean. Probably way more of a complex process than something as simple as that, I would assume. But if not, that'd be a lovely surprise.
I actually don't know how to do rom hacking (which is what you'd need to input other characters into existing games). I only know how to make them from scratch!
@@PigsysRetroGameDevTutorials oh, definitely! we should always use the KISS method (Keep It Simple Stupid) 🤣. Ah, Congratulations for what u r doing bro! (y)
I'm not 100% sure tbh, so don't want to say. With const you define the data type too (u8, u16 int), so I'm not sure what data type define uses when you input a number.
@@PigsysRetroGameDevTutorials DEFINE would be a compilation pre processor So before compiling it would go through and replace it as though you typed it in. In that case it would be a const, I believe. Actually with that in mind I believe it might actually be less efficient because every instance of using that it would create a new constant in memory I can't confirm that I really don't know for sure. But I do know for sure that if you declare a const variable in the class you definitely only allocate it once.
Update on this, so in C a const is just a normal variable with constraints on how it's used not differences in how it's allocated. A DEFINE is a preprocessing directive, basically it will do a replace all on the code, so those would be what would typically be described as being literals in other languages. It appears the efficiency of the constant comes down to the compiler and how smart it is. My concern would be if you used a constant multiple places if it would store and use that value separately each time. Im unclear on if it does. I found a relevant link: stackoverflow.com/questions/1576489/where-are-constant-variables-stored-in-c Ex. // variable const foo = 5; int x = foo; // constant int x = 5;
@@Tiptup300 It gets confusing, but define is used by creator of SGDK in his code samples, so I thought it best to follow his example :) Maybe it doesn't make a huge difference anyway
You can change the background tiles on the fly in order to create background animations. I did it a few months back, as I wanted test doing some of the clockwork backgrounds you find in Castlevania games, but I don't think I did it in a clever way. As a crude way, you could simply create a timer, and then reload different backgrounds at certain times to create an animation. I will do a proper tutorial on it once I get competent at the technique myself
Hi, great tutorial.. but i have a problem... the sprite doesn´t show at all... #include #include Sprite* player; int main() { VDP_setBackgroundColor(50); PAL_setPalette(PAL2, axel_sprite.palette->data, DMA); SPR_init(); player = SPR_addSprite(&axel_sprite, 40, 10, TILE_ATTR(PAL2, FALSE, FALSE, FALSE));
while(1) { SPR_update(); VDP_waitVSync(); } return (0); } i don´t know why... maybye is a new update of SGDK and something change again? Thanks in advance...
UPDATE: Please note that SGDK has been updated since this video was created. If you are using a version of SGDK newer than 1.7, then please write "SPR_init();" instead of "SPR_init(0, 0, 0);" and it should compile fine :)
As usual, feel free to ask any questions in the comments. I will be spending the rest of the weekend working on the SotN game, but will check back for any issues later. I was pretty damn tired when I edited this, so I hope there aren't any mistakes :) Hope every has a great weekend!
You're a god, bro.
Thanks!
Cheers!
Awesome video. My Axel is marching through Green Hill zone ready to kick some serious ass.
Haha, sounds great!
Excellent video! I appreciate all your hard work bringing us these tutorials.
I'm having fun making them, so I'll keep them coming!
Maybe to explain why #define is more suitable here:
A #define is a preprocessor directive, which gets replaced by the value given to it during compilation.
So basically, the #define is just a method to make something more human readable and make it easier to understand.
This kind of technique saves valuable RAM space, since the value isn't stored in RAM but instead directly written to the variable already declared.
The const int would declare 16Bit space in RAM and a read from it will copy the value from it to somewhere else, while the #define is just a number in your assembler code.
On the other hand, you can't overwrite a #define with another value ;)
Thanks for the explanation. In the videos I try to strike a balance between explaining things without getting too bogged down in technical stuff, but I appreciate it when people add knowledge in the comments, so thanks - I often end up learning something myself! :)
@@PigsysRetroGameDevTutorials Yeah, getting the balance right is kinda hard. But there are some crucial basics people have to go through in order to understand what they are doing properly, so I thought it's better to explain this a bit, because it could save a lot of RAM and a lot of headache :)
Would be nice to see some inline ASM or real ASM programming, but I guess this is way too complicated for most people without programming knowledge :D
thanks for the extra info! :)
Great, great, great. This series is awesome. I'm planning on starting a little project now, so I'm getting back into programming thanks to you, man. I really, really appreciate your efforts publishing these tutorials. Thank you very much!
All the best with your project!
This is becoming an epic series already, thank you so much for the knowledge and breaking the information down more simply.
Keep up the amazing work.
Also that first track sounds so familiar but I can't place it, what's it from? 🤣
Good luck with adding more to SOTN. 💜
Eswat (as is all the music from this episode)
@@PigsysRetroGameDevTutorials yes! Thank you, now I'm having flashbacks of how hard it used to be to get the power suit. 🤣
@@RetroRanter Yeah, that wasn't easy! I really liked the game though
Awesome video, Pigsy man! Keep up the good work, brother!
Thanks, will do!
I can't wait for this to get further on!!! You already gave me so much homework.
Have fun with the homework :)
@@PigsysRetroGameDevTutorials Finally been doing my homework. Going trough this lessons and making things work is super fun. Thanks a lot! ♥♥♥
I really appreciate these videos when it comes to the Genesis and one thing I finally understand is how the Genesis can use sprites as small as 8x8 and as large as 32x32 making it the most customizable 16-bit sprite system of that era by comparison to the Turbo Grafx 16 and Super Nintendo. Out of curiosity I ran your SOTN Christmas demo in an emulator called Exodus that includes sprite outlining in it's debugging mode so you can see where and what the sprites are doing in real time. It was neat seeing that the trees in the background weren't part of the tile maps like I had assumed and actually were sprites. But what was even more fascinating was how Alucard's sprite was constructed. Instead of it being assigned to the same sprites, every single frame of his animation seemed pieced together with different meta sprites in creating his whole image. Was that something you had to do by hand or was it something that's automatically part of the SGDK? I saw this sprite swapping not only with your game but pretty much every genesis game I loaded would seemingly or dynamically shuffle around meta sprites on a frame by frame basis. The Mesen Sour emulator has that same debugging feature of outlining sprites and since it supports GB/GBC, NES, PC Engine, and SNES I saw the same style of sprite shuffling with those systems as well. 😃
Thanks
Cheers!
This is awesome. At some point (I know is getting ahead of myself here) if you could teach us the way to duplicate character slots to create blank ones and add new characters to preexisting games as well?
I'd love to see or maybe even attempt a mashup of all Sega characters in Bare Knuckle III. And they're big names they got under their belts too from the Genesis Era... Michael Jackson, Bruce Lee, a custom Joe Montana sprite or something... Joe Musashi, Sonic (and Friends), etc.
Also don't know if that would be the appropriate approach with what I asked above... But I hope you still get what I mean.
Probably way more of a complex process than something as simple as that, I would assume. But if not, that'd be a lovely surprise.
I actually don't know how to do rom hacking (which is what you'd need to input other characters into existing games). I only know how to make them from scratch!
@julian blake I'm sure I'll get round to doing a tutorial on that one day.
spectacular content!
I used to create a Struct for animation or sprite use, i like it more than have a lot of variables poping around and makes me crazy
Oh, definitely use structs if you know how. I'm just trying to keep things simple for these beginner tutorials.
@@PigsysRetroGameDevTutorials oh, definitely! we should always use the KISS method (Keep It Simple Stupid) 🤣. Ah, Congratulations for what u r doing bro! (y)
For using photoshop, I had to load in the animated sprite and set the image mode to indexed color and saved over the old version. Then it worked.
VERY GOOD!
thanks!
how would i go about having the idle frame be what ever the current animation frame is?
Does DEFINE not allocate memory for them? I was thinking the compiler would save space on memory if using constants
I'm not 100% sure tbh, so don't want to say. With const you define the data type too (u8, u16 int), so I'm not sure what data type define uses when you input a number.
@@PigsysRetroGameDevTutorials
DEFINE would be a compilation pre processor
So before compiling it would go through and replace it as though you typed it in. In that case it would be a const, I believe.
Actually with that in mind I believe it might actually be less efficient because every instance of using that it would create a new constant in memory I can't confirm that I really don't know for sure.
But I do know for sure that if you declare a const variable in the class you definitely only allocate it once.
Update on this, so in C a const is just a normal variable with constraints on how it's used not differences in how it's allocated.
A DEFINE is a preprocessing directive, basically it will do a replace all on the code, so those would be what would typically be described as being literals in other languages.
It appears the efficiency of the constant comes down to the compiler and how smart it is. My concern would be if you used a constant multiple places if it would store and use that value separately each time. Im unclear on if it does.
I found a relevant link: stackoverflow.com/questions/1576489/where-are-constant-variables-stored-in-c
Ex.
// variable
const foo = 5;
int x = foo;
// constant
int x = 5;
@@Tiptup300 It gets confusing, but define is used by creator of SGDK in his code samples, so I thought it best to follow his example :) Maybe it doesn't make a huge difference anyway
@@PigsysRetroGameDevTutorials
best to follow their advice over strangers!
Cheers!
Do you have any videos that deal with changing animation speeds based on the animation?
Not yet, but I will in the future
Pigsy, what code to use to make the Sega Logo correctly?
I managed to make it work using SPR_addSprite, but SEGA did it using BG_A.
You can change the background tiles on the fly in order to create background animations. I did it a few months back, as I wanted test doing some of the clockwork backgrounds you find in Castlevania games, but I don't think I did it in a clever way. As a crude way, you could simply create a timer, and then reload different backgrounds at certain times to create an animation. I will do a proper tutorial on it once I get competent at the technique myself
Pigsy, thanks for the light.
"GRAND UPPAAAHH!!"
Hi, great tutorial.. but i have a problem... the sprite doesn´t show at all...
#include
#include
Sprite* player;
int main()
{
VDP_setBackgroundColor(50);
PAL_setPalette(PAL2, axel_sprite.palette->data, DMA);
SPR_init();
player = SPR_addSprite(&axel_sprite, 40, 10, TILE_ATTR(PAL2, FALSE, FALSE, FALSE));
while(1)
{
SPR_update();
VDP_waitVSync();
}
return (0);
}
i don´t know why... maybye is a new update of SGDK and something change again?
Thanks in advance...
I love you, but I cant get things set up properly.
Sorry to hear that. Let me know what kind of error message you get and I'll try to help
@@PigsysRetroGameDevTutorials , I will give it another try.