//
// AnimInPlace.java    1/12/99  AJD
//
// A scrolling landscape applet.
//

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.Random;

public class AnimInPlace extends Applet implements Runnable {
    static final int NofImages = 2;
    int index = 0;
    Image images[];
    int count;
    static final int IMAGE_SIZE = 300;
    static final int STEP_SIZE = 4;
    boolean suspendRequest = false;
    Thread animator;
    Random rand;
    boolean ship_hit = false;
    int min_delay = 10;
    int delay = 10;
    int max_delay = 1000;

    // Used for generating scrolling image.
    int h = 1;
    int b = 1;
    int r = 1;
    int offset = 0;
    int buffer[];

    int ship_y = IMAGE_SIZE/2;
    int ship_x = IMAGE_SIZE/2;
    boolean auto_ship_move = true;

    int bomb_x = -1;
    int bomb_y = -1;
    int radar_x = -1;
    int radar_dir = 0;
    Color mountainColour = Color.orange;
    Color shipColour = Color.red;
    Color bombColour = Color.cyan;
    Color radarColour = Color.yellow;

    public void init() {
        setBackground(Color.black);
        rand = new Random();
        buffer = new int[IMAGE_SIZE/STEP_SIZE];
        for (int i=0; i<IMAGE_SIZE; i++) scrollBuffer();
        initImages(IMAGE_SIZE);
        animator = new Thread(this);
        animator.start();
    }

    private void scrollBuffer () {

        // Add a point to the scrolling buffer, and increment the buffer offset.
        buffer[offset] = h;
        h = (h+((int)(rand.nextFloat()*11.0)-5));
        if (h<10) h=10;
        if (h>IMAGE_SIZE/2) h=IMAGE_SIZE/2;
        offset = (offset+1)%(IMAGE_SIZE/STEP_SIZE);

        // Check if time to start bomb drop.
        if (bomb_x<0) {
            b = (b+((int)(rand.nextFloat()*11.0-4.8)));
            if (b>IMAGE_SIZE/2) {
                b = 0;
                bomb_x = IMAGE_SIZE-5;
                bomb_y = ((int)(rand.nextFloat()*(IMAGE_SIZE/2)));
            }
            else if (b<10) b=10;
        }

        // Check if time to draw radar dish.
        if (radar_x<0) {
            r = (r+((int)(rand.nextFloat()*11.0)-4));
            if (r>IMAGE_SIZE/2) {
                r = 0;
                radar_x = IMAGE_SIZE-5;
                if (rand.nextFloat()*10.0<6.0) radar_dir = 1; else radar_dir=0;
            }
            else if (r<10) r=10;
        }
    }

    private void drawNextFrame (int i) {
        scrollBuffer();

        Graphics g = images[i].getGraphics();
        g.setColor(Color.black);
        g.fillRect(0,0,IMAGE_SIZE,IMAGE_SIZE);
        g.setColor(mountainColour);
        int ofs = offset;
        int x = 0;
        int prevx=-1;
        int prevy=-1;
        while (true) {
            if (prevx!=-1)
                g.drawLine(prevx,prevy,x,IMAGE_SIZE-buffer[ofs]);
            prevx=x;
            prevy=IMAGE_SIZE-buffer[ofs];

            if (!ship_hit && x<ship_x+3 && x>ship_x) {
                g.setColor(shipColour);

                if (auto_ship_move) {
                    if (IMAGE_SIZE-buffer[ofs]<(ship_y+30)) ship_y-=1;
                    if (IMAGE_SIZE-buffer[ofs]>(ship_y+50)) ship_y+=1;
                }

                int y = ship_y;
                g.drawLine(x-5,y-3,x-5,y-3);
                g.drawLine(x-5,y-2,x-4,y-2);
                g.drawLine(x-5,y-1,x+4,y-1);
                g.drawLine(x-5,y,x+2,y);
                g.drawLine(x+4,y,x+5,y);
                g.drawLine(x-5,y+1,x+4,y+1);
                g.setColor(mountainColour);
            }

            if (radar_x>=0 && x<radar_x+5 && x>radar_x) {
                int y = IMAGE_SIZE-buffer[ofs]-4;
                radar_x-=4;
                g.setColor(radarColour);
                if (radar_dir==1) {
                    g.fillArc(x-6,y-9,10,10,45,-180);
                    g.drawLine(x-2,y-5,x-4,y-7);
                    g.drawLine(x-2,y-4,x-4,y-6);
                }
                else {
                    g.fillArc(x-1,y-9,10,10,135,185);
                    g.drawLine(x+4,y-5,x+6,y-7);
                    g.drawLine(x+4,y-4,x+6,y-6);
                }
                g.drawLine(x+2,y-4,x+2,y+4);
                g.drawLine(x+1,y-4,x+1,y+4);
                g.setColor(mountainColour);
            }

            if (bomb_x>=0 && x<bomb_x+5 && x>bomb_x) {
                int y2 = IMAGE_SIZE-buffer[ofs];
                int y = bomb_y;
                boolean ship_in_range = (bomb_y>ship_y-5 && bomb_y<ship_y+5 &&
                                     bomb_x>ship_x-5 && bomb_x<ship_x+5);
                if (bomb_y>y2+2) {bomb_x=-1;}
                else if (bomb_y>y2-6 || ship_in_range) {
                    g.setColor(Color.red);
                    g.drawLine(x,y-7,x,y+7);
                    g.drawLine(x-7,y,x+7,y);
                    g.drawLine(x-7,y-7,x+7,y+7);
                    g.drawLine(x+7,y-7,x-7,y+7);
                    g.setColor(mountainColour);
                    bomb_y++;
                    if (ship_in_range) {
                        ship_hit=true;
                        bomb_x=-1;
                        delay=max_delay;
                    }
                }
                else {
                    g.setColor(bombColour);
                    g.drawLine(x-1,y-1,x+1,y-1);
                    g.drawLine(x-3,y,x+3,y);
                    g.drawLine(x-3,y+1,x+3,y+1);
                    g.drawLine(x-1,y+2,x+1,y+2);
                    g.setColor(mountainColour);
                    bomb_y+=4;
                }
                bomb_x-=4;
            }

            x+=4;
            ofs = (ofs+1)%buffer.length;
            if (ofs==offset) break;
        }
    }

    public boolean keyDown (Event e, int key) {
        if (key==Event.UP) {
            ship_y--;
        }
        else if (key==Event.DOWN) {
            ship_y++;
        }
        else if (key==Event.ENTER) {
            auto_ship_move = !auto_ship_move;
        }

        return true;
    }

    private void initImages (int imageSize) {
        images = new Image[NofImages];
        images[0]= createImage(imageSize, imageSize);
        images[1]= createImage(imageSize, imageSize);

        drawNextFrame(0);
    }

    public void stop()
    {
        suspendRequest = true;
    }

    public void start() {
        synchronized(this) {
            suspendRequest = false;
            notify();
        }
    }

    public synchronized void paint (Graphics g) {
        g.drawImage(images[index],0,30,this);
    }

    public void update (Graphics g) {
        paint(g);
    }

    public void run() {
        while(true) {
            if (suspendRequest) {
                synchronized(this) {
                    try {
                        wait();
                    } catch (InterruptedException e) {}
                }
            }
            try {
                Thread.sleep(delay);
                if (delay>min_delay) delay-=250;
                else ship_hit=false;

                if (delay<min_delay) delay=min_delay;
            } catch (InterruptedException e) {}
            bumpIndex();
            drawNextFrame(index);
            repaint();
        }
    }

    private synchronized void bumpIndex() {
        index = ++index % images.length;
    }
}
