├── .gitattributes ├── Player.pde ├── README.md ├── Search2048.pde ├── State.pde └── Tile.pde /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Player.pde: -------------------------------------------------------------------------------- 1 | class Player { 2 | long fitness; 3 | boolean dead = false; 4 | int score =0; 5 | 6 | //--------------------------------------------------------------------------------------------------------------------------------------------------------- 7 | ArrayList tiles = new ArrayList(); 8 | ArrayList emptyPositions = new ArrayList(); 9 | PVector moveDirection = new PVector(); 10 | boolean movingTheTiles =false; 11 | boolean tileMoved = false; 12 | 13 | float[][] startingPositions = new float[2][3]; 14 | 15 | State start; 16 | 17 | 18 | //constructor 19 | 20 | Player() { 21 | fillEmptyPositions(); 22 | 23 | //add 2 tiles 24 | 25 | addNewTile(); 26 | addNewTile(); 27 | 28 | startingPositions[0][0] = tiles.get(0).position.x; 29 | startingPositions[0][1] = tiles.get(0).position.y; 30 | startingPositions[0][2] = tiles.get(0).value; 31 | 32 | 33 | startingPositions[1][0] = tiles.get(1).position.x; 34 | startingPositions[1][1] = tiles.get(1).position.y; 35 | startingPositions[1][2] = tiles.get(1).value; 36 | } 37 | 38 | Player(boolean isReplay) { 39 | 40 | fillEmptyPositions(); 41 | } 42 | 43 | 44 | void setTilesFromHistory() { 45 | 46 | tiles.add(new Tile(floor(startingPositions[0][0]), floor(startingPositions[0][1]))); 47 | tiles.get(0).value = floor(startingPositions[0][2]); 48 | 49 | tiles.add(new Tile(floor(startingPositions[1][0]), floor(startingPositions[1][1]))); 50 | tiles.get(1).value = floor(startingPositions[1][2]); 51 | 52 | 53 | for ( int i = 0; i< emptyPositions.size(); i ++) { 54 | if (compareVec(emptyPositions.get(i), tiles.get(0).position) || compareVec(emptyPositions.get(i), tiles.get(1).position)) { 55 | emptyPositions.remove(i); 56 | i--; 57 | } 58 | } 59 | } 60 | 61 | 62 | //--------------------------------------------------------------------------------------------------------------------------------------------------------- 63 | void show() { 64 | //show the ones which are going to die first so it looks like they slip under the other ones 65 | for (int i = 0; i< tiles.size(); i++) { 66 | if (tiles.get(i).deathOnImpact) { 67 | tiles.get(i).show(); 68 | } 69 | } 70 | 71 | for (int i = 0; i< tiles.size(); i++) { 72 | if (!tiles.get(i).deathOnImpact) { 73 | tiles.get(i).show(); 74 | } 75 | } 76 | } 77 | //--------------------------------------------------------------------------------------------------------------------------------------------------------- 78 | void move() { 79 | if (movingTheTiles) { 80 | for (int i = 0; i< tiles.size(); i++) { 81 | tiles.get(i).move(moveSpeed); 82 | } 83 | if (doneMoving()) { 84 | for (int i = 0; i< tiles.size(); i++) {//kill collided tiles 85 | if (tiles.get(i).deathOnImpact) { 86 | tiles.remove(i); 87 | i--; 88 | } 89 | } 90 | 91 | movingTheTiles =false; 92 | setEmptyPositions(); 93 | addNewTileNotRandom(); 94 | } 95 | } 96 | } 97 | 98 | boolean doneMoving() { 99 | 100 | for (int i = 0; i< tiles.size(); i++) { 101 | if (tiles.get(i).moving) { 102 | return false; 103 | } 104 | } 105 | 106 | return true; 107 | } 108 | 109 | //--------------------------------------------------------------------------------------------------------------------------------------------------------- 110 | void update() { 111 | move(); 112 | } 113 | //------------------------------------------------------------------------------------------------------------------------------------- 114 | 115 | void fillEmptyPositions() { 116 | for (int i = 0; i< 4; i++) { 117 | for (int j =0; j< 4; j++) { 118 | emptyPositions.add(new PVector(i, j)); 119 | } 120 | } 121 | } 122 | //--------------------------------- 123 | 124 | void setEmptyPositions() { 125 | emptyPositions.clear(); 126 | for (int i = 0; i< 4; i++) { 127 | for (int j =0; j< 4; j++) { 128 | if (getValue(i, j) ==0) { 129 | emptyPositions.add(new PVector(i, j)); 130 | } 131 | } 132 | } 133 | } 134 | 135 | //---------------------------------------------------------------------------------------------------------------------------------------------------- 136 | 137 | 138 | 139 | void moveTiles() { 140 | tileMoved = false; 141 | for (int i = 0; i< tiles.size(); i++) { 142 | tiles.get(i).alreadyIncreased = false; 143 | } 144 | ArrayList sortingOrder = new ArrayList(); 145 | PVector sortingVec = new PVector(); 146 | boolean vert = false;//is up or down 147 | if (moveDirection.x ==1) {//right 148 | sortingVec = new PVector(3, 0); 149 | vert = false; 150 | } else if (moveDirection.x ==-1) {//left 151 | sortingVec = new PVector(0, 0); 152 | vert = false; 153 | } else if (moveDirection.y ==1) {//down 154 | sortingVec = new PVector(0, 3); 155 | vert = true; 156 | } else if (moveDirection.y ==-1) {//right 157 | sortingVec = new PVector(0, 0); 158 | vert = true; 159 | } 160 | 161 | for (int i = 0; i< 4; i++) { 162 | for (int j = 0; j<4; j++) { 163 | PVector temp = new PVector(sortingVec.x, sortingVec.y); 164 | if (vert) { 165 | temp.x += j; 166 | } else { 167 | temp.y += j; 168 | } 169 | sortingOrder.add(temp); 170 | } 171 | sortingVec.sub(moveDirection); 172 | } 173 | 174 | for (int j = 0; j< sortingOrder.size(); j++) { 175 | for (int i = 0; i< tiles.size(); i++) { 176 | if (tiles.get(i).position.x == sortingOrder.get(j).x && tiles.get(i).position.y == sortingOrder.get(j).y) { 177 | PVector moveTo = new PVector(tiles.get(i).position.x + moveDirection.x, tiles.get(i).position.y + moveDirection.y); 178 | int valueOfMoveTo = getValue(floor(moveTo.x), floor(moveTo.y)); 179 | while (valueOfMoveTo == 0) { 180 | //tiles.get(i).position = new PVector(moveTo.x, moveTo.y); 181 | tiles.get(i).moveTo(moveTo); 182 | moveTo = new PVector(tiles.get(i).positionTo.x + moveDirection.x, tiles.get(i).positionTo.y + moveDirection.y); 183 | valueOfMoveTo = getValue(floor(moveTo.x), floor(moveTo.y)); 184 | tileMoved = true; 185 | } 186 | 187 | if (valueOfMoveTo == tiles.get(i).value) { 188 | //merge tiles 189 | Tile temp = getTile(floor(moveTo.x), floor(moveTo.y)); 190 | 191 | 192 | 193 | if (!temp.alreadyIncreased) { 194 | 195 | tiles.get(i).moveTo(moveTo); 196 | tiles.get(i).deathOnImpact = true; 197 | 198 | 199 | //tiles.remove(i); 200 | temp.alreadyIncreased = true; 201 | tiles.get(i).alreadyIncreased = true; 202 | temp.value *=2; 203 | score += temp.value; 204 | temp.setColour(); 205 | tileMoved = true; 206 | } 207 | } 208 | } 209 | } 210 | } 211 | if (tileMoved) { 212 | movingTheTiles = true; 213 | } 214 | } 215 | 216 | 217 | //------------------------------------------------------------------------------------------------------------------------------------ 218 | 219 | void addNewTile() { 220 | 221 | 222 | PVector temp = emptyPositions.remove(floor(random(emptyPositions.size()))); 223 | tiles.add(new Tile(floor(temp.x), floor(temp.y))); 224 | } 225 | 226 | 227 | void addNewTileNotRandom() { 228 | int notRandomNumber = score;// % 229 | for (int i = 0; i< tiles.size(); i++) { 230 | notRandomNumber += floor(tiles.get(i).position.x); 231 | notRandomNumber += floor(tiles.get(i).position.y); 232 | notRandomNumber += i; 233 | } 234 | 235 | int notRandomNumber2 = notRandomNumber % emptyPositions.size(); 236 | PVector temp = emptyPositions.remove(notRandomNumber2); 237 | tiles.add(new Tile(floor(temp.x), floor(temp.y))); 238 | 239 | if (notRandomNumber % 10 < 9) { 240 | tiles.get(tiles.size() -1).value = 2; 241 | } else { 242 | tiles.get(tiles.size() -1).value = 4; 243 | } 244 | 245 | tiles.get(tiles.size() -1).setColour(); 246 | } 247 | 248 | 249 | //-------------------------------------------------------------------------------------------------------------------------- 250 | int getValue(int x, int y) { 251 | if (x > 3 || x <0 || y>3 || y<0) { 252 | return -1; 253 | } 254 | for (int i = 0; i< tiles.size(); i++) { 255 | if (tiles.get(i).positionTo.x == x && tiles.get(i).positionTo.y ==y) { 256 | return tiles.get(i).value; 257 | } 258 | } 259 | return 0;//means that its free 260 | } 261 | 262 | 263 | //---------------------------------------------------------------------------------------------------------------------------------- 264 | Tile getTile(int x, int y) { 265 | for (int i = 0; i< tiles.size(); i++) { 266 | if (tiles.get(i).positionTo.x == x && tiles.get(i).positionTo.y ==y) { 267 | return tiles.get(i); 268 | } 269 | } 270 | 271 | return null; 272 | } 273 | 274 | 275 | //----------------------------------------------------------------------------------------------------------------------------------- 276 | void setStartState() { 277 | start = new State(); 278 | //clone tiles 279 | for (int i = 0; i< tiles.size(); i++) { 280 | start.tiles.add(tiles.get(i).clone()); 281 | } 282 | start.score = score; 283 | start.setEmptyPositions(); 284 | } 285 | 286 | //------------------------------------------------------------------------------------------------------------------------------------- 287 | //gets the best move by looking x number of moves into the future. 288 | void getMove() { 289 | setStartState(); 290 | start.getChildrenValues(0); 291 | switch(start.bestChild) { 292 | case 0 : 293 | moveDirection = new PVector(1, 0); 294 | break; 295 | case 1 : 296 | moveDirection = new PVector(-1, 0); 297 | break; 298 | case 2 : 299 | moveDirection = new PVector(0, 1); 300 | break; 301 | case 3 : 302 | moveDirection = new PVector(0, -1); 303 | break; 304 | 305 | 306 | } 307 | 308 | if(start.children[start.bestChild].value <= 0){ 309 | setup(); 310 | } 311 | } 312 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2048 AI 2 | -------------------------------------------------------------------------------- /Search2048.pde: -------------------------------------------------------------------------------- 1 | 2 | Player p; 3 | boolean released = true; 4 | boolean teleport = false; 5 | 6 | int maxDepth = 4; 7 | //this means that there is some information specific to the game to input here 8 | 9 | int pauseCounter = 100; 10 | int nextConnectionNo = 1000; 11 | int speed = 60; 12 | int moveSpeed = 60; 13 | 14 | 15 | int xoffset = 0; 16 | int yoffset = 0; 17 | 18 | void setup() { 19 | frameRate(60); 20 | size(850, 850); 21 | p = new Player(); 22 | } 23 | 24 | 25 | 26 | void draw() { 27 | background(187,173,160); 28 | fill(205,193,180); 29 | for(int i = 0 ; i< 4 ;i++){ 30 | for(int j =0; j< 4 ;j++){ 31 | rect(i*200 + (i+1) *10, j*200 + (j+1) *10, 200, 200); 32 | 33 | } 34 | 35 | 36 | } 37 | p.move(); 38 | p.show(); 39 | 40 | if(p.doneMoving()){ 41 | p.getMove(); 42 | p.moveTiles(); 43 | } 44 | } 45 | 46 | 47 | void keyPressed() { 48 | if (released) { 49 | switch(key) { 50 | case CODED: 51 | switch(keyCode) { 52 | case UP: 53 | if (p.doneMoving()) { 54 | p.moveDirection = new PVector(0, -1); 55 | p.moveTiles(); 56 | } 57 | break; 58 | case DOWN: 59 | if (p.doneMoving()) { 60 | p.moveDirection = new PVector(0, 1); 61 | p.moveTiles(); 62 | } 63 | break; 64 | case LEFT: 65 | if (p.doneMoving()) { 66 | p.moveDirection = new PVector(-1, 0); 67 | p.moveTiles(); 68 | } 69 | break; 70 | case RIGHT: 71 | if (p.doneMoving()) { 72 | p.moveDirection = new PVector(1, 0); 73 | p.moveTiles(); 74 | } 75 | break; 76 | } 77 | } 78 | released = false; 79 | } 80 | } 81 | 82 | void keyReleased(){ 83 | released = true; 84 | 85 | } 86 | 87 | boolean compareVec(PVector p1, PVector p2) { 88 | if (p1.x == p2.x && p1.y == p2.y) { 89 | return true; 90 | } 91 | return false; 92 | } -------------------------------------------------------------------------------- /State.pde: -------------------------------------------------------------------------------- 1 | class State { 2 | State[] children = new State[4]; 3 | float value = 0; 4 | int score = 0; 5 | 6 | ArrayList tiles = new ArrayList(); 7 | ArrayList emptyPositions = new ArrayList(); 8 | boolean differentFromParent = false; 9 | boolean dead =false; 10 | int bestChild =0; 11 | 12 | State() { 13 | } 14 | 15 | 16 | 17 | State clone() { 18 | State clone = new State(); 19 | //clone tiles 20 | for (int i = 0; i< tiles.size(); i++) { 21 | clone.tiles.add(tiles.get(i).clone()); 22 | } 23 | clone.score = score; 24 | clone.setEmptyPositions(); 25 | return clone; 26 | } 27 | 28 | void fillEmptyPositions() { 29 | for (int i = 0; i< 4; i++) { 30 | for (int j =0; j< 4; j++) { 31 | emptyPositions.add(new PVector(i, j)); 32 | } 33 | } 34 | } 35 | //--------------------------------- 36 | 37 | void setEmptyPositions() { 38 | emptyPositions.clear(); 39 | for (int i = 0; i< 4; i++) { 40 | for (int j =0; j< 4; j++) { 41 | if (getValue(i, j) ==0) { 42 | emptyPositions.add(new PVector(i, j)); 43 | } 44 | } 45 | } 46 | } 47 | 48 | 49 | void move(int x, int y) { 50 | PVector moveDirection = new PVector(x, y); 51 | differentFromParent = false; 52 | for (int i = 0; i< tiles.size(); i++) { 53 | tiles.get(i).alreadyIncreased = false; 54 | } 55 | ArrayList sortingOrder = new ArrayList(); 56 | PVector sortingVec = new PVector(); 57 | boolean vert = false;//is up or down 58 | if (x ==1) {//right 59 | sortingVec = new PVector(3, 0); 60 | vert = false; 61 | } else if (x ==-1) {//left 62 | sortingVec = new PVector(0, 0); 63 | vert = false; 64 | } else if (y ==1) {//down 65 | sortingVec = new PVector(0, 3); 66 | vert = true; 67 | } else if (y ==-1) {//right 68 | sortingVec = new PVector(0, 0); 69 | vert = true; 70 | } 71 | for (int i = 0; i< 4; i++) { 72 | for (int j = 0; j<4; j++) { 73 | PVector temp = new PVector(sortingVec.x, sortingVec.y); 74 | if (vert) { 75 | temp.x += j; 76 | } else { 77 | temp.y += j; 78 | } 79 | sortingOrder.add(temp); 80 | } 81 | sortingVec.sub(moveDirection); 82 | } 83 | 84 | for (int j = 0; j< sortingOrder.size(); j++) { 85 | for (int i = 0; i< tiles.size(); i++) { 86 | if (tiles.get(i).position.x == sortingOrder.get(j).x && tiles.get(i).position.y == sortingOrder.get(j).y) { 87 | PVector moveTo = new PVector(tiles.get(i).position.x + moveDirection.x, tiles.get(i).position.y + moveDirection.y); 88 | int valueOfMoveTo = getValue(floor(moveTo.x), floor(moveTo.y)); 89 | while (valueOfMoveTo == 0) { 90 | //tiles.get(i).position = new PVector(moveTo.x, moveTo.y); 91 | tiles.get(i).moveToNow(moveTo); 92 | moveTo = new PVector(tiles.get(i).position.x + moveDirection.x, tiles.get(i).position.y + moveDirection.y); 93 | valueOfMoveTo = getValue(floor(moveTo.x), floor(moveTo.y)); 94 | differentFromParent = true; 95 | } 96 | 97 | if (valueOfMoveTo == tiles.get(i).value) { 98 | //merge tiles 99 | Tile temp = getTile(floor(moveTo.x), floor(moveTo.y)); 100 | 101 | 102 | 103 | if (!temp.alreadyIncreased) { 104 | 105 | tiles.get(i).moveToNow(moveTo); 106 | tiles.get(i).deathOnImpact = true; 107 | 108 | 109 | //tiles.remove(i); 110 | temp.alreadyIncreased = true; 111 | tiles.get(i).alreadyIncreased = true; 112 | temp.value *=2; 113 | score += temp.value; 114 | temp.setColour(); 115 | differentFromParent = true; 116 | } 117 | } 118 | } 119 | } 120 | } 121 | if (differentFromParent) { 122 | 123 | addNewTileNotRandom(); 124 | } else { 125 | dead= true; 126 | } 127 | } 128 | //------------------------------------------------------------------------------------------------------------------------------------ 129 | 130 | void addNewTile() { 131 | 132 | 133 | PVector temp = emptyPositions.remove(floor(random(emptyPositions.size()))); 134 | tiles.add(new Tile(floor(temp.x), floor(temp.y))); 135 | } 136 | 137 | 138 | void addNewTileNotRandom() { 139 | 140 | setEmptyPositions(); 141 | if (emptyPositions.size() ==0) { 142 | dead = true; 143 | return; 144 | } 145 | int notRandomNumber = score;// % 146 | for (int i = 0; i< tiles.size(); i++) { 147 | notRandomNumber += floor(tiles.get(i).position.x); 148 | notRandomNumber += floor(tiles.get(i).position.y); 149 | notRandomNumber += i; 150 | } 151 | 152 | int notRandomNumber2 = notRandomNumber % emptyPositions.size(); 153 | PVector temp = emptyPositions.remove(notRandomNumber2); 154 | tiles.add(new Tile(floor(temp.x), floor(temp.y))); 155 | 156 | if (notRandomNumber % 10 < 9) { 157 | tiles.get(tiles.size() -1).value = 2; 158 | } else { 159 | tiles.get(tiles.size() -1).value = 4; 160 | } 161 | 162 | tiles.get(tiles.size() -1).setColour(); 163 | } 164 | 165 | 166 | //-------------------------------------------------------------------------------------------------------------------------- 167 | int getValue(int x, int y) { 168 | if (x > 3 || x <0 || y>3 || y<0) { 169 | return -1; 170 | } 171 | for (int i = 0; i< tiles.size(); i++) { 172 | if (tiles.get(i).position.x == x && tiles.get(i).position.y ==y) { 173 | return tiles.get(i).value; 174 | } 175 | } 176 | return 0;//means that its free 177 | } 178 | 179 | 180 | //---------------------------------------------------------------------------------------------------------------------------------- 181 | Tile getTile(int x, int y) { 182 | for (int i = 0; i< tiles.size(); i++) { 183 | if (tiles.get(i).position.x == x && tiles.get(i).position.y ==y) { 184 | return tiles.get(i); 185 | } 186 | } 187 | return null; 188 | } 189 | //------------------------------------------------------------------------------------------------------------------------------------- 190 | 191 | void setValue() { 192 | if (dead) { 193 | value =0; 194 | return; 195 | } 196 | value = 0; 197 | value += score; 198 | value += random(1000); 199 | 200 | //for (int i = 0; i< tiles.size(); i++) { 201 | // for (int j = 0; j< tiles.size(); j++) { 202 | // if (i != j && dist(tiles.get(i).position.x, tiles.get(i).position.y, tiles.get(j).position.x, tiles.get(j).position.y) <= 1) { 203 | // //tiles whihc are adjacent are good 204 | // if (tiles.get(i).value == tiles.get(j).value) { 205 | // value += tiles.get(i).value/2; 206 | // } 207 | 208 | // //have adjacent things be close in value 209 | // if (tiles.get(i).value == tiles.get(j).value/2) { 210 | // value += tiles.get(i).value/4; 211 | // } else if (tiles.get(j).value == tiles.get(i).value/2) { 212 | // value += tiles.get(j).value/4; 213 | // } 214 | // } 215 | // } 216 | //} 217 | ////value empty spaces 218 | //value*= (1.0+(emptyPositions.size() * 0.05)); 219 | //int max = 0 ; 220 | //int maxTile = 0; 221 | //for (int i = 0; i< tiles.size(); i++) { 222 | // if (tiles.get(i).value > max) { 223 | // max = tiles.get(i).value; 224 | // maxTile = i; 225 | // } 226 | //} 227 | 228 | //if (tiles.get(maxTile).position.y ==0) { 229 | // value *= 1.5; 230 | // if (tiles.get(maxTile).position.x ==0) { 231 | // value *=3; 232 | // max = 0; 233 | // int secondBest = 0; 234 | // for (int i = 0; i< tiles.size(); i++) { 235 | // if (i != maxTile && tiles.get(i).value > max) { 236 | // max = tiles.get(i).value; 237 | // secondBest = i; 238 | // } 239 | // } 240 | // if (tiles.get(secondBest).position.y ==0 && tiles.get(secondBest).position.x ==1) { 241 | // value *= 1.2; 242 | // max = 0; 243 | // int thirdBest = 0; 244 | // for (int i = 0; i< tiles.size(); i++) { 245 | // if (i != maxTile && i != secondBest && tiles.get(i).value > max) { 246 | // max = tiles.get(i).value; 247 | // thirdBest = i; 248 | // } 249 | // } 250 | // if (tiles.get(thirdBest).position.y ==0 && tiles.get(thirdBest).position.x ==2) { 251 | // value *= 1.2; 252 | // } 253 | // } 254 | // } 255 | //} 256 | } 257 | 258 | 259 | //--------------------------------------------------------------------------------------------------------------------------------------- 260 | 261 | float getChildrenValues(int depth) { 262 | if (depth >= maxDepth) { 263 | setValue(); 264 | return value; 265 | } 266 | 267 | for (int i = 0; i< 4; i++) { 268 | children[i] = clone(); 269 | } 270 | 271 | children[0].move(1, 0); 272 | 273 | children[1].move(-1, 0); 274 | 275 | children[2].move(0, 1); 276 | 277 | children[3].move(0, -1); 278 | 279 | for (int i = 0; i< 4; i++) { 280 | if (!children[i].differentFromParent) { 281 | children[i].dead = true; 282 | } 283 | } 284 | 285 | 286 | 287 | float max = 0; 288 | int maxChild =0; 289 | for (int i = 0; i < 4; i++) { 290 | if (!children[i].dead) { 291 | float temp = children[i].getChildrenValues(depth+1) ; 292 | 293 | // if (i == 2) { 294 | // temp *= 0.5; 295 | // } 296 | if (depth ==0) { 297 | println("Child " + i + "gets a value of " + temp); 298 | } 299 | if (temp > max) { 300 | max = temp; 301 | maxChild = i; 302 | } 303 | } 304 | } 305 | 306 | 307 | bestChild = maxChild; 308 | 309 | setValue(); 310 | if(max < value){ 311 | return value; 312 | } 313 | return max; 314 | } 315 | } -------------------------------------------------------------------------------- /Tile.pde: -------------------------------------------------------------------------------- 1 | class Tile { 2 | int value; 3 | PVector position; 4 | PVector pixelPos;//top left 5 | boolean alreadyIncreased = false; 6 | boolean moving = false; 7 | 8 | color colour; 9 | PVector positionTo; 10 | PVector pixelPosTo; 11 | 12 | 13 | boolean deathOnImpact =false; 14 | 15 | Tile(int x, int y) { 16 | if (random(1)< 0.1) { 17 | value = 4; 18 | } else { 19 | value =2; 20 | } 21 | 22 | position = new PVector(x, y); 23 | positionTo = new PVector(x, y); 24 | 25 | pixelPos = new PVector(xoffset +x*200 + (x+1) *10, yoffset + y*200 + (y+1) *10); 26 | pixelPosTo = new PVector(xoffset + x*200 + (x+1) *10, yoffset + y*200 + (y+1) *10); 27 | 28 | setColour(); 29 | } 30 | 31 | //--------------------------------------------------------------------------------------------------------- 32 | 33 | 34 | void show() { 35 | if (!deathOnImpact || moving) { 36 | fill(colour); 37 | noStroke(); 38 | rect(pixelPos.x, pixelPos.y, 200, 200); 39 | if (value < 8) { 40 | fill(40); 41 | } else { 42 | fill(240); 43 | } 44 | textAlign(CENTER, CENTER); 45 | textSize(50); 46 | text(value, pixelPos.x+100, pixelPos.y+100); 47 | } 48 | } 49 | 50 | //------------------------------------------------------------------------------------------------------------ 51 | void moveTo(PVector to) { 52 | positionTo = new PVector(to.x, to.y); 53 | pixelPosTo = new PVector(xoffset +to.x*200 + (to.x+1) *10, yoffset +to.y*200 + (to.y+1) *10); 54 | moving = true; 55 | } 56 | void moveToNow(PVector to) { 57 | position = new PVector(to.x, to.y); 58 | pixelPos = new PVector(xoffset +to.x*200 + (to.x+1) *10, yoffset +to.y*200 + (to.y+1) *10); 59 | } 60 | //------------------------------------------------------------------------------------------------------------ 61 | void move(int speed) { 62 | if (moving) { 63 | if (!teleport && dist(pixelPos.x, pixelPos.y, pixelPosTo.x, pixelPosTo.y) > speed) { 64 | PVector MoveDirection = new PVector(positionTo.x - position.x, positionTo.y - position.y); 65 | MoveDirection.normalize(); 66 | MoveDirection.mult(speed); 67 | pixelPos.add(MoveDirection); 68 | } else { 69 | moving = false; 70 | pixelPos = new PVector(pixelPosTo.x, pixelPosTo.y); 71 | position = new PVector(positionTo.x, positionTo.y); 72 | } 73 | } 74 | } 75 | 76 | //------------------------------------------------------------------------------------------------------------ 77 | 78 | 79 | void setColour() { 80 | switch(value) { 81 | case 2: 82 | colour = color(238, 228, 218); 83 | break; 84 | case 4: 85 | colour = color(237, 224, 200); 86 | break; 87 | case 8: 88 | colour = color(242, 177, 121); 89 | break; 90 | case 16: 91 | colour = color(2345, 149, 99); 92 | break; 93 | case 32: 94 | colour = color(246, 124, 95); 95 | break; 96 | case 64: 97 | colour = color(246, 94, 59); 98 | break; 99 | case 128: 100 | colour = color(237, 207, 114); 101 | break; 102 | case 256: 103 | colour = color(237,204,97); 104 | break; 105 | case 512: 106 | colour = color(237,200,80); 107 | break; 108 | case 1024: 109 | colour = color(237,197,63); 110 | break; 111 | case 2048: 112 | colour = color(237,197,1); 113 | break; 114 | case 4096: 115 | colour = color(94,218,146); 116 | break; 117 | 118 | } 119 | } 120 | 121 | Tile clone() { 122 | Tile clone = new Tile(floor(position.x), floor(position.y)); 123 | clone.value = value; 124 | clone.setColour(); 125 | 126 | return clone; 127 | } 128 | } --------------------------------------------------------------------------------