#11327 - RaBBi - Thu Oct 02, 2003 6:33 pm
Hi all,
Here I start to make games on GBA, and games<in general, and there some concepts about main() fonction and vblank interrupt that I don't assimile very well.
I know, if I understood, that VBlank comes 60 times per second, doesn't it?
And I know, also if I understood, that main() loop is called continuously until stop command, like game over.
But if I have a function F in main that is executed more than 1/60 secs (First is it possible????), do the VBlank functions execute too?
And F resume from an interrupted point after VBLANK execution?
And if the execution time of a function VBF in VBLANK take more than 1/60, what's happen?
Does VBLANK mean new frame?
HBLANK take more time and more ressources ?
Sorry, I know that it will make many of you laughing, but I need some "experts" advice to do a really good start with functions that use frame change detection.
Ex: NPC sprites moves when I move my hero, or NPC moves when I display some text as type-writer effect.
Sorry for poor english, I'm french and very ill tonight ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11329 - poslundc - Thu Oct 02, 2003 7:05 pm
RaBBi wrote: |
Hi all,
Here I start to make games on GBA, and games<in general, and there some concepts about main() fonction and vblank interrupt that I don't assimile very well.
I know, if I understood, that VBlank comes 60 times per second, doesn't it? |
Yes, very close to that.
RaBBi wrote: |
And I know, also if I understood, that main() loop is called continuously until stop command, like game over. |
Not exactly. Your AGBMain() function is called once, when the ROM is executed (or the power to the GBA turns on).
You will want to put an infinite loop into this function, and this loop is where you will determine what appears on the screen every 1/60th of a second.
Even when your game reaches "Game Over", you will still want to display a "Game Over" image on the screen, then return them to the title screen, maybe when they press Start or something. All of this should be handled in your infinite loop: as long as you are displaying something on the screen, you are still looping, and on a console like this, the loop doesn't terminate until the player turns the GBA off.
RaBBi wrote: |
But if I have a function F in main that is executed more than 1/60 secs (First is it possible????), do the VBlank functions execute too?
And F resume from an interrupted point after VBLANK execution?
And if the execution time of a function VBF in VBLANK take more than 1/60, what's happen?
Does VBLANK mean new frame?
HBLANK take more time and more ressources ? |
I suggest you take a good, long look at The Pern Project tutorials, or even better, there is an excellent tutorial in french here.
The best advice I can give you is to work through these tutorials bit by bit, and make sure you understand what is going on. You are asking questions about interrupts and cycles, but first you need to learn how the hardware works.
Basically, it takes the GBA 1/60th of a second to draw the screen.
Your code can be running at any point during this redrawing.
However, if your code is running at a point where the GBA is actually outputting a picture onto the LCD screen, and you change the data in that picture, then it will look very bad. You do not want to change that picture while the GBA is drawing it on the screen.
For this reason, the GBA hardware stops when it's done drawing the screen, and waits a while before starting again, so that you can change what it draws without it screwing up the picture. This is what is called VBlank.
A well-designed program will spend the time that the GBA is drawing on the screen figuring out what happens next, handling user input, etc. Then when the GBA is done drawing and enters VBlank mode, the program will update the screen with any changes.
Go, read the tutorials. Try them out for yourself. Learn by doing. Bonne chance.
Dan.
Last edited by poslundc on Thu Oct 02, 2003 7:06 pm; edited 1 time in total
#11330 - niltsair - Thu Oct 02, 2003 7:05 pm
First, you program should never exit from function 'Main', else the game reset. Code: |
bool gReset = false;
void main()
{
//init stuff
bReset = false;
....
while( Reset == false )
{
//Your game logic, loop, etc..
F();
....
}
} |
Now VBlank occurs about 60 times per seconds. It's an interupt, and like all interupt, it means that :
-Program Stop
-Infos concerning current execution are saved
-Code for interupt loaded
-Code for interupt executed
-Code for previous function restored(from save)
-Continue current execution exactly where it left off
So, yes, executing Main takes more than 1/60th seconds, it actually take from when you started the game to the moment you reset/power off it. But it's constantly being interupted by.. well.. interupts :)
Interupts should be very quick to execute. If it takes more time to execute than it takes to generate a new one, then you have a problem. In this case, if it takes more than 1/60th of a second, then you'll program will either crash or stay in the interupt code(depends if you disable int code while in one)
GBA has 160lines that need to be refreshed, but it actually refresh a little more than 228. The period that it's refreshing non-existing screen lines is the VBlank period where it's safe to refresh screen data without having display problem. VBlank occurs when it reach line 160.
HBlank occurs at the end of every line refresh(when reach col 240), VBlank occurs at the end of screen refresh(when reach line 160).
HBlank = 228 Time per screen refresh
VBLank =1 Time per screen refresh.
So, HBlank is called 228x more often and thus would take away more time of your main program.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11331 - sajiimori - Thu Oct 02, 2003 7:07 pm
It sounds like you need some practice with general programming before you try doing GBA development. Get a handle on writing C programs for your computer, and you'll be able to answer many of your own questions, such as what main() is for. There are some tutorials online, or you can get a good book on the subject.
http://www.amazon.com/exec/obidos/tg/detail/-/0672322226/qid=1065117270/sr=8-2/ref=sr_8_2/103-1152808-1223059?v=glance&s=books&n=507846
Sometimes when I "answer" somebody's questions this way, they reply by saying "I already know C and I've been writing programs for years!" Well, I got the impression that you need to know C better because you misunderstand what main() is, and that's something that you would know if you knew C. The main() function is not the same as a "main loop".
*edited for error
#11333 - RaBBi - Thu Oct 02, 2003 8:19 pm
First of all, thank you all
And second, sorry for my mistake about main loop...like I said, I'm ill (I may not be here tonight but my learn envy is too big lol) and I didn't want to say "main loop" but loop in main function ^^
In fact, I use while(1) { game code } in my main function.
But when I wrote my first post, I made this language mistake ^^
[game code is composed by functions like
- load maps, sprites
- activate/deactivate/move BGs
- test input
- move sprites
- z_ordering sprites
- etc...]
I read all and it's sounds more clearly.
you're right, I must learn more C and more about GBA hardware.
In fact, I already have read many tutorial and the ENTIRE Pern Project.
I didn't have all info in my brain, but I know where to search to find some answers to basic questions.
But never found a tutorial about how games are made.
That's was the purpose of this topic in fact.
I had ideas about interrupt and you confirmed that I was ok about that, I'm happy ^^
In fact, in my game, I use VBLANK ONLYto copy objs to OAM (cause BGs don't ask for refresh too times), and I put a variable "g_newFrame" to 1.
So in loop (in main function), I test g_newFrame before doing anything.
I wanted to know if I was right and if I may have to do this all the time in game programming.
Do you put another function in your VBLANK?
For now, my game didn't crash so it seems that my function VBLANK is fast enough to be executed during this time I suppose.
I really thank you all and I'll take a look at the book you recommended me, even I think I understand now how it works, it will be a very useful complementary information ^^
EDIT: when re-reading post of niltsait, I ask me how to use several interrupt.
Can I activate one VBLANK and one TIMER so I can keep on copy objects to OAM while waiting for a timer to be over?
Thank you ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11336 - sajiimori - Thu Oct 02, 2003 8:58 pm
My main() is something like this:
Code: |
main()
{
init();
while(1)
{
get_input();
update_world();
wait_for_vblank();
copy_oam();
}
}
|
This is simpler than using interrupts, and somewhat more fault tolerant. If a frame takes too long to process, the game will slow down, but everything will still run ok.
I only use the vblank interrupt to update the audio buffer, so slowdowns won't cause the audio to skip.
#11338 - RaBBi - Thu Oct 02, 2003 9:24 pm
ok ^^
I don't know "waiting for VBlank" for the moment
In fact, the main problem I think about is for automatic events.
Example::Intro of my game:
BG is scrolling while two NPCs are running and sometimes text appears.
Example::End
Can I do an unique function intro(), in which I use a loop with "new frame detecting" functions inside ? Plus input detecting inside.
And if Ok, where I can call it?
In fact, for me, with my game coding level, move NPCs randomly in loop while BG scrolling in loop while move my hero with keys isn't too hard.
But I have a big mind problem facing automation with stop at precise times, etc.
Perhaps it is nothing for an experimented game developper, I hope.
But while I'm not ok with this, I think my code, even if it works, will be badly structured.
Thank you ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11341 - poslundc - Thu Oct 02, 2003 10:36 pm
RaBBi wrote: |
ok ^^
I don't know "waiting for VBlank" for the moment
In fact, the main problem I think about is for automatic events.
Example::Intro of my game:
BG is scrolling while two NPCs are running and sometimes text appears.
Example::End
Can I do an unique function intro(), in which I use a loop with "new frame detecting" functions inside ? Plus input detecting inside.
And if Ok, where I can call it? |
Part of the difficulty in coding a game on a console like the GBA is that you need to stop thinking at such a high-level and think more about the basic structure of a program.
The basic structure for a GBA program (to more-or-less quote sajiimori) is this:
Code: |
BEGIN
Make any necessary initializations
DO
Handle Player Input
Update Game Status
Wait Until VBlank
Update Screen
LOOP FOREVER
END
|
It is your "Handle Player Input" and "Update Game Status" functions that determine whether you are in the intro screen, gameplay mode, etc.
A game that is in this format is called a finite state machine. I can't go into an indepth explanation just now as to what that means, but if you search on the Internet you will find many good explanations. This would be a good concept to learn and understand if you want to do game programming.
Most games can be represented as finite state machines: You start off in the TITLE SCREEN mode, then if the player hits "Start" you go into the LEVEL SELECT mode, then if the players hits A you go into the GAMEPLAY MODE, but if they hit B you go back to TITLE SCREEN mode, etc.
Je crois que nous avons eu la difficult? comprenant vos questions. Si ceci ne t'aide pas, tu peux vouloir essayer de demander en fran?ais... peut-?tre il y'aura quelqu'un qui peut repondre mieux en englais s'il te comprendre en fran?ais d'abord.
Bonne chance,
Dan.
#11342 - niltsair - Thu Oct 02, 2003 11:02 pm
Another detail, waiting for VBlank doesn't mean you're using interupts.
When you're just waiting for it, it means that you keep checking where the screen refresh is at, untill it reach line 160 and then update the screen.
While using VBlank interupts means that you enabled interupts for VBlank which automaticly call a function that handle your screen refresh or any other things you want your game to do after a VBlank interupt (often people use it to create timers) This is done outside of your main loop and use no 'WaitForVBlank()'.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11343 - sajiimori - Thu Oct 02, 2003 11:08 pm
This is how to wait for vblank.
Code: |
#define REG_VCOUNT *(volatile u16*)0x4000006
wait_for_vblank()
{
while(REG_VCOUNT != 160);
}
// If you have interrupts set up properly,
// use this instead to save GBA battery life.
wait_for_vblank()
{
asm("swi 5":::"r0","r1","r2","r3","r12","lr");
}
|
For your intro example, you would want get_input() to detect if the player pressed "start" to skip the intro maybe, and you would want update_world() to move your NPCs and scroll the background. Of course, get_input() and update_world() might do other things when the intro is not running. So, use function pointers like this:
Code: |
void (*get_input)();
void (*update_world)();
main()
{
init();
start_intro();
while(1)
{
get_input();
update_world();
wait_for_vblank();
copy_oam();
}
}
start_intro()
{
get_input = intro_get_input;
update_world = intro_update_world;
}
intro_get_input()
{
if(PRESSED(KEY_START))
start_game();
}
intro_update_world()
{
scroll_background();
move_npcs();
draw_text();
}
start_game()
{
get_input = game_get_input;
update_world = game_update_world;
}
|
#11344 - RaBBi - Thu Oct 02, 2003 11:27 pm
Thanks again ^^
Dan>I appreciate your effort to speak french, but you did some mistakes yet and I hope I don't do them in english cause it would be hell for you to understand me ! lol
I joke, it was almost clear :)
so come back to the subject, I must say that I progress in understanding game concepts.
But I think I'm troubled with loops in fact...
For example, sajimori wrote:
Code: |
intro_update_world()
{
scroll_background();
move_npcs();
draw_text();
}
|
But there is no sign of a loop at first sight.
So may I understand that the loop is conditionned by "while(1)" in main function?
And that I CAN'T/MAY NOT/DON'T use loops in other functions? Just detecting new frame?
I ask that cause scroll_backgrounds is while move_npcs and while draws_text, not one after another.
Dan> by "finite state machine" do you mean I can use a variable that determines in which state my game is, and may test this variable to execute particulary functions?
I'll never thank enough guys ^^
I have a last question (I imagine you thinking about killing me at this time lol) : Are there Frenchies on this board ;)
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11345 - sajiimori - Thu Oct 02, 2003 11:44 pm
You can use loops whenever you like, but my example has only one: while(1) in main().
The function scroll_background() would move the background by a small amount, so you would only call it once per frame. Same with move_npcs(). That's why they are not in a loop.
It doesn't matter what order you call them in, because the effects won't be seen until the next frame.
With this setup, you don't need to "detect" a new frame at all.
*edit* Re: finite state machines -- The variables in my example are function pointers, so they don't need to be tested. You just call them. But, you could do this instead (though it's not so pretty and it's slower):
Code: |
#define STATE_INTRO 1
#define STATE_INGAME 2
...
int game_state;
main()
{
...
game_state = STATE_INTRO;
...
}
get_input()
{
switch(game_state)
{
case STATE_INTRO:
intro_get_input();
break;
case STATE_INGAME:
ingame_get_input();
break;
...
}
}
update_world()
{
switch(...
}
|
#11347 - RaBBi - Thu Oct 02, 2003 11:56 pm
it grows it grows ! ^^
But it works without frame detection only if I use wait_for_vblank I guess?
If I use interrupt VBLANK, I must use frame detection in all my "one execution by frame" functions, do I?
For the loops, let me tell you what it blocks my mind :
In fact, I think that if I put a loop in a function, drawtext() for example, all the others functions would be stopped until this (loop) is finished...
For scrolling BG or moving Npc, it's not so hard (update X,Y once per frame) but to draw text, I cannot use a loop that read a character then display it only each 5 frames (type writer effect) then read next character, and so on...until string is complete.
IF I do a loop here, BGs and NPCs will be draw yes ('cause interrupt) but not moving, no?
EDIT: I just read your edit after posting, and effectively, I'm using this slower way in my game. I think I can be excused cause it's my first lol
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11366 - niltsair - Fri Oct 03, 2003 3:16 pm
I'm french, from Qu?bec(Canada) and there's some more on this forum.
As for your type writer thingie, here's what you could do.
Code: |
u32 gFrameCount(0);
void main()
{
init();
while(1)
{
//Do your loop here with functions calls
gFrameCount++;
}
} |
So, in your draw text function, you only write a character per 5 frames by checking the modulo of gFrameCount; You could use it anywhere else you want to also do something at interval instead of everyframe.
As for the screen, yes it's still would be draw you were right on this but it'S nto because of interupt. The screen just refresh itself constantly, by hardware with no programmer intervention. The interupt that you can enabled if you want to, is just telling you the screen just refreshed itself, it's not doing the refresh.
And for game, finite state machine is the way to go. Another way you could implement it while keeping it clear would be to use 1 loop per state and 1 loop that include all states, like this :
Code: |
u32 gFrameCount;
u8 gState;
void main()
{
Init();
gState = STATE_INTRO;
While(gState != STATE_RESET)
{
switch( gState )
{
case STATE_INTRO: StateIntro(); break;
case STATE_GAME: StateGame(); break;
case STATE_PAUSE: StatePause(); break;
case STATE_MENU: StateMenu(); break;
}
}
}
void StateIntro()
{
stIntro_Init();
while( gState == STATE_INTRO)
{
stIntro_ReadKeys();
stIntro_UpdateWorld();
WaitVBlank();
gFrameCount++;
}
stIntro_CleanUp();
}
void stIntro_ReadKeys()
{
if( KeyPressed == Start)
gState = STATE_GAME;
}
void stIntro_UpdateWorld()
{
//Scroll the backgrounf or something
}
....
And so on for every others states |
As you can see, we loop inside the Intro state as long as gState fit. If we want to change state, we merely need to change the value of gState and it'll switch accordingly.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11372 - sajiimori - Fri Oct 03, 2003 5:41 pm
Quote: |
But it works without frame detection only if I use wait_for_vblank I guess?
|
The OAM copy will probably fail, because you are only allowed to write to the OAM during vblank. But if you put the OAM copy in the vblank interrupt handler, and remove the wait_for_vblank(), things will run fine -- just way too fast. That is, everything will move as fast as the CPU can move them, which is probably faster than 60 times per second.
Quote: |
If I use interrupt VBLANK, I must use frame detection in all my "one execution by frame" functions, do I?
|
No, you see, those functions are called once per frame anyway. Upon entry to the function, you *know* you are in a new frame, so you don't have to *detect* anything.
Quote: |
In fact, I think that if I put a loop in a function, drawtext() for example, all the others functions would be stopped until this (loop) is finished...
|
That's right, so make sure there is enought time for the rest of the frame to be processed. If the whole frame takes a little longer than 1/60th of a second, your game will slow down by half (because it missed one vblank, and will wait for the next). But, I don't think this is a problem for you yet.
Quote: |
For scrolling BG or moving Npc, it's not so hard (update X,Y once per frame) but to draw text, I cannot use a loop that read a character then display it only each 5 frames (type writer effect) then read next character, and so on...until string is complete.
|
Right, if you put that loop in draw_text(), it would draw the entire string before anything else happens. This is not what you want. The function will be called once per frame, and each time it's called, it does a little more work. Here is an example where draw_text() does *one* frame worth of work, not the whole thing at once:
Code: |
draw_text()
{
if(frames_since_last_character_printed >= 5)
{
print_a_character();
frames_since_last_character_printed = 0;
}
else
++frames_since_last_character_printed;
}
|
Quote: |
IF I do a loop here, BGs and NPCs will be draw yes ('cause interrupt) but not moving, no?
|
The vblank interrupt is not the cause of the screen refresh. The GBA automatically redraws the screen 60 times a second.
If you still don't understand, you need to practice. Learn by doing. :-)
#11373 - RaBBi - Fri Oct 03, 2003 5:47 pm
Thank you niltsair ^^, if you prefer I post in the two languages or just in french, tell me.
Ok, so I already use the trick of g_framesCount.
I'm on a good way, don't you think ? lol
And I already use game states to know where in game I am.
The second code you gently propose to me is similar to the one I use yet.
This sort of loop containing functions like :
- queryKeys()
- updateWorld()
- waitForVblank() >> I didn't use it yet but I will ! Good trick ^^
- copyObjToOam()
I understand them and already use them.
But, what's embarassed me, is to put a loop in a function like updateWorld().
In your example, you tell me to put the BG scroll in the stIntro_UpdateWorld() function. I'm OK with it, it's how I do ^^
But in this function scroll function, may I use g_newFrame detecting and use a static variable to remember where I was in the scrolling sequence (for the next call)?
Because if I execute all the scrolling in one time with a loop, my NPCs didn't move by theirself while, and also I cannot query Keys while this time too.
I hope my problem is clearer for you after that.
(If you prefer I'll post it in French)
Anyway thank you for the explanation about automatic screen refresh, I didn't figure how it works before.
EDIT (I was posting while sajimori was too ^^)
sajimori wrote: |
If you still don't understand, you need to practice. Learn by doing. :-)
|
Of course, I know, in computer domain (and in plenty of others), I always learned by doing ^^
But like I said in first post, I'm ill for now, so I can't code and I prefer to discuss with you guys about these concepts I have difficulty with, before restart to program :P
So, you took away my doubts about loops that are blocking others functions after. I thank you for that.
But you tell that functions are called each frame.
All functions?
IE that if a function takes more time than a screen refresh, it will not end?
In fact I don't really imagine how fast a console run...I think...
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
Last edited by RaBBi on Fri Oct 03, 2003 6:01 pm; edited 1 time in total
#11375 - niltsair - Fri Oct 03, 2003 6:01 pm
First, you don't want to use the word 'gently' to thank me, it got a different meaning than in french, one i don't think you'd care to learn ;-) 'Kindly' is the word you meant,
And secondly, yes, you just use a static variable inside your UpdateWorld that tell you what to do next frame, such as scrolling again or such. You can't keep looping inside it seing how it block everything else.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11376 - RaBBi - Fri Oct 03, 2003 6:06 pm
sorry niltsair, I had doubts about using this term, the sense is more friendly than other ^^
I will learn two language from now : C and English lol
Ok it seems that I had the good concepts in my mind, but I wanted to discuss them with "experts" to confirm I was not as lost and fool that I thought.
A pb of self-reliance I think ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11378 - sajiimori - Fri Oct 03, 2003 7:13 pm
Quote: |
But in this function scroll function, may I use g_newFrame detecting and use a static variable to remember where I was in the scrolling sequence (for the next call)?
|
g_newFrame is useless. Forget about it entirely. Forget about detecting new frames, and forget about the vblank interrupt (until you are doing something more advanced).
Now think about this for a minute: If you call a function once per frame, why would you need to detect if you are in a new frame? The function is only called on new frames!
That's pretty much the idea. :-)
#11380 - RaBBi - Fri Oct 03, 2003 7:36 pm
uh....in one sentence, you've change my whole mind lol
I'm Ok with but now there is 2 points I don't manage to collapse :
-Each function is called once per frame? or each frame?
-But VBlank interrupt causes the functions stop, then they restart from stopped point (like all interrupts do)?
So I'm asking if all functions are EXECUTED ENTIRELY in one frame?
Because if not, and if they're called each frame they never finish uh?
Do you think I'm too ill to understand ? ^^
Me, I begin to think so :)
Anyway, I'll think more about this way, thank U.
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11381 - niltsair - Fri Oct 03, 2003 7:52 pm
What happen is, you execute your code inside the loop untill you arrive at WaitForVBlank(). Then it just wait until it detect the end of a new frame.
This mean that your code could take more than 1 frame without problem, it doesn't matter how many frames occurs before WaitForVBlank. The function just make sure that before continuing it's the end of a frame, not that '1' frame was done.
Of course, if too many frames occured before you call WaitforVBlank, then animations would look clunky (saccad?s)
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11382 - RaBBi - Fri Oct 03, 2003 8:16 pm
And the light occurs ! ^^
It make sense for me now, at each point that was dark before.
I think the most important words are "too many frames", so I don't do complex functions for the moment, as newbie, thus I think they don't take too much time.
Then, can I use the fact that human eye see good and fluid at 30 images/sec to have an amount of frames available to execute some big thing before display?
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11383 - niltsair - Fri Oct 03, 2003 8:28 pm
Yep.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)
#11386 - tepples - Fri Oct 03, 2003 11:42 pm
Most PlayStation 1 and Nintendo 64 games did run at 30 fps because the producers found polygon count more important than absolute fluidity, and some monochrome Game Boy games ran at 30 fps to cut down on blurring on the original system's green-tinged passive-matrix display.
The reason film can get away with 24 fps is that film has a natural motion blur, whereas most computer-rendered images don't.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#11387 - grumpycat - Sat Oct 04, 2003 12:49 am
You might want to take a look at the source code to my "Thrust" and "Galaxy Invader" programs, that is available on my website http://www.geocities.com/grumpycatsoftware. The "Thrust" game includes title screens, a demo mode, pause, the running game (of course!) and a high-score table.
"Thrust" was my first GBA project, so I'm not claiming it's any great example of anything, but it does illustrate the general program structure comments that have been discussed here.
Regards,
Grumpy.
#11396 - RaBBi - Sat Oct 04, 2003 10:45 am
Thanks for more explanation tepples ^^
And thanks to grumpy for his sources, I'll take a very carfully look at them ^^
Thanks to all who spend time to answer very detailled ideas to a newbie like me.
It's what I call a "communauty" !
I won't hesitate to show what I'll manage to do with your help and advices, be sure ^^
I did some basic things yet, but as I repeated in all my post until you show me the light, I had difficulty to coordonnate all the events.
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11444 - RaBBi - Tue Oct 07, 2003 12:30 pm
Hi,
I posted a big post yesterday but it was lost during a forum send operation error.
So I will be lighter this time.
My ask is simple for one time lol :
how can I manage to code functions (and their call way) which are exectuted only after another function has done, and which use frames counting.
For example:
Code: |
void main(){
while(1) {
doStuff();
}
void doStuff(){
drawText(1,4,"blabla"); // draw text using a function that depends on frame couting
waitSomeTime(5); // wait for a number of seconds for example
clearText();
drawText(1,4,"blabla"); // same as above
waitSomeTime(5); // wait for a number of seconds for example
clearText();
}
(void?) drawText(...) {
// this functions draws a character from a string each number_of_frames frames, for example
if (g_frames%number_of_frames) print_a_caracter();
}
|
May I use many test detection in my doStuff function?
Like : if (draw_text_precedent_has_finished) { do_the_next} ?
For the moment, I use some "handworker" tricks, but I know they didn't belong to a proper way of game programming.
I hope I'd be more clearly than in my precedent posts ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11445 - Datch - Tue Oct 07, 2003 2:23 pm
If I understand you well, you want to have a text display like in RPGs, with letters appearing one after one.
Since there's 60 vblanks per second, you can synchronize animation by counting vblanks.
Eg: You wait for a vblank before drawing each letter of your text. The display will be very slow like this I guess, 60 letters per second. Maybe it would be better to draw two or more letters every vblank.
_________________
Visit SR-388 now and get a 40% discount!
#11446 - tepples - Tue Oct 07, 2003 3:27 pm
The way to do this is to maintain the state of your text-drawing operation, and then if(in_the_middle_of_drawing_text) draw_one_more_glyph();
Datch wrote: |
The display will be very slow like this I guess, 60 letters per second. |
The U.S. TV caption system encodes at that rate (2 letters every 1/30 second), yet it manages to keep up with what is being said.
Quote: |
Maybe it would be better to draw two or more letters every vblank. |
Many games make text writing speed adjustable.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#11456 - RaBBi - Tue Oct 07, 2003 8:11 pm
arf sorry guys...I think I was not as clear as I thought ^^
In fact, drawText function was just an example of function that use frames couting (or Vblank counting as you want ^^).
I could have chose moveSprite(source, destination,...) for example ^^
I would put in sequence functions of that sort, but the next function must be triggered only if the previous has done.
But I cannot execute the whole function in one time, because, for example, I couldn't detect inputs or move sprites while, if I must wait that this function has done...
You say that functions are called many times during game execution, so this sort must execute some little stuff (not the whole in a unique call) and must know what was their last action to do next stuff.
In details, I will try:
- my function doStuff() is call once,
- It trigger drawText() function,
- That function doesn't draw entire characters in one time,
- it draws some, then exit
- but as it is not entirely accomplished, I can execute other actions like starting to draw other text, cause not the previous text is displayed yet!
- I exit doStuff();
- I look at input,
- I copy to Oam,
- and I recall doStuff(), to continue displaying the next part of the text,
- and If all the text is displayed, the function must know that the next time it will be triggered, it musn't display the same text, but another.
Perhaps for you it's easy to understand and practice this concept, but not for me yet...
For info I coded a frames counting display text function yet, but I don't figure out how to "chain" (?) them.
For now, I use a trick based on a integer in static variable, that increment only if the text is entirely displayed, and a switch function that test this value, and execute other drawtext calls.
REMEMBER: don't believe I only want to draw text ^^, it's not the matter ! lol
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11458 - sajiimori - Tue Oct 07, 2003 9:39 pm
Code: |
// A simple printing subsystem.
// Only supports one text printing operation at a time.
// Use your imagination to improve it. ^_^
// Warning: Not for real use.
static char* current_string;
static int string_length;
static int current_char;
static int print_x, print_y;
// Call this to start a printing operation.
start_printing(char* string, int x, int y)
{
current_string = string;
string_length = strlen(string);
current_char = 0;
print_x = x;
print_y = y;
}
// Call this every frame.
update_text()
{
if(!current_string)
return;
if(current_char >= string_length)
{
current_string = 0;
return;
}
print_char(current_string[current_char++],
print_x, print_y);
print_x += CHAR_WIDTH;
}
|
#11462 - RaBBi - Tue Oct 07, 2003 11:09 pm
really good sajimori ^^
It's near the way I think about for some days :
- one function to initiate an action, like drawText or spriteMovement
- one for update these every frame (or definite number of frames)
I'm going to keep on this way, adapting my drawtext functions in a first time.
Try some other stuff next.
If someone has another tips that are more general about this sort of function, I'll be interested ^^
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11467 - sajiimori - Wed Oct 08, 2003 1:57 am
More general advice for state machines, such as the text module I posted:
1) Make a set of variables that stores the state of the machine (e.g. current_string and current_char).
2) Make a set of functions for altering the state of the machine (e.g. start_printing()).
3) Make a function that interprets the state of the machine to produce the desired effect (e.g. update_text()).
To have multiple machines of the same type, use a struct to hold the state of each one.
#11483 - RaBBi - Wed Oct 08, 2003 12:44 pm
Yeh, I saw some sources using this way of states.
But what do you mean by "machines"?
_________________
Sorry for my poor english, but it would be worst for you to understand me if I speak in my native language, French ^^
#11493 - tepples - Wed Oct 08, 2003 4:23 pm
Start here:
Finite state machine@Wikipedia
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.