public void Draw(int width, int height, double startx, double starty, double scale, ref byte[] pixels, bool isHilight, int light, bool texture, bool houses, bool wires, bool fogofwar, ref Tile[,] tiles) { if (texture) { int blocksWide = (int)(width / Math.Floor(scale)) + 2; //scale=1.0 to 16.0 int blocksHigh = (int)(height / Math.Floor(scale)) + 2; double adjustx = ((width / scale) - blocksWide) / 2; double adjusty = ((height / scale) - blocksHigh) / 2; startx += adjustx; starty += adjusty; int skipx = 0, skipy = 0; if (startx < 0) skipx = (int)-startx; if (starty < 0) skipy = (int)-starty; double shiftx = (startx - Math.Floor(startx)) * scale; double shifty = (starty - Math.Floor(starty)) * scale; int py, px; double lightR, lightG, lightB; // draw backgrounds int hellLevel = ((tilesHigh - 230) - groundLevel) / 6; //rounded hellLevel = hellLevel * 6 + groundLevel - 5; py = skipy * (int)scale; for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale; int bg = -1; int bgw = 128, bgh = 16; int v = sy; if (sy < groundLevel) { bg = -1; bgw = 16; } else if (sy == groundLevel) { bg = 0; v = sy - groundLevel; } else if (sy < rockLevel) { bg = 1; bgh = 96; v = sy - groundLevel; } else if (sy == rockLevel) { bg = 2; v = sy - rockLevel; } else if (sy < hellLevel) { bg = 3; bgh = 96; v = sy - rockLevel; } else if (sy == hellLevel) { bg = 4; v = sy - hellLevel; } else { bg = 5; bgh = 96; v = sy - hellLevel; } for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; int bgtile=0; if (bg >= 0) { int style = caveStyle[3]; if (sx <= caveX[0]) style = caveStyle[0]; else if (sx <= caveX[1]) style = caveStyle[1]; else if (sx <= caveX[2]) style = caveStyle[2]; if (style == 8 && jungleStyle != 0) style++; bgtile = backStyles[bg + style * 6]; if (bg > 3) bgtile += hellStyle; } Texture tex = Textures.GetBackground(bgtile); Tile tile = tiles[sx, sy]; if (light == 1) lightR = lightG = lightB = tile.light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (fogofwar && !tile.seen) lightR = lightG = lightB = 0.0; int u = (sx % (bgw / 16)) * 16; int vv = (v % (bgh / 16)) * 16; if (bg == -1) //sky vv = sy * (tex.height-16) / groundLevel; drawTexture(tex, 16, 16, vv * tex.width * 4 + u * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, 0); px += (int)scale; } py += (int)scale; } //draw walls Texture wallOutline = Textures.GetWallOutline(0); py = skipy * (int)scale - (int)(scale / 2); for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale - (int)(scale / 2); for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; Tile tile = tiles[sx, sy]; if (tile.wall > 0) { if (tile.wallu == -1) fixWall(sx, sy, ref tiles); Texture tex = Textures.GetWall(tile.wall); if (light == 1) lightR = lightG = lightB = tile.light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (fogofwar && !tile.seen) lightR = lightG = lightB = 0.0; drawTexture(tex, 32, 32, tile.wallv * tex.width * 4 * 2 + tile.wallu * 4 * 2, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.wallColor); Int16 blend = wallInfo[tile.wall].blend; if (sx > 0 && tiles[sx - 1, sy].wall > 0 && wallInfo[tiles[sx - 1, sy].wall].blend != blend) drawTexture(wallOutline, 2, 16, 0, pixels, (int)(px + (scale / 2) - shiftx), (int)(py + (scale / 2) - shifty), width, height, scale / 16.0, lightR, lightG, lightB, 0); double pad = 14.0 * scale / 16.0; if (sx < tilesWide - 2 && tiles[sx + 1, sy].wall > 0 && wallInfo[tiles[sx + 1, sy].wall].blend != blend) drawTexture(wallOutline, 2, 16, 14 * 4 * 2, pixels, (int)(px + pad + (scale / 2) - shiftx), (int)(py + (scale / 2) - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); if (sy > 0 && tiles[sx, sy - 1].wall > 0 && wallInfo[tiles[sx, sy - 1].wall].blend != blend) drawTexture(wallOutline, 16, 2, 0, pixels, (int)(px + (scale / 2) - shiftx), (int)(py + (scale / 2) - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); if (sy < tilesHigh - 2 && tiles[sx, sy + 1].wall > 0 && wallInfo[tiles[sx, sy + 1].wall].blend != blend) drawTexture(wallOutline, 16, 2, 14 * tex.width * 4 * 2, pixels, (int)(px + (scale / 2) - shiftx), (int)(py + pad + (scale / 2) - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); } px += (int)scale; } py += (int)scale; } List<Delayed> delayed = new List<Delayed>(); //draw tiles py = skipy * (int)scale; for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale; for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; Tile tile = tiles[sx, sy]; if (light == 1) lightR = lightG = lightB = tiles[sx, sy].light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (tile.inactive) { lightR *= 0.4; lightG *= 0.4; lightB *= 0.4; } if (isHilight && (!tile.isActive || !tileInfos[tile.type, tile.u, tile.v].isHilighting)) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (fogofwar && !tile.seen) lightR = lightG = lightB = 0.0; if (tile.isActive) { if (tile.u == -1 || tile.v == -1) fixTile(sx, sy, ref tiles); bool flip = false; // flip every other weed, coral, herb, banner, etc if (tile.type==3 || tile.type==13 || tile.type==20 || tile.type==24 || tile.type==49 || tile.type==50 || tile.type==52 || tile.type==61 || tile.type==62 || tile.type==71 || tile.type==73 || tile.type==73 || tile.type==74 || tile.type==81 || tile.type==82 || tile.type==84 || tile.type==91 || tile.type==92 || tile.type==93 || tile.type==110 || tile.type==113 || tile.type==115 || tile.type==135 || tile.type==141 || tile.type==165 || tile.type==201 || tile.type==205 || tile.type==227) flip=(sx&1)==1; int texw = 16; int texh = 16; int toppad = 0; if (tile.type == 4 && tileInfos[tiles[sx,sy-1].type].solid) //torch { toppad = 2; if (tileInfos[tiles[sx - 1, sy + 1].type].solid || tileInfos[tiles[sx + 1, sy + 1].type].solid) toppad = 4; } if (tile.type == 78 || tile.type == 85 || tile.type == 105 || tile.type==132 || tile.type == 133 || tile.type == 134 || tile.type==135 || tile.type == 139 || tile.type == 142 || tile.type == 143 || (tile.type == 178 && tile.v <= 36) || tile.type == 185 || tile.type == 186 || tile.type == 187 || tile.type == 207 || tile.type == 210 || tile.type == 215 || tile.type == 217 || tile.type == 218 || tile.type == 219 || tile.type == 220 || tile.type == 231 || tile.type == 233 || tile.type == 243 || tile.type == 244 || tile.type == 247 || tile.type == 254) //small items have a gap toppad = 2; if (tile.type == 33 || tile.type == 49 || tile.type == 174) //candles toppad = -4; //trees and weeds and others are 20 pixels tall if (tile.type == 3 || tile.type == 4 || tile.type == 5 || tile.type == 24 || tile.type == 33 || tile.type == 49 || tile.type == 61 || tile.type == 71 || tile.type == 110 || tile.type == 174 || tile.type == 201) texh = 20; // furniture and others are 18 pixels tall else if (tile.type == 14 || tile.type == 15 || tile.type == 16 || tile.type == 17 || tile.type == 18 || tile.type == 20 || tile.type == 21 || tile.type == 26 || tile.type == 27 || tile.type == 32 || tile.type == 69 || tile.type == 72 || tile.type == 77 || tile.type == 80 || tile.type == 124 || tile.type == 132 || tile.type == 135 || tile.type == 137 || tile.type == 138) texh = 18; if (tile.type == 52) //vines toppad -= 2; if (tile.type == 28 || tile.type == 238 ) //pots and purple flower toppad += 2; if (tile.type == 4 || tile.type == 5) //torch and tree texw = 20; if (tile.type == 73 || tile.type == 74 || tile.type == 113) //weeds { toppad -= 12; texh = 32; } if (tile.type == 227) //dye plants { texw = 32; texh = 38; if (tile.u == 238) //orange blood root toppad -= 6; else toppad -= 20; } if (tile.type == 184) //flowers { texw = 20; if (tile.v <= 36) toppad = 2; else if (tile.v <= 108) toppad = -2; } if (tile.type == 81) //coral { toppad -= 8; texw = 24; texh = 26; } if (tile.type == 72 && tile.u>=36) //mushroom drawMushroom(tile.u, tile.v, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); if (tile.type == 103) //bowl if (tile.u == 18) texw = 14; //solid tile adjacent to water if (tileInfos[tile.type].solid && (tiles[sx - 1, sy].liquid > 0 || tiles[sx + 1, sy].liquid > 0 || tiles[sx, sy - 1].liquid > 0 || tiles[sx, sy + 1].liquid > 0)) { byte waterMask = 0; double sideLevel = 0.0; int v = 4; int waterw = 16; int waterh = 16; double xpad = 0.0; double ypad = 0.0; //lrtb int mask = 0; Tile edge; if ((edge = tiles[sx - 1, sy]).liquid > 0) { sideLevel = edge.liquid; mask |= 8; //left if (edge.isLava) waterMask |= 2; else if (edge.isHoney) waterMask |= 4; else waterMask |= 1; } if ((edge = tiles[sx + 1, sy]).liquid > 0) { sideLevel = edge.liquid; mask |= 4; //right if (edge.isLava) waterMask |= 2; else if (edge.isHoney) waterMask |= 4; else waterMask |= 1; } if ((edge = tiles[sx, sy - 1]).liquid > 0) { mask |= 2; //top if (edge.isLava) waterMask |= 2; else if (edge.isHoney) waterMask |= 4; else waterMask |= 1; } else if (!edge.isActive || !tileInfos[edge.type].solid) v = 0; // water has a ripple if ((edge = tiles[sx, sy + 1]).liquid > 0) { if (edge.liquid > 240) mask |= 1; //bottom is high enough if (edge.isLava) waterMask |= 2; else if (edge.isHoney) waterMask |= 4; else waterMask |= 1; } if ((waterMask & 3) != 3) //don't render if water *and* lava { int waterid = 0; //water if ((waterMask & 2) == 2) //lava waterid = 1; if ((waterMask & 4) == 4) //honey waterid = 11; if ((mask & 0xc) != 0 && (mask & 1) == 1) //bottom and any side? mask |= 0xc; //same as both sides if (tile.half || tile.slope > 0) //half block or slope? mask |= 0x10; sideLevel = (256 - sideLevel) / 32.0; if (mask == 2) //hlrTb waterh = 4; else if (mask == 0x12) //HlrTb waterh = 12; else if ((mask & 0xf) == 1) //lrtB { waterh = 4; ypad = 12.0 * scale / 16.0; } else if ((mask & 2) != 2) //t { waterh = (int)(16 - sideLevel * 2); ypad = sideLevel * 2.0 * scale / 16.0; if ((mask & 0x1c) == 0x8) //!half Lr waterw = 4; if ((mask & 0x1c) == 0x4) //!half lR { waterw = 4; xpad = 12 * scale / 16.0; } } double alpha = waterid == 0 ? 0.5 : 0.85; Texture tex = Textures.GetLiquid(waterid); drawTextureAlpha(tex, waterw, waterh, v * tex.width * 4, pixels, (int)(px + xpad - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, 0, alpha); } } if (tile.type == 5 && tile.v >= 198 && tile.u >= 22) //tree leaves { Delayed delay = new Delayed(); delay.px = (int)(px - shiftx); delay.py = (int)(py - shifty); delay.sx = sx; delay.sy = sy; delayed.Add(delay); } else if (tile.type == 128) //armor { int au = tile.u % 100; //draw armor stand Texture tex = Textures.GetTile(tile.type); drawTexture(tex, texw, texh, tile.v * tex.width * 4 + au * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB,tile.color); //draw armor int armor = tile.u / 100; if (armor > 0) { Delayed delay = new Delayed(); delay.sx = sx; delay.sy = sy; delay.px = (int)(px - shiftx); delay.py = (int)(py - shifty); delayed.Add(delay); } } else if (tile.type == 237 && tile.u == 18 && tile.v == 0) //lihzahrd altar { Delayed delay = new Delayed(); delay.sx = sx; delay.sy = sy; delay.px = (int)(px - shiftx); delay.py = (int)(py - shifty); delayed.Add(delay); } else if (tile.type == 5) //tree { int wood = -1; int trunkx = sx; int trunky = sy; if (tile.u == 66 && tile.v <= 45) trunkx++; if (tile.u == 88 && tile.v >= 66 && tile.v <= 110) trunkx--; if (tile.u == 22 && tile.v >= 132) trunkx--; if (tile.u == 44 && tile.v >= 132) trunkx++; while (tiles[trunkx, trunky].isActive && tiles[trunkx, trunky].type == 5) trunky++; if (tiles[trunkx, trunky].isActive) { switch (tiles[trunkx, trunky].type) { case 23: //corrupted grass wood = 0; break; case 60: //jungle grass wood = 1; if (trunky > groundLevel) wood = 5; break; case 70: //mushroom grass wood = 6; break; case 109: //hallowed grass wood = 2; break; case 147: //snow if (styles[3] != 0) wood = 3; break; case 199: //flesh wood = 4; break; } } Texture tex; if (wood == -1) tex = Textures.GetTile(tile.type); else tex = Textures.GetWood(wood); drawTexture(tex, texw, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB,tile.color); } else if (tile.type == 80) //cactus { int cactus = -1; int cactusx = sx; int cactusy = sy; if (tile.u == 36) cactusx--; if (tile.u == 54) cactusx++; if (tile.u == 108) { if (tile.v == 18) cactusx--; else cactusx++; } while (cactusy<sy+20 && (!tiles[cactusx,cactusy].isActive || tiles[cactusx, cactusy].type == 80 || !tileInfos[tiles[cactusx,cactusy].type].solid)) cactusy++; if (tiles[cactusx, cactusy].isActive) { switch (tiles[cactusx, cactusy].type) { case 112: //ebonsand cactus = 1; break; case 116: //pearlsand cactus = 2; break; case 234: //crimsand cactus = 3; break; } } Texture tex; if (cactus == -1) tex = Textures.GetTile(tile.type); else tex = Textures.GetCactus(cactus); drawTexture(tex, texw, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } else { Texture tex; tex = Textures.GetTile(tile.type); double ypad = 0.0; if (tile.slope > 0) { if (tile.slope == 1) { for (int i = 0; i < 8; i++) { double xpad = ((double)i * 2.0) * scale / 16.0; ypad = ((double)toppad + (double)i * 2.0) * scale / 16.0; drawTexture(tex, 2, 14 - i * 2, tile.v * tex.width * 4 + (tile.u + i * 2) * 4, pixels, (int)(px + xpad - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } } if (tile.slope == 2) { for (int i = 0; i < 8; i++) { double xpad = (14 - (double)i * 2.0) * scale / 16.0; ypad = ((double)toppad + (double)i * 2.0) * scale / 16.0; drawTexture(tex, 2, 14 - i * 2, tile.v * tex.width * 4 + (tile.u + 14 - i * 2) * 4, pixels, (int)(px + xpad - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } } ypad = ((double)toppad + 14.0) * scale / 16.0; drawTexture(tex, 16, 2, (tile.v + 14) * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } else { //non-platform solid tile next to a half tile if (!tile.half && tile.type != 19 && tileInfos[tile.type].solid && sx>0 && sx<tilesWide-2 && (tiles[sx - 1, sy].half || tiles[sx + 1, sy].half)) { if (tiles[sx - 1, sy].half && tiles[sx + 1, sy].half) //both sides { ypad = ((double)toppad + 8.0) * scale / 16.0; drawTexture(tex, texw, 8, (tile.v + 8) * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); ypad = (double)toppad * scale / 16.0; drawTexture(tex, 16, 8, 126 * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } else { ypad = ((double)toppad + 8.0) * scale / 16.0; drawTexture(tex, texw, 8, (tile.v + 8) * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); if (tiles[sx - 1, sy].half) //left side { double xpad = 4 * scale / 16.0; ypad = (double)toppad * scale / 16.0; drawTexture(tex, texw - 4, texh, tile.v * tex.width * 4 + (tile.u + 4) * 4, pixels, (int)(px + xpad - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); drawTexture(tex, 4, 8, 126 * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } else //right side { ypad = (double)toppad * scale / 16.0; drawTexture(tex, texw - 4, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); double xpad = 12 * scale / 16.0; drawTexture(tex, 4, 8, 138 * 4, pixels, (int)(px + xpad - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } } } else { //half block on top of an empty space if (tile.half && (!tiles[sx, sy + 1].isActive || !tileInfos[tiles[sx, sy + 1].type].solid || tiles[sx, sy + 1].half)) { ypad = ((double)toppad + 8.0) * scale / 16.0; if (tile.type == 19) //platform { drawTexture(tex, texw, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } else { drawTexture(tex, texw, texh - 12, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); ypad = ((double)toppad + 12.0) * scale / 16.0; drawTexture(tex, texw, 4, 66 * tex.width * 4 + 144 * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, tile.color); } } else { byte col = tile.color; // use grass shader? if (col > 0 && col < 13 && (tile.type == 0 || tile.type == 2 || tile.type == 5 || tile.type == 23 || tile.type == 59 || tile.type == 60 || tile.type == 70 || tile.type == 109 || tile.type == 199)) col += 27; ypad = ((double)toppad + (tile.half ? 8.0 : 0.0)) * scale / 16.0; if (flip) drawTextureFlip(tex, texw - 1, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, col); else drawTexture(tex, texw, texh - (tile.half ? 8 : 0), tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, col); } } } } } // draw liquid if (tile.liquid > 0 && (!tile.isActive || !tileInfos[tile.type].solid)) { int waterLevel = (int)((255 - tile.liquid) / 16.0); int waterid = 0; if (tile.isLava) waterid = 1; if (tile.isHoney) waterid = 11; double alpha = waterid == 0 ? 0.5 : 0.85; int waterh = 16 - waterLevel; int v = 0; double ypad = waterLevel * scale / 16.0; //water above, no ripple if (tiles[sx, sy - 1].liquid > 32 || (tiles[sx,sy-1].isActive && tileInfos[tiles[sx,sy-1].type].solid)) v = 4; Texture tex = Textures.GetLiquid(waterid); drawTextureAlpha(tex, 16, waterh, v * tex.width * 4, pixels, (int)(px - shiftx), (int)(py + ypad - shifty), width, height, scale / 16.0, lightR, lightG, lightB, 0, alpha); } if (wires && tile.actuator) { Texture tex = Textures.GetActuator(0); drawTexture(tex, 16, 16, 0, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, 0); } // draw wires if necessary if (wires && tile.hasRedWire) drawRedWire(sx, sy, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); if (wires && tile.hasGreenWire) drawGreenWire(sx, sy, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); if (wires && tile.hasBlueWire) drawBlueWire(sx, sy, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); px += (int)scale; } py += (int)scale; } //draw delayed blocks foreach (Delayed delay in delayed) { Texture tex; Tile tile = tiles[delay.sx, delay.sy]; int texw = 16, texh = 16; if (light == 1) lightR = lightG = lightB = tiles[delay.sx, delay.sy].light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight && !tileInfos[tile.type, tile.u, tile.v].isHilighting) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (fogofwar && !tile.seen) lightR = lightG = lightB = 0.0; if (tile.type == 128) //armor { double dy = 8.0; int au = tile.u % 100; int armor = tile.u / 100; switch (tile.v) { case 0: //head tex = Textures.GetArmorHead(armor); texw = 40; texh = 36; dy = 12.0 * scale / 16.0; break; case 18: //body tex = Textures.GetArmorBody(armor); texw = 40; texh = 54; dy = 28.0 * scale / 16.0; break; default: //legs tex = Textures.GetArmorLegs(armor); texw = 40; texh = 54; dy = 44.0 * scale / 16.0; break; } if (au >= 36) //reverse drawTexture(tex, texw, texh, 0, pixels, (int)(delay.px - 4.0 * scale / 16.0), (int)(delay.py - dy), width, height, scale / 16.0, lightR, lightG, lightB, 0); else drawTextureFlip(tex, texw, texh, 0, pixels, (int)(delay.px - 4 * scale / 16.0), (int)(delay.py - dy), width, height, scale / 16.0, lightR, lightG, lightB, 0); } else if (tile.type == 5) //tree leaves { drawLeaves(tile.u, tile.v, delay.sx, delay.sy, pixels, delay.px, delay.py, width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); } else if (tile.type == 237) //lihzahrd altar { tex = Textures.GetTile(tile.type); drawTexture(tex, texw, texh, 0, pixels, delay.px, delay.py, width, height, scale / 16.0, lightR, lightG, lightB, 0); } } double minx = skipx + startx; double maxx = minx + blocksWide; double miny = skipy + starty; double maxy = miny + blocksHigh; // draw npcs at sx,sy foreach (NPC npc in npcs) { if (npc.sprite != 0 && (npc.x / 16) >= minx && (npc.x / 16) < maxx && (npc.y / 16) >= miny && (npc.y / 16) < maxy) //npc on screen { Tile t = tiles[(int)(npc.x / 16), (int)(npc.y / 16)]; if (light == 1) lightR = lightG = lightB = t.light; else if (light == 2) { lightR = t.lightR; lightG = t.lightG; lightB = t.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } Texture tex = Textures.GetNPC(npc.sprite); px = (int)(skipx + npc.x / 16 - (int)startx) * (int)scale - (int)(scale / 4); py = (int)(skipy + npc.y / 16 - (int)starty) * (int)scale - (int)(scale / 4); drawTexture(tex, tex.width, 56, 0, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); } if (houses && npc.num != 0) { //calc home x and y int hx = npc.homeX; int hy = npc.homeY - 1; while (!tiles[hx, hy].isActive || !tileInfos[tiles[hx, hy].type].solid) { hy--; if (hy < 10) break; } hy++; if (hx >= minx && hx < maxx && hy >= miny && hy < maxy) //banner on screen { Tile t = tiles[hx, hy]; if (light == 1) lightR = lightG = lightB = t.light; else if (light == 2) { lightR = t.lightR; lightG = t.lightG; lightB = t.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } int dy = 18; if (tiles[hx, hy - 1].type == 19) //platform dy -= 8; px = (int)(skipx + hx - (int)startx) * (int)scale + (int)(scale / 2); py = (int)(skipy + hy - (int)starty) * (int)scale + (int)(dy * scale / 16); Texture tex = Textures.GetBanner(1); //house banner int npx = (int)(px - tex.width * scale / 32.0); int npy = (int)(py - tex.height * scale / 32.0); drawTexture(tex, 32, 40, 0, pixels, (int)(npx - shiftx), (int)(npy - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); tex = Textures.GetNPCHead(npc.num); npx = (int)(px - tex.width * scale / 32.0); npy = (int)(py - tex.height * scale / 32.0); drawTexture(tex, tex.width, tex.height, 0, pixels, (int)(npx - shiftx), (int)(npy - shifty), width, height, scale / 16.0, lightR, lightG, lightB,0); } } } } else { for (int y = 0; y < height; y++) { int bofs = y * width * 4; int sy = (int)(y / scale + starty); for (int x = 0; x < width; x++) { int sx = (int)(x / scale + startx); UInt32 c = 0xffffff; if (sx >= 0 && sx < tilesWide && sy >= 0 && sy < tilesHigh) { Tile tile = tiles[sx, sy]; if (sy < groundLevel) c = skyColor; else if (sy < rockLevel) c = earthColor; else { //fade between rockColor and hellColor... double alpha = (double)(sy - rockLevel) / (double)(tilesHigh - rockLevel); c = alphaBlend(rockColor, hellColor, alpha); } if (tile.wall > 0) { c = wallInfo[tile.wall].color; } if (tile.isActive) { c = tileInfos[tile.type, tile.u, tile.v].color; if (tile.inactive) c = alphaBlend(c, 0x000000, 0.4); if (isHilight && tileInfos[tile.type, tile.u, tile.v].isHilighting) c = alphaBlend(c, 0xff88ff, 0.9); } if (tile.liquid > 0) c = alphaBlend(c, tile.isLava ? lavaColor : tile.isHoney ? honeyColor : waterColor, 0.5); if (light == 1) c = alphaBlend(0, c, tile.light); else if (light == 2) { uint r, g, b; r = (uint)((c >> 16) * tile.lightR); g = (uint)(((c >> 8) & 0xff) * tile.lightG); b = (uint)((c & 0xff) * tile.lightB); c = (r << 16) | (g << 8) | b; } if (isHilight && (!tile.isActive || !tileInfos[tile.type, tile.u, tile.v].isHilighting)) c = alphaBlend(0, c, 0.3); if (fogofwar && !tile.seen) c = 0; } pixels[bofs++] = (byte)(c & 0xff); pixels[bofs++] = (byte)((c >> 8) & 0xff); pixels[bofs++] = (byte)((c >> 16) & 0xff); pixels[bofs++] = 0xff; } } } }
private void ResizeMap() { for (int y = 0; y < tilesHigh; y++) { Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() { serverText.Text = ((int)((float)y * 100.0 / (float)tilesHigh)) + "% - Allocating tiles"; })); for (int x = 0; x < tilesWide; x++) { if (tiles[x, y] == null) tiles[x, y] = new Tile(); } } if (tilesWide < Widest || tilesHigh < Highest) //free unused tiles { for (int y = 0; y < Highest; y++) { int start = tilesWide; if (y >= tilesHigh) start = 0; for (int x = start; x < Widest; x++) tiles[x, y] = null; } } }
private byte fixTile(int x, int y, ref Tile[,] tiles) { int t = -1, l = -1, r = -1, b = -1; int tl = -1, tr = -1, bl = -1, br = -1; byte c = tiles[x, y].type; Int16 u; int set = rand.Next(0, 3) * 2; if (x > 0) { if (tiles[x - 1, y].isActive) l = tiles[x - 1, y].type; if (y > 0) { if (tiles[x - 1, y - 1].isActive) tl = tiles[x - 1, y - 1].type; } if (y < tilesHigh - 1) { if (tiles[x - 1, y + 1].isActive) bl = tiles[x - 1, y + 1].type; } } if (x < tilesWide - 1) { if (tiles[x + 1, y].isActive) r = tiles[x + 1, y].type; if (y > 0) { if (tiles[x + 1, y - 1].isActive) tr = tiles[x + 1, y - 1].type; } if (y < tilesHigh - 1) { if (tiles[x + 1, y + 1].isActive) br = tiles[x + 1, y + 1].type; } } if (y > 0) if (tiles[x, y - 1].isActive) t = tiles[x, y - 1].type; if (y < tilesHigh - 1) if (tiles[x, y + 1].isActive) b = tiles[x, y + 1].type; int mask; if (c == 33 || c == 49) //candles { // these tiles don't have u/v, but are single tiles tiles[x, y].u = 0; tiles[x, y].v = 0; return 0; } if (c == 4) //torch { //check if left is moutable or right is mountable.. set to -1 if not u = 0; if (b < 0) //no bottom { if (l >= 0) u = 22; else u = 44; } tiles[x, y].u = u; tiles[x, y].v = 0; return 0; } if (c == 80) //cactus { fixCactus(x, y, t, b, l, r, bl, br, ref tiles); return 0; } if (c == 19) //wooden platform { // check if left is mountable or right is mountable.. set to -1 if not mask = 0; if (l == c) mask |= 8; if (r == c) mask |= 4; if (l == -1) mask |= 2; if (r == -1) mask |= 1; tiles[x, y].u = uvPlatforms[mask * 2]; tiles[x, y].v = uvPlatforms[mask * 2 + 1]; return 0; } mask = 0; //if tile is stone and next to stone, treat them as the same if (tileInfos[c].isStone) { if (t > -1 && tileInfos[t].isStone) mask |= 0x80000; if (b > -1 && tileInfos[b].isStone) mask |= 0x40000; if (l > -1 && tileInfos[l].isStone) mask |= 0x20000; if (r > -1 && tileInfos[r].isStone) mask |= 0x10000; if (tl > -1 && tileInfos[tl].isStone) mask |= 0x880; if (tr > -1 && tileInfos[tr].isStone) mask |= 0x440; if (bl > -1 && tileInfos[bl].isStone) mask |= 0x220; if (br > -1 && tileInfos[br].isStone) mask |= 0x110; } //if tile blends with current tile, treat as if it were current tile if (t > -1 && (t == c || (tileInfos[t].blend == c && (fixTile(x, y - 1, ref tiles) & 4) == 4))) mask |= 0x80000; if (b > -1 && (b == c || (tileInfos[b].blend == c && (fixTile(x, y + 1, ref tiles) & 8) == 8))) mask |= 0x40000; if (l > -1 && (l == c || (tileInfos[l].blend == c && (fixTile(x - 1, y, ref tiles) & 1) == 1))) mask |= 0x20000; if (r > -1 && (r == c || (tileInfos[r].blend == c && (fixTile(x + 1, y, ref tiles) & 2) == 2))) mask |= 0x10000; if (tl > -1 && (tileInfos[tl].blend == c || tl == c)) mask |= 0x880; if (tr > -1 && (tileInfos[tr].blend == c || tr == c)) mask |= 0x440; if (bl > -1 && (tileInfos[bl].blend == c || bl == c)) mask |= 0x220; if (br > -1 && (tileInfos[br].blend == c || br == c)) mask |= 0x110; //if current tile can blend, set up the blend rules. Int16 blend = tileInfos[c].blend; if (blend > -1) { if (t == blend) mask |= 0x88000; if (b == blend) mask |= 0x44000; if (l == blend) mask |= 0x22000; if (r == blend) mask |= 0x11000; if (tl == blend) mask |= 0x808; if (tr == blend) mask |= 0x404; if (bl == blend) mask |= 0x202; if (br == blend) mask |= 0x101; } //set up merge rules if (tileInfos[c].canMerge) { if (t > -1 && tileInfos[t].canMerge) mask |= 0x80000; if (b > -1 && tileInfos[b].canMerge) mask |= 0x40000; if (l > -1 && tileInfos[l].canMerge) mask |= 0x20000; if (r > -1 && tileInfos[r].canMerge) mask |= 0x10000; if (tl > -1 && tileInfos[tl].canMerge) mask |= 0x880; if (tr > -1 && tileInfos[tr].canMerge) mask |= 0x440; if (bl > -1 && tileInfos[bl].canMerge) mask |= 0x220; if (br > -1 && tileInfos[br].canMerge) mask |= 0x110; } if (c == 32 && b == 23) mask |= 0x40000; //corrupted vines above corrupted grass if (c == 69 && b == 60) mask |= 0x40000; //jungle thorn above jungle grass if (c == 51) //cobwebs blend with everything { if (t > -1) mask |= 0x80000; if (b > -1) mask |= 0x40000; if (l > -1) mask |= 0x20000; if (r > -1) mask |= 0x10000; if (tl > -1) mask |= 0x880; if (tr > -1) mask |= 0x440; if (bl > -1) mask |= 0x220; if (br > -1) mask |= 0x110; } if (tileInfos[c].isGrass) //do grasses { foreach (UVRule rule in grassRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].u = rule.uvs[set]; tiles[x, y].v = rule.uvs[set + 1]; return rule.blend; } } } if (tileInfos[c].blend > -1 && !tileInfos[c].isGrass) //do blend-onlys { foreach (UVRule rule in blendRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].u = rule.uvs[set]; tiles[x, y].v = rule.uvs[set + 1]; return rule.blend; } } } if (tileInfos[c].blend > -1) //do blend and unmatched grasses { foreach (UVRule rule in blendGrassRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].u = rule.uvs[set]; tiles[x, y].v = rule.uvs[set + 1]; return rule.blend; } } } // no match, delete blends if (tileInfos[c].isGrass) //with grasses, blends are equal mask &= 0xf0f00; else mask = ((mask & 0xf0000) ^ ((mask & 0xf000) << 4)) | ((mask & 0xf0) << 4); foreach (UVRule rule in uvRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].u = rule.uvs[set]; tiles[x, y].v = rule.uvs[set + 1]; return rule.blend; } } //should be impossible to get here. return 0; }
private void fixWall(int x, int y, ref Tile[,] tiles) { byte t = 0, l = 0, r = 0, b = 0; byte c = tiles[x, y].wall; int set = rand.Next(0, 3) * 2; if (x > 0) l = tiles[x - 1, y].wall; if (x < tilesWide - 1) r = tiles[x + 1, y].wall; if (y > 0) t = tiles[x, y - 1].wall; if (y < tilesHigh - 1) b = tiles[x, y + 1].wall; //we don't actually care what the wall texture is, we just care if there's a wall or not. int mask = 0; if (t > 0) mask |= 0x80000; if (b > 0) mask |= 0x40000; if (l > 0) mask |= 0x20000; if (r > 0) mask |= 0x10000; if (x % 3 == 1 && y % 3 == 1) mask |= 0x300; else if (x % 3 == 0 && y % 3 == 0) mask |= 0xc00; else if (x % 3 == 2 && y % 3 == 1) mask |= 0x500; else if (x % 3 == 1 && y % 3 == 2) mask |= 0xa00; else mask |= 0xf00; foreach (UVRule rule in uvRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].wallu = rule.uvs[set]; tiles[x, y].wallv = rule.uvs[set + 1]; return; } } //again, impossible to be here. }
private int findCorruptGrass(int x, int y, ref Tile[,] tiles) { for (int i = 0; i < 100; i++) { Tile tile = tiles[x, y + i]; if (tile.type == 2) //normal grass { int s = treeStyle[3]; for (int j = 0; j < 3; j++) if (x <= treeX[j]) { s = treeStyle[j]; break; } if (s == 0) return 0; return s + 5; } if (tile.type == 23) //corrupt grass return 1; if (tile.type == 60) //jungle grass { if (y > groundLevel) return 13; if (styles[2] == 1) return 11; return 2; } if (tile.type == 109) //hallowed grass return 3; if (tile.type == 147) //snow block { if (styles[3] == 0) return 12; return 4; } if (tile.type == 70) //mushroom grass return 14; if (tile.type == 199) //flesh grass return 5; } return 0; }
private void fixCactus(int x, int y, int t, int b, int l, int r, int bl, int br, ref Tile[,] tiles) { //find the base of the cactus int basex = x; int basey = y; while (tiles[basex, basey].isActive && tiles[basex, basey].type == 80) { basey++; if (!tiles[basex, basey].isActive || tiles[basex, basey].type != 80) { if (tiles[basex - 1, basey].isActive && tiles[basex - 1, basey].type == 80 && tiles[basex - 1, basey - 1].isActive && tiles[basex - 1, basey - 1].type == 80 && basex >= x) basex--; if (tiles[basex + 1, basey].isActive && tiles[basex + 1, basey].type == 80 && tiles[basex + 1, basey - 1].isActive && tiles[basex + 1, basey - 1].type == 80 && basex <= x) basex++; } } Int16 mask = 0; if (x < basex) mask |= 1; if (x > basex) mask |= 2; if (br == 80) mask |= 4; if (bl == 80) mask |= 8; if (r == 80) mask |= 0x10; if (l == 80) mask |= 0x20; if (b == 80) mask |= 0x40; if (t == 80) mask |= 0x80; foreach (UVRule rule in cactusRules) { if ((mask & rule.mask) == rule.val) { tiles[x, y].u = rule.uvs[0]; tiles[x, y].v = rule.uvs[1]; return; } } }
private void drawRedWire(int sx, int sy, byte[] pixels, int px, int py, int w, int h, double zoom, double lightR, double lightG, double lightB, ref Tile[,] tiles) { int mask = 0; //udlr if (sx < tilesWide - 1 && tiles[sx + 1, sy].hasRedWire) mask |= 1; //right if (sx > 0 && tiles[sx - 1, sy].hasRedWire) mask |= 2; //left if (sy < tilesHigh - 1 && tiles[sx, sy + 1].hasRedWire) mask |= 4; //down if (sy > 0 && tiles[sx, sy - 1].hasRedWire) mask |= 8; //up Texture tex = Textures.GetWire(0); drawTexture(tex, 16, 16, uvWires[mask * 2 + 1] * tex.width * 4 + uvWires[mask * 2] * 4, pixels, px, py, w, h, zoom, lightR, lightG, lightB,0); }
private void drawLeaves(int u, int v, int sx, int sy, byte[] pixels, int px, int py, int w, int h, double zoom, double lightR, double lightG, double lightB, ref Tile[,] tiles) { if (u < 22 || v < 198) return; //not a leaf int variant = 0; if (v == 220) variant = 1; else if (v == 242) variant = 2; Texture tex; int leafType; switch (u) { case 22: //tree top leafType = findCorruptGrass(sx, sy, ref tiles); tex = Textures.GetTreeTops(leafType); if (leafType == 3) //hallowed { variant += (sx % 3) * 3; drawTexture(tex, 80, 140, variant * 82 * 4, pixels, px - (int)(30 * zoom), py - (int)(124 * zoom), w, h, zoom, lightR, lightG, lightB,0); } else if (leafType == 2 || leafType==11 || leafType==13) //jungle drawTexture(tex, 114, 96, variant * 116 * 4, pixels, px - (int)(46 * zoom), py - (int)(80 * zoom), w, h, zoom, lightR, lightG, lightB,0); else drawTexture(tex, 80, 80, variant * 82 * 4, pixels, px - (int)(30 * zoom), py - (int)(62 * zoom), w, h, zoom, lightR, lightG, lightB,0); break; case 44: //left branch leafType = findCorruptGrass(sx + 1, sy, ref tiles); tex = Textures.GetTreeBranches(leafType); if (leafType == 3) //hallowed variant += (sx % 3) * 3; drawTexture(tex, 40, 40, variant * 42 * tex.width * 4, pixels, px - (int)(22 * zoom), py - (int)(12 * zoom), w, h, zoom, lightR, lightG, lightB,0); break; case 66: //right branch leafType = findCorruptGrass(sx - 1, sy, ref tiles); tex = Textures.GetTreeBranches(leafType); if (leafType == 3) //hallowed variant += (sx % 3) * 3; drawTexture(tex, 40, 40, variant * 42 * tex.width * 4 + 42 * 4, pixels, px, py - (int)(12 * zoom), w, h, zoom, lightR, lightG, lightB,0); break; } }
public void Draw(int width, int height, double startx, double starty, double scale, ref byte[] pixels, bool isHilight, int light, bool texture, bool houses, bool wires, ref Tile[,] tiles) { if (texture) { int blocksWide = (int)(width / Math.Floor(scale)) + 2; //scale=1.0 to 16.0 int blocksHigh = (int)(height / Math.Floor(scale)) + 2; double adjustx = ((width / scale) - blocksWide) / 2; double adjusty = ((height / scale) - blocksHigh) / 2; startx += adjustx; starty += adjusty; int skipx = 0, skipy = 0; if (startx < 0) skipx = (int)-startx; if (starty < 0) skipy = (int)-starty; double shiftx = (startx - Math.Floor(startx)) * scale; double shifty = (starty - Math.Floor(starty)) * scale; int py, px; double lightR, lightG, lightB; // draw backgrounds int hellLevel = ((tilesHigh - 230) - groundLevel) / 6; //rounded hellLevel = hellLevel * 6 + groundLevel - 5; py = skipy * (int)scale; for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale; int bg = 0; int bgw = 16, bgh = 16; int v = sy; if (sy < groundLevel) bg = 0; else if (sy == groundLevel) { bg = 1; bgw = 96; v = sy - groundLevel; } else if (sy < rockLevel) { bg = 2; bgw = 96; bgh = 96; v = sy - groundLevel; } else if (sy == rockLevel) { bg = 4; bgw = 96; v = sy - rockLevel; } else if (sy < hellLevel) { bg = 3; bgw = 96; bgh = 96; v = sy - rockLevel; } else if (sy == hellLevel) { bg = 6; bgw = 96; v = sy - hellLevel; } else { bg = 5; bgw = 96; bgh = 96; v = sy - hellLevel; } Texture tex = Textures.GetBackground(bg); for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; Tile tile = tiles[sx, sy]; if (light == 1) lightR = lightG = lightB = tile.light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } int u = (sx % (bgw / 16)) * 16; int vv = (v % (bgh / 16)) * 16; if (bg == 0) //sky vv = sy * tex.height / groundLevel; drawTexture(tex, 16, 16, vv * tex.width * 4 + u * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); px += (int)scale; } py += (int)scale; } //draw walls py = skipy * (int)scale - (int)(scale / 2); for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale - (int)(scale / 2); for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; Tile tile = tiles[sx, sy]; if (tile.wall > 0) { if (tile.wallu == -1) fixWall(sx, sy, ref tiles); Texture tex = Textures.GetWall(tile.wall); if (light == 1) lightR = lightG = lightB = tile.light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } drawTexture(tex, 32, 32, tile.wallv * tex.width * 4 * 2 + tile.wallu * 4 * 2, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); } px += (int)scale; } py += (int)scale; } List<Delayed> delayed = new List<Delayed>(); //draw tiles py = skipy * (int)scale; for (int y = skipy; y < blocksHigh; y++) { int sy = (int)(y + starty); px = skipx * (int)scale; for (int x = skipx; x < blocksWide; x++) { int sx = (int)(x + startx); if (sx < 0 || sx >= tilesWide || sy < 0 || sy >= tilesHigh) continue; Tile tile = tiles[sx, sy]; if (light == 1) lightR = lightG = lightB = tiles[sx, sy].light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight && (!tile.isActive || !tileInfos[tile.type, tile.u, tile.v].isHilighting)) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (tile.isActive) { if (tile.u == -1 || tile.v == -1) fixTile(sx, sy, ref tiles); int texw = 16; int texh = 16; if (tile.type == 5) //tree texw = 20; if (tile.type == 72) //mushroom drawMushroom(tile.u, tile.v, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); if (tile.type == 103) //bowl if (tile.u == 18) texw = 14; if (tile.type == 5 && tile.v >= 198 && tile.u >= 22) //tree leaves { Delayed delay = new Delayed(); delay.px = (int)(px - shiftx); delay.py = (int)(py - shifty); delay.sx = sx; delay.sy = sy; delayed.Add(delay); } else if (tile.type == 128) //armor { int au = tile.u % 100; //draw armor stand Texture tex = Textures.GetTile(tile.type); drawTexture(tex, texw, texh, tile.v * tex.width * 4 + au * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); //draw armor int armor = tile.u / 100; if (armor > 0) { Delayed delay = new Delayed(); delay.sx = sx; delay.sy = sy; delay.px = (int)(px - shiftx); delay.py = (int)(py - shifty); delayed.Add(delay); } } else { Texture tex = Textures.GetTile(tile.type); drawTexture(tex, texw, texh, tile.v * tex.width * 4 + tile.u * 4, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); } } // draw liquid if (tile.liquid > 0) { UInt32 c = tile.isLava ? lavaColor : waterColor; uint r = (uint)((c >> 16) * lightR); uint g = (uint)(((c >> 8) & 0xff) * lightG); uint b = (uint)((c & 0xff) * lightB); c = (r << 16) | (g << 8) | b; drawOverlay(c, tile.isLava ? 0.85 : 0.5, tile.liquid, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0); } // draw wires if necessary if (wires && tile.hasWire) { drawWire(sx, sy, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); } px += (int)scale; } py += (int)scale; } //draw delayed blocks foreach (Delayed delay in delayed) { Texture tex; Tile tile = tiles[delay.sx, delay.sy]; int texw = 16, texh = 16; if (light == 1) lightR = lightG = lightB = tiles[delay.sx, delay.sy].light; else if (light == 2) { lightR = tile.lightR; lightG = tile.lightG; lightB = tile.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight && !tileInfos[tile.type, tile.u, tile.v].isHilighting) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } if (tile.type == 128) //armor { int dy = 8; int au = tile.u % 100; int armor = tile.u / 100; switch (tile.v) { case 0: //head tex = Textures.GetArmorHead(armor); texw = 40; texh = 36; dy = 12; break; case 18: //body tex = Textures.GetArmorBody(armor); texw = 40; texh = 54; dy = 28; break; default: //legs tex = Textures.GetArmorLegs(armor); texw = 40; texh = 54; dy = 44; break; } if (au >= 36) //reverse drawTexture(tex, texw, texh, 0, pixels, delay.px - 4, delay.py - dy, width, height, scale / 16.0, lightR, lightG, lightB); else drawTextureFlip(tex, texw, texh, 0, pixels, delay.px - 4, delay.py - dy, width, height, scale / 16.0, lightR, lightG, lightB); } else if (tile.type == 5) //tree leaves { drawLeaves(tile.u, tile.v, delay.sx, delay.sy, pixels, delay.px, delay.py, width, height, scale / 16.0, lightR, lightG, lightB, ref tiles); } } double minx = skipx + startx; double maxx = minx + blocksWide; double miny = skipy + starty; double maxy = miny + blocksHigh; // draw npcs at sx,sy foreach (NPC npc in npcs) { if (npc.sprite != 0 && (npc.x / 16) >= minx && (npc.x / 16) < maxx && (npc.y / 16) >= miny && (npc.y / 16) < maxy) //npc on screen { Tile t = tiles[(int)(npc.x / 16), (int)(npc.y / 16)]; if (light == 1) lightR = lightG = lightB = t.light; else if (light == 2) { lightR = t.lightR; lightG = t.lightG; lightB = t.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } Texture tex = Textures.GetNPC(npc.sprite); px = (int)(skipx + npc.x / 16 - (int)startx) * (int)scale - (int)(scale / 4); py = (int)(skipy + npc.y / 16 - (int)starty) * (int)scale - (int)(scale / 4); drawTexture(tex, 40, 56, 0, pixels, (int)(px - shiftx), (int)(py - shifty), width, height, scale / 16.0, lightR, lightG, lightB); } if (houses && npc.num != 0) { //calc home x and y int hx = npc.homeX; int hy = npc.homeY - 1; while (!tiles[hx, hy].isActive || !tileInfos[tiles[hx, hy].type].solid) { hy--; if (hy < 10) break; } hy++; if (hx >= minx && hx < maxx && hy >= miny && hy < maxy) //banner on screen { Tile t = tiles[hx, hy]; if (light == 1) lightR = lightG = lightB = t.light; else if (light == 2) { lightR = t.lightR; lightG = t.lightG; lightB = t.lightB; } else lightR = lightG = lightB = 1.0; if (isHilight) { lightR *= 0.3; lightG *= 0.3; lightB *= 0.3; } int dy = 18; if (tiles[hx, hy - 1].type == 19) //platform dy -= 8; px = (int)(skipx + hx - (int)startx) * (int)scale + (int)(scale / 2); py = (int)(skipy + hy - (int)starty) * (int)scale + (int)(dy * scale / 16); Texture tex = Textures.GetBanner(1); //house banner int npx = (int)(px - tex.width * scale / 32.0); int npy = (int)(py - tex.height * scale / 32.0); drawTexture(tex, 32, 40, 0, pixels, (int)(npx - shiftx), (int)(npy - shifty), width, height, scale / 16.0, lightR, lightG, lightB); tex = Textures.GetNPCHead(npc.num); npx = (int)(px - tex.width * scale / 32.0); npy = (int)(py - tex.height * scale / 32.0); drawTexture(tex, tex.width, tex.height, 0, pixels, (int)(npx - shiftx), (int)(npy - shifty), width, height, scale / 16.0, lightR, lightG, lightB); } } } } else { for (int y = 0; y < height; y++) { int bofs = y * width * 4; int sy = (int)(y / scale + starty); for (int x = 0; x < width; x++) { int sx = (int)(x / scale + startx); UInt32 c = 0xffffff; if (sx >= 0 && sx < tilesWide && sy >= 0 && sy < tilesHigh) { Tile tile = tiles[sx, sy]; if (sy < groundLevel) c = skyColor; else if (sy < rockLevel) c = earthColor; else { //fade between rockColor and hellColor... double alpha = (double)(sy - rockLevel) / (double)(tilesHigh - rockLevel); c = alphaBlend(rockColor, hellColor, alpha); } if (tile.wall > 0) { c = wallInfo[tile.wall].color; } if (tile.isActive) { c = tileInfos[tile.type, tile.u, tile.v].color; if (isHilight && tileInfos[tile.type, tile.u, tile.v].isHilighting) c = alphaBlend(c, 0xff88ff, 0.9); } if (tile.liquid > 0) c = alphaBlend(c, tile.isLava ? lavaColor : waterColor, 0.5); if (light == 1) c = alphaBlend(0, c, tile.light); else if (light == 2) { uint r, g, b; r = (uint)((c >> 16) * tile.lightR); g = (uint)(((c >> 8) & 0xff) * tile.lightG); b = (uint)((c & 0xff) * tile.lightB); c = (r << 16) | (g << 8) | b; } if (isHilight && (!tile.isActive || !tileInfos[tile.type, tile.u, tile.v].isHilighting)) c = alphaBlend(0, c, 0.3); } pixels[bofs++] = (byte)(c & 0xff); pixels[bofs++] = (byte)((c >> 8) & 0xff); pixels[bofs++] = (byte)((c >> 16) & 0xff); pixels[bofs++] = 0xff; } } } }
private void fixWall(int x, int y, ref Tile[,] tiles) { byte t = 0, l = 0, r = 0, b = 0; byte tl = 0, tr = 0, bl = 0, br = 0; byte c = tiles[x, y].wall; int set = rand.Next(0, 3) * 2; if (x > 0) { l = tiles[x - 1, y].wall; if (y > 0) tl = tiles[x - 1, y - 1].wall; if (y < tilesHigh - 1) bl = tiles[x - 1, y + 1].wall; } if (x < tilesWide - 1) { r = tiles[x + 1, y].wall; if (y > 0) tr = tiles[x + 1, y - 1].wall; if (y < tilesHigh - 1) br = tiles[x + 1, y + 1].wall; } if (y > 0) t = tiles[x, y - 1].wall; if (y < tilesHigh - 1) b = tiles[x, y + 1].wall; int mask = 0; if (t == c) mask |= 0x80000; if (b == c) mask |= 0x40000; if (l == c) mask |= 0x20000; if (r == c) mask |= 0x10000; if (tl == c) mask |= 0x880; if (tr == c) mask |= 0x440; if (bl == c) mask |= 0x220; if (br == c) mask |= 0x110; foreach (UVRule rule in uvRules[mask >> 16]) { if ((mask & rule.mask) == rule.val) { tiles[x, y].wallu = rule.uvs[set]; tiles[x, y].wallv = rule.uvs[set + 1]; return; } } //again, impossible to be here. }
private int findCorruptGrass(int x, int y, ref Tile[,] tiles) { for (int i = 0; i < 100; i++) { Tile tile = tiles[x, y + i]; if (tile.type == 2) //normal grass return 0; if (tile.type == 23) //corrupt grass return 1; if (tile.type == 60) //jungle grass return 2; if (tile.type == 109) //hallowed grass return 3; if (tile.type == 147) //snow block return 4; } return 0; }