5 ms·
You saw them a lot in old games (the kind likely to be written in assembly), because not even C, let alone a general-purpose scripting language, was acceptable
by ANTSANTS 13y ago
You saw them a lot in old games (the kind likely to be written in assembly), because not even C, let alone a general-purpose scripting language, was acceptable for performance reasons for quite some time, yet there has always been a need for greater abstraction and expressive power. Look at any Japanese RPG of the 80s and 90s, for instance, and there's probably a simple bytecode VM (or state machine, if you prefer) for scripts that move characters around during story sequences, one for displaying text in menus and dialogs, and so on. Look in an arcade shooter, and there's probably one for defining enemy movement patterns, etc. Tiny bytecode DSLs not only boosted expressive power for programmers, they also allowed non-programmers to script behavior. 6502 assembly might be out of reach for non-programmers, but `SETANIM PLAYER1 PLAYER_WALK_TICK; WAIT 20; SETANIM PLAYER1 PLAYER_WALK_TOCK; WAIT 20; LOOP;` is not. If you only have to remember a few simple rules to get the behavior you want, even learning to hand-assemble bytecode is not out of the question for a dedicated professional.
Nowadays, you'd probably be better served by embedding a general-purpose dynamic language in most of these scenarios, but hand-rolled bytecode can still win in certain situations that need high performance and/or low latency. Imagine, for instance, one of those fancy "danmaku" shooters with hundreds or even thousands of bullets on screen moving in intricate patterns. You just might want a language more dynamically manipulable than C to script the behavior of those bullets, but using a dynamic language that furiously generates garbage and demands collection pauses for something that must happen 60 frames per second on so many objects is probably going to cause hitches eventually that will get your player killed (in the game, at least). You'll then be subject to a very harsh but valid criticism: "I played games like this on my PlayStation back in the day with no slowdown, this guy must be a crappy programmer if his 2D game stutters on my monster PC." Sure, it's great that you don't need to break out the optimized assembly to do a Breakout clone anymore, but at the same time, you should feel bad if a 1Mhz 6502 provides a considerably more reliable experience than your game on a modern x86.
A certain popular 2D shooter series made by an ex-Taito arcade game programmer uses a bytecode DSL for its intricate bullet patterns for this reason. It was probably an easier decision to make when the series started in the late 90s, but today it lets the author be productive without adding wildly variable latency into the mix that would kill the gameplay. People should not forget that running smoothly even on poor hardware is a real feature. Even in 2014, I'm sure there are plenty of people out there still using Pentium 4s and Windows XP. If you make the only new games/apps/whatever that run well on these computers, you have a captive audience.
At the same time, I think you could extract 99% of the performance benefits of the bytecode approach if your language had a well-defined heapless, stackless "tasklet/microthread" subset that centered around mutating existing objects and making certain limited kinds of allocations (allocating from a memory pool and manually "freeing" by marking the object as unused later). Knowing that a piece of code will never generate garbage and that a garbage collection cycle will never happen during its execution makes a huge difference.
- munificent 13y ago> Even in 2014, I'm sure there are plenty of people out there still using Pentium 4s and Windows XP. Don't forget low-end mobile devices.
- x1024 13y agoEh, angry birds runs on Lua. Your point was?
- TheZenPsycho 13y agoI think the point is you don't generally need something with the extreme power and flexibility of lua to simulate comments like yours. A simple bytecode with 5 or 6 instructions should do. And it'll be performant enough to run on a casio calculator watch at full speed!
- ANTSANTS 13y agoAngry Birds is not a terribly involved or demanding game, and the hard part, 2D physics simulation, is handled in C by the Box2D library anyway. It requires no real-time control, you just aim the bird and watch the reaction. You could half or quarter the framerate and add enormous interframe jitter and the game would play exactly the same. If you tried to do the same thing with an demanding twitch action game, it would quickly become unplayable.
- eropple 13y agoLua's been fast enough to do what you describe for years on gear much slower than even bottom-end smartphones, but if that's too iffy for you, AngelScript is a sub-megabyte runtime when run on Android via the NDK. It's historically been performant enough for use on the PS2 (with its ballin' 300MHz MIPS CPU and 32MB of RAM). It's statically typed, has a very well-defined garbage collector you can pretty easily avoid ever invoking once, and as a simple transform language generates very little (possibly even no? I don't remember) heap allocations. It will also take literally ten minutes to set up for the sort of use case we're talking about here. (If you want to bind a big honking C++ library to it, then things get interesting, but we aren't talking about that.) You still write your perf-sensitive code in C++, of course. Just like if you embed Lua. Because you aren't dumb. munificent hit on the one use case where this makes a ton of sense to me--when you're a basically-embedded environment, he was talking about a platform with four megabytes of RAM--but that hasn't been a serious use case in games on popular platforms for a while now. Which is why I'm confused why it's in a book that seems to basically be for novices, at least without some "you should rethink doing this unless" asterisks.