private static void hitTestCells(ArrayList nearByCells, Ball ball) { Cell currentCell; if (nearByCells.Count > 0) { for (int i = 0; i < nearByCells.Count; i++) { //("Cell around i: " + nearByCells[i].j + " cell.j: " + nearByCells[i].i + " currentCellI: " + currentCellI + " currentCellJ: " + currentCellJ + " x: " + x + " y " + y); currentCell = nearByCells[i] as Cell; if (ball.y - GameConfig.BALL_RADIUS <= (currentCell.y + GameConfig.BRICK_HEIGHT) && ball.y - GameConfig.BALL_RADIUS >= currentCell.y && ballInXTunnel(currentCell, ball) && ball.goingUp) //cell on top { currentCell.clearBrick(); ball.bounceOff(false); } else if ((ball.y + GameConfig.BALL_RADIUS) >= currentCell.y && (ball.y + GameConfig.BALL_RADIUS) <= (currentCell.y + GameConfig.BRICK_HEIGHT) && ballInXTunnel(currentCell, ball) && ball.goingDown) //cell on bottom { currentCell.clearBrick(); ball.bounceOff(false); } else if (ball.x - GameConfig.BALL_RADIUS <= (currentCell.x + GameConfig.BRICK_WIDTH) && ball.x - GameConfig.BALL_RADIUS >= currentCell.x && ballInYTunnel(currentCell, ball) && ball.goingLeft) //cell on left { currentCell.clearBrick(); ball.bounceOff(true); } else if ((ball.x + GameConfig.BALL_RADIUS) >= currentCell.x && (ball.x + GameConfig.BALL_RADIUS) <= (currentCell.x + GameConfig.BRICK_WIDTH) && ballInYTunnel(currentCell, ball) && ball.goingRight) //cell on right { currentCell.clearBrick(); ball.bounceOff(true); } } } }
private static void splitBall(Ball ball, int targetBallCount, FieldSimulation field) { int ballCopiesCount = targetBallCount - 1; //add more balls var resultBalls = new ArrayList {ball}; if (ballCopiesCount > 0) { for (int i = 0; i < ballCopiesCount; i++) { Ball ballCopy = getBallCopy(ball, field); resultBalls.Add(ballCopy); } } double currentAngle = ball.getCurrentAngle(); double newBallAngle = currentAngle%90; double leftover = newBallAngle - MINIMUM_ANGLE; double fraction = (leftover*2)/(targetBallCount + 1); for (int i = 0; i < resultBalls.Count; i++) { newBallAngle = currentAngle + leftover - (i + 1)*fraction; Console.WriteLine("newBallAngle: " + newBallAngle); (resultBalls[i] as Ball).setVector(newBallAngle); if (resultBalls[i] != ball) //add new balls to field { field.ballsManager.balls.Add(resultBalls[i]); } } }
/** * Checks for cells which are around and "hit tests" them by comparing coordinates. * @param ball * @param field */ public static void hitTest(Ball ball, FieldSimulation field, bool shieldProtection) { double currentCellI = Math.Floor(ball.x / GameConfig.BRICK_WIDTH); double currentCellJ = Math.Floor(ball.y / GameConfig.BRICK_HEIGHT); AroundCellData nearByCellsData = new AroundCellData(field.fieldCells.cells, (int)currentCellI, (int)currentCellJ, field); hitTestFieldSides(nearByCellsData, ball, field, shieldProtection); if (ball.stealthMode == false) //if stealth (during switching presets) -> don't hittest cells hitTestCells(nearByCellsData._cells, ball); }
public void createBall() { var ball = new Ball(_fieldLink); //NB! setting x & y after initiating. Because here, when passed to constructor ball x & y were rounded o_O ball.x = _fieldLink.bouncer.x + (_fieldLink.bouncer.currentWidth - GameConfig.BALL_SIZE)*0.7; //setting ball a lil bit to the right (because it's bouncing w angle) ball.y = _fieldLink.bouncer.y - GameConfig.BALL_SIZE - 1; Console.WriteLine((_fieldLink is NPCFieldSimulation ? " [NPC] " : " [Player] ") + "Ball at: " + ball.x + " : " + ball.y + " current tick: " + currentTick); _balls.Add(ball); }
private static Ball getBallCopy(Ball targetBall, FieldSimulation fs) { var copy = new Ball(fs); copy.x = targetBall.x; copy.y = targetBall.y; copy.stealthMode = targetBall.stealthMode; copy.dead = targetBall.dead; copy.setVector(targetBall.getCurrentAngle()); if (targetBall.wiggler.wiggling) //copy wiggling params { copy.goWiggle(); copy.wiggler.currentShiftX = targetBall.wiggler.currentShiftX; copy.wiggler.currentShiftY = targetBall.wiggler.currentShiftY; copy.wiggler.currentPerpendicularAngle = targetBall.wiggler.currentPerpendicularAngle; copy.wiggler.currentStepNumber = targetBall.wiggler.currentStepNumber; } return copy; }
private static void hitTestFieldSides(AroundCellData nearByCellsData, Ball ball, FieldSimulation field, bool shieldProtection) { if (ballAtCriticalZone(ball, field) && ball.goingDown) //currentCellJ > 25 so no unnecessary hittesting { field.saveCriticalHitForNPC(); if (ball.x > field.bouncer.x && ball.x < (field.bouncer.x + field.bouncer.currentWidth)) //hit panel { Console.WriteLine("[Hit panel]: " + field.bouncer.x + " : " + ball.x + " " + ball.y + " tick: " + field.ballsManager.currentTick + (field is NPCFieldSimulation ? " [NPC] " : " [Player] ")); ball.bounceOff(false, (ball.x - field.bouncer.x) / field.bouncer.currentWidth); if (ball.stealthMode) ball.goOutOfStealth(); } else if (shieldProtection) { Console.WriteLine("YYYY: shield protection on. tick: " + field.ballsManager.currentTick); if (ball.y + GameConfig.BALL_RADIUS >= field.bouncer.y + GameConfig.BOUNCER_WATER_DEPTH) { Console.WriteLine("YYYY: shield protection on and bounce off at: " + ball.y + " tick: " + field.ballsManager.currentTick); ball.bounceOff(false); if (ball.stealthMode) ball.goOutOfStealth(); } } else { Console.WriteLine("[Missed panel]: " + field.bouncer.x + " : " + ball.x + " " + ball.y + " tick: " + field.ballsManager.currentTick + (field is NPCFieldSimulation ? " [NPC] " : " [Player] ")); ball.die(); } if (!shieldProtection) ball.y = field.bouncer.y - GameConfig.BALL_RADIUS; //making sure ball will bounce off always from the same point } else if ((nearByCellsData.leftBorderNearby && ball.x - GameConfig.BALL_RADIUS <= 0 && ball.goingLeft) || (nearByCellsData.rightBorderNearby && (ball.x + GameConfig.BALL_RADIUS) >= GameConfig.FIELD_WIDTH_PX && ball.goingRight)) ball.bounceOff(true); else if (nearByCellsData.topBorderNearby && ball.y - GameConfig.BALL_RADIUS <= 0 && ball.goingUp) ball.bounceOff(false); }
public BallWiggler(Ball ballModel) { _ballLink = ballModel; }
private static bool ballInYTunnel(Cell cell, Ball ball) { return ball.y >= cell.y && ball.y <= (cell.y + GameConfig.BRICK_HEIGHT); }
private static bool ballInXTunnel(Cell cell, Ball ball) { return ball.x >= cell.x && ball.x <= (cell.x + GameConfig.BRICK_WIDTH); }
private static bool ballAtCriticalZone(Ball ball, FieldSimulation field) { return ball.y + GameConfig.BALL_RADIUS >= field.bouncer.y; }
private Point getTargetPoint() { var p = new Point(); if (_targetBall == null) { foreach (Ball b in _ballsManager.balls) { if (!b.dead) { _targetBall = b; break; } } } if (_targetBall != null) //there still might not be any ball in a weird scenarios { p.x = _targetBall.x - _currentX; p.y = _targetBall.y - _currentY; } return p; }
private void removeBall(Ball ball) { _balls.Remove(ball); Tracer.t("Removed ball. Left: " + _balls.Count + (_fieldLink is NPCFieldSimulation ? "[NPC]" : "[PLAYER]"), Relations.MISC_EVENTS); EventHandler handler = lostBall; handler(this, EventArgs.Empty); if (_balls.Count == 0) createBall(); }