import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
public class Turtle extends Actor
{
/**
* Act - do whatever the Turtle wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
int laufmenge;
public void act()
{
if(Greenfoot.isKeyDown("left")){
move(-speed);
}
if(Greenfoot.isKeyDown("right")){
move(speed);
}
if(Greenfoot.isKeyDown("up")){
setLocation(getX() ,getY() -speed);
}
if(Greenfoot.isKeyDown("down")){
setLocation(getX() ,getY() +speed);
}
if(Greenfoot.isKeyDown("x")){
if(speed<10) speed++;
}
if(Greenfoot.isKeyDown("y")){
if(speed>0) speed--;
}
System.out.println(speed);
}
private int speed=1;
}
This is code from Greenfoot because i am currently trying to learn coding. I cant understand why when i execute the programm and control the speed he is changing the value by more than one. I guess it will be an easy question.
And is it possible to put the increase and decrease of the speed on one button with two letters like the >< key? i didnt work in my case.
This happens because act() is called in rapid succession. Even if you just press and release x, act() will have run several times while the key is down, and therefore updated the speed several times.
To avoid that, you can track whether or not you've adjusted the speed since the first time you noticed that the button was pressed.
For example, you can have a private bool adjustedSpeed = false; in your class, and then do:
if(Greenfoot.isKeyDown("x")){
if(speed<10 && !adjustedSpeed) speed++;
adjustedSpeed = true;
} else if(Greenfoot.isKeyDown("y")){
if(speed>0 && !adjustedSpeed) speed--;
adjustedSpeed = true;
} else {
adjustedSpeed = false
}
Related
I'm trying to write a logic in memory game that when I click on cards and they are not a pair (different ID), program should swap them back after 1s. If they are same, then leave them as they are.
The problem is that when I first click and the card appears, after second clicking on another (different) card it doesn't appear and swap the first card after 1s. someone knows why the second card does not appear after clicking?
Btw when the pair is correct, everything works fine, here is my fragment of the code responsible for that logic in listener:
final int copy = i;
card2.addActionListener((e) -> {
card2.setIcon(new ImageIcon(icons[copy].getAbsolutePath()));
if(firstClick == null)
{
firstClick = (Card)e.getSource();
}
else
{
Card secondClick = (Card)e.getSource();
if(firstClick.getID() != secondClick.getID())
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e1)
{
//e1.printStackTrace();
}
firstClick.setIcon(new ImageIcon(background.getAbsolutePath()));
secondClick.setIcon(new ImageIcon(background.getAbsolutePath()));
firstClick = null;
}
else
firstClick = null;
}
});
While method actionPerformed is executing, the GUI cannot react to mouse and keyboard events, so basically your code is "freezing" your GUI for one second. I believe that the class javax.swing.Timer is what you need and at first glance it looks like the duplicate question that MadProgrammer referred to may help you.
I´ve been dealing with this for some days now I´ve serach over the internet and tried everything that came up to my mind but nothing works. My problem is that I am making a pexeso game, we have some additionaly library directly from school or something like that which allows us to draw some pictures instead of comad line only... (We didn´t have graphics yet) So my problem is that my game is running in cycle and waiting for my click som I am checking the condition if click was made. And if I want to click I have to have just a method public void vyberSuradnice(int, int) declared in my code.
So the problem is that my game is runinng in cycle and checking if click was made. But when the click was made the method vyberSuradnice is executed and there I am setting the value off atrrbiute - cakatNaKlik on false, so click was made and one step of game can be made.. But since the function is running in cycle, then even If I clicked and in the method vyberSuradnice the value of attribute is changed, my function which is running in cycle isn´t respond to that change, so the game isn´t going on.
this is the method for clicking
public void vyberSuradnice(int paSuradnicaX, int paSuradnicaY) {
this.riadokOdkry = (paSuradnicaY ) / 25;
this.stlpecOdkry = (paSuradnicaX - 10) / 25;
if (this.riadokOdkry > this.aPocetRiadkov || this.stlpecOdkry > this.aPocetStlpcov) {
System.out.println("Klikli ste mimo hracieho pola ");
} else {
this.cakatNaKlik = false;
}
}
This the part of code where I am waiting for cakatNaklik - false value
while (uhadol) {
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
But even if the value is changed in method vyberSuradnice this condition is not triggered. But when I make something like this :
while (uhadol) {
System.out.print(this.cakatNaKlik);
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
the game is working like by writing the variable refresh it or something... but I am getting neverending print of true true or false on command line and this is something I can´t afford to have...
I know this may can be dan by threads but it´s something I can´t allowed to make and I am basically trying to do two things at once.
Is there any other to do this that the variable will be refreshed even without that println and the code will work ?
Thanks very much for every help
Thanks everybody for help, I finally solved it. I just tried tu put a sleep before the if condition. It only need to sleep for even a one miliseconds and it´s seems that the condition is refreshed so it works.
Try this:
Implement an ActionListener interface or extend a class that implements an ActionListener interface. For example:
public class MyClass implements ActionListener {
}
Register an instance of the event handler class as a listener on one or more components. For example:
someComponent.addActionListener(instanceOfMyClass);
instanceOfClass = this; //(if it is handled in the same Class)
Include code that implements the methods in listener interface. For example:
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
Reference:
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
I'm having this issue with my 2 checks for a frogger-style game.
So the Gameover check is a simple collision check on the frog object.
The next check does a getY coord check for checking if the frog object has hit the roof of the world ergo has beaten the game.
Now when the GameOver check is fulfilled there is no more object to do a getY check on. So it gives an error.
How can I bypass this ?
full code of the Frogger class:
public class Frogger extends Actor
{
public void act()
{
checkKeys();
hitEnemy();
atTop();
}
private void checkKeys()
{
if (Greenfoot.isKeyDown("up")) {
setLocation(getX(), getY()-3);
}
if (Greenfoot.isKeyDown("down")) {
setLocation(getX(), getY()+3);
}
if (Greenfoot.isKeyDown("left")) {
setLocation(getX()-3, getY());
}
if (Greenfoot.isKeyDown("right")) {
setLocation(getX()+3, getY());
}
}
public void hitEnemy()
{
Actor Enemy = getOneIntersectingObject(Enemy.class);
if(Enemy != null)
{
World myWorld = getWorld();
Gameover gameover = new Gameover();
myWorld.addObject(gameover, 300, 200);
myWorld.removeObject(this);
}
}
private void atTop()
{
if (getY() < 30)
{
World myWorld = getWorld();
Youwin youwin = new Youwin();
myWorld.addObject(youwin, 300, 200);
myWorld.removeObject(this);
}
}
}
Different approaches. When the game is over, you could just not do a getY() check anymore. Do not continue running the game, but rather to back to a main menu or something. the getY() method is irrelevant here. You could halt the program completely.
But your code looks weird. GameOver is an object? Rather than a simple method in your game. It does look like your code has a weird structure for a game. Anyway, when the game is over the 'gamelogic' loop should no longer be running, bur rather go to a menu.
Or you could keep the game running and do a null check. But reading your code, it seems like the whole structure is not that good. Is the aTop part of your Frog class? If so, it should exist for it to be called on. If you remove the Frog class from the world, you could do something like (but I do not see where the aTop method gets called)
if(myWorld.getFrog()!=null){
// Get method
}
Could you maybe share a bit more of your code? I think this should give you an idea though, there should be no more calls to the object when the object is removed, because the game ended and the normal game loop should no longer be running. And otherwise, nullchecks.
I try to improve the movement of my figures but i dont find the real reason why they stutter a bit. I am moving them with an SequenceAction containing an MoveToAction and an RunnableAction that does reset the moveDone flag so there can be started a new move.
The game itself is gridbased so if a move is done the squence starts a move to the next grid depending on the direction. So here is how it looks like:
note that this is inside of the Act of the figure
....//some more here
if (checkNextMove(Status.LEFT)) //check if the position is valid
{
status = Status.LEFT; //change enum status
move(Status.LEFT); // calls the move
screen.map.mapArray[(int) mapPos.x][(int) mapPos.y] = Config.EMPTYPOSITION;
screen.map.mapArray[(int) (mapPos.x - 1)][(int) mapPos.y] = Config.CHARSTATE;
mapPos.x--;
moveDone = false;
}
//... same for the up down right and so on.
//at the end of this checking the updating of the actor:
// methode from the absctract to change sprites
updateSprite(delta);
super.act(delta); // so the actions work
//end of act
And here is the move Method that does add the Actions
protected void move(Status direction)
{
// delete all old actions if there are some left.
clearActions();
moveAction.setDuration(speed);
//restart all actions to they can used again
sequence.restart();
switch (direction)
{
case LEFT:
moveAction.setPosition(getX() - Config.TILE_SIZE, getY());
addAction(sequence);
break;
case RIGHT:
moveAction.setPosition(getX() + Config.TILE_SIZE, getY());
addAction(sequence);
break;
case UP:
moveAction.setPosition(getX(), getY() + Config.TILE_SIZE);
addAction(sequence);
break;
case DOWN:
moveAction.setPosition(getX(), getY() - Config.TILE_SIZE);
addAction(sequence);
break;
default:
break;
}
}
The figures dont really move smothy.
Anyone does see a misstake or isnt it possible to let them move smothy like this?
It always stutter a bit if a new move is started. So i think this might not work good. Is there a differnt approach to move them exactly from one Grid to an nother? (Tried it myself with movementspeed * delta time but this does not work exactly and i struggeled around and used the Actionmodel)
it seems to make troubles with the one Frame where it does not move for example.
Here is an mp4 Video of the stuttering:
stuttering.mp4
just to mention, the camera movement is just fine. it's smothy but the figure stutters as you can see i hope
If you use your moveAction each move, you should call moveAction.restart() to reset the counter inside it:
// delete all old actions if there are some left.
clearActions();
sequence.reset(); // clear sequence
// add movementspeed. Note it can change!
moveAction.restart();
moveAction.setDuration(speed);
UPDATE:
Now issue occurs, because you call restart of SequenceAction after clearActions(). If your clearActions() removes all actions from SequenceAction then restart will be called for empty SequenceAction. So, do this instead:
//restart all actions to they can used again
sequence.restart();
// delete all old actions if there are some left.
clearActions();
moveAction.setDuration(speed);
Okay so i solved it myself. It has nothing todo with changing sequences around. It has something todo with the updatefrequency of the act() of the figures. The MoveToAction interpolates between the 2 points given by time. So if the last update, updates the MoveToAction by "to much time" it would need to go over the 100% of the action. So it would move to far but the action does not do this it set the final position and thats what it should do. Thats why it does not look fluent.
So how to solve this issue?
By decreasing the updatetime the "to far movement" decreases too because the steplength is getting smaller. So i need to increase the updatespeed above the 60fps. Luckily i got an thread for my updating of the figures and positions and so on. GameLogicThread. This ran on 60fps too. So i solved the stuttering by increasing it's frequence. up to around 210fps at the moment so the "overstep" is minimal. You can't even notice it.
To Show how my thread works:
public class GameLogicThread extends Thread
{
private GameScreen m_screen;
private boolean m_runing;
private long m_timeBegin;
private long m_timeDiff;
private long m_sleepTime;
private final static float FRAMERATE = 210f;
public GameLogicThread(GameScreen screen)
{
m_screen = screen;
setName("GameLogic");
}
#Override
public void run()
{
m_runing = true;
Logger.log("Started");
while (m_runing)
{
m_timeBegin = TimeUtils.millis();
// hanlde events
m_screen.m_main.handler.processEvents();
synchronized (m_screen.figureStage)
{
// now figures
if (m_screen.m_status == GameStatus.GAME)
{
m_screen.character.myAct(1f / GameLogicThread.FRAMERATE);// and here it is ;)
m_screen.figureStage.act(1f / GameLogicThread.FRAMERATE);
}
}
m_timeDiff = TimeUtils.millis() - m_timeBegin;
m_sleepTime = (long) (1f / GameLogicThread.FRAMERATE * 1000f - m_timeDiff);
if (m_sleepTime > 0)
{
try
{
Thread.sleep(m_sleepTime);
}
catch (InterruptedException e)
{
Logger.error("Couldn't sleep " + e.getStackTrace());
}
}
else
{
Logger.error("we are to slow! " + m_sleepTime);
}
}
}
public void stopThread()
{
m_runing = false;
boolean retry = true;
while (retry)
{
try
{
this.join();
retry = false;
}
catch (Exception e)
{
Logger.error(e.getMessage());
}
}
}
}
I am programming a game, but I have ran into an error.
When the player collided with an object, player.hasCollided is set to true.
if(playerBounds.intersects(wolfBounds)){
player.hasCollided = true;
player.dead();
}
Now, when hasCollided is true, something from the LoseScreen class is printed out onto the screen:
if(player.hasCollided){
lose.start(g);
}
In player.dead(), the player's speed is set to 0.
public void dead(){
playerSpeed = 0;
coinBank += coinsCollected;
}
The problem is that in my InputHandler class I make it so that on the lose screen, when the choice is 1, and enter is pressed, restartGame() is called.
public void restartGame(){
obstacleWolf.getNewPosition();
obstacleHole.getNewPosition();
hasLost = false;
player.hasCollided = false;
player.playerSpeed = 5;
player.nextX = 1000;
player.coinsCollected = 0;
player.xElapsed = 0;
}
if(lose.choice == 1 && enter){
game.hasLost = false;
game.restartGame();
System.out.println(player.hasCollided + " " + player.playerSpeed);
}
Those variables ARE being set to what they are meant to be set to (for example playerSpeed becomes 5 from 0, and hasCollided is becoming false from true) but the effects are not taking place. So, like I showed before, lose.start(g); is only meant to be called when hasCollided is true, but even when it becomes false, it is still printed out on the screen.
Here is how the relevant variables/methods are being used:
public void move() {
x = x - player.playerSpeed;
}
(All moving objects share the same move method)
Parts of the game class:
public void tick(){
input.tick();
if(gameState){
player.tick();
player.move();
collision();
treeline.move();
obstacleHole.move();
obstacleWolf.move();
coin.move();
coin.tick();
}
I am not sure if I can make this question clearer. I can provide more code from different classes if needed.
The question can't be answered in its current form (see 2 comments above).
The reason for that is current code structure.
You need to refactor code, then you will find the problem.
Put all modification of player fields in methods of Player class.
Access fields only through methods. Making fields private is old good practice.
Then the only code you need to share would be this Player class.
In one thread environment, that's all.