• No results found

Assignment 9: Balls and Bumpers

N/A
N/A
Protected

Academic year: 2021

Share "Assignment 9: Balls and Bumpers"

Copied!
14
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

Algorithmic Thinking and Structured Programming (in Greenfoot)

© 2017 Renske Smetsers-Weeda & Sjaak Smetsers1

Contents

Introduction 1

Learning objectives 1

Instructions 1

Theory 2

9.1 Smooth movements . . . 2

9.2 The resolution of the world . . . 2

9.3 Vectors . . . 3

9.4 Getter methods . . . 3

9.5 Setter methods . . . 4

9.6 Colliding with a bumper . . . 4

9.7 Implementing how moving balls collide . . . 5

9.8 Collision with different masses . . . 5

Challenges 6 9.1 Getting started with Balls and Bumpers . . . 6

9.2 Changing the cell size . . . 6

9.3 Changing the resolution of the world . . . 6

9.4 Exploring the Vector class . . . 7

9.5 Setting up the Ball class . . . 7

9.6 The ball starts rolling . . . 7

9.7 Bounce back . . . 8

9.8 Adding bumpers . . . 8

9.9 Bounce off of bumpers . . . 9

9.10 Moving balls colliding . . . 9

9.11 Different sized balls . . . 9

9.12 Balls with different masses . . . 10

Reflection 11

1Licensed under the Creative Commons Attribution 4.0 license:https://creativecommons.org/licenses/by/4.0/

(2)

Saving and Handing in 12

(3)

Introduction

In the following challenges we will continue to give you less code and tips in advance. For the largest part, you will design and implement the scenario on your own.

In this assignment you will make a pinball ma- chine. In order to do that, you will simulate the movement of one or more balls in a two-dimensional space.

The simulation is in a Greenfoot world, so it it bounded (a ball can’t fall out of the world). A ball moving in a straight line will eventually hit one of the borders. After that, it will bounce back.

And what happens when there are more balls in- volved in the game, and one ball hits another? Or if there are other obstructions in the world where the

ball can bounce into? That makes it a bit more complicated!

The simulation will be as realistic as possible. To do this you will use and implement collision laws that you learned in Physics: the law of conservation of energy and the law of conservation of momen- tum.

Learning objectives

After completing this assignment, you will be able to:

• make a (2-dimensional) simulation for a real (3-dimensional) situation;

• use and apply formula’s from another subject (or field).

Instructions

For this assignment you will need:

• scenario ’BallWorldScenario9’: to be downloaded from the course website2.

Throughout the assignment you will also need to answer some questions. The following must be handed in:

• All flowcharts: use pencil and paper, or go to https://www.draw.io/;

• Your code

• The reflection sheet: complete and hand it in.

You must discuss all other answers with a programming partner. Jot down a short answer on (the assignment) paper.

2http://course.cs.ru.nl/greenfoot/

(4)

There are three types of challenges:

Recommended. Students who need more practice or with limited programming experience should complete all of these.

Mandatory. Everyone must complete these.

Excelling. More inquisitive tasks, designed for students who completed 2 star tasks and are ready for a bigger challenge.

Students who skip 1-star challenges should complete all 3-star challenges.

Theory

Theory 9.1: Smooth movements

To make the simulation realistic, the balls have to move smoothly over the screen. This isn’t possible in Mimi’s wereld (which exists only out of 12-by-12 cells), as you will see the ball (or actor) jump from one cell to the next. This results in jerking movements. To simulate smoother movements, the world needs to be made up of many more, smaller, cells.

Theory 9.2: The resolution of the world

The cell-size that we want to use for this simulation is 1-by-1. Every cell is made up of just one pixel.

As pictures are often more than one pixel, pictures will cover multiple cells. The following figure shows the difference between a world with a high and a low resolution.

Figure 1: World with a low resolution. Figure 2: World with a high resolution.

With a higher resolution, more cells are needed for the simulation. Mimi’s world, with just 12-by-12 cells is much too small for such a simulation. Possibly a 600-by-600 cell world would be more realistic.

Using class-constants to define the resolution makes it easy to change the size later on, if you are not satisfied with the way it looks.

Indicating the world’s resolution

The resolution is indicated in the call of the World-constructor. Here, the hight and width of the cell-size is given.

Example

Here is an example on how to indicate the resolution in the extension of World-class:

public class BallWorld extends World {

private static final int WIDTH = 600;

private static final int HEIGHT = 500;

private static final int CELLSIZE = 1 ;

(5)

/**

* Create the world of balls.

* This world has a size of WIDTH by HEIGHT cells

* each cell consists of CELLSIZE pixels

*/

public BallWorld( ) {

super( WIDTH , HEIGHT , CELLSIZE ) ; }

}

Theory 9.3: Vectors

The Vector class has been given. Vectors can be represented in two different ways:

a) The Cartesian form: as a pair of distances, expressed as x and y components;

b) The Polar form: as a pair with a direction component and a distance (length) component.

This figure shows the same vector being represented in both manners://

Figure 3: Vector in its Cartesian form. Figure 4: Vector in its Polar form.

In some cases, it is more convenient to use the Cartesian form. In other cases, the Polar form may be favorable. The Java-implementation makes use of both formats. Internally, the Vector-object is constantly updated automatically.

Theory 9.4: Getter methods

Another object can use a public accessor method (a so-called getter method) to ask for the value of an object’s private instance variable. Not every instance variable has a public getter method. Getter methods are only written if they are useful, that is to say, if the values need to be shared with other objects.

Naming conventions of a getter method

How to name a getter method depends on the result which the method returns.

• If the result is a boolean, choose ’is....’, for example boolean isHatched ( );

• Otherwise, choose a name as ’get...’, for example int getNrOfEggsHatched ( ).

Here, the variable name is written instead of ’...’.

Example code for a getter method

Because instance variables are private, other objects can’t access its value. Another object can ask its value by using a getter method.

Below is an example of a public getter method for the private myNrOfEggsHatched variable. By adding this getter method, another object can call the method to ask how many eggs have been hatched:

(6)

public int getNrOfEggsHatched( ) { return myNrOfEggsHatched( ) ; }

This is a public method. Thus, another object can call this getNrOfEggsHatched ( ) method to ask how many eggs have been hatched. Note that another object can’t change the value of the variable by calling this method, another object can only ask its value.

Theory 9.5: Setter methods

The value of a private instance variable can be changed by another object using a public mutator method (a so-called setter method).

Tip: Use setter methods sparingly. Only add them to a class if they are really needed. That keeps the variables better protected, and thus it’s safer.

Example code for a setter method

For this example, assume MyDodo has an instance variable private int eggsToHatch with which Mimi can keep track of how many eggs she has to hatch.

Only she knows how many eggs she has to hatch (the variable is private). A snake may come along and eat an egg. In that case, Mimi can get a message from the snake telling her there is one less egg to hatch. Mimi then changes the value of myEggsToHatch herself (she decreases it by one). We don’t trust the snake to change the value of myEggsToHatch directly because he would immediately set its value to 0. The snake’s intention is to eat all the eggs; he doesn’t want Mimi to hatch any eggs at all. So, we don’t trust the snake with the variable myEggsToHatch and keep it private.

The following setter method can be called by another object in order to change one of MyDodo’s vari- ables:

public void setOneEggLessToHatch( ) {

myEggsToHatch−−; // decrease value by one }

Because the method setOneEggLessToHatch ( ) is public, another object can use setOneEggLessToHatch ( ) to decrease the value of the variable myEggsToHatch by only one. Another object is now given the ’power’

to change the value by one, but not to immediately set it to 0. Obviously, calling setOneEggLessToHatch () many times will lead myEggsToHatch to equal 0. However, we could keep track of how often another ob- ject calls a method and take adequate measures. In the case of the egg-eating-snake, after he eats 5 eggs we could set a snake trap. Whatever the case, the variable can not be changed without MyDodo knowing about it.

Theory 9.6: Colliding with a bumper

For balls to bounce off of bumpers properly, it can be useful to take a step back and analyse exactly what needs to happen if a ball bumps into a bumper. Actually, whether a ball bounces into a boundary or a bumper doesn’t make a difference: only the direction component of the velocity changes. With bumpers, the same happens. The following figure depicts this:

(7)

• The ball (whose center is at (x1, y1)) collides with the bumper (whose center is at (x2, y2)) at an angle θ.

• To determine the effect of the collision on the ball, we need to calculate L, the component of the balls’ speed ~v in the direction of the bumper. This can be done in a simple manner by roating the vector ~v clockwise over an angle −θ. L is then equal to the x component of the rotated vector.

• Due to the collision, the x component has to be inverted. The final speed is calculated by rotating the changed vector over the angle θ again.

Theory 9.7: Implementing how moving balls collide

Implementing how balls collide into each other is actually very similar to the collisions of the balls with the bumpers. The only difference is that the ball may collide into a moving ball (rather than an object that is standing still). In that case, the velocities of both balls will change.

Laws of conservation of energy

Using the laws of conservation of energy, you can calculate that when balls of the same mass collide head-on, they exchange each others velocity.

So, if the first ball has a velocity of v1and the second ball has a velocity of v2, then, after the collision, the first ball will have a velocity of v2and the second ball with have a velocity of v1.

However, generally, balls will not collide exactly head-on. Just as when a ball hits a bumper, there may be an angle with which it collides. This angle of incidence, θ, is calculated in the same way as with the balls and bumpers.

Theory 9.8: Collision with different masses

If one ball collides into a ball with another mass (originally standing still) in a head-on collision, the new velocity of the balls can be calculated using the law of conservation of energy.

Here, the first ball has a mass of m1and speed of v. The second ball has a mass of m2(and no velocity because it is standing still). The new velocities, u1 for the first ball and u2for the second ball can be calculated as follows:

u1= m1− m2 m1+ m2

v u2= 2m1 m1+ m2

v

(8)

Challenges

Challenge 9.1: Getting started with Balls and Bumpers

We are going to get started with the Balls and Bumpers simulation. You will be given three Java classes in advance. We will add these to the scenario.

a) Make your own new scenario for the Balls and Bumpers simulation. Come up with an appropriate name.

