[icon ] blenderdumbass . org [icon scene] Articles

So I Cleaned Up Some Spaghetti from Dani's Race Code

[avatar]  Blender Dumbass

December 29, 2024

👁 143

https://mastodon.social/ : 👁 3
https://lemmy.ananace.dev/ : 👁 1
https://blenderdumbass.org/ : 👁 2
https://mastodon.online/ : 👁 1
https://lm.madiator.cloud/ : 👁 2

#DanisRace #MoriasRace #GameDev #FreeSoftware #Gnu #Linux #OpenSource #GtaClone #Programming #Python #SpaghettiCode #UPBGE #blender3d

[icon left] Next [icon right] Previous
License:
Creative Commons Attribution Share-Alike
Audio Version





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.


[embedded image]


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]

    # Moria drive the car to the race
            
    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"])

    # Moria racing the race
                
    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()

    # Deleting starters
    for starter in race["starters"]:
        if starter["cylinder"]:
            DeleteCylinder(starter, ignoreTimer=True)

    # Making the racers race
    for racer in race["racers"]:

        racer["racing"] = True
        racer["launchtime"] = 100
        racer["race"] = racename
        
        # Testing
        racer["npc"] = "racer"
        racer["active"] = False

        # Beam of energy
        racer["beam"] = Reuse.Create("Racer.Indicator")

    # If the race includes dani.
    if dani:
        dani["race"] = racename
        dani["checkpoint"] = 0   
        dani["lap"] = 0
        

        # Make the racing UI visible
        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

        # Play the start the race sound.
        bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding


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.


[embedded image]


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.





Petition


I just want to remind you that there is a petition going on for the game and it is taking a bit long. Please, if you have a fediverse account, make sure to sign that petition so that this "already old" version could be released and a new petition with all those improvements could be started.

Happy Hacking!!!



[icon terminal] JSON [icon markdown] Markdown

[icon left] Next [icon right] Previous
[icon question] Help

Subscribe RSS
[icon link] Author
[icon link] Website
Share on Mastodon


[icon question] Help


You can comment from Mastodon.










[icon articles]Why are we blind to 99% of Child Abuse?

[thumbnail]

[avatar]  Blender Dumbass

👁 28 💬 1



Child Abuse in on my mind right now. I have written a screenplay for a feature film that I'm already in early talks to produce. The bad guy in the movie is a child-rapist / child-killer. His presence alone justifies the anger of the heroes and creates the tension in the film. Yet I don't think I can make a movie that is a shlocky exploitation film. The subject matter is a bit too strong for something that careless.


#abuse #childabuse #politics #freedom #freerangekids #kids #paternalism


[icon petitions]Release: Dani's Race v2025-03-17

[thumbnail]


29 / 50 Signatures

[avatar]  Blender Dumbass

👁 355 💬 2



Dani's Race version 2025-03-17


#DanisRace #MoriasRace #Game #UPBGE #blender3d #project #petition #release


[icon articles]Is BeamNG Drive a Free Software Game

[thumbnail]

[avatar]  Blender Dumbass

👁 201 💬 0



Once upon the time, I remember feeling utterly unpleasant toward playing racing games where cars did not break. I thought that GTA games, for example, were far more realistic because making mistakes and crashing into something is going to break the car and therefor you have to drive more carefully. Yes I was a strange kid. But I did enjoy games such as Flat Out where the objective is to crash your car as much as possible. I think I liked games that simulate reality, rather then those that are just made for fun. You could imagine how excited I was when I saw videos of this new racing game that came out at about 2013 called BeamNG Drive. A game where cars don't just swap body shapes with pre-modeled deformations. But a game that simulates the destruction fully. Using soft body physics. I didn't play it. At first my computer was way too slow and there was no GNU / Linux support. Then the game became paid. Then I changed from being a mere "Linux user" to being a "GNU / Linux user", which meant that this game is not good for my freedom. But is it though?


[icon reviews]The Fury 1978 what the hell is this movie?

[thumbnail]

[avatar]  Blender Dumbass

👁 52 💬 2



While Brian De Palma was making Carrie ( as a part of his Alfred Hitchcock imitation films ), Alfred Hitchcock himself was making his last picture Family Plot, where he used the composer from Steven Spielberg's Jaws John Williams for the score. De Palma, probably knowing Williams through Spielberg, decided to mess around with Hitchcock himself, making a sort of yet another Carrie ( a film about people with superpowers ) but this time hiring John Williams himself for the score. And weirdly enough ( while Spielberg was finishing Close Encounters and starting 1941 where his camera sexually obsessed over De Palma's GF at the time Nancy Allen ) De Palma hires Spielberg's girlfriend at the time Amy Irving for the lead role.


#TheFury #BrianDePalma #AmyIrving #StevenSpielberg #JohnWilliams #Israel #Palestine #film #review #movies #cinemastodon


[icon reviews]Baby Driver

[thumbnail]

[avatar]  Blender Dumbass

👁 114 💬 5



If you expect Baby Driver to be anything like Hot Fuzz. Don't! If you expect Baby Driver to be anything like Scott Pilgrim Vs The World. Don't! If you expect Baby Driver to be anything like Last Night In Soho. Don't! The director of Baby Driver, Edgar Wright set for himself a challenge to make every next movie he does in a different genre. Therefor you get absolutely different effects from his movies. Even though there are obvious Edgar Wright tropes in every one of his movies.


[icon codeberg] Powered with BDServer [icon python] Plugins [icon analytics] Analytics [icon mastodon] Mastodon [icon peertube] PeerTube [icon element] Matrix
[icon user] Login