I sometimes have trouble determining what codes should be improvised, and what codes I should make an engine for. Here are pros and cons of improvised and engine codes:
Improvised:
+easier to get something onscreen
+doesn't require as much planning
-could make programming more difficult in the long run
Engine:
+could eventually make programming easier in the long run
-more difficult to get something onscreen
-requires a lot of planning
-can impose limitations on game design
I believe that there should be a balance between these two approaches, but I don't know exactly where to draw the line.
Begin to improvise one game. Once you think you have a bit of structure to its program, refactor any functionality that you think another game could share into an engine. Begin developing this second game in parallel, and continue this refactoring until the games are sharing as much engine code as needed. That's what I'm doing with a couple Python games I'm working on, both of which I plan to port back to the NES.
If you could code the game without an engine, you would, since that gives the most flexibility. So an engine is a tradeoff between the game and some other resource.
* Reduce mental difficulty with engine's abstractions
* Share effort among games
* Learn about engines
My take is that you want to start out without an engine, then when you see clear advantages, snapshot and try building an engine in, then see whether it was worth it. I think that tepples' approach of making the engine so central to development might hamper the games, with you focusing more on sharing it between games than letting the games expand where they want to. I've tried this in other contexts and often let the sharability overshadow eveything. A comical extreme would be to end up with both games being the same.
Making a game instead of engine gives you a straight single goal to reach.
I don't know how you could manage to code a game without coding an engine.
Even if you did it would quickly be a completely unusable mess of unmaintainable code. Heh, even game engines tend to finish like this, especially when written in assembly language.
Engine is part of the game, but that engine is made for that specific game not all would be games that are not yet conceived. You have less to worry, as you know exactly what your game needs and can implement it, no time spent on thinking about things others may want and then implementing them in a way others may like.
I always stick to the concept 'if you want to make a game, make a game, not an engine'. It worked well for me for a long time. During years, I have seen many people who wanted to make a game, but go with 'make an engine' way have never got to making the game itself (lost enthusiasm, never 'finished' an engine etc).
Engines may be a good idea for modern platforms in some cases, but for retro platforms where resources are very limited and universal solutions aren't working well, it seems to not be effective.
Perhaps someone thinking of making an engine should hook up with someone in the ROM hacking community who makes total conversion hacks.
Ok can someone please define how you could write a game without writing an engine ?
Bregalad wrote:
Ok can someone please define how you could write a game without writing an engine ?
I think what is meant by engine here is modularity and separation of code and data. Writing something that is an engine, would, at the extreme end, means that you could affect every aspect of the gameplay without touching machine code, and only touching data/macro code.
Yes, an engine is a separate entity, with most or all aspects being data-controlled. Making a game without an engine in fact means that you write similar code as an engine would have, but with tons of short cuts, you don't need to keep it all data-controlled, can hardcode many things, omit subsystems (for example, don't code any things that aren't needed for a particular game), etc.
I have a hard time to see how for example you could have a platformer and a RPG running on the same engine without changing a single line of code.
Regardless, considering how limited the NES ROM and RAM are, all shortcuts are good to be taken.
Platformers and RPGs might share the tile-grid updating code, but then they might not. Platformer maps tend to be wide horizontally and narrow vertically, while RPG maps tend to be closer to square. This influences the level compression. Platformers and action RPGs might share some collision detection code; movement behaviors would of course be different.
But one could still take the engine from one platformer game and make a total conversion mod of it resulting in another platformer game. Think Mega Man to Darkwing Duck.
A single engine idea is too all-encompassing. Keeping code organized in small modules that perform a specific task is still worth while though. If the code is kept specific, there is no need for runtime checks for different engine options. Reading controller input, for example: Generally you are going to want to be able to read all buttons, and if you only need button A, the slight overhead of doing so by reusing controller code is not a big deal, plus the benefits of abstraction are still there.
Example, to access the NES controller, the code/module is included somewhere, then I include this file when needed:
Code:
; ca65
.ifndef _INT_CONTROLLER_H_
_INT_CONTROLLER_H_ = 1
.scope iController
; function
.import refresh
; variables
.importZP pressed
.importZP pressedLastFrame
.importZP pressedNew
.importZP releasedNew
.endscope
.endif
In use:
Code:
if iController::pressedNew & #BUTTON_START
; do stuff if start pressed
endif
I think the key is staying organized and keeping things that are separate, separate. Using namespaces this way, you could avoid ever having to directly reference a global variable.
I like the idea of focusing on sub-engines rather than trying to make one big engine. You make a framework to piece together sub-engines, and then you can either reuse old sub-engines you've created, such as a sound engine, or make a new one on the fly. You can also tweak reused pieces to fit the needs of your game. I always reuse my template for putting these pieces together, and just change the mapper specific stuff like bankswitching. Then I'll usually go as far as reusing a sound engine, math libraries (includes multiplication, division, random number generation, etc.), perhaps sprite mapping code, and PPU updating code (By that I mean the piece that physically writes buffers to $2007). I never reuse game logic code, anything relating to AI, or even map decoding. All of these will depend on the type of game I'm making.
If you plan on making more than one game, I think it's important to keep your code modularized so you can reuse pieces of it. I can gladly say I will NEVER have to write another math function, no matter how many bits I'm multiplying together. All I have to do is include my math file, and make sure my variables are declared properly. Also common macros, like reading a controller. 3 handy variables to have the ability to reference immediately: ControlCurrent, ControlPrevious, ControlTrigger. The first two are obvious. Didn't know what to call the last one. It contains specifically, newly pressed buttons. Since I always forget the formula of how to get that value, I'm glad I don't have to figure it out again each time.
Writing code that is easy to maintain is a worthwhile goal whether or not you're going to reuse it after the current project. Modularity is a principle that can often result in maintainable, well structured code.
However, knowing how to properly modularize a system usually comes with experience. You can (and should) plan for it as you're going in, but if you haven't written this kind of system before you will inevitably leave some critical things out in your first pass anyway. Over the length of your project you will rework, revise, and hack that system to get what you need out of it.
In my opinion, game engine building should be an iterative process, where each iteration is the production of a single game. Finish and release a game first, then review its code. Extract anything you think is worth keeping to begin your next game project, and if there are systems that you can refactor or rewrite in a better way now that you've seen the final state/needs of the first project, this is now a good time to do that. Continue from here to finish your second game. As you repeat this process, the code you retain should become easier to work with, more generically applicable, more elegant, and you might get to something worth calling an "engine".
For the hobbyist, I think you should just focus on finishing your game. Think a little about your engine while you're between games, planning. Just making a good first game is a hard enough problem without dragging yourself down worrying about whether or not you can reuse any of this code for the next ten games you want to (and may never) make. No matter how much mess you happen to make getting the first game finished, at the end I guarantee you will have left over much code and/or experience that you can build from for your next game; you don't need to worry about that up front.
I don't hesitate to hard-code certain aspects of my games if I am certain there is only one of something, for example, like a main character. In my new game, there is a hard-coded main character and a hard coded familiar, because I know that is how it will be. But, I'm re-using the sound-engine from Nomolos. However, I recently re-wrote it to use structures of arrays rather than arrays of structures (thanks Tepples). I also ended up re-writing a lot of other stuff that I might have re-used from Nomolos, and found my fluency in 6502 went up quite dramatically from the last time around (probably largely due to using structures of arrays it really shows how idiomatic this is for 6502 when you get used to it). I think I'm with Shiru on this one. Each game is so unique you're going to end up re-writing a lot, and 6502 is so flexible your fluency will probably multiply from one game to the next. So...modularize what you can, but don't worry too much about making a super ultimate generic game engine that you'll never have to touch ever again. Especially because as you add more and more layers of abstraction and indirection, this usually implies at least some overhead, which on a constrained system like the NES just isn't worth it, to me. Abstractions are so hard to get right. When applied to a new problem, they often leak and you have to hack them anyway.
GradualGames wrote:
I don't hesitate to hard-code certain aspects of my games if I am certain there is only one of something, for example, like a main character. In my new game, there is a hard-coded main character and a hard coded familiar, because I know that is how it will be. But, I'm re-using the sound-engine from Nomolos. However, I recently re-wrote it to use structures of arrays rather than arrays of structures (thanks Tepples). I also ended up re-writing a lot of other stuff that I might have re-used from Nomolos, and found my fluency in 6502 went up quite dramatically from the last time around (probably largely due to using structures of arrays it really shows how idiomatic this is for 6502 when you get used to it). I think I'm with Shiru on this one. Each game is so unique you're going to end up re-writing a lot, and 6502 is so flexible your fluency will probably multiply from one game to the next. So...modularize what you can, but don't worry too much about making a super ultimate generic game engine that you'll never have to touch ever again. Especially because as you add more and more layers of abstraction and indirection, this usually implies at least some overhead, which on a constrained system like the NES just isn't worth it, to me. Abstractions are so hard to get right. When applied to a new problem, they often leak and you have to hack them anyway.
Couldn't agree more about the structure of arrays vs. array of structures thing. I think Tokumaru introduced this concept to me as "interleaving" data. My code is so much more efficient now that I handle things this way. I actually did the same thing, where I went back and turned everything in my project to structures of arrays, because it has that much of an impact on performance.
But yeah, pretty much unless you're releasing some sort of NES game maker program with a nice GUI where anyone can make a game with no programming skills, you should be able to hardcode certain things into your engine for the sake of your time and system performance. I'd say if there's more than like 3 of a given thing you're handling throughout your game (music, levels, enemies), you'd probably want to create something to handle it generically. Otherwise, you might consider hard coding it.