What I do in my 2D engine, is that I define a Polygon type property (called CollisionPolygon) for all classes that represent collidable objects. My Polygon type is basically just a list of lines. (More precisely, line sections. Each line is defined by its 2 end points.) You have to define the edges of the collision polygon of your objects manually once. If you have only a couple of objects to be tested for collision, you can use complex polygons with 100+ edges and it won't affect the performance drastically. If you have hundreds of objects, than you should stick to 4-12 sided polygons, just in case.
The next step is to implement the Point-in-Polygon algorithm. Since you didn't state which programming language or framework do you use, here's a sample implementation:
Then you create another method, using Point-in-Polygon, that tests if two Polygons are colliding (if any of Polygon A's edges is inside Polygon B, then it's a collision).
NOTE: You have to do it both ways (it is possible, that A has none of its edges in B, but B has one or more of its edges in A). Also note, that depending on the velocity of the objects, and your game's refresh rate, you might miss some collisions! Imagine two needle-like polygons crossing each other's path at high velocity. At time T1, they have no overlapping areas. At time T2, they intersect, but none of them have edges in the other one. This will not be detected with the Point-in-Polygon method. If this seems to be a problem in your engine, you will have to do some more research.
Finally, implement your own way of handling actual collisions. It really depends on what you want to do... In my engine, I always store the previous position of the object, and reset the colliding objects' positions to it whenever a collision occurs. I also calculate the inertia of the two objects (velocity * mass), multiply it with an arbitrary <1 value ("energy loss"), and calculate the new velocities of the colliding objects, using good old primary school physics.
I recommend defining an interface for all of these (ICollidable, for example), that contains the following:
CollisionPolygon property (type: Polygon),
BoundingRectangle property (type: Rectangle),
bool CollidesWith(ICollidable otherObj) method.
Then your collision detection will be basically this:
1. For every ICollidable on the scene, do the BoundingRectangle test with all the other objects.
2. If two objects' bounding rectangles collide, then do the polygon-based collison test.
3. If the polygon-based test is also positive, then register the collision (perhaps by storing indexes of the two objects).
4. Once all the objects have been tested for collisions, go through the registered collision instances, and do your "OnCollision" stuff. In my engine, this is where I sum up all the inertia changes for a given object, and then apply the changes.