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

Proposal: AGS 3.6 and beyond roadmap #762

Closed
sonneveld opened this issue May 10, 2019 · 14 comments
Closed

Proposal: AGS 3.6 and beyond roadmap #762

sonneveld opened this issue May 10, 2019 · 14 comments
Labels
ags3 related to ags3 (version with full backward compatibility) ags 4 related to the ags4 development context: project related to the project and its organization type: information for notification

Comments

@sonneveld
Copy link
Member

sonneveld commented May 10, 2019

Okay, summary: my hopes are that 3.6 is an actual minor release, only doing bug fixes and porting to SDL2 (which would require some update/rendering refactoring). 3.7 and beyond we look at how we refactor to make it easier for new people to add features but still keep compatibility. You might note that I've only been thinking about the backend and engine, not so much new features just yet.

My suggestions, just to start off the conversation:

3.6

  • Port engine to solely use SDL2 and OpenGL 3 for sound, events and graphics. edit: possibly with a very cut down allegro library for some software drawing and packfile loading.
  • Determine supported operating systems (perhaps Windows, Linux, Macos, Android and iOS, with the minimal version being the oldest still supported release) and support them via our budding CI system.
  • Use a slightly multi-threaded approach where timing and graphics are done in the main thread, and game loop is done in a separate thread (I have an experimental version in my sdl2 branch)
  • Investigate replacing video decoding with something like ffmpeg
  • Investigate using C++14 (it's a minor update over C++11 and gives us some nice tools like make_unique)
  • Investigate unicode support (probably utf8 with some conversion to utf16 for windows where necessary)
  • Try to reduce the number of build projects we have. I suggest retaining a single MSVS project and cmake for other systems where possible.
  • edit: to help with console ports, possibly move any code that reads config files, and searching into an desktop_entry point. Consoles would just accept a config struct prepared by their own entry method.

3.7
These are some ideas that I'd like myself or others to pursue, but not necessarily everything we could do (in no particular order):

  • Investigate refactoring to allow adding new features but still retain some backwards compatibility
  • Tidy up our game state and our use of 'externs' to read in global variables
  • Investigate reducing our nested namespaces to just a flat '::ags' namespace. Apparently nested namespaces are a bit hairy in c++, especially when you bring in other namespaces that share some of the same name.
  • Higher resolution fonts in low res games (for example, the platformer Celeste)
  • Launcher for mac/linux, to allow configuring files via a gui
  • Refactor audio system to support more channels.
  • Investigate other packing formats, like a simple zip, or just plain files, to allow easy patching (a library like physicsFS may help here)
  • Investigate tools like breakpad/crashpad for sending bug reports
  • Investigate auto-generating a lot of the script exports, possibly using c++ annotations, along with deprecation/versioning information
  • Investigate allow compiling a forward compatible engine that only supports non-deprecated features (using ifdefs or strategic linking to remove old support), possibly even only the script exports a game requires.
  • An in-engine or external tool for migrating game data to newer engine formats. (if in-engine, we could place in a temporary dir)
  • Replacing raw pointers with smart pointers for resources/cleanup
  • Porting editor to run on other systems?
@sonneveld
Copy link
Member Author

sonneveld commented May 10, 2019

I think having an in-engine migration might help with adding new features, sort of like database migrations. I don't know if it would work, but for each major version we could could add a 'migrate_to_version_3_6' mechanism. It would take data from, say load_game_3_5_or_older and migrate to 3.6. Older games might have to go through several migration steps.

We sort of have a similar process in place now, but it's done with fixups after the loading. That suggests the fixups always have to be updated if we change our internal structs. Instead, we would just have a simple 3_5 struct and a 3_6 struct, completely separate. Only the migration code would know how to map them. Then engine would only work with 3_6 structures. Then we could optionally compile out the migration and older structs for a forward compatible engine.

(note: I'm not suggesting we have multiple structs for all the versions that exist. Maybe just 3_5_and_legacy and 3_6 to begin with)

My experiences with keeping my sdl2 branch up to date with ags3 have suggested that if we keep separate ags3 and ags4 branches, it won't be long before it will be very difficult to port fixes across. I still care about supporting the hundreds of legacy games out there.

edit: To borrow an idea from cmake, they have an idea called policies which affects behavior, and newer versions enable more policies by default. We could possibly use this for deprecated behavior that needs to be passed on and can't be done just via struct mapping.

@sonneveld
Copy link
Member Author

One request: please be civil. I might hide comments that are rude and non-constructive.

@ghost
Copy link

ghost commented May 10, 2019

For the reference: old ags4 draft : #450

@i30817
Copy link

i30817 commented May 10, 2019

I'm a bit afraid of ambitions like 'become always multi-threaded' in a language like C++. I honestly wouldn't feel it's a good idea without the language being rust or something like that can statically verify against race conditions. There is a reason that mozilla invented rust before servo was done and why google bothered with Go, and that's because they had experience of how painful it would be otherwise in C++.

@ghost
Copy link

ghost commented May 10, 2019

Also, a note, I changed bunch of things in ags4 branch, cutting out restrictions imposed by legacy script API and plugin API to the internal engine structs layout, dropping support for plugin API that required exact backend like DirectDraw, and something else along these lines.
One could investigate commits made to ags4 in 2018 for the reference.

@sonneveld
Copy link
Member Author

I'm a bit afraid of ambitions like 'become always multi-threaded' in a language like C++.

ah, I didn't go into details but this is more like a coroutine, or just swapping execution between two threads. I wanted to have a traditional game loop with one spot where events, timing and rendering is done. The problem is that our game code can get recursive and have mini loops for gui, dialogs, etc.

All this does is run the game update loop in another thread, wait for a frame to be finished, then do the processing in the main thread. The engine just treats the game update code like an object with a "get frame" method. The separate thread allows us to return from a nested stack. Eventually we could untangle our nested update code and literally have a game object we call update on.

It was an experiment that seemed to work? /shrugs

@edmundito
Copy link
Contributor

@sonneveld Is this only a technical roadmap? Is there also a product roadmap as well?

@ericoporto
Copy link
Member

ericoporto commented Oct 1, 2019

@sonneveld I suggest the 3.6 be of a reduced scope where the goal is move towards using SDL in place of Allegro with the expected benefit of easier/better multiplatform support. About OpenGL, maybe a small improvement would be moving the GUI system to use it instead of software drawing. I understand this means still having this version with that cutdown version of allegro in place, but a goal to remove it eventually would be helpful.

@ivan-mogilko ivan-mogilko added context: project related to the project and its organization type: information for notification labels Oct 24, 2019
@ericoporto
Copy link
Member

Use a slightly multi-threaded approach where timing and graphics are done in the main thread, and game loop is done in a separate thread (I have an experimental version in my sdl2 branch)

I always wanted to know what that meant, I think I found how this was done.

https://github.com/sonneveld/ags/blob/938b9cefcde544bcc6872a57ad5a9448b753b9f1/Engine/main/simple_engine.cpp

I don't understand what that means still, would it be like you can set game fps and script tps (ticks per second)? Or they are still kept at the same frame-ticks equivalence?

I was looking at the perspective of running Zniw, a 85fps game, with a 60fps vsync and still hit the same timings as 85fps.


About the rest of this issue, I think we may either close it or edit it saying, information below is outdated and left as a reference for future developments or something.

@ivan-mogilko
Copy link
Contributor

ivan-mogilko commented May 4, 2023

I don't understand what that means still, would it be like you can set game fps and script tps (ticks per second)? Or they are still kept at the same frame-ticks equivalence?

The point is to have whole game logic run on a separate thread at its own fps, also known tps in some engines/games (ticks per second), while render and system events are done on the main thread using separate render fps. Basically, make game logical updates disconnected from the render times.

Your Zniw example is correct, but also slow games may benefit from higher speed render and smoother cursor movement.

In this case SetGameSpeed only applies to well, game speed, while render speed is player's/system's choice.

Overall this assumes that times of game update and render do not match, multiple game updates may happen between 2 renders if game runs faster; or multiple re-renders may happen between 2 game updates if game runs slower.

This assumes that there's a list of sprites, or "drawing operations" (as in sonneveld's example branch), kept at all times ready for the render, and it's only recreated at "sync points" in time. For example when both game is updated and we are going to render, or after each game update and kept ready for the next render, whenever it may take place.

There are various approaches to this; on one hand the "game update" may prepare this list of operations for a renderer to use whenever next update is complete. On another hand, the main thread may request game to do this whenever it needs to. (So it's a choice between taking something if it's ready or requesting something)

One thing that I just realized is that after this separation there will no longer be any game logic explicitly run "after draw", as it is coded now. All the logic will be updated at once, and whether any draw occur or not - will become irrelevant. Idk if that will lead to any compatibility issues with old games.

Unfortunately this was never documented as its own task in this tracker, but it may be. The task is briefly mentioned in the ags4 milestone ticket #1298.

I think @sonneveld 's work may be a good reference for both threading and "SceneGraph" interface/implementation.
OTOH, the SDL2 also uses a similar concept of draw operations in its renderer, where "draw operation" may be not only drawing a texture, but drawing a arbitrary quad, or applying effect, and so on. This is simply for reference.

EDIT: it's not immediately clear whether #1349 must be done before this, or would simply make it easier. It's possible that it's not obligatory, except the engine will not call renderer directly from within these multiple update loops.

@ivan-mogilko
Copy link
Contributor

ivan-mogilko commented May 4, 2023

About the rest of this issue, I think we may either close it or edit it saying, information below is outdated and left as a reference for future developments or something.

Yes, the development went a different way. This plan assumed that it will be kept in 3.* branch with full compatibility, and serious effort would be put into developing an easier "legacy feature support" and "migration" systems. While we did SDL2 and unicode in 3.*, more effort is put into the stripped ags4 now.

Still, refactoring the engine and separating it into parts with only minimal connections might make it possible to return legacy support in a form of custom engine build, for instance, where the main engine code would only have some sort of "linkage points" to plug in legacy support. Migration tools do not have to be a part of the core team project either, all this may be done separately.

EDIT: I wanted to reread older "plan" tickets and update/close/recreate these depending on how they refer to the current situation.

@ericoporto
Copy link
Member

Your Zniw example is correct, but also slow games may benefit from higher speed render and smoother cursor movement.

So, about the slow games, I don't think they will, because afaict the logic is ran in the script "engine", as an example, because tweens exist in script code (the tween module), this would actually make things less smooth. The mouse cursor I think it's either better solved by the OS Cursors (#1686), or some way to have things update at different fpss - so the mouse cursor could be updated at monitor speed, and the rest at a different one.

@ivan-mogilko
Copy link
Contributor

ivan-mogilko commented May 4, 2023

The mouse cursor I think it's either better solved by the OS Cursors (#1686), or some way to have things update at different fpss - so the mouse cursor could be updated at monitor speed, and the rest at a different one.

That is what I meant: update the cursor position at render frequency.

@ivan-mogilko
Copy link
Contributor

ivan-mogilko commented Jun 5, 2023

Closing this as outdated, but giving a small recap.

  1. 3.6.0 turned out to be a major updated, instead of SDL2-only update. Besides porting to SDL2 it also featured new audio subsystem, and full Unicode support (actually, mixed ASCII/Unicode support).
  2. ScummVM finally got a AGS port, which in a way delegates our responsibilities for maintaining old games, at least partially.
  3. AGS 4, an experimental branch with cut legacy features, had been developed more, and received few major additions, which make it actually interesting to work in. The first 4.0 alpha release for public test made recently.

Following distinct ideas from above list may still be useful, and should receive respective feature tickets at some point:

There's also a plan draft for the major engine refactor started here:
https://github.com/adventuregamestudio/ags/wiki/AGS-4-Draft:-major-engine-refactor

@ivan-mogilko ivan-mogilko added ags 4 related to the ags4 development ags3 related to ags3 (version with full backward compatibility) and removed ags3-next labels Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ags3 related to ags3 (version with full backward compatibility) ags 4 related to the ags4 development context: project related to the project and its organization type: information for notification
Projects
None yet
Development

No branches or pull requests

5 participants