Summary
September ended up being quite a busy month for me, as I started teaching, and began to receive more freelancing requests. Looking at my progress though I am pleased with it, I wanted to be further along at this point. This is mostly the effect of getting caught up in the daily motions of life. Personal projects inevitably end up taking a back seat to the paid work we do. Regardless the project must move forward
From my last blog update I wanted to have the tarot card programming outlined with either a game flow or a UML diagram. I also wanted to start working on a Technical Design Document. I am glad to say I have made it past these steps.
Project Trello Update
I was able to successfully plan out my tarot card game and start drafting a TDD. I went the route of writing a rough UML diagram instead of a game flow. My Technical Design Document is still in a hand written format, and I will be making a priority to type that up over this upcoming week. On top of the tasks I had set out for myself from the previous blog update. I was able to successfully prototype some of the gameplay of the tarot cards, and in the last week I've finished my second round of debugging.
My latest updates to the Magic Shop VR Project.
Planning the Tarot Gameplay
When I am planning gameplay I like to write everything down, and work on paper to start with. I find that if I just jump into Visual Studio without a plan, I will end up spending more time confused than productive.
Gameplay Design Notes
For the tarot gameplay I started by writing down the sequence of events I wanted to happen, and in what order they should happen in. I drew some diagrams for myself to visualize my thoughts and I wrote down how I wanted the sequence to appear on screen. After that I worked on figuring out what scrips were needed to make this whole event work smoothly. This lead me to pseudo coding each script to outline what it managed, and how it should contribute to the gameplay.
Once I had those ideas down on paper, I moved onto figuring out a very rough UML diagram. This diagram breaks down the scripts into different sub-classes and I wrote down all of the ideas I had about how to approach the code here.
Setting up the Game Objects
Before I started scripting anything, I put together all the prefabs and game objects I needed to be able to test the script's functionality. I used some temporary assets that I made from my level blocking phase and got to working.
The tarot game prefab is composed of six main objects : the deck, the start position, the end position, the base, the spawn trigger positions, and the tarot game manager that contains the positional information for where to spawn all the card slots.
In the last week I talked about the Auto Hands premium asset I purchased. Included in that were some additional scripts for XR interactable objects. For this game I use the place point script as positions where the tarot card deck will snap to when the player releases it within a trigger collision. I am also using the provided Grabbable script on the deck itself. This just makes my life a little easier and gives me one less thing to create from scratch. Both the start and the end points have events that run and make changes to the tarot game, calling on functions from other game objects in the prefab.
Scripting the Gameplay
After everything was planned out and made physical on paper. I started working on the scripts I needed in order to make the tarot gameplay function. This meant that I've omitted the 'order' functionality for the time being. So I'm going to go through the scripts and describe how they play their part in the greater whole. I'll also be talking about any troubles I may have run into while working on each. Lets start small and work our way up to the larger components.
Spawn Points
Spawn points are positions in 3D space where cards will be spawned into the game. Spawn points are created by the Deck script at the start of the tarot Mini game. Spawn points tell the tarot deck to spawn a card whenever the Deck game object overlaps their triggers. Each spawn point can only tell the deck to spawn a card one time. Currently these scripts only have two functions.
OnTriggerEnter() - If the Deck collides with the spawn point trigger, It tells the deck to spawn a card, only if it has not told the deck to do so already.
ResetStation() - Resets the Boolean used to track if the spawn point has told the deck to spawn a card.
Moving Object
The MovingObject script is a base class for all props, or items in the game that need to be moved via code. This base class can move or rotate an object to match a desired location, or rotation. Currently the MovingObject script has five functions for any sub-class to call upon.
MovingObjectStart()- Start function that must be called within the sub-class start function. Sets the rigid body variable, and grabs the initial local rotation of the game object.
MoveToTargetLocation() - Moves an object to a set target location.
MatchTargetRotation() - Matches the object's local rotation with a set target's rotation.
UpdateDestination(GameObject aTarget) - Updates the object's set target destination or rotation.
UpdateMovement() - Sets the velocity of the moving object's rigid body and lerps the object's local rotation based on delta time and rotation speed.
Card
The Card script is attached to the Card Prefab, and represents all of the properties of the card. The Card script is a subclass of the MovingObject script allowing it move around the scene. There are five variations of the Card Prefab each associated with a different suit of cards. Tarot cards have four main suits similar to your regular playing cards. Each of those four suits have 14 cards, but tarot decks also have 22 Major Arcana cards.
Each variant has a list of materials matching the number of cards in it's suit. When a card is spawned it randomly generates a number that will be used to assign it's material. Currently there is not any code in place to prevent the spawning of multiples of the same card but it is on my to do list. The Card script has five main functions for the time being.
MovementStates() - A coroutine made to loop until the card has successfully matched the position and rotation of it's target. Once in place , it will wait until it is given a new destination.
bool MovementStatus(Vector3 aCardVector, Vector3 aTargetVector, bool isCheckingRotation) - Called upon by the MovementState() function to determine weather or not the card has reached it's target destination or rotation and returns a bool.
Visible(bool isVisible) - Public function used to either make the card visible or invisible to avoid visual clipping when cards are stacked together.
SnapToDestination() - This function is used to transport the card to their target location when they are within a close enough distance. This function can also be used to teleport the card anywhere. This is useful in removing visual jitter when the card is trying to align perfectly with a location.
OnTriggerEnter() - Handles the situational events required for each object that may collide with the card's trigger.
Deck
The Deck script is attached to the Deck game object located in the Tarot Game prefab. The Deck script creates the spawn locations at the start of the game, and uses them to trigger the spawning of the cards. The deck game object is a player interactive object. It has five main functions.
SpellType(int aSuitNumber) - This function changes what suit of cards to spawn based on the spell type specified by an enumerator.
SpawnTriggers() - This instances the spawn point game objects.
SpawnCards(Vector3 aPosition) - A function called upon by the spawn points that has the deck spawn a new card at the given position. It also scales the size of the deck to make it appear as though it is shrinking.
CanGrabDeck(bool isGrabbable) - This function changes the player's ability to grab the deck game object in VR. This is used to to lock the deck into place once all the cards are finished spreading.
ResetStation() - Resets the deck script's Booleans, and position so it is ready for a new game.
Card Positions
Card positions are the points in 3D space where cards will travel to during the gameplay. They are spawned each time the gameplay starts by the CardMovementManager script. There are three kinds of card positions in the game. A standard position, a gather position, and a selected position. Each of these variants represent different stages the cards will go through. Though I plan on making this script a Base class and these variants subclasses, for the moment it is all contained in one class. The main functions of the Card Position are as follows.
SpreadCards()- Gather positions are responsible for taking a list of accumulated cards and dispersing them each to one of the standard positions.
SpreadCardMove() - This function moves a single card by updating that card's destination.
DefaultCardMove() - A coroutine built for the standard cards. This routine will move a card to the next position in line, once the next position is empty. It works on a timer allowing the cards enough time to get from point A - to point B before trying to move the card again.
SetCurrentCard() - For standard Cards this function is used to set the current card that is in the position. For gather position cards it is used to identify the current card it is trying to move.
MakeGatherPoint() - This changes a Boolean that can make any standard position into a gather position.
MakeSelectionPoint() - This changes any card position to a Selected Card position at time.
bool HasCurrentCard() - Used to check weather or not a position currently is in possession of a card. will return true or false depending on the null status of the 'thisCurrentCard' variable. Useful for making sure a card does not get sent to a position that already has a card.
SetShuffleSettings(bool isShuffling, bool isForward) - Tells the standard positions to move the cards, and defines the direction the card must move.
ResetStation() - Reset for the card positions, means destroying them so they can be re-spawned when the next game is starting.
Card Movement Manager
This is the last script to discuss but arguably the most important. This script manages the movement of the cards and keeps track of the stages of the tarot mini game. This script uses an enum to represent the different states of the mini-game. The movement manager has control over every card position in the game and tells the other scripts when they are supposed to call specific functions. Some of the key functions of the CardMovementManager are as follows.
Update() - function called at every frame. it uses a switch statement to call the various functions of the script depending on the current state of the game.
ChangeState(int aState) - uses a switch statement to change the state of the game based on the integer inputted.
SetUp() - Called when the game is at the start phase, it spawns the gather point for all the cards to move to.
DeckSlide() - When the deck is sliding and spawning cards, the movement manager, spawns the standard card positions.
SpawnCardSlots() - Function called upon by both the deck slide and spread cards function to spawn additional card slots of different Kinds.
SpreadCards() - When all the cards reach the gather position the movement manager tells the gather point to spread out the cards to all the standard card positions.
ShuffleCards() - When all the cards are in the right positions, the movement manager tells the standard card positions to shuffle the cards. This function works on a timer, and when the timer resets the cards will change from shuffling clockwise to counter clockwise.
int NumCardsSelected() - Keeps track of the number of cards that have been selected by the player, and returns it as an integer.
StampOrder()- When three of the spread cards are selected the remaining cards are deleted and wait for the order to be stamped.
GameObject GetGatherPoint() - Returns the gather position game object.
ResetStation() - Resets the card Movement manager and tells all the positions, and the deck to reset.
Review and Next Steps
Currently the tarot game is functional up until the point where the player has to select the cards. My next task is to create the magic projectiles the player will shoot out of the wand to select cards from the moving targets. I'm also listing a short video from my progress debugging the scripts below.
Magic Shop VR Debugged Gameplay video
So currently the game runs as expected without any errors or bugs. The deck can be slid from left to right in order to spawn cards. The cards gather at one point and wait a beat before each card is moved to a designated card position. Once all the cards are in position, they wait a beat before shuffling. First they move clockwise, then after a timer they move counter clockwise.
My next steps going forward are to complete the full gameplay loop of the tarot cards. This means, completing the card selection functionality and order stamping. Depending on my timeline I will also be working on creating the order functionality, and working out how to determine order completion with my current functionality. This will most likely include some major refactoring of my code.
Thus concludes this update.
Comments