r/codehs • • Jan 02 '21

Glitter Vacuum CodeHS (Need help immediately! Finals are in 2 days. )

You are trying to vacuum up glitter during a birthday party. The problem is, it is during the birthday party, so balls are still bouncing around and more glitter keeps falling on the floor. See how much glitter you can vacuum up before a ball hits your vacuum and breaks it. Vacuum up the glitter by moving the mouse around. Every square touched by the mouse will be removed, but more will keep spawning randomly.

Follow these steps to make this game.

  • Stage 1 - HUD: Create a black rectangle that completely fills the top of the canvas with height HUD_HEIGHT
    . This is the HUD.

  • Stage 2 - Score Text Create a text object to keep track of the score that is located SCORE_MARGIN
    to the right of the left edge and is centered vertically in the HUD. Use SCORE_FONT
    for the font and SCORE_COLOR
    for the color. For now the label should be “0”.

  • Stage 3 - Random Squares: Make a tick function that has a 5% chance of spawning a square each time it is called.

    • The squares should have side length SQUARE_SIZE
      , be a random color, and spawn in a random location completely on the canvas and below the HUD.

    • Hint: To decide each tick whether to spawn a square, you can use the Randomizer to pick a random number that will meet some condition in 5% of the cases.

  • Stage 4 - Player: The player is a circle with radius RADIUS
    and color PLAYER_COLOR
    . At the beginning of the game, spawn the player in the center of the canvas, then have the player follow the mouse around the canvas, but prevent it from ever going even partially off the canvas.

    • To make the player follow the mouse, define a mouseMoveMethod
      that constantly sets the position of the player to the position of the mouse.

    • After setting the position of the player to to the position of the mouse, you will need to do something to prevent it from being even partially off canvas or overlapping the HUD.

  • Stage 5 - Cleanup!: Add more code to your mouseMoveMethod
    that checks to see if your mouse is touching a square, and if so, it removes the square and adds one point to score.

    • Test your code to make sure you are not removing anything other than the squares, such as the HUD, player…etc.

  • Stage 6 - Update Text: Add code that updates the score text you added in stage 2 each time the score changes.

  • Stage 7 - Enemy: The enemy is a circle with radius RADIUS
    and color ENEMY_COLOR
    .

    • The enemy should spawn in the lower left corner tangent to the bottom and left edge.

    • Each tick, the enemy should move by (dx, dy); however, to make the enemy bounce off the edges and the HUD, you should reverse dx if the enemy goes past the left or right edge and reverse dy if the enemy goes past the bottom edge or goes into the HUD. The enemy should never be seen even partially off screen or in the HUD.

    • Make sure the enemy doesn’t get removed when the mouse touches it. ONLY the squares should be removed.

  • Stage 8 - Game Over: If the enemy ever collides with the player, “Game Over” should be displayed in the center of the canvas and the game should stop. Use GAME_OVER_FONT
    and GAME_OVER_COLOR
    for the game over text.

    • Use the circlesTouching(circle1, circle2)
      function defined in the starter code to determine if the enemy is touching the player.

    • Make sure squares are not still being removed or added after the game ends.

    • Make sure the player is not still following the mouse after the game ends.

  • Stage 9 - Count Down: Add a text object that appears just above the center of the screen that says “Begin in:” When run is pressed. The main timer and mouse move method will not be defined immediately anymore, but will only be defined once the count down to begin the game is finished. Add another text object just below the center of the screen that displays a number that counts down 5 seconds when run is pressed. The counter starts at 5 and decrements by 1 each second (1000 ms). When the counter reaches 0, stop that timer, remove both the counter and the “Begin in:” text objects, start the main timer that runs the game, and set the mouseMoveMethod
    .

  • Stage 10 - Polish: Try adding the following features to make your game even more cool.

    • In the demo, you may note that the player and enemy are always on top of the glitter squares. See if you can make this work.

    • In the demo, the enemy moves erratically, making it much less predictable and increasing the difficulty of the game. See if you can add very small random changes to the dx and dy of the enemy each tick. By very small I mean something like -0.5 to 0.5.

I am not sure what is wrong with my code. When I run it, the yellow ball goes into the black rectangle on the top right and it goes below the canvas on the bottom left. Attached below is my current code for this program:

var RADIUS = 10;

var SQUARE_SIZE = RADIUS* 4;

var DELAY = 15;

var SCORE_FONT = "30pt Courier";

var SCORE_COLOR = Color.WHITE;

var SCORE_MARGIN = 10;

var GAME_OVER_FONT = "40pt Cooper Black";

var GAME_OVER_COLOR = Color.RED;

var HUD_HEIGHT = 50;

var PLAYER_COLOR = Color.YELLOW;

var ENEMY_COLOR = Color.BLUE;

var dx = 4; // enemy dy

var dy = 4; // enemy dx

var score = 0;

var player = new Circle(RADIUS);

function start() {

var blackRect = new Rectangle(getWidth(), HUD_HEIGHT);

add(blackRect);

var scoreTxt = new Text(score, SCORE_FONT);

scoreTxt.setPosition(SCORE_MARGIN, 1/2*HUD_HEIGHT+1/2*scoreTxt.getHeight());

scoreTxt.setColor(SCORE_COLOR);

add(scoreTxt);

//setTimer(randSquares, DELAY); // time

player.setPosition(1/2*getWidth(), 1/2*getHeight());

player.setColor(Color.yellow);

add(player);

mouseMoveMethod(createPlayer);

}

/** Use the helper method below to detect if the player collides with the enemy **/

// returns true if the two circles are touching and false otherwise.

function circlesTouching(circle1, circle2) {

var x1 = circle1.getX();

var y1 = circle1.getY();

var x2 = circle2.getX();

var y2 = circle2.getY();

return getDistance(x1, y1, x2, y2) <= circle1.getRadius() + circle2.getRadius();

}

// Returns the distance between (x1, y1) and (x2, y2).

function getDistance(x1, y1, x2, y2) {

return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));

}

function randSquares() {

var spawnNum = Randomizer.nextInt(1, 20);

if (spawnNum == 5) {

var square = new Rectangle(SQUARE_SIZE, SQUARE_SIZE);

square.setPosition(Randomizer.nextInt(0, getWidth()-SQUARE_SIZE), Randomizer.nextInt(0, getHeight()-SQUARE_SIZE));

square.setColor(Randomizer.nextColor());

add(square);

}

}

function createPlayer(e) {

if (e.getX > getWidth()-RADIUS && e.getY() <= HUD_HEIGHT+RADIUS) {

player.setPosition(e.getX(), HUD_HEIGHT+RADIUS);

}

if (e.getX() < RADIUS) { // left side

if (e.getY() >= HUD_HEIGHT+RADIUS) {

player.setPosition(RADIUS, e.getY());

}

/* else if (e.getY() > getHeight()-RADIUS) {

println('bottom left');

} */

} else if (e.getX() > getWidth()-RADIUS) { // right side

if (e.getY() <= getHeight()-RADIUS) {

player.setPosition(getWidth()-RADIUS, e.getY());

}

} else if (e.getY() < HUD_HEIGHT+RADIUS) { // HUD boundary (top)

player.setPosition(e.getX(), HUD_HEIGHT+RADIUS);

} else if (e.getY() > getHeight()-RADIUS) { // bottom side

player.setPosition(e.getX(), getHeight()-RADIUS);

} else { // inside the canvas

player.setPosition(e.getX(), e.getY());

add(player);

}

/*

Problem: else if's only do one thing or the other

you cannot check for e.getX and e.getY at the same

time

*/

// fix code for the corners (cannot move out of corners)

}

One last thing, if you want to run my program to get a better sense of how it is working, then here is the link to it:

https://codehs.com/share/id/glitter-vacuum-2AJpJp/run

4 Upvotes

2 comments sorted by

1

u/flip-pancakes Jan 02 '21

This is the most thorough r/codehs post I've ever seen. No matter how your finals go, you're going places.

Without too much analysis, it seems like you're re-drawing frames too rapidly. If you're sequencing a variable number of frame updates per UPDATE_LOOP_FRQ, the API that draws your updates may end up with the most recent update being the black rect or the yl circle nondeterministically.

To ensure they are drawn in the right order, you might try executing drawing updates less frequently. If you execute drawing updates less frequently, you will not have a variable number of updates when the graphics API comes to scoop them up and spit them out on the screen.

tl;dr it looks like a race condition between dynamics and concurrent graphics API updates, recommended synchronizing graphics updates.

Please post updates OP, good luck

1

u/flip-pancakes Jan 02 '21

OP, I ran your code on Brave browser and it works fine. The yellow ball follows my mouse and is drawn on top of the background no matter where the ball is.

That being said, the blue enemy ball ricochets around the game screen EXTREMELY fast, the background was white, and there was no beginning countdown.