On a way to implement space combat I have implemented conflict detection logic and unstubbed some parts of the game. Conflict detection is a mechanism for finding where and when space battle happens. Under the hood a fleet can have multiple waypoints and with advanced enough interstellar drive it can pass through multiple star systems in a same turn. If one of them happens to have an enemy presence, space battle happens and the fleet ends it's turn there. When the conflict begins is also important, it influences a turn limitation. If at the end of player's turn a fleet was 1 light year away from destination, traveled at the speed of 2 ly/turn and battle happened there then it would have 50% of maximum combat turns to resolve the fight. In case the battle doesn't end by then I plan to make persistent battles which can span multiple galaxy turns. I also thought about making a mechanism where a quick enough fleet can fight in multiple systems. For instance if a fleet finishes one battle quickly and is fast enough to travel to next star system it would be able to fight a few more turns there too. The problem is int that case conflicts wouldn't be isolated and players wouldn't be able to play each conflict to the end before moving on to the next one. It might work by making players play all space battles simultaneously, one turn at the time but that doesn't sound like fun. So I'll go with one battle per fleet per turn limitation and keep the idea in the drawer :). There is also a question of what to do with colony ships that retreated from the battle, do they try to reach a marked planet or do they go home and do what exactly? I'll cross that bridge when I come to it.
Next step toward space battles was making AI build ships so a player can have somebody to attack. In order to implement that I had to change how the game rotates players during the turn. So far I had a "current player" number and only one player could interact with a "game core" at the time. On the other hand AI was supposed to do it's work in the background. Since both AI and human player used the same means of communicating with the game core AI could only manipulate the empire of current human player so for a brief moment there was an AI which filled my building queues with random stuff :). To make AI independent I tossed the concept of the current player out of the core so from the it's perspective everybody is playing simultaneously and it is up to a user interface to worry about who has the turn. Interesting consequence of it is that Stareater is now very close to having hot-seat multiplayer.
Prikazani su postovi s oznakom implementation. Prikaži sve postove
Prikazani su postovi s oznakom implementation. Prikaži sve postove
nedjelja, 31. siječnja 2016.
utorak, 24. studenoga 2015.
Fleet movement
Next feature on the completed list was fleet movement. Well sort of completed because it was refactored while doing colonization (more about it next time) and there is an open question of how to propagate information about multiple missions to GUI.
Let me start from the beginning, in the last iteration of the project I made two collections for fleets, one for stationary and the other for moving fleets. Reasons were difference in data structure, moving ones have current, start and destination positions while stationary only have current position; in visualization, stationary fleet marker should appear next to the star instead in the center of it; and in some internal logic. In the current iteration I wanted to unify those two collections for easier handling and I did it by introducing the concept of fleet missions. I started by giving stationary fleets a "stationary" mission and moving fleets a "move" missions and while most parts got simpler, some were not in the best shape. With only two things fleet could do there was no need for spending more time on the topic.
That changed when implementation of colonization started. At first I started by making separate collection for colony ships but then I've realized it won't make stuff simpler. It worked well for colonizing within a star system but when it came to moving ships to remote stars I had to either duplicate the code of normal fleet movement or unify colonizers with regular fleets. Guess which path did I choose, more complicated one with better scalability. And on top of that I've pulled out visitor pattern. It was like climbing uphill a bit be rewarded with relaxing bike ride downhill. I've changed fleet data from having a single mission to having a list of missions which combined with visitor pattern led to simpler code, believe it or not. Missions themselves were changed, descriptor for "stationary" mission was removed, now fleets with empty mission list are considered stationary, "move" missions have reference to star lane they are using instead of starting star (which was used to deduce whether star lane was in use or not), "move" missions also have reference to only one destination instead of all waypoints (not yet implemented on GUI but planned for future) and "colonize" and "skip turn" missions were introduced. "Colonize" missions does what you'd expect, marks ships ready for landing and establishing a colony. "Skip turn" also does what the name says but the reason for introducing it was to prevent colony ships from having unfair advantage over normal ships by taking action on the same turn when they are built.
In the Stareater I aim for having strict rules about what happens when. Construction is an action that takes a whole turn so when a ship is built it should act as if it (or should I say "she", I find it weird to refer to ship as she, partly because it's inanimate genderless object and partly because in my first language and in German the ship is "he") has spent it's turn. Since colonies and stellarises (made up word for star system wide government) are processed before fleets and colony ships are built with non-empty list of missions, colony ship could colonize a planet within a system or move toward destination on the same turn it was built. Explicit "skip turn" mission was a way to prevent that.
Finishing fleet movement allowed for tackling more features. As you might have figured out colonization was next but it's worthy to mention that also brought me one step closer to implementing space combat. And I've decided to make it more interesting then it was in last iteration.
Let me start from the beginning, in the last iteration of the project I made two collections for fleets, one for stationary and the other for moving fleets. Reasons were difference in data structure, moving ones have current, start and destination positions while stationary only have current position; in visualization, stationary fleet marker should appear next to the star instead in the center of it; and in some internal logic. In the current iteration I wanted to unify those two collections for easier handling and I did it by introducing the concept of fleet missions. I started by giving stationary fleets a "stationary" mission and moving fleets a "move" missions and while most parts got simpler, some were not in the best shape. With only two things fleet could do there was no need for spending more time on the topic.
That changed when implementation of colonization started. At first I started by making separate collection for colony ships but then I've realized it won't make stuff simpler. It worked well for colonizing within a star system but when it came to moving ships to remote stars I had to either duplicate the code of normal fleet movement or unify colonizers with regular fleets. Guess which path did I choose, more complicated one with better scalability. And on top of that I've pulled out visitor pattern. It was like climbing uphill a bit be rewarded with relaxing bike ride downhill. I've changed fleet data from having a single mission to having a list of missions which combined with visitor pattern led to simpler code, believe it or not. Missions themselves were changed, descriptor for "stationary" mission was removed, now fleets with empty mission list are considered stationary, "move" missions have reference to star lane they are using instead of starting star (which was used to deduce whether star lane was in use or not), "move" missions also have reference to only one destination instead of all waypoints (not yet implemented on GUI but planned for future) and "colonize" and "skip turn" missions were introduced. "Colonize" missions does what you'd expect, marks ships ready for landing and establishing a colony. "Skip turn" also does what the name says but the reason for introducing it was to prevent colony ships from having unfair advantage over normal ships by taking action on the same turn when they are built.
In the Stareater I aim for having strict rules about what happens when. Construction is an action that takes a whole turn so when a ship is built it should act as if it (or should I say "she", I find it weird to refer to ship as she, partly because it's inanimate genderless object and partly because in my first language and in German the ship is "he") has spent it's turn. Since colonies and stellarises (made up word for star system wide government) are processed before fleets and colony ships are built with non-empty list of missions, colony ship could colonize a planet within a system or move toward destination on the same turn it was built. Explicit "skip turn" mission was a way to prevent that.
Finishing fleet movement allowed for tackling more features. As you might have figured out colonization was next but it's worthy to mention that also brought me one step closer to implementing space combat. And I've decided to make it more interesting then it was in last iteration.
srijeda, 12. ožujka 2014.
Ship designs
As promised I've started to work on ship design feature. First thing on "to do" list for the feature is a list of ship designs. Figure above is a mockup and figure below is how it looks now.
The list works and "info panel" (details about selected design ) will have to wait. Currently ship design data has very few attributes: name, size (hull type) and image. Once I implement the rest (weapons, mission equipment, special equipment, shields type, armor, reactor, engines, sensors and maybe something else that I can't remember right now), I'll implement info panel. As you can see there is a lot of different component types, it might take a while. On the other hand I have a template that I can reuse, hull type data so it might as well take 2-4 days. What really slows me down is designing GUI for making ship designs.
This is what I have for now. It's missing few stuff (interstellar drive on/off, short info about armor, mobility, sensors and cloaking) but that's no-brainer to add. What I can't decide is how to present equipment (both weapons/mission and special) selection. Previous version had a slider for dividing space between primary and secondary weapon/mission and I wanted to get rid of it this time. It didn't reflect the decision making process very well (player would think in equipment quantity rather in percent space occupied) and made certain complications for design update logic. So I was thinking about predefined ratio (let's say 2:1) or limiting ratio selection to only few options (let's say 2:1, 3:1, 4:1 and 5:1). I had more radical ideas such as allowing more than two types of weapons/missions with predefined ratio (let's say 1:2:4: ... : 2^n or simply 1:2:3: ... : n). I'm still not satisfied with any of it. Maybe in the end I'll do it MoO way, by letting player to enter desired quantity.
Edit:
Since it took me some time to write this post, mockup has been changed.
Now all elements are there and I think weapon/equipment list looks OK. Quantity manipulation controls are still work in progress but the basics are there. MoO 1 & 2 had simple +1 and -1 buttons which were not so elegant for adding dozens or hundreds pieces. I came up with few idea, one is to add or remove multiple pieces by "shift" clicking a button and the other is to allow player to type the number directly. On the mockup the "up" arrow button is supposed to open such window but now that I think of it I could as well place a text box beside "+" and "-" buttons. Another thing I'm not happy with is info at the top right. It's crammed and I've just noticed it doesn't show combat speed (mobility is currently evasion score).
Anyway I'll work on it some more and in parallel implement parts that are good (image and hull selection). And one more thing, predefined designs are essentially implemented. See the "Interceptor" on the second image? It's predefined design. Those designs are automatically added to design list as player acquires necessary technologies or at the beginning of the game it they have no requirements. I say essentially implemented because designs themselves are missing 80% components but as new components are added, predefined designs will get updated.
utorak, 11. veljače 2014.
Buildings
Along with implementing colony and star system details I have implemented buildings logic. First I'd like to make a difference between construction project and building. Industry points are invested to construction project which upon completion either produce a building or some other non-building effect (such as removing planets negative trait). This distinction simplifies ship construction that was hackish in previous version and allows cleaner implementation of terraforming.
Currently implemented construction projects are:
Next on the menu is ship design. Yay, finally!
Currently implemented construction projects are:
- Colonization - increases planet's population for a turn and produces no actual building (like housing and trade goods in Master of Orion II)
- Industrialization - produces workplaces for population, an actual buildings
Next on the menu is ship design. Yay, finally!
ponedjeljak, 2. prosinca 2013.
Silent fail and rage
I raged last Friday over a stupid designed choice Microsoft made for .Net framework. It all started with benign change, I changed folder where game settings were stored. When I tried to test the change the main window refused to close. I stabbed red "close window" button a couple more times but to no avail. It seamed as absurd as not being able to start a car because a house few street away has new door. So I paused the program through debugger and it turned out that "close window" event was being aborted for some reason. For those unfamiliar with MS Windows Forms, program can subscribe to "somebody requested to close the window" event. On such event the program is notified and can act upon it and even prevent closing. Stareater GUI code is subscribed to such event and naturally I checked it out:
A single line that saves settings. There is no code that cancels closing. With debugger tools I followed internals of SettingsWinforms.Get.Save() and it's execution wasn't as I expected. It was cut in a middle of execution. I spent some time trying why and it turned out there was an exception being thrown (sort of runtime error) inside Save. When a program doesn't handle an exception it usually crushes but proper programming tool catches it and presents plenty of information that helps programmer to fix it. Take a look at Visual Studio 2010:
It clearly says where the code broke and why. Other C# IDEs (programs for programming) also offer such good debugging tools so it's kind of expected that every exception will show on programmers radar. But no, Microsoft decided that in certain conditions window must not crush. If exception occurs in such situations, framework will catch it and "handle" it by not doing anything. That's called silent failure. This is how it looks like when it happens within "window is about to close" event:
Do you see it? I made similar divide by zero error like on previous image. Take some time. It's hidden in the last line in the "Output" window at the bottom. On top of that full message doesn't fit the window. Now I hope You can understand, dear reader, why I was furious.
Reasoning behind silent failure is usually that end user is see less crushes. In my opinion it's just giving the sense of false security for end user and as demonstrated makes job unnecessarily more difficult for programmer. There is absolutely no benefit from it in "debug mode".
And in the end, how did saving settings prevented window from closing? Destination folder didn't exist. Normally when non-existent file is open for writing it is automatically created. Apparently creating missing folders is completely different beast but it's OK as long as I get informed when my presumption turns to be wrong.
četvrtak, 24. listopada 2013.
Building queue
This is how system view looks like now. Not much different from before but under the hood it's not a place holder any more. "Construction site name" panel is aware of selected body. So far this awareness is manifested only as an icon of first building in the queue. I have some ideas of what to display in place of "Construction site name" label but I'm still working out technical details. Idea is to have different name format for different types of bodies. Rock planets would be the usual star name + roman numeral such as Alpha Centaury IV for 4th planet around Alpha Centaury. For asteroids it would be something like "Asteroid belt at Alpha Centaury III" and for gas giants "Moons of Alpha Centaury VI". In both cases I'll have to support a way of injecting a text (such as a star name) in the middle of localized text entry.
Next update will come later than usual. As I said, real life got me busy so during the month I did next to nothing for the project and I got little tired from the last month. Not in a way where I lacked sleep but in a way where I've started to add stuff without the proper planning. I don't know how to describe but that makes me feel tired, as if mentally exhausted.
On the bright side, I finally managed to learn how to draw simple stuff in Inkscape. Alhough it's not on the same level as Paint.NET, it's good enough for my needs and better then any vector graphics tool I'll ever make. I've already converted a few old ship images from raster (PNG) to vector (SVG) format.
subota, 19. siječnja 2013.
Map generation pipeline
New game form is almost complete, all that is left is map setup GUI. That would be trivial if it was simple "select size" drop down menu but I want to expand it a little, I want to add more options. By default map is square shaped and I want to add means for defining different shapes such round or spiral. Instead of hardcoding few shapes, I opted for plugin based system where each shape generator is a DLL file containing a class with certain interface. Actually a single DLL file can contain multiple map shapes but that's technical detail point is, map shapes are .Net code that is outside the main executable. That was the idea before I've started implementing new game GUI. Thing I realized yesterday is that code for positioning stars is short compared to the rest of the map generation code (assigning star types, populating stars with planets, ensuring balanced distribution of "good" and "bad" planets) and that I or modder would want to reuse that over multiple map shapes. That made think a little bit more, define the map generation pipeline and decide what would be moddable and how.
Looks simple and trivial and that is the power of documentation (that I can't stress more). In star positions phase, as mentioned positions for the stars are calculated but stars are not yet generated. In the next phase
star types and sizes are decided. There potentially could be more attributes such as space monster lairs or alien relics but at the moment they are not defined. In parallel to that phase can go the phase where "starlanes" (or wormholes) are distributed. Planet distribution phase and planet attributes phase may actually be single phase. Anyway those two phases fill star systems with planets and calculate attributes such as planet size or environmental conditions.
Potentially each phase on the flow chart can be made moddable but at the moment I don't see the need for that extreme. For now I'd group those five phases to two groups: star graph and planet generation.
Odd choice is putting star attribution to planet generation. The original idea was that star type directly influences distribution of planets (both positionwise and typewise) in the star system. Putting star positions and starlanes in the same bucket may reduce the code reuse a bit but it simplifies interfaces for plugin code. I don't know, may I could split them somehow without "void *" arguments and with the fewest presumptions.
Looks simple and trivial and that is the power of documentation (that I can't stress more). In star positions phase, as mentioned positions for the stars are calculated but stars are not yet generated. In the next phase
star types and sizes are decided. There potentially could be more attributes such as space monster lairs or alien relics but at the moment they are not defined. In parallel to that phase can go the phase where "starlanes" (or wormholes) are distributed. Planet distribution phase and planet attributes phase may actually be single phase. Anyway those two phases fill star systems with planets and calculate attributes such as planet size or environmental conditions.
Potentially each phase on the flow chart can be made moddable but at the moment I don't see the need for that extreme. For now I'd group those five phases to two groups: star graph and planet generation.
Odd choice is putting star attribution to planet generation. The original idea was that star type directly influences distribution of planets (both positionwise and typewise) in the star system. Putting star positions and starlanes in the same bucket may reduce the code reuse a bit but it simplifies interfaces for plugin code. I don't know, may I could split them somehow without "void *" arguments and with the fewest presumptions.
nedjelja, 7. listopada 2012.
Localization
I was going write about localization as I was implementing it but the lack of a free time prevented me form finishing the post before the implementation was completed. Now that it's finished and it's weekend with holiday on Monday, I finally have the time to write a few words about it.
I did some polishing on the IKON library, my pet project, to streamline the data loading logic in the Stareater. As I said in the previous post, application settings (language choice, GUI size, game settings) use IKSTON variant of IKON and language files use a custom variant.This is how a simple language file looks like:
If you remember from the previous post, each IKON value starts with a "sign", a character that defines it's format. First sign in the example is ":", a colon. That sign defines what I call a context, a named set of key-value entries, much like IKSTON compound value. Terminating character for contexts is "-", a minus. Context in the example is named FormMainMenu and contains entries for the game's main menu. Sign for other values in the example is "=" and represents the beginning of a single line text value. Text in those values is interpreted as a literal text with stripped leading and trailing white spaces. Other formats I'm planning to implement are for supporting multiline and variable texts. Both formats will be introduced after (re)implementing technologies and expression in data files.
There is one more thing to say about localization support, folder structure. All language data are stored in {Stareater}/language/ folder (where {Stareater} is thefolder where the Stareater is installed). Subfolders of that folder are named after the language code, so US English texts are located in {Stareater}/language/en-us/ and Croatian in {Stareater}/language/hr/. Also if the language is intended to be used as "default", suffix(default) is added to it's folder name. Default language is the language that is set initially and used as a fallback. If a certain translation is not found in the language selected by user, text from the default language will be used.
Now that first few bricks are laid, it's time for more game related work: "new game" screen, map generators and organizations. I finally decided what should be organizations used for (except cosmetics), they would provide bonus level for technologies. Bonus levels would affect benefits from that technology but would not increase research cost and requirements for upgrading technology effectively reducing the cost of developing that tech. Sound simple but don't expect it to be done by the end of a month :).
I did some polishing on the IKON library, my pet project, to streamline the data loading logic in the Stareater. As I said in the previous post, application settings (language choice, GUI size, game settings) use IKSTON variant of IKON and language files use a custom variant.This is how a simple language file looks like:
:FormMainMenuExcept the first and the last line, entries are key-value pairs. This is the simplest format that is and will be supported. It's easy to read and easy to edit. At least I thinks so, complaint in the comments if you don't think so :). I'm planning to add support form more complex formats along the way.
FormTitle = Main menu
Title = Stareater
NewGame = New game
Settings = Settings
Save = Save
Load = Load game
Quit = Quit
-
If you remember from the previous post, each IKON value starts with a "sign", a character that defines it's format. First sign in the example is ":", a colon. That sign defines what I call a context, a named set of key-value entries, much like IKSTON compound value. Terminating character for contexts is "-", a minus. Context in the example is named FormMainMenu and contains entries for the game's main menu. Sign for other values in the example is "=" and represents the beginning of a single line text value. Text in those values is interpreted as a literal text with stripped leading and trailing white spaces. Other formats I'm planning to implement are for supporting multiline and variable texts. Both formats will be introduced after (re)implementing technologies and expression in data files.
There is one more thing to say about localization support, folder structure. All language data are stored in {Stareater}/language/ folder (where {Stareater} is thefolder where the Stareater is installed). Subfolders of that folder are named after the language code, so US English texts are located in {Stareater}/language/en-us/ and Croatian in {Stareater}/language/hr/. Also if the language is intended to be used as "default", suffix(default) is added to it's folder name. Default language is the language that is set initially and used as a fallback. If a certain translation is not found in the language selected by user, text from the default language will be used.
Now that first few bricks are laid, it's time for more game related work: "new game" screen, map generators and organizations. I finally decided what should be organizations used for (except cosmetics), they would provide bonus level for technologies. Bonus levels would affect benefits from that technology but would not increase research cost and requirements for upgrading technology effectively reducing the cost of developing that tech. Sound simple but don't expect it to be done by the end of a month :).
Pretplati se na:
Postovi (Atom)