Animation in particular is something I would like to know in detail. I checked out a book and I feel like there's a lot of groundwork I need to familiarize myself with before getting there (lot of math).
Animation and graphics is where math is KEY. Matrix and vector arithmetics must become your friends, same with trigonometry, linear algebra and quaternions. More advanced features in gfx/physics will require you to dive into new math areas but this is something you'll soon discover once you start research on a given topic.
At what point do you call the application an 'engine', as in what exactly are the bare essentials. Is that when you have a way to define game objects, have some physics system set up, and can have scripts running? Is the ability to attach scripts to objects (plus free-standing un-attached to any object) the defining feature of an engine? Also, how do you represent objects(players, npc, etc.) in game?
There's no strict definition of what an 'engine' is. In my book, as soon as I get a separate interface to handle drawing, audio, input and file access, I talk about having an engine. These are pretty much the bare-bones of any game engine out there. Physics, animation, memory management etc. are "just" additional functionality which you may/may not need depending on what kind of engine you want to make. Also: your target platform is important. Working with single OS is easy, it's after you start targetting multiple hardware when things start getting really interesting. For example, you may need to solve memory allocation performance issues on console X which you haven't seen on a PC, so a custom memory handling scheme may be required. It's a fun but sometimes frustrating process, especially if you're dealing with "device X" for the first time. Either way, for starters I highly recommend focusing on a single platform (like Windows, Mac or Linux) and start building up your knowledge from there. As for object representation, there's really no single way to do it. In my old 2D engine, I represented every single object on a scene with a "SceneObject" class which contained a bounding box, transformation matrix and some other data essential to put it on screen and make it move. Some people put all this data into a single class, others take advantage of multiple inheritance, so you may get a separate class for "Object" (just bounding box and transform data), "MovingObject" (extra class to make the object move), "PhysicsObject" and so on. You'll have to see which solution suits you best and which is the most comfortable.
The one paradigm I have come across in a few places is the event-based one. Each script responds to 'events' generated by the game and calling callback functions that will be invoked when the script is processed. Surely the more pre-defined types of events you have the easier it is to write scripts in terms of, right?
True, though I'm not sure having a lot of predefined events is a good approach. If you want to focus on making a game engine, one thing you can do is provide some abstract interface for the user and let him/her come up with custom events of their own. How the event itself is handled can be then easily customized via a script or application code, so you don't have to touch the engine. What you can do is create an in-engine event handler that each frame will process the created events and call their "Execute/Action" functions which launch the event's functionality. So one idea is to create something along these lines (in C++):
// event class for the user to override
class Event {
virtual ~Event() {} = 0;
virtual void Setup() = 0; // perform necessary setup for event
virtual void Execute() = 0; // execute the event action
}
// in-engine event processor
class EventProcessor {
public:
void QueueEvent(Event *e); // add event to queue
void Update(float dt); // update event queue, check whether the event should be executed
private:
std::queue<Event*> m_events;
}
// call this function somewhere in the main loop
void EventProcessor::Update(float dt) {
Event* currEvent = m_event.front(); // fetches next event in queue to execute
if(event_should_execute) {
currEvent->Execute();
m_event.pop_front();
}
}
/* in the actual application */
class GetWeaponEvent : public engine::Event {
/* do whatever you wish the game to do on weapon pickup */
}
This is just a very rough code sketch but it should give you the idea. Note that this is only an example on how to handle game events. Apart from those, you will need to take into consideration other things, such as system events, key input, mouse handling etc. Once your idea clarifies it's important to think through the process of handling all events very carefully, since you want to give the user enough flexibility but at the same time, you'd like to have as little bloat-code as possible (ie. requiring the user to write 100+ events just to get the basics running is not a good idea).
I see you have a 2D engine called Talon. Did you need to write additional (non-script) code to create the final games i.e touch the engine proper?
I didn't have to write any additional engine code and the games were coded purely in C++. Talon had no scripting language support since my goal was to create a simple environment to make games fast and I was the primary (rather: single) user of the engine. In my case scripts gave me no advantage over writing C++ code but "your mileage may vary". Either way, having scripting support is never a bad idea, especially if you want to make a bigger game with fully programmable logic. This way no recompilation will be required to make the tweaks to the gameplay itself (also, this makes specific types of patching a lot easier!).
As a sidenote, I strongly recommend grabbing this book. It's HUGE and not the cheapest out there but it has all the quintesential knowledge required to start off with engine programming. It also comes with a chapter dedicated to animation, so you may find it really interesting:
"Game Engine Architecture" by Jason Gregory. http://gameenginebook.com/