Solved

Java Sprites

Posted on 2011-03-09
23
627 Views
Last Modified: 2012-06-27
I am creating a java midlet game. I have created sprites that drift back and forth. I now want to have these sprites travel along a path. My sprite class is below.  

I want to have my sprites go in a circular path around a number of points. How would I go about doing this?
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;

public class DriftSprite extends Sprite {
  private Random     rand;
  private int        speed;
  private TiledLayer barrier;

  public DriftSprite(Image image, int frameWidth, int frameHeight, int driftSpeed,
    TiledLayer barrierLayer) {
    super(image, frameWidth, frameHeight);

    // Initialize the random number generator
    rand = new Random();

    // Set the speed
    speed = driftSpeed;

    // Set the tiled layer barrier
    barrier = barrierLayer;
  }

  public void update() {
    // Temporarily save the position
    int xPos = getX();
    int yPos = getY();

    // Randomly move the sprite to simulate drift
    switch (Math.abs(rand.nextInt() % 4)) {
    // Drift left
    case 0:
      move(-speed, 0);
      break;
    // Drift right
    case 1:
      move(speed, 0);
      break;
    // Drift up
    case 2:
      move(0, -speed);
      break;
    // Drift down
    case 3:
      move(0, speed);
      break;
    }

    // Check for a collision with the barrier
    if ((barrier != null) && collidesWith(barrier, true)) {
      // Move the sprite back to its original position
      setPosition(xPos, yPos);
    }

    // Move to the next animation frame in the sequence
    nextFrame();
  }
}

Open in new window

0
Comment
Question by:tango2009
  • 12
  • 11
23 Comments
 
LVL 12

Expert Comment

by:satsumo
ID: 35086956
A circular path around a number of points can be interpreted in a few ways.  Could you do a diagram of the kind of path you want?
0
 

Author Comment

by:tango2009
ID: 35088406
ok just something really simple like the one below. path
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35088805
I would probably do that as an angular path.  It goes right for some period (angle is 0).  Then the direction changes for a few frames until its 90 degrees (downwards).  It travels in that direction for a shorter period, then starts changing angle again to 180.

I'm not used to Java. This code is as close as I can guess to the right syntax.  You may have to tweak it a bit.

public class LoopSprite extends Sprite
{
  private float angle;
  private int frame;
  private int speed;

  public LoopSprite(Image image, int frameWidth, int frameHeight, int loopSpeed,
    TiledLayer barrierLayer) {
    super(image, frameWidth, frameHeight);

    angle = 0;
    frame = 0;
    speed = loopSpeed;

    barrier = barrierLayer;
}

public void update()
{
    switch (Math.floor (frame / 5))
    {
         case 3:
         case 6:
         case 10:
         case 13:
             angle += (Math.Pi / 10);
    }

    ++frame;
    if (frame == 70) frame = 0;
    move (Math.cos (angle) * speed, Math.sin (angle) * speed);
}

Open in new window


It works in 5 frame groups, every time you call update is another frame.  It goes right for 15 frames, turns for 5 frame, down for 10 frames, turns again, left for 15 frames, turns again, up for 10 frames, then turns back to where it started.  The entire pattern takes 70 frames, on the 70th it starts from 0 again.  It still uses a speed variable, so that you can control how fast it moves.

Math.Pi equates to 180 degrees.  Math.Pi / 10 is 18 degrees.  5 turns of 18 degrees gets you 90 degrees from whatever angle you started with.
0
 

Author Comment

by:tango2009
ID: 35099039
The only problem that I have is that I get this error below

possible loss of precision
found   : double
required: int
      switch (Math.floor( frame /5))

and this one

 javax.microedition.lcdui.game.Layer cannot be applied to (double,double)
    move (Math.cos (angle) * speed, Math.sin (angle) * speed);

move uses integers. How can I get around this?
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35101291
Thats because floor rounds the number down to the nearest integer, but returns the value in a double value.  I think this will work instead.

switch ((int) (frame / 5));

Open in new window

0
 
LVL 12

Expert Comment

by:satsumo
ID: 35101499
The problem with move using integers can be solved in a similar way

move ((int) Math.round (Math.cos (angle) * speed), (int) Math.round (Math.sin (angle) * speed));

Open in new window

Though that becomes less accurate if speed is small.  If speed is less the 0.5, the sprite won't move at all.

A better way is to keep the sprites x and y coordinates as double values.  Then move it to the nearest integer position.  This code keeps track of the integer position of the sprite.  There's probably an easier way to do this, either the sprite can be positioned (rather than moved) or you can get it's pixel x and y rather than having to keep track of them.

public class LoopSprite extends Sprite
{
  private float angle;
  private int frame;
  private int speed;
  private float x, y;  // accurate x and y
  private int px, py;  // pixel x and y

public LoopSprite(Image image, int frameWidth, int frameHeight, int loopSpeed, TiledLayer barrierLayer)
{
    angle = 0;
    frame = 0;
    speed = loopSpeed;
    x = ?; // needs a start position
    y = ?; // needs a start position
   px = (int) Math.round (x);
   py = (int) Math.round (y);
}

public void update()
{
    int dx , dy;

    switch (Math.floor (frame / 5))
    {
         case 3:
         case 6:
         case 10:
         case 13:
             angle += (Math.Pi / 10);
    }

    x += Math.cos (angle) * speed;
    y += Math.sin (angle) * speed;
    dx = (int) Math.round (x);
    dy = (int) Math.round (y);
    move (dx - px, dy - py);
    px = dx;
    py = dy;

    ++frame;
    if (frame == 70) frame = 0;
}

Open in new window

0
 

Author Comment

by:tango2009
ID: 35112023
I have a problem with using Math.round. I get errors saying

cannot find symbol
symbol  : method round(float)
location: class java.lang.Math
    px = (int) Math.round(x);

round doesn't seem to be an option that I can use with Math. Is there anything I can use to do a similar job.
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35113287
Math.round was in the docs I looked up. http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html.  No matter, this works the same.

px = (int) Math.floor (x + 0.5);

Open in new window

0
 

Author Comment

by:tango2009
ID: 35142686
So if I want to make the sprite change direction more times do I have to just add more of these lines to change the direction with different values?

angle += (Math.Pi / 10);

0
 
LVL 12

Expert Comment

by:satsumo
ID: 35142970
Yep, that all there is too it.  The angle is what direction it moves, you can have it move in circles, wave patterns, a figure of eight, anything that you can program changes in the angle to describe.  Using positive or negative numbers turns the sprite clockwise or anti-clockwise.
0
 

Author Comment

by:tango2009
ID: 35147627
Where in the code does it state that it will first move right for 15 frames? The problem I have with it is it keeps going right off the screen. I am assuming that this is because it goes in the right direction for too many frames.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 12

Expert Comment

by:satsumo
ID: 35149833
Does it come back again OK?  Try setting the speed to a smaller value.  The 15 frames is defined by this part -

switch (Math.floor (frame / 5))
{
     case 3:

Open in new window

This divides the frame count by five, if the result is between 3 and 4 (a frame count between 15 and 20) then it runs the code in the switch statement.  If it did this -

switch (Math.floor (frame / 3))
{
     case 2:
     case 5:

Open in new window

The code would run on frames 6-9 and 15-18.
0
 

Author Comment

by:tango2009
ID: 35151452
No it doesn't come back at all it, well not that I can see it might go down for too many frames so I can't see it coming back. To solve this would be best just cutting down the number of frames it goes right for instead of the speed.
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35152667
After 70 frames it should return to where it started, if that's not happening something else must be wrong.  Changing the speed will let you see the whole loop without having to mess with the frame counts.
0
 

Author Comment

by:tango2009
ID: 35156767
I have changed the speed right down and it still continues to just go in the right direction without turning to go down. I have even stopped it on a barrier to see if it would then change direction after the frame count and it doesn't. I will post my loop class below is there something I have missed?




import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;

public class LoopSprite extends Sprite {
  private Random     rand;
  private double       speed;
  private TiledLayer barrier;
  private int frame;
  private int angle;
  private float x, y;  // accurate x and y
  private int px, py;  // pixel x and y


  public LoopSprite(Image image, int frameWidth, int frameHeight, int driftSpeed,
    TiledLayer barrierLayer) {
    super(image, frameWidth, frameHeight);


    x = 10.4f; // needs a start position
    y = 5.4f; // needs a start position
    px = (int) Math.floor(x + 0.5);
    py = (int) Math.floor (y + 0.5);

    // Initialize the random number generator
    rand = new Random();
    angle = 0;
    frame = 0;
    // Set the speed
    speed = 0.4;

    // Set the tiled layer barrier
    barrier = barrierLayer;





  }

  public void update() {
    // Temporarily save the position
    int xPos = getX();
    int yPos = getY();

      int dx , dy;

   // switch (Math.floor(frame / 5))
      switch ((int)( frame /5))
    {
        case 3:
        case 6:
        case 10:
        case 13:
            angle += (Math.PI / 10);
    }
       ++frame;
    // Randomly move the sprite to simulate drift
  /*  switch (Math.abs(rand.nextInt() % 4)) {
    // Drift left
    case 0:
      move(-speed, 0);
      break;
    // Drift right
    case 1:
      move(speed, 0);
      break;
    // Drift up
    case 2:
      move(0, -speed);
      break;
    // Drift down
    case 3:
      move(0, speed);
      break;
    }*/


    x += Math.cos (angle) * speed;
    y += Math.sin (angle) * speed;
    dx = (int) Math.floor (x);
    dy = (int) Math.floor (y);
    move (dx - px, dy - py);
    px = dx;
    py = dy;
    if (frame == 70) frame = 0;

   // move (Math.cos (angle) * speed, Math.sin (angle) * speed);

    move ((int) Math.floor (Math.cos (angle) * speed), (int) Math.floor (Math.sin (angle) * speed));

    // Check for a collision with the barrier
    if ((barrier != null) && collidesWith(barrier, true)) {
      // Move the sprite back to its original position
      setPosition(xPos, yPos);
    }

    // Move to the next animation frame in the sequence
    nextFrame();
  }
}

Open in new window

0
 
LVL 12

Expert Comment

by:satsumo
ID: 35159409
move ((int) Math.floor (Math.cos (angle) * speed), (int) Math.floor (Math.sin (angle) * speed));

Open in new window

This line will make it move twice as fast as it should.  I don't think thats the problem but please delete it.

angle += (Math.PI / 10);

Open in new window

Could you set a breakpoint on this line and run the program?  It appears like the program never gets to this line.  It could be something outside of the function that prevents this happening.  Is something setting 'frame' back to zero or changing one of the other variables?
0
 

Author Comment

by:tango2009
ID: 35173132
I have put in a breakpoint and I have put a print screen of the variables at this breakpoint.

I think at the moment just looking I might be setting the position twice could this be the problem?
breakpoint.jpg
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35173285
Thats useful but you need to continue the program from this breakpoint.  It should stop again at the same point but angle should be different the second time.  Continue it a few times and angle should keep changing.

When you say setting the position, do you mean using setPosition()?  It's used in the update function, is it used somewhere else?
0
 

Author Comment

by:tango2009
ID: 35173426
The angle stays at 0 all of the time. What I mean't above was that I am using setPosition in the update function. but in this code above at the beginning I am setting the position

 x = 10.4f; // needs a start position
    y = 5.4f; // needs a start position

could this be the problem?
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35173995
The x = 10.4f and y = 5.4f lines are initialisation.  They only run once, when you first create the sprite.
The problem is that angle stay at zero and I've just spotted why, angle is declared as an int, it needs to be a float.
0
 

Author Comment

by:tango2009
ID: 35176785
Ah yes it is working it is going around in a complete circle now thankyou. Can I just ask you one more thing. At the moment it goes round in too small a circle to make it go around in a larger circle do I simply need to add to the number of frames in the sequence?
0
 
LVL 12

Accepted Solution

by:
satsumo earned 500 total points
ID: 35178010
Either increase the speed (makes it travel further in the same amount of time), or change the frame counters.  Increasing the frame counters will mean it takes more time to get around the loop.
0
 

Author Comment

by:tango2009
ID: 35201355
I am trying to keep the sprite move on its circular path but to make its path much larger. I am trying to add the frames so that I can create a larger path like below.

switch ((int)( frame /15))

and here

angle += (Math.PI / 20);

However this either distorts the path or makes the sprite just leave the screen. How can I increase the size of the path without distorting the path?
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Game Asset Design and Performance. 7 83
VBA color chart bars 12 65
changePi Challenge 15 75
wordmultiple challenge 12 89
Having just graduated from college and entered the workforce, I don’t find myself always using the tools and programs I grew accustomed to over the past four years. However, there is one program I continually find myself reverting back to…R.   So …
This article will show, step by step, how to integrate R code into a R Sweave document
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now