Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewriting the game from scratch (at least in large parts) #534

Closed
Quintus opened this issue Mar 26, 2016 · 95 comments
Closed

Rewriting the game from scratch (at least in large parts) #534

Quintus opened this issue Mar 26, 2016 · 95 comments

Comments

@Quintus
Copy link
Member

Quintus commented Mar 26, 2016

Hi everyone,

when working on the SFML port and now on the CEGUI 0.8 port, I have come over numerous problems of the code in terms of

  • Bad code design (no private or protected, for example — violations of the secrecy principle everywhere!)
  • Bad variable naming (numerous member variables have no prefix; variable names are often nondescriptive or even misleading)
  • No documentation (the comments often only repeat what the code says anywhere, and do not contain any reasoning or usage documentation; exceptions are the comments that we as the TSC team added to our legacy codebase)
  • No use of exceptions, except where we introduced it slightly
  • No use of references, except where we introduced it silghtly
  • No use of modern C++(11) in general. The legacy codebase is, except for parts we modified, in the state of C++ 10 years ago.
  • The menu system is a mess.
  • Global variables everywhere! (and of course not obviously named as global variables)

I am sure the list can be continued. I therefore make the suggestion the rewrite large parts of the game from scratch. The code for the enemies can most likely be kept in large places, but everything else is up for new. As we have more or less discussed redoing many parts of the game in our cycle anyway, I think we should be honest and think about whether starting from a blank slate and with a clean architecture is going to give us less work then trying to fit our ideas of good code architecture into the legacy code base we have. For instance, we have discussed:

  • Scene architecture. This will cause a rewrite of a very large part of the codebase.
  • Physics systems.
  • Lighting systems.
  • Upgrading OpenGL.
  • Energy system.
  • Game mechanics.
  • Numerous issues tagged with "legacy code" on this tracker.

If all of these will be implemented, this will be a rewrite of most of TSC anyway. So we can also just start from scratch. Of, course graphics, music, etc would be kept! There is no need to remove that!

I do not mean to start this right now. I will complete the CEGUI 0.8 porting, and we will see a number of releases of the 2.x series. I suggest to consider the rewrite for a 3.x series.

A rewrite will allow us to architect the codebase the way we want it to have, without having to worry about how to fit things into this mess we have inherited. We can completely redo our dependency list, and we will be able to go easier make the changes listed above. Instead of a step-by-step upgrade causing bugs and misbehaviours of the rest of the legacy we have, we can directly do it correctly. As a side effect, we could rethink legal aspects of the codebase if we don’t have any lines left from original SMC. That however is stuff for a new issue in case we decide to go for the rewrite. Even more, if anyone here feels unsatisfied with C++, we could consider a different programming language. Let me however make clear that I am very reluctant to that as I’m pretty happy with C++.

If we get time, I’d like to discuss this a little in the upcoming General Discussion, but I repeat that this is a midterm proposal and nothing for the next release or even the next number of releases. It is not in a votable state. It is an open discussion that we should have here.

This ticket is mainly targetted at the programmers involved into TSC. @Luiji, @brianvanderburg2, @lambda-11235, @datahead8888, what do you think of this? I am sure everyone of you has stood before the legacy code and thought more than once “what a mess it is!”. In my opinion, trying to reform the large legacy codebase with all its flaws is not worth it. Restarting is better and quicker.

Valete,
Quintus

@refi64
Copy link
Member

refi64 commented Mar 26, 2016

Yeah, I noticed the codebase's...uhh...quality...when porting the audio system to SFML.

@Quintus
Copy link
Member Author

Quintus commented Mar 26, 2016

@datahead8888
Copy link
Member

These are the suggestions/concerns I brought up in our IRC discussion:

  • We have already slowed feature development down while doing API upgrades and attempting a scene management system before. We need to keep some features rolling in a 2.X series while we start on the new 3.X series for the rewrite. This helps keep people coming back to our game.
  • If we have any interest in dual licensing or alternate licenses such as MIT/BSD, now is the time to discuss this before the rewrite starts.
    • As an example, I was looking at doing the lighting system privately so that others could not submit GPL'ed code to it while I work. I then was going to dually license it such that both TSC and my own game could use it. This is an example of a place where dual licenses might have benefit.
  • I would probably suggest having the rewrite be a continuation of our existing git history. This allows people who have racked up commits in GitHub to continue having these commits show. This can be useful for job hunting for people; employers are likely only to look at one Secret Chronicles game's commit count and not two different game repos.
  • We should probably have a discussion on design goals and then design a UML diagram together so that we can work with one another to build the best architecture we can.
  • We need to get started on making mechanics decisions for the 3.X series, since these affect both the rewrite of the physics system and what kinds of classes are needed in the architecture.

@sauer2 - changing game mechanics means changing levels -- we will be needing your input as we discuss mechanics changes.

@Quintus
Copy link
Member Author

Quintus commented Mar 26, 2016

I don’t want to clutter this issue with legal questions. Let’s focus on the technical side here, and discuss any legal stuff in #535.

@Quintus
Copy link
Member Author

Quintus commented Mar 26, 2016

I would probably suggest having the rewrite be a continuation of our existing git history. This allows people who have racked up commits in GitHub to continue having these commits show. This can be useful for job hunting for people; employers are likely only to look at one Secret Chronicles game's commit count and not two different game repos.

On this I agree and suggest to have the first commit in the 3.x branch be a rm -rf *. Anything we want to keep can be re-commited. This allows to retrieve the list of all authors involved in the "new" TSC easily with one Git command (important for legal issues).

We have already slowed feature development down while doing API upgrades and attempting a scene management system before. We need to keep some features rolling in a 2.X series while we start on the new 3.X series for the rewrite. This helps keep people coming back to our game.

To clarify: We will probably develop 2.x and 3.x in parallel, with focus shifting slowly from 2.x to 3.x.

Valete,
Quintus

@xet7
Copy link
Member

xet7 commented Mar 26, 2016

At IRC discussion, I chatted with @Quintus that it's good to blog about game parts rewrite process etc to our website news section, it shows that project is active.

@ghost
Copy link

ghost commented Mar 27, 2016

Good idea, if you actually have the time.

