Sprite movement issues [SOLVED]

Started by
4 comments, last by thelegendofzaku 18 years ago
I'm having problems trying to get my sprite to move around my tile layer. For some reason, I'm getting the nagging suspicsion that it might be due to the fact that my keypresses are not invoking the methods that move the sprite around. I'm not sure about this, but is it feasible to use both keystates and keypresses at th3e same time and would that help in invoking the sprite movement methods? Also, since my player sprite is five frames (one for standing still and the rest for moving in a given direction), how can I juggle frame sequences when moving and standing still. In other words, when I move my character, will I have to set the frame sequence for those movement methods and for standing still, will I have to create a method that uses a boolean to indicate whether or not the character is moving so that it can be set back to the first frame? Enclosed is the code for my game screen and player sprite. EDIT: I got it working and I realized why there were movement issues when running my midlet in my phone's default J2ME emulator. It seems that it only implements the basic stuff and only implemented the Game API sparingly. That and after reading up more about this issue, it seems that it is not suited for gaming, thus it has a lot of compatibility issues with lots of games. Luckily, the IBM J2ME Midlet launcher FULLY implements J2ME w/o cutting corners and managed to move my sprite across my tile layer just like in the emulator. Granted it lags a little, but a toning down of my graphics should do the trick. my game screen class (update 3/29/06)
package de.enough.polish.example;

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

public class GameScreen extends GameCanvas implements Runnable, CommandListener{
    static final int MILLIS_PER_TICK = 50;
    private static final int RUN_OFF = 0;
    private Command backCommand = new Command("Back", Command.BACK,1);
    private MenuMidlet midlet;
    private LayerManager layerManager;
    private Thread gameThread;
    private TiledLayer background;
    private int keyPress;
    private int regGameCodes;
    private TheLevels theLevels;
    private Display display;
    private int width;
    private int height;
    private int screenViewWidth;
    private int screenViewHeight;
    private int scnX, scnY;
    private Image cityBackground;
    boolean isPlay;
    private PlayerSprite playerSprite;
    private Sprite backgroundSprite;
    private int currentFrame = 1;
    private static final int MOVE_RATE = 5;
    private static final int END_TILELAYER_BUFFER = 15;
    private static final int OFFSET_LEFT = 30;
    private static final int OFFSET_RIGHT = 120;
    
    public GameScreen(MenuMidlet midlet) throws Exception {
        super(false);
        this.midlet=midlet;
        addCommand(backCommand);
        setCommandListener(this);

        isPlay = true;
        
        theLevels = new TheLevels(screenViewHeight);
        //theLevels.setMap(2);
        background = theLevels.getBackground();
        
        width=getWidth();
        height=getHeight();
        screenViewHeight = width;
        
        scnX=0;
        
        Image playerImage = Image.createImage("/sprite.png");
        playerSprite = new PlayerSprite(playerImage,24,56,width,height);
        playerSprite.startPosition();
        
        
        layerManager = new LayerManager();
        layerManager.append(playerSprite);
        layerManager.append(background);
        //layerManager.append(backgroundSprite);
    }
    public void start() {
        gameThread = new Thread(this);
        gameThread.start();
        try {
            cityBackground = Image.createImage("&#<span class="java-number">47</span>;citybg.png"</span>);
        }
        <span class="java-keyword">catch</span> (Exception e){
            
        }
        <span class="java-comment">//#debug</span>
        System.out.print(<span class="java-literal">"Game thread running"</span>);

    }
    <span class="java-comment">// Stop thread for game loop</span>
    <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> stop() {
        gameThread = <span class="java-keyword">null</span>;
    }
    