b) Add the three given Java classes to the scenario:

i) Exit Greenfoot.

ii) Download the classes: BallWorld, Vector and SmoothMover .

iii) Copy-paste these three classes in the folder that belongs to the scenario which you have just made.

c) Open the scenario again.

d) Have a look at the class diagram. The three classes should appear in the Greenfoot project-window.

As you can see, the Vector class is shown at the bottom of the class-window, and not as one of the Actor classes. This is because it is not an Actor. This is because no Vector objects will appear in the world on their own. The SmoothMover class is a helper-class, which is an extension of the Actorclass. We will get into more details later.

e) Compile the scenario. There is no point in running the scenario yet. For that, you must program first!

Please read Theory 9.1: Smooth movements.

Please read Theory 9.2: The resolution of the world.

Challenge 9.2: Changing the cell size

Smaller cells need to be used to simulate smooth movements. The cell-size is indicated using pixels:

dots on the screen. In Mimi’s world the cells are made up of 60-by-60 pixels. And in ”The egg-hoarder (Sokoban)” in assignment 8, the cells were made a little smaller so that all the levels could fit on the screen without a problem. The corresponding cell-size was 50-by-50 pixels. The cell-size is specified in Madagaskar.

a) Open the scenario for assignment 8 (”The egg-hoarder (Sokoban)”).

b) Have a look at Madagaskar’s code. Can you find where the cell-size is specified?

c) And where is the cell-size used?

d) Why is this in capital letters? Do you remember what this was called? Tip: have a look back at Theory 7.1.

(9)

Challenge 9.3: Changing the resolution of the world

Change the resolution of the Balls and Bumpers scenario:

a) Open the code belonging to BallWorld.

b) Adjust the code as explained in Theory 9.2.

Please read Theory 9.3: Vectors.

Challenge 9.4: Exploring the

Vector

class

We now explore the methods in the given Vector class so that you can use them later on.

a) Open the Vector class.

b) Have a look at the 2 constructors in this class.

i) What is the difference between these constructors?

ii) When making a new Vector instance, how do you ensure the correct constructor is called?

c) Which operations have been defined for vectors? What do these operations do?

Challenge 9.5: Setting up the

Ball

class

In order to show a ball on the screen, you obviously need a Ball class. You will now develop and im- plement the Ball class. As a ball needs to roll smoothly over the screen, this will be a sub-class of the SmoothMover (we will have a look at this class later). First, we add the Ball class to the scenario. To do so, follow the next steps:

a) Extend the SmoothMover class with a class called Ball:

i) In the class diagram, right-click on the SmoothMover and select New subclass ....

ii) Choose a name and picture for your ball.

iii) Click on OK.

b) Compile your scenario. Probably, you will get an error because your Ball constructor doesn’t call the SmoothMover constructor. Solve this as follows:

i) In the Ball constructor, use super to call the constructor which you are extending.

ii) Give super the same parameters as the SmoothMover constructor expects. You have seen such a call before, when you were extending the World class. Have a look at the BallWorld for some example code.

iii) Compile the scenario again.

c) It is useful to keep track of the ball’s radius.

i) Add an appropriate instance variable.

ii) Determine the radius from the picture which you choose for the ball.

iii) Attain the picture using getImage ( ). The width can then be determined using getWidth ( ).

Use the Greenfoot documentation to figure out how to use these methods.

Please read Theory 9.4: Getter methods.

Please read Theory 9.5: Setter methods.

(10)

Challenge 9.6: The ball starts rolling

The Ball class is now a sub-class of the SmoothMover . We will now have a look at the SmoothMover class in more detail.

a) Open the code for the SmoothMover class.

b) Near the top you will see three instance variabels:

• myXCoord and myYCoord of the type double: to keep track of the position of a SmoothMover ;

• myVelocity of the type vector: to keep track of the velocity.

c) In the previous assignments, to determine the position of Mimi or an egg, we used coordinates.

For this we used the getX ( ) and getY ( ) methods from Actor.

i) What is the difference between myXCoord’s type and the return-type of getX ( )?

ii) Why would we now prefer to use myXCoord?

d) The class’s constructor expects the initial SmoothMover ’s velocity expressed in Polar form. (Tip:

see Theory 9.3)

e) Using the method move, the SmoothMover moves one step.

• If (x, y) is the current position of the ball, and it’s velocity is ~v, then its new position is (x + vx, y + vy).

• As you can see, this uses the Cartesian form of vector ~v. (Tip: see Theory 9.3)

f) For each of the other methods, have a look at the getter methods belonging to the instance vari- ables (Tip: see Theory 9.4).

Challenge 9.7: Bounce back

We now want to simulate how a ball bounces off other objects. Because this is pretty complex, we will break the implementation down into several steps. We start with a simple implementation of the Ball which we then extend, step-by-step, until it works perfectly. We start by checking if the ball bumps into something which it needs to bounce off of, and then we implement the bouncing itself.

a) Open the code for Ball.

b) First, in the act ( ) method call a move ( ).

c) Compile and run the scenarion.

d) Something should be happening. Describe what you see.

e) The ball moves around, but doesn’t take into account that the world is bounded. In Mimi’s world we saw that an Actor can’t step out of the world. Write a method which checks if a world-boundary has been reached. Tip: Compare the distance from the boundary to the center of the ball with the ball’s radius.

f) Write a method which makes the ball bounce back off a boundary:

i) Describe precisely what happens to a vector when the ball bounces straight back. Tip: the direction changes, but it’s speed remains the same.

ii) Write a method void handleWallCollision ( ) that checks if a world boundary has been reached, and if so, adjusts the velocity of the ball accordingly.

(11)

Challenge 9.8: Adding bumpers

We now add obstacles to the scenario. In a pinball machine, these are called bumpers. For these, we add a class called Bumper:

1. Bumper-objects are round and can’t move. Decide which class you should extend with your new Bumper-class.

2. Extend the Actor class with a Bumper-class.

3. Which instance variable would be useful to add to the Bumper class? Tip: Have a look at Challenge 9.5 part c).

4. Add this instance variable and initialize it appropriately.

5. Which class is responsible for making the balls bounce back? That is to say, determines how it bounces back? Having figured that out, what is left over for the Bumper? Tip: The definition of Bumpermay be extremely simpel.

Please read Theory 9.6: Colliding with a bumper.

Challenge 9.9: Bounce off of bumpers

We work-out the steps for simulating bouncing off the bumpers step by step.

a) Add a method void handleBumperCollision ( ) to the Ball class, which does the following:

i) First checks if the ball collides with a bumper. How do you determine if the ball hits a bumper?

Tip: You can get all the bumper-objects using the world method getObjects ( Class cls ).

This will give you a list of bumpers. For each bumper, determine if the ball is near enough.

ii) If the ball hits a bumper, the next steps must be executed:

1) Determine the angle θ. Tip: Create a new vector with its starting point at the center of the ball, and endpoint at the center of the bumper. Now, figure out how you could easily obtain θ from this.

2) Rotate the velocity of the ball over the angle −θ;

3) Invert the x−component of this velocity;

4) Rotate the velocity again, this time over the angle θ.

b) In the act ( ) methode belonging to the Ball class, call void handleBumperCollision ( ).

c) Run and test your scenario. Does it work as you would expect it to?

Please read Theory 9.7: Implementing how moving balls collide.

Challenge 9.10: Moving balls colliding

We now modify the code so that two balls can collide at a particular angle:

a) Figure out how to calculate the new velocities of the colliding balls. Tip: use the rotations again to determine the correct components of each of the speeds, and exchange these between the two balls.

b) For the above, write a method void handleBallCollision ( ). Call this method in the act ( ) method.

c) Run and test your scenario.

(12)

Challenge 9.11: Different sized balls

Modify your code so that the simulation works with different sized balls. A few tips:

• In Greenfoot you can create your own image for a ball (in the next step you will transform this into a picture of a ball). Connect this image to your actor using the Greenfoot class GreenfootImage . Then use the constructor public GreenfootImage ( int width , int height ) to make a rectangular image where the ball fits in perfectly. How large are its width and height?

• Draw a circle. It’s easiest to color in the circle first, and then draw its border.

First choose the color of the ball. Use setColor ( Color c) to choose the pen color for coloring in the ball.

Use the GreenfootImage method fillOval ( int x , int y , int width , int height ) to color in the circle. Have a look at the Greenfoot API to understand how to use the parameters.

If you want to give the circle a black border, you need to first change the color of the pen (back)

to black. After that you can draw a border using drawOval ( int x , int y , int width , int height ).

Use Greenfoot . getRandomNumber ( int limit ) to create a random-sized or random-colored ball.

Please read Theory 9.8: Collision with different masses.

Challenge 9.12: Balls with different masses

In this challenge we will make the simulation more realistic (and complex) by allowing balls with dif- ferent masses.

a) Just like in the previous challenge, both balls are moving and we don’t need to consider a perfect head-on collision. You can describe this general case as a 1-dimensional case using a rotation and a transformation. Determine exactly how this happens. Tips:

i) First, represent the velocity of the first ball( ~v1) with respect to the second ball (with velocity

~

v2). This is done by a simple subtraction: ~v1− ~v2. ii) Rotate this result over an angle −θ.

iii) Use the formula in Theory 9.8 to calculate the velocities after the collision.

iv) Convert everything back to the original situation.

b) Write these steps out in Java code.

c) Test your program.

d) Now modify the code so that the mass coincides with the size of the ball. The larger the ball, the heavier it is.

e) Test your modifications.

(13)

Reflection

In this assignment you practiced using list to store values. You also learned about the for-each-loop to traverse lists and how to use a list to store (Egg) objects. One of the most important steps in becoming good at anything is to evaluate and reflect on what you did and how it went:

Result

I know my solution works because ...

I am proud of my solution because ...

I could improve my solution by ...

Method

My approach was good because ...

What I could do better next time is ...

Fill the following table with smileys

indicating how things went. I can do it

I did it a bit but didn’t fully get it I didn’t get it at all

I can make a (2-dimensional) simulation for a real (3-dimensional) situ- ation;

I can use and apply formula’s from another subject (or field).

(14)

Saving and Handing in

You have just finished the assignment. Save your work! You will need this for future assignments. In the Greenfoot menu at the top of the screen, select ’Scenario’ and then ’Save’. You now have all the scenario components in one folder. The folder has the name you chose when you selected ’Save As ...’.

Handing in

Hand in the following:

• Your code;

• Flowcharts: paste (photo’s of) your flowcharts in a Word document;

• The reflection sheet: complete and hand it in.

Referenties

GERELATEERDE DOCUMENTEN

The fact that the Dutch CA – a governmental body with the experience and expertise in child abduction cases – represents the applying parent free of charge, while the

Publisher’s PDF, also known as Version of Record (includes final page, issue and volume numbers) Please check the document version of this publication:.. • A submitted manuscript is

Mais, c’est précisément dans ce genre de contrôle que l’introduction d’un niveau de sécurité devient très délicat étant donné qu’il est impossible de

When this assumption does not hold, we prove an O(1/n) convergence for our upper and lower bounds for equidistant input data points in the case of Hausdorff distance and the

As with all comparative analyses that involve jurisdictions using diff erent general languages, the Common Core comparatist compares the various legal systems within a

A method and machine for generating map data and a method and navigation device for determining a route using map data Citation for published version (APA):.. Hilbrandie, G.,

jaren bij patiënten in het Academisch Ziekenhuis Nij- megen, Academisch Ziekenhuis Vrije Universiteit Amsterdam en Leijenburg Ziekenhuis te Den Haag bijeengevoegd worden, om tot

• Write a setter method to tell the egg when it has been hatched (to change the value of the instance variable boolean iAmHatched ): public void setHatched( )v. • Modify