cube movement... smooth movements..
BlitzPlus Forums/BlitzPlus Beginners Area/cube movement... smooth movements..
| ||
Let's say I create a cube, or load an image of a cube. I wana move it as follow: If I press a certain key it will move to the left. +5 Pixel to the left in like a few milliseconds, to make it look as smooth as possible. Teach me about timed movements, custom timers... Like instead of doing +5 instantly I want it to do: +1 do +1 do +1 do... ect, timed to look smoothly. I'm not sure if I'm explaining this correctly... if you don't understand please tell me I'll try to clarify. Please help! |
| ||
timer=CreateTimer(50) ; for 50 fps Repeat WaitEvent() If EventID()=$4001 ; timertick If EventSource()=timer ; optional, if you have more than 1 timer.. ; update EndIf EndIf If EventID()=$803 quit=true ; windowclose Until quit So, each time you press a key just add +1 to your coordinate-variable, the updates go automatically. |
| ||
I forgot to mention that I'm not working on an application, I'm working on learning 2D Game developpement.. I know it has to be done with timers, I don't know how to make them work yet. I need it to do +5, but smoothly, and whatever direction, I just wana see how it could be done. Smooth PLayer Movements is what I'm trying to figure out at this stage. |
| ||
Has nothing to do with apps or games. You're using Blitz+, rite? Take advantage of it. Here's how you can combine events and 2d: Graphics 640,480 timer=CreateTimer(50) Repeat WaitEvent() If EventID()=$4001 Plot Rnd(640),Rnd(480) EndIf If EventID()=$101 Cls EndIf Flip Until KeyHit(1) End |
| ||
If EventID()=$4001 Plot Rnd(640),Rnd(480) EndIf So that would be like the main loop of the game? It would loop forever every 50 frames? Or something. If I wanted to make a custom timer how would I do it? Like after 10 seconds do this and that. Without having any interferance in the main loop, like without stoping it. Having something flash and a count down from 10.. having two things working at the same time.. ? :o |
| ||
WaitEvent() waits for an event from the OS, which is like: buttonpresses, mousemoves, keyhits, timers, windowresize etc. If nothing happens, then the 'programcounter' err.. imagine an arrow pointing where the program is in the source, then all that will stay at the WaitEvent() command. So, if something happens (an event occurs) then you simply have to determine what event it is. You do this by checking on several event properties, like EventID() the type of event that occured EventSource() where the event came from EventData() sometimes there's extra data like a keycode EventX(), EventY() coordinate on a canvas-gadget etc. (see the manual) You can have various timers running at the same time, this multitimer stuff may look alien, but they all just create events, that's all you'll have to be concerned about. So you can have various async timers at once! What you were trying to do was polling. That's where you have a mainloop and in it you update the gamestatus, and do the gameupdate (draw stuff etc.) always, as fast as the program can. Polling-based programming and Event-based programming are different things, and personally I **NEVER** ever want to go back to polling! In BMaxgui the eventsystem is even better, but alas. So, to answer your question: you could see this $4001 as a mainloop yes, at 50 fps in this case. However, if you put everything in there (game AI update and screen update) then there wouldn't be much of a difference with what you're doing now (apart from that I really don't like polling-timers). What you could do is have 2 timers, one timer triggers the game-AI updates (like 30fps) and another does the screen updates (like 60fps), another timer (at speed 1) could be a timer to trigger a real clock etc. That would look like this: Graphics 640,480 AItimer=CreateTimer(30) GFXtimer=CreateTimer(60) CLOCKtimer=CreateTimer(1) Repeat WaitEvent() If EventID()=$4001 If EventSource()=AItimer ; do the updates EndIf If EventSource()=GFXtimer ; do the screen update Flip EndIf If EventSource()=CLOCKtimer ; update the clock EndIf EndIf Until KeyHit(1) When a timerevent ($4001) happens, the program goes into that If-EndIf, next you check which timer it was by checking the EventSource() with your timers. So, if you were programming visually: checking on events is like having all the possible options on a large grid, and then you go narrowing the choices down until you have the right choise. Logically it's best to narrow down in an efficient way by first filtering out the largest part of all the options. So, this would work perfectly, but it's wrong.. :P WaitEvent() If EventSource()=AItimer If EventID()=$4001 ; do the updates EndIf EndIf If EventSource()=GFXtimer If EventID()=$4001 ; do the screen update Flip EndIf EndIf If EventSource()=CLOCKtimer If EventID()=$4001 ; update the clock EndIf EndIf it *would* be ok to first check on the EventSource() when you're checking all the canvas-actions in case you're using a canvas.. then you go about; If EventSource()=MyCanvas If EventID()=$201 EndIf If EventID()=$202 EndIf If EventID()=$203 EndIf If EventID()=$204 EndIf ; etc. EndIf |
| ||
I'm not using any canvas, I'm making a normal 2D game, so that way I can learn how to make things work. I'm trying a small rpg... So I'll have to make all the menus then character movements and then mapping using tiles :) But I'm still very far from this. Soo hard lol.. I like how you explain this, you should make a tutorial for stupid begginners teach types, looping, mapping and how things should be to be the most efficient. And I'm sure there would be less questions in here. This was really helpful. One question remains AItimer=CreateTimer(30) GFXtimer=CreateTimer(60) CLOCKtimer=CreateTimer(1) are those seconds or milliseconds? so it refreshes every 60? |
| ||
The canvas was just an example. Your game could perfectly run in a window on a canvas btw. but that's for later.. timer units = hertz so 1 = 1 tick per second, 60 = 60 ticks per second etc. |
| ||
Another question for you, so now I got an AI loop, a GFX loop and a clock loop.. What would be the best way or the best place to start my game mechanism? Like if I wanted to make a menu, the menu codes of mouse over and detecting where the mouse is and all, this wouldnt go in AI nor the two other loops, where would that go? |
| ||
uh.. make a new timer? CTRLtimer=CreateTimer(30) for all the menus, buttons etc. Tho you could just as well put all that control stuff in the game AI loop since that's also 30fps.. You shouldn't see those 'loops' as restricted area orso, it's just the place to update your game thingies at 30fps. That could include anything, *even* the screenupdates, if you would settle for 30fps. Usually you want more fps so 60fps would do. Btw, you could as well do 60fps for evreything, AI and GFX .. Really, try to make some GUI app orso, doesn't even have to be that special, but after a week of GUI'ing you'll completely understand events and timers! |
| ||
Ok thanks, I prefer sticking to non-application things. I didn't get the answer to my cube problems though, moving a cube by +1 every seconds up to like 20, without affecting the other loops. Lets say it's an AI. I can't use delay 1000, this freezes the whole game. delay 1000 cube_x + 1 delay 1000 cube_x + 1 ... up to 20 delay 1000 cube_y + 1.. then I could turn. How would you do that, I can think of a way with timers but to me it'd take like 20 timers lol |
| ||
The delay method is bad indeed. Here's a freshly hacked solution.. dunno if it could be improved, I don't care to bother actually .. it just works :PGraphics 640,480 timer=CreateTimer(25) repeatwalks=-1 Repeat WaitEvent() If KeyHit(200) repeatwalks=0 direction=0 ; up EndIf If KeyHit(208) repeatwalks=0 direction=1 ; down EndIf If KeyHit(203) repeatwalks=0 direction=2 ; left EndIf If KeyHit(205) repeatwalks=0 direction=3 ; right EndIf If EventID()=$4001 If repeatwalks>=0 repeatwalks=repeatwalks+1 If repeatwalks<=5 Select direction Case 0 y=y-1 Case 1 y=y+1 Case 2 x=x-1 Case 3 x=x+1 End Select Else repeatwalks=-1 EndIf EndIf Cls For px=-8 To 8 For py=-8 To 8 Plot (x+px)*8,(y+py)*8 Next Next Rect x*8,y*8,8,8,1 f=f+1 fx=Sin(f*3.0)*32 fy=Cos(f*2.0)*32 Rect 320+fx*8,240+fy*8,4,4,1 Flip EndIf Until KeyHit(1) End |
| ||
I like this example very much. (I don't get the small flying cube's code but that's not important right now.) Thanks for your help your awesome! One thing I noticed, if I slow the timer to 10, it's not very smooth, is that because it's not drawn fast enough, or because it's just too slow? Is there any way to make it very slow but smooth without it being jumpy? |
| ||
The flying cube was purely to demonstrate multiple processes at the same time, all triggered by the same timer. Lowering the timer amount means less fps, so logically things become course. It may look bumpy because of the *8 in the x,y coordinates. If you want smooth steps over the same distance you simply gotta have more than 5 steps.. try: If repeatwalks<=32 and change all the the *8 into *1 (better comment the grid out!) |
| ||
This seems a little confusing, but eventually I'll get it, thanks! :) |