Functional Pip-boy 3000 Mk IV from Fallout 4

There is some nice vector art I have already made in the artwork folder. I remade the Pip-Boy logo, gauges, and a few other things.
 

More GUI progress!
I now have animations working on the Raspberry Pi. I had to optimize a lot of the display calls to get the frame rate up from about 15fps to 30fps.
The Vault-Boy walking animation is only 8 frames, and runs at 8 FPS, getting that to work just right along with the scan line effect took quite a bit of time.

I figured out why the previous frames were jittery on the Pi. That is because when you parse a folder of files on windows it numbers 0 to 9. But on Linux is numbers 9 to 0. So the animations were playing backwards. But while trying to figure this out I ended up learning how to do time based animations anyways.

I also have a working boot screen now. This was quite a trick to get working, next I will add all the proper sounds to that.

I am slowly going through and trying to rip out anything hardcoded in, such as the special screen. I am then converting the code so that it pulls in from a dynamic table of values in a single python file. That way each screen can effectively work off the same template with items populated as needed.

Again, feel free to download the code of git hub and populate the radio station folders with music to have a Pip-Boy themed MP3 player.
 
Really impressive! I am currently also working on a RPi project with pygame and I still need to learn a lot. I will probably check your github code soon, to get some inspiration.
 
Markus The Pypboy code was modularized by someone else a while back and some areas were good but some others unoptimized. It took me quite a lot of time to even figure out what code was doing what.

So just to get you jump started:
The code uses a single "master" screen that it blits everything else onto. The other objects are either groups of sub-screens, sprites, or groups of sprites. The master screen allows for some persistent effects such as a background and the scanline effect to remain on regardless of the other screens.

The __init__ calls in the modules render the static objects, while the Render() commands are called once per frame. I use this to handle the animations based on the current time.

What is confusing is the core code is split between two different folder, perhaps by two different people. And some of the code (including mine) is a work in progress and not actually active.

The biggest headache I ran into was trying to get one piece of code to trigger something else. Because it is a lot of instanced object oriented code which I don't quite understand it is hard to get one script to trigger something else in another script.

For example the boot screen is actually three sub-modules that cycle one to the next. To change sub-modules you just press 1,2,3, etc... on the keyboard. In the end I had to use the event system in Pygame to simulate pressing the 1 key instead.

For some other functions I just alter a setting.py variable and have the other module check it at render to see if it changed.
 
Hey, this was easier than I thought. I just downloaded your github code onto my Kubuntu machine and (after installing xmltodict) it is running. After a few seconds, I figured out how to use the "F1", "F2", ... keys and the number keys to switch screens. The graphics (animations and scanlines) really look great. I'm just getting started with pygame and I do note (yet) understand everything that you just mentioned. But it will certainly help me to get there. Thanks a lot!
 
I decided not to distribute any of the audio files since the code is setup as a MIT license.

If you want the original in-game music then you can use the B.A.E. program to extract the files from the game, then the Yakitori Audio Converter to convert them back to MP3 files. The same can be done with the Old World Radio, or any other radio station mod.

I plan on adding the ability to support "album artwork" where if a radio folder has an image inside it will display it.
 
Bottlecap Mine.gif


More progress! Animated inventory screens!
This is actually using the same code as the SPECIAL screen, but that was the whole pont.

I hacked up the OBJ Viewer code for Pygame, and instead converted it into a animation generator.
Using NIFScope I extract a OBJ file from the game. This is easier said then done as many objects are modular and have half a dozen textures.
If is a modular object, such as the knife I combine the models in Meshmixer, and just render them without a texture.

Some objects load with mirrored textures too, and some are z-up and some are y-up. So I have to fiddle with variables on each model. It is a bit rough, but still saves me a ton of time.

The output is a series of images that I can drop into a folder and point my code at.
 
A small update: All of the SPECIAL and Perks graphics are SWF (Flash) animations in the game files. It is quite tedious to convert all 104 of the files over to a series of PNG images, especially if I ever decide to alter the size or color of the images.

So instead I added code that renders a SVG file directly in Python. I am using cairosvg which seems impossible to properly install on Windows. So I have switched to using the PyCharm IDE as it makes python virtualized, which makes the whole setup much easier.

Using a flash decompiler I can extract the SWF files to FLA and open them in Adobe Animate. From there I can re-scale the artwork to fit the image size, optimize the animation, and then export the animation to SVG frames ready for the GUI to read in. In the end it is one less processing step, and the graphics can be re-scaled to fit anywhere on the GUI.
 
Last edited:
Small update: Scrolling menus!

The old Pypboy code only supported 10 lines of on-screen menu items before it is just clipped them off. So you couldn't scroll through your radio stations or inventory.

It took a lot of time, but I figured out how to make menus that scroll up/down just as they do in-game. I even have the little arrows that indicate if the list continues up or down off screen. Since the on-screen list is a subset of the full list, it is still dynamic and can be expanded as much as you want and will still pull in animations and images. I also optimized some of my code which was unnecessarily splitting up the longer lists into sub-lists.
 
1627537000370.png


The code has been updated with a few more changes:

The inventory and data screens can now display either a paragraph or a table depending on the settings file.

Radio stations can be set to either ordered or random. Ordered stations work as you might expect. The End and Home keys are used to change songs. The stations also loop through their lists.

If the station is set to random, it not only picks a random song, but it also drops into a random point in that song, making it sound much more like tuning a radio broadcast. I still want to code it so that if you resume a station it drops in as if that station continued playing in the background.

The menu scrolling has also been fixed to work better at re-loading the proper radio station when the program starts.

The "Radio Off" station no longer plays a blank file over and over, but you still need "Silence.mp3" in that folder for now.
 
Last edited:
The code has been updated with a few more changes:

The inventory and data screens can now display either a paragraph or a table depending on the settings file.

Radio stations can be set to either ordered or random. Ordered stations as you might expect. The End and Home keys are used to change songs. The stations cab also loop through their lists.

If the station is set to random, it not only picks a random song, but it also drops into a random point in that song, making it sound much more like tuning a radio broadcast. I still want to code it so that if you resume a station it drops in as if that station continued playing in the background.

The menu scrolling has also been fixed to work better at re-loading the proper radio station when the program starts.

The "Radio Off" station no longer plays a blank file over and over, but you still need "Silence.mp3" in that folder for now.
I find it incredible, how you approach all these details! It really motivates me to dig deeper into pygame.
 

Virtual Radio Stations are now working!

It took me a lot of brain power to figure out how to get virtual live radio stations working the way I wanted. I probably tried a half dozen different methods before settling on what I have now.

First I parse all the MP3 files in a folder into a python deque list. (A basically a list that can be looped). So rather then trying to keep track of the index of the current song (Which breaks if the lists are different lengths), I instead just rotate the list so that the current song playing is index 0
If the metadata file calls for it, I can randomize the list at program load, or anytime if I want.

I then calculate the length of each song in the list, and the time since the program started. When you drop into a radio station it will drop into the correct song and time in that radio station based on time.

Even if you change the current radio station all the other stations will continue to virtually play in the background. The cool part is you can also change the song on the current station and it will continue "live" playback.

The tricky part comes when you jump into a station after listening to another after a few minutes. I have to figure out which song in the list is supposed to be playing based on the time that has past, then adjust the list of songs so that song is the current one, and then also jump into the proper spot in that song as if the station never stopped playing. This was by far the hardest feature to get working as the radio stations are all different lengths. Currently if you do drop into a station that is 10 minutes long, but 15 minutes have elapsed I just start the station over.

The code is updated on GIT hub, but as usual you have to drop in your own MP3s.
 

Another day, another feature added: Working waveform visualizations!

Again, I tried lots of different libraries to get something working. What cracked it was finding this code from prtx:

The code is currently un-optimized, so there is lag while the game loads and converts the entire MP3 to an array, and then dumps the samples I don't need for the visualization. Later I will create a sub-program that will perhaps build this all ahead of time and save it off to a file.

I had to get the frame rate, sample rate, scrolling rate etc... all in perfect sync to make it line up with the music playing. I also had to be able to drop into a different section of the waveform since you can drop into the middle of a song when you switch stations. I don't think I actually have this working perfectly over time, and may need to re-think the syncing.

There still some bugs to fix but I have to fix. For example Pygame won't load MP3s on Rasabian, so I will have to convert everything over to .OGG. Which means i have to find a new song length calculator since the one I was using only supports MP3s.
 
I added code that can generate the waveform data, and then save it off to a cached file. It takes a few seconds longer for the program to load, but then switching songs is instant. Right now you have to process the files on a PC, for some reason the Pi gives an too many indexes error when doing the same thing. But it loads the cached file just fine so I am not worrying about it for now.

You can force the program to rebuild the cache, or ignore if needed. It also automatically builds the cache if missing. All music files also need to be OGG format now.
 

I have added Google Maps to the map page. I use two different styles for the world and local map. The google maps is a simple image call and styling, but it updates very fast. I overlay the player arrow, eventually I will make the icon rotate and the coordinates update based on real world data. If you download the code, you will need your own google maps API key as mine is setup for just me.

There is also now a footer with dynamic data that can be updated depending on the screen. It was tricky to make it so the bar-graph could be either in the middle or on the right.

The radio page now loads the song artist and title into the footer, along with the waveform data.
 
I was able to optimize the code so that caching is no needed at all. First off the waveform generator runs as a separate thread so it won't block the music playback. Then I used a different array flattening method that means the waveform is generated in a faction of a second even on the Raspberry Pi.

The waveform is also kept in perfect sync by comparing the converting the song playback time to the proportional position in the waveform.

Finally I added some variable to the settings file that allows you to customized the waveform display a bit, such as the framerate or zoom of the waveform
 
1628379189124.png


More progress!

I now have a working terminal lock screen! A very special thanks for MrVolt. I don't think I could have wrapped my head around the code to get this made myself.

He wrote the code for a terminal project you can see here:

His code is here:

Check out his insane GlaDOS build: Portal 2 Animatronic GLaDOS

I had to edit a lot of the code to work with PyGame, but once it was all put together it works just like in the game. This will work great for a secured Holotape, or as a lock screen of sorts. Currently if you pass, it takes you to the boot screen.

The code is using Pygcurse which I will be able to use to create other terminal based things, such as Holotape logs. The only glitch right now is the cursor doesn't blink even though Pygcurse code says they support that feature.
 

I now have Virtual Holotapes working!

The code for it is a bit of a mess, but it works. The holotapes are automatically parsed from a XML file and loaded into the menu. The holotapes work just like they do in game except for the audio tapes, for those I made a cool screen with the waveform visualizer. The Holotapes can have multiples pages, with audio mixed in. It is using the same Pygcurse library as the hacking screen, which allows for reading and writing text on the fly, so it can be expanded into other interfaces such as a settings screen.

I don't plan on making any of the holo-games. If someone wants to port the flash games over to Pygame then I could take a look. Someday I may try porting in a basic Pygame or Pygcurse based game like Snake or Tetris. The goal currently it get every in-game screen working, then start integrating it with external electronics.
 
I've got someone I could point to the matter of the games. What are things currently looking like for the physical housings? I have the "cover" portion for all the holotape games (still need to sort out the labels for the most recent three) and a couple of good ol' orange blanks. I have one of your extant chassis prints, to try out the coloring methods you demoed and check the fit with the covers. I hope whatever you end up with is compatible with those shells, as far as fit and screw holes.
 
Back
Top