Just keep in mind that cache locality might matter for levels with 1k+ tiles and that many (even "modern") C++ features tend to harm code transparency and maintenance if used more than sparsely. I know this might sound harsh but I often can't help but get the feeling you aim for completely over-software-engineering.

Also - since I skimmed the log - I came across the suggestion to put more parts of the game logic into scripts.
Please don't.
I've been curious about interpreters - in particular embedded interpreters - for some years now and the universal, repeating story in every domain appears to be that people regret putting more code than really simple event handling into scripts.

@datahead8888 About game mechanics:
Is there already a possible change we need to discuss or is there need to discuss something on IRC before the meeting on 9th?

@datahead8888
Copy link
Member

I know this might sound harsh but I often can't help but get the feeling you aim for completely over-software-engineering.

Yes, some design patterns can overcomplicate the architecture, while others will make it more supportable for us. This is another reason to use UML diagrams in order to make up our minds what works well.

We at least want to clean up poor practices like use of global variables, use of internal CEGUI API's, hacky physics systems, etc.

Ive been curious about interpreters - in particular embedded interpreters - for some years now and the universal, repeating story in every domain appears to be that people regret putting more code than really simple event handling into scripts.

I was thinking something along the lines of allowing some game rules or initialization to be overridden with scripts, possibly. We aren't going to do this on a whim, so there should be plenty of chances to raise concerns.

Is there already a possible change we need to discuss or is there need to discuss something on IRC before the meeting on 9th?

Not yet - this was just an FYI that it's going to start being discussed more and more soon. You will probably want to keep an eye out. The meeting is going to discuss the life energy system and some associated questions like save states, lives, and dying in pits. Other mechanics discussions, like the jump distance for Alex or power up systems are probably going to start popping up in the tracker and/or mailing list.

@ghost
Copy link

ghost commented Mar 27, 2016

OK, thanks for clarification.
Well, guess we have to wait for the meeting.

Am 27.03.2016 um 04:20 schrieb Chris Jacobsen:

I know this might sound harsh but I often can't help but get the
feeling you aim for completely over-software-engineering.

Yes, some design patterns can overcomplicate the architecture, while
others will make it more supportable for us. This is another reason to
use UML diagrams in order to make up our minds what works well.

We at least want to clean up poor practices like use of global
variables, use of internal CEGUI API's, hacky physics systems, etc.

Ive been curious about interpreters - in particular embedded
interpreters - for some years now and the universal, repeating
story in every domain appears to be that people regret putting
more code than really simple event handling into scripts.

I was thinking something along the lines of allowing some game rules
or initialization to be overridden with scripts, possibly. We aren't
going to do this on a whim, so there should be plenty of chances to
raise concerns.

Is there already a possible change we need to discuss or is there
need to discuss something on IRC before the meeting on 9th?

Not yet - this was just an FYI that it's going to start being
discussed more and more soon. You will probably want to keep an eye
out. The meeting is going to discuss the life energy system and some
associated questions like save states, lives, and dying in pits. Other
mechanics discussions, like the jump distance for Alex or power up
systems are probably going to start popping up in the tracker and/or
mailing list.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#534 (comment)

@Quintus
Copy link
Member Author

Quintus commented Mar 27, 2016

many (even "modern") C++ features tend to harm code transparency and maintenance if used more than sparsely.

Yes, but the current state of the code base is awful. It is conglomerate of ad-hoc code changes with lots and lots of global variables and no public/protected/private scoping anywhere. I wasn’t meaning to now use C++11 lambdas at every possibility in case you fear that. I am aware that advanced code features must be used sparingly, otherwise the result hurts more than it helps. People using templates for no reason or using exceptions to terminate nested loops don’t do things correctly. Another thing I am particularlyly reluctant of is the auto keyword. I want to know my types. If I don’t want that, I use another programming language.

My top 1 goal is always a good code design that is easy to grasp and the result of logical thinking. I usually sacrifice performance for that goal as I find a bugfree slower program more useful than a buggy performant program. It is a question of maintenance work.

Also - since I skimmed the log - I came across the suggestion to put more parts of the game logic > into scripts.
Please don't.
I've been curious about interpreters - in particular embedded interpreters - for some years now and the universal, repeating story in every domain appears to be that people regret putting more code than really simple event handling into scripts.

I absolutely agree with you. I want the scripting facility to remain in-level scripting for level design purposes, not part of the game core. Or in other words: It should be possible to conditionally compile TSC without scripting enabled and it should still run (although of course levels won’t have scripting).

Yes, some design patterns can overcomplicate the architecture, while others will make it more supportable for us.

FurballSingletonDelegatorFactoryGeneratorFactory::produceFurball()... Oh wait, I thought we didn’t want to go Java.

Valete,
Quintus

@ghost
Copy link

ghost commented Mar 27, 2016

That's reasonable I guess. But one further question:

When you wrote

It should be possible to conditionally compile TSC without scripting
enabled and it should still run (although of course levels won’t have
scripting).

Do you expect those levels to be designed in a way that you can finish
them without scripting? Or at least the campaign levels?
That would prohibit quite a number of possibilities.

Also, whenever TSC is compiled without mruby it should probably show a
message about it. Maybe some banner text, similar to if you open a file
manager with administrator rights. Otherwise we might get complaints
"your levels are incomplete/your game is broken".

@Quintus
Copy link
Member Author

Quintus commented Mar 27, 2016

Do you expect those levels to be designed in a way that you can finish them without scripting? Or at least the campaign levels?

No, I didn’t mean that. It is more of a theoretical thought that should outline the level of integration into the game core. You are absolutely free and encouraged to make levels that require scripting! And of course, those will be included into the main campaign.

Also, whenever TSC is compiled without mruby it should probably show a message about it.

We can have that, but I have doubts anybody would compile it without mruby. As said, this was a theoretical thought.

Vale,
Quintus

@Bugsbane
Copy link
Member

I'm fine with whether the code is rewritten or not as long as it remains FLOSS. From my perspective, this is an issue for the coders, as you're the ones who'll need to deal with it, so whatever makes the coders happy and encourages future development, has my vote.

@brianvanderburg2
Copy link

I've always felt the code needed an overhaul. I can help out here and there, but sadly rather sparingly. Just so many other obligations, a job that consumes, driving and all, about 12 hours a day, etc.

