The "action" systems that 2D game frameworks all now have...

Started by
14 comments, last by avision 9 years, 4 months ago

When implementing 2D games to somewhat heavy-weight 2D frameworks like Sprite Kit or Cocos2D, do you use the action system for everything or do you prefer a traditional game loop?

I'm currently working in Swift + Sprite Kit which is new for me. I find myself searching for documentation or sample code that implements a standard


scene->update(dt); 
scene->render()

style game loop, but then I think maybe I am just being old-fashioned and instead I should try to embrace the actions system. My problem is that the game I am working on doesn't seem like it wants to be implemented in terms of actions, but it could just be me.

As a little background, basically these frameworks are kind of new in the grand scheme of things, meaning before the mobile era the only "framework" most people would consider for a 2D game would be something like SDL. SDL isnt so much a framework as a hardware abstraction layer so this question wasn't really an issue. I'm just wondering what other people do besides me -- particularly people who didn't grow up writing 2D games without any kind of framework.

Advertisement

I am also curious what others have to say about this.

I like the idea of doing things in batches so you can sort stuff and only do slow context switches once. Passing time-delayed messages to everyone can be hard to debug and cause infinite loops.

Having said that, if the framework you are using expects to use Actions for everything, then it will certainly be harder to try and do things differently.

Maybe old gamers like us are rare, but I still like to have an init, while loop, shutdown game loop.

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

To be perfectly honest a lot of people don't understand how the more low level parts of a game engine like the game loop usually even work, my thoughts would be this whole action system thing developed as a way of hiding away all that code to make it simpler for a wide range of coders. You are talking about a framework for 2d games, not the deep down code of a massive engine like source or unreal or something. XNA hid its game loop as well if you used the base game class.

I haven't actually used any of these "action" things but taking a peek at cocos it seems like it would be pretty standard behavior you might implement in a game anyway, movements or color changes to sprites either instantly or over a period of time, based on the code it seems like a bit of a soft excuse for them to have hidden the core game code away in some singleton instance. At the very least they'll be tracking time and doing a bit of a mini-loop somewhere to actually advance all the actions and things anyway.

Is it good or bad? I don't know, I guess that's in the eye of the beholder, it probably makes things a lot more accessible in the same way that Unity has severely lowered the ceiling for coding ability that you need to throw together a game. Personally I'm more interested in down to the metal access and is the main reason I stick to libraries like SFML instead of frameworks that abstract everything away for you without any control. Why? Main reason is you learn a lot more, there are quite a lot of projects out there you might want to attempt someday, or working with others, that require someone to know all that down to the metal implementation information.

If you're going to USE cocos I would say you'd probably make your life a lot simpler to prefer their methods to what you're used to, unless that isn't -enough- to do what you want to do. I'm not that old really but to be frank I would say there is much more of a divide growing between code that would made by someone able to develop a full fledged engine for a game, and someone who does nothing but script for middleware.

Develop a game faster but have a much lower ceiling on your knowledge, or take much longer but have a greater depth of knowledge. Seems to be a wide divide these days.

I used it in cocos (long ago) because I didnt find any other means to control the stuff (like animations) tightly.

I hated it, it requires a bunch of loading code to prepare the actions, and when you need to interrupt it, cancel in the middle or something, it gets even more ugly. ( I dont remember very well thou)

In my engine, I have chainable tasks, the purpose of those (from my POV of course) is to use it when you need to execute some code that would be a rare if case in the game loop. Basically, having a loop full of IFs that almost never execute is ugly/poor code, so the tasks works perfectly for stuff like this, since in the game loop is just a tasker.update(delta); call. So I use it as a temporary code executer.

One of my tasks is a "delegate task", that basically executes a delegate till it returns false, making it very easy to create new tasks without having to derive a new class (just create a new method and plug on the delegate).

Chaining tasks is not as cute as I though it would be when I implemented it. Reusing tasks by reordering the chain is not so obvious and generally I end up with a few small tasks that are almost the same.

The fact that I prohibit myself from allocate memory at run time also requires pre initializing all tasks, with is also a pain in the ass. The task machine works with shared pointers so I basically initialize a bunch shared pointers with noop deleters.


I used it in cocos (long ago) because I didnt find any other means to control the stuff (like animations) tightly.
I hated it, it requires a bunch of loading code to prepare the actions, and when you need to interrupt it, cancel in the middle or something, it gets even more ugly. ( I dont remember very well thou)

