ELEC2645 (2018/19) / Mbed 2 deprecated el17cd

Dependencies:   mbed

Committer:
el17cd
Date:
Wed May 08 18:17:59 2019 +0000
Revision:
46:824ec81ff578
Parent:
39:41dcf1604fdf
Potentiometer now changes screen contrast for use on other devices.; Final Submission.; I have read and agreed with the Statement of Academic Integrity.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
el17cd 31:e681177037ef 1 #include "Renderer.h"
el17cd 33:02c5048b3b3f 2
el17cd 31:e681177037ef 3 N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);
el17cd 31:e681177037ef 4
el17cd 31:e681177037ef 5 Renderer::Renderer() {
el17cd 39:41dcf1604fdf 6 selectionCube.setVisible();
el17cd 31:e681177037ef 7 }
el17cd 31:e681177037ef 8
el17cd 31:e681177037ef 9 void Renderer::init() {
el17cd 31:e681177037ef 10 lcd.init(); //initialize the lcd
el17cd 31:e681177037ef 11 fov = 50; //set the field of view to 50
el17cd 31:e681177037ef 12 }
el17cd 31:e681177037ef 13
el17cd 33:02c5048b3b3f 14
el17cd 31:e681177037ef 15 float Renderer::xTo2D(float x, float z) { //Project 3D x coordinate to 2D perspective
el17cd 31:e681177037ef 16 return x * (fov/z) + 42;
el17cd 31:e681177037ef 17 }
el17cd 31:e681177037ef 18
el17cd 31:e681177037ef 19 float Renderer::yTo2D(float y, float z){ //Project 3D y coordinate to 2D perspective
el17cd 31:e681177037ef 20 return y * (fov/z) + 21;
el17cd 31:e681177037ef 21 }
el17cd 31:e681177037ef 22
el17cd 31:e681177037ef 23 void Renderer::drawHorizon(float angle){ //draw the line at the horizon
el17cd 31:e681177037ef 24 lcd.drawLine(0,
el17cd 31:e681177037ef 25 21-rint(-angle*40),
el17cd 31:e681177037ef 26 84,
el17cd 31:e681177037ef 27 21+rint(-angle*40),
el17cd 31:e681177037ef 28 1);
el17cd 31:e681177037ef 29 }
el17cd 31:e681177037ef 30
el17cd 31:e681177037ef 31 void Renderer::drawFace(Face *face, float angle) { //Draw a single face from a cube
el17cd 31:e681177037ef 32 float points[4][3];
el17cd 31:e681177037ef 33 float y, x;
el17cd 31:e681177037ef 34
el17cd 31:e681177037ef 35 for(int vertex = 0; vertex < 4; vertex++) {
el17cd 31:e681177037ef 36 for(int axis = 0; axis < 3; axis++) {
el17cd 31:e681177037ef 37 points[vertex][axis] = face->getVertexValue(vertex, axis); //copy all cube verticies to local array
el17cd 31:e681177037ef 38 }
el17cd 31:e681177037ef 39 y = points[vertex][1];
el17cd 31:e681177037ef 40 x = points[vertex][0];
el17cd 31:e681177037ef 41
el17cd 31:e681177037ef 42 points[vertex][0] = x*cos(-angle)-y*sin(-angle); //perform temporary rotation for lean effect when moving in x axis
el17cd 31:e681177037ef 43 points[vertex][1] = y*cos(-angle)+x*sin(-angle);
el17cd 31:e681177037ef 44 }
el17cd 31:e681177037ef 45
el17cd 31:e681177037ef 46 if (checkOnScreen(points)){ //if face is on the screen then fill the face and draw its outline
el17cd 31:e681177037ef 47 rasterizeFace(points, face);
el17cd 31:e681177037ef 48 drawFaceOutline(points);
el17cd 31:e681177037ef 49 }
el17cd 31:e681177037ef 50 }
el17cd 31:e681177037ef 51
el17cd 31:e681177037ef 52 void Renderer::rasterizeFace(float (&points)[4][3], Face *face) { //Fill in the face using white lines
el17cd 31:e681177037ef 53 int diffX1, diffY1, diffX2, diffY2;
el17cd 31:e681177037ef 54 float stepBottomY, stepTopX, stepTopY;
el17cd 33:02c5048b3b3f 55 diffX1 = xTo2D(points[0][0], points[0][2])-xTo2D(points[1][0],
el17cd 33:02c5048b3b3f 56 points[1][2]); //Calculate difference between top horizontal edge x coordnates
el17cd 33:02c5048b3b3f 57 diffY1 = yTo2D(points[0][1], points[0][2])-yTo2D(points[1][1],
el17cd 33:02c5048b3b3f 58 points[1][2]); //Calculate difference between right vertical edge y coordinates
el17cd 33:02c5048b3b3f 59 diffX2 = xTo2D(points[2][0], points[2][2])-xTo2D(points[3][0],
el17cd 33:02c5048b3b3f 60 points[3][2]); //Calculate difference between bottom horizontal edge x coordinates
el17cd 33:02c5048b3b3f 61 diffY2 = yTo2D(points[2][1], points[2][2])-yTo2D(points[3][1],
el17cd 33:02c5048b3b3f 62 points[3][2]); //Calculate difference between left horizontal edge y coordinates
el17cd 39:41dcf1604fdf 63 if(diffX2 != 0) {
el17cd 31:e681177037ef 64 stepBottomY = (float)diffY2/(float)diffX2; //increment multiplier for Y axis on bottom edge of face
el17cd 31:e681177037ef 65 stepTopX = (float)diffX1/(float)diffX2; //increment multiplier for X axis on top edge of face
el17cd 31:e681177037ef 66 stepTopY = (float)diffY1/(float)diffX2; //increment multiplier for Y axis on top edge of face
el17cd 31:e681177037ef 67
el17cd 31:e681177037ef 68 drawFillLines(points, diffX2, stepBottomY, stepTopX, stepTopY); //fill the face with white lines
el17cd 31:e681177037ef 69 }
el17cd 31:e681177037ef 70 }
el17cd 31:e681177037ef 71
el17cd 31:e681177037ef 72 void Renderer::drawFillLines(float (&points)[4][3],
el17cd 31:e681177037ef 73 int diffX2, int stepBottomY, int stepTopX, int stepTopY) { //draw the white lines within the face to fill it in
el17cd 31:e681177037ef 74
el17cd 31:e681177037ef 75 for(int step = 0; step< abs(diffX2); step++) {
el17cd 31:e681177037ef 76 if(diffX2 > 0) { //determine whether the face is inverted in y axis
el17cd 31:e681177037ef 77 lcd.drawLine(rint(xTo2D(points[0][0], points[0][2])-stepTopX*step), //draw lines from top edge to bottom edge until face is filled in
el17cd 31:e681177037ef 78 rint(yTo2D(points[0][1], points[0][2])-stepTopY*step),
el17cd 31:e681177037ef 79 rint(xTo2D(points[3][0], points[3][2])+step),
el17cd 31:e681177037ef 80 rint(yTo2D(points[3][1], points[3][2])+stepBottomY*step),
el17cd 31:e681177037ef 81 0);
el17cd 31:e681177037ef 82 }
el17cd 31:e681177037ef 83 else {
el17cd 31:e681177037ef 84 lcd.drawLine(rint(xTo2D(points[0][0], points[0][2])+stepTopX*step),
el17cd 31:e681177037ef 85 rint(yTo2D(points[0][1], points[0][2])+stepTopY*step),
el17cd 31:e681177037ef 86 rint(xTo2D(points[3][0], points[3][2])-step),
el17cd 31:e681177037ef 87 rint(yTo2D(points[3][1], points[3][2])-stepBottomY*step),
el17cd 31:e681177037ef 88 0);
el17cd 31:e681177037ef 89 }
el17cd 31:e681177037ef 90 }
el17cd 31:e681177037ef 91 }
el17cd 31:e681177037ef 92
el17cd 31:e681177037ef 93 void Renderer::drawFaceOutline(float(&points)[4][3]) { //Draw the outline of the face
el17cd 31:e681177037ef 94 for (int i = 0; i < 3; i++) { //cycle through each edge and draw them
el17cd 31:e681177037ef 95 lcd.drawLine(rint(xTo2D(points[i][0], points[i][2])),
el17cd 31:e681177037ef 96 rint(yTo2D(points[i][1], points[i][2])),
el17cd 31:e681177037ef 97 rint(xTo2D(points[i+1][0], points[i+1][2])),
el17cd 31:e681177037ef 98 rint(yTo2D(points[i+1][1], points[i+1][2])),
el17cd 31:e681177037ef 99 1);
el17cd 31:e681177037ef 100 }
el17cd 31:e681177037ef 101 lcd.drawLine(rint(xTo2D(points[0][0], points[0][2])),
el17cd 31:e681177037ef 102 rint(yTo2D(points[0][1], points[0][2])),
el17cd 31:e681177037ef 103 rint(xTo2D(points[3][0], points[3][2])),
el17cd 31:e681177037ef 104 rint(yTo2D(points[3][1], points[3][2])),
el17cd 31:e681177037ef 105 1);
el17cd 31:e681177037ef 106 }
el17cd 31:e681177037ef 107
el17cd 46:824ec81ff578 108 void Renderer::drawAllFaces(Face *faceArray, int noOfCubes, float angle) { //draw all faces in game using the painters algorithm
el17cd 31:e681177037ef 109 Face temp;
el17cd 31:e681177037ef 110 for (int f = 0; f< (noOfCubes*6)-1; f++) { //sort the faces in decreasing average z value using bubble sort
el17cd 31:e681177037ef 111 for (int f2 = 0; f2< (noOfCubes*6)-f-1; f2++) {
el17cd 31:e681177037ef 112 if(faceArray[f2].getAvgZ() < faceArray[f2+1].getAvgZ()) {
el17cd 31:e681177037ef 113 temp = faceArray[f2+1];
el17cd 31:e681177037ef 114 faceArray[f2+1] = faceArray[f2];
el17cd 31:e681177037ef 115 faceArray[f2] = temp;
el17cd 31:e681177037ef 116 }
el17cd 31:e681177037ef 117 }
el17cd 31:e681177037ef 118 }
el17cd 31:e681177037ef 119 for (int f = 0; f< noOfCubes*6 ; f++) { //draw each face from furthest away to closest
el17cd 39:41dcf1604fdf 120 if (faceArray[f].getVisible()) {
el17cd 39:41dcf1604fdf 121 drawFace(&faceArray[f], angle/15);
el17cd 39:41dcf1604fdf 122 }
el17cd 31:e681177037ef 123 }
el17cd 31:e681177037ef 124 }
el17cd 31:e681177037ef 125
el17cd 31:e681177037ef 126 bool Renderer::checkOnScreen(float (&points)[4][3]) { //Check whether any part of the face is on screen
el17cd 33:02c5048b3b3f 127 if (points[0][2] < 6 || points[1][2] < 6 || points[2][2] < 6 ||
el17cd 33:02c5048b3b3f 128 points[3][2] < 6) { //not on screen if behind perspective
el17cd 31:e681177037ef 129 return false;
el17cd 31:e681177037ef 130 }
el17cd 33:02c5048b3b3f 131 else if ((xTo2D(points[0][0], points[0][2]) < 0 || xTo2D(points[0][0],
el17cd 33:02c5048b3b3f 132 points[0][2]) > 84) //check if any 2D projection verticies are within screen boundaries
el17cd 33:02c5048b3b3f 133 && (xTo2D(points[1][0], points[1][2]) < 0 || xTo2D(points[1][0],
el17cd 33:02c5048b3b3f 134 points[1][2]) > 84)
el17cd 33:02c5048b3b3f 135 && (xTo2D(points[2][0], points[2][2]) < 0 || xTo2D(points[2][0],
el17cd 33:02c5048b3b3f 136 points[2][2]) > 84)
el17cd 33:02c5048b3b3f 137 && (xTo2D(points[3][0], points[3][2]) < 0 || xTo2D(points[3][0],
el17cd 33:02c5048b3b3f 138 points[3][2]) > 84)){
el17cd 31:e681177037ef 139 return false;
el17cd 31:e681177037ef 140 }
el17cd 31:e681177037ef 141 return true;
el17cd 31:e681177037ef 142 }
el17cd 31:e681177037ef 143
el17cd 31:e681177037ef 144 void Renderer::print(const char *text, int x, int y) { //print string at x, y position
el17cd 31:e681177037ef 145 lcd.printString(text, x, y);
el17cd 31:e681177037ef 146 }
el17cd 31:e681177037ef 147
el17cd 31:e681177037ef 148 void Renderer::printScore(int score, int x, int y) { //print a score at x, y position
el17cd 31:e681177037ef 149 char buffer[5];
el17cd 31:e681177037ef 150 sprintf(buffer, "%d", score/3);
el17cd 31:e681177037ef 151 print(buffer, x, y);
el17cd 31:e681177037ef 152 memset(buffer, 0, sizeof buffer);
el17cd 31:e681177037ef 153 }
el17cd 31:e681177037ef 154
el17cd 31:e681177037ef 155 void Renderer::clear() { //clear the display
el17cd 31:e681177037ef 156 lcd.clear();
el17cd 31:e681177037ef 157 }
el17cd 31:e681177037ef 158
el17cd 31:e681177037ef 159 void Renderer::refresh() { //refresh display and wait for 1/60th second (target fps = 60)
el17cd 31:e681177037ef 160 lcd.refresh();
el17cd 31:e681177037ef 161 wait_ms(1000/60);
el17cd 31:e681177037ef 162 }
el17cd 31:e681177037ef 163
el17cd 31:e681177037ef 164 void Renderer::turnOff() { //turn off the display
el17cd 31:e681177037ef 165 lcd.turnOff();
el17cd 31:e681177037ef 166 }
el17cd 31:e681177037ef 167
el17cd 46:824ec81ff578 168 void Renderer::setContrast(float contrast) { //set the contrast of the display
el17cd 46:824ec81ff578 169 lcd.setContrast(contrast);
el17cd 46:824ec81ff578 170 }
el17cd 46:824ec81ff578 171
el17cd 31:e681177037ef 172 void Renderer::drawDeathScreen(int selection, int highScore) { //draw the screen once the user has collided with cube
el17cd 31:e681177037ef 173 Face faces[6];
el17cd 31:e681177037ef 174 int x, y, z;
el17cd 31:e681177037ef 175 if(selection == 0){ //determine position of seleciton cube based on menu selection
el17cd 31:e681177037ef 176 x = -30;
el17cd 31:e681177037ef 177 y = -3;
el17cd 31:e681177037ef 178 z = 50;
el17cd 31:e681177037ef 179 }
el17cd 31:e681177037ef 180 else{
el17cd 31:e681177037ef 181 x = -30;
el17cd 31:e681177037ef 182 y = 15;
el17cd 31:e681177037ef 183 z = 50;
el17cd 31:e681177037ef 184 }
el17cd 31:e681177037ef 185
el17cd 31:e681177037ef 186 print("Best:", 30, 0); //print high score
el17cd 31:e681177037ef 187 printScore(highScore, 60, 0);
el17cd 31:e681177037ef 188 drawDeathButtons();
el17cd 31:e681177037ef 189 drawSelectionCube(x, y, z, 2);
el17cd 31:e681177037ef 190 }
el17cd 31:e681177037ef 191
el17cd 31:e681177037ef 192 void Renderer::drawDeathButtons() {//draw the death screen buttons
el17cd 31:e681177037ef 193 lcd.drawRect(24, 14, 45, 11, FILL_WHITE);
el17cd 31:e681177037ef 194 lcd.drawRect(24, 14, 45, 11, FILL_TRANSPARENT);
el17cd 31:e681177037ef 195 lcd.printString("Restart",26,2);
el17cd 31:e681177037ef 196 lcd.drawRect(24, 30, 45, 11, FILL_WHITE);
el17cd 31:e681177037ef 197 lcd.drawRect(24, 30, 45, 11, FILL_TRANSPARENT);
el17cd 31:e681177037ef 198 lcd.printString("Menu",35,4);
el17cd 31:e681177037ef 199 }
el17cd 31:e681177037ef 200
el17cd 31:e681177037ef 201 void Renderer::drawHomeScreen(int selection) { //draw the home screen
el17cd 31:e681177037ef 202 int x, y, z;
el17cd 31:e681177037ef 203 if(selection == 0) { //determine position of selection cube based on home screen selection
el17cd 31:e681177037ef 204 x = -30;
el17cd 31:e681177037ef 205 y = -12;
el17cd 31:e681177037ef 206 z = 50;
el17cd 31:e681177037ef 207 }
el17cd 31:e681177037ef 208 else if(selection == 1) {
el17cd 31:e681177037ef 209 x = -30;
el17cd 31:e681177037ef 210 y = 5;
el17cd 31:e681177037ef 211 z = 50;
el17cd 31:e681177037ef 212 }
el17cd 31:e681177037ef 213 else {
el17cd 31:e681177037ef 214 x = -30;
el17cd 31:e681177037ef 215 y = 22;
el17cd 31:e681177037ef 216 z = 50;
el17cd 31:e681177037ef 217 }
el17cd 31:e681177037ef 218 drawHomeButtons();
el17cd 31:e681177037ef 219 drawSelectionCube(x, y, z, -1);
el17cd 31:e681177037ef 220 }
el17cd 31:e681177037ef 221
el17cd 31:e681177037ef 222 void Renderer::drawHomeButtons() { //draw home screen buttons
el17cd 31:e681177037ef 223 lcd.drawRect(24, 6, 45, 10, FILL_WHITE);
el17cd 31:e681177037ef 224 lcd.printString("Play",35,1);
el17cd 31:e681177037ef 225 lcd.drawRect(24, 6, 45, 10, FILL_TRANSPARENT);
el17cd 31:e681177037ef 226
el17cd 31:e681177037ef 227 lcd.drawRect(24, 22, 45, 10, FILL_WHITE);
el17cd 31:e681177037ef 228 lcd.printString("Help",35,3);
el17cd 31:e681177037ef 229 lcd.drawRect(24, 22, 45, 10, FILL_TRANSPARENT);
el17cd 31:e681177037ef 230
el17cd 31:e681177037ef 231 lcd.drawRect(24, 38, 45, 10, FILL_WHITE);
el17cd 31:e681177037ef 232 lcd.printString("Quit",35,5);
el17cd 31:e681177037ef 233 lcd.drawRect(24, 38, 45, 10, FILL_TRANSPARENT);
el17cd 31:e681177037ef 234 }
el17cd 31:e681177037ef 235
el17cd 31:e681177037ef 236 void Renderer::drawSelectionCube(int x, int y, int z, int rotationSpeed) { //draw the seleciton cube
el17cd 31:e681177037ef 237 Face faces[6];
el17cd 31:e681177037ef 238 selectionCube.translate(x, y, z); //translate from origin to required position
el17cd 31:e681177037ef 239
el17cd 31:e681177037ef 240 for(int i = 0; i < 6; i++) {
el17cd 31:e681177037ef 241 faces[i] = selectionCube.getFace(i);
el17cd 31:e681177037ef 242 }
el17cd 31:e681177037ef 243 drawAllFaces(faces, 1, 0); //draw all faces of the cube
el17cd 31:e681177037ef 244 selectionCube.translate(-x, -y, -z); //translate back to origin
el17cd 31:e681177037ef 245 selectionCube.rotateX(-0.05*rotationSpeed); //rotate the cube
el17cd 31:e681177037ef 246 selectionCube.rotateY(-0.025*rotationSpeed);
el17cd 31:e681177037ef 247 selectionCube.rotateZ(0.04*rotationSpeed);
el17cd 31:e681177037ef 248 }
el17cd 31:e681177037ef 249
el17cd 31:e681177037ef 250 void Renderer::drawHelpScreen1() { //draw the first help screen
el17cd 31:e681177037ef 251 lcd.printString("Use the",20,0);
el17cd 31:e681177037ef 252 lcd.printString("joystick",17,1);
el17cd 31:e681177037ef 253 lcd.printString("to move",20,2);
el17cd 31:e681177037ef 254 lcd.printString("left and right.",0,3);
el17cd 39:41dcf1604fdf 255 lcd.printString("(Press B)",17,5);
el17cd 31:e681177037ef 256 }
el17cd 31:e681177037ef 257
el17cd 31:e681177037ef 258 void Renderer::drawHelpScreen2(){ //draw the second help screen
el17cd 31:e681177037ef 259 lcd.printString("Dodge the",15,0);
el17cd 31:e681177037ef 260 lcd.printString("cubes as they",3,1);
el17cd 31:e681177037ef 261 lcd.printString("move closer",10,2);
el17cd 31:e681177037ef 262 lcd.printString("to you",25,3);
el17cd 39:41dcf1604fdf 263 lcd.printString("(Press B)",17,5);
el17cd 31:e681177037ef 264 }
el17cd 31:e681177037ef 265
el17cd 31:e681177037ef 266 void Renderer::drawHelpScreen3(){ //draw the third help screen
el17cd 31:e681177037ef 267 lcd.printString("Even the",17,0);
el17cd 31:e681177037ef 268 lcd.printString("smallest",17,1);
el17cd 31:e681177037ef 269 lcd.printString("touch can",15,2);
el17cd 31:e681177037ef 270 lcd.printString("kill you",17,3);
el17cd 39:41dcf1604fdf 271 lcd.printString("(Press B)",17,5);
el17cd 31:e681177037ef 272 }
el17cd 31:e681177037ef 273
el17cd 31:e681177037ef 274 void Renderer::drawHelpScreen4(){ //draw the fourth help screen
el17cd 31:e681177037ef 275 lcd.printString("Good luck!",15,1);
el17cd 39:41dcf1604fdf 276 lcd.printString("(Press B)",17,5);
el17cd 31:e681177037ef 277 }