views:

246

answers:

2

Hello all! I have a problem where I need to make a multi-colored wheel spin using a Canvas in J2ME. What I need to do is have the user increase the speed of the spin or slow the spin of the wheel. I have it mostly worked out (I think) but can't think of a way for the wheel to spin without causing my cellphone to crash. Here is what I have so far, it's close but not exactly what I need.

class MyCanvas extends Canvas{
//wedgeOne/Two/Three define where this particular section of circle begins to be drawn from
int wedgeOne;
int wedgeTwo;
int wedgeThree;
int spinSpeed;
MyCanvas(){
    wedgeOne = 0;
    wedgeTwo = 120;
    wedgeThree = 240;
    spinSpeed = 0;
}
//Using the paint method to 
public void paint(Graphics g){
    //Redraw the circle with the current wedge series.
    g.setColor(255,0,0);
    g.fillArc(getWidth()/2, getHeight()/2, 100, 100, wedgeOne, 120);
    g.setColor(0,255,0);
    g.fillArc(getWidth()/2, getHeight()/2, 100, 100, wedgeTwo, 120);
    g.setColor(0,0,255);
    g.fillArc(getWidth()/2, getHeight()/2, 100, 100, wedgeThree, 120);
}
protected void keyPressed(int keyCode){
    switch (keyCode){
        //When the 6 button is pressed, the wheel spins forward 5 degrees.
        case KEY_NUM6:
            wedgeOne += 5; wedgeTwo += 5; wedgeThree += 5;
            repaint();
            break;
        //When the 4 button is pressed, the wheel spins backwards 5 degrees.
        case KEY_NUM4:
            wedgeOne -= 5; wedgeTwo -= 5; wedgeThree -= 5;
            repaint();
    }
}

I have tried using a redraw() method that adds the spinSpeed to each of the wedge values while(spinSpeed>0) and calls the repaint() method after the addition, but it causes a crash and lockup (I assume due to an infinite loop). Does anyone have any tips or ideas how I could automate the spin so you do not have the press the button every time you want it to spin?

(P.S - I have been lurking for a while, but this is my first post. If it's too general or asking for too much info (sorry if it is) and I either remove it or fix it. Thank you!)

A: 

Hi, given that you haven't had a response yet, I thought I'd try to contribute even though my experience isn't in J2ME. I have some practice in Java2D, which will likely be possible on J2ME, although someone feel free to tell me if otherwise!

If you are able to use a JPanel, you could design a slightly game-cycle like design similar to one I have used in the past.

The idea: at a given interval, interogate each entity that must be drawn (in this case the wedges), update it to find the new position, and ask it to paint itself. To demonstrate this, here is a fairly stripped out version of a GamePanel I've used before-

public class GamePanel extends JPanel {
Timer loopTimer;
boolean changed = false;
ArrayList<Entity> entities = new ArrayList<Entity>();
int spinSpeed = 1;
int pollingMillis = 20;

public GamePanel () {
    setBackground(Color.black);
    setDoubleBuffered(true);
    entities.add(new Wedge(0,0,0,90,Color.red));     // See below about these lines
    entities.add(new Wedge(0,0,90,90,Color.blue));
    entities.add(new Wedge(0,0,180,90,Color.yellow));
    entities.add(new Wedge(0,0,270,90,Color.green));
    loopTimer = new Timer();
    loopTimer.scheduleAtFixedRate(new runLoop(), 0, pollingMillis);
}

public void addEntity(Entity e) {
    entities.add(e);
}

@Override
public void paint (Graphics graph) {
    super.paint(graph);
    Graphics2D g = (Graphics2D) graph;
    for (Entity e: entities) {
        e.draw(g);
    }
    g.dispose();
}

private class runLoop extends TimerTask {
    @Override
    public void run() {
        for (Entity e: entities) {
            e.update();
        }
        if (changed) {
            repaint();
            changed = false;
        }
    }
}
}

This will create the basic cycle that will allow you to render items into the JPanel. The code above has 4 'wedges' being added, although you need a bit more code yet for that. To do this, you need the following abstract class:

public abstract class Entity {
int x,y;
public Entity (int x, int y) {
    this.x = x;
    this.y = y;
}
public abstract void update();
public abstract void draw(Graphics2D g);
}

Now, the entities you want to render extend this class, allowing them to be added to the render cycle. For example, the wedge class- private class Wedge extends Entity { int startAngle; int arcLength; Color color;

    public Wedge (int x, int y, int start, int length, Color color) {
        super(x,y);
        startAngle = start;
        arcLength = length;
        this.color = color;
    }

    @Override
    public void update() {
        startAngle -= spinSpeed;
        changed = true;
    }

    @Override
    public void draw(Graphics2D g) {
        g.setColor(color);
        g.fillArc(x, y, 200, 200, startAngle, arcLength);
    }
}

This should then allow you to render an animated circle that spins! I hope that some of this is tranferrable over to J2ME, and I also hope you appreciate that this code may be far from optimal, and if you wish for me to expand on any of it, just comment.

obfuscation
Thank you for the answer, but J2ME does not have a lot of the methods and classes mentioned above. Though, you have given me an idea on how to tackle this problem, I think. Thank you!
JohnQPublic
No problem, although if you'd like I'm happy to try and help further- just tell me which classes you don't get in the J2ME environment, and I can try to tailor the solution better using alternative methods!
obfuscation
A: 

I think you should create a thread and in the run method of the thread call this paint/repaint method. If you want the keypressed to run the thread than it simply :

case KEY_NUM6: thread.start;

Ari R. Fikri
This is the problem that I was having, I didn't realize that all of the animation had to be done in a seperate thread.
JohnQPublic