Obsługa zdarzeń i logika aplikacji

W pliku opisującym Layout aplikacji (xml) dodaj definicję przycisku Plot i ustaw odpowiednie atrybuty oraz funkcję obsługi zdarzenia polegającego na naciśnięciu przycisku. Activity naszej aplikacji jest napisany w języku Java i znajduje się w pliku /app/src/main/java/com.delta.tango.mod3/MainActivity.java.

package com.tango.tmp2;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity
{
   A obj;
   float cx=50,cy=400,radius=0;

   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      obj=(A)findViewById(R.id.v1);
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu)
   {
      getMenuInflater().inflate(R.menu.activity_main, menu);
      return true;
   }

   public void fdraw(View v)
   {
      cx+=5;
      cy-=5;
      radius=5;   obj.setCircle(cx, cy, radius);
      obj.invalidate();
   }
}

Ćwiczenie 1

Dodaj do widoku układ współrzędnych. Żeby to zrobić, do metody onDraw() klasy A powinieneś dodać wywołania odpowiednich metod na rzecz obiektu Paint.

public void onDraw(Canvas canvas)
{
   paint.setColor(Color.BLACK);
   canvas.drawLine(50, 50, 50, 400, paint);
   canvas.drawLine(50, 400, 400, 400, paint);
   canvas.drawCircle(cx, cy, radius, paint);
}

Oprócz dwóch osi, dodaj także strzałki, opis osi i podziałkę. W powyższym przykładzie każde naciśnięcie przycisku Plot przesuwa punkt wzdłuż pewnej prostej. Rozwiń swoją aplikację w ten sposób, żeby zwizualizować rzut ukośny. Po każdym naciśnięciu przycisku, punkt w układzie współrzędnych będzie renderowany w nowym położeniu wynikającym z rozwiązania odpowiednich równań opisujących rzut ukośny. Dodaj także pola tekstowe na informacje pozwalające ustalić prędkość początkową (wartość bezwzględną wektora prędkości kąt jaki tworzy z osią OX). Na końcu dodaj odpowiedni kod pozwalający wyrysować ślad poruszającego się punktu i porównać go ze śladami poprzednich rzutów (z innymi prędkościami początkowymi) oraz przycisk do kasowania śladów poprzednich rzutów.

Ćwiczenie 2

Zaimplementuj animację rzutu kośnego. W tym celu będziesz potrzebował oddzielny wątek, który będzie przesuwał ciało do kolejnych położeń jego trajektorii w trakcie rzutu. Jak pamiętasz, wątek w języku Java jest obiektem który rozszerza klasę biblioteczną java.lang.Thread albo implementuje interfejs java.lang.Runnable. Napisz odpowiednia klasę oraz odpowiednią implementację metody run() tej klasy (cykl życia wątku). Następnie dodaj ją do projektu i zaimplementuj przesuwanie ciała po kolejnych punktach trajektorii, sterowane przez wątek animacji. Żeby wstrzymać działanie wątku, na pewną ilość milisekund, użyj metody sleep().

class SilnikKuli extends java.lang.Thread
{
   Kulka a;

   SilnikKuli(Kula a)
   {
      this.a=a;
      start();
   }

   public void run()
   {
      try
      {
         while(true)
         {
            a.nextKrok();
            sleep(15);
         }
      }
      catch(InterruptedException e){}
   }
}

Ćwiczenie 3

Dodaj odpowiednie przyciski, pola tekstowe i napisz implementację prostego kalkulatora graficznego pozwalającego wykonywać operacje arytmetyczne i wykreślać wykresy funkcji. Do tej ostatniej funkcjonalności będziesz potrzebował parser wyrażeń arytmetycznych. Jeżeli napotkasz na trudności z implementacją takiego parsera, to ogranicz się do jakiejś wybranej kategorii funkcji (na przykład do wielomianów).

Ćwiczenie 4

Poniżej znajdziesz przykładowy szkielet popularnej gry Android, zaimplementowanej w postaci aplikacji desktopowej z wykorzystaniem biblioteki Java2D.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;

class Kulka extends Ellipse2D.Float
{
   Plansza p;
   int dx,dy;

   Kulka(Plansza p,int x,int y,int dx,int dy)
   {
      this.x=x;
      this.y=y;
      this.width=10;
      this.height=10;

      this.p=p;
      this.dx=dx;
      this.dy=dy;
   }

   void nextKrok()
   {
      x+=dx;
      y+=dy;
      if(getMinX()<0 || getMaxX()>p.getWidth()) dx=-dx;
      if(getMinY()<0 || getMaxY()>p.getHeight()) dy=-dy;

      p.repaint();
   }
}

class SilnikKulki extends Thread
{
   Kulka a;

   SilnikKulki(Kulka a)
   {
      this.a=a;
      start();
   }

   public void run()
   {
      try
      {
         while(true)
         {
            a.nextKrok();
            sleep(15);
         }
      }
      catch(InterruptedException e){}
   }
}

class Belka extends Rectangle2D.Float
{
   Belka(int x)
   {
      this.x=x;
      this.y=170;
      this.width=60;
      this.height=10;
   }

   void setX(int x)
   {
      this.x=x;
   }
}

class Plansza extends JPanel implements MouseMotionListener
{
   Belka b;
   Kulka a;
   SilnikKulki s;

   Plansza()
   {
      super();
      addMouseMotionListener(this);

      b=new Belka(100);
      a=new Kulka(this,100,100,1,1);
      s=new SilnikKulki(a);
   }

   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      Graphics2D g2d=(Graphics2D)g;

      g2d.fill(a);
      g2d.fill(b);
   }

   public void mouseMoved(MouseEvent e)
   {
      b.setX(e.getX()-50);
      repaint();
   }

   public void mouseDragged(MouseEvent e)
   {

   }
}

public class Program
{
   public static void main(String[] args)
   {
      javax.swing.SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            Plansza p;
            p=new Plansza();

            JFrame jf=new JFrame();
            jf.add(p);

            jf.setTitle("Test grafiki");
            jf.setSize(400,370);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.setVisible(true);
         }
      });
   }
}

Przeanalizuj jej konstrukcję i rozwiń ten szkielet do postaci w pełni funkcjonalnej prostej gry polegającej na zbijaniu kulą cegiełek. Następnie zastanów się nad pytaniem, jakie różnice pomiędzy implementacją aplikacji desktopowej i aplikacji mobilnej (Android) należy wziąć pod uwagę. Następnie napisz implementację takiej gry dla platformy Android.

Następna część - Wstęp