    <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> run() {
        Graphics g = getGraphics();
        
        Thread currentThread = Thread.currentThread();
        <span class="java-keyword">try</span>{
            <span class="java-keyword">while</span> (currentThread == gameThread) {
                <span class="java-primitives">long</span> startTime = System.currentTimeMillis();
                <span class="java-keyword">if</span> (isShown()) {
                    <span class="java-keyword">if</span> (isPlay) {
                        <span class="java-keyword">switch</span>(regGameCodes){
                            <span class="java-keyword">case</span> UP: playerSprite.moveUp(); <span class="java-keyword">break</span>;
                            <span class="java-keyword">case</span> DOWN: playerSprite.moveDown(); <span class="java-keyword">break</span>;
                            <span class="java-keyword">case</span> LEFT: 
                                playerSprite.moveLeft(); 
                                <span class="java-keyword">if</span> ((scnX &gt; <span class="java-number">0</span>)&amp;&amp; (playerSprite.getX() &lt; (scnX*MOVE_RATE)+OFFSET_LEFT))
                                    scnX--;
                                <span class="java-keyword">break</span>;
                            <span class="java-keyword">case</span> RIGHT: 
                                playerSprite.moveRight(); 
                                <span class="java-keyword">if</span> ((scnX &lt; getWidth()+END_TILELAYER_BUFFER)&amp;&amp;(playerSprite.getX() &gt; (scnX*MOVE_RATE)+OFFSET_RIGHT))
                                    scnX++;
                                <span class="java-keyword">break</span>;
                            <span class="java-comment">//case RUN_OFF: playerSprite.setRunOff(); break;</span>
                        }

                        <span class="java-comment">/*switch(keyPress){
                            case KEY_NUM1: playerSprite.moveUpLeft(); break;
                            case KEY_NUM3: playerSprite.moveUpRight(); break;
                            case KEY_NUM7: playerSprite.moveDownLeft(); break;
                            case KEY_NUM9: playerSprite.moveDownRight(); break;
                            //case RUN_OFF: playerSprite.setRunOff(); break;
                        }*/</span>
                        <span class="java-comment">//debug</span>
                        System.out.println(<span class="java-literal">"ScnX: "</span>+scnX*<span class="java-number">5</span>+<span class="java-literal">". "</span>+<span class="java-literal">"PlayerXPosition: "</span>+playerSprite.getX());
                        <span class="java-comment">//debug</span>
                        System.out.println(<span class="java-literal">"Current width: "</span>+getWidth()+<span class="java-literal">". "</span>+<span class="java-literal">"Tile width: "</span>+theLevels.getWidth());
                    }
                    drawScreen(g);
                    <span class="java-comment">//render(g);</span>
                }
                <span class="java-primitives">long</span> timeTake = System.currentTimeMillis() - startTime;
                <span class="java-keyword">if</span> (timeTake &lt; MILLIS_PER_TICK) {
                    <span class="java-storageclasses">synchronized</span> (<span class="java-keyword">this</span>) {
                        wait(MILLIS_PER_TICK - timeTake);
                    }
                } <span class="java-keyword">else</span> {
                    currentThread.yield();
                }
            }
        } <span class="java-keyword">catch</span>(Exception ex){
            
        }
        
    }
    <span class="java-visibilitymodifier">protected</span> <span class="java-primitives">void</span> keyPressed(<span class="java-primitives">int</span> keyCode){
        <span class="java-keyword">super</span>.keyPressed(keyCode);
        regGameCodes=getGameAction(keyCode);
        keyPress=keyCode;
        <span class="java-keyword">if</span> ((regGameCodes == UP) || (regGameCodes == DOWN) || (regGameCodes == LEFT) || (regGameCodes == RIGHT) || (keyPress == KEY_NUM1) || (keyPress == KEY_NUM3) || (keyPress == KEY_NUM7) || (keyPress == KEY_NUM9)){
            playerSprite.setFrameSequence(playerSprite.MOVEMENT_SEQUENCE);
        }
        <span class="java-comment">//playerSprite.setFrameSequence(playerSprite.MOVEMENT_SEQUENCE);</span>
    }
  <span class="java-comment">/*protected void keyRepeated(int keyCode){
      super.keyRepeated(keyCode);
      keyPress=keyCode;
  }*/</span>
    <span class="java-visibilitymodifier">protected</span> <span class="java-primitives">void</span> keyReleased(<span class="java-primitives">int</span> keyCode){
        <span class="java-keyword">super</span>.keyReleased(keyCode);
        regGameCodes=<span class="java-number">0</span>;
        keyPress=<span class="java-number">0</span>;
        playerSprite.setFrameSequence(<span class="java-keyword">null</span>);
        playerSprite.setFrame(<span class="java-number">0</span>);
    }
    

    <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> commandAction(Command c, Displayable d) {
        <span class="java-keyword">if</span> (c == backCommand) {
            midlet.mainMenuShow();
        }
    }
    
   
    <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> newGame(){
        <span class="java-keyword">try</span>{
            theLevels.setMap(<span class="java-number">1</span>);
        } <span class="java-keyword">catch</span> (Exception e){
            <span class="java-comment">//#debug</span>
            System.out.println(e);
        }
        display.setCurrent(<span class="java-keyword">this</span>);
        repaint();
    }
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">void</span> drawScreen(Graphics g) {
        <span class="java-comment">//g.setColor(0x00C000);</span>
        
        g.setColor(0xffffff);
        g.fillRect(<span class="java-number">0</span>, <span class="java-number">0</span>, getWidth(), getHeight());
        <span class="java-comment">/*g.setColor(0x37c3fd);
        g.fillRect(0, 12, 176, 150);*/</span>
        g.drawImage(cityBackground, <span class="java-number">0</span>, -<span class="java-number">20</span>, Graphics.TOP | Graphics.LEFT);
        g.setColor(0x0000ff);

        background = theLevels.getBackground();
        
        <span class="java-comment">// display all layers</span>
        <span class="java-comment">//layerManager.paint(g,0,0);</span>
        layerManager.setViewWindow(scnX*MOVE_RATE,<span class="java-number">30</span>,<span class="java-number">176</span>,<span class="java-number">190</span>);
        layerManager.paint(g,<span class="java-number">0</span>,<span class="java-number">0</span>);
        
        flushGraphics();
    }
    
}


</pre></div><!--ENDSCRIPT-->

my player sprite class (update 3/29/06)<!--STARTSCRIPT--><!--source lang="java"--><div class="source"><pre>
<span class="java-keyword">package</span> de.enough.polish.example;

<span class="java-keyword">import</span> javax.microedition.lcdui.game.*;
<span class="java-keyword">import</span> javax.microedition.lcdui.*;

<span class="java-visibilitymodifier">public</span> <span class="java-keyword">class</span> PlayerSprite <span class="java-keyword">extends</span> Sprite{
    <span class="java-storageclasses">static</span> <span class="java-storageclasses">final</span> <span class="java-primitives">int</span> MOVE = <span class="java-number">5</span>;
    <span class="java-storageclasses">static</span> <span class="java-storageclasses">final</span> <span class="java-primitives">int</span> XMOVE = <span class="java-number">5</span>;
    <span class="java-storageclasses">static</span> <span class="java-storageclasses">final</span> <span class="java-primitives">int</span> DMOVE = MOVE*<span class="java-number">100</span>/<span class="java-number">141</span>;
    <span class="java-visibilitymodifier">private</span> <span class="java-storageclasses">static</span> <span class="java-storageclasses">final</span> <span class="java-primitives">int</span> END_BUFFER = <span class="java-number">22</span>;
    <span class="java-visibilitymodifier">private</span> Image image;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> xPos;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> yPos;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> frameWidth;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> frameHeight;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> scnWidth, scnHeight;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> frame;
    <span class="java-visibilitymodifier">public</span> <span class="java-storageclasses">static</span> <span class="java-storageclasses">final</span> <span class="java-primitives">int</span>[] MOVEMENT_SEQUENCE={<span class="java-number">1</span>, <span class="java-number">2</span>, <span class="java-number">3</span>, <span class="java-number">4</span>};
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">boolean</span> isRun;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> currentFrame = <span class="java-number">0</span>;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> maxSpriteFrames = <span class="java-number">5</span>;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> firstWalkingFrame;
    <span class="java-visibilitymodifier">private</span> <span class="java-primitives">int</span> standingFrame = <span class="java-number">0</span>;
    <span class="java-visibilitymodifier">private</span> TheLevels theLevels;


    <span class="java-comment">/** Creates a new instance of PlayerSprite */</span>
    <span class="java-visibilitymodifier">public</span> PlayerSprite(Image image, <span class="java-primitives">int</span> frameWidth, <span class="java-primitives">int</span> frameHeight, <span class="java-primitives">int</span> scnWidth, <span class="java-primitives">int</span> scnHeight) <span class="java-keyword">throws</span> Exception {
        <span class="java-keyword">super</span>(image, frameWidth, frameHeight);
        defineReferencePixel(frameWidth/<span class="java-number">2</span>, frameHeight/<span class="java-number">2</span>);
        <span class="java-keyword">this</span>.scnWidth = scnWidth;
        <span class="java-keyword">this</span>.scnHeight = scnHeight;
        <span class="java-keyword">this</span>.frameWidth = frameWidth;
        <span class="java-keyword">this</span>.frameHeight = frameHeight;
        <span class="java-keyword">this</span>.isRun = <span class="java-keyword">false</span>;
        <span class="java-keyword">this</span>.setFrame(<span class="java-number">0</span>);
    }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> startPosition() {
    setPosition(scnWidth/<span class="java-number">2</span>,scnHeight-<span class="java-number">85</span>);
    
  }
    <span class="java-comment">//this.setFrameSequence(MOVEMENT_SEQUENCE);</span>
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveLeft() {
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span> (getX() - XMOVE &gt; <span class="java-number">0</span>) {
      move(XMOVE * -<span class="java-number">1</span>,<span class="java-number">0</span>);
      setTransform(TRANS_MIRROR);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
      System.out.println(<span class="java-literal">"Left"</span>);
      <span class="java-comment">//debug</span>
      System.out.println(<span class="java-literal">"X: "</span>+ MOVE);
    }
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveRight() {
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span> (getX() + XMOVE + END_BUFFER &lt; (scnWidth*<span class="java-number">6</span>)+<span class="java-number">96</span>) {
      move(XMOVE,<span class="java-number">0</span>);
      setTransform(TRANS_NONE);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
      System.out.println(<span class="java-literal">"Right"</span>);
      <span class="java-comment">//debug</span>
      System.out.println(<span class="java-literal">"Y: "</span>+ MOVE);
    }
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveUp() {
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span> (getY() - MOVE &gt; scnHeight-<span class="java-number">90</span>)
      move(<span class="java-number">0</span>, MOVE * -<span class="java-number">1</span>);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
      System.out.println(<span class="java-literal">"Up"</span>);
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveDown() {
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span> (getY() + MOVE + getHeight() &lt; scnHeight+<span class="java-number">20</span>)
      move(<span class="java-number">0</span>,MOVE);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
      System.out.println(<span class="java-literal">"Down"</span>);
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveUpLeft(){
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span>(xPos-DMOVE&gt;<span class="java-number">0</span>&amp;&amp;yPos-DMOVE&gt;<span class="java-number">0</span>)
      move(-DMOVE,-DMOVE);
      setTransform(TRANS_MIRROR);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveUpRight(){
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span>(xPos+DMOVE+frameWidth&lt;scnWidth&amp;&amp;yPos-DMOVE&gt;<span class="java-number">0</span>)
      move(DMOVE,-DMOVE);
      setTransform(TRANS_NONE);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveDownLeft(){
     <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span>(xPos-DMOVE&gt;<span class="java-number">0</span>&amp;&amp;yPos+DMOVE+frameHeight&lt;scnHeight)
      move(-DMOVE, DMOVE);
      setTransform(TRANS_MIRROR);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> moveDownRight(){
      <span class="java-comment">//getXY();</span>
    <span class="java-keyword">if</span>(xPos+DMOVE+frameWidth&lt;scnWidth&amp;&amp;yPos+DMOVE+frameHeight&lt;scnHeight)
      move(DMOVE,DMOVE);
      setTransform(TRANS_NONE);
      nextFrame();
      isRun = <span class="java-keyword">true</span>;
  }

  <span class="java-comment">/*public void getXY(){
      xPos=getX();
      yPos=getY();
  }*/</span>
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">int</span> giveX(){
      <span class="java-keyword">return</span> xPos;
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">int</span> giveY(){
      <span class="java-keyword">return</span> yPos;
  }
  <span class="java-visibilitymodifier">public</span> <span class="java-primitives">void</span> setRunOff(){
      <span class="java-keyword">if</span> (isRun){
          isRun = <span class="java-keyword">false</span>;
          setFrameSequence(<span class="java-keyword">null</span>);
          setFrame(<span class="java-number">0</span>);
      }
  }

}



</pre></div><!--ENDSCRIPT--> 

<!--EDIT--><span class=editedby><!--/EDIT-->[Edited by - thelegendofzaku on March 29, 2006 11:05:34 PM]<!--EDIT--></span><!--/EDIT-->
Advertisement
OK, I was able to fix the key pressing issue that I had. Looks like when I called super in my contstructor, it was set on true. After setting it on false, I was able to move my sprite in eight directions in the emulator, but on the real device, it only moved up and down, any takers? Anways, now the other problem I have is trying to juggle the sprite frame calls so that it cycles through a four-frame endless loop while walking and that the contstricts my sprite to my street pavement tile (all you need to know is that the pavement tile is 64x64. I'll update the source code from my first post on this thread.
I'll have a go at answering your walking animation question.
If you have 5 frames but the first one (standing still) is never used in the walking animation then you could try something like the following.

When user presses the arrow key (to walk) the player begins walking. When the user stops pressing the arrow key the player stops walking and goes to the standing still image.

So
if (arrow key is pressed)  player.move();else // no arrow pressed so no movement.  player.standing();move() {  spriteImage.setFrame(currentFrame++)  if (currentFrame &gt; maxSpriteFrames)    currentFrame = firstWalkingFrame;}standing() {  spriteImage.setFrame(standingFrame);  currentFrame = standingFrame;}



The above is puedocode, but basically whenever the arrow key is pressed the player will just cycle through the walking animation. Whenever the player stops pressing the arrow the player will go back to the standing frame and set the walking animation back to the start (currentFrame = standingFrame).
You should be able to expand the above to work for multiple directions. Just create methods called moveLeft, moveRight etc.

Hopefully this is clear. If not let me know.

Greig
Well, I was able to make my sprites animate when moved, and all it took was for me to set the frame sequences accordingly in the keyPressed and keyReleased methods. I have a feeling that it might get complicated when I have to set other sequences for things like punching and kicking frame sequences. Now on to another issue that I'm facing. I was wondering if someone can take a look at my two updated classes. I'm having a hard time trying to keep the scrolling within the dimensions of the tile layers since everytime I move my sprite to the very end of my tile layer, the view window goes beyond the last tile column, exposing the layers underneath it. That and for some reason, the scrolling is not working on my device, but works fine on the emulator. In other words, I can only move my sprite vertically on my phone, but when I try hitting the left or right key presses, it gets stuck and my sprite does not move at all, but still runs through the frame sequence. Also, I need help setting offsets so that the view window moves from a given point from a given direction in the total screen width. For example, let's say that my frame is originally centered in the middle of the screen and that my screen width is 176. I want to set conditions so that it would move the view window backwards if the current x position is above 44 pixels from the beginning of the screen width and that is within the length of the tile layer and to move forward if the current x position is above 132 pixels and it is within the total length of the tile layer. In other words, I want my view window follow the offsetted direction of my Sprite. Can somebody get back to me about this. My first post should have the latest code.

[Edited by - thelegendofzaku on March 8, 2006 11:14:11 AM]
I'm gonna give out more info which will help others solve this problem. So my tile layer is 18 tiles (each tile is 64 pixels wide) long, making it 1152. What I wanna do is have the view window move in a direction whenever the sprite is in a current horizontal pixel that is defined, you know like a trigger. In other words, since my current screen width is 176, I want my sprite to move the view window forwards when my sprite's current X position is 132 and to move it backwards when the sprites current X position is 88. Also, the view window must not be able to go beyond the boundaries of the tile layer. Someone please get to me about this.
Sorry to bump this but I seriously need someone's help on this please, since I want to get this issue out of the way once and for all. I wanna see if I can use maximum values for moving left so that the screen does not go beyond the beginning of the tile layer and minimum values so that the screen does not go beyond the last tile layer column. The problem that I'm having is in trying to implement these conditions in my sprite class, since at the moment, there is an if statement in my left and right methods in that for example when I move left, it will only move the sprite five number of pixels backwards per paint call if the sprite's current x position plus the rate in which I move my sprite (defined by x which happens to be five) is greater than zero and when I try moving to the right, it will only move my sprite five number of times if my sprites current x position + plus five plus 20 (just so that the screen does not go beyond the tile layer) is greater than the total width of the tile layer, which is 1150. With my current code, I am able to move left and right, however, whenever I reach the end of the tile layer on the right and I then move the opposite direction, the screen scrolls backward from that endpoint without an offset of a few pixels. As a result, when I scroll a little bit backwards and then move forwards again, my screen does not scroll at all. The same behavior occurs when I move my sprite to the beginning of the tile layer, in that the screen moves forward from the very beginning and cuts off my sprite when I move left. In other words, I want to create screen offsets so that my screen only moves to the right when my sprite reaches pixel 125 out of the screen witdh of 176 regardless of where it is on the tile layer; the same goes for only scrolling to the left if it is on the 35 pixel of the screen width. Someone please get back to me about this.

EDIT: Code updated in the first post.

This topic is closed to new replies.

Advertisement