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

2015/12/7

How to link counter to hitting blocks

1
2
malikdon malikdon

2015/12/7

#
Okay so I am working on a project and it's essentially a simplified Super Mario Bros. (based on the Pengu scenario) and I am trying to do the following: 1) I have a Question Block in the world and it's supposed to be one of those blocks with lots of coins in it. I am trying to add collision detection so that when Mario's head (yes, I know it's really his fist but this is simplified for my project) hits the block, it adds 1 to my Coin Counter. also 2) I am trying to add sounds for when Mario jumps, hits the block, acquires coins, and also the music that will be constantly playing in the background. All of the sounds are in my sounds folder. I just am not sure how to get them to play. I am unsure of how to do these things. I am pretty sure I can make it where if Mario makes contact with the block, a sound will play, but I would like for there to be the sort of "bounce" back like in Breakout. I know if I was ending the game, I would code the following: public void gameOver() { Greenfoot.playSound("gameover.wav"); Greenfoot.stop(); } Any tips?
danpost danpost

2015/12/7

#
My Value Display Tutorial scenario may be able to help you with your counter issue. Work on one thing at a time. Get the counter working first, then start a discussion on one of your other issues if you need more help.
malikdon malikdon

2015/12/7

#
Okay, so here is the interaction between Mario and the block (which triggers the counter): import greenfoot.*; public class Mario extends Mover { private static final int jumpStrength = 16; private Counter myCounter; public Mario(Counter counter) { myCounter = counter; } public void act() { checkKeys(); checkFall(); checkBlock(); } private void checkKeys() { if (Greenfoot.isKeyDown("left") ) { setImage("mario-left.png"); moveLeft(); } if (Greenfoot.isKeyDown("right") ) { setImage("mario-right.png"); moveRight(); } if (Greenfoot.isKeyDown("space") ) { if (onGround()) jump(); } } private void jump() { setVSpeed(-jumpStrength); fall(); Greenfoot.playSound("jump.wav"); } private void checkFall() { if (onGround()) { setVSpeed(0); } else { fall(); } } public void checkBlock() { if (canSee(Block.class)) { myCounter.add(1); Greenfoot.playSound("coin.wav"); } if (myCounter.getValue()>=10) { gameOver(); } } } ------------------------------ For some reason I keep getting an error with this. When I hit compile, it opens up the editor for scene (which extends world) and then highlights the Mario line (see below) and says: "constructor Mario in class Mario cannot be applied to given types; required: Counter; found: no arguments; reason: actual and formal argument lists differ in length public Scene() { super(750, 500, 1); addObject ( new Cliff(false), 85, 441); addObject ( new Cliff(true), 665, 441); addObject ( new Platform(), 369, 315 ); addObject ( new Mario(), 66, 244 ); addObject ( new Block(), 379, 120 ); myCounter = new Counter(); addObject(myCounter, 688, 29); } public void updateCounter() { myCounter.add(1); } } public Scene() { super(750, 500, 1); addObject ( new Cliff(false), 85, 441); addObject ( new Cliff(true), 665, 441); addObject ( new Platform(), 369, 315 ); addObject ( new Mario(), 66, 244 ); addObject ( new Block(), 379, 120 ); myCounter = new Counter(); addObject(myCounter, 688, 29); } public void updateCounter() { myCounter.add(1); } }
danpost danpost

2015/12/7

#
You will have to determine which class the counter is to be located and controlled from; then, the parameters of your constructor and constructor calls should match.
malikdon malikdon

2015/12/8

#
I have Counter as an extension of Actor. Here is the code: import greenfoot.*; import java.awt.Color; public class Counter extends Actor { private int count; public Counter() { GreenfootImage myImage = new GreenfootImage(100, 40); setImage(myImage); updateImage(); } public void updateImage() { GreenfootImage image = getImage(); image.clear(); image.setColor(Color.WHITE); image.drawString("Coins x " + count, 0, 15); setImage(image); } public void add(int value) { count = count + value; updateImage(); } }
danpost danpost

2015/12/8

#
danpost wrote...
You will have to determine which class the counter is to be located and controlled from; then, the parameters of your constructor and constructor calls should match.
I was referring to the Counter object when I used 'counter' here, not the Counter class. You have a Mario constructor that is to receive a Counter object and place it in a 'myCounter' field. But, when you try to create a Mario object, no Counter object is being passed. You have a second field that is to hold a Counter object in your Scene class. You only need one of these fields. Also, in your Mario class, you are calling a 'getValue' method on the Counter object, but there is no method with that name in the Counter class.
malikdon malikdon

2015/12/8

#
I'm not sure which of the two is simpler to do. What would you suggest?
malikdon malikdon

2015/12/8

#
Would you be willing to take a quick glance at a zip file of my scenario?
danpost danpost

2015/12/8

#
malikdon wrote...
I'm not sure which of the two is simpler to do. What would you suggest?
Either way is really okay -- however, if you consider the score to be a game score, putting it in the world class would be more appropriate; and, if you consider it a player score, then in the class of the player.
malikdon malikdon

2015/12/8

#
I am getting this error when Mario makes contact with the block. I did initialize the counter in Mario so I'm not sure why I am getting a Null Pointer Exception. java.lang.NullPointerException at Mario.tryToEatBlock(Mario.java:129) at Mario.act(Mario.java:83) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205) java.lang.NullPointerException at Mario.tryToEatBlock(Mario.java:129) at Mario.act(Mario.java:83) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205)
Super_Hippo Super_Hippo

2015/12/8

#
Show the 'tryToEatBlock' method. Maybe you are removing the object from the world and call a method which requires it to be in the world (e.g. 'getX', 'getWorld')?
malikdon malikdon

2015/12/8

#
import greenfoot.*; public class Mario extends Animal { private static final int jumpStrength = 16; private int vSpeed = 0; private static final int acceleration = 2; private static final int speed = 7; private Counter myCounter; public Mario(Counter counter) { myCounter = counter; } public void moveRight() { setLocation ( getX() + speed, getY() ); } public void moveLeft() { setLocation ( getX() - speed, getY() ); } public boolean onGround() { Object under = getOneObjectAtOffset(0, getImage().getHeight()/2-8 , null); return under != null; } public void setVSpeed(int speed) { vSpeed = speed; } public void fall() { setLocation ( getX(), getY() + vSpeed); vSpeed = vSpeed + acceleration; if ( atBottom() ) gameEnd(); } private boolean atBottom() { return getY() >= getWorld().getHeight() - 2; } private void gameEnd() { Greenfoot.stop(); } /** * Return true if we can see an object of class 'clss' right where we are. * False if there is no such object here. */ public boolean canSee(Class clss) { Actor actor = getOneObjectAtOffset(0, 0, clss); return actor != null; } /** * Try to eat an object of class 'clss'. This is only successful if there * is such an object where we currently are. Otherwise this method does * nothing. */ public void eat(Class clss) { Actor actor = getOneObjectAtOffset(0, 0, clss); if(actor != null) { getWorld().removeObject(actor); } } public void act() { checkKeys(); checkFall(); tryToEatBlock(); } private void checkKeys() { if (Greenfoot.isKeyDown("left") ) { setImage("mario-left.png"); moveLeft(); } if (Greenfoot.isKeyDown("right") ) { setImage("mario-right.png"); moveRight(); } if (Greenfoot.isKeyDown("space") ) { if (onGround()) jump(); } } private void jump() { setVSpeed(-jumpStrength); fall(); Greenfoot.playSound("jump.wav"); } private void checkFall() { if (onGround()) { setVSpeed(0); } else { fall(); } } public void tryToEatBlock() { if (canSee(Block.class)) { eat(Block.class); myCounter.add(1); Greenfoot.playSound("coin.wav"); } } }
danpost danpost

2015/12/8

#
You need to show your revised Scene class constructor ( 'public Scene()' ).
malikdon malikdon

2015/12/11

#
Thanks, but I was able to isolate the problem yesterday morning finally. Here is how the code in scene should look like: theCounter = new Counter(); addObject(theCounter, 688, 29); Mario mario = new Mario(theCounter); addObject (mario, 66, 244 ); Block block = new Block(); addObject (block, 379, 176 ); ----------------------------------------------------- The problem was that I originally placed the above bolded code after the two lines of code pertaining to Mario when they should be before. In other words, before Mario can make contact with the block and before the counter can count, it must first be initialized.
danpost danpost

2015/12/11

#
malikdon wrote...
The problem was that I originally placed the above bolded code after the two lines of code pertaining to Mario when they should be before. In other words, before Mario can make contact with the block and before the counter can count, it must first be initialized.
That explanation shows a lack of understanding in what is happening. If the Counter object is to be passed to the Mario object when the Mario object is created, then the Counter object must be created first. The first four lines above could be written as follows:
1
2
addObject(theCounter = new Counter(), 688, 29);
addObject(new Mario(theCounter), 66, 244);
"before Mario can make contact with the block": both the Mario object and however many Block object you have must be initialized and added into the world; and the constructor must have completed its execution; and the scenario must be started. "before the counter can count": the Counter object must be initialized and added to the world; and the scenario must be started. If the counter is controlled by an actor, it must also be initialized and added to the world.
There are more replies on the next page.
1
2