Group objects into families. This helps a LOT! For example in one of my games I had a lot of different types of terrain (Desert, Volcanic, Jungle, Ice...) and I needed to allow for wall sliding and other behaviors to occur on most wall types, but not on Ice. So I created a family called SlideWalls and put them all in it, except for the ice tiles. Now in my logic I no longer have to test for each type of wall, it automatically works for any wall type that is added to the family. The same type of logic carries to enemies, bullets, hazards, etc... anything with similar behaviors or similar events should be grouped in families to simplify your logic. It really reduces the amount of redundancy in your events. And remember that objects can belong to more than one family. For example I have some enemies that can be shot and some enemies that can be jumped on. So I have a family for each, but some enemies fall into both categories so instead of doing special logic for those ones, I just add them to both families.
The other major tip I have is to use variables to track the state of just about everything. For example in my logic I have some pretty crazy tests that have to be done as certain moves can't be done when wall sliding, or when bouncing off a bounce pad, etc... so I create variables to track each of these "states". isWallSliding, isBouncing, etc... that way when I have to check if they can do a certain move, etc... I just test to see what state they are currently in. This allows for much more complex interactions without having to add a ton of extra logic, you use variable to track the state of objects that you may need to test for in your logic. By thinking ahead a bit you can make things much easier on yourself this way.