The Concept
For my midterm project, I decided to create a choice-making game based on the Star Wars film series. The concept is that you have the choice to control the events in the film Revenge of the Sith, following up to Anakin Skywalker becoming Darth Vader. You get to control key events in the film to try to prevent Anakin Skywalker from becoming Darth Vader.
The Process and Challenges
I first started out by creating the starting page of the game on p5. I downloaded an image that I had and added a sound in the background in the draw function. I added the full-screen option and resized the window accordingly. My initial plan for the instructions page was for you to click an instructions button, and a box would appear telling you the instructions. I built the instructions button and the box appearing, but then I didn’t end up liking it as much as I thought I would. That’s when I decided to make the instructions appear in the same way the opening crawl appears at the beginning of every Star Wars film. I found a website that creates crawls and made one. The only problem was that the video was 90 MB, and p5 only supports up to 5 MB. I tried cutting up the video into several videos and playing them one after the other, but that was not working. It would only play one video, or it would play each one under the other in the same window at the same time. That made it extremely difficult to create the idea I wanted, and it made running p5 very uncooperative, as the page would refuse to load and p5 would crash.
That’s when I decided to switch to VS Code.
After switching to VS Code, I uploaded the instructions video, and it worked perfectly. A problem I faced however was that the background audio kept running overitself over and over again, so I switched its location to the setup() function and it worked. My sister told me afterwards, to include a way to skip the instructions because that would make debugging easier and playing much more enjoyable. I created a Skip button and a start button, but I ended up removing the skip button altogether since the start button served the same purpose.
I then began creating the nodes and game states. To do that, I decided to incorporate Object-Oriented Programming to create each question in its own seperate class instead of repeatedly writing down the questions and option buttons. I created my first question class and used it as a template. I attempted to use a for loop to run through the class because that’s what I assumed I had to do. Then I decided to completely omit the for loop and just accessing the classes without loops.
After accessing the question from my class, I started working on the conditional aspect of changing the node after clicking the choice you want. I tried doing a typical option1Button.mousePressed(xyz), but it wasn’t working. So I asked ChatGPT and it told me it’s because I’m not accessing the class itself so I had to include the array name before.
Following that, I started actually working with my game states. (since my game is a choice-making game, I had to incroporate a state for every single node). I used the following code example: if (firstQuestion[0].option1Button.mousePressed()){ gameState===’node2′; }. I used this because my if statements in the beginning of my game call to draw the other nodes once the game state changes. This did not work and I was not able to access my other node/question when I clicked the choice button..After multiple attempts at debugging like trying to make the background black to cover over the previous start page, I resorted to ChatGPT which suggested I make a seperate transition function to be called when the buttons are pressed. This transition function would change the game state successfully and allow me to switch between nodes/questions since this was the structure of my game states:
function draw(){
//creating the conditions that will allow to switch between nodes
if (gameState === 'start') {
drawStartScreen();
} else if(gameState==='instructions'){
drawInstructions();
} else if (gameState==='node1'){//what happens in the first node and so on
drawNode1();
} else if (gameState==='node2'){
drawNode2();
} else if (gameState==='node3'){
drawNode3();
} else if(gameState==='node4'){
drawNode4();
} else if(gameState==='node5'){
drawNode5();
} else if(gameState==='node6'){
drawNode6();
} else if(gameState==='node7'){
drawNode7();
} else if(gameState==='sithEnding'){
drawSithEnding();
} else if(gameState==='deathEnding'){
drawDeathEnding();
} else if(gameState==='happyEnding'){
drawHappyEnding();
}
}
I then wrote the specific draw functions for each node. The concept of the transition node was extremely helpful and I used it repeatedly across my code. I proceeded to repeat the pattern of transition functions —> changing the node —> writing my drawNode functions.
I repeated this cycle across my timeline until I had to code the endings. Once I finished my endings, I had to incorporate a method to reset the game. At the endings of my timeline, I included a restart button. This button would call a transition function. This transition function would change the node back to ‘start’ again, effectively reseting the game.
Part I’m Most Proud Of
I’m most proud of using OOP for my questions and choice buttons. I think that was one of the most effective and efficient ways I could have run my code. It saved me so much time that could have been wasted debugging and searching for which question in particular to fix. It kept everything organized and structured.
class Question1{
constructor(question, option1, option2){
this.question = question;
this.option1 = option1;
this.option2 = option2;
this.option1Button=createButton(this.option1);
this.option1Button.style('font-size', '18px');
this.option1Button.style('font-family', 'titleFont');
this.option1Button.style('color', 'white');
this.option1Button.style('background-color', 'black');
this.option1Button.style('text-align', 'center');
this.option1Button.style('border', 'none');
this.option1Button.size(500, 80);
this.option1Button.position(width*0.25 - 250, height/1.5);
this.option1Button.hide();
this.option2Button=createButton(this.option2);
this.option2Button.style('font-size', '18px');
this.option2Button.style('font-family', 'titleFont');
this.option2Button.style('color', 'white');
this.option2Button.style('background-color', 'black');
this.option2Button.style('text-align', 'center');
this.option2Button.style('border', 'none');
this.option2Button.size(500, 80);
this.option2Button.position(width*0.75 - 250, height/1.5);
this.option2Button.hide();
}
display(){
fill('white')
textFont(titleFont);
textSize(34);
textAlign(CENTER, CENTER)
text(this.question, width/2, height/3);
}
show(){
this.option1Button.show();
this.option2Button.show();
}
hide(){
this.option1Button.hide();
this.option2Button.hide();
}
}
AI Disclosure
I used Gemini to produce the backdrop images of the nodes. I used ChatGPT to debug issues such as:
- The soundtrack playing repeatedly, ChatGPT told me to move my soundtrack.play to setup() since draw() runs 60 times a second
- The nodes would not switch but that was because I did not know the difference between = and ===. ChatGPT explained the difference to me, and I was able to know when to use = and ===
- I was not able to change nodes when I click buttons, this was the structure I tried incorporating:
(firstQuestion[0].option1Button.mousePressed()){ gameState==='node2'; }but it did not work and it refused to switch nodes. ChatGPT told me to incoroporate the transition nodes. That was I believe the most beneficial and efficient parts that ChatGPT told me to incorporate. Without it my code would be extremely chaotic and difficult to debug. It was extremely beneificial, and it allowed me to create the pattern I would use to switch out the node and game states. It was a one time suggestion, but it was something I repeatedly included in multiple parts of the code. Even within restarting the game I used it. And also, towards the end of coding my instructions video was changing its position differently than I coded it. So, I applied the transition function to only call the video when the instructions button is pressed.
- My buttons would not be in the correct position until I hit full-screen, so ChatGPT told me to put their code in my windowResized function
- I used the CoPilot extension in VS Code to change stylistic components of my buttons. After I finished the project and posted the github link, I realized that I had been working on the project with my computer zoomed out to 33% instead of it being at the default 100%. So I asked the extension to change all the text and button sizes 66% smaller to fit the frame correctly. I did this to save time instead of going to every singular text and button and manually changing the sizes which would have been extremely time consuming. I made it lower the positions of my buttons and change the background colors instead of manually doing it for every button and text.
All the code was written entirely by me, all AI tools were used as a supplement to debug.
Reflection:
For the future I would love to incorporate the idea of creating and animating the actual characters and allowing the users to move the characters around with the mouse, choosing which other characters to speak to and picking choices from the dialogue themselves. I would want to give it a video game style. I would have loved to create more storylines and endings for the game as well.
GAME LINK: https://da3755-ui.github.io/prevent-the-fall-of-anakin/