#13896 - gbawiz - Wed Dec 24, 2003 6:06 pm
Hi all,
I have a question regarding the control of the sprite movement in my games.
At the moment I can only move my sprites at one pixel at a time in any direction while using my collision testing techniques (bounding box and sprite to BG testing).
The problem arises when I want sprites to move faster than this, say 18 pixels at a time. When I attempt a collision with the background, the move is cleared and the sprite is placed at the new location (i.e sprite y + 18).
The thing is that there is a wall between the original location and the new location that would have been detected if the player moved one pixel at a time.
Does this mean that I can only move all my sprites at one pixel at a time or is there a specific method which must be used.
I would be grateful for any advice.
Thanks
GbaWIZ
#13900 - sajiimori - Wed Dec 24, 2003 6:12 pm
The easiest solution is to move one pixel at a time 18 times in a row, all in one frame, checking for collisions each time. It will still appear as if the sprite is moving 18 pixels at once, but all the appropriate collisions will happen.
#13901 - Miked0801 - Wed Dec 24, 2003 6:17 pm
Option 2 is to actually do the vector math to figure out if a collision has happened anywhere along the path - of course, checking every possible pixel location between is easier to do, but much slower...
Mike
#13921 - gbawiz - Wed Dec 24, 2003 11:51 pm
Thanks for the response guys,
The thing is, I have about 100 enemy sprites and their moves are calculated and positions are updated every program loop.
for each of the 100 enemys they have to check for collision against every other sprite object in the program (including the 99 other enemies).
As a result the program is reeeeeeeeeally slow and as the enemies are destroyed then the program speeds up.
I have tried methods such as only moving the enemies which are in range of the player but it only helps a little
you mentioned frames, would updating the positions at specific frame times help speed up the program?
thanks
GbaWIZ
#13922 - sajiimori - Thu Dec 25, 2003 12:10 am
This topic has been discussed here before. In short: try sorting your objects by their locations to eliminate many possibilities at once.
#13937 - Miked0801 - Thu Dec 25, 2003 7:34 am
Yep, a good sort or cull changes the search from O^2 to nearly O.
#13955 - jenswa - Thu Dec 25, 2003 9:16 pm
I don't realy know how to say this in english.
But if you have 100 sprites and you check every sprite with the 99 others,
there are double checks that way.
you check one sprite for 99 collisions, than sprite no 100 is done, sprite no 99 was already checked with sprite no 100, so only 98 collision checks for sprite no 98 are left, etc etc...
And indeed, that sorting trick has been discussed before and is a very nice trick to use.
_________________
It seems this wasn't lost after all.
#13961 - gbawiz - Thu Dec 25, 2003 10:33 pm
i see what you mean about only testing each object once.
The method that I have used recently is like this
there are 100 enemies (0 to 99) and the rest upto 121 are collidable objects which the enemies can collide with (including the other enemies)
in my checks I use a for loop (for scan=0;scan<100;scan++)
and within the loop there is another while loop which checks other sprites against the current enemy being checked.
next=scan+1;
while(next<121){
do checks between 'scan' and 'next'
next++;
}
this means that only the current enemy being checked is only checked against the sprites following it up to 121.
however this doesnt seem to work properly as some of the enemies (not all) seem to move through others.
#13970 - Miked0801 - Fri Dec 26, 2003 7:00 pm
OK, if you check every sprite against every other on the screen, you get 100 x 100 seaches or 100^2. This is too slow.
Now there's a bunch of ways to speed this up. Here's one way. Use the X and Y position to create a Hash Table. For example - lets assume you have a world size of 1024x1024 pixels (fairly small). Then lets create an array of 1024 sprite pointer linked lists. We'll use the following for our hash function:
u32 spriteHashFunc(u32 xPos, u32 yPos)
{
ASSERT(xPos < 1024 && yPos < 1024);
return ((xPos >> 5) + (yPos & 0xFFFFFFE0));
}
This will return a value from 0 to 1023. Now, run all your actors through this function and add them to the hash table. The first add will take some time, but not too bad. Now every tic, take the sprite's hash function value and use it to index into the hash table. The only sprites you need check against are sprites in the same list as the target sprite.
Every tic, you'll need to update all the sprites that have moved to different hash arrays - but this should be much, much quicker than doing a huge number of collision checks.
Mike
#14026 - gbawiz - Sat Dec 27, 2003 8:29 pm
hello all,
thanks for your response to my previous posts,
I currently have the problem of collision detection between 100 sprite objects
each of the 100 objects is required to test the other 99 objects and this is proving to slow.
I need to use some sort of sorting methods to cut down on the amount of collision tests needed.
I have heard of the sector method and the axis sorting method but have no idea on how to store and use these methods.
Can anyone suggest a good method which can be used in this problem.
Also, how do I create and access tables (as in hash tables)?
many thanks
GbaWIZ
#14029 - dagamer34 - Sat Dec 27, 2003 11:04 pm
Do you have to check enemy-enemy collisions?
I know for one, that it is better to play a game with good gameplay and ok graphics than good graphics and SLOW gameplay.
One thing though is to make sure that you always use a systems strengths. It is pointless to make a next generation 3D game on the GBA, it's just not gonna happen (I purposely exaggerated to show my point).
_________________
Little kids and Playstation 2's don't mix. :(
#14058 - jma - Sun Dec 28, 2003 5:47 pm
You could break the collisions up using algorithms designed for raytracing (like quad-trees, etc). A basic idea would be like (untested code used to show concept):
o each sprite is in an "area" of the screen; these are bit-based so they can be combine (0,1,2,4,etc); this is stored in an array somewhere:
Code: |
int sprite_location[128]; // max 128 sprites |
o The screen is divided into 4 areas (0,0-120,80), (120,80-240,80), (0,80-120,160), (120,80-240,160). If you need more areas, subdivide even more.
o At the start of your program, loop through each of your sprites and use x/y and size to determine which areas it is in.
o Each time a sprite is moved, check to see if the area(s) it is in change and update your sprite_location array accordingly. Offscreen sprites set their sprite_location to 0:
Code: |
void update_location(int *location,int x,int y) {
if (x < 120 && y < 80) *location |= 1;
// TODO: etc.
}
void set_sprite_location(int sprite) {
int x = sprite_x(sprite),y = sprite_y(sprite);
int cx = x + sprite_sizex(sprite), cy = y + sprite_sizey(sprite);
sprite_location[sprite] = 0; // reset
update_location(&sprite_location[sprite],x,y);
update_location(&sprite_location[sprite],cx,cy);
update_location(&sprite_location[sprite],cx,y);
update_location(&sprite_location[sprite],x,cy);
// NOTE: this could be sped up quite a bit by just
// looking at adjustments to the current location
} |
o Each collision test, your first test would be like so:
Code: |
for(i=0;i<nSprites;i++) {
if (i == thisSprite) continue;
if ((sprite_location[i] & sprite_location[thisSprite]) == 0) continue;
// TODO: check sprite collision between i and thisSprite
} |
This should cut down your sprite collision tests by about 75% using 4 areas, and even more if you divide into 8, 16, or more areas.
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#14061 - col - Sun Dec 28, 2003 7:08 pm
jma wrote: |
...
Code: | for(i=0;i<nSprites;i++) {
if (i == thisSprite) continue;
if ((sprite_location[i] & sprite_location[thisSprite]) == 0) continue;
// TODO: check sprite collision between i and thisSprite
} |
This should cut down your sprite collision tests by about 75% using 4 areas, and even more if you divide into 8, 16, or more areas.
Jeff |
doing it that way, you are still doing 128 * 128 tests though - just 'location' tests instead of box overlap tests...
don't keep the sector info in the sprite objects.
keep it seperate.
each sector is a linked list of the sprites that are in that sector.
to check for collisions, just check each of the sprites in a sector with the other sprites in that sector.
Of course this approach falls apart if your game objects can potentially congregate in the same sector. You then have all the overhead of managing the lists, and still 128*128 tests to do :(
much better to use 'game rules' to reduce the number of collision checks. Then if it suits your game, use x coord (or y) to order the entities for further savings if needed.
col
#14069 - Miked0801 - Mon Dec 29, 2003 12:02 am
Hehe. See my example above for sector testing (algorithm uses 32x32 pixel sectors)
#14090 - jma - Mon Dec 29, 2003 5:22 pm
Nice, Mike! didn't see that above :)
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#14093 - gbawiz - Mon Dec 29, 2003 7:55 pm
Thanks for the response to my post,
About the sector method. I have looked at the possibility of dividing my gamemap into a grid of sectors, with a list for each, and storing my sprite reference within the list according to which sector it falls within.
There are a couple of things which im not sure about.
If the sprite should overlap sectors then do I have to store that sprite in all of those sectors? (i.e check all the corners of the bounding box of my sprite and store sprite ref in the sectors which those corners rest).
Another way I thought of is to make the sectors smaller and then scan the surrounding sectors of that which the sprite is located.
also how do I make a list as im not too clued up on linked lists (can these be used?).
many thanks
GbaWIZ
#14132 - Miked0801 - Wed Dec 31, 2003 2:21 am
If checking against a box, then as long as your box is smaller than the sector size, at worst it will fit into 4 sectors (if axis aligned - all bets are off on a rotated collision box.) So just check the 4 sectors.
I'm not convinced that checking 100 objects would be too slow myself. That would be at most 10,000 checks. If done intelligently, you'd only need about 4950 ((100 * 99) / 2) checks when removing redundancies. On games I've worked on where hundreds of objects needed to be checked, it wasn't too bad to check them all.
If you can get away with radius checks, taking X distance squared + Y distance Squared between 2 objects and comparing is very fast (2 muls, 2 subtracts, 2 adds, and a compare.) Just square the final distance you're checking against to be things work.
example:
I'm at position 2,3. My radius is 10 (squared to 100). My collision check point lives at 9, 9 and has a radius of 4 (squared to 16).
Collision check:
2 - 9 = -7 ^ 2 == 49
3 - 9 = -6 ^ 2 == 36
Added together this gives a squared distance of 85.
My square radius plus his is 100 + 16 == 116
85 < 116 so we are colliding.
Very fast (probably around 15 cycles or so per check.) an completely accurate for radius.
As it plays with less numbers, it will also have less memory access than a box check as well.
Mike
#14171 - col - Wed Dec 31, 2003 5:01 pm
Miked0801 wrote: |
Hehe. See my example above for sector testing (algorithm uses 32x32 pixel sectors) |
I saw it :)
32x32 sectors mean that most sprites will commonly be in multiple sectors
If you have boxes greater that 32x32 (not unusual), they will often occupy 9 or more sectors - ouch - starts to make the hash table a lot less simple to manage - suddenly you can't just use the corner points to get your hash value...
moving your sprites in the hash table will happen often with such a small sector size, and if you have 9 sectors to update, thats a lot of list manipulation to process.
Could leave you with a crippling worst case !
as you suggest in a later post - for the sector method, you really need to make sure that the largest collision box is <= the sector size (for some versions of the algorithm, it must be <= half the sector size)
in the end, if cpu is becoming in issue the best thing is to implement multiple algorithms and profile them - trying to stress their weaknesses...
cheers
Col
#14181 - gbawiz - Wed Dec 31, 2003 9:20 pm
I was reading about the sector method where it is described that the screen is divided into sectors and there is a sector array where the sector location for each sprite is stored.
But what do I do when the case is that the sprite overlaps onto four sectors? do i have to calculate a sector for each of the corners and then store the spritenumber in each of those sectors?
#14183 - Miked0801 - Wed Dec 31, 2003 10:27 pm
yep which is why you want to make sure your sprite box is smaller than the sector size else you might worse case higher than 4 sectors. It does work though - I used it to speed up detection on a PSX game I worked on a long time ago :)
Mike
#14283 - gbawiz - Sat Jan 03, 2004 9:35 pm
Well, I have created a sector method for sorting my collision tests and have found that it has made only a little difference in speed, not enough to warrant smooth playability.
The enemy sprites are mostly grouped 3x4, 2x3, 7x8, etc. and each group is spread throughout the gamemap.
What is the best method for collision detection in this case?
#14287 - Miked0801 - Sat Jan 03, 2004 10:44 pm
I hate to ask, but are you absolutely sure that collision detection is what is slowing down your app? Have you done a full profile check to make sure something else isn't eating away at your time? If collision detection is only 3% of your overall CPU, a 50% speed increase only gets you 1.5% of your overall CPU time back...
Mike
#14295 - XeroxBoy - Sat Jan 03, 2004 11:21 pm
Quote: |
Well, I have created a sector method for sorting my collision tests and have found that it has made only a little difference in speed, not enough to warrant smooth playability.
The enemy sprites are mostly grouped 3x4, 2x3, 7x8, etc. and each group is spread throughout the gamemap.
What is the best method for collision detection in this case? |
An easy optimization you can do in this case is to simply check collision on the bounding boxes of the enemy groups - if there's a collision, do further testing to see what collided with what. That, theoretically, could reduce the number of checks you need to do exponentially.
#14400 - gbawiz - Tue Jan 06, 2004 12:33 am
I've tried disabling the enemy movement procedure in my app and found that the problem is in large part due to the enemy movement.
Could it be the fact that all of my code is in C and none in assembly which is slowing my app down?
I also have a routine which calculate the relative screen coords of each sprite in the map (the map is larger than the screen and makes use of scrolling and offsets) and updates the screen. This is carried out on every cycle of the program loop as well as the controlling enemy movement.
#14404 - sajiimori - Tue Jan 06, 2004 1:25 am
We have no way of knowing where your bottlenecks are. Yes, you can usually make code faster by using hand-written assembly. No, we can't tell you if doing this will make your code meet your requirements.
You need to profile your code to find out where the CPU is spending its time. Then you can post the critical section (which is usually quite short) and we can probably help you.
#14410 - Miked0801 - Tue Jan 06, 2004 2:36 am
Quote: |
Could it be the fact that all of my code is in C and none in assembly which is slowing my app down
|
C code is just fine for this sort of thing - we do it all the time w/o issue. You just need to be careful in what algorithm the code is running per Enemy. If you've got some ultra complex trig routine running in every enemy to lead a target or something, that'll kill you. Profile your code, then you'll know where to begin. Any time spent optimizing w/o profiling is wasted.
Mike
#14501 - gbawiz - Wed Jan 07, 2004 5:48 pm
Here is my bounding box collision test:
char bbtest(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh)
{
if(ax+aw<bx)return FALSE;
if(ax>bx+bw)return FALSE;
if(ay+ah<by)return FALSE;
if(ay>by+bh)return FALSE;
return TRUE;
}
Could it be a possibility that the above is slowing down my app?
Also a note on linked lists, removing an entry from the llist, is it necessary to scan the until the desired entry is found or is there a more direct method like key in data out in one go without having to scan?
Thanks
#14504 - Miked0801 - Wed Jan 07, 2004 6:15 pm
You can get rid of the adds if you store the box as 4 coordinates instead of 2 coords and 2 offsets. Also, passing 8 parameters means 4 are put on the stack. I'd consider putting the b values in a local struct on the outer-loop of your collisions check - then directly put this test code in the inner loop. That gets rid of the function calls and stack accesses. This type of code should also be in fastRAM as ARM code so you have enough registers to do it right. We store our collision data in u16s - that way when intially reading from ROM, we only need 2 32-bit reads instead of 4.
That said, I really doubt this is your bottle-neck. Profile your code and find out what is.
Mike
#14523 - gbawiz - Wed Jan 07, 2004 11:50 pm
Thanks for response,
how do I profile code on the GBA? I use the devkit advance compilers(GCC).
#14526 - tepples - Thu Jan 08, 2004 12:35 am
Try clicking Search above and entering profiling as your keyword.
It's too bad that phpBB's search uses a POST form; otherwise, I'd have linked a result page the way I do on Slashdot for Google search results. (Or is the CPU cost of search in phpBB so high that the phpBB developers did this on purpose to discourage linking to expensive result pages?)
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#14966 - gbawiz - Thu Jan 15, 2004 12:51 pm
Well I have found a method of speeding up my collision detections but im not quite convinced that it is the best way.
My gamemap is 512x512 with scroll. I have created an axis sort method where all the sprite's y coords are used as a reference to an array:
yaxis[spritey]=spritenumber. (these are initiated at the beginning of the app).
I thought about getting rid of the bounding box collision test because i found a faster method but that would only test the whole 16x16 boundings of each sprite.
I want to be able to check a 'footprint' within the sprite which is a smaller bounding box within the sprite area, so i have to keep the adds in my bbtest.
Is there a limit to the number of sprites which i should have on screen at any one time?
#14968 - LOst? - Thu Jan 15, 2004 1:40 pm
gbawiz wrote: |
Is there a limit to the number of sprites which i should have on screen at any one time? |
I believe 128 sprites during a Vblank is the answer
#14987 - animension - Thu Jan 15, 2004 7:30 pm
It is possible to get more than 128 sprites on screen using HBLANK IRQs. Essentially, what you do is change the OAM's properties after a scan line has passed the bottom of the sprite during HBLANK to locate it somewhere else further down the screen from the current scanline.
Code: |
----------
| |
| | Sprite OAM #0 @ Y position 60
| |
----------
_____________________________________ Current Scanline @ Y position 70
----------
| | Sprite OAM #0 now @ Y position 80
| | moved down here during HBLANK.
| | You can even tell it to use a different graphic.
----------
|
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin
#14991 - poslundc - Thu Jan 15, 2004 8:39 pm
The danger with that technique is you only get 950 pixels of processing per scanline, which may seem like a lot, but rot/scale sprites and double-size sprites consume much more than their actual horizontal dimension.
Furthermore, that technique really should only be necessary in exceptional circumstances. Sprite-based text engines and complicated particle effect games, mostly. 128 sprites is a lot on a screen the size of the GBA's.
Dan.
#15000 - tepples - Thu Jan 15, 2004 11:19 pm
For short:
Q: How many 8x8 sprites can you display on one scanline?
A: Almost all of them.
Remember that 950 pixels equals about 118 sprites, each of width 8. It seems that T&L processing might dominate in a GBA particle effect demo.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#15011 - Miked0801 - Fri Jan 16, 2004 2:32 am
Though T&A would definately garner more attention :)
#15036 - gbawiz - Fri Jan 16, 2004 11:25 am
I was wondering if having a certain amount of sprites on the screen at one time would slow the program down.
Also, what happens if I try to write to sprite attribute memory while the screen is being drawn? (i.e. not during vblank or hblank). Is the attribute memory 'dual access' or can only one device access it at a time.
If this is the case then which gets the priority, the cpu or the lcd controller?
I have noticed the shearing of the image but i am wondering if the cpu is placed in a wait state if it has attempted to write to attributemem during the lcd controller access.
You may have guessed I am still trying to speed up my collision detection and sprite movement processes :)
Thanks
gbaWIZ
#62519 - gbawiz - Thu Dec 01, 2005 8:28 pm
Hello,
I have read different documents which talk about the sector method and some ways of implementing them.
The main issue with the sector method arises when one sprite object falls within more than one sector.
if the sprite centers on the corner of a sector then it occupies 4 sectors at the same time.
This would mean that I would have to store the sprite number in each of the linked lists representing the sectors, and when the sprite moves, I have to change the entries for all 4 sectors.
Does this mean that each sprite object will have to memorize which sectors it is CURRENTLY in so that when moving the sprite, these entries can be changed.
Also, when a sprite is moved from one sector to another, having to traverse each sector's linked list takes time. Is there a better way?
One which I have also heard of is to use ONLY the top left 'sprite coordinate' to determine the sector which the object is in and then scan through all the surrounding sectors (9 in total).
Thanks in advance.
#62529 - tepples - Thu Dec 01, 2005 9:25 pm
gbawiz wrote: |
Does this mean that each sprite object will have to memorize which sectors it is CURRENTLY in so that when moving the sprite, these entries can be changed. |
That or clear the list in each sector every frame.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#62538 - Miked0801 - Thu Dec 01, 2005 11:40 pm
Depends - if you have objects that'll never move, there's an optimization to be had here. If all your sprites are flying all over the place, then it'll be faster to recontruct your list every tic. Man this thread came back from the dead :)
#62541 - gbawiz - Thu Dec 01, 2005 11:59 pm
Yeah, unfinished business to take care of :)
I was just working out how I might use the sector method.
If an object falls within one sector then all of its four corners will fall into the same sector, it would be silly to scan the same sector four times.
I would have to memorise the fact that this sector has already been checked.
I would have to have another list for each of the objects, which contain the 'different' sectors which the object falls in.
i.e instead of having the four corner sectors in 2,3,2,5. Then I would have something like 2,3,5, ?.
I may need a list sorter to filter out the duplicates.
I have come up with this myself but can't help think that there may be a better way of doing this as it seems a bit tedious.
Are there any source code or pseudo code listings available which would detail a good sector method technique?
Thanks again
#62544 - tepples - Fri Dec 02, 2005 1:43 am
Or you could just divide the screen into vertical sectors and use the sorting method horizontally within each sector, using a binary search to find where in the adjacent sectors to start looking.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#62555 - sajiimori - Fri Dec 02, 2005 9:21 am
If you're set on using 2D sectors, here are some things to consider.
Each sector could have a linked list of objects that are within it. The linked list can pass through the object structs, like so:
Code: |
struct Object
{
Object* prevInSector;
Object* nextInSector;
};
|
It's a doubly-linked list so it will be fast to remove an object from a sector, and so you can quickly find all of an object's neighbors by traversing the list in both directions.
Objects that are at least 2x2 pixels in size can be in up to four sectors at once, so that single pair of pointers isn't enough.
Code: |
struct SectorLink
{
SectorLink* prev;
SectorLink* next;
};
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
};
|
SectorLink has to have pointers to SectorLinks in each direction instead of objects. If it had pointers to objects, you wouldn't know which of the object's links to follow to continue along the same list.
If none of your objects are wider or taller than a sector, then 4 links will always be enough. If any are larger, you could increase MAX_SECTORS, or you could dynamically allocate an array of links for each object. Flexible arrays are also an option.
Given an object, you need to be able to find all all the other objects that are in the occupied sectors. By following each of the four links to the left and to the right, you will reach the links owned by all the objects in those sectors. You may have noticed that there's no clear way to reach an object given one of its SectorLinks, but it's easy enough to add a pointer to it:
Code: |
struct SectorLink
{
Object* parent;
SectorLink* prev;
SectorLink* next;
};
|
'Parent' will point to the object that owns the link.
If you happen to allocate all your objects from a pool in the form of an array, and they hold their links by value, you can skip the 'parent' pointer and calculate the address of the object based on the address of the link:
Code: |
Object objectPool[MAX_OBJECTS];
Object* objectForLink(SectorLink* link)
{
return objectPool + ((int)link - (int)objectPool) / sizeof(Object);
}
|
The division might hurt, though. Either way, it's easy to find all the nearby objects:
Code: |
void findNearbyObjects(Object* obj)
{
for(int link = 0; link < MAX_SECTORS; ++link)
{
for(SectorLink* left = obj->sectorLinks[link].prev;
left->parent != 0; left = left->prev)
{
Object* other = left->parent;
// Do something with the other object.
}
for(SectorLink* right = obj->sectorLinks[link].next;
right != 0; right = right->next)
{
Object* other = right->parent;
// Do something with the other object.
}
}
}
|
A problem with the above code is that you can run into the same object multiple times if it occupies more than one sector that the first object is in. An easy solution is to use a timestamp. Stamp objects with the latest 'time' when you encounter them, and ignore objects that already have the latest timestamp.
Code: |
struct Object
{
...
int timestamp;
};
int latestTimestamp;
void findNearbyObjects(Object* obj)
{
++latestTimestamp;
for(...)
{
for(...)
{
...
if(other->timestamp == latestTimestamp)
continue;
other->timestamp = latestTimestamp;
// Do something with the other object.
}
}
}
|
When an object changes position, remove it from all its current sectors and add it to the new ones. In my experience, it's not worthwhile to try to minimize the number of 'remove' and 'add' operations by skipping sectors that the object will be re-added to. Searching for those sectors takes more work than you save.
Removing an object from all its sectors is as easy as closing the links:
Code: |
void removeFromSectors(Object* obj)
{
for(int linkIndex = 0; linkIndex < MAX_SECTORS; ++linkIndex)
{
SectorLink* link = &obj->sectorLinks[linkIndex];
if(link->prev)
link->prev->next = link->next;
if(link->next)
link->next->prev = link->prev;
link->prev = link->next = 0;
}
}
|
Adding objects to the overlapped sectors starts out pretty easy, too:
Code: |
void addToOverlappedSectors(Object* obj)
{
int right = rightwardSectorExtent(obj);
int bottom = downwardSectorExtent(obj);
for(int x = leftwardSectorExtent(obj); x <= right; ++x)
for(int y = upwardSectorExtent(obj); y <= bottom; ++y)
addToSector(obj, x, y);
}
|
The 'extent' functions are based on the object's rectangle and the dimensions of the sectors. Writing 'addToSector' requires deciding how to represent the sector grid. One easy representation is a 2D array. It's late, though, so I'll stop for now.
Last edited by sajiimori on Mon Dec 12, 2005 7:46 pm; edited 2 times in total
#62688 - SittingDuck - Sun Dec 04, 2005 12:33 pm
Yes, this is the snapshot effect, and it's very problematic. Come on, the GBA is 60fps. Be thankful. With flash games, it's usually 24fps and it's much harder!
#63132 - gbawiz - Fri Dec 09, 2005 12:20 am
Hello,
Thanks sajimori for the code, I am beginning to understand how the code works.
The main issue with the sector lists is being able to determine object's sector and the sector's objects. And with my sprites falling within upto 4 sectors at a time this makes referencing even more confusing.
I am curious about adding to overlapped sectors. I assume that you have pre-written procedures (i.e. rightwardsectorextend(obj) ). What does this procedure do?
sajiimori wrote: |
void addToOverlappedSectors(Object* obj)
{
int right = rightwardSectorExtent(obj);
int bottom = downwardSectorExtent(obj);
for(int x = leftwardSectorExtent(obj); x <= right; ++x)
for(int y = upwardSectorExtent(obj); y <= bottom; ++y)
addToSector(obj, x, y);
}
|
I am also curious as to how I would reach the objects parameters from scanning through the current sector list. You mentioned the object *parent pointer . When is this pointer setup to point to the object?
I assume that *prev and *next are setup when the entry is added to the current sector list.
Thanks again for the advice given as this stuff is normally quite confusing to me and you have helped me to understand this subject bit better.
#63136 - sajiimori - Fri Dec 09, 2005 1:05 am
Quote: |
I assume that you have pre-written procedures (i.e. rightwardsectorextend(obj) ). What does this procedure do? |
Actually, all that code was from scratch, so I don't have anything "pre-written." :) The four functions return the edges of the object on the sector grid so you can iterate from top to bottom and left to right, adding the object to each sector it overlaps.
Quote: |
You mentioned the object *parent pointer . When is this pointer setup to point to the object? |
If objects hold their sector links by value, then the parent of a link will never change, so you can set the pointers when creating objects.
Quote: |
I assume that *prev and *next are setup when the entry is added to the current sector list. |
Yup.
#63138 - gbawiz - Fri Dec 09, 2005 1:52 am
Hello again, thanks for you reply :)
I was looking at the code again and got stuck at the following:
I can see that this part is straight forward where you have defined the linked list node-type 'sectorlink' then created an object type which would hold 4 of these links, referring to maximum of 4 sectors. (can i assume that the other object parameters will be defined here also, such as coords, etc...)
sajiimori wrote: |
struct SectorLink
{
SectorLink* prev;
SectorLink* next;
};
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
};
|
I have adjusted the code according to your recommendations :)
Thanks again
Last edited by gbawiz on Fri Dec 09, 2005 12:36 pm; edited 1 time in total
#63142 - sajiimori - Fri Dec 09, 2005 2:30 am
I've edited my post so that the final SectorLink definition is just like the second one except with the parent pointer (which was my intention). It doesn't make any sense to have the parent be another SectorLink, though -- what would it point to?
#63178 - gbawiz - Fri Dec 09, 2005 12:48 pm
Hello again,
I have ammended the code to take into account the changes that you described.
The reason that I asked about this is because when I try to define the structs, they each need the other one to be defined before it can be defined.
for example:
Defining object here requires that SectorLink be defined first before the completion of the object type as it makes use of SectorLink.
sajiimori wrote: |
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
};
|
But here it requires that the 'Object' type be defined prior to the definition of SectorLink.
sajiimori wrote: |
struct SectorLink
{
Object* parent;
SectorLink* prev;
SectorLink* next;
};
|
My compiler says "missing storage-class or type specifiers" when attempting to define each. I have tried swapping the order but still get the same error.
Thanks
#63180 - keldon - Fri Dec 09, 2005 1:20 pm
I use this format for what you are trying to do
Code: |
typedef struct tagCell {
void *head;
struct tagCell*tail;
}Cell; |
So I would have had something like:
Code: |
typedef struct tagSectorLink
{
Object* parent;
struct tagSectorLink* prev;
struct tagSectorLink* next;
}SectorLink; |
#63203 - sajiimori - Fri Dec 09, 2005 7:13 pm
gbawiz,
Forward declare Object before defining SectorLink.
Code: |
struct Object;
struct SectorLink
{
Object* parent;
SectorLink* prev;
SectorLink* next;
}; |
keldon,
I'm not sure what tagCell is for.
#63277 - gbawiz - Sun Dec 11, 2005 2:34 am
Hello,
I am wondering how to start the whole process of sector linked lists.
would it be better to start with an array of sectorlinks as the starting point. i.e:
Code: |
SectorLink allsectors[16]; // assuming there are 16 sectors in total |
I belive this would create an array of 'sector heads' which would then probably each have to be initialised. I could set the individual parameters to NULL.
Would a good method of adding an object to a sector to do something like.
Get the sector number which is being added to.
create a new node (SectorLink).
Set the parent to point to current object.
return the address of this new sectorlink and store it in the object's sectorlink[n]. i.e:
Code: |
object[n].sectorlinks[t]=returned_pointer; |
(where 'n' is the current sprite and 't' is the current corner of the sprite).
Another thing which I was wondering is that if I create a new entry into a particular sector then this would mean that I would be attaching it to the head (which was declared earlier). This head is empty and would never be used.
I'd be grateful for any thoughts and advice on this subject.
Many Thanks
#63280 - sajiimori - Sun Dec 11, 2005 3:11 am
The "head link" idea is good, but if you're using a 1-dimensional sector "grid," you're better off not using sectors at all, and instead just sorting your objects on that axis.
You said you were making a 2D sector grid, right? Then create your sectors as a 2D array, as I suggested in my first post.
Quote: |
create a new node (SectorLink).
Set the parent to point to current object.
return the address of this new sectorlink and store it in the object's sectorlink[n]. |
The definition of Object I gave stores whole SectorLinks, not pointers to SectorLinks. By having a fixed-size array of pointers to SectorLinks and dynamically allocating the links, you're getting the worst of all worlds: you have a fixed maximum number of sectors you can be in, you waste cycles on each allocate/free operation, and your code is more complex.
Quote: |
This head is empty and would never be used. |
It's used to point to the first object, and to tell when you've reached the beginning of the list when iterating to the left.
#63317 - gbawiz - Sun Dec 11, 2005 11:22 pm
Hello,
I noticed that you make use of a procedure called 'addToSector(obj,x,y)' within your 'void addToOverlappedSectors(Object *obj)' procedure
How does this addtosector procedure achieve it's task?
I would be grateful for any advice.
Thanks :)
#63345 - sajiimori - Mon Dec 12, 2005 4:13 am
How do you think it might accomplish its task?
#63374 - gbawiz - Mon Dec 12, 2005 3:37 pm
sajiimori wrote: |
How do you think it might accomplish its task? |
I'm trying to get an idea of how it might be done properly.
If I were to guess:
the x and y coords would have to be translated into an x and y sector.
the x and y sectors would be used to access a 2d- array of sector heads, for example 'type' sectors[x][y]; (im not yet decided on whay the type should be 'object' or 'sectorlink').
But from here I'm a bit undecided.
I assume that the sector heads will be created at the start of the program as a 2D array of heads using the format described above:
'type' sectors[max_x][max_y];
But at this point, what do I put in the secor head? as I have not yet defined any sprite locations.
Im not too sure where to start and I believe that if I can see how the addtosector function works then It may help me to understand how the whole list is constructed.
Thanks
#63401 - sajiimori - Mon Dec 12, 2005 7:45 pm
Yeah, but this is sort of the last piece of the sector-collision puzzle, so I figured I'd leave it to you as much as possible. ;)
Your ideas sound good so far. I just updated this part of findNearbyObjects:
Code: |
for(SectorLink* left = obj->sectorLinks[link].prev;
left != 0; left = left->prev) |
When iterating to the left, you eventually hit the head link, and that's how you know it's the beginning of the list. But the head link is a real link (not null), so the exit condition was wrong:
Code: |
for(SectorLink* left = obj->sectorLinks[link].prev;
left->parent != 0; left = left->prev) |
That way we look for a link that doesn't correspond to any object.
#63436 - gbawiz - Tue Dec 13, 2005 3:07 am
Back again,
I will start the program by creating an array of sectorlinks corresponding to the various sectors available:
Code: |
sectorlink sectors[MAX_X][MAX_Y]; |
The above should create a 2D array of sector 'heads' but Im not too sure whether or not it should create an array of pointers to sectorlinks called sectors i.e:
Code: |
sectorlink *sectors[MAX_X][MAX_Y]; |
The problem arises when I have to add a new entry (add a new node) to the sector list, this means that I am leaving out the sector head. Seems like a waste.
Then create an array of objects:
Code: |
object[MAX_OBJECTS]; |
I have difficulty grasping the concept of the 4 (assuming 4 sectors max at one time) sectorlink links within the object struct.
Looking at it from the 'struct object' view, it would seem that the 4 sectorlink links are an offshoot from the object in question, how do the other objects link into this objects sector-links and how does the main sectors tie in with these also.
Thanks
#63437 - sajiimori - Tue Dec 13, 2005 3:42 am
What seems like a waste? Creating an array of SectorLinks instead of pointers? Try it with pointers then, and see if you run into any obstacles. (I have one in mind, but encountering the problem yourself will help you understand it better.)
Try to actually write addToSector so you can find out which part you're missing.
Also, if you haven't worked with linked lists before, please practice with those before continuing.
#63504 - gbawiz - Tue Dec 13, 2005 8:35 pm
The waste I was referring to was to create and array of sector heads and then not being able to use the head for storing data, instead just adding to it using an addtosector function. Assuming that the add to sector only adds and doesn't check to see if there was anything in the sector head.
(the sector head being created as before sectorlink sectors[MAX_X][MAX+Y] )
Also I was wondering what the sectorlinks stated below are filled with and how.
Code: |
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
}; |
Any new info would be helpful.
Thanks
#63507 - sajiimori - Tue Dec 13, 2005 8:43 pm
They are links in the lists of objects that are in the sectors the object is in. If you don't understand that, or if you don't know how to add objects to a list, please study linked lists. ^_^
#63508 - gbawiz - Tue Dec 13, 2005 8:51 pm
I can understand the idea of linked lists.
What I am uncertain of is what is how to choose the position to enter into these sectorlinks:
Code: |
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
}; |
I could guess that the add to sector function will create the entry into the desired sector, return an address (pointer) and then the pointer would be stored at this sectorlinks[n]
Is this correct?
#63510 - sajiimori - Tue Dec 13, 2005 9:01 pm
I'm not sure which position you're referring to, but the order of the sectorLinks array doesn't matter, and the order of the linked lists doesn't matter, either.
The only work you need to do in addToSector is a few assignments to link the object into the sector's list. Nothing is being created or destroyed (memory-wise).
addToSector adds objects to sectors. When it completes, the object is added. If you have to do some additional work afterwards to "really" add the object to the sector, then you haven't finished the implementation of addToSector.
#63512 - gbawiz - Tue Dec 13, 2005 9:40 pm
Hello,
Thanks for the information.
I have been reading more about the linked list.
Before when I was talking about creating the sector heads, creating a head that would not be used, I get what you mean when you say nothing has been created.
For example I will use the following to define my arrays (noting the '*')
Code: |
sectorlink *sectors[MAX_X][MAX_Y]; |
I belive that the above does not actually create anything, i.e there is no memory allocated and there is nothing stored in these arrays yet.
I realise that this is basic pointer knowledge which seemed to have slipped my mind briefly.
The memory would be allocated just before I add information to the sector.
#63665 - gbawiz - Thu Dec 15, 2005 12:38 pm
I tried the following code but I get the error:
Quote: |
no operator defined which takes a right-hand operand of type 'struct sectorlink *' (or there is no acceptable conversion) |
I cannot immediately see what this means, any ideas?
Code: |
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<dos.h>
#define MAX_X 16
#define MAX_Y 15
#define MAX_SECTORS 4
struct obj;
struct sectorlink{
obj *parent;
sectorlink *prev;
sectorlink *next;
};
struct obj{
sectorlink sectorlinks[MAX_SECTORS];
};
//-----------------------------------------------------------------
void main()
{
sectorlink sectors[MAX_X][MAX_Y];
printf("Hello World\n");
sectors[10][10]=(sectorlink*)malloc(sizeof(sectorlink));
} |
#63667 - byg - Thu Dec 15, 2005 1:10 pm
I've just had a quick look at the code and from what I can see sectors is an array of sectorlink objects, yet you are trying to allocate a sectorlink pointer with the following code:
sectors[10][10]=(sectorlink*)malloc(sizeof(sectorlink));
Try changing
sectorlink sectors[MAX_X][MAX_Y];
to
sectorlink* sectors[MAX_X][MAX_Y];
_________________
Modasi Games
www.modasi.com
#63713 - sajiimori - Thu Dec 15, 2005 7:40 pm
To be blunt, I think you are not ready for this task yet.
Quote: |
I belive that the above does not actually create anything, i.e there is no memory allocated and there is nothing stored in these arrays yet. |
It most certainly does. It creates a 2D array of pointers, each of which takes up the size of a pointer.
Quote: |
The memory would be allocated just before I add information to the sector. |
The whole point of this scheme is to avoid dynamic allocation.
Code: |
sectors[10][10]=(sectorlink*)malloc(sizeof(sectorlink)); |
You're way off base. Please study arrays, pointers, and malloc/free.
#63816 - gbawiz - Fri Dec 16, 2005 3:38 pm
The line which I have written as:
Code: |
sectors[10][10]=(sectorlink*)malloc(sizeof(sectorlink)); |
is just to test the idea of being able to allocate memory for that particular sectorlink head. Of course I will not be allocating memory in this way, I will be using a method which creates a new sectorlink (as an when required) and then assign it to the head, adjusting the necessary parameters. (it is similar to the standard linked-list 'push' function except with some modifications).
The other line which I mentioned:
Quote: |
I belive that the above does not actually create anything, i.e there is no memory allocated and there is nothing stored in these arrays yet. |
I was testing the idea of basic pointer creation. For example if a pointer was created such as int *ptr; I was simply stating that since malloc has not yet been used to allocate a memory location for this pointer, where would the pointer point to? ZERO. And the fact that I have not assigned any data to this pointer either means that nothing has been stored here.
sajiimori wrote: |
To be blunt, I think you are not ready for this task yet. |
Giving up is not an option. But actually I have seen through a lot of problems and have nearly got my code working now.
I learn through the mistakes as well as the achievements.
I can see what you mean with regards to the learning the basic pointer stuff.
I have used pointer many times and taken them for granted, kinda like 'they do what they do' I decided now to try and look deeper into them in order to gain solid knowledge of them.
Anyway, I am nearly finished my code and may post the finished result.
Thanks
Last edited by gbawiz on Mon Dec 19, 2005 10:46 am; edited 2 times in total
#63817 - byg - Fri Dec 16, 2005 3:51 pm
I don't think sajiimori was trying to be negative. Merely stating that there is still some learning required before attempting this coding. If you need to test 'being able to allocate memory' and '...testing the idea of basic pointer creation' he is probably right.
By all means don't give up! But perhaps start with a simpler problem and topic. Perhaps read through a few tutorials on pointers first.
_________________
Modasi Games
www.modasi.com
#63841 - sajiimori - Fri Dec 16, 2005 7:37 pm
Quote: |
For example if a pointer was created such as int *ptr; I was simply stating that since malloc has not yet been used to allocate a memory location for this pointer, where would the pointer point to? ZERO. |
Not if it's local. Anyway, the pointer has a memory location whenever it is in scope. It's just a variable.
Quote: |
And the fact that I have not assigned any data to this pointer either means that nothing has been stored here. |
For statics and globals, the startup code that runs before main() stores 0 in them.
Quote: |
Giving up is not an option. |
Did I say give up?
#63893 - gbawiz - Sat Dec 17, 2005 10:15 am
No probs,
I'll take time to adjust my code to see how it works in my main prog.
thanks.
#64062 - gbawiz - Mon Dec 19, 2005 12:54 am
Quote: |
#define MAX_SECTORS 4
struct Object
{
SectorLink sectorLinks[MAX_SECTORS];
}; |
Shouldn't the above look like:
Quote: |
#define MAX_SECTORS 4
struct Object
{
SectorLink *sectorLinks[MAX_SECTORS];
}; |
Changing 'sectorlinks' into 'pointers to sectorlinks'
#64066 - sajiimori - Mon Dec 19, 2005 1:26 am
Not in the system that I described.
#64097 - gbawiz - Mon Dec 19, 2005 10:45 am
sajiimori wrote: |
Not in the system that I described. |
OK, then this must mean that your system makes use of the fact that the address of (pointer to) the sectorlinks[n] had already been allocated when creating the object types.
When adding an object to a particular sector list, you must be using the sectorlink[n] address in that list.
the other way I was looking at it was when creating the link node, to allocate the memory when creating the node then set the '*sectorlinks[n]' pointer to point to this (using the * in this case).
#64130 - sajiimori - Mon Dec 19, 2005 7:15 pm
Quote: |
OK, then this must mean that your system makes use of the fact that the address of (pointer to) the sectorlinks[n] had already been allocated when creating the object types. |
No. SectorLinks are being allocated, not pointers to SectorLinks.
Quote: |
the other way I was looking at it was when creating the link node, to allocate the memory when creating the node then set the '*sectorlinks[n]' pointer to point to this (using the * in this case). |
No. If sectorLinks is an array of pointers, then sectorLinks[n] is a pointer, and *sectorLinks[n] is a SectorLink.
You need to study pointers more. Learn what * and & mean, and how the * in a declaration is totally different than the unary * operator (not to mention the binary * operator).
(Sometimes I wish people could start with untyped version of C that just uses words. Then they'd see right away that it's all just numbers, and that types only enforce an interpretation.)
#64131 - sajiimori - Mon Dec 19, 2005 7:18 pm
Also find out why a[n] is a synonym for *(a + n).
#64174 - gbawiz - Tue Dec 20, 2005 12:10 am
sajiimori wrote: |
Also find out why a[n] is a synonym for *(a + n). |
a is the address (or base pointer) and n is the offset, each n occupies the amount of memory of the defining type.
i.e:
char a[n];
a is the first address and if n is 10 then the actual location where the info is held is a+(10 x 1byte) since char occupies 1 byte.
Last edited by gbawiz on Tue Dec 20, 2005 12:19 am; edited 1 time in total
#64177 - gbawiz - Tue Dec 20, 2005 12:16 am
Quote: |
No. SectorLinks are being allocated, not pointers to SectorLinks. |
You misunderstood what I meant:
When sectorlinks are being allocated, they are given a memory location (pointer), true?
for example if I create:
int n;
I am creating a variable called n, its memory location (pointer) is automatically allocated by the program, compiler (if not then I would not be able to store anything in n, i.e n=10, it would crash the program).
It has to be stored somewhere in memory.
The computer will allocate a 16-bit area of memory (which will have a memory location (or pointer if you like)).
One question, does any part of your code make use of 'malloc' or 'new' or any other type of memory allocation code (Y/N)?
#64185 - keldon - Tue Dec 20, 2005 1:57 am
Memory is allocated on the stack when this statement appears within a function and cannot be used after the function has returned.
#64190 - sajiimori - Tue Dec 20, 2005 2:47 am
Quote: |
When sectorlinks are being allocated, they are given a memory location (pointer), true? |
Pointers are variables. "Allocating a pointer" means allocating enough space to hold a pointer. Allocating an object does not imply allocating a pointer to that object.
Quote: |
One question, does any part of your code make use of 'malloc' or 'new' or any other type of memory allocation code (Y/N)? |
I've said two or three times that the design is made to avoid dynamic allocation.
#64192 - gbawiz - Tue Dec 20, 2005 2:57 am
sajiimori wrote: |
I've said two or three times that the design is made to avoid dynamic allocation. |
I just wanted to clarify what 'dynamic allocation' meant.
The reason I asked is that I have got my code working in one way.
The other way, which is what I believe the principle behind your method, is:
Code: |
#define MAX_XS 16
#define MAX_YS 15
#define MAX_SECTORS 4
#define MAX_SPRITES 5
#define SPR_WIDTH 8
#define SPR_HEIGHT 8
struct obj;
struct sectorlink{
obj *parent;
sectorlink *prev;
sectorlink *next;
};
struct obj{
sectorlink sectorlinks[MAX_SECTORS]; // creates an allocates sectorlinks
int xcoord;
int ycoord;
};
sectorlink *sectors[MAX_XS][MAX_YS];
obj myspr[MAX_SPRITES]; //create sprite objects
void main()
{
int x,y;
//setup mysprite 0 to 1 for test purposes only
myspr[0].xcoord=200;
myspr[0].ycoord=156;
myspr[1].xcoord=123;
myspr[1].ycoord=789;
//----------------------------------
//add all to sector 0,0 for test purposes only
//all set the first entry 0 as link
//sprite 0
myspr[0].sectorlinks[0].parent=&myspr[0]; // set the parent to point to myspr[0]
myspr[0].sectorlinks[0].next=sectors[0][0]; // set the next to point to the head of sector 0,0
sectors[0][0]=&myspr[0].sectorlinks[0]; // set the new head equal to the address of sectorlink[0] (within object)
//sprite 1
myspr[1].sectorlinks[0].parent=&myspr[1]; // set the parent to point to myspr[0]
myspr[1].sectorlinks[0].next=sectors[0][0]; // set the next to point to the head of sector 0,0
sectors[0][0]=&myspr[1].sectorlinks[0]; // set the new head equal to the address of sectorlink[0] (within object)
//-------------------------------------------------------------------------------
sectorlink *test=sectors[0][0]; //creates a temporary test and points it to sector[0][0] (head of)
x=test->parent->xcoord;
y=test->parent->ycoord;
printf("\nFirst entry's X,Y = %d,%d",x,y);
test=test->next;
x=test->parent->xcoord;
y=test->parent->ycoord;
printf("\nNext entry's X,Y = %d,%d",x,y);
|
#64193 - sajiimori - Tue Dec 20, 2005 3:14 am
I see the data declarations, but I don't see any functions that implement the collision system.
#64195 - gbawiz - Tue Dec 20, 2005 3:33 am
sajiimori wrote: |
I see the data declarations, but I don't see any functions that implement the collision system. |
At least let me know if this is the correct method.
The whole point of this was to work out how 'addtosector' works.
The collision system is part of another collection of functions. This one deals with the adding and removing of objects from sectors.
Also, the code used to remove an object from a sectorlist has to be modified to take into account the situation where the 'head' of the list is removed.
Last edited by gbawiz on Fri Dec 30, 2005 12:38 am; edited 1 time in total
#64209 - sajiimori - Tue Dec 20, 2005 6:32 am
It will become more clear as you put more things together.
#65100 - sajiimori - Fri Dec 30, 2005 2:33 am
Instead of having your collide function just return true or false for whether there was a collision, have it return what kind of collision happened. Code: |
enum CollideResult
{
COLLIDE_NONE,
COLLIDE_X,
COLLIDE_Y,
COLLIDE_BOTH
};
CollideResult collide(const Object*, const Vector2* motion); |
#65146 - gbawiz - Fri Dec 30, 2005 5:16 pm
Hello ALL,
Take the scenario where I have a sprite which can be controlled to move in all eight directions (up,down,left,right and diagonals).
The directions are set as Xdir and Ydir being either -1 or 1 (or 0 if stationary).
There is a wall to the left of the sprite and the sprite is heading diagonally up/left towards the wall and up at the same time, this means that the direction is set as xdir=-1, ydir=-1.
The directions are added to the current x and y coords and then tested for collision.
If collision then the x and y coords are restored and the direction is set to zero, otherwise the new position is kept.
The problem is that when the directions of -1,-1 are applied and the sprite collides with the left wall, the sprite is stopped in its tracks, even although upwards movement is available.
even although sprite is moving up/left and collides wit the wall on the left, I want sprite to still be able to move upwards while pressing up/left.
I got around this method by applying and testing the X and Y movements separately like this:
Code: |
Get X and Y directions (can be -1,0,+1)
add Xdir to sprites Xcoord
test for collision with wall
if collide then restore sprite X coord and set Xdirection to 0
add Ydir to sprites Ycoord
test for collision with wall
if collide then restore sprite Y coord and set Ydirection to 0 |
Im not too happy with this because there are two collision tests for this one sprite.
Any suggestions from anyone?
#65167 - sajiimori - Fri Dec 30, 2005 9:29 pm
Did you not like my solution, or would you rather play games than make them?
#65173 - gbawiz - Fri Dec 30, 2005 10:25 pm
sajiimori wrote: |
Did you not like my solution, or would you rather play games than make them? |
I would like someone else's objective on this subject instead of this type of arrogant and abusive nonsense which I have come to expect from you.
Do not post anymore of this rubbish!!
#65176 - keldon - Fri Dec 30, 2005 10:47 pm
Sajimori's solution is fine whether you like his approach of speech or not. I (in the past) achieved this result by handling movement for left, up, right and down seperate. If the player was holding up and right then first I try to move him up and if it collides I will move him back and so on.
My solution is not good and Sajimori's idea is much better; but you did ask for another take.
I am not sure how you are doing collision. If you are doing it with vectors for each edge of the bounding box then returning the CollideResult value is easy right? If you are using a bound box then it is the same case too.
#65180 - poslundc - Fri Dec 30, 2005 11:54 pm
gbawiz wrote: |
sajiimori wrote: | Did you not like my solution, or would you rather play games than make them? |
I would like someone else's objective on this subject instead of this type of arrogant and abusive nonsense which I have come to expect from you.
Do not post anymore of this rubbish!! |
Dude, I'm still trying to figure out how he managed to answer your exact question in the post before you asked it. That's not rubbish; that's skill.
The least you could do is try out the solution he gave you and then post either why you couldn't get it to work, or why you don't think it solves your problem effectively, or what you don't understand about it, etc. It doesn't exactly inspire the rest of us to come your aid when you demonstrate an unwillingness to pay attention to the help you're given. For the record, you are swimming in the deep end when you still need more practice in the shallow end, and most of us aren't generous enough to give half the help that sajimori has given you so far when that's the case.
And sajimori: try to be nice. :D
Dan.
#65181 - sajiimori - Sat Dec 31, 2005 12:01 am
As much as I'd like to claim that I have ESP, the simpler explanation is that he erased his post and re-posted it after I answered, possibly to trick people into thinking that the question wasn't answered.
Incidentally, that explains my snarky wording. :P