Yeah the trouble with the actions thing that I see is the following:

  1. You often need something to happen that is "an action" in a general sense but that doesn't map cleanly to a particular sprite. It needs to happen to a bunch of sprites. It needs some state to be preserved across modifications to the sprites but not across iterations of the game loop. It is something that just naturally wants to be applied to some sprites in a loop rather than to be called by each sprite.
  2. You need to perform an action on a sprite that will take a long time (in game programming terms) to complete and probably will be cancelled, interrupted, or otherwise transformed before it completes.

Now obviously both 1. and 2. can be done with actions but would you choose to do either this way, all things be equal, if a framework wasn't demanding that you have to? And further, I would say that most "actions" in the games that I write are like 1. or 2. The exceptions would be very simple cosmetic things such as this guy is taking damage so make him glow red or whatever, but very simple cosmetic things are the exception not the rule...

In cocos2d-x I was able to get out of the whole action thing by just scheduling an update event on the layer and then treating that like the update in a game loop. I wrote an entire game to cocos2d-x and didn't use actions at all. Basically I used cocos2d-x for the node tree, input, and sound and that was the extent to which I used the framework. I believe it will be possible to do the same thing with Sprite Kit ... I am just posting here to see if I am being stupid. I don't want to be some dude who insists on doing everything the way I have always done it, but it just looks like to me that using the actions system is going to make my code worse.


scene->update(dt);
scene->render()


I'm not sure what you're specifically referring to, but it might be related to that code sample there. That's an inefficient and inflexible way to handle game updates. Even back in the simpler days, that kind of update loop only took you so far before you started needing piles of hacks to get all the different things to update in the right order.

On mobile devices (and the Web) you're also barred from actually having a main loop. They're not allowed. Those OSes do not allow an application to "run forever" but instead require that they only run in an idle or timer callback driven by the low-level OS/library itself. e.g., you can't have a `main` function, but you can have a `onAnimationFrame` (borrowing some HTML5 terminology there) that will be called at some point by the OS/platform when it feels like it (usually at a steady 60 FPS if the application is active, and never at all if it's not active). This is due to the vastly different multitasking models of mobile platforms and the Web compared to desktop applications.

Sensible PC game engines are still heavily event-driven and the main loop serves mostly to pump out events and poll hardware at a steady rate. Since other platforms do this automatically, it makes sense for game frameworks to abstract this detail so that things will work on mobile and the Web while also working on PC.

Sean Middleditch – Game Systems Engineer – Join my team!


That's an inefficient and inflexible way to handle game updates. Even back in the simpler days, that kind of update loop only took you so far before you started needing piles of hacks to get all the different things to update in the right order.

I don't know anything about fancy 3D engines but 2D games indeed commonly have a method that gets called with a time delta on some game stage object or whatever that then updates the state of in-play sprites and what-nots with the time delta and then draws them. Are you seriously saying that that is not common?

Don't know if mobile frameworks are not calling the update method in a simple loop in their implementations but whatever they are doing amounts to a loop.

Are you seriously saying that that is not common?

That's how I like to do it. However, Qt, being a desktop application GUI toolkit, wants to control the main messaging loop for me, so I have to write my code to react in response to callbacks. Not too much of a hassle, since I still have React(), Update(), Draw(). Having dozens of different callbacks that I'd need to react to would be annoying, depending on how high-level the API is.

Can you register for OnUpdate/etc events?

Lots of game engines I've used in the past were entirely event based, but a damn lot of stuff always ended up an Entity's called-once-every-frame OnUpdate event.

I'm not sure what your issue is exactly. Spritekit already has methods for:
update <---- This would be your game loop
evaluateActions
simulatePhysics
finishUpdate

These are called every frame. You don't need to use actions to control Sprites you can actually set the properties manually in the update method of your scene:

mySprite.scale = 1.2

Apple actually mentions in some of the documentation that this is the recomended way of doing things and that Actions should only be used for one time canned effects or UI animation

Cocos2D has similar methods too. However all the tutorials out there people just tend to use the Actions because they are simple to set up. If you are doing anything more complex than a match3 or word puzzle game then just drop actions and stick to updating your objects manually.

This topic is closed to new replies.

Advertisement