@Bugsbane
Copy link
Member

We just have to be careful though... more than once I've seen a major rewrite of a foss project become so overwhelming that it demotivated the people involved and killed, or just about killed the project (eg. Kdenlive, which seems to have just about recovered, but not before going months without contributions or releases and having the project lead quit, although he eventually came back)

@Bugsbane
Copy link
Member

Admittedly, working on kludgy, buggy, hard to understand, peeved together code must also be demotivating, so I guess it's about finding a balance.

@brunonymous
Copy link

Please consider SDL2. SFML does not support Wayland. Wayland is more or less "the future" compared to X.

So if you look here you will see the supported SDL2 platforms:

  • Windows Win32
  • Windows WinRT ("Modern" application, Windows Mobile, etc.)
  • Linux - X11
  • GNU/Linux - Wayland (GNOME, KDE, Enlightenment, etc)
  • GNU/Linux - Mir (Ubuntu Unity)
  • OS X
  • iOS
  • Android

Current SFML supported platforms:

  • Windows Win32
  • GNU/Linux - X11
  • OS X
  • iOS (coming soon)
  • Android (coming soon)

@Quintus
Copy link
Member Author

Quintus commented Apr 10, 2016

Please consider SDL2. SFML does not support Wayland. Wayland is more or less "the future" compared to X.

The "future" is going to take some time still, and SFML is under active development. We have just (1 month ago) switched from SDL (1) to SFML and nearly all devs of the team found its API to be much nicer to code against than SDL’s, so it is very unlikely we switch back.

more than once I've seen a major rewrite of a foss project become so overwhelming that it demotivated the people involved and killed, or just about killed the project (eg.

I can understand this concern, but I think we can handle it. We are going to maintain 2.x for now while we start into a planning phase for 3.x first. I.e. we will not directly jump into coding tomorrow, but plan some of the architecture prior to doing so, which should allow for a more quick implementation (in theory).

The thing is, the current code’s quality is awful. Once simple does not want to work with it. Every time I touch it I feel highly motivated to restart from scratch instead, and would rather stop contributing to the old code base than not starting from scratch.

KDenlive is a project much more complex than our little game. While a game’s architecture in code is usually similar in most games, one can’t really say that from programs intended for production of things. If a few of us will support the rewrite, we can definitely do it. If it comes out during the planning phase that only me alone will ever commit a line of code, it is rather unlikely (but not impossible).

Valete,
Quintus

@datahead8888
Copy link
Member

We just have to be careful though... more than once I've seen a major rewrite of a foss project become so overwhelming that it demotivated the people involved and killed, or just about killed the project (eg. Kdenlive

We might do an approximate effort estimate after better determining requirements. We can't really do a time to completion estimate for certain, since this is volunteer and because we cannot be sure of people's availability. How much time people have actually is the greater issue.

Since we're essentially going to make a new game, anyways, it could be viewed as starting on a new game, albeit with the same name. It would be healthy, however, to compare the effort roughly between the two options of modifying the existing code base and starting a brand new one.

Please consider SDL2. SFML does not support Wayland. Wayland is more or less "the future" compared to X.

We can't just switch back and forth all time time, even for the rewrite. Quintus seems to have a valid point on the future.

@Quintus
Copy link
Member Author

Quintus commented Apr 11, 2016

@brunonymous I did you a favour and requested Wayland support in SFML, which is what you should have done instead of asking downstream projects to boycot it. SFML/SFML#1082

@Quintus
Copy link
Member Author

Quintus commented May 4, 2016

Time to get things up and running! We should first agree on a general architecture, rather than digging up random UML diagrams.

Let us start with a brainstorm phase. Could everybody please give his thoughts for what he would like the TSC code base to look like? We’ll later collect the best ideas and decide on a a design that will hopefully fulfill as much of them as possible.

There are no bad ideas in brainstorming. Bring forward everything you can think of, as long as it is related to the code architecture (so not things like "I think the graphics should look different").

Happy brainstorming,
Quintus

@refi64
Copy link
Member

refi64 commented May 4, 2016

Here's my initial thoughts (I've been trying to make an RPG in Pascal for fun, and I'm using a similar architecture):

We would have a class pertaining to a window. This window class would sort of be the over-arching class that manages the SFML window and draws objects onto it via a method void draw(sf::Drawable& obj);. It could also potentially manage things like sound and saving.

The window would contain a (smart) pointer to a "screen" object. This could be an ABC; the actual derived classes would be things like LoadingScreen, MainMenuScreen, WorldMapScreen, and LevelScreen. This would encapsulate the actual state of the game itself. When the window object picks up a key press, it passes it down to the actual screen via a virtual method, passing the window object. So the methods could be like virtual void handle_key_press(Window& w, SomeType key);.

Each screen would also have a method virtual void draw(Window& w);, which would draw the screen onto the window. The screen's drawing internals would go much like one would expect. Maybe there could be some kind of mixin-style class for managing gradual state, or things that change over a time period.

The LevelScreen would contain a Level object, corresponding to...a level. Just the map and enemy positions. When the LevelScreen is given a key press, it could use some sort of abstract interface with the level to determine how to move Alex around. The level screen would also manage the camera. I'm thinking the level's abstract interface could have methods for getting the Entity at a certain coordinate and such. The level, when initially constructed, could be maybe be passed some sort of object for managing the gradual state, maybe via callbacks.

That's the furthest my ideas have gotten, though.

@ghost
Copy link

ghost commented May 4, 2016

There are no bad ideas in brainstorming. Bring forward everything you can think of, as long as it is related to the code architecture (so not things like "I think the graphics should look different").

OK, here goes nothing:

You could implement object types that may appear in big numbers, like particles or static tiles as data oriented as feasible. SMC struck me as a little heavy on the CPU (that said, maybe also on the GPU side, but I think it became slower as the average level contained more and more tiles), more than it should. As a bonus, depending on how it's done it may be easier to bind mruby.

Maybe some LevelGeometry class could take care of drawing/handling the tiles in it, if that fits into @kirbyfan64 s schema.

