Pycraft, a 3D open-source open-world video game made in python with Pygame, Numpy and PyOpenGL.
This article, released at the start of every month will document what changes have been made to the project, what challenges we faced and how we overcame them and how and where you can install this project from. For anyone wondering, this is to accompany the Pycraft weekly updates released weekly on Friday on my twitter page (@pycraftdev on twitter: twitter.com/PycraftDev), under the #PycraftTJ. I am Tom Jebbo, the lead developer and graphics designer and I hope you enjoy both playing the game and reading this article!
First of all, I believe it right to start by discussing how this article will be laid out. We will begin by discussing the highlight features of the upcoming release, complete with a few code snippets, challenges and how we overcame them. Then the article will progress into the smaller features that will be less noticeable, but there in the final release of the update, which will be called QuickBits. Let's begin!
- Highlight Features
- Display Resizing and Full Screen Support
- Benchmark Mode
- The Credits GUI
- Walking and Game Sounds
- The Load Screen
- Final Words
- Links and Credits
Pycraft was originally set to a specific resolution, (1280x720). This makes it easier to program the game, as every visual feature needs to be given a coordinate to appear on screen (starting from the top left as 0,0). However, this presents a challenge where the game will appear far smaller than intended on larger displays, and in a modern world, displays can be far larger than 720p, so we decided we should allow the game to be resized to counter this, and as we were implementing this feature, we thought to ourselves; “Why not also add full screen support to the game?”. So, in addition to the display now resizing you can also press F11 in all the GUIs and menus in the game to resize the window to your display size. This poses a challenge as its alright to have the physical window itself resize, but that does not dictate the rest of the objects in the GUIs will do the same, so by getting the display size in all the game loops by using the syntax:
realWidth, realHeight = pygame.display.get_window_size()
We can then use maths to resize and move the objects in all the GUIs to match the resolution the game is changed to. We achieved this by using scale factors. Because the game was originally programmed in a set resolution, we can simply calculate the scale factor of the width and height of the display and displace everything by this accordingly, as seen below:
yScaleFact = realHeight/720
xScaleFact = realWidth/1280
Then it's a simple, if repetitive, task of applying this scale factor, in addition to other forms of scaling in some circumstances to get everything to dynamically change as the display resizes, which we can achieve by -upon creating the display- adding the pygame.RESIZE syntax. Although all this is relatively simple, there is a lot of GUIs to update and a lot of graphics to be scaled in order to achieve this, which takes up a lot of time. In addition to this, as mentioned below in QuickBits, all the relevant graphics -that haven't been removed- have also been scaled accordingly. In addition, there is another downside to the display resizing, the way the display is updated with the syntaxes: pygame.display.update() or pygame.display.flip() and the way windows handles graphics (starting by drawing from the top left to the top right and traveling downwards in that style, which is dictated by the “p” in the resolution (for example; 720p)) leads to some interesting results, which can be seen in this video here:
Also, in an attempt to prevent people from, either intentionally or accidentally changing the game size really small, the game will; if dragged to less than the original ratio of (1280x720) snap back to that as its the lowest display size the game currently supports.
The new update to the game, version 0.9 will include three new GUIs, Achievements, Character Customizer and Benchmark mode, however the first two will not be fully showcased in the upcoming update owing to there being little use for them as Pycraft 0.10, the intended update for the main game section to be overhauled hasn’t arrived yet, so achievements can’t be earned and there isn’t currently characters to be customised, however they will be updated after Pycraft 0.10 to add these new features, for now however drafts and ideas have been trialled for both GUIs.
Benchmark mode then, the one that has been focused on primarily of the three, is nearing completion, it includes a short file read and write test, before focusing on a rendering test at a series of frame rates, from 15 FPS to in excess of 400, starting with a simple blank screen test, before adding drawing elements and finally a short OpenGL test too, to give to an idea of the performance you will likely get using this game. The game is currently optimised for single core use so CPU frequency is preferred over core count, and the game is able to be run on really low-end hardware with slower storage fine. So, benchmark mode will give you an indication of the performance your device could get you (which will be a lot on most devices I’ll add), but is that all it does?
Nope! In addition to providing information to you, the user on the performance you are likely to get, it can also recommend which settings you use and also, in the future will be tied to the adaptive performance setting in the Settings GUI, which will prompt you to choose either visuals or performance and will dynamically change the settings of the game for you as you play to fit either profile. However, that’s for the future and won't be included in this upcoming update.
The credits GUI is also an area of the game this large update will affect, this GUI will be changed from the previous style, from Pycraft v0.8 and backwards to a new more modern style, this is a feature that is also in the middle of getting re-modelled so there are no nice photos I can share with you at current; however it will be a more in depth and up to date insight into the people, modules and resources that helped make this project happen, in addition to a more up-to-date changelog. The GUI will, as it did in Pycraft v0.8 automatically scroll upwards however the text will now scale properly with the display resize, and will include images of the branding of the companies that helped make this project happen, laid out in a more user friendly, visually appealing way.
The last few updates have included clicking sounds when pressing buttons or interacting with some elements of the display, however this update includes a minor change, expanding on this concept. In the main game GUI (which is the focus of v0.10) there is now footstep sounds for walking and sounds for landing after jumping, this is a small touch that makes the game sound more immersive, in addition the game can now randomly select a footstep sound from a variety of 6, adding a further depth of detail to the game.
The way sound is played and sampled is now different, in Pycraft v0.8, all sounds were loaded entirely into memory as the game loaded. Now sounds are simply sampled from the storage device when they are needed; through the syntax: pygame.mixer.music.load(soundFILE), and bits at a time, this makes it more memory efficient for those running on low memory machines. The sampled sounds are also now categorised into channels with Pygame’s; pygame.mixer.Channel(num) syntax, which means, unlike in previous versions, multiple sounds can be played at the same time as each other, creating a more seamless experience.
Pycraft’s load screen has, for a while appeared quite dated, with an old orange, grey and dark grey colour palate, however now the main load screen has been transformed. Instead of displaying an image with a loading bar and splash text, it now draws in each aspect of the screen which improves overall seamlessness with themes and colour changes.
In addition to this, the Long Load screens counterpart, the Short Load Screen has also been removed due to how fast the game loads the shorter load screen could cause issues with flashing colours which could be dangerous to some users so have now been discontinued.
Now we have covered a few of the highlight features, I think it's time to have a look at some of the 40+ smaller features this game update includes. It's time for QuickBits:
- Let's start by talking screenshots, originally in Pycraft v0.8 this was achieved through the following syntax:
myScreenshot = pyautogui.screenshot(region=((0, 0, width, height)))
This works alright for when the display is in full screen mode, where the image is simply the whole screen, however things get a fair bit more complicated when taking a screenshot of the display when it's in windowed mode, because the user may have dragged it around, so we have to use a much more complicated setup here. However, there is one unfortunate drawback, neither of these methods works when the GUI is not on the primary display.
Now let's discuss performance. Originally Pycraft v0.1, the first stable release of Pycraft was much slower, considerably so over later versions, as each update includes performance enhancements, these improved load times as well as the frame rate you could expect. Pycraft v0.9 is no exception to this rule; however some parts of the game just got a lot faster. Images can be loaded and stored in under half the time as before with the; .convert() syntax. Sound is sampled and not loaded completely, improving upon the game's memory usage. And finally, the start-up time of the game has been significantly reduced as before the game would check if all the resources the game needed where present before sending you to the relevant starting point, now the game does this, but only when you're starting up the game for the first time that day and when the game didn’t close correctly, as a way of safely checking file integrity.
The mouse is an important aspect of day-to-day computing, and now the mouse has been supported in game, in Microsoft’s Windows the mouse changes from a pointer to a hand when hovering other something clickable, the same is now also true for Pycraft. The mouse will change to a hand when hovering over clickable text, display the egg-timer or loading icon when parts of the game are loading and will also change to a crosshair in game!
Dynamic Performance, when the game is detected to be in a minimised mode it will automatically lower the maximum FPS the game can run at to 15, from whatever it was previously set to as well as pausing any sound that currently being played back. This is to improve battery life on battery powered devices and to also be less intrusive with sound playback and performance use when the game is minimised.
All the graphics in the game that occupy the whole screen are now getting updated by switching from loading images in Pygame to loading them in PIL (Pillow or Python Imaging Library), this does come at the downside of graphics loading speed, but introduces lazy loading into the game (only loading the graphics when they are needed and not immediately), this change has arrived as PIL introduces the ability to stretch and resize images, that need to fit the full display as the display is now no longer locked to its (1280x720p) resolution. Images that do not take up the full display, however are still loaded with the faster and improved Pygame loading.
When you're in the settings GUI and the games window height is between 720 and 760 pixels in height, some of the settings menu is not visible on the window, so a scroll bar has been added so you can now scroll through the settings when in this mode to see those settings, this doesn’t apply when the games display is large enough to fit the whole settings menu in.
The start menu, a GUI that shows when the game is starting for the first time, or when a crash has been detected and the game has attempted to repair its self has now also been updated, this now allows the animation to be smoother and also to prevent the operating system from thinking the application is not responding as has been seen in previous versions.
This one is a more minor feature, when multiple instances of the game are run in the (.exe) executable version, or when the game is running in a compiled state when they both try to modify game files it could lead to crashed or unexpected behaviour, so now when multiple instances of the game are running you have to close all the other instances of the game before you can start up the game again. In effect removing any unexpected behaviour this may cause.
A less noticeable detail now, but if you tried to run this game without the minimum necessary OpenGL drivers then a window will appear telling you that you can-not run the game without them, the earliest supported OpenGL driver version is v2.8. In later updates this will be expanded to also check the SDL Library and also minimum system requirements.
Finally a feature I’m quite proud of, should your game crash or data to be lost or modified in a way the game can no longer read its main storage file (this stores everything from the date the game was last run on, to if the game crashed on last run and the games previous window size) then the game crashes and will attempt to restart, should this in addition fail then a message appears, telling you the game has crashed in a dangerous way and that you could lose all your progress, then the game will attempt to save your data in a safer mode, should this fail the game wipes the file and starts you again, so you don’t have issues where files become corrupt in the compiled mode and you have to completely reinstall the game, loosing valuable saved data that might be still saved.
That’s all the QuickBits for this article, however there are a bunch more smaller features this update holds that won't be documented because they are much smaller features (like for example the delay before the settings description comes up for that relevant setting in the Settings GUI has been tweaked).
In this final section before we conclude I’d like to talk about the future. Pycraft is a long-term project and it will take a while before the game is finished, there will be many updates and tweaks to each of the GUIs as well as new highlight features. So far, the project looks to be planned out as follows:
Pycraft v0.8; The current Pycraft version.
Pycraft v0.9; This is the version documented in this article, the release date for this is roughly around the middle of September however this, as with all the updates I’ve released, will not be rushed and will be as bug free as I can make it, as well as to the highest quality I can get it.
Pycraft v0.10; This update is scheduled to be started in the middle of September, after the completion of Pycraft v0.9. This update will include changes to the Main Game GUI featuring Vertex Buffer Objects (VBOs), higher performance, better weather integration, more sounds for walking in the rain and snow, rain sounds, weather sounds (like wind), better fog, more realistic (and working) skyboxes, a day and night cycle, instancing and the possible introduction of grass, trees and shrubs, an ocean and collisions system (with sounds for walking on grass, paths and stone), further updates to the entire 3D map as well as updates to the inventory and map GUIs, this update will also hopefully include a HUD (Heads-up display) also. This update is big and as so will take some considerable time to complete, it's too early to tell if all the mentioned features there will be introduced in this update, and also to give a release date, however id estimate Christmas as a best-case scenario here.
Pycraft v0.11; This is a very long way off but this update will focus on updating settings (like a delay for the information about what each setting does, with relevant information) as well as the character customizer and achievement menus that where first designed and introduced in this update, Pycraft v0.9.
Anything beyond that is too far away to tell yet, and please note that some of the mentioned features there will not be added if a suitable and clean way to implement them can be found, however I’ll do my very best to implement as many of them as I can.
Yes, you've made it, thank you for reading it's really appreciated. A lot of time and effort goes into creating these updates and writing articles like this, over 40 hours of research, engineering, prototyping, art and resource design, implementation, bug fixes and fine tuning goes into each of the “Highlight” features of these updates as well as a considerable amount of time behind the scenes with the smaller “QuickBits” to add to the update. In addition to all this I keep the GitHub page up to date (Which can be found here: PycraftDeveloper/Pycraft) as well as keeping everyone informed on twitter (@pycraftdev on twitter: twitter.com/PycraftDev), under the #PycraftTJ.
Finally, I’d like to thank you all for reading, so much effort goes into all this, and this is my first attempt at an article like this so please bear with me as I learn and take the feedback (which would be much appreciated).
With thanks to:
Pygame (www.pygame.org), Numpy (www.numpy.org), Pillow (PIL) (www.python-pillow.org), Python (www.python.org), Tkinter, PyAutoGUI (https://github.com/asweigart/pyautogui), psutil (https://github.com/giampaolo/psutil), GitHub (www.github.com), PyOpenGL (PyOpenGL — The Python OpenGL Binding: https://github.com/mcfletch/pyopengl), OpenGL (www.opengl.org), YouTube, Windows, Visual Studio Code (code.visualstudio.com), Microsoft and My amazing Twitter followers and community.
Please note links under the “With thanks to” are not moderated by me, they are safe links at the time of writing however I do not control the content on them.