1
\$\begingroup\$

enter image description here

enter image description here

NEW IMAGE NO SPRITE WITH :

   if(q>=15){
        screen.clear(0);
        screen.render(Art.sprites[i][0], 20 , cx);
        i++;
        movement();
        cx+=1;
        if(i>=3)i=0;
        q=0;

    }

This sprite leaves a trail and I can't find a way to fix it. I spent close to a good 2 hours trying to look online for it and could not fix it if someone could help that would be great. <3

Note: The sprite is drawn in the "render" method. (I hope that there is enough information. Also 1st time working with sprites)

import java.awt.Canvas;
import java.awt.Color;
//import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

 import me.matt.tower.gfx.Art;
 import me.matt.tower.gfx.Screen;

  public class TowerComponent extends Canvas implements Runnable{

/**
 * 
 */
private static final long serialVersionUID = 1L;
public static final int WIDTH = 640, HEIGHT = 480;
private boolean running =false;
public static final String NAME = "Tower Of Death";

private Screen screen;
public int q=0;
public int i=0;
public int cx= 20;
public int cy= 20;




public TowerComponent (){
    screen = new Screen (WIDTH, HEIGHT);

}

public void stop(){

    running = false;

}
public void start(){
    running = true;
    new Thread(this).start();
}





@Override
public void run() {
    int fps = 0, tick = 0;

    double fpsTimer = System.currentTimeMillis();

    double nsPerTick = 1000000000.0d / 60;
    double then = System.nanoTime();
    double unprocessed = 0;


    while(running){
        boolean canRender = false;
        double now = System.nanoTime();

        unprocessed += (now-then) / nsPerTick;
        then = now;
        while (unprocessed >=1){

            //Updates game objects
            tick++;
            tick();
            canRender = true;
            --unprocessed;

        }

            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            //draws game objects
            if(canRender){
                fps++;
                render();
            }
            //FPS Counter Report
            if(System.currentTimeMillis()- fpsTimer >1000){
                System.out.printf("%d fps, %d tick%n",fps,tick);
                fps = 0; tick =0;
                fpsTimer +=1000;
            }

    }




}
private void render() {

    BufferStrategy bs = getBufferStrategy();
    if(bs == null){
        createBufferStrategy(2);
        requestFocus();
        return;
    }
    Graphics g = bs.getDrawGraphics();
    //Rendering

        q++;// counts frames.... use fps count later?

    if(q>=15){
        screen.clear(0);
        screen.render(Art.sprites[i][0], 20 , cx);
        i++;
        movement();
        cx+=1;
        if(i>=3)i=0;
        q=0;

    }
    //done rendering

    g.drawImage(screen.image, 0,0, WIDTH,HEIGHT,null);

    g.dispose();
    bs.show();
  }

public void movement(){
 cx+=10;
 cy+=10;
 screen.clear(0);
 repaint();
 }

private void tick() {


}

public static void main(String [] args){
    TowerComponent game = new TowerComponent();
    Dimension dimension = new Dimension(WIDTH,HEIGHT);
    game.setMaximumSize(dimension);
    game.setMaximumSize(dimension);
    game.setPreferredSize(dimension);
    game.setSize(dimension); 
    JFrame frame = new JFrame();
    frame.setTitle(NAME);
    frame.add(game);
    frame.pack();
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
    game.start();

}

}

Bitmap class

package me.matt.tower.gfx;

import java.util.Arrays;

public class Bitmap {

public int w,h;
public int [] pixels;
public Bitmap(int w , int h){
    this.w = w;
    this.h = h;
    pixels = new int [w*h]; 
}

//public void clear(int color){
//  Arrays.fill(pixels, color);
//}
public void render(Bitmap bitmap, int x, int y){
    int x0= x;
    int x1 = x + bitmap.w;
    int y0=y;
    int y1 = y + bitmap.h;
    if(x0 <0)x0=0;
    if(x1>w) x1 = w;
    if(y0 < 0)y0=0;
    if(y1 >h) y1=h;
    int ww = x1 - x0;

    for (int yy= y0; yy < y1; yy++){
        int tp = yy *w +x0;
        int sp = (yy - y )* bitmap.w + (x0 -x);
        tp -= sp;
            for(int xx = sp; xx < sp + ww; xx++){
                int col = bitmap.pixels[xx];
                if (col < 0) pixels [tp+xx] = col;

        }

    }
}

}

Screen class

package me.matt.tower.gfx;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

public class Screen extends Bitmap{

public BufferedImage image;

public Screen(int w, int h) {
    super(w, h);
    image = new BufferedImage(w ,h , BufferedImage.TYPE_INT_ARGB);
    pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

}

}

Art class

import java.io.IOException;

import javax.imageio.ImageIO;

import me.matt.tower.TowerComponent;

public class Art {

public static final Bitmap [][] sprites = cut("/SpriteSheet.png", 32 ,32);
private static Bitmap[][] cut(String string, int w,int h){
    return cut(string ,w,h,0,0);

}

private static Bitmap[][] cut(String string, int w, int h, int sx ,int sy){
    try {
        BufferedImage image = ImageIO.read(TowerComponent.class.getResourceAsStream(string));
        int xTiles = (image.getWidth()- sx)/w;
        int yTiles = (image.getHeight()-sy)/h;
        Bitmap[][] result = new Bitmap[xTiles][yTiles];
        for(int x= 0; x< xTiles;x++){
            for(int y=0;y< yTiles;y++){
            result[x][y]=new Bitmap(w,h);

            image.getRGB( sx + x * w, sy + y * h,w,h,result[x][y].pixels,0,w);
            }
        }

        return result;
    } catch (IOException e) {

        e.printStackTrace();
    }
    return null;
    }

}
\$\endgroup\$
6
  • 4
    \$\begingroup\$ Looks like you don't clear the screen. \$\endgroup\$ Oct 6 '15 at 2:36
  • \$\begingroup\$ 'screen.clear();' i couldn't get to work it would just clear screen when i got the sprite to display. Maybe I'm using it wrong?(I've also tried it in many different spots just to see if i could get it to work.) \$\endgroup\$ Oct 6 '15 at 2:41
  • 2
    \$\begingroup\$ You need to call clear in your render loop before calling drawImage. \$\endgroup\$
    – ashes999
    Oct 6 '15 at 3:06
  • \$\begingroup\$ tried it in many different spots just to see if i could get it to work and that was one of the places i put it. :/ still doesn't work \$\endgroup\$ Oct 6 '15 at 3:29
  • \$\begingroup\$ The screen.clear(); call must be just before screen.render(...) inside public void render() function. Could you post the contents of the screen.render(...) function? \$\endgroup\$ Oct 6 '15 at 3:44
4
\$\begingroup\$

The way a computer draws to the screen is very different to say... how we draw on a piece of paper. The computer actually is flipping bits on a memory array, called the video memory. This memory array happens to be represented on the screen as an image a human can understand. With this in mind, let's start:

When you draw a sprite—several times, on different positions and without clearing the screen first—the PC actually grabs the array representing the sprite and copies the values into its video memory, but only modifies the region that the sprite will occupy. This means that whatever was already on the video memory will still remain there, leading to something similar to this:

The familiar stairs from ye old windows hangs

So in order for you to prevent this to happen, you totally clear all the bits on the video memory that represent the screen to a certain color, and then draw your new sprites all over again. Of course you only clear the screen once and only once per frame, not for every sprite (which I think is what happened on your second example screenshot).

The process can be outlined like this:

  1. You clear the screen to whatever color you like.
  2. You draw all that needs to be drawn on a single time step of your game.
  3. You flip the display if you have Double Buffering enabled.
  4. Repeat.

So, I think I misunderstood how the drawing works in your specific code, but the thing is that you have to find the spot outside any loop that draws objects and clear the screen there, just in time before starting to draw the new frame.

While this example example uses a different language (C) on a different API (Allegro 5) this section applies the process quite well:

al_clear_to_color(al_map_rgb(0,0,0));

al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
al_draw_bitmap(ball, ball_x, ball_y, 0);
al_draw_bitmap(monster, monster_x, monster_y, 0);

al_flip_display();

Note: The code on the link doesn't have the ball and monster lines, I just added them to exemplify point 2 of the process I described above.

\$\endgroup\$
4
  • \$\begingroup\$ I did as you said and all i get is a blank now no sprite shows up \$\endgroup\$ Oct 7 '15 at 17:31
  • \$\begingroup\$ OK so probably that is not the correct spot to put that line then... Give me some time to see your code posted here and I will find the correct spot \$\endgroup\$
    – rlam12
    Oct 7 '15 at 20:15
  • \$\begingroup\$ So hopefully this version at least gives you a light on the subject and leads you to a solution to your issue. \$\endgroup\$
    – rlam12
    Oct 8 '15 at 5:27
  • \$\begingroup\$ I read what you posted and not 5 minutes later it works. Thank you so much<3 \$\endgroup\$ Oct 9 '15 at 17:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.