Another aspect, but I'm not sure if it's related to architecture: It probably should be easier to add custom tiles if one makes third party levels. Maybe it could be solved similar the way C-Dogs SDL implements it:

  • a folder, including the level files
  • may include the overworld file(s) (given we have something like an overworld in tsc, I'm out of the loop in that regard)
  • may include a file that lists additional tiles and a subfolder img that contains the images

@Quintus
Copy link
Member Author

Quintus commented May 4, 2016

Here’s what I was imagining all the time when I talked about "the scene system". It is actually pretty close to kirbyfan’s suggestion. Forgive me the theatre terminology, I couldn’t resist it in the face of the term "scene system" and the discussed storylines.

There’s a Play singleton class that acts as the the one (! only one!) global object in our codebase. Any global information we need goes into this object and nowhere else. This singleton object has a stack of scenes, where the topmost scene is considered the active or "current" one, i.e. the one the player is playing at a moment. So, when the game starts, the first scene pushed onto the stack is the TitleMenu scene. The player then selects a world. This pushes a WorldScene onto the stack, making it the topmost and hence current scene. In the world, the player then selects a level. This pushes a LevelScene onto the stack., making it the current scene. The player plays the level, finishes it. When finishing the level, the topmost scene (the LevelScene) is popped from the stack and destroyed. Since the next scene below it is the WorldScene again (it wasn’t removed, it’s a stack!) the player automatically gets shown the WorldScene again as it’s now the topmost scene. When exiting the world, the WorldScene gets popped off the stack and then the topmost scene is the TitleMenu scene again. When the player then selects "exit" on the title sceen, the TitleMenu scene is also popped off -- leaving the stack empty. The game’s main loop will terminate when it detects an empty scene stack.

The nice thing is that for all of these scenes, we can have a base class Scene which comes with two methods:

class Scene
{
  // ...
  virtual void update();
  virtual void draw(sf::RenderWindow stage) const;
  // ...
};

Each scene class can built on these two methods, while the main loop only needs to know about these two. So when a LevelScene is on top of the scene stack, it’s update() and draw() methods will be called by the main loop automatically. A LevelScene then includes information from a specific level that it will display, including all actors in this level (Alex, the enemies, anything that moves). Even the scenery can be included in such a level scene, and the best thing is: The rest of the game (all other scenes) do not need to care about how the LevelScene manages its internals. So there’s room for the LevelScene containing for example a single object for the entire static scenery (this is from sauer2's suggestion). The TitleMenu doesn’t need to know this. Current TSC architecture passes global information around everywhere, which is scary...

Of course, this concept can be applied to anything that needs to be passed from the window system to the game, like keypresses as kirbyfan has suggested. The flow of information always goes this way:

(OS) -> sf::RenderWindow -> TSC::Play singleton -> Scene on top of the scene stack

This scene system has returning to previous scenes automatically built in by means of the stack. There’s no worrying about how to get the player back to the title scene after he entered a world or a level. Even more, if he uses the direct "enter level" functionality skipping the world layer, this system doesn’t have to do anything special. There will be simply no WorldScene in the stack, meaning that when the LevelScene gets popped off the stack the next active scene will be the TitleMenu scene. Likewise, an InGameMenu scene can simply be pushed onto the stack when the player presses the [ESC] key. As the current scene it will be the only one updated and drawn by the game’s main loop. When he exits the in-game menu, the InGameMenu scene gets popped off the stack, and, voilà, the next scene on top is the LevelScene with the level he just left.

The system is completely dynamic and agnostic of which scenes are on the stack. New scenes can be added without the need to edit any of the other scenes other than pushing it onto the stack somewhere. Want to add a credits scene? Write one and when finishing the last level, pop the level off the stack and instead push the Credits scene onto it. Result: After exiting the Credits scene the player returns to the TitleMenu scene. Want to add a Shop scene for in-level use? Write it and simply push it onto the stack when a certain item is queried in the level. When the ShopScene closes, it gets popped off the stack, and, again, what’s next on the top of the scene stack is the LevelScene again so the player is back at where he came from.

How does that sound?

Valete,
Quintus

@refi64
Copy link
Member

refi64 commented May 4, 2016

@Quintus The stack is a really neat idea! However, take the case of post-level cutscenes. Would the level push the cutscene "scene" onto the stack, even though the level is already technically complete, or would it somehow replace itself with the cutscene?

@Quintus
Copy link
Member Author

Quintus commented May 4, 2016

@kirbyfan64 I haven’t even thought about the cutscenes, but the term makes it obvious they should be a scene. I would implement a post-level cutscene the same way I suggested for the credits scene: Pop off the level scene from the stack and push the cut scene onto it. The active scene does not change the very moment when you push something new onto the stack, but only on the next iteration of the main loop when the top of the scene stack is inspected again. Doing things like this is thus fine:

void on_level_finish() // hypothetical method executed at end of level
{
  delete gp_play->pop_scene(); // Pop off the level scene
  gp_play->push_scene(new CutScene("cutscenefile");
  // Next iteration of main loop will encounter the CutScene instance on top of the stack
}

Vale,
Quintus

@refi64
Copy link
Member

refi64 commented Jul 16, 2016

Ok. Just curious. ;)

@Quintus
Copy link
Member Author

Quintus commented Jul 27, 2016

I just stumbled over this audio library: http://kcat.strangesoft.net/openal.html

If we go with GLFW, that would be one of the candidates for audio.

Vale,
Quintus

@Quintus
Copy link
Member Author

Quintus commented Jul 28, 2016

I would like to not include a "package" system as TSC currently has, but which is unfinished. This reason behind this is that I want the game to be recognised as "this is TSC", and graphics and multimedia makes up most of the recognised identity of a game -- and I think the functionality moves TSC too far into the direction of a general-purpose engine. Not using it will keep the asset loading code more simple.

Valete,
Quintus

@ghost
Copy link

ghost commented Jul 28, 2016

@Quintus Does that mean that there only will be no download manager of some kind or do you also want to skip loading custom assets from a campaign/world folder?

In case of #2, please keep the "world folders for overwold, levels and scripts" thing if possible, because all levels in one folders is a mess, IMHO...

@Quintus
Copy link
Member Author

Quintus commented Jul 28, 2016

Does that mean that there only will be no download manager of some kind or do you also want to skip loading custom assets from a campaign/world folder?

Neither. I was referring to the package system introduced by Brian, which as of now has not even a UI available. Custom assets and levels will of course be possible, but exchanging all of the core graphics as the package system currently allows should not be possible.

@datahead8888
Copy link
Member

datahead8888 commented Jul 29, 2016

This is going to bring us into multiple inheritance, I guess. This is not bad per se, but it needs to be handled with care. Would it look like this?

class Furball: public Enemy, public Behaviours::Movable
{
...
}

This is one solution. Another solution would be to have both a Player class and separately contained Behavior class. The Player class could then return a pointer to the Behavior class, based on a requested id or similar means.

Networked multiplayer can also be played with two instances of the game on the same computer, thus networked multiplayer always includes local multiplayer.

For networked multiplayer over the general Internet, lag must be dealt with, which has to be accounted for when deciding whether or not the physics systems are in sync, as I understand it. Thus any kind of multiplayer without lag is much easier to program. I have not researched this topic much at all, however.

You can't just drop two players into an existing level. It would defeat the design of the level. For multi-user, new levels are needed.

Yes, levels must be designated. Ideally we would probably have a different campaign for each player mode. It might be interesting to think how levels could be built to work both ways, but this would make them harder to test.

If you use the SFML graphics module (which is what SFML is all about, otherwise we could just use GLFW and some sound library) then you can't affect existing SFML objects with custom OpenGL as the entire lowlevel stuff is handled by SFML.

It is natural that this context resetting causes performance hits. Sticking to plain OpenGL completely will eliminate these, but then there is no point in using SFML other than the audio module

As with the choice of programming language, it is largely a question of what we enjoy working with and how much control we want. Performance is also a consideration, but it probably is not the deciding factor. Also keep in mind that SFML (last I checked) uses legacy OpenGL, which would be different than what we are using if we write a lot of modern OpenGL code with shaders (ideally using the latest version of GLSL). Of course, SFML is not the only library out there.

It should be possible to satisfy both positions by providing a script that assembles lose graphic files into sprite maps automatically based on some easy description file.

This could be a solution. We could make it optional to include sprite map files if artists want to (providing a link with information). It is a common practice. We accept patches from programmers who don't really want to use git, so we aren't being inconsistent.

I would like to not include a "package" system as TSC currently has, but which is unfinished.

If people want to swap all graphics, they can always fork the game like we did with FluXy's version. Also, you are correct that most people will not use packaging if it involves a lot of XML file writing and no GUI.

For substantially large levels, how much of a hit do you think XML-only reading will roughly take? If there is a noticeable loading time, I would say I think we need some sort of binary format available in release mode. Having an alternate XML format for debugging (maybe configurable) does make sense, however. I suppose benchmarks are better, though someone would have to find time to write one or find some samples on the Internet. Of course, if we find an API to handle both for us, this would be easiest.

More considerations:

  • I saw Quintus opened 4 tickets with the Cegui team recently. This isn't the first time we had issues. It doesn't seem to be supported well with crossbuilds (or Windows). We might discuss our API selection here a bit more.
  • Do we want to add automated unit tests? I kind of feel like it would be like corporate coding if I had to do these, especially if I had to fill them in when non team members didn't submit them. I do realize there are benefits to automated testing if it is leveraged well, though.
  • Would anyone else be interested in going through some game artificial intelligence tutorials? This is something I've been interested in pursuing, and there is a use for it in TSC. Perhaps we could start some "group study sessions" :)
    • OpenGL and C++ 11 would also make good group topics
  • Will we inherit the coding standards from the current codebase or rediscuss any of them?

@Quintus
Copy link
Member Author

Quintus commented Jul 29, 2016

Thus any kind of multiplayer without lag is much easier to program. I have not researched this topic much at all, however.

I still remain in the opinion that TSC is not a multiplayer game.

Performance is also a consideration, but it probably is not the deciding factor.

Yes, for me it's more about learning things, which is why I'm interested in GLFW. Performance however matters in so far as the game does not get unplayable. However, I'm not so much behind the GLFW idea that I would insist on it. After all, it's not only me who will write here (I hope -- if it will be only me, I will use whatever I find comfortable). kirbyfan and lambda already expressed they prefer SFML. However, as I said above, if we do not use SFML's graphics module, then I would definitely recommend against using SFML at all, because then we'd lose control with no gains and increase our dependency count unnecessaryly.

So, in summary, I'm fine with either SFML or GLFW.

saw Quintus opened 4 tickets with the Cegui team recently. This isn't the first time we had issues. It doesn't seem to be supported well with crossbuilds (or Windows)

To do the CEGUI devs justice, most (all?) of them are Windows-only developers. I do feel occasionally like I'm the CEGUI-on-Linux beta tester, though. However, they react pretty quickly on any bug tickets I file, which is very nice.

Do we want to add automated unit tests?

I don't think this fits an OSS game. To put it bluntly: Let it be buggy! We'll fix in later releases. It's more important to go forward and make it greater :-)

We're not a library, so we don't have to worry about people depending on our code (which is the prime reason for automated testing).

Would anyone else be interested in going through some game artificial intelligence tutorials?

Not at the moment. I have enough to do with learning OpenGL.

Will we inherit the coding standards from the current codebase or rediscuss any of them?

I would like to avoid this behemoth of a discussion and just continue using the standard we had. I do want to get rid of the c in front of class names, though.

Vale,
Quintus

@Quintus
Copy link
Member Author

Quintus commented Jul 29, 2016

For substantially large levels, how much of a hit do you think XML-only reading will roughly take?

Numbers! I have created a new branch xml-performance which only has one more commit than devel. If you run a TSC compiled from that branch it will print out on the standard output how long it took to parse the XML and create the level objects from it each time you load a level. Even more, if you compile it with -DBENCHMARK_RAW_LOADING=ON, then it will skip the creation of level objects, giving you the raw XML handling overhead. This results in an empty level then, obviously :-)

Note that object creation is subject to the performance problem described in #550, so be careful before drawing conclusions from the large difference in time.

Also note that on startup it will print the benchmark info for the menu level, just in case you're confused where that extra info comes from.

For lvl_1, I get 27.5204 seconds with object creation enabled and 0.206197 seconds without it. Feel free to post your results.

Valete,
Quintus

@ghost
Copy link

ghost commented Jul 31, 2016

@kirbyfan64 Now, that you, datahead and Quintus optimized most of the loading time away and there is even room by optimizing the XML format, is there still a point in using protobuffers?

@Luiji
Copy link
Member

Luiji commented Aug 4, 2016

This is a looooot of text that I'll have to run through over time, so I'll just leave this here for now.

We should probably have a discussion on design goals and then design a UML diagram together so that we can work with one another to build the best architecture we can.

AAAAAAH! UML!

@refi64
Copy link
Member

refi64 commented Aug 4, 2016

@Quintus
Copy link
Member Author

Quintus commented Aug 4, 2016

On Thu, Aug 04, 2016 at 08:58:26AM -0700, Luiji Maryo wrote:

We should probably have a discussion on design goals and then design
a UML diagram together so that we can work with one another to build
the best architecture we can.

AAAAAAH! UML!

We will gladly accept better suggestions I guess. Feel free to come up
with anything you find more appealing (I agree that UML sucks, but I
don't know if there's a real alternative when planning a project).

But great to see you take part in idea shaping :-)

