This site requires JavaScript, please enable it in your browser!
Greenfoot back
Czaherin
Czaherin wrote ...

2014/11/17

How to end the game when a score reaches a certain number?

1
2
Czaherin Czaherin

2014/11/17

#
Hi everyone, I'm at a complete loss here. I've been researching this for a couple hours and I can't find anything that is helping me solve this issue. I am making a game where a hunter shoots birds, when the hunter has shot a certain number of birds the game is supposed to end. I cannot get this to work at all. I have a working scoreboard and score counter, but I cannot get the game to end properly. Any help would be greatly appreciated, thanks.
EnderPicture EnderPicture

2014/11/17

#
How do you want your game to end?
danpost danpost

2014/11/17

#
Please post the code you have tried (use the 'code' link below the reply box to insert code into your post).
Czaherin Czaherin

2014/11/17

#
We have to shoot 50 birds, when 1/4 of them are killed or 3 minutes have elapsed, the game is supposed to end.
danpost danpost

2014/11/17

#
What code do you have that registers a bird being shot?
Czaherin Czaherin

2014/11/17

#
Hunter class
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Hunter here.
 * 
 * @author (Ryan Sepesy) 
 * @version (Version 1.0)
 */
public class Hunter extends SmoothActor
{
    private static final int gunReloadTime = 50;
    private int reloadDelayCount;
    private GreenfootImage hunter = new GreenfootImage ("hunter.png");
    

    /**
     * initialize the hunter
     */
    public Hunter()
    {
        reloadDelayCount = 0;
    }
    
    /**
     * This is what where the hunter does everything specified.
     */
    public void act() 
    {
        checkKeys();
        checkIntersect();
        reloadDelayCount++;
    }    
    
    /**
     * this is where we check what keys are pressed, and respond accordingly.
     */
    private void checkKeys()
    {
        if (Greenfoot.isKeyDown("left"))
        {
            setRotation(getRotation() - -10);
        }
        if (Greenfoot.isKeyDown("right"))
        {
            setRotation(getRotation() - 10);
        }
        if (Greenfoot.isKeyDown("up"))
        {
            move(3);
        }
        if (Greenfoot.isKeyDown("down"))
        {
            move(-3);
        }
        if (Greenfoot.isKeyDown("space")) 
        {
            fire();
        }
    }
    
     /**
     * Fire a bullet if the gun is ready.
     */
    private void fire() 
    {
          if (reloadDelayCount >= gunReloadTime)
          {
              Bullet bullet = new Bullet (new Vector(getRotation(),15), getRotation());
              getWorld().addObject (bullet, getX(), getY());
              bullet.move();
              reloadDelayCount = 0;
          }
    }
    
    /**
     * check if our hunter is intersecting a tree. If true, stop him from moving.
     */
    public void checkIntersect()
    {
        if (canSee(Tree.class))
        {
            move(-3);
        }
    }
    
}
World Class
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)
import java.awt.Color;

/**
 * A world for the boids.
 * 
 * @author Poul Henriksen 
 * @version 2.0
 */
public class Sky extends World
{
    /**
     * Constructor for objects of class Sky.
     * 
     */
    public Counter scoreCounter;
    public Sky()
    {    
        super(800, 600, 1);
        getBackground().setColor(new Color(220,220,100));
        
        getBackground().fill();
        populateTrees(100);
        populateBoids(50);
        
        scoreCounter = new Counter("Score: ");
        addObject(scoreCounter, 790, 590);
    }
    
    public void populateBoids(int number) {
        for(int i=0; i < number; i++) {            
             int x = (int) (Math.random() * getWidth());          
             int y = (int) (Math.random() * getHeight());
             Boid b = new Boid();
             addObject(b, x, y);
        }
    }
    
    public void populateTrees(int number) {
        // Size of block in pixels
        int blockSize = 70; 
        // Trees per block
        int treesPrBlock = 10;
        // How close together trees in a block are. Higher number, the closer they are.
        int blockCoherence = 1;
        for(int block = 0; block < number / treesPrBlock; block++) {           
             int x = Greenfoot.getRandomNumber(getWidth()/blockSize) * blockSize;   
             int y = Greenfoot.getRandomNumber(getHeight()/blockSize) * blockSize;  
             for(int t = 0; t < treesPrBlock; t++) {
                 int dx = Greenfoot.getRandomNumber(blockSize/blockCoherence);
                 int dy = Greenfoot.getRandomNumber(blockSize/blockCoherence);
                 Tree b = new Tree();
                 addObject(b, x  + dx, y + dy);                
             }    
        }        
    }   
    
    public void countScore()
    {
        scoreCounter.add(1);
    }
    
    public void gameOver()
    {
        ScoreBoard board = new ScoreBoard(scoreCounter.getValue()); 
        addObject(board, getWidth()/2, getHeight()/2);
    }
}
Bird code
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)
import java.util.*;

/**
 * A boid is an object that is part of a flock. 
 * The boid follows a few simple rules that gives emergent behaviour when lots of boids are placed in the world.
 * 
 * @author Poul Henriksen 
 * @version 2.0
 */
public class Boid extends SmoothActor
{
    /** Distance the wall-force will start working from.  */
    private final static int WALL_DIST = 50;    
    /** The size of wall force when it is at max. */
    private final static int WALL_FORCE = 200;
    
    /**  Maximum speed of the boid. */
    private final static int MAX_SPEED = 75;
    /**  Minimum speed of the boid. */
    private final static int MIN_SPEED = 25;
    /** The speed is divided by this. */
    private final static int SPEED_DIVIDER = 15; 
     
    /** Distance from which repulsion from other objects start working.*/
    private final static int REPULSE_DIST = 40;   
    /** Distance from which alignment with other boids start working. */ 
    private final static int ALIGN_DIST = 150;    
    /** Distance from which attraction to other boids start working. */ 
    private final static int ATTRACT_DIST = 150;
    
    /**
     * Creates a new boid with minimum speed in a random direction.
     */
    public Boid()
    { 
        setMaximumSpeed(MAX_SPEED);
        setMinimumSpeed(MIN_SPEED);
        setSpeedDivider(SPEED_DIVIDER);
        
        Vector vel = new Vector();
        vel.setDirection((Math.random())*360);
        vel.setLength(MIN_SPEED);
        setVelocity(vel);
    }
    
    /**
     * Flock!
     */
    public void act() 
    {      
        acc();
        super.act();
    }    
    
    /**
     * Calculate accelaration by appling the boid rules
     */
    private void acc() {
        Vector acc = new Vector(0,0);
        acc.add(getFlockAttraction(ATTRACT_DIST).divide(7.5));     
        acc.add(getFlockRepulsion(REPULSE_DIST).multiply(1));
        acc.add(getFlockAlignment(ALIGN_DIST).divide(8));
        acc.add(getWallForce());
        setAccelaration(acc);
    }
    
    /**
     * Get the size of the wall force on this boid. Will make the boid avoid the world boundaries.
     */    
    public Vector getWallForce() {
        Vector location = getLocation();
        //Special border repulse rules:
        Vector wallForce = new Vector(0,0);
        if(location.getX() <= WALL_DIST) {
            double distFactor = (WALL_DIST - location.getX()) / WALL_DIST;
            wallForce.add(new Vector(WALL_FORCE * distFactor, 0));
        }
        if( (getWorld().getWidth() - location.getX()) <= WALL_DIST) {
            double distFactor = (WALL_DIST - (getWorld().getWidth() - location.getX())) / WALL_DIST;
            wallForce.subtract(new Vector(WALL_FORCE * distFactor, 0));
        }
        if(location.getY() <= WALL_DIST) {
            double distFactor = (WALL_DIST - location.getY()) / WALL_DIST;
            wallForce.add(new Vector(0, WALL_FORCE * distFactor));
        }
        if(getWorld().getHeight() - location.getY() <=  WALL_DIST) {
            double distFactor = (WALL_DIST - (getWorld().getHeight() - location.getY())) / WALL_DIST;
            wallForce.subtract(new Vector(0, WALL_FORCE * distFactor));
        }
        return wallForce;
    }
    
    /**
     * Get the other objects that are within the given distance.
     */
    private List getNeighbours(int distance, Class cls) {
        return getObjectsInRange(distance, cls);
    }
    
    /**
     * Get the center of all the boids within the given distance. 
     * That is, the average of all the positions of the other boids.
     */
    public Vector getCentreOfMass(int distance) {
        List neighbours = getNeighbours(distance, Boid.class);
        //add me
        neighbours.add(this);
        Vector centre = new Vector();
        for(Object o : neighbours) {
            Boid b = (Boid) o;
            centre.add(b.getLocation());
        }
        return centre.divide(neighbours.size()); 
    }

    /**
     * Get the attraction from the other boids within the given distance.
     */
    public Vector getFlockAttraction(int distance) {
        Vector com = getCentreOfMass(distance);
        //distance to the centre of mass
        Vector distCom = getCentreOfMass(distance).subtract(getLocation());
        return distCom;        
    }
    
    /**
     * Get the repulsion from the other boids within the given distance.
     */
    public Vector getFlockRepulsion(int distance) {
        Vector repulse = new Vector();
        List neighbours = getNeighbours(distance, SmoothActor.class);
        for(Object o : neighbours) {            
            SmoothActor other = (SmoothActor) o;
            //dist to other actor
            Vector dist = getLocation().subtract(other.getLocation());
            if(dist.getLength() > distance) {
                // Make sure we are looking at the logical distance.
                continue;
            }
            repulse.add(dist.setLength(distance - dist.getLength()));
        }
        return repulse;        
    }
    
    /**
     * Get the average velocity of all boids within the given distance.
     */
    private Vector getAverageVelocity(int distance) {
        List neighbours = getNeighbours(distance, Boid.class);
        //add me
        neighbours.add(this);
        Vector avg = new Vector();
        for(Object o : neighbours) {
            Boid b = (Boid) o;
            avg.add(b.getVelocity());
        }
        return avg.divide(neighbours.size());
    }
    
    /**
     * Get the relative direction this boid should be facing to match the average direction of the flock.
     */
    private Vector getFlockAlignment(int distance) {
        Vector avgVel = getAverageVelocity(distance);
        avgVel.subtract(getVelocity());
        return avgVel;
    }
    
    public void hit()
    {
        ((Sky)getWorld()).countScore();
        getWorld().removeObject(this);
    }
}
Dr_Diabetes Dr_Diabetes

2014/11/17

#
Ryan, we are in the same class =) What I did was create a counter class that extends Actor and used the code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.awt.Graphics;

//This is how counting systems are made =)

public class Counter extends Actor
{
    private static final Color textColor=new Color (255,255,255);
    private int value = 0;
    private int target = 0;
    private String text;
    private int stringLength;
    
    public Counter()
    {
        this("");
    }
    
    public Counter(String prefix)
    {
        this(prefix, 0);
    }
    
    public Counter(String prefix,int value)
    {
        this.value=value;
        text = prefix;
        stringLength = (text.length()+2)*10;
        
        setImage(new GreenfootImage (stringLength, 16));
        GreenfootImage image = getImage();
        image.setColor(textColor);
        updateImage();
    }
    
    public void updateImage()
    { //this is where images are born from
        GreenfootImage image = getImage();
        image.clear();
        image.drawString(text+value,1,12);
    }
    
    public void add(int score)
    {
        target += score;
    }
    
    public int getValue()
    {
        return value;
    }
    
    public void act()
    {
        if(value < target)
        {
            value++;
            updateImage();
        }
        else if (value>target)
        {
            value--;
            updateImage();
        }
        endGame();
    }
    
    public void killCount()
    {
        value++;
        updateImage();
    }
    
    public void endGame()
    {
        if (target==13)
        {
            Greenfoot.stop();
        }
    }
I just havent figured out a way to make the final scoreboard
Dr_Diabetes Dr_Diabetes

2014/11/17

#
25% of 50 = 12.5 so I rounded up to 13
Czaherin Czaherin

2014/11/17

#
I have a counter class as well, but I did not try to end the game through that, so I'll try changing up my code to try that. I'll let you know how that goes!
Czaherin Czaherin

2014/11/17

#
Also I think yours is not working because of the greenfoot.stop. You don't want to stop the program entirely, just have the scoreboard display.
danpost danpost

2014/11/17

#
If there is a 'get' method in your Counter class to get the current value, then your 'hit' method in the Boid class should start with:
public void hit()
{
    ((Sky)getWorld()).countScore();
    if (((Sky)getWorld()).scoreCounter.getValue() > 50*1/4)
    {
        // code for game won
    }
    getWorld().removeObject(this);
}
For the 3 minute timer, that would go in your Sky class using the act method in that class to run the timer. EDIT: I did not see the last 4 posts while I wrote this.
Czaherin Czaherin

2014/11/17

#
Woo! I got it working! Thanks for your help everyone!
Dr_Diabetes Dr_Diabetes

2014/11/17

#
So Danpost, with using code lines 75-81 of the code I posted. How would I display a scoreboard instead of calling greenfoot.stop? When I plug in sky.scoreboard() it tells me that I can't call a nonstatic method from a static method?
Dr_Diabetes Dr_Diabetes

2014/11/17

#
Here's what I'm trying to do. its sky.gameOver();
 public void hit()
    {
        ((Sky)getWorld()).getScoreCounter();
        if (((Sky)getWorld()).scoreCounter.getValue()>(50*1/4))
        {
           Sky.gameOver();
        }
    }
}
Dr_Diabetes Dr_Diabetes

2014/11/17

#
It highlights .gameOver and says "non-static method gameOver() cannot be referrenced from a static context:"
There are more replies on the next page.
1
2