by Blender Dumbass
Aka: J.Y. Amihud. A Jewish by blood, multifaceted artist with experience in film-making, visual effects, programming, game development, music and more. A philosopher at heart. An activist for freedom and privacy. Anti-Paternalist. A user of Libre Software. Speaking at least 3 human languages. The writer and director of the 2023 film "Moria's Race" and the lead developer of it's game sequel "Dani's Race".
A few days ago I had told you that I'm stopping with making the police station in my game
Dani's Race because it had a
Spaghetti Code Problem. The
main() function in the
Main_Update.py file was 1683 lines of code long and contained way too many things in it. At the moment, the same function is down to 641 lines of code. This is still way too much stuff in the
main() but this is a hell of a lot of reduction.
Racing Code
After the article I worked on cleaning the
main() function by myself and documented some of it on
Dani's Race Matrix Chatroom. This is when I moved pretty much the majority of the racing code out of
main() and into
Racing.py.
I did not simply dumped the code from
main() into an equally stupid spaghetti code thing in Racing.py. Instead I've broken it up into 13 individual functions, which are now useful to do various interesting things that weren't possible before.
There is a point in the first story mission where
Moria sits into a car you bring her and goes on practicing the racetrack. To do this in the
Script.py I had to manually fool the system to think that Moria is now a part of the race.
if Story["Moria"].get("driving"):
racepos = [-61.7856, 1028, 0]
if Story["Moria"]["driving"].getDistanceTo(racepos) > 2 and "Moria-Practicing" not in Story:
Story["Moria"]["driving"]["npc"] = "story"
Story["Moria"]["driving"]["target"] = racepos
Vehicle.TargetedNPC(Story["Moria"]["driving"])
elif "Moria-Practicing" not in Story:
Story["Moria"]["driving"]["race"] = "RacetrackRace"
Story["Moria"]["driving"]["npc"] = "racer"
Story["Moria"]["driving"]["racing"] = True
Story["Moria-Practicing"] = True
But now I have a specific function
StartRace() which can start any race even without Dani being a part of it.
def StartRace(racename, dani=None):
race = Races()[racename]
race["started"] = True
race["start-time"] = bge.logic.getRealTime()
for starter in race["starters"]:
if starter["cylinder"]:
DeleteCylinder(starter, ignoreTimer=True)
for racer in race["racers"]:
racer["racing"] = True
racer["launchtime"] = 100
racer["race"] = racename
racer["npc"] = "racer"
racer["active"] = False
racer["beam"] = Reuse.Create("Racer.Indicator")
if dani:
dani["race"] = racename
dani["checkpoint"] = 0
dani["lap"] = 0
scene = bge.logic.getCurrentScene()
pointer = scene.objects["PointingArrow"]
posindicator = scene.objects["Dani_Pos_Indicator"]
timeindicator = scene.objects["Dani_Time_Indicator"]
lapindicator = scene.objects["Dani_Lap_Indicator"]
posindicator.visible = True
pointer.visible = True
timeindicator.visible = True
lapindicator.visible = True
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"])
This theoretically gives me an ability ( with a minor modification ) to make racing in the city happen in the background. Like once every so often you would be able to stumble upon street racers doing their racing by themselves. Which sounds like it could be a lot of fun and could give the game a bit more life.
In the same time making the functions smaller gave me an ability to look at them more carefully and it made me fix two long lasting bugs:
Bug #26 and
Bug #29.
The thing causing both of those bugs was a rather sloppy implementation of the car's spawning. For example, you may drive pass a racing event, for which the race driver cars would spawn. And then you may continue a little bit further, making one of the cars de-spawn and re-spawn again as a car on the road, which is no longer a race car, but which still was recorded in the metadata of the race as a race car in the race. Which you can probably guess did some problems.
Also if a car spawned for the race it would not spawn ever again, for some reason, if you go further from the race. Forcing you to restart the game if you want to play the same race twice.
One friend of mine was playing the story mode and one mission required going to a race. But he chose to pass through the race starting zone when going through the previous part in the story. The cars spawned and then when the story needed it to be a race, refused to spawn again, making everything break. So cleaning the
main() actually helped the game be a bit less buggy, since I saw all those mistakes and fixed them along the way.
Here is a recording of
my PeerTube livestream where I finished moving the code of the racing. And where I discovered and fixed some of the bugs.
By the way,
subscribing to the RSS of this website will not only give you new articles, but also notify you when I am streaming on PeerTube.
The rest of the main
Further I had to move all kinds of other code, such as optimization code and code for doors and elevators. Some of which I did during the livestream that I linked above.
Later I tried doing another livestream where I tried cleaning the code, but I was tired as hell and so it became a stupid ADHD-fest where I ended up working on the Police Station instead, in the end, because I couldn't concentrate on the code.
But, then even later I actually streamed again, this time with proper energy and concentration and moved elevators, doors and a lot of optimization code out of
main(). Here is the recording of that stream:
In the same time I broke
main() itself into a few functions, separating it into
main(),
Init() which runs in the first frame of the game and
OnExit() which runs when you close the game. The
Init() itself is also not just a copy-paste from what there was in the
main() but rather I broken off some of the initialization into Racing.py, Doors.py, Elevators.py and
Opt.py. Leaving only just a few
if statements in the
Init():
for object in scene.objects:
if "spawn" in object:
Vehicle.RegisterSpawnPoint(object)
if str(object.name).startswith("Crate"):
crates = bge.logic.globalDict["garage-crates"]
crates.append(object)
if "LightSpawn" in object:
Opt.RegisterObjects(object, spawnAtDistance, "LightSpawn")
elif type(object.blenderObject.data) == bpy.types.AreaLight:
Opt.RegisterObjects(object, spawnAtDistance, "AreaLamp")
elif "Tree" in object.name:
Opt.RegisterObjects(object, spawnAtDistance, "Tree")
elif "Palm" in object.name:
Opt.RegisterObjects(object, spawnAtDistance, "Palm")
elif "Elevator" in object:
Elevators.RegisterElevator(object)
elif "Door" in object:
Doors.RegisterDoor(object)
elif "ambiance-sound" in object:
bge.logic.globalDict["sound-ambiances"].append(object)
I could have made functions to precalculate all those things in some sort of way that would look like this in
Init():
Opt.Precalculate()
Doors.Precalculate()
Elevators.Precalculate()
But I decided against that, because it would have required looping over all those objects multiple times and the game has a lot of them. Even if it only happens on the first frame. The first frame is already a bit too slow, so to optimize it a bit I made one loop in the
Init() and call functions based of the object type from there.
Bones And All
![[thumbnail]](https://upload.wikimedia.org/wikipedia/en/5/5f/Bones_and_All.jpg)
Blender Dumbass
👁 49 💬 2
It is very hard to describe the style of
Luca Guadagnino, the director of
Bones And All. His films are very good. But it seems like he is not interested in plot, which is weird, considering that the movies are good. He is famous for his erotic dramas, films centered around a sexual tension between people, like his perhaps most acclaimed movie
Call Me By Your Name, in which all the substance comes from very subtle things. A character looks a certain way on another character. Or perhaps holds onto another character's hand for way too long. And you have to piece together all these little clues to even start feeling some kind of presence of a plot. Because if you don't pay attention it all looks like people just casually hanging out. And then suddenly a payoff happens, which would make sense only if you paid attention to the little clues.
Rush 2013 is not the same as F1 2025
![[thumbnail]](https://upload.wikimedia.org/wikipedia/en/d/d0/Rush_UK_poster.jpeg)
Blender Dumbass
👁 4 💬 0
After seeing a somewhat of a racing movie called
American Graffiti starring
Ron Howard, the next movie to watch was an obvious choice. A directed by
Ron Howard 2013 racing film called
Rush, which might feel like a predecessor of 2025's
Joseph Kosinski film
F1. But watching it I found this movie to be closer to
Scorsese's
The Wolf Of Wall Street rather than
F1.
#rush #racing #ronhoward #film #review #movies #cinemastodon
Shazam! 2 is jank in a good way? maybe... let me explain
![[thumbnail]](https://upload.wikimedia.org/wikipedia/en/thumb/f/fb/Shazam%21_Fury_of_the_Gods_%282023%29_Main_Poster.png/250px-Shazam%21_Fury_of_the_Gods_%282023%29_Main_Poster.png)
Blender Dumbass
👁 12 💬 2
Shazam! Fury of the Gods is another
David F. Sandberg film that has an issue with it's opening. I just reviewed his film
Until Dawn and if you can survive the not so good dialogue of the first couple of scenes, you are in for a very good movie. This film has a similar issue.
#shazam #davidfsandberg #movie #review #film #cinemastodon #dceu #galgadot #rachelzegler
Copyright Made People Do Useless Work
Blender Dumbass
👁 39 💬 0
Oh the copyright! The system that many believe is there to "protect" artists from exploitation. But the system that is quite clearly one big exploitation in and of it self. I hope that my readers here have a job. Since I want to draw a very interesting parallel. Would you work if there was no contract? Would you do anything if the person that supposed pay you, would not pay you if he didn't want to? Or you would first sign a contract and then do the job? In the world of copyright, there is no contract to sign. There is no boss that will pay you. You have to risk everything to do something that might or might not interest other people in the first place. And no copyright will save you if you did something so utterly uninteresting that nobody will even pay you for it. Let's explore this!
Powered with BDServer
Plugins
Analytics
Contact
Mastodon