Vale,
Quinuts

Blog: http://www.guelkerdev.de
PGP/GPG ID: F1D8799FBCC8BC4F

@default0
Copy link

Productivity should be a concern for the rewrite. The more productive the setup for working on it, the quicker it can get done.
Considering that C++ is pretty terrible at being productive (unsafe runtime, slow compile times, terrible error messages that take unnecessarily long to track down, ..., ..., full reference: http://yosefk.com/c++fqa/) I kind of think it may not be a good choice.
Picking a language close to it syntactically/semantically is a good idea though, simply because it'll be quite easy for everyone to pick up (there's D, there's C#, there's Java, there's like, tons more languages).

It should also be noted that from what I can gather it is unlikely to think that a rewrite can be done while keeping the main codebase activate. The manpower just doesn't exist.

@refi64
Copy link
Member

refi64 commented Aug 27, 2016

Considering that C++ is pretty terrible at being productive

With C++11, it's actually pretty decent:

  • Smart pointers help a lot with memory safety.
  • The error messages grow on your. Once you have experience with them, it isn't too bad.
  • ...yeah, the compile times still suck...but at least there's parallel compilation, and Clang's decently fast.

Also:

  • there's D

It's worth noting that GC's languages aren't too good at game development, since they make getting a consistent FPS tricky, with the exception of C# (since the GC is super-optimized).

  • there's C#

This would make the game hard to run on non-Windows systems. .NET Core and Mono are EXTREMELY large dependencies.

  • there's Java

You speak of productivity, and yet you mention Java. It's like talking about great-tasting food and then mentioning live squid. ;)

@default0
Copy link

default0 commented Aug 27, 2016

It's worth noting that in D you can easily avoid GC pauses by simply not using the GC. People used it for audio-plugins, which have even harsher requirements when it comes to GC-pauses (ie they can't happen at all). It's also been used in a AAA-Game - so if it wasn't a viable option I'm pretty sure they wouldn't have used it.

