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

2018/6/5

Complicated problem. Pls help!

Chrizzi Chrizzi

2018/6/5

#
Hello, I made a Little game with greenfoot and I programmed a save-file System, that the game 'remembers' where the Player was and that stuff. It works Pretty good, except one Thing: At this Point of time, the Actor respawns at the same Point in every Level (A new Level is a new world-class), and I wanted to make, that I can make him respawn at other Points of the Level (For example if there are 2 layers in a Level). There are some txt files in the game Folder, which save the stats of the Actor. There are 6, but only 2 of them matter, because These 2 are for the coordinates and the other 4 ones do what they should do. The 2 file-names are in a Folder named 'SOOS' and the names of them are '0xFF_ReX.txt' and '0yFF_ReY.txt'. Another important Information is, that Java io is used to write and read the files. I used These 3 functions and pasted them in every class that Needs to Change any game file:
void write(String dir, String txt) {
        String fileName = dir;
        try {
            FileWriter fileWriter =
                new FileWriter(fileName);
            BufferedWriter bufferedWriter =
                new BufferedWriter(fileWriter);                            
            bufferedWriter.write(txt);

            bufferedWriter.close();
        }
        catch(IOException ex) {
            System.out.println(
                "Error writing to file '"
                + fileName + "'");
        }
    }
    String read(String dir) {
        String fileName = dir;
        String line = null;
        try {
            FileReader fileReader = 
                new FileReader(fileName);
            BufferedReader bufferedReader = 
                new BufferedReader(fileReader);
            while((line = bufferedReader.readLine()) != null) {
                return line;
            }   
            bufferedReader.close();         
        }
        catch(FileNotFoundException ex) {
            System.out.println(
                "Unable to open file '" + 
                fileName + "'");                
        }
        catch(IOException ex) {
            System.out.println(
                "Error reading file '" 
                + fileName + "'");                  
        }
        return line;
    }
    int convertStr(String dir){
        String str = read(dir);
        int value = Integer.parseInt(str);
        return value;
    }
Here's an Explanation how to use them: write("",""), read("") The 3rd function called convertStr only converts a string to int, it is used, because if I save a number in the file, it is saved as a String, but to use it, I have this function. I have 3 classes, that are involved in my Problem, the word Level1() (Level1() is an example, all Levels use the same respawn-system), the Actor updateFile and the Actor Teleport(). UpdateFile() is an invisible Actor and is used to Change the respawn-coordinates in the next Level. The file-update gets triggered, when this Actor is touched by the Player. Teleport() is used to load the next Level, when it's touched. But it isn't that important in the Problem, you just Need to know, that it uses the function Greenfoot.setWorld() to load the next Level. The world Name is set in the constructor of teleport(). Now I will Show you, how the updateFile class manipulates the 2 files. I will Show you the whole Code of this class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.io.*;
/**
 * Write a description of class UpdateFile here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class UpdateFile extends Actor
{
    int nx;
    int ny;
    String xs;
    String ys;
    float once;
    /**
     * Act - do whatever the UpdateFile wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
        this.getImage().clear();
        if(collisionDetection(Marcel.class)&&once==0){
            xs = "" + nx;
            ys = "" + ny;
            Greenfoot.delay(5);
            write("SOOS/0xFF_ReX.txt",xs);
            write("SOOS/0yFF_ReY.txt",ys);
            once++;
        }
    }    
    public UpdateFile(int nextX, int nextY){
        nx = nextX;
        ny = nextY;
        xs = "" + nx;
        ys = "" + ny;
        once = 0;
    }
        void write(String dir, String txt) {
        String fileName = dir;
        try {
            FileWriter fileWriter =
                new FileWriter(fileName);
            BufferedWriter bufferedWriter =
                new BufferedWriter(fileWriter);                            
            bufferedWriter.write(txt);

            bufferedWriter.close();
        }
        catch(IOException ex) {
            System.out.println(
                "Error writing to file '"
                + fileName + "'");
        }
    }
    String read(String dir) {
        String fileName = dir;
        String line = null;
        try {
            FileReader fileReader = 
                new FileReader(fileName);
            BufferedReader bufferedReader = 
                new BufferedReader(fileReader);
            while((line = bufferedReader.readLine()) != null) {
                return line;
            }   
            bufferedReader.close();         
        }
        catch(FileNotFoundException ex) {
            System.out.println(
                "Unable to open file '" + 
                fileName + "'");                
        }
        catch(IOException ex) {
            System.out.println(
                "Error reading file '" 
                + fileName + "'");                  
        }
        return line;
    }
    int convertStr(String dir){
        String str = read(dir);
        int value = Integer.parseInt(str);
        return value;
    }
    boolean collisionDetection(java.lang.Class thing){
        Actor stuff = getOneIntersectingObject(thing);
        return stuff != null;
    }
}
Basically, it uses the function write() to save the x and y coords to the 2 files, when the Player touches this class. The new x and y coords are defined in the constructor. Now, let me explain you, how the world adds the Player object at the specific coordinates: addObject(mar, convertStr("SOOS/0xFF_ReX.txt"), convertStr("SOOS/0yFF_ReY.txt")); It just uses this Code, which reads the 2 txt files and adds the Player class at These 2 coordinates. It is called in the world constructor and is used in every word class. mar is the variable for the Player. The Player class is called Marcel, so this is the variable in the world class: Marcel mar = new Marcel();. Just as simple as that. Now you hopefully know everything you Need to know to help me fix my Problem. The Basic Problem is, that the updateFile class saves the Location perfectly, when the Player touches it, but when the Player uses teleport() to go to the next Level, it still respawns him at the old Location, not on the one, that was just saved. Another strange Thing, that happens, is that the world respawns the Player at the new Location, when I reset the game using the button. So the coords can just be used to respawn the Player after the game gets resetted, so I hope, there's anyone who can help me fix this Problem. If you have some other Questions, how exactly the save-System works, or if something is still not clear, feel free to ask me.
Chrizzi Chrizzi

2018/6/5

#
Please help, I tried so many things, so maybe a more experienced programmer can help me.
danpost danpost

2018/6/5

#
I can understand having a save system for resuming a game. That which I do not understand is using it between levels. Also, one file should be sufficient to store a paused game (or even a number of paused games). And it should only be updated (written to) when a game is being paused. If you want to add your actor to a specific new location when a new world in created, then let it be added where it will and reset its location in the new world:
World world = new MyWorld(); // create new world
Actor player= world.getPlayer(); // get reference to player
player.setLocation(30, 360); // reset its location (wherever)
Chrizzi Chrizzi

2018/6/5

#
Thank you for the answer. There's just a little problem with the method you showed me, because when the game gets saved, for example at x=100 and y=250 and the game gets reloaded, the actor would still respawn at x=30, y=360. And the reson I want to use the save-system between levels is, that I had the idea to use the saved coordinates to set the location in every level, when it gets loaded, for example, let's say, the actor spawns in Level1 at x=100, y=400, but I want him to spawn at a different location in Level2, for example x=50, y=700, then I would use the updateFile class in Level1, just before the actor touches the teleport class, that his coordinates get updated to x=50, y=700, just before he gets taken to Level2, that he would respawn there. In theory, it would work, but as I said, the coordinates only get updated, if I reset the game or close it.
danpost danpost

2018/6/6

#
I really do not see why you cannot just add the actor (or set its location) from the constructor of the level (being they are different world classes).
Chrizzi Chrizzi

2018/6/6

#
The actor is added in the world constructor, by reading the saved x and y coords. For example if I have this code in the world constructor: this.addObject(mar, 100, 100) (mar is the variable of the player in my game), and if I would save the game in this level, by touching a checkpoint class (This class saves all character stats when touched, basically like the updateFile class, but updateFile just saves the coordinates and it is invisible), I want the character to respawn at the location of the checkpoint, not on the fixed coordinates from the world constructor. This save system works pretty well, but the problem is the coordinate updating when going to a new level. As I said earlier, the file only gets updated, when the game gets resetted, so I have an idea. Is there any method, that does the same thing as pressing reset? If there is one, I could trigger it, when the coordinates get updated and after the reset, I would start the game again, if there is such a method. Sorry for the complicated explanation xD. If you want, I can send you the game, that you can see how it works.
danpost danpost

2018/6/6

#
From the sounds of it, you need a way such that there are two starting positions for Marcel -- the initial one and the saved one. The easiest way to do that is to have multiple (two) constructors in the initial world class -- one for the initial start and one to resume (reading file coordinates).
Chrizzi Chrizzi

2018/6/6

#
That's a good idea. I will try that one.
Chrizzi Chrizzi

2018/6/6

#
I have another question, I hope, it isn't that complicated this time xD. I need some kind of wait method, that only pauses the class in which it's written. I know, that there's Greenfoot.delay(), but it pauses the whole game. So is it possible to make such a method?
danpost danpost

2018/6/6

#
Chrizzi wrote...
I have another question, I hope, it isn't that complicated this time xD. I need some kind of wait method, that only pauses the class in which it's written. I know, that there's Greenfoot.delay(), but it pauses the whole game. So is it possible to make such a method?
Just add a timer field to the class:
private int waitTimer;
To start a waiting period, use:
waitTimer = 60*10; // for 10 seconds (adjust 10 to whatever)
Then add the following to be the first line of the act method in the class:
if (waitTimer > 0 && --waitTimer > 0) return;
Chrizzi Chrizzi

2018/6/6

#
danpost wrote...
From the sounds of it, you need a way such that there are two starting positions for Marcel -- the initial one and the saved one. The easiest way to do that is to have multiple (two) constructors in the initial world class -- one for the initial start and one to resume (reading file coordinates).
Ok, maybe I'm missing something, or this is more complicated than I expected it to be. Could you send me an example code for that?
danpost danpost

2018/6/6

#
Chrizzi wrote...
Could you send me an example code for that?
import greenfoot.*;

public class GWaiter()
{
    private int waitTimer;
    
    public void act()
    {
        if (waitTimer > 0 && --waitTimer > 0) return; // run delay
        move(2); // move
        turn(Greenfoot.getRandomNumber(21)-10); // random turn
        if (isAtEdge()) turn(135+Greenfoot.getRandomNumber(90)); // edge turn
        if (Greenfoot.isKeyDown("g")) waitTimer = 60*10; // set delay
    }
}
The actor will do what it is supposed to (move and turn) until the "g" key is pressed, when it will stop for about 10 seconds.
Chrizzi Chrizzi

2018/6/6

#
Thank you, but I actually meant the idea with the 2 constructors in the world class
danpost danpost

2018/6/6

#
Chrizzi wrote...
Thank you, but I actually meant the idea with the 2 constructors in the world class
import greenfoot.*;

public class Level1 extends World
{
    public Level1()
    {
        this(false);
    }
    
    public Level1(boolean resuming)
    {
        super(600, 400);
        int marX = 100;
        int marY = 400;
        if (resuming)
        {
            marX = read("SOOS/0xFF_ReX.txt");
            marY = read("SOOS/0xFF_ReY.txt");
        }
        addObject(new Marcel(), marX, marY);
    }
}
To restart, create a new world with:
new Level1(false);
and to resume, use:
new Level1(true);
Chrizzi Chrizzi

2018/6/6

#
Thank you very much :)
You need to login to post a reply.