WHAT WENT RIGHT.
We started the meeting on a positive note by brainstorming what went right for us:
- work times were designated
- strong creative force
- we had a good sales pitch
- “outsourcing” brought people in
A strong creative force is born with people who care and are excited about a project. When your project starts up, you get some bonus excitement to work with. If you don’t use that excitement in time, it goes away. We waited too long to give excited people something to do, so they got bored and left the project. We thought bringing in more people would help get the project off the ground, and each of those people had some excitement to start off with, but the same thing happened to them: we waited to long and they got bored.
So why did we let that happen?
WHAT WENT WRONG.
- no documentation early on (gamedoc)
- initiated the project too soon
- mixed unfinished ideas with production
- scope of project was ambiguous
- too much content
The project wasn’t well-defined. We started developing the project before we even knew what it was. If you don’t know what the project is in the beginning, you never will. If you can type up a 3-page gamedoc of what your project is, if you can play your game in your head, your project is strong enough to expand upon. We never had a gamedoc, we started the project with some idea that sounded like it could work. We should have drawn up several gamedocs and gone with our favorite one. Instead, we went with the first idea we had.
If you start producing a half-baked idea, what do you think you’re gonna get? A monstrosity. Complete your thought, then produce it.
If you don’t complete that thought, you’ll hit problems. You won’t know how big your project is supposed to be, so you can’t estimate how much time should be spent doing what. You won’t have a cap for how much content (art, audio, etc.) you want to produce; you’ll keep asking for more and more until it matches the idea you have in your head. If you know what your game is, you’ll know how much content it needs, and what the content should look and sound like.
We had a team of maybe 15 in the first month of production. Half of them were designers. NEVER “bring designers on for production.” There’s nothing to design if you’ve begun production. Beginning production means you know what you want your game to be, so what’s there to design? Bring people on once you’re ready to produce, and those people should only be artists, musicians, or programmers. If you keep designing after you’ve begun production, the people you’ve brought on will get frustrated because you keep changing the design or are waiting for a final decision. You don’t have to start production immediately; design as long as you need to, you have all the time in the world.
Document your project before beginning production.
- no communication when someone had a design question
- lack of clarity
- lack of creative direction
- recreating content because a design choice was changed
All these things could have been avoided by having had the design completed before production.
This is one of the most important things that creates momentum in a project: confident answering. When someone has a question, it means that they’re thinking about how to do their job and want to do it right. As the project lead, you need to complete that momentum by confidently answering that question. Usually it’s a design question. If you know what your project is, you can answer anything. It’s important to answer the same question consistently, so you don’t give different answers to two different people. People will trust that you know what you’re doing. If you’re asked a question that you don’t have the answer to, your artist or programmer will try to assume the role of a designer to help you answer the question. Then you’re wasting their time. We hit the worst-case scenario where all the programmers and artists ended up trying to be designers to help answer questions. Think to yourself: are you honestly running a confident project? No one knows what they’re doing. You, the leader, are who people depend on for answers.
Don’t answer a question if you’re not sure that it’s the design choice you want to go with. The programmer or artist will make their content according to that answer. If you change your mind and decide it would be best if we did something else, all that work was for naught.
Be able to confidently and consistently answer any question asked.
- no early tests were done
- testing should be done instead of discussion
- deadlines should have been used in place of milestones
- multiple hats should be used carefully
Before production, we should have made prototypes. You don’t need artists or audio people to make prototypes, barely a programmer if you can use an engine. Like I said, we went with the first idea we had. We should have had several ideas, prototyped our favorite ones, and started production on the prototype we liked the most. No early tests were done — everything was in our heads. If you can’t see or touch your idea, you’ll have trouble deciding if you actually like it or not.
We gave general dates for things to get done where we should have used hard deadlines. It’s amazing how well people respond to set dates if you’re confident about your decisions.
We had a team of 15 people at one point, but we still had people wearing multiple hats (taking on multiple jobs), as many as three or four. This should only be done if you’re handling yourself well with one job. Keep in mind, this project is important, but there are other important things like life and school. Take those into consideration when you take on more responsibility. If you can’t handle all the tasks you take on, the people that depending on you won’t be able to do their jobs.
Be able to touch your ideas. Be confident about setting deadlines. Make sure not to take on too much responsibility.
We know why we ended up where we did and how we got there. Make sure to start your project off right from the get-go.
Project Z was officially ended on October 18, 2013.
I was hesitant to do this because it would means my sixth failed project. But that day, Tobiah Marks came over and told me something that really blindsided me: “Aim to fail. Fail early and fail often.” It was 2 o’ clock, I didn’t believe him until 11pm. It didn’t make sense to not try to succeed, but that’s not what it was about, I wasn’t thinking of it correctly.
He had explained you only have so much time, you better spend that time doing something that you love. Z ran for five months. Granted, I enjoyed myself when I programmed some cool new feature, but 90% of Z was sitting around doing nothing. Even though you’re doing nothing, you’re thinking about it and being lethargic about it. Why would I want to spend five months of my life doing that?
I went to dinner with Tobiah and he explained that with every project, you can aim a step ahead of yourself or five steps ahead of yourself. No matter what you do, you’re going to learn about the same, so why not do a bunch of small, completable projects and learn from each one, rather than one big AAA title (not AAA but you get the point).
The team was dead, why complete a project if no one wants to complete the project? Why work on a game that I myself wouldn’t want to play? No, you do what you want with your life. You can spend money, you can lose resources, but you’re never getting time back.
You need to think of this on a macro scale: you can put your time into something you love or you can put it into something you dislike, which one would you choose? What if it was for money? Is money important? I’d like to think not. Do you know what it means to sell out? It means to trade your life for a sum of cash. You traded all your time for money. It’s easy to do, but not worth it. You didn’t work for it, you’re not earning that money. Do what you love, even if it means it’s not the most lucrative thing.
A friend of mine told me a story where he was offered a job for more money, but that he would hate the job. Was it worth it? He’d be selling his happiness for money. With the help of his uncle, he decided against it; he paid the extra money he would make for happiness. Money can’t buy happiness, but you can refuse to let happiness go at the expense of potential financial gain. If you do what you love, things will follow.
So what did I learn from Z? I’m putting on a postmortem tonight at 6:30. I felt better upon announcing the postmortem, it made me feel like these 5 months would be worth it because I’d get to find out what I learned from it.
I’ve had this idea for a while. Basically, I wanted to have a control panel full of switches and pots and LEDs, have it hook up to an Arduino and have the Arduino send data to the game. That way I can turn the potentiometer to tweak some value without having to recompile the code. So I put together a breadboard with lots of stuff and then I realized I could just use a keyboard instead.
I have this wireless keyboard that has a twisty knob for volume control. I really wanted to use that for value adjustment, so I did. I decided to combine this value-adjustment system with the Console class I had already created. Android doesn’t let you use System.out.println() to print to any console of any sort. If you want to, you can run “adb logcat” in command prompt and Android will use the command prompt as an output console. Then you can call Log.d() to print to the console. The problem’s that Android prints A LOT of stuff, so it’s hard to find the output you’re looking for, which is why I created a console class to overlay on top of the screen. It displayed FPS and console output.
Anyway, I decided to combine the value adjustment system with the console. The first thing I wanted to do was make it so turning the volume knob didn’t adjust the Ouya’s volume. You can override that functionality. If you override the onKeyDown() listener and catch the volume up key (if(keyCode == KeyEvent.KEYCODE_VOLUME_UP)) you can return true. This tells the system that you’ve handled the fact that the volume up key was pressed, so it doesn’t need to do anything. If you return false, the system assumes it needs to do something about it, so it adjusts the volume.
Then I could move on to the actual system. I started with 8 doubles (mapped to F1 ~ F8) and 4 strings (mapped to F9 ~ F12). When the user holds down one of the function keys, types something, then lets go of the function key, the value changes to whatever the user typed. Alternatively, the user can hold down a function key, turn the volume knob, then let go of the function key. Then, somewhere in the game code calls Console.getValue() to get the value of that field the user just changed.
The next thing I did was make it so the console was hideable. Even though it’s invisible you can still tweak the values. That’s hella cool.
From there I added some ergonomics and made it pretty. When you press a function key, it highlights which field you’re editing. When you type, it shows you what you’re typing in realtime. You can press escape to exit editing. If you press a function key without typing anything, it will lock on that function key, letting you type, only saving what you’ve typed once you press the function key again or enter. If you press a function key, you can press another function key to switch focus to that value instead (discarding any changes you made to the first value).
I wanted to actually bind these value tweakers to fields within the game code. By now I had it so the game code had to call a getValue method, which works well if you’re just trying to decide which value works best for you. But what if I wanted to edit some important data realtime? I created a FieldBinding class full of 12 getters that can be overridden to get a field from the game and store it in one of the function keys every loop and 12 setters that can be overridden to automatically set one of the game’s fields whenever I tweak one of the function keys. I ended up having game-bounded values flash if the game changed them. The FieldBinding class gets extended and set in the console as the designated FieldBinding instance.
It was a lot of fun standing in fire and having the health value flash every time is took a point of damage, and then turning it back up to 15 realtime. It’s on my wishlist to add a command console so I can say “teleport to debugland” or “kill Cara”. This fieldbinding system is going to make making the combat system hella fun.
In other news I implemented pool terrain. Walking in a pool halves your movement. Pool terrain can be frozen into permanent ice (ice usually melts after a few seconds). The frozen pool can then be melted back into a pool using fire. I need to have it so the pool can douse fire.
And I was showing this fieldbinding system to someone in action, and I was exclaiming how happy I was that this was awesomely working, I just have to turn this knob and she gains health back and if I turn this value up the spell reaches further. And I got him to miss programming and remember how awesome it was (he’s an animator now, a good one too). It’s an amazing feeling being so passionate about something that others can feel it too. It’s refreshing to be proud of something I did.
I’ve been experimenting with a couple sound player classes within Android.
The first one I came across was SoundPool. It looked promising and seemed like it was what everyone was using. I had an ogg Vorbis file that weighed ~2.4mb (shrunk down from 31.6mb wav using Audacity). I kepy getting an error saying it was trying to allocate more than 1mb for the SoundPool but that 1mb was all it allowed. So I shrunk the ogg Vorbis file down to quality 0 (~800kb) and tried again. Again it didn’t work. Turns out the uncompressed version (which would be several mb’s) needs to be less than 1mb. So just to test I took a <1mb sample from my file (as a wav) and tested. It worked as expected. It turns out SoundPool is only meant to play short sounds that are used over and over.
Everyone said that the alternative and preferred method of playing music is to use MediaPlayer. So I looked at MediaPlayer, and it handled playing my ogg file really well. The problem was getting it to loop, and I had a few specifications. It needed to play the beginning part of the song, and then when it looped, it needed to begin at some point a few seconds into the song (so it needed to skip the intro of the song). I also needed it to do that seamlessly, gaplessly, so no stuttering between loops. These problems were intertwined so I solved them simultaneously.
My first thought was to set the MediaPlayer to play my ogg asset (btw, I load everything in this game, audio, png’s, levels, from the assets/ folder, which is stored in the same directory as src/ and res/ etc. You can access things in the assets/ folder using AssetManager. It’s more dynamic than res and lets you have a directory structure unlike using resId’s). So I would load the ogg asset into MediaPlayer and set an onCompletionListener. In the listener, I put a MediaPlayer.seekTo statement that had the MediaPlayer seek to a few seconds into the song, and then called MediaPlayer.start(). There was a huge gap produced between loops, because the seekTo method takes time to seek. So I thought about loading two instances of the same song, so while one played, I could seek on the other one and vice versa. It would play one, then the other, as I expected, but there were still gaps inbetween just because I’m sure there’s delay in using the onCompletionListener.
So I took another approach. I decided to slice the song into two parts: the intro and the looped part. I had two MediaPlayers, one for each. I used the onCompletionListener to transition from the intro to the looped part, and it was seamless enough (might’ve been unnoticeable just because of how quiet the song was at certain parts), but calling MediaPlayer.start() again in the onCompletionListener for the looped part made it loop with a gap. So mixed in my older approach: I loaded the looped part twice in two separate MediaPlayers, for a total of three MediaPlayers. The two loop MediaPlayers would bounce back and forth using the onCompletionListener. I thought it would work because I wasn’t using seekTo so hopefully there would be no delay, but it turns out listeners are just too slow.
I found out there’s a MediaPlayer.setNextMediaPlayer() method. I tried to have the loop player select itself, but that’s not allowed. So I had the two loop players select each other. It worked perfectly, for the first two round, and then it just refused to continue, and I could never figure out why. So I wondered, why won’t the setLooping method work? So I set the MediaPlayer.setLooping(true) and it worked perfectly, every time. I started taking out excess code. As soon as I took out the setNextMediaPlayer method, it looped, but with gaps.
For SOME reason, MediaPlayer will loop with a small gap if its nextMediaPlayer isn’t set to something.
My looks like this:
MediaPlayer intro = new MediaPlayer();
MediaPlayer loop = new MediaPlayer();
loop.setNextMediaPlayer(intro); //weirdest bug ever. will never transition back to intro since looping is set to true, but setting this will prevent gapping
No onCompletionListener is needed.
On a side note, this is how I loaded the ogg from the assets/ folder:
AssetManager am = getAssets();
AssetFileDescriptor afd = am.openFd(“audio/sailingintro.ogg”);
intro.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
DON’T USE intro.setDataSource(afd.getFileDescriptor()); The FileDescriptor alone doesn’t have enough information for the MediaPlayer to know how to load your file. That’s why you have to pass in the two extra parameters (afd.getStartOffset(), afd.getLength()).
Now I have this system in a global Symphony class. Basically you can set the path of the background music in Tiled (the level editor) and the game will automatically load the ogg files (both the intro and loop) into Symphony for all to hear.
I should be posting more. It’s important to document your progress as you go along. As a fan of game developers I love seeing Hitbox post updates about their game because it lets you feel like indie developers are people too and you can do it just like them.
I haven’t been posting because I feel like all my posts have to be visually appealing with pictures and short to read. I’m not tailoring to that. I want to write just to write. I’m only posting pictures if it’ll help me get the point across. I can’t be a good blogger right away. I have to make my there through mistakes.
I finished spellcasting. It was a whole ordeal. I’m writing this code in a very reusable, modular, and abstract way. There are a few major types of entities that exist in the game:
Anything that’s a Being can exist in a TileRoom (a TileRoom can be either the Overworld that you freely walk in or Combat). The way that Beings occupy these TileRooms are exactly the same in both the Overworld and Combat. The only difference is the rules that let you move in each TileRoom. You can still face a direction, move, have a Status, step on a tile (activating its event), and interact with Terrain. Anything that’s a Being can cast a Spell. Basically everything that’s alive is a Being, so characters, monsters, even things like turrets in League of Legends can cast spells. They all have health, stats. I decided to create a container called a Party that has a list of Beings (so you can have a monster on your team ) and gave the Party an Inventory. That way, all the Beings in the party will share that Inventory.
TileRooms all have a grid where different kinds of Terrain are laid out (Frozen, Fire, Plateau, etc.). Every TileRoom can contain Beings, collisions, Terrains, and events that are triggered by a Being stepping on it.
Terrain can exist in any TileRoom (so either in the Overworld or in Combat).
Properties are attributes innate to a Terrain. A Terrain can classify a Property in three different ways: as a passive Property, an active Property, or an overlay Property. A Property always affects the Terrain the same way no matter how the Terrain classifies it. The classification decides when that Property is applicable (when it should affect the Terrain). A passive property affects the Terrain all the time. An active property happens only when a Being steps on the Terrain (it can also affect the Being if it chooses to, so fire Terrain can give a Being the ignited Status if it steps on it). An overlay Property happens when another Terrain is laid on top of this Terrain, because only one Terrain can occupy a space at one time. An overlay Property’s job is to decide which Terrain should be kept (and what else should be done based on which two Terrain’s were overlaid). Properties are modular enough that a Terrain can consider one Property as both a passive and active Property. I don’t know why you’d want to but it’s possible.
Spells are beautiful because any Being can cast them. Spells are basically sets of Commands that are tailored based on the Being casting it, so it’ll cast the same line of ice but in a different direction based on which direction the caster is facing. On a side note, anything in the list above with an askterisk (*) is a singleton. That means that the game only makes one copy of it, ever, and just reuses that copy over and over. This saves a lot of memory. So there’s an inherent beauty to this. Think about the spell Expelliarmus (the disarming charm from Harry Potter). It works the same exact way no matter who uses it, it does the same exact thing every time — disarms the target. Everyone can learn this same spell. So in the game, there’s a Party spellbook, and this spellbook contains a list of spells. Anyone can read this spellbook and cast one of the spells, and the spell will work the same exact way every time. The thing that changes is how it’s cast (it’s conjured in a different way), in this case (Expelliarmus) the thing that changes is the target, but it does the same thing to them. So it’s beautiful that the universe created these spells once and anyone can use them as many times as they want.
Statuses are to Beings like Properties are to Terrain, except Being only classify Statuses as a passive Status (meaning it affect the Being all the time as long as the Being has that status).
Commands are low-level code that the game uses to do things and make changes. Commands are the gateway between entities like Beings, Spells, Properties, etc. and the inner-workings of the game. They’re the handles that we can use to do delicate surgery inside.
This is how I design code and how I program. I do it in a very connected and interchangeable way. This makes things really reusable and opens up possibilities you might never think of doing (like casting Spells in the overworld. We planned on implementing Spells just in combat but it’s so much fun to what it looks like to cast a Spell in the overworld. And there’s no reason you shouldn’t be able to either).
Made a game for the Knight’s Tour and 8 Queens problem.
Whenever you solve one puzzle, it moves to a bigger board. Every board size is possible (I think) from 5×5 on.In chess, the knight moves in an L-shape. The goal of the game is to have the knight visit every space only once.
In chess, the queen can move any number of spaces horizontally, vertically, or diagonally.
The goal of the 8 queens puzzle is to place n queens (where n is the board size) in a way that none of them will kill each other.
Every time you solve the puzzle, it moves to a bigger board. Every board is solvable starting at 4×4.
I made both these games in a few hours each. Rapid prototyping You can download the Android app HERE.
Both these games have a solve function that solves the puzzle for you using brute force backtracking. It’s really pretty watching it work.
I have yet to make it look good on multiple screen sizes. I’ve only tested it on mine
We were going to make our own editor (twice) but it looks like Tiled has everything we’ll ever need.
It imports tilesheets and slices them up into individual tiles, then lets you make levels out of them. Each tile can have its own properties (like collidable or not).
It also has an object layer I’m playing around with (events?).
Right now, the prototype can read the xml’s (technically .tmx). Each level has its own set of tilesets.
It would be cool to use Tiled as for scripting, rather than having to hardcode events that happen.
Right now, we’re deciding on a kind of style, where the difference might mean using Photoshop as a level editor rather than Tiled. We’ll see what happens.
The prototyping system is going to be set up so that once you edit the level in Tiled, you’ll see the changes automatically on a running game with the press of a button
The new direction the club is taking brought several new members in. We have a few extra artists and two sounds guys.
My co-leader and I weren’t taking the correct approach. We appointed a separate project manager to oversee everything.
He’s experienced and knows what needs to happen first.
First we need to make the Game Bible.
If you have a question about the game, this book will answer it.
It documents everything from NPC dialogue to combat progression.
Multiple designers had different combat models, so we needed to meet today to finalize it.
COMBAT MODEL DECISION
There were two opposing systems for spellbuilding, so we needed to decide on one.
One would allow for on-the-fly but resource-dependent casting; the other would allow for unlimited casting of a few select spells.
—–what feeling did we want?—–
limitedness; or freedom?
We hadn’t decided on a central mood for the game.
Tim Burton or Salvador Dali? You can’t choose an artistic style before you choose a mood.
We all knew what we were going for, but we couldn’t pinpoint a word:
- nostalgic (most accurate)
These touched what we wanted for the game. What motifs could we use to portray it?
Now that we had what motifs we wanted to instill, what devices could we use to do that?
- no fleeing from battle
- visuals (trapped on island)
- level design (outnumbered in battle)
- spaced save points
- exiting the world is complex
- no fleeing from battle
- visually stuck on island
- grandeur (landscape)
- in battle, ran out of resources
- spaced save points
- cornered, no fleeing
- know what you must face
It’s important to include devices; it’s equally as important to leave certain devices out:
accidentally including a device like letting the player save anywhere will disrupt the mood.
We had the tools, but we didn’t know what to use them for; we needed to understand what we were putting the player through:
UNDERSTANDING THE GAME
Reference: Sword Art Online
You’re trapped in a world. You’ve accepted this fate.
Now, given the resources at your disposal, you must play by the game’s rules to find your way out.
We knew what the world was like.
We needed to understand exactly what we were facing the player with. We broke the game down into a ladder:
Escape world (end goal). How do you do that?
—–Defeat world’s creator at end of world. How do you do that?
———-Find your way out. How do you do that?
—————Negotiate environment (navigate mazes, “hack through vines”, defeat enemies). How do you do that?
——————–Gather strength and resources. This is the crux of our game.
Given this ladder, what devices can we use and how can we use them to promote each of these steps?
What we need to do next is know what devices will emphasize the elements of the ladder.
If we answered what devices could promote “Gather strengths and resources,” we would have seen that a spellbuilding system dependent on resources would have fit right in.
After we resolve the mood, we’ll be able to resolve the spellbuilding system, then the combat system.
We’ll know what we want the game to feel like, so we’ll be able to finalize the plot.
Then we’ll be able to do the Game Bible.
Then we can move onto production.
Really, knowing the mood is so fundamental, that nothing can be answered until we know what it is.
We’ve been told the club needs more spirit.
It’s hard to motivate people to do something. A club runs better when everyone wants to do something. How do you do that?
- Leave the club open all day
- Make the club a productive place
- Make your own progress
- Officer meetings
Leave the club open all day
No one wants to come in if they can’t come in. We were scared people would steal if we left the club open all day. But we’re a family, and there’s gotta be some trust.
Since we’ve left the door open, there’ve been more curious onlookers. We also wrote “Game Development Club” on the board so tours can’t call us “The Video Game Club.”
Make the club a productive place
The room has been overhauled twice.
The first time, we got rid of the video game station and couches and got more desks.
The second time, I rearranged things for more space, and set up workstations for people to create and draft at. Also whiteboards.
Make your own progress
It’s the trickle-down effect — if people see you making progress, they’ll want to make progress too. That your job as the leader.
As the leader, you can’t tell someone to do something you wouldn’t try to do yourself.
As the leader, you’re the carry. You pave the way for others to follow.
When others do venture into the club, having a task for them to do creates interest right away. After that, it’s up to you to keep them interested.
We decided to only have one officer meeting a month. By the end of the month, there were two hours of problems to discuss.
Communication is vital. It merges individuals into a group, a club, an unstoppable workhorse if everyone is motivated.
Communication + motivation.
When people feel like the club is active, there is more energy and more attraction.
We’re putting on a Retro Game Night with pizza. Some sage advice is that pizza attracts crowds.
I’ve plastered propaganda all over school.
Furthermore, advertising Zecharabra’s progress is generating interest.