Regarding Java it's still more productive, because using a language in which you do not have to memorize to always correctly use "smart" pointers and like 50 different other idioms/rules to write decent code will still be more productive, even if there's lots of boiler-plate. Plus, there's people like me who simply don't feel motivated to contribute because they don't want to fight the (very pointlessly steep by comparison with other languages that can do the same) learning curve of C++.
I bashed my head a couple times at it, each time it came back hurting from idioms that just seem... dumb (not because they ARE dumb, but dumb that a language that is used in 2016 would require them) as well as messy 5-line+ error messages for the simplest kinds of problems. Refer to the FQA I linked earlier.
Actually, have one of those idioms that make me feel there is something deeply wrong with C++: http://c2.com/cgi/wiki?PimplIdiom
So essentially because encapsulation is broken we need to use this crappy workaround to actually get better encapsulation than what C++ would natively offer us using its access qualifiers. Wat.

It's further worth noting that getting a stable FPS is also tricky in non-GC languages. Making a game run smoothly when there's a lot going on simply is not an easy task and C++ won't make that magically easy (note how the release 2.0 hangs quite a bit each time you save and also takes its sweet time to load even small levels).
Further note that a game such as TSC won't generally be a performance-hungry beast. There's no crazy rendering going on, there's typically not that many entities on the screen, the physics calculations are going to be rather tame for the most part, etc.

@datahead8888
Copy link
Member

datahead8888 commented Aug 27, 2016

I still remain in the opinion that TSC is not a multiplayer game.

If we were to let the user choose one or the other, people could play it either way. Levels would be built for one mode or the other. The only other consideration with this is the amount of work in the code architecture for it, but the game architecture should not be heavily constrained to work only for one player anyways.

I don't think this fits an OSS game. To put it bluntly: Let it be buggy! We'll fix in later releases..

I don't want the game to be buggy; I just don't think unit tests are the answer. You also have to put a LOT of work into unit tests to start getting serious benefits from them.

I would like to avoid this behemoth of a discussion and just continue using the standard we had.

I don't think we should permanently use a standard that was sort of made in reaction to a discussion that didn't go well. It is good to revisit this every so many years. I would have just waited a while longer before suggesting we review this again, but then people would say that the standards are already in place in the rewrite (assuming we do the rewrite).

If you run a TSC compiled from that branch it will print out on the standard output how long it took to parse the XML and create the level objects from it each time you load a level.

This is better than nothing, but we would have to implement binary file loading in TSC and benchmark that in order to draw true comparisons. A simpler benchmarking would be to write a standalone app with a really large XML file and really large binary file and compare the numbers. We would then add anything else to the benchmark we deem necessary to simulate TSC's needs. It's a bit of work, though, which is why I was asking if you had a rough idea.

AAAAAAH! UML!

I suggested UML because it is known by many people and is useful for programmers in job interviews (experience). If you know of another standard, please suggest it, but I still think UML has some serious benefits.

default0 brought up a good point in IRC that using a managed language would reduce a lot of the work we do on builds, though developer preference is still a major factor in language choice. If we end up implementing AI algorithms or more serious physics logic eventually, C++ could pay off performance wise.

It's worth noting that GC's languages aren't too good at game development, since they make getting a consistent FPS tricky, with the exception of C# (since the GC is super-optimized).

In C# you can use object pooling to eliminate garbage collection delays (this is a standard practice in Unity games). It is a little bit of a hassle to have to do this, though not a big one.

Here are some suggestions for handling input:

  • It would simplify the architecture to have both Joystick and Keyboard input accessible through a common InputManager class of some sort. This class could either send events to other game classes or be queried for the state by them, depending on which way we want the communication to go. The Joystick and Keyboard could still be directly dealt with using their own classes behind the scenes.
  • The InputManager class could then be extended with additional sources of input down the line or accept "logical" sources -- either game recording playback or input from an AI system (maybe).
  • The joystick subsystem needs to work with multiple axes (an arbitrary number)
  • Ideally any type of game action should be configurable to work with either joystick buttons, keyboard input, a joystick axis, or any other form we support. Unity has a good example of how this can be done.
  • All input usage in the game should be coordinated through the InputManager, without bypassing it completely (as TSC does using direct SFML calls), unless there is a really good reason.

@datahead8888
Copy link
Member

I've had some hesitations recently about whether a rewrite is a good idea.

  • We've already spent a lot of time on the SDL -> SFML and Cegui upgrades and are still doing bug fixing and joystick implementation work for these upgrades. Features have mostly been put on hold.
  • Doing a rewrite may take 1-2 years before we have a reasonable feature set. As @default0 said, it is questionable if we have the manpower to support both the old and new applications at the same time.
  • People are currently a bit hesitant to create levels and/or implement code changes for fear they will be wiped out in the rewrite
  • We had discussed only demoing game rule and story changes in the new rewrite, but this, again, is probably two years away.
  • We still really need user base growth, and game features and levels play a major role in attracting people. We really need features because TSC currently lacks a lot of major features that spark interest (enemies with different behavior, collectibles, complex bosses, etc, etc).
  • I'm personally a bit hesitant to spend a lot of time on a rewrite if it's all copyleft code I can't reuse. A rewrite by definition means very high time being required, more so than modifying existing code. I do contribute to GPL'ed projects, but I normally keep my time spent within bounds and try to serve secondary purposes with gaining experience.

Of course, the code right now is a royal mess in some places. It's just a question of whether it will benefit the project more to attempt to clean it up incrementally or all at once. Likewise there is the question of what extent we will develop the old codebase in the interim if we push forward with the rewrite (we need to prototype ideas, but people are hesitant to write content that will be wiped out).

On another note, we really need to follow up on getting TSC into Linux distros if we want user base growth. We need to follow up with individual build maintainers and maybe even recruit people.

Yes, for me it's more about learning things, which is why I'm interested in GLFW.

I think there is nothing wrong with a project choosing to implement its own rendering system or other subsystems from scratch. Aside from offering a learning experience (and potentially offering more control in some cases), I view such work as a sort of art form. However, it is more urgent for us to get something working that lets the project keep moving forward. Thus, if we do the rewrite, my recommendation is to use a high level renderer such as SFML (except for special cases requiring OpenGL) for now and then consider rewriting the rendering system with something custom (GLFW/OpengL) later, after we get something running. We just need to remain open to this swap out later.

Thus I'm boiling things down to two points:

  • The features and levels need to keep rolling
  • We need to find a solution that encourages people in general to contribute

@refi64
Copy link
Member

refi64 commented Aug 27, 2016

I don't want the game to be buggy; I just don't think unit tests are the answer. You also have to put a LOT of work into unit tests to start getting serious benefits from them.

You accidentally replied to the wrong quote..

@datahead8888
Copy link
Member

Corrected.

@Quintus
Copy link
Member Author

Quintus commented Aug 28, 2016

As for the language choice, I am probably a bad measure since I actually enjoy coding in plain C. So I could even imagine doing the rewrite in C, but I'm pretty sure that I can't convince anybody else from this. Someone will certainly call this masorchism, but I like C for the same reason I like to run ArchLinux (or Gentoo) as my Linux distribution: I like to do things from the ground up. At some time I am going to test out Linux From Scratch just for fun. I am a person aiming for minimalism; anything I don't need will not be installed on my hard disk. If it weren't for a web browser and games like TSC, I wouldn't have installed X11 most likely as screen does work just fine on the virtual console.

I mention this only so you have a better sense of my position. Specifically regarding C# it is a hassle to use on Linux, with Mono being a huge dependency. I am a Linux-only user privately, so C# is certainly not an option for a game I only work on hobbywise. Java is likewise something large and I don't even have it installed. Most Linuxes don't have it installed, and in their repos they usually don't provide Oracle Java, but another implementation that is available under an open license that (as far as I understood it) is not 100% compatible with Oracle Java. On D I can't comment since I never even used it. Since I would like to stick to a mainstream language, this makes C++ a natural choice. I am interested in how Rust will develop, but the language is far too young for me and will stay so for several years to come. Finally, as Ruby fan, I would of course appreciate it if we chose to use Ruby as the language for TSC.

Lastly, I want to reiterate that TSC can be written in literally any serious programming language since it is not incredibly performance hungry. I thus don't see the point of arguing about the programming language at all from this side. In case of TSC it is just a matter of taste. We should probably just have each developer make a list of which programming langauges he likes or otherwise prefers and then decide on those that are most often mentioned.

I am sorry to say this, but the choice of programming language cannot be made under the argument of which language is easiest to pick up for contributors. The persons who work on the game most are the core developers, and it is their preference that must be honoured. If most core developers are unhapppy with the language, they will leave. The other way round there might be less casual contributors, but this is definitely preferable to not having core developers.

I just don't think unit tests are the answer. You also have to put a LOT of work into unit tests to start getting serious benefits from them.

Correct. I don't see Unit Tests for TSC either.

I've had some hesitations recently about whether a rewrite is a good idea.

Incrementally upgrading TSC to a modern architecture sums up into a rewrite anyway due to all its deficiencies. So better make developers happy instantaneously and do a new architecture from the ground up. Much more fun to code that than dealing with this legacy mess.

We still really need user base growth, and game features and levels play a major role in attracting people.

Specifically related to this argument, I want to postulate the inverse. I don't know about the other involved people, but I code on TSC because I like coding on it. I don't actually code on it under the premise that it attracts many users. That's how I would code on a commercial game since it is intended to make money, but not on my hobby project, whose main purpose is to make me as the person exercising this hobby happy. Sure, I am happy when I see a program I (co-)authored finds its users, but if not, it still was a nice experience. This is in my understanding the very essence of open-source software. Make something, see how people react. Not the other way around.

Valete,
Quintus

@datahead8888
Copy link
Member

Specifically related to this argument, I want to postulate the inverse. I don't know about the other involved people, but I code on TSC because I like coding on it. I don't actually code on it under the premise that it attracts many users.

I originally became involved in TSC (then SMC) with the hopes of helping it have a new release after five years. Upon forking the game, I hoped to at least reach the same level of use as the old SMC if not exceed it and approach that of Super Tux.

Getting more users leads to getting more contributors. Super Tux generally has a larger stream of people contributing to it over time for this reason. Having more contributors means a project can shoot further, as long as it is administered well. This is the main reason I have been interested in attracting more users.

So better make developers happy instantaneously and do a new architecture from the ground up.

The major pause in the project still concerns me, but you are the main person contributing to TSC (as shown in https://github.com/Secretchronicles/TSC/graphs/contributors). As you have repeatedly said, your leaving TSC will bring it to a halt. Thus it may actually be better just to let you decide, since you take the most responsibility in getting coding done. By contrast, I have always worked on things as I have time or interest.

So I could even imagine doing the rewrite in C,

My personal view is that object oriented languages offer a lot of advantages over C both in the ways you can architect your application and in the ease of standard libraries. Rust seems a bit new to me to base a long term game off of. C++ is more established.

@datahead8888
Copy link
Member

If we do the rewrite, we had suggested having separate source control repositories for the old and new architecture versions. My suggestion would be to do something like this:

  • TSC-Classic - Old architecture (2.X series)
  • TSC-New - New architecture (3.X series and higher versions)

Using a name such as TSC-Classic implies that we did something useful for all the work we have done and sounds better than TSC-Old, which implies our work is no longer interesting.

We would likely put most major new game features in the 3.X series and above, but we could look at both options. Leaving the 2.X series with SMC style rules makes it a "new SMC", though the old architecture might still be useful for prototyping new TSC game rules.

We could also do this if we want:

  • 2.X series - old architecture - SMC style rules
  • 3.X Series - old architecture - some new game rules we try prototyping
  • 4.X series - the new architecture - all new game rules

@Quintus
Copy link
Member Author

Quintus commented Oct 9, 2016

3.x as a prototype series? An interesting thought. I wouldn't be against it.

I'd like to get the ball rolling again, as we are currently seeing some kind of hiatus that resulted from my absence over my university work. Especially, it is obvious that I can't do it all alone. So while my motivation on working on TSC is probably different than datahead's, this does not mean that his or any other's motivation is inferior. I should probably not assume that my motivation is shared by other people in the same degree. As a result, making TSC more contributor-friendly should be a goal for the next series unless someone of the persons involved into this thread disagrees. I change my position in this regard, but in your decision than please consider that I am also one of the contributors the game wants to keep and/or attract.

With me alone coding 90% of the game there most likely will never be a TSC 3.x with all the new features discussed in this and other threads. I have neither the time nor the motivation to go through such obstacles; all I would do is keeping the status quo and maybe add minor new features. I want TSC 3.x to be a collaborative work of all of us, some more, some less contributing. Or to put it another way, if I look through the commit log of the last two months and there is not a single source-code commit not by me, this is depressing. It makes me lose motivation. If there's something in TSC itself that makes you hesitant to contribute, please bring it up. If it is something on my person that makes you refrain from contributing, please mention it. If it is a valid point, I will try to improve.

On the technical topic, we should now decide the language issue and start prototyping. I will now take a deep breath and encourage all of you to make the first design proposal on the code (ideally in a new ticket). Sketch some classes and their relations, ask if your idea is good. I will explicitely not make any such suggestion until somebody of you has made one. TSC should not be my personal pet project, the codebase is too large for that (and will be after a rewrite, likewise).

Valete,
Quintus

@datahead8888
Copy link
Member

What did you think of my idea (once the team starts serious releases in the 3.X rewrite series) of calling the old version of the game (with the classic game mechanics) "TSC Classic"? Aside from using this name in the repository, we also might consider using it in the title screen.

This:

  • Helps differentiate the old version of the game versus the new version
  • Encourages people to support / play the old version of the game still -- if we said "TSC Old" and "TSC", no one wants to touch the old version at all. If we say "TSC Classic" and "TSC", it evokes nostalgia, much like like people continue to play Super Mario Bros. today while also checking out newer releases like "The New Super Mario Bros."
  • Makes it easier for people who worked on the older project to cite experience, as it is a clearly named and valued project

We could also play the name game with the rewrite, calling it something like "The New TSC", "TSC Rebooted" or even "TSC Rewritten", though this would take more discussion. The name on the new game's title screen doesn't have to match the source control repository name, either.

@Quintus
Copy link
Member Author

Quintus commented Nov 16, 2016

On Tue, Nov 15, 2016 at 07:27:32PM -0800, Chris Jacobsen wrote:

What did you think of my idea (once the team starts serious releases
in the 3.X rewrite series) of calling the old version of the game
(with the classic game mechanics) "TSC Classic"? Aside from using
this name in the repository, we also might consider using it in the
title screen.

I like the idea. It draws a clear distinction between the two series.

We could also play the name game with the rewrite, calling it
something like "The New TSC", "TSC Rebooted" or even "TSC Rewritten",
though this would take more discussion. The name on the new game's
title screen doesn't have to match the source control repository name,
either.

On this I think we should simply continue using our current
name. Renaming one of two series should be enough to make the different
approaches clear.

Greetings
Marvin

Blog: http://www.guelkerdev.de
PGP/GPG ID: F1D8799FBCC8BC4F

@Quintus
Copy link
Member Author

Quintus commented Mar 31, 2018

So, I've started with the rewrite. It's using C++ and SFML, and uses nuklear as GUI toolkit. See https://github.com/Secretchronicles/TSC3. Thus I think I can close this.

@Quintus Quintus closed this as completed Mar 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants