<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Greenfoot Discuss</title>
    <link>https://greenfoot.org/topics</link>
    <description>The latest Greenfoot discussion posts</description>
    <language>en-us</language>
    <item>
      <title>Reply to Hello again!</title>
      <description>I think what he means is that even though the source wasn&amp;amp;#39;t uploaded, since it was a jar file uploaded and viewable with a java applet viewer, if you download the jar you can &amp;amp;quot;decompile&amp;amp;quot; it and get the source from there (since a jar is pretty much a zip archive with the code and some other stuff on top). Am i right @jetlennit?

I am on the same journey btw lol with reviving/looking at old projects. I did know how to use github(barely) so i had the source saved, just never uploaded the project because i did file-based score tracking. I upgraded it to the latest greenfoot, fixed it since i know how to code now and uploaded it recently.

10 years have passed since my very first complete project which i just uploaded here. Thank you danpost, you&amp;amp;#39;ve helped me back in the day too, I&amp;amp;#39;m a software engineer now and pretty much started with greenfoot!</description>
      <author>mehanix</author>
      <pubDate>Tue, 08 Sep 2026 18:06:37 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151056#post_151056</link>
    </item>
    <item>
      <title>Reply to Hello again!</title>
      <description>&lt;div class="bb_quote"&gt;&lt;div class="bb_quote_header"&gt;JetLennit wrote...&lt;/div&gt;made the changes for compatibility with new Greenfoot (java.awt.Color is no longer acceptable vs greenfoot.Color it seems)&lt;/div&gt;Actually, it is &lt;span class="bb_underline"&gt;javascript&lt;/span&gt; security measures that disallow any use of &lt;span class="bb_italic"&gt;java.awt&lt;/span&gt; and &lt;span class="bb_italic"&gt;javax.swing&lt;/span&gt; packages.

&lt;div class="bb_quote"&gt;&lt;div class="bb_quote_header"&gt;JetLennit wrote...&lt;/div&gt;It also seems as though the jar files are still hosted on the Greenfoot server, just hidden from view.&lt;/div&gt;I am not too sure on that.  I was under the understanding that they were not uploaded to the site when the source code was not included as per a &lt;span class="bb_italic"&gt;Greenfoot&lt;/span&gt; team member.</description>
      <author>danpost</author>
      <pubDate>Sun, 06 Sep 2026 21:09:26 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151055#post_151055</link>
    </item>
    <item>
      <title>Reply to Hello again!</title>
      <description>For anyone else curious there is a way to do this (though convoluted)!  I used the Wayback machine to view an old version of my game&amp;amp;#39;s page, found the jar file in the code of the page, downloaded the jar, decompiled that, imported the project in Greenfoot, then made the changes for compatibility with new Greenfoot (java.awt.Color is no longer acceptable vs greenfoot.Color it seems). 

I do wonder if downloading a legacy version of Greenfoot would remove that last step. I&amp;amp;#39;ll find out later when I&amp;amp;#39;m on not on an ARM based Mac.

Edit: Seems clicking &amp;amp;quot;View Applet&amp;amp;quot; does the same thing as dealing with Wayback machine... that would&amp;amp;#39;ve saved me some time if I&amp;amp;#39;d been paying attention

It also seems as though the jar files are still hosted on the Greenfoot server, just hidden from view.</description>
      <author>JetLennit</author>
      <pubDate>Sat, 05 Sep 2026 14:50:44 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151054#post_151054</link>
    </item>
    <item>
      <title>Reply to Hello again!</title>
      <description>Understood, appreciate the response! I remember back in the day you could get the jar from the webpage but I think since it is all HTML now that it isn&amp;amp;#39;t there anymore. Recreating could be fun, haven&amp;amp;#39;t done game programming in a while and I&amp;amp;#39;ve been itching to try Raylib! Maybe this time I&amp;amp;#39;ll actually spell the words right lol</description>
      <author>JetLennit</author>
      <pubDate>Sat, 05 Sep 2026 14:10:18 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151053#post_151053</link>
    </item>
    <item>
      <title>Reply to Black screen with truncated error: &amp;quot;lass: java.lang.RuntimeException - (JavaScrip&amp;quot; </title>
      <description>To track down the cause of the `&lt;span class="bb_italic"&gt;RuntimeException&lt;/span&gt;` I added some `&lt;span class="bb_italic"&gt;System.out.println(&amp;amp;quot;start of Intro()&amp;amp;quot;)&lt;/span&gt;` statements to the constructor of my initial world class. They should have shown up in the browser console. But they did not. So I figured the issue must be in the static code of my initial world class. By trial and error I found out it was the `&lt;span class="bb_italic"&gt;static final&lt;/span&gt;` keywords for the world background `&lt;span class="bb_italic"&gt;GreefootImage&lt;/span&gt;` and &lt;span class="bb_italic"&gt;GreenfootSound&lt;/span&gt;`. Here is a diff:  

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;ndex 4d57810..4781524 100644
@@ -8,8 +8,8 @@ import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
  */
 public class Intro extends World
 {
-    static final GreenfootImage BG_IMAGE = new GreenfootImage(&amp;amp;quot;touhou_opening.png&amp;amp;quot;);
-    static final GreenfootSound BG_SOUND = new GreenfootSound(&amp;amp;quot;dova_nikki_full_mix_30sec.mp3&amp;amp;quot;);
+    GreenfootImage BG_IMAGE = new GreenfootImage(&amp;amp;quot;touhou_opening.png&amp;amp;quot;);
+    GreenfootSound BG_SOUND = new GreenfootSound(&amp;amp;quot;dova_nikki_full_mix_30sec.mp3&amp;amp;quot;);
     static final int WIDTH = 700;
     static final int HEIGHT = 700;
     static final int VOLUME = 60;&lt;/pre&gt;&lt;/div&gt;
I don&amp;amp;#39;t understand why those `&lt;span class="bb_italic"&gt;static final&lt;/span&gt;` are an issue especially since they work well elsewhere. But nevertheless, I was some step further.

In order to even come so far, I had to find out and fix some other restrictions of the HTML5 runtime.

First I had to remove dependencies to &lt;span class="bb_italic"&gt;java.nio.*&lt;/span&gt; and &lt;span class="bb_italic"&gt;java.awt.*&lt;/span&gt;. For example, to open files I had to use `&lt;span class="bb_italic"&gt;InputStream&lt;/span&gt;` instead of `&lt;span class="bb_italic"&gt;Files.readString()&lt;/span&gt;`

Here is a diff:

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;---------------------------- touhou/FileReader.java ----------------------------
index fc3b427..5c8d52b 100644
@@ -1,6 +1,6 @@
 import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
-import java.nio.file.*;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -93,16 +93,23 @@ public class FileReader extends Actor
     {
         try
         {
-            String content = Files.readString(Path.of(filename));
-            int size;
+            InputStream input = getClass().getClassLoader().getResourceAsStream(filename);
+
+            if (input == null)
+            {
+                System.out.println(&amp;amp;quot;File not found: &amp;amp;quot; + filename);
+                return;
+            }
+
+            String content = new String(input.readAllBytes());
+            input.close();
 
             segments = parse(content);
             textHeight = 0;
 
-
             for (FontSegment segment : segments)
             {
-                size = segment.font.getSize();
+                int size = segment.font.getSize();
 
                 if (segment.text.equals(&amp;amp;quot;\n&amp;amp;quot;))
                 {
&lt;/pre&gt;&lt;/div&gt;
In my local version I used `&lt;span class="bb_italic"&gt;Desktop.getDesktop().browse(uri)&lt;/span&gt;` to allow the user to open links to used artwork in my &amp;amp;quot;Credits&amp;amp;quot; view. I had to drop this completely, because it is not possible to open links in HTML5. And it is even not possible to have code depending on the runtime environment. Say to support opening links in the local Greenfoot environment and to drop this support only in HTML5 environment.

And there were more issues to solve.

In Greenfoot you can use &amp;amp;quot;Set image...&amp;amp;quot; in the class view to assign an image to a class. But this image is not picked up in the HTML5 runtime. Here is a diff showing what I had to change:

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;------------------------------ touhou/Bullet.java ------------------------------
index e790eca..ad5b2ca 100644
@@ -7,14 +7,17 @@ import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
  */
 public class Bullet extends Actor
 {
+    static GreenfootImage BULLET = new GreenfootImage(&amp;amp;quot;button-purple.png&amp;amp;quot;);
     protected int speed = 15;
 
-    Bullet()
+    static
     {
-        GreenfootImage image;
+        BULLET.scale(7, 7);
+    }
 
-        image = getImage();
-        image.scale(7, 7);
+    Bullet()
+    {
+        setImage(BULLET);
         setRotation(270);
     }
&lt;/pre&gt;&lt;/div&gt;

Also I learned that `&lt;span class="bb_italic"&gt;UserInfo.getMyInfo()&lt;/span&gt;` returns `&lt;span class="bb_italic"&gt;null&lt;/span&gt;` if the player is not logged in. So I had to fix a null pointer exception:

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;----------------------------- touhou/MyWorld.java -----------------------------
index 1657634..67567d6 100644
@@ -408,7 +408,7 @@ public class MyWorld extends World
                             myInfo = UserInfo.getMyInfo();
                             score = scoreCounter.getValue();
 
-                            if (score &amp;amp;gt; myInfo.getScore())
+                            if (myInfo != null &amp;amp;amp;&amp;amp;amp; score &amp;amp;gt; myInfo.getScore())
                             {
                                 myInfo.setScore(score);
                                 /* write back to server */&lt;/pre&gt;&lt;/div&gt;
A very important lesson I learned is: Do not block!

In local Greenfoot, waiting for `&lt;span class="bb_italic"&gt;Greenfoot.isKeyDown()&lt;/span&gt;` in a while loop works because the simulation runs on a separate thread. In HTML5, there is only one thread — the simulation loop itself. So the while loop blocks everything, `&lt;span class="bb_italic"&gt;isKeyDown()&lt;/span&gt;` never updates, and the loop never exits → browser timeout.

Here is how I solved it:

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;------------------------------ touhou/Intro.java ------------------------------
index 8612fdc..9d37034 100644
@@ -19,6 +19,7 @@ public class Intro extends World
     Credits credits;
     License license;
     int frameCount;
+    boolean soundStopped = false;
 
     enum intro
     {
@@ -70,15 +71,20 @@ public class Intro extends World
                 {
                     showText(null, getWidth() / 2, getHeight() / 2);
                     BG_SOUND.stop();
+                }
 
-                    while (BG_SOUND.isPlaying())
-                        /* wait */
-                        ;
+                frameCount++;
 
-                    Greenfoot.setWorld(new MyWorld());
+                if (!soundStopped)
+                {
+                    soundStopped = !BG_SOUND.isPlaying();
+                    /* wait till sound stopped */
+                    break;
                 }
 
-                frameCount++;
+                /* reset sound state for next turn */
+                soundStopped = false;
+                Greenfoot.setWorld(new MyWorld());
                 break;
 
             default:&lt;/pre&gt;&lt;/div&gt;

You can find my code and all changes in my &lt;a href="https://gitlab.com/video-games-playshop/tohuwabohu/"&gt;Gitlab repository&lt;/a&gt;</description>
      <author>lmoellendorf</author>
      <pubDate>Thu, 03 Sep 2026 21:33:32 +0000</pubDate>
      <link>https://greenfoot.org/topics/66684?pid=151052#post_151052</link>
    </item>
    <item>
      <title>Reply to Hello again!</title>
      <description>Greetings, JetLennit.  Two of your scenarios where uploaded with the source code being made available.  These are &lt;a href="https://www.greenfoot.org/scenarios/8395"&gt;KeyTyping&lt;/a&gt; and &lt;a href="https://www.greenfoot.org/scenarios/8055"&gt;Cool Colorfull Squares&lt;/a&gt;.  You can click the big green &lt;span class="bb_italic"&gt;Greenfoot&lt;/span&gt; buttons near top right to download the source code.  Just open downloaded file in greenfoot application, where you can then create an executable jar file from.

I do not know, and kind of doubt, that you will be able to regain the source from your other scenarios.  You could try to recreate them as you remember them as being, but that would not be the same, especially if it is for the memories.</description>
      <author>danpost</author>
      <pubDate>Thu, 03 Sep 2026 01:31:50 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151051#post_151051</link>
    </item>
    <item>
      <title>Reply to Hello again!</title>
      <description>Hello Greenfoot users! I was wondering if there is any way I could get the old jar files from my games? Most of them don&amp;amp;#39;t run in browser any more. The code has been missing for over 10 years at this point and I&amp;amp;#39;m feeling nostalgic for where it all started. Is there someone I should try and contact? I see the owners are different now as far as I can tell so I haven&amp;amp;#39;t the foggiest on who I should talk to. Thanks!

P.S. If you see this danpost, I cannot thank you enough for the help you provided me as a kid and I&amp;amp;#39;m sure countless other aspiring programmers.</description>
      <author>JetLennit</author>
      <pubDate>Wed, 02 Sep 2026 21:09:25 +0000</pubDate>
      <link>https://greenfoot.org/topics/66685?pid=151050#post_151050</link>
    </item>
    <item>
      <title>Reply to Black screen with truncated error: &amp;quot;lass: java.lang.RuntimeException - (JavaScrip&amp;quot; </title>
      <description>How can I debug this?

The game runs fine locally, but the HTML5 version fails. No helpful console output. Only the truncated error message:

&amp;amp;quot;lass: java.lang.RuntimeException - (JavaScrip&amp;amp;quot;

The game is here:

https://www.greenfoot.org/scenarios/36670</description>
      <author>lmoellendorf</author>
      <pubDate>Tue, 01 Sep 2026 20:28:33 +0000</pubDate>
      <link>https://greenfoot.org/topics/66684?pid=151049#post_151049</link>
    </item>
    <item>
      <title>Reply to Publish failed: Invalid username or password</title>
      <description>My bad:

email-address != username

I tried to login with my email address instead of the username</description>
      <author>lmoellendorf</author>
      <pubDate>Tue, 01 Sep 2026 19:51:16 +0000</pubDate>
      <link>https://greenfoot.org/topics/66683?pid=151048#post_151048</link>
    </item>
    <item>
      <title>Reply to Publish failed: Invalid username or password</title>
      <description>I try to publish my first game and get this error:

Publish failed: Invalid username or password

But I use the same credentials as I use here on this website and I copy them from the same password manager.

Are there any restrictions regarding special characters in passwords or password length in Greenfoot, which do not apply to the website?</description>
      <author>lmoellendorf</author>
      <pubDate>Tue, 01 Sep 2026 14:20:19 +0000</pubDate>
      <link>https://greenfoot.org/topics/66683?pid=151047#post_151047</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>can anyone help me out to answer this question

can we say actor which is moving upward or downward as moving left or right</description>
      <author>Shifashaikh</author>
      <pubDate>Fri, 07 Aug 2026 14:28:05 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151045#post_151045</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>No 4
Gudang()
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;import java.util.ArrayList;
import java.util.List;

/**
 * Tugas Anda (b): generic class yang hanya boleh menyimpan SATU jenis
 * barang (dijamin compiler lewat &amp;amp;amp;lt;T extends Barang&amp;amp;amp;gt;).
 */
public class Gudang&amp;amp;lt;T extends Barang&amp;amp;gt; {

    private List&amp;amp;lt;T&amp;amp;gt; daftarBarang = new ArrayList&amp;amp;lt;&amp;amp;gt;();

    public void tambah(T item) {
        // TODO (b): tambahkan item ke daftarBarang.
        daftarBarang.add(item);
    }

    public T get(int index) {
        // TODO (b): kembalikan barang pada index tersebut.
        return daftarBarang.get(index);
    }

    /** Total harga seluruh barang di gudang ini. */
    public double totalNilai() {
        // TODO (b): jumlahkan getHarga() seluruh isi daftarBarang.
        double total = 0;

    for (T barang : daftarBarang) {
        total += barang.getHarga();
        }

        return total;
    }

    public int jumlahBarang() {
        return daftarBarang.size();
    }
}
&lt;/pre&gt;&lt;/div&gt;
UtilGudang()
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;import java.util.Collections;
import java.util.List;

/** Kumpulan generic method utility yang bekerja di atas Gudang jenis apa pun. */
public class UtilGudang {

    /**
     * Tugas Anda (c): generic method dengan upper bound. Kembalikan barang
     * dengan harga tertinggi dari daftar. Asumsikan daftar tidak kosong.
     */
    public static &amp;amp;lt;T extends Barang&amp;amp;gt; T cariTermahal(List&amp;amp;lt;T&amp;amp;gt; daftar) {
        T termahal = daftar.get(0);

        for (T barang : daftar) {
            if (barang.getHarga() &amp;amp;gt; termahal.getHarga()) {
            termahal = barang;
            }
        }

        return termahal;
    }

    /**
     * Tugas Anda (c): generic method dengan wildcard. Jumlahkan totalNilai()
     * dari SELURUH gudang pada daftarGudang, walaupun tiap gudang berisi
     * jenis barang yang berbeda-beda (Elektronik, Fashion, dst).
     */
    public static double totalNilaiSemuaGudang(List&amp;amp;lt;Gudang&amp;amp;lt;? extends Barang&amp;amp;gt;&amp;amp;gt; daftarGudang) {
        double total = 0;

        for (Gudang&amp;amp;lt;? extends Barang&amp;amp;gt; gudang : daftarGudang) {
            total += gudang.totalNilai();
        }

        return total;
    }

    /**
     * (Bonus, Tugas d) generic method dengan multiple bound: T harus berupa
     * Barang SEKALIGUS Comparable&amp;amp;amp;lt;T&amp;amp;amp;gt;. Urutkan daftar secara ascending
     * memakai Comparable-nya sendiri (mis. Collections.sort).
     */
    public static &amp;amp;lt;T extends Barang &amp;amp;amp; Comparable&amp;amp;lt;T&amp;amp;gt;&amp;amp;gt; void urutkanNaik(List&amp;amp;lt;T&amp;amp;gt; daftar) {
        Collections.sort(daftar);
    }
}
&lt;/pre&gt;&lt;/div&gt;
Elektronik()
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;/**
 * Tugas Anda (a): implementasikan Barang dan Comparable&amp;amp;amp;lt;Elektronik&amp;amp;amp;gt;
 * (compareTo berdasarkan harga, ascending).
 */
public class Elektronik implements Barang, Comparable&amp;amp;lt;Elektronik&amp;amp;gt; {

    private String nama;
    private double harga;
    private double berat;

    public Elektronik(String nama, double harga, double berat) {
        // TODO (a): inisialisasi field.
        this.nama = nama;
        this.harga = harga;
        this.berat = berat;
    }

    @Override
    public String getNama() {
        return nama;
    }

    @Override
    public double getHarga() {
        return harga;
    }

    @Override
    public double getBerat() {
        return berat;
    }

    @Override
    public int compareTo(Elektronik lainnya) {
        // TODO (a): bandingkan berdasarkan harga (ascending).
        return Double.compare(this.harga, lainnya.harga);
    }

    @Override
    public String toString() {
        return getNama() + &amp;amp;quot; (Rp&amp;amp;quot; + getHarga() + &amp;amp;quot;)&amp;amp;quot;;
    }
}
&lt;/pre&gt;&lt;/div&gt;</description>
      <author>arumsari</author>
      <pubDate>Wed, 05 Aug 2026 06:13:25 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151044#post_151044</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>No 3 
PendaftaranProcessor()
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Memproses file pendaftaran peserta HackFest: membaca, memvalidasi, dan
 * menulis laporan. Ini adalah file utama yang Anda kerjakan.
 */
public class PendaftaranProcessor {

    private List&amp;amp;lt;Peserta&amp;amp;gt; pesertaDiterima = new ArrayList&amp;amp;lt;&amp;amp;gt;();

    public List&amp;amp;lt;Peserta&amp;amp;gt; getPesertaDiterima() {
        return pesertaDiterima;
    }

    /**
     * Tugas Anda (a, b, c): baca namaFile baris demi baris. Format tiap
     * baris: Nama,Umur,Kategori,BiayaPendaftaran
     *
     * - (a) Tangani FileNotFoundException: cetak &amp;amp;quot;File peserta tidak
     *   ditemukan!&amp;amp;quot;, program tidak boleh crash.
     * - (b) Tangani NumberFormatException saat parsing Umur/BiayaPendaftaran:
     *   cetak &amp;amp;quot;Data tidak valid pada baris ke-N (Nama), baris dilewati.&amp;amp;quot;
     *   lalu lanjut ke baris berikutnya.
     * - (c) Validasi umur (17-25); jika di luar rentang, lempar dan tangkap
     *   UmurTidakValidException, cetak &amp;amp;quot;Pendaftaran [Nama] ditolak: umur
     *   tidak memenuhi syarat (17-25 tahun).&amp;amp;quot;, baris dilewati.
     * - Baris yang valid ditambahkan ke pesertaDiterima.
     */
    public void prosesFile(String namaFile) {
        try {
            Scanner scanner = new Scanner(new File(namaFile));
            int baris = 1;

            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();

                try {
                    String[] data = line.split(&amp;amp;quot;,&amp;amp;quot;);

                    String nama = data[0];
                    int umur = Integer.parseInt(data[1]);
                    String kategori = data[2];
                    double biaya = Double.parseDouble(data[3]);

                    if (umur &amp;amp;lt; 17 || umur &amp;amp;gt; 25) {
                        throw new UmurTidakValidException(
                                &amp;amp;quot;Pendaftaran &amp;amp;quot; + nama +
                                &amp;amp;quot; ditolak: umur tidak memenuhi syarat (17-25 tahun).&amp;amp;quot;);
                    }

                    pesertaDiterima.add(
                            new Peserta(nama, umur, kategori, biaya)
                    );

                } catch (NumberFormatException e) {
                    String nama = line.split(&amp;amp;quot;,&amp;amp;quot;)[0];
                    System.out.println(
                            &amp;amp;quot;Data tidak valid pada baris ke-&amp;amp;quot; +
                            baris + &amp;amp;quot; (&amp;amp;quot; + nama + &amp;amp;quot;), baris dilewati.&amp;amp;quot;);
                } catch (UmurTidakValidException e) {
                    System.out.println(e.getMessage());
                }

                baris++;
            }

            scanner.close();

        } catch (FileNotFoundException e) {
            System.out.println(&amp;amp;quot;File peserta tidak ditemukan!&amp;amp;quot;);
        }

    }

    /**
     * Tugas Anda (d): tulis file namaFileOutput berisi daftar nama peserta
     * pada pesertaDiterima beserta total biaya pendaftaran yang terkumpul.
     */
    public void tulisLaporan(String namaFileOutput) {
        try {
            PrintWriter writer = new PrintWriter(new FileWriter(namaFileOutput));

            for (Peserta p : pesertaDiterima) {
                writer.println(p.getNama());
            }

            writer.println(&amp;amp;quot;Total Biaya: &amp;amp;quot; + getTotalBiaya());

            writer.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Total biaya pendaftaran dari seluruh peserta yang diterima. */
    public double getTotalBiaya() {
        double total = 0;

        for (Peserta p : pesertaDiterima) {
            total += p.getBiayaPendaftaran();
        }

        return total;
    }
}
&lt;/pre&gt;&lt;/div&gt;</description>
      <author>arumsari</author>
      <pubDate>Wed, 05 Aug 2026 06:10:04 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151043#post_151043</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;/** Tugas Anda (b): valid bila nomorKartu 16 digit angka DAN belum expired. */
public class KartuKredit implements MetodePembayaran {

    private String nomorKartu;
    private boolean sudahExpired;

    public KartuKredit(String nomorKartu, boolean sudahExpired) {
        // TODO: inisialisasi field.
        this.nomorKartu = nomorKartu;
        this.sudahExpired = sudahExpired;
    }

    @Override
    public String getNamaMetode() {
        return &amp;amp;quot;Kartu Kredit&amp;amp;quot;;
    }

    @Override
    public boolean validasi() {
        // TODO (b): valid bila nomorKartu terdiri dari tepat 16 digit angka
        // DAN sudahExpired bernilai false.
        return nomorKartu.matches(&amp;amp;quot;\\d{16}&amp;amp;quot;) &amp;amp;amp;&amp;amp;amp; !sudahExpired;
    }

    @Override
    public StatusPembayaran prosesBayar(double nominal) {
        // TODO (b): bila !validasi() atau nominal &amp;amp;lt;= 0 -&amp;amp;gt; GAGAL.
        // Bila valid dan nominal &amp;amp;gt; 0 -&amp;amp;gt; SUKSES.
        if (!validasi() || nominal&amp;amp;lt;= 0){
            return StatusPembayaran.GAGAL;
        } else {
            return StatusPembayaran.SUKSES;
        }
    }
}
&lt;/pre&gt;&lt;/div&gt;
Kartu Kredit ()

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;import java.util.ArrayList;
import java.util.List;

/** Tugas Anda (c): implementasikan Repository&amp;amp;amp;lt;Reservasi&amp;amp;amp;gt;. */
public class ReservasiRepository implements Repository&amp;amp;lt;Reservasi&amp;amp;gt; {

    private List&amp;amp;lt;Reservasi&amp;amp;gt; items = new ArrayList&amp;amp;lt;&amp;amp;gt;();

    @Override
    public void save(Reservasi item) {
        // TODO (c): simpan item ke dalam items.
        items.add(item);
    }

    @Override
    public Reservasi findById(String id) {
        // TODO (c): cari dan kembalikan Reservasi dengan id yang cocok,
        // atau null bila tidak ditemukan.
        for (Reservasi reservasi : items){
            if (reservasi.getId().equals(id)){
                return reservasi;
            }
        }
        return null;
    }

    @Override
    public List&amp;amp;lt;Reservasi&amp;amp;gt; getAll() {
        // TODO (c): kembalikan seluruh isi items.
        return new ArrayList&amp;amp;lt;&amp;amp;gt;(items);
    }
}
&lt;/pre&gt;&lt;/div&gt;
ReservasiRepo()

&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;/** Mengorkestrasi pembuatan reservasi: validasi, bayar, simpan. */
public class ReservasiService {

    private ReservasiRepository repository;
    private int counter = 0;

    public ReservasiService(ReservasiRepository repository) {
        this.repository = repository;
    }

    /**
     * Tugas Anda (d): validasi metode pembayaran, proses pembayaran, set
     * status reservasi sesuai hasil prosesBayar(), simpan reservasi ke
     * repository, lalu kembalikan objek Reservasi tersebut (status sudah
     * final: SUKSES atau GAGAL).
     */
    public Reservasi buatReservasi(String namaPemesan, double totalHarga, MetodePembayaran metode) {
        if (!metode.validasi()) {
            Reservasi reservasi = new Reservasi(buatId(), namaPemesan, totalHarga, metode);
            reservasi.setStatus(StatusPembayaran.GAGAL);
            repository.save(reservasi);
            return reservasi;
        }
            StatusPembayaran status = metode.prosesBayar(totalHarga);
            Reservasi reservasi = new Reservasi(buatId(), namaPemesan, totalHarga, metode);
            reservasi.setStatus(status);
            repository.save(reservasi);
            return reservasi;
    }

    /** Helper pembuat ID reservasi, silakan dipakai di buatReservasi(). */
    protected String buatId() {
        counter++;
        return &amp;amp;quot;RSV-&amp;amp;quot; + System.currentTimeMillis() + &amp;amp;quot;-&amp;amp;quot; + counter;
    }
}
&lt;/pre&gt;&lt;/div&gt;
ReservasiService()</description>
      <author>arumsari</author>
      <pubDate>Wed, 05 Aug 2026 06:08:01 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151042#post_151042</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;/**
 * Rekap skor submission peserta CodeClash menggunakan ragged array.
 * skorSubmission[i].length = jumlah submission peserta ke-i (bisa berbeda
 * antar peserta, termasuk 0 bila belum pernah submit).
 */
public class Leaderboard {

    private String[] namaPeserta;
    private int[][] skorSubmission;

    public Leaderboard(String[] namaPeserta, int[][] skorSubmission) {
        this.namaPeserta = namaPeserta;
        this.skorSubmission = skorSubmission;
    }

    /** Tugas Anda (b): jumlahkan seluruh skor submission peserta ke-i. */
    public int totalSkor(int pesertaIndex) {
        // Ingat: SELALU pakai skorSubmission[pesertaIndex].length untuk
        // iterasi, jangan asumsikan semua peserta punya jumlah submission
        // yang sama.
        int totalSkor = 0;
        for (int i = 0; i &amp;amp;lt; skorSubmission[pesertaIndex].length; i++){
            totalSkor += skorSubmission[pesertaIndex][i];  
        }
        return totalSkor;        
    }

    /**
     * Tugas Anda (b): rata-rata skor submission peserta ke-i.
     * Kembalikan 0 bila peserta belum pernah submit.
     */
    public double rataRataSkor(int pesertaIndex) {
        double rataRata = 0;
        if (skorSubmission[pesertaIndex].length == 0){
            return rataRata;
        } else {
            rataRata = (double) totalSkor(pesertaIndex) / skorSubmission[pesertaIndex].length;
            return rataRata;
        }
    }

    /**
     * Tugas Anda (c): index submission dengan skor tertinggi milik peserta
     * ke-i. Kembalikan -1 bila peserta belum pernah submit.
     */
    public int submissionTerbaik(int pesertaIndex) {
        if (skorSubmission[pesertaIndex].length == 0) {
            return -1;
        }
        int maxSkor = skorSubmission[pesertaIndex][0];
        int indexMax = 0;
        for (int i = 1; i &amp;amp;lt; skorSubmission[pesertaIndex].length; i++) {
            if (skorSubmission[pesertaIndex][i] &amp;amp;gt; maxSkor) {
                maxSkor = skorSubmission[pesertaIndex][i];
                indexMax = i;
            }
        }
        return indexMax;
    }

    /**
     * Tugas Anda (c): index peserta dengan totalSkor() tertinggi se-leaderboard.
     * Bila seri, kembalikan index terkecil.
     */
    public int pesertaSkorTertinggi() {
        int maxTotalSkor = totalSkor(0);
        int indexMax = 0;
        for (int i = 1; i &amp;amp;lt; jumlahPeserta(); i++) {
            int totalSkor = totalSkor(i);
            if (totalSkor &amp;amp;gt; maxTotalSkor) {
                maxTotalSkor = totalSkor;
                indexMax = i;
            }
        }
        return indexMax;
    }

    public String getNamaPeserta(int index) {
        return namaPeserta[index];
    }

    public int jumlahPeserta() {
        return namaPeserta.length;
    }
}
&lt;/pre&gt;&lt;/div&gt;
itu CodeClash</description>
      <author>arumsari</author>
      <pubDate>Wed, 05 Aug 2026 06:06:03 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151041#post_151041</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>&lt;div class="bb_quote"&gt;&lt;div class="bb_quote_header"&gt;hafizz.hnn wrote...&lt;/div&gt;&amp;amp;lt;&amp;amp;lt; Code Omitted &amp;amp;gt;&amp;amp;gt;&lt;/div&gt;You can reduce the number of fields needed for the infectious state.  By using a single int field (instead of two boolean fields and an int timer field), you can have a value of -1 be the immune state, the value of 0 be the not immune nor infected state and any positive value being the running timer values for the infected state.  Something like the following:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;import greenfoot.*;

public class People extends Actor
{
    private int infectiousState;
    
    public People() {
        this(false);
    }
    
    public People(boolean state) {
        setInfectedState(state);
    }
    
    public void act() {
        runInfectionTimer();
        moveRandom();
        spreadInfection();
    }
    
    private void runInfectionTimer() {
        if (isInfected() &amp;amp;amp;&amp;amp;amp; ++infectiousState &amp;amp;gt; 200) setImmune(true);
    }
    
    private void moveRandom() {
        move(4);
        if (Greenfoot.getRandomNumber(100) &amp;amp;lt; 20) turn(Greenfoot.getRandomNumber(61)-30);
        if (isAtEdge()) turn(180);
    }
    
    private void spreadInfection() {
        if (!isInfected()) return;
        for (People p : getIntersectingObjects(People.class)) p.setInfected(true);
    }
    
    public boolean isNormal() {
        return infectiousState == 0;
    }
    
    public boolean isImmune() {
        return infectiousState == -1;
    }
    
    public boolean isInfected() {
        return infectiousState &amp;amp;gt; 0;
    }
    
    public void setImmune(boolean newState) {
        if (newState == true) {
            infectiousState = -1;
            setImage(&amp;amp;quot;immune.png&amp;amp;quot;);
        }
        else setInfectedState(false);
    }
    
    public void setInfectedState(boolean newState) {
        if (isImmune()) return;
        if (newState == true) {
            if (isInfected()) return;
            infectiousState++;
            setImage(&amp;amp;quot;infected.png&amp;amp;quot;);
        }
        else {
            infectiousState = 0;
            setImage(&amp;amp;quot;normal.png&amp;amp;quot;);
        }
    }
}&lt;/pre&gt;&lt;/div&gt;Much easier to control a single field over controlling multiple fields!

Lines 11 through 13 is a second constructor that allows for setting the infected state of the People object when created using:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;People infected = new People(true);&lt;/pre&gt;&lt;/div&gt;letting you add the infected person into the world with:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;addObject(new People(true), ...etc.&lt;/pre&gt;&lt;/div&gt;while still allowing uninfected persons to be added without using the boolean:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;addObject(new People(), ...etc&lt;/pre&gt;&lt;/div&gt;or, if desired, with:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;addObject(new People(false), ... etc&lt;/pre&gt;&lt;/div&gt;
So, your world constructor could look like the following:
&lt;div class="bb_code_wrap"&gt;&lt;pre class="brush: java"&gt;public MyWorld() {
    super(800, 600, 1);
    for (int i=0; i&amp;amp;lt;51; i++) {
        People p = new People(i == 50);
        int x = Greenfoot.getRandomNumber(getWidth());
        int y = Greenfoot.getRandomNumber(getHeight());
        addObject(p, x, y);
    }
    addObject(new Ambulance(), 0, 0);
}&lt;/pre&gt;&lt;/div&gt;Hope this helps some.</description>
      <author>danpost</author>
      <pubDate>Wed, 15 Jul 2026 19:56:32 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151040#post_151040</link>
    </item>
    <item>
      <title>Reply to testing</title>
      <description>import greenfoot.*;

public class MyWorld extends World
{
    public MyWorld()
    {
        super(800, 600, 1);

        // Spawn 50 orang normal
        for (int i = 0; i &amp;amp;lt; 50; i++)
        {
            addObject(
                new People(),
                Greenfoot.getRandomNumber(getWidth()),
                Greenfoot.getRandomNumber(getHeight())
            );
        }

        // Spawn 1 orang infected secara random
        People infected = new People();
        infected.setInfected(true);

        addObject(infected,Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight()));

        // Spawn ambulance
        addObject(new Ambulance(), 0, 0);
    }
}
=============================================

import greenfoot.*;

public class Ambulance extends Actor
{
    private int speed = 5;
    private int stepDown = 30;
    private boolean movingRight = true;

    public void act()
    {
        moveZigZag();
        healPeople();
    }

    private void moveZigZag()
    {
        if (movingRight)
        {
            setLocation(getX() + speed, getY());

            if (getX() &amp;amp;gt;= getWorld().getWidth() - 1)
            {
                movingRight = false;
                setLocation(getX(), getY() + stepDown);
            }
        }
        else
        {
            setLocation(getX() - speed, getY());

            if (getX() &amp;amp;lt;= 0)
            {
                movingRight = true;
                setLocation(getX(), getY() + stepDown);
            }
        }

        // Jika sudah mencapai bawah, kembali ke atas
        if (getY() &amp;amp;gt;= getWorld().getHeight() - 1)
        {
            setLocation(getX(), 0);
        }
    }

    private void healPeople()
    {
        People p = (People)getOneIntersectingObject(People.class);

        if (p != null &amp;amp;amp;&amp;amp;amp; p.isInfected())
        {
            p.setInfected(false);
        }
    }
}

=====================================================
import greenfoot.*;
import java.util.List;

public class People extends Actor
{
    private boolean infected = false;
    private boolean immune = false;
    private int infectionTimer = 0;

    public People()
    {
        updateImage();
    }

    public void act()
    {
        randomMove();

        if (infected)
        {
            spreadInfection();

            infectionTimer++;

            if (infectionTimer &amp;amp;gt;= 200)
            {
                setImmune(true);
            }
        }
    }

    // Gerak random
    private void randomMove()
    {
        move(4);

        if (Greenfoot.getRandomNumber(100) &amp;amp;lt; 20)
        {
            turn(Greenfoot.getRandomNumber(61) - 30);
        }

        if (isAtEdge())
        {
            turn(180);
        }
    }

    // Menularkan ke orang yang disentuh
    private void spreadInfection()
    {
        List&amp;amp;lt;People&amp;amp;gt; people = getIntersectingObjects(People.class);

        for (People p : people)
        {
            if (p != this &amp;amp;amp;&amp;amp;amp; !p.isImmune() &amp;amp;amp;&amp;amp;amp; !p.isInfected())
            {
                p.setInfected(true);
            }
        }
    }

    // Mengubah status infected
    public void setInfected(boolean status)
    {
        if (immune)
            return;

        infected = status;

        if (infected)
        {
            infectionTimer = 0;
        }
        else
        {
            infectionTimer = 0;
        }

        updateImage();
    }

    public boolean isInfected()
    {
        return infected;
    }

    // Mengubah menjadi immune
    public void setImmune(boolean status)
    {
        immune = status;

        if (immune)
        {
            infected = false;
            infectionTimer = 0;
        }

        updateImage();
    }

    public boolean isImmune()
    {
        return immune;
    }

    // Mengganti gambar sesuai status
    private void updateImage()
    {
        if (immune)
        {
            setImage(&amp;amp;quot;immune.png&amp;amp;quot;);
        }
        else if (infected)
        {
            setImage(&amp;amp;quot;infected.png&amp;amp;quot;);
        }
        else
        {
            setImage(&amp;amp;quot;normal.png&amp;amp;quot;);
        }
    }
}</description>
      <author>hafizz.hnn</author>
      <pubDate>Thu, 09 Jul 2026 11:58:05 +0000</pubDate>
      <link>https://greenfoot.org/topics/66680?pid=151039#post_151039</link>
    </item>
    <item>
      <title>Reply to Space Haven Project</title>
      <description>hallo mein Project ist nicht in der richtigen Größe was kann ich tun um es zu spielen</description>
      <author>schaeff_lu</author>
      <pubDate>Thu, 09 Jul 2026 11:58:02 +0000</pubDate>
      <link>https://greenfoot.org/topics/66679?pid=151038#post_151038</link>
    </item>
    <item>
      <title>Reply to need help</title>
      <description>&lt;div class="bb_quote"&gt;&lt;div class="bb_quote_header"&gt;arumsari wrote...&lt;/div&gt;need help
&amp;amp;lt;&amp;amp;lt; Code Omitted &amp;amp;gt;&amp;amp;gt;&lt;/div&gt;The only thing I see wrong with your codes is in the second line of the &lt;span class="bb_italic"&gt;prepareBoard &lt;/span&gt;method, which should increment the column (&lt;span class="bb_italic"&gt;c&lt;/span&gt;) value, not the row (&lt;span class="bb_italic"&gt;r&lt;/span&gt;) value.

Don&amp;amp;#39;t really know what you need help with.  You need to explain (in English, please) what you are trying to do and how the execution is wrong.</description>
      <author>danpost</author>
      <pubDate>Sun, 28 Jun 2026 16:15:23 +0000</pubDate>
      <link>https://greenfoot.org/topics/66675?pid=151034#post_151034</link>
    </item>
    <item>
      <title>Reply to need help</title>
      <description>import greenfoot.*;  

public class Sudoku extends World
{
    // Pola Sudoku awal berdasarkan slide kuliah (0 berarti kosong)
    private int board = {
        {5, 3, 0, 0, 7, 0, 0, 0, 0},
        {6, 0, 0, 1, 9, 5, 0, 0, 0},
        {0, 9, 8, 0, 0, 0, 0, 6, 0},
        {8, 0, 0, 0, 6, 0, 0, 0, 3},
        {4, 0, 0, 8, 0, 3, 0, 0, 1},
        {7, 0, 0, 0, 2, 0, 0, 0, 6},
        {0, 6, 0, 0, 0, 0, 2, 8, 0},
        {0, 0, 0, 4, 1, 9, 0, 0, 5},
        {0, 0, 0, 0, 8, 0, 0, 7, 9}
    };

    public Sudoku()
    {    
        // Ukuran cell disesuaikan dengan pixel grid pada gambar .jpg dosen
        super(9, 9, 50); 
        
        // Pasang gambar template sebagai background
        setBackground(&amp;amp;quot;sudoku_board.jpg&amp;amp;quot;); 
        
        prepareBoard();
    }

    private void prepareBoard()
    {
        for (int r = 0; r &amp;amp;lt; 9; r++) {
            for (int c = 0; c &amp;amp;lt; 9; r++) { // Jika infinity loop, pastikan c++
            }
        }
        // Koreksi loop penempatan cell agar presisi 9x9
        for (int r = 0; r &amp;amp;lt; 9; r++) {
            for (int c = 0; c &amp;amp;lt; 9; c++) {
                int val = board;
                
                Cell cell = new Cell();
                addObject(cell, c, r);
                
                if (val != 0) {
                    cell.setNumber(val);
                }
            }
        }
    }

    // Validasi baris: dipanggil setiap kali ada cell yang berubah nilainya
    public boolean isValidRow(int row, int num) {
        int count = 0;
        java.util.List&amp;amp;lt;Cell&amp;amp;gt; cells = getObjects(Cell.class);
        for (Cell c : cells) {
            if (c.getY() == row &amp;amp;amp;&amp;amp;amp; c.getNumber() == num) {
                count++;
            }
        }
        return count &amp;amp;lt;= 1; 
    }
}</description>
      <author>arumsari</author>
      <pubDate>Sun, 28 Jun 2026 06:55:55 +0000</pubDate>
      <link>https://greenfoot.org/topics/66675?pid=151033#post_151033</link>
    </item>
  </channel>
</rss>
