IS480 Team wiki: 2012T1 6P Development
Home | Project Overview | Project Management | Project Documentation | Meeting Minutes | Game Development |
Overview | Game Mechanics | User Testing | UI Screenshots | Graphics Development | Technical Complexity| |
Technical Complexity
Game Scenes Setup
Sprite collections with polygon colliders setup
Every images before appearing on the scene has to be added to a sprite collection library where its precise settings and parameters are manually set in order for the image to take shape in the scene and allow it to have natural interaction with other objects.
Scene setup
The following is an example of a scene setup that consists of 16 different objects laid out in one frame of the scene. The average amount of objects in one stage would go up to about 400 and the crucial part of making the game fun and challenging greatly relies on the precise manual positioning of every objects in this step.
Transition between various scenes
As gralch progresses through the scene, there’ll be a change in theme. However, the change must not be too sudden, or it will disrupt the user’s experience, and the flow of the game. Therefore, our group implemented a gradual change as Gralch progresses through the stages, by controlling the alpha (transparency) of the two backgrounds (overlay). Some additional points about the implementation are as shown below:
1. At the start of every segment (section of the map), the alpha of the theme image (to show) will be 1f, while the other image (theme) will be 0f.
2. As Gralch progresses along the segment, the alpha of the first theme will move towards 0f, while the other image will move towards 1f.
3. When Gralch reaches the next segment of the map, point 1 is repeated, this time with the other theme starting with 1f.
Example Code:
// find out which segment currently in int segmentTravel = (int)((Runner.distanceTraveled % wholeInterval) / (wholeInterval / 4)) + 1; // find out which round currently in int roundTravel = (int)(Runner.distanceTraveled / wholeInterval) + 1; // find out progress within segment float progress = (Runner.distanceTraveled % (wholeInterval / 4)) / (wholeInterval / 4); if (segmentTravel == 1){ if(renderer.name.Contains("bg1")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,1f); } if(renderer.name.Contains("bg2")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,0f); } } if (segmentTravel == 2){ if(renderer.name == "foreground1"){ renderer.material.color = new Color(((1 - progress)/2),renderer.material.color.g,renderer.material.color.b); } if(renderer.name.Contains("bg1")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,1f - progress); } if(renderer.name.Contains("bg2")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,progress); } } if (segmentTravel == 3){ if(renderer.name.Contains("bg1")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,0f); } if(renderer.name.Contains("bg2")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,1f); } } if (segmentTravel == 4){ if(renderer.name == "foreground1"){ renderer.material.color = new Color(((progress)/2),renderer.material.color.g,renderer.material.color.b); } if(renderer.name.Contains("bg1")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,progress); } if(renderer.name.Contains("bg2")){ renderer.material.color = new Color(renderer.material.color.r,renderer.material.color.g,renderer.material.color.b,1f - progress); } }
Precise control of objects behaviour
The main focus of the development work of our project is to achieve precise control over the manipulation of the components' behaviour that are attached to all objects with the use of C# scripts, this includes collision and effects handling for every single event.
With the use of C# scripts, we are able to have precise control on every collision events and the desired outcome of each case:
- Gralch triggering a trap at the precise contact point.
- Gralch gains x amount of energy upon contact with y type of cherry.
- Gralch loses x amount of energy upon contact with y type of obstacle.
- Gralch passing a checkpoint which result to a notification to user.
- Gralch movements along the game
- Elevates upon touch and hold of mobile input on touchscreen
- Freefall on release of touch of mobile input on touchscreen
- Gralch animations
- Idle - During start of game
- Flying - Upon exiting contact with platform or planks
- Running - Upon contact with platform or planks
- Constant draining of Gralch's energy throughout game.
- Gradual speed increase of Gralch throughout the stage as player progresses to further checkpoints.
Game Controls
Pseudo Code For Touch & Hold
IF( Mobile Touch Input ) IF( GameHasStarted ) play flying animation button pressed is true flying is true ELSE set rigidbody kinematic to false IF(Audio not mute)Start play audio GameHasStarted is true flying is true play flying animation add force to rigidbody IF(button pressed is true) if(current animation is "Running") play flying animation add force to rigid body
Pseudo Code For Swipe
IF (Input.GetButtonDown) initialize flickTime to 0 get the current pixel position where the input is detected and store as posDown take note of the time when input is detected and store as timeDown
IF (Input.GetButtonUp) get the current pixel position where the input is last detected posUp take note of the time when input is last detected and store as timeUp update flickTime to be the difference between timeUp and timeDown update flickLength to be the distance between the posUp and posDown calculate flickSpeed by having distance, flickLength divide by time, flickTime IF (flickSpeed is beyond limit, flickSpeedCap) set flickSpeed to flickSpeedCap convert both pixel positions, posDown and posUp to the world position, vectorDown and vectorUp
Calculate force to add to the object using this formula - (vectorDown - vectorUp) x flickSpeed Add rigid body force to the object’s ForceMode property
Pseudo Code For Joystick
//Initialization Method Initialize vector position of touchArea to be the bottom left of the screen Get the center position of the touchArea to be touchAreaCenter (x + width/2, y + height/2)
//Linear Interpolation Method for the movement of joystick object Creates an animation that smoothly interpolates through a range of data points Takes in two data points, (xMin,yMin) and (xMax,yMax) xVar in this case is the x position of the joystick object Formula: y = yMin + (yMax – yMin) * ((xVar - xMin) / (xMax – xMin))
//Method to move joystick Get the current pixel position where the input is detected within the touchArea to be posCurr Get the difference in length between posCurr and touchAreaCenter and store it as posDiff
IF (Input.GetButtonDown) IF(posDiff is larger than the joystickRadius) lock joystick.x and joystick.y at the joystick’s circumference (joystickRadius * PI * 2) Convert joystick pos (-1 to be left (yMin), 1 to be right (yMax)) using joystick circumference as a limit apply linear interpolation method to get horizontal property vertical property is basically an inverted output of horizontal position ELSE reset joystick.x and joystick.y position to be touchAreaCenter horizontal and vertical properties are equal to 0
Calculate the change in object’s position upDown leftRight Add rigid body force upDown to ForceMode.Velocity property Add rigid body force, leftRight to ForceMode.Acceleration property