public void bump(int x, int y, boolean canBreakBricks) { byte block = level.getBlock(x, y); if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BUMPABLE) > 0) { bumpInto(x, y - 1); level.setBlock(x, y, (byte) 4); // level.setBlockData(x, y, (byte) 4); if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_SPECIAL) > 0) { if (!mario.large) { addSprite(new Mushroom(this, x * 16 + 8, y * 16 + 8)); } else { addSprite(new FireFlower(this, x * 16 + 8, y * 16 + 8)); } } else { mario.getCoin(); coinsCollected++; // addSprite(new CoinAnim(x, y)); } } if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BREAKABLE) > 0) { bumpInto(x, y - 1); if (canBreakBricks) { level.setBlock(x, y, (byte) 0); } else { // level.setBlockData(x, y, (byte) 4); } } }
public void bumpInto(int x, int y) { byte block = level.getBlock(x, y); if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_PICKUPABLE) > 0) { mario.getCoin(); coinsCollected++; level.setBlock(x, y, (byte) 0); } for (Sprite sprite : sprites) { sprite.bumpCheck(x, y); } }
public void init() { Level.loadBehaviors(); Sprite.spriteContext = this; sprites.clear(); mario = new Mario(this); sprites.add(mario); startTime = 1; timeLeft = totalTime * 15; tick = 1; }
// Update internal level representation to what we get from the API. // includes some gap detection code public boolean setLevelScene(byte[][] data) { int HalfObsWidth = 11; int HalfObsHeight = 11; int MarioXInMap = (int) mario.x / 16; int MarioYInMap = (int) mario.y / 16; boolean gapAtLast = true; boolean gapAtSecondLast = true; int lastEventX = 0; int[] heights = new int[22]; for (int i = 0; i < heights.length; i++) heights[i] = 0; int gapBorderHeight = 0; int gapBorderMinusOneHeight = 0; int gapBorderMinusTwoHeight = 0; for (int y = MarioYInMap - HalfObsHeight, obsX = 0; y < MarioYInMap + HalfObsHeight; y++, obsX++) { for (int x = MarioXInMap - HalfObsWidth, obsY = 0; x < MarioXInMap + HalfObsWidth; x++, obsY++) { if (x >= 0 && x <= level.xExit && y >= 0 && y < level.height && obsX < data.length && obsY < data.length) { byte datum = data[obsX][obsY]; if (datum != 0 && datum != -10 && datum != 1 && obsY > lastEventX) { lastEventX = obsY; } if (datum != 0 && datum != 1) { if (heights[obsY] == 0) { heights[obsY] = y; } } // cannon detection: if there's a one-block long hill, it's a cannon! // i think this is not required anymore, because we get the cannon data straight from the // API. if (x == MarioXInMap + HalfObsWidth - 3 && datum != 0 && y > 5) { if (gapBorderMinusTwoHeight == 0) gapBorderMinusTwoHeight = y; } if (x == MarioXInMap + HalfObsWidth - 2 && datum != 0 && y > 5) { if (gapBorderMinusOneHeight == 0) gapBorderMinusOneHeight = y; gapAtSecondLast = false; } if (x == MarioXInMap + HalfObsWidth - 1 && datum != 0 && y > 5) { if (gapBorderHeight == 0) gapBorderHeight = y; gapAtLast = false; } if (datum != 1 && level.getBlock(x, y) != 14) level.setBlock(x, y, datum); } } } if (gapBorderHeight == gapBorderMinusTwoHeight && gapBorderMinusOneHeight < gapBorderHeight) { // found a cannon! // System.out.println("Got a cannon!"); level.setBlock(MarioXInMap + HalfObsWidth - 2, gapBorderMinusOneHeight, (byte) 14); } if (gapAtLast && !gapAtSecondLast) { // found a gap. int holeWidth = 3; // make the gap wider before we see the end to allow ample time for the // planner to jump over. for (int i = 0; i < holeWidth; i++) { for (int j = 0; j < 15; j++) { level.setBlock(MarioXInMap + HalfObsWidth + i, j, (byte) 0); } level.isGap[MarioXInMap + HalfObsWidth + i] = true; level.gapHeight[MarioXInMap + HalfObsWidth + i] = gapBorderMinusOneHeight; } for (int j = gapBorderMinusOneHeight; j < 16; j++) { level.setBlock(MarioXInMap + HalfObsWidth + holeWidth, gapBorderMinusOneHeight, (byte) 4); } return true; } return false; }
public void tick() { // advance the world state. directly from the original physics engine. timeLeft--; if (timeLeft == 0) { mario.die(); } xCamO = xCam; yCamO = yCam; if (startTime > 0) { startTime++; } float targetXCam = mario.x - 160; xCam = targetXCam; if (xCam < 0) xCam = 0; if (xCam > level.width * 16 - 320) xCam = level.width * 16 - 320; fireballsOnScreen = 0; for (Sprite sprite : sprites) { if (sprite != mario) { float xd = sprite.x - xCam; float yd = sprite.y - yCam; if (xd < -64 || xd > 320 + 64 || yd < -64 || yd > 240 + 64) { removeSprite(sprite); } else { if (sprite instanceof Fireball) { fireballsOnScreen++; } } } } if (paused) { for (Sprite sprite : sprites) { if (sprite == mario) { sprite.tick(); } else { sprite.tickNoMove(); } } } else { tick++; level.tick(); for (int x = (int) xCam / 16 - 1; x <= (int) (xCam + 320) / 16 + 1; x++) for (int y = (int) yCam / 16 - 1; y <= (int) (yCam + 240) / 16 + 1; y++) { int dir = 0; if (x * 16 + 8 > mario.x + 16) dir = -1; if (x * 16 + 8 < mario.x - 16) dir = 1; if (dir != 0) { byte b = level.getBlock(x, y); if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0) { if ((b % 16) / 4 == 3 && b / 16 == 0) { if ((tick - x * 2) % 100 == 0) { addSprite(new BulletBill(this, x * 16 + 8 + dir * 8, y * 16 + 15, dir)); } } } } } for (Sprite sprite : sprites) { sprite.tick(); } for (Sprite sprite : sprites) { sprite.collideCheck(); } // System.out.println("Sim Mario ya: " + mario.ya); for (Shell shell : shellsToCheck) { for (Sprite sprite : sprites) { if (sprite != shell && !shell.dead) { if (sprite.shellCollideCheck(shell)) { if (mario.carried == shell && !shell.dead) { mario.carried = null; shell.die(); } enemiesKilled++; } } } } shellsToCheck.clear(); for (Fireball fireball : fireballsToCheck) { for (Sprite sprite : sprites) { if (sprite != fireball && !fireball.dead) { if (sprite.fireballCollideCheck(fireball)) { fireball.die(); enemiesKilled++; } } } } fireballsToCheck.clear(); } sprites.addAll(0, spritesToAdd); sprites.removeAll(spritesToRemove); spritesToAdd.clear(); spritesToRemove.clear(); }