PDA

View Full Version : Transparent Rectangle Overlay (and more).



Chesso
02-01-2007, 12:29 AM
Hello.

So basically I want to fill a rectangle over the entire screen that still allows you to see the game itself, it's used in alot of games so hopefully you know what I'm on about.

Any help is appreciated.

P.S. I'm using D7 and UnDelphiX 1.07B.

EDIT:

Also, how can I make it so that when one object (the player), collides with another object (say just a square box or something), that it can no longer move in that direction, and can only proceed in other directions or along the object (not directly into it).

I know how this can be done manually (although a bit of a pain), I don't see how to do this using the sprite engine, sure it tells me when it's collided but then how do I know where they hit each other from and to reverse/fix the situation.

Chesso
02-01-2007, 05:45 AM
Iv'e also posted this question on DelphiGameDev, just in case there are other users there with more insite (although I think some from here visit both?).

jasonf
02-01-2007, 10:15 AM
There is no built in solution to your collision problem. They all require some amount of coding. You'll have to manually reposition your sprites after the collision. You could always move your sprite back to a place where there had previously not been a collision.

to do this..

in domove

oldX := x;
oldY := y;

// Move the sprite using a simple force based system.
x:=x+forceX;
y:=y+forceY;


in oncollision

x:=oldX;
y:=oldY;
//check the collision again
//if there's a collision move either above, to the left, to the right, or below the object.




I've done collision tutorials for DelphiX which might be able to help you.
http://www.cerebral-bicycle.co.uk/links.asp?cat=24&subj=5
In particular
http://www.cerebral-bicycle.co.uk/viewdoc.asp?doc=35

What I would be tempted to do would be,

1. Store the last X and Y positions in DoMove
2. On collision, call a funciton which moves the sprite back along its original path by checking at specific points if it's still colliding.

The function would take the current X - OldX and current Y - OldY to get a movedX and movedY. Then using a recursive function

This is pseudo-code and has never been compiled.. in fact, it was typed into the browser.

function mysprite.fixcollide( originx, originy, movedx, movedy : double; itteration : integer )
var
newx, newy : double;
begin
newx := originx + movedx;
newy := originy + movedy;

movesprite(newx,newy);
if itteration<10 then
begin
if checkcollision() then
begin
fixcollide( originx, originy, movedx/2, movedy/2, itteration+1);
end
else
begin
fixcollide( newx, newy, movedx/2, movedy/2, itteration+1);
end;
end;
end;


or.. you could give each sprite a collision distance and set your sprites position to this based on the angle your sprite was travelling in.

so you'd work out the angle you were travelling in by storing the oldX and oldY each doMove.


On collision you work out the angle using atan2

Then you move in the opposite direction, the distance of your sprite's collision distance and the colliding sprite's collision distance. This way is quicker, but not as accurate as the first method.

There are TONNES of ways of handling collision detection and resolution. They can be as complicated or simple as you want.


As for the overlay problem, I'm not entirely sure I'm clear on what you mean..

Do you mean an overlay like a window around the play area? or do you want to tint the screen a particular colour with an overlay?

For the first case, the bordered window, you draw a bitmap the size of the screen, make a pretty border and fill the center with a transparent colour. However, this technique is quite wasteful and you'll want to break your window up into smaller parts.. to prevent wasting time rendering a large area of transparent pixels.

DelphiX is not a complete game engine. In order to craft your game, you have to write a sizable amount of code.

Hope this helps.[/pascal]

Chesso
02-01-2007, 10:22 AM
Oh I know that, I just figured if it was going to tell me when a collision occurs, it could be more usefull and give me some options on what to do when they collide lol.

Tinting might work I guess but I don't know how to do alot of fancy effects and things with UnDelphiX.

Basically I want the screen to darken like it does in many games, console, pc or otherwise when they pause.

So the screen looks as if someone has slapped black over the entire screen and made it quite transparent.

The screen is only 350x350 Windowed, so it's nothing big (not scrolling either).

Chesso
02-01-2007, 10:50 AM
Ok, as of right now, I'm using the simple Old_X and Old_Y method, so when they collide (after collisions check after moving) it's reset to the old values that are re-stored before the movement before collision checking.

For the moment, the objects and the player are just a simple square box, but even then you can see the spaceinbetween them when it collides.

Even setting PixelCheck to true with all of them, doesn't change a thing, it still ends up the same gap.

Is there anyway to fix this up?, most of the game objects will be square or it won't matter too much, but the player and some of the enemies will likely not be so I need to make the collision detection a bit more precise.

I read the stuff on the website, but it doesn't exactly go into much theory as to the mathematics behind the different forms :P. Or it's easier than I think and i'm completely missing the point lol.

jasonf
02-01-2007, 12:12 PM
Well, it's not so easy, I've not found a perfect solution and I've had a few attempts believe me.

I think the problem comes from the fact that we don't know the exact point where the collision occurred (without a little processing), we only know that it did. With polygons, it's a bit easier as it's 100% maths. It's not with pixel testing. For a start, there's a lot more information to check.

At the moment, in my game, I'm using a method similar to the one I described. I subdivide the distance until I'm not colliding anymore. It's by no means perfect or the fastest way because of its reliance on pixel testing. Perhaps a better way would be to use polygons.

The lastX, lastY method will always be inaccurate and will always leave a gap, unless you've only moved 1 pixel at a time. The faster your sprites move, the more inaccurate that method becomes. You will need some way of testing that you're no longer colliding as you move the object away from the colliding object. Then, at that point, you're touching exactly and you can do other stuff like transfer forces around between them.

You'll notice in my balls example, I don't actually reset the positions to the point of impact, I just pass forces around.. in fact, I think I just reverse their directions. A better way would be to determine the angle of impact and divide the forces up for the two objects depending on this angle. You can really go to town on this if you want, but I'd be tempted to use a 3rd party physics engine in that case.

As for your overlay, you might want to use a flag in your game loop which, when set, calls FillRectSub(const DestRect: TRect; Color: TColor)
This will subtract the colour you supply from the destination surface.

Chesso
02-01-2007, 12:34 PM
That's a bummer, I can't really think of anyway to make the collision better the way it's setup now without too much here, there and everywhere.

Could (well I would assume it could) the collision detection of the sprite engine itself be improved and be expanded on options?, I know a couple of people who have worked on the source before and are familiar with it, they don't come online much but when they do, I might bug them to have a look for me :P.

So if I use that, at the point I want the game paused, then I would use that after everything has been drawn to the buffer/surface?

Oh and another small thing, I figured I can pause by simply disabling the timer, but then the screen won't re-draw itself, or perhaps I'm wrong on that, I haven't tested that yet.

jasonf
02-01-2007, 01:19 PM
well, the way I did it was with a flag.

If not paused then doMove(1);

then I set and unset the pause on a keypress.. all from within the timer.

I originally tried 2 timers, one for logic, one for renderring.. but it was slow for me. Unless the renderring is HWAccellerated, you want to really keep an eye on it, not have it running in its own thread eating up all the CPU :D

I think a generic collision/react system would be beyond the scope of DelphiX, it's a component set to give you easy access to DirectX.. it's not really supposed to do any more than that. Which is why it's so useful for so many types of games.. because there's no game-specific code in there. No AI, no Pathfinding, no Physics no Particle systems.. etc.

You'll have to roll your own I think. Anyway, DelphiX is a little long in the tooth these days for expanding with new features.

Chesso
02-01-2007, 01:32 PM
Awww I dunno, it's not too bad really.

Some small things like some good solid coded options for collisions and other minor things and I don't think there is anything to complain about (except maybe something simpler lol).

But so far, aside from the little collision problem I'm having, I'm pretty happy with it.

I was going to give a crack at doing the same thing in Asphyre and seeing how far I got (was told that my problem would be easier to solve) and it apperently is more optomized than undelphix.

However the initial install doesn't have the sprite engine and the power package that does, doesn't stick the engine in the component palette, maybe it's just me but I'm used to having it there for some reason, oh well.