[icon ] blenderdumbass . org [icon scene] Articles

Story Without Cutscenes in Dani's Race

[avatar]  Blender Dumbass

January 28, 2025

👁 52

https://dev.dubvee.org/ : 👁 1
https://blenderdumbass.org/ : 👁 4
https://blenderdumbass.org/search?text=DanisRace&tags=on : 👁 1

#DanisRace #MoriasRace #Game #Gamedev #UPBGE #blender3d #animation #GTAClone #programming #project #Story #Storytelling #Gnu #Linux #Freesoftware #OpenSource

License:
Creative Commons Attribution Share-Alike
Audio Version





There is a petition happening right now for Dani's Race version 2025-01-19 which if you will sign it, will help both the development of the game and will help one very important contributor. So please go there and sign it. ( You must have a fediverse account for it, though ).



Continuing Moria's Race I can't make Dani's Race simply story-less, yet I do not want to take the obvious route and turn the game into a movie either. A lot of games these days forget that they are games and try very hard to be "cinematic". Which means that they are films and not games. And that is not interesting. Why don't you just release it as a movie if you want to make a movie?


[embedded image]


So the challenge for Dani's Race is deliberately not to be a movie. As in the game should not have cuts, nor there ever should be a moment when the player loses control over the character. Yet through all those limitations I want to continue a story I started in an actual movie. Which is kind of complicated.

For example in the first story mission in the game, which you play immediately as you download the game: Dani is in his room alone. Suddenly a phone calls and Paps ( the father character from Moria's Race with a recognizable voice ) is asking Dani ( and by extent you, the player ) to bring a race car from the garage of the house to the racetrack. But he instructs you not to break it. Since Moria will need to use this car later to practice the race.


[embedded image]


Here are some challenges: You should be able to combine the animation of Dani talking to a phone with him walking around and doing any other activity. So that the answering of the phone will not break the flow of the rest of the game; there should be cars which are breakable; a specific car, related to a story should spawn in a specific place for the story to work; there should be Paps and Moria waiting for you in the racetrack; And when you bring the car Moria should take it from you and go practicing with it on the racetrack. So if you stick around you could see her drive the whole racetrack. And if you remember from the movie it is not a simple racetrack; Also characters should speak at their right moment. And even sometimes say different lines based on different things you do. And while speaking they also need to at least open their mouths.


[embedded image]


The way the animation was approached is rather fortunate. UPBGE, the game engine of choice, has an ability to mix multiple animations into one. Overwriting only certain actions. So I can have a base animation ( layer 0 ) be the walking of the character. While on top of that ( layer 1 ) have him put his phone near his head to talk. Where only the hand will overwrite everything. While the rest of the body will use the animation from layer 0.


[embedded image]


Dani has multiple actions. One for the base, one for the phone specifically, and one for emotions and facial expressions. Which I can layer one over the other to make the range of animations that I need for this game. The base animation action might contain multiple base animations at different times. For example from frame 0 to frame 300 it is Dani's idle animation. Basically him standing. Then from 300 to 310 it's his walk cycle. And so on. All of those I later write down into a JSON file, which is later interpreted with this function, so I wont need to setup everything manually each time:

def ApplyAnimation(character, animation, keep=False, **kwargs):

    # Optimization
    cam = bge.logic.getCurrentScene().active_camera
    if character in Reuse.reuse.get(character.name, [])\
       or cam.getDistanceTo(character) > 150:
        return
    
    # Exctracting data request
    rig        = getRig(character)   
    action     = rig.get("Action") 
    startframe = animation[0]
    endframe   = animation[1]

    # Failsafe
    if not action:
        return
    
    # If we are reading animation from the database
    if type(animation) == str and animation in animations.get(character.name, {}):
        
        data       = animations[character.name][animation]
        action     = data.get("Action", action)
        keep       = data.get("Keep", keep)
        startframe = data["Frames"][0]
        endframe   = data["Frames"][1]
        kwargs     = data.get("kwargs", kwargs)

    elif type(animation) == str:
        startframe = 0
        endframe   = 0
        
    # Sometimes we might want to keep the animation at it's
    # last frame when it ends.
    if keep and rig.getActionFrame(kwargs.get("layer", 0)) == endframe:
        startframe = endframe
    
    
    # Executing the animation
    rig.playAction(action, startframe, endframe, **kwargs)

    # To activate the stand animation we want to know if anything is playing
    if kwargs.get("layer", 0) == 0:

        # Recording the animation
        rig["animation"] = animation


So now if I want to have Dani do the answering of the phone motion I can just simply write:

Character.ApplyAnimation(dani, "AnswerPhone")


... which is exactly what I do in Script.py when he answers his phone.

Now if you look into the first scene() function in that file you will see that there are some conditions on the rigging of the phone. It doesn't just immediately ring. I want the player to get somewhat familiar with the controls first. And then when it does ring it gives the player an option of not answering it. Postponing the plot of the game.

Yet since the car is supposedly in the garage of this house and Paps and Moria are waiting for this car on the racetrack, the phone should not ring far away from the house. Or especially should not ring on the racetrack. So that the illusion of the game world happening will not be broken.

if dani.getDistanceTo(house) < 600 and not dani.get("race"):
    
    # If at least 20 seconds have been passed from the start of the game.
    
    if bge.logic.getRealTime() > Story.get("lastring", 20):
        
        Story["ringing"] = RingPhone()
        Story["lastring"] = bge.logic.getRealTime() + 400

As you can see the program is checking that Dani is not father than 600 meters away from the house and is not currently racing, or doing some other side-quest, which I always record into dani"race"
Of course the location of the house before the first mission is marked on the mini-map, so if you do get away from it and start messing around in the city, you will still get reminded that something interesting must be at the house itself.

Now, when you answer the phone this audio-file plays:




As you can hear, the audio starts with 3 seconds of silence. This is needed for the animation of Dani answering the phone to be done before we can hear him say "Yes". Which is then followed by Paps's monologue.

While writing new lines for Paps is not a significantly complex process, because I was the voice actor in Moria's Race that voiced Paps and I can always switch to using Paps's voice. With Dani or Moria this is not that simple. I talked many times about the challenges of finding and then convincing a voice actress to do Moria's Race with me. And expecting her to come back, let alone work in such an unpredictable pace ( after she told me that she would not do that ), is not going to happen. So I am trying to reuse the stuff I got from her for the movie, which is not a lot of stuff, even though I can use takes that didn't make it into the final cut.

Writing new scenes with such a limited palette of phrases is actually sort of interesting in an artistic way. It kind of makes me go through a Lars Von Trier-esk technique of limitations, to distill some interesting stuff. And even though it is very hard, I am kind of enjoying the process. I don't really want to have a voice actor for Moria and Dani for this game.

Anyway. I guess I need to stop blabbering. This article is already getting a bit long. And I need to still proof-read it, record a recording of it... Damn! I forgot to start a recording of how I'm writing it. See? This is what happens when you are tired.

At the moment I'm working on another scene which involves characters that need to navigate themselves through doors and stuff and being able to drive though the whole town without mistakes. This will flex my programming a bit since I need to make sure the game has code for all of it. I guess you can visit my livestreams where I am occasionally streaming how I'm working on this game.

And do not forget to sign the petition. It is really important. It helps the community. And helps the game be released. And there are a lot of reasons for it. So please go to the latest petition page, use your fediverse account and help us get the project rolling. Thank you! ... and ...

Happy Hacking!!!





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









[avatar]  elban c:0


Если ты просто сейчас пошёл спать ничего мне не сказав, я буду тебя проклинать

[icon send] Reply
[avatar]  elban c:1


На заставке статьи папус выглядит так будто его штаны настолько ему жмут что весь жир ушел под нижнюю часть тела...

[icon send] Reply
[avatar]  elban c:2


Ты же понимаешь что если ты не зайдешь в звонок в течении десяти минут, тебе будет пиздец?

[icon send] Reply



[icon reviews]The House That Jack Built

  Unread  

[thumbnail]

[avatar]  Blender Dumbass

👁 49 💬 0



When I started doing movie reviews I told myself that I will make reviews right after I saw the movie. But there is an exception to this rule. The first and the last time I saw The House That Jack Built was in Jerusalem Cinemateque in the end of 2018. Roughly 5 years ago. And this review will be made from the memory I have of the movie. I have no problem with the existence of this movie. Freedom of Speech is important. But I am not willing to watch it again. Even though I am kind of a fan of the director Lars Von Trier and the movie is arguably very good. It's just I'm not brave enough to sit through it again.


[icon petitions]Release: Dani's Race v2025-01-19

  Unread  

[thumbnail]


230 / 250 Signatures

[avatar]  Blender Dumbass

👁 70 💬 0



Dani's Race version 2025-01-19


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


[icon malware]Deception

  Unread  

[thumbnail]

[avatar]  Blender Dumbass

👁 42 💬 1



Sometimes developers of a program will lie to the user knowing very well that they are lying. This kind of Deception is often implemented as a malicious functionality.



[icon articles]Statistics On Moria's Race So Far

  Unread  

[thumbnail]

[avatar]  Blender Dumbass

👁 32 💬 1



Moria's Race was released 118 days ago on 26th of August 2023. And as of now, I'm aware only of about 604 views across 6 platforms that I track.


#MoriasRace #blender3d #animation #statistics


[icon articles]Dumb Phones

  Unread  

[thumbnail]

[avatar]  Blender Dumbass

👁 51 💬 1



"You know they are listening to us this very moment?" - said Jake to Tom on a party one night. "What are you talking about?" - Tom was obviously confused. So Jake had to continue - "You know the Facebook app and the Google app on your phone is constantly recording what we have to say to each other, forming an opinions on us. They claim it's for advertising. But they can use it for anything they want. You know?". Tom looked at Jake with a slight smile. He knew he had a very good comeback. After a short pause Tom said - "I use a dumb phone." - and went into the party. But Jake didn't stop feeling bad. Jake didn't use no phone at all.


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