#29387 - Jau - Fri Nov 19, 2004 12:40 pm
I've got this code to implement physics:
hero.vx = hero.vx + hero.ax * dt;
hero.vy = hero.vy + hero.ay * dt;
hero.x = hero.x + hero.vx * dt;
hero.y = hero.y + hero.vy * dt;
where v is velocity and a acceleration
but it goes too fast and I need more precision. I've got to put dt =1 that is the minimum that I can put. How can I solve this?
#29388 - identitycrisisuk - Fri Nov 19, 2004 1:07 pm
If you look at the thread I posted on how to make a character jump in Coding, it eventually talks about using fixed point. This will help you to slow down your movement as you can create numbers that you view as being less than 1. For example you could use the value 1<<4 for dt, which you may think wil create very large velocities and positions which it will. However they key is that you perform a >>8 (just an example shift value, the bigger the number the more decimal accuracy but the less space you have for the integer part of the number) before you use the value to position something on screen. Hope that makes sense to you, I've only just got into using it myself but I think it's great!
#29563 - Jau - Mon Nov 22, 2004 12:10 am
thank you very much for your help
#30209 - Jau - Mon Nov 29, 2004 3:37 pm
Now I need to do collision detection, but with this code it's hard. For example, when I jump high enough at the return it goes too fast and my character goes to a tile inside the floor, instead of going just above the floor. The return velocity is good for playing, but it's too fast for my collision detection. How do I get a collision detection robust enough for fast velocities? Thanks
#30214 - identitycrisisuk - Mon Nov 29, 2004 4:13 pm
I've not actually got to this point yet (still learning how to scroll backgrounds properly) but I had anticipated that there would be cases where the speed of a character might make them move through more than a tile in a frame and skip a tile that needs to be collided with. I don't know how wise this is on the GBA but I plan to do ray-like collision detection, where you check the line that a character will move along in a frame, finding the first object that it will hit on that path. It seems like a lot to do but I've seen a few people on here say you can do surprising stuff on the GBA if you code it well. I really kinda need ray collision detection as I want to have a gun that fires but you won't see a bullet, it will just damage the first thing it comes into contact with in a straight line.
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30221 - keldon - Mon Nov 29, 2004 5:10 pm
erm, well you know that maths problem of where will two trains hit; that is 1-d collision detection. If you've never done this maths problem then here is the lowdown:
The distance an object advances every frame is called the gradient. The floor has no gradient, so it is constant.
floor's gradient: x = 10
A moving object would have a gradient of how far it advances each frame.
character's gradient: x = 5 + jumpDistance*numFrames
Now the number of frames the character is doing this for will tell you whether they will collide long before it happens, which may be necessary for AI.
Code: |
collision = 5 - 10 = -5
numFrames = 3
jumpDistance = 2
collision = -5 + 2*3
-5 + 2*3 > 0 == true
|
Now the logic is that by seeing where two lines collide will tell you if they will ever touch each other in this instance. If the value collision was below 0 then they will not collide.
You can take this further to take the y-coordinates to check collision with a wall. And I'm sure someone else will point out an easier way to do this using matrices or something.
---
There are some things you can do, like just check whether or not your character crosses the line at all; but where your game seems to have them going completely past the line you might want to know where it took place so that you know where he should be after the jump.
#30587 - identitycrisisuk - Thu Dec 02, 2004 2:07 pm
Would anyone have any pointers on how I'd go about making a ray collision test that will tell me what tiles a ray will pass through if allowed to travel to it's end point? I'm just using 8x8 tiles and a collision map output by MapEd so I'd be looking for any tiles != 0 for a collision tile of some sort, after I'd got it I'd choose how to handle it for things like slopes. My character position is stored as a single number rather than splitting it into a tile and offset but these can easily be retrieved by getting pos>>3 and pos&7.
My first thought was to compare the horizontal and vertical components of the movement that I want to make separately as that should make it quite easy to find the first tile it can collide with in that direction. But I think whichever direction I choose to check first it could bring up some problems in certain situations. For example if the path was pretty much diagonal and it will pass very close to a corner tile before a drop. Checking the vertical first will say that it can only move a small amount but it will be able to move freely horizontally.
Code: |
*<- Start Here
\
\
\
--+ \ *<- Will actually move here
| \
| \
| \
| \
| *<- Should move here |
I can't think of a relatively simple way to just get the tiles that the line will pass through. I think if I can get this then any other problems can be sorted out.
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30589 - keldon - Thu Dec 02, 2004 2:41 pm
So is that what you're saying:
- Your character has a position
- It wants to move to a new position
- This movement vector is refered to as the ray
- You wish to find all tiles the ray will pass through
If so that it's basically a lineTo algorithm. And in this you replace the putPixel call with a tile!=0 check.
#30594 - identitycrisisuk - Thu Dec 02, 2004 4:31 pm
Thanks for that.
I found this page which is supposedly a very fast algorithm for drawing lines using fixed point. Just one question, it uses abs and I was wondering whether that is something supported well by the GBA? I couldn't remember the include for abs anyway so I got it to work using the macro: Code: |
#define abs(x) ((x > 0) ? x : -x) |
Would there be any point in using the standard abs function over this macro?
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30614 - keldon - Thu Dec 02, 2004 8:42 pm
if abs(x) will always return a positive x then that's fine.
#30615 - identitycrisisuk - Thu Dec 02, 2004 8:48 pm
keldon wrote: |
if abs(x) will always return a positive x then that's fine. |
I can't quite decide if that's a subtle hint that my macro might not always return a positive value :s
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30620 - tepples - Thu Dec 02, 2004 9:19 pm
What happens when you take abs(INT_MIN)? Under the representation used for signed int on compilers that target ARM7TDMI, there is one more int less than 0 than greater than 0.
Anyway, you're supposed to use an inline function instead of a macro in order to keep from evaluating the argument twice, especially if the argument has a function call or a read-modify-write operator (++, --, etc). So put this in a header file somewhere:
Code: |
static inline unsigned int myabs(signed int x)
{
return (x >= 0) ? x : -x;
}
|
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#30625 - identitycrisisuk - Thu Dec 02, 2004 9:49 pm
Ah, I had thought about putting x >= 0 but I didn't think it made any difference. Good call on it being a function too, I always forget about evaluating arguments multiple times in macros.
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30873 - identitycrisisuk - Sun Dec 05, 2004 7:27 pm
Ach, I'm thinking I'm overcomplicating things with this ray collision detection as I don't think my character ever moves faster than 8 pixels per frame and even if it was possible to do so it would be better to cap it. 8 pixels per frame would mean a whole screen crossed in half of a second and it's just nicer knowing you can't move more than one tile in a frame. I tried doing that thing with the lines but I think it got complicated at the point of impact so I was just getting stuck in walls. Can stand on the floor now though :D
I've got some old code for tile collisions but unfortunately I never got round to putting in sliding along walls (it was from overhead) so you just stop if you run into a wall at an angle. With my current thing being a platformer that's not an option so I'll need to figure out a way of doing that. My first thought is:
Code: |
if you can move to the final position
move to it
otherwise
move as far as you can in x
move as far as you can in y, from the new x position |
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |
#30879 - tepples - Sun Dec 05, 2004 8:10 pm
identitycrisisuk wrote: |
I don't think my character ever moves faster than 8 pixels per frame and even if it was possible to do so it would be better to cap it. |
Good job for the jump physics, but does your character have a gun?
Quote: |
8 pixels per frame would mean a whole screen crossed in half of a second |
Bullets go faster.
Quote: |
My first thought is:
Code: | if you can move to the final position
move to it
otherwise
move as far as you can in x
move as far as you can in y, from the new x position |
|
That should work, except on perhaps diagonal walls and floors. For a platformer, you may need separate states (if you haven't looked up finite state machines, do so now) for standing on something and in mid-air.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#30903 - identitycrisisuk - Sun Dec 05, 2004 11:44 pm
tepples wrote: |
Good job for the jump physics, but does your character have a gun?
Bullets go faster. |
He does indeed and I will come back to the ray collision detection when I get to using them properly. What I plan to do is have no visible indication of the bullet, I kinda dislike that effect you get of rapid fire just looking like an unmoving line of bullets. I'll just calculate what will get hit by that 'bullet' (will just be in code) and have the effect of the shot happen within a few frames of the bullet being fired. This may be a splash of blood if an enemy is hit, spark off the level etc.
tepples wrote: |
That should work, except on perhaps diagonal walls and floors. For a platformer, you may need separate states (if you haven't looked up finite state machines, do so now) for standing on something and in mid-air. |
I'm ignoring diagonals for now but I will need them eventually I think. It will probably need a specific state to stop it from looking like the character is constantly falling and landing as you go down one if I carried on using what I've programmed so far.
_________________
Code: |
CanIKickIt(YES_YOU_CAN); |