Closed Fyll closed 8 years ago
Sorry for the late reply. I told myself I needed to ponder this one, but I don't think it helped.
Personally, I would like to 'finish' this project. That said, I've got another game I'm working on, so I won't be heartbroken if we decide to stop here. I'm definitely better at C++ than when we started :D
If we do stick at it, I agree that it's time to get some momentum going. I don't think we're ready for content though. What we really need to do at this point is what they call 'finding the fun'. We need to work out which bits of the game are enjoyable, and develop them, and which parts aren't, and fix or remove them. We have a functional game. Once we have a functional and fun game, we can look at making it bigger.
With regards to fun, the main sticking point for me is the platforming. The controls all feel… wrong. That's probably just a problem with the numbers though, so we could tweak them and see.
(EDIT: I tried tweaking the numbers. It definitely helps, but there are a few problems that will mean changing code. There doesn't seem to be any friction on props, either for the player or for other props. I keep sliding off crates into the abyss! Also, it might be good to ignore friction for upward movement on the player. Wall sliding is good, but having walls slow your jumps is annoying.)
My other gripe would be the lack of strategy. I find I don't have to think much to get through the levels. Most of my deaths are from the platforming, or from dropping a cannonball on my own head. We either need to make the game more 'intellectually challenging', or we need to change focus and make a mario clone.
Also apologies for the late reply.
I am in favour of winding this up at some point in the not-so-distant future. My time is very limited at the moment as I'm in the thick of writing my thesis, so until the Autumn I don't expect to be able to invest a great deal of time in this. (Sorry also for my aloofness generally, this year has been pretty busy so far!)
I agree with David that the controls need figuring out in some way. I've only ever played platform games on a console with a controller, so I don't know what PC platformers do. Playing the game just now I've noticed two things:
EDIT: Okay I see we have a sweet-looking menu now, awesome! However, allow me to be a complete pain the arse and say the keybinds are all wrong. Let me propose the following:
I also agree that the game needs to be more challenging. However, I think if we're going down the puzzle route then we need some concept of an inventory with pick-ups. My reason for saying this is that in my (limited) experience puzzle games require a sequence of different actions, each depending on the previous, in order to get the final result. Our game would fit this pattern if the weapons/items were dotted around the level and each item was required to get to the next one or exit the level. The downside of this is the amount of time that would need to be invested to create an inventory system with some kind of pick-up detection and (optionally) messages describing what the pick-up does. The upside is that we wouldn't have a Mario clone :-P. EDIT: having played for a bit I can see that it would be possible to have some puzzle functionality without pick-ups, but with the game mechanics as they stand we're a bit limited in what we can achieve.
Once we've found the fun, then we should just work on polish, such as proper save/load functionality, character name, backstory/branding.
How about the following plan of attack:
Also, did I mention the character needs a name?
EDIT: Also just profiled the code and the function that's using up the most time is the Vector subtract operator, which I think suggests that the code is fairly well optimised(?), so well done guys.
I believe Iain already programmed in an inventory system of sorts. The blue gem that appears in one of the levels is actually a flamethrower pickup, we just don't notice it because we have all the guns already.
I like your plan of attack.
He doesn't strictly speaking need a name. He's mysterious!
The horizontal slowness is caused by the floor having too much drag, and that is on my list of things-to-sort-out. I think an inventory actually wouldn't be that bad to do (some combination of pickups and the pause menu).
As for your keys, don't they require 3 hands: one for mouse (aiming/firing), one for moving (left/right or A/D), and one for jumping (space). Changing space to make you jump (and I think WASD is already in) will be easy, but I would think it would be better to have jump near the arrow keys.
I do agree that the controls are wonky and the puzzles are easy, but I think the puzzles being too simple might be solved when there are more of them around. Obviously, I can't say for certain, but at the moment there are only a handful of puzzle bits, with only about 1 solution each, whereas the original plan was for lots of puzzles with multiple solutions, wasn't it?
Oh cool! Well don't I look as out of touch as a government minister? That should lighten the load somewhat then :-)
Also, I could warm to him being nameless. A bit like "The Narrator" in Fight Club :-P.
I more mean finishing touches, like sorting out the save/load functionality and the like. Testing into the ground, that sort of thing.
EDIT: I think the majority of keyboards are such that you can reach A/D with your fingers and space with your thumb. Correct me if I'm wrong though.
EDIT2: David's adjustments to the parameters seem to have done the trick. Thanks!
Speaking of names, what's the opinion on putting a story/context in? If there's no story, he doesn't really need a name until the end when it's fluffing time (the code's fine just calling him "Player" for now), and if there is a story, then, we really probably should sort out our text (assuming we're fine with just using menu-esque screens to relay any text). Also, a name and story may suggest NPCS....
As for awkward jumping, what would you say to disabling mid-air movement? That might make things feel a bit more natural, although it would obviously make precision platforming a lot harder.
Story did occur to me, though we don't want to make too much work for ourselves.
EDIT: Also we need to discuss the future of the remote repository. With my PhD coming to an end I may have to downgrade my account to free again, which means we'll lose access to this repo. To preserve these issues and so forth I would wipe the commit history and make the repo public. BitBucket is similar to GitHub, but a free account allows for private repositories. So that's an option.
Huh, I didn't know you needed to pay for having a private repository! Seeing as I'm hopefully going to be a student for another few years, I could try to set up a private repository and shift control over to me (Mwa ha ha ha! >:D), but that would still only be a temporary solution (although if we're still working on this in 3 years, something has probably gone wrong).
As for the vector sub function being the most called (only just noticed your edit), that's probably because of how nigh on everything is interested in relative positions, so I wouldn't necessarily say that it's a sign of good optimisation....
EDIT: Also, as for the friction not working on Props, I believe that was just caused by a typo in the code (although it's been sufficiently long that I may have just broken something instead). I've fixed it and pushed, so hopefully friction should work fine now.
That might work. We also have to ask ourselves: is this something we actually want to make money out of? Because if not, then an alternative would be to just make the repo public and open-source it in some way. Employers like to see code, so having this available would be the upside.
No no I genuinely think it means the code is well structured for performance. The perf command bundled with linuxtools records the amount of time spent in each function. Here's the output: The two functions that are taking the most time are functions that are very inexpensive to run (one's just a simple subtraction and the other is just accessing an integer in memory). Yes, vectors are subtracted a lot I expect, but the point is that the function that's using the most cycles is also the one that's also "pre-optimised" so to speak. So anyway, good work :-)
I'm not sure I'd want an employer looking at my code... It's not exactly the cleanest stuff around. :(
Also: Hooray, we're slightly optimised! From my own quick checks I assumed the function with the most time spent in it was SDL_GL_SwapWindow(), but that's not even on the list!
Well there will almost certainly be some platform-dependence since the versions of the dependencies you're running may be different, and the binaries may be prepared differently. You can check by running perf record ./game
then perf report
(you may need to apt-get install linux-tools
first).
The picture is quite different when the code is compiled with the optimisation flags, but I can't be bothered to recompile every single source file again, so you'll have to take my word for it on that one. Not different in a bad way of course, but from looking at the unoptimised assembly generated by the compiler, it seems to spend about 75% of the time in Vector::operator-
just doing function overhead stuff (setting up the call stack etc.). Turning optimisation on, I expect the compiler probably inlines some of these smaller functions, so at the assembly level there's no function call.
@Fyll Your fix for props works! Hooray! Definitely feels better. I think if we can stop him sticking to walls when jumping upwards, the platforming should feel pretty comfortable.
Are you guys happy for me to start new issues for the sticky-walls and for the puzzles-vs-mario debate, and then close this one? The question (if "So…?" counts as a question) seems to have been answered.
The wall grinding might be tricky to remove, as the easiest way to do it that I can think of would be to just turn off the Player (or everything)'s vertical drag, but then that would mess with swimming. I suppose this raises the question: Do we want water in? As established, we have no water physics (and I'm pretty sure we'll never have any either), so at the moment it only serves as a thing to freeze or get stuck in (because you can't jump high enough to get out).
Seeing as we're a robot, it would make sense to just short-circuit when we touch water, right? And that way I can completely remove drag (not friction, mind), which should make the path-finding a lot nicer at least. Also this would mean we wouldn't need "swimming" animations, or to faff about trying to repeatedly jump in the water or whatever. Also also, there wouldn't need to be any Air Blocks at all in the game (as they currently only exist to apply a litle bit of drag to the Player), which should make things a little bit faster, and make several bits of code nicer (in fact, now I'm tempted to just remove them anyway...).
I'm fine with you splitting this up. Funnily enough, when I originally wrote this it was called "The Future?", before realising that I'd already done that one! :P
I'll change space over to being a jump key (as A/D are already in due to the game working with WASD), and make left-shift a gun scrolling key (as it seems like a good idea to have one, and my little finger rests on it when I try to control with A/D/Space). The rest of the keys seem the same already, except Escape quits while Return pauses. I kind of like having a quit button, and Escape is the natural choice. I suppose allowing the player to accidentaly quit out when trying to pause is bad, but it's also probably a bad idea from that point of view to even have a seppuku key.
How about seppuku and quit are made part of the menu? The buttons could then literally say "quit" and "restart level", which would make it obvious. That would also make it more obvious to the player what those actions do :-P. Would that be easy to do?
Should be. The save-and-quit button on the menu currently does just quit, and level restarting should be easy (it's been a while since I've looked at that, but I imagine it is). We do probably need to do some design for the menu, rather than just a faded screen with some big buttons on it.
I'd be fine with making water lethal. It would give a reason to use the ice-wand.
I think we should keep the quick-quit and seppuku buttons for dev builds, and take them out when we finish. They're confusing for people who aren't used to them, but they're really convenient for us.
I agree with water being lethal, especially seeing as you can't jump out of it easily and none of the puzzles are underwater. Also, the game segfaults if you freeze stuff while underwater. Maybe that needs a separate issue?
Do we want some sort of -dev
flag then? Or should I just write (and then comment out) pausing on Escape?
If water's lethal, then it shouldn't be a problem (I'll look into it anyway though). So are people happy with me removing Air Blocks then? The level editor may need tweaking if I do.
I think the seg-fault is just when you freeze stuff. It doesn't seem to matter if anything's in it.
I think just commenting it out is the best bet. Or leaving it completely for now.
When you say "the level editor may need tweaking", do you mean that air blocks in level files will cause a crash, or just that it's inefficient to include them when we don't need them? The puzzle-vs-mario debate hasn't been resolved, and may well lead to some changes in the kinds of level we want to build. If I'm going to modify or replace the level editor for that, I'd rather not change it twice.
I imagine it would just spit out a load of warnings saying Unrecognised code: ",,"
or whatever (which I could suppress for this specific case anyway), but otherwise should be fine (I'll have to see when I get to the code).
I don't get it. For the menu isn't it just a simple case of chaning the keybindings and how the Input::quit
function works?
I think if we're talking about having separate behaviour that's a result of development, then we should create a devel branch in git, which is a nice way of separating new features in the code from stuff that we know works.
Quitting, yes. Restarting the level will need a bit of change, as I don't think having the option on the menu to close the menu, and then die is what we want. It shouldn't be difficult to introduce a method to straight up restart the level (minus a life), but that is what'd have to be done.
If that works.... I'd rather avoid using anything more complicated than the basic commands if at all possible. Would branching mean that our pushes would still be applied to both branches? Would it really be easier than just commenting out the problematic code?
Branches are pretty easy as long as you keep track of which one you're working on. Just do git checkout -b <branch_name>
to create a new branch, then just push it as you would normally (i.e. git push origin <branch_name>
. Just, when you pull changes, make sure you pull from the correct branch into the correct one, otherwise you'll merge prematurely. You can check which branch you're on with git status
, and checkout the relevant branch with git checkout <branch_name>
. That's the only danger.
I was more coming at this from the philosophy that branches are a way of implementing new features in code, which is the general git philosophy. That way the working version of the game is kept intact and when developing you have something to refer back to if something goes wrong.
Hmm. Fair enough. I've just tended to refer back to the last push that I know worked if I've tweaked everything irrepairably.
Okay, I've fixed the segfault. It turned out I was trying to assign to a const char*
, so when the water accessed it to figure out what to turn into, it naturally segfaulted. It's just a char*
now, as makes much more sense.
Cool, thanks for figuring this out. Using a const char*
inside a union sounds like a recipe for undefined behaviour :-/
If I might make a suggestion... why not just use a std::string
and avoid the risk of memory leaks? Creating strings by dynamically allocating a char*
is soooo C and soooo 20th century :-P
We should try to make use of the C++11 standard library as much as possible to avoid reinventing the wheel.
Unsurprisingly, my first attempt (way back when) used an std::string
, but because a string is not a basic type, it's not allowed. That's why I went to a const char*
, my brain reasoning that "an std::string
is just a const char*
with extra structure, so they should be equivalent."
Sure dynamically allocating char*
's is C rather than C++, but unions are C rather than C++. I could easily just drop the union and everything would still work (maybe after a little bit of tweaking), but I believe it is slightly more efficient to have them tucked away like that (using less memory), and y'know, premature optimisation is the root of all good in the world, right? :P
Oh no! Don't get me started on C vs C++. Totally different languages :-P
After some reading unions do still have their use in C++ it seems, though not for this case. The C++ way of doing it would be to have setter/getter functions for the variables f, c and i, such that setting one unsets the other two. This is the philosophy behind classes and encapsulation. Otherwise we might as well just code in C, and I don't have the skill or strength to do that...
More importantly in this particular case, the huge benefit of using a string is that we avoid memory leaks and corruption.
Also, on the subject of memory usage. I was thinking about this the other day, and given that even most mobile devices these days have memory in excess of 256MB, I don't think we really need to worry about memory usage, since we're only making a small platform game.
Bleh. I suppose I shouldn't be risking memory leaks from manual construction/destruction for the sake of a minor bit of efficiency. I would however vote for just dropping the union rather than replacing it with some other structure. I used the union as a simple method of reducing the overhead, so would say that it's not worth adding all that much complexity to retain it.
Alternatively, I think I could just use a char[2]
, as the only value it takes is an array of two char
's, but it'll probably be nice to have std::string
flexibility in the long run.
Okay, I've removed the union and the Air Blocks, put Restart and Quit on the options menu, and made space be jump (and left shift be gun change). Currently, Restart doesn't do anything ('cause I still need to wrap my head around what the best way is short of just writing in a pretend "Restart Level" button into the inputs), and escape and backspace still cause the game to quit and you to die respectively, but escape does also technically pause the game.
...And now Restart works. It's still bound to backspace, but it skips all of the fading and just immediately drops you back to the level. I think this wraps up everything from this issue, except for the bits that have their own issues.
So... are you two still interested in this? Things have been quiet for a fair while now, and my willingness to continue wrestling with the physics engine is gradually diminishing, so I'm asking: What's the plan?
I think if we are to continue working on this, it'll probably be a good idea to sit down and come up with a proper design document (or at least, decide on a plan for what worlds, zones, obstacles, weapons, enemies, etc. to have). Even if we diverge from this plan (which I would highly expect), it's still better than just sitting here adding things that seem like cool ideas (which, while nice, will probably result in a pile of cool ideas rather than a cohesive game).
I do think it's about time we started (at least thinking about) trying to add content, and I'm not just saying this because I want to do something other than bug-fixes. :P