Search code examples
slick2d

I'm stuck at slick graphics


I'm trying to make a game, using slick2d, and lwjgl. I don't get why this code doesn't work

firstStage.java

package net.CharlesDickenson;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

public class firstStage extends BasicGameState {

    public bossVar bossChecker() {
        if(isBeforeMiddleBoss) return bossVar.beforeBoss;

        if(isMiddleBoss) return bossVar.Middle;

        if(isBeforeBoss) return bossVar.beforeBoss;

        if(isBoss) return bossVar.Boss;

        return null;
    }

    @SuppressWarnings("static-access")
    public firstStage(int state) {
        this.state = state;
    }

    @Override
    public void init(GameContainer _arg0, StateBasedGame _arg1)
            throws SlickException {
        scoreBoard = new Image("res/scoreBoard.png");
        backs = new Image("res/1stageBack.gif");
        isBeforeMiddleBoss = true;
        isMiddleBoss = false;
        isBeforeBoss = false;
        isBoss = false;
        _arg0.setShowFPS(false);
    }

    @Override
    public void render(GameContainer arg0, StateBasedGame _arg1, Graphics _g)
            throws SlickException {
        this._g = _g;

        new Mob().getGraphics(_g);//i passed graphics
        new Char().getGraphics(_g);//i passed graphics
        new Bullet().getGraphics(_g);//i passed graphics

        _g.drawImage(scoreBoard, 550, 5);
        _g.drawImage(backs, 10, 10);
        _g.drawString(fps, 580, 570);
        _g.drawString("High Score-> Not avaiable", 560, 60);
        _g.drawString("Score-> " + currScore, 595, 80);
    }

    @Override
    public void update(GameContainer _arg0, StateBasedGame _arg1, int arg2)
            throws SlickException {
        fps = "Frame Per Second-> " + _arg0.getFPS();

        bossVar b = bossChecker();

        switch(b) {
        case beforeMiddle :
            break;
        case Boss :
            break;
        default:
            break;
        }
    }

    @SuppressWarnings("static-access")
    @Override
    public int getID() {
        return this.state;
    }

    private static int state;
    private static int currScore = 0;
    private static final int originX = 270;
    private static final int originY = 490;
    public static int X = originX;
    public static int Y = originY;
    private static String fps;
    private Image scoreBoard;
    private Image backs;
    private Graphics _g;
    public boolean isBeforeMiddleBoss;
    public boolean isMiddleBoss;
    public boolean isBeforeBoss;
    public boolean isBoss;

}

Char.java

package net.CharlesDickenson;

import org.lwjgl.input.Keyboard;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

public class Char extends Bullet implements Entity {

    @Override
    public void getGraphics(Graphics _g) {
        this._g = _g;//so i got graphics, but 
        if(!isInit) return;
        _g.drawImage(Char, getCharX(), getCharY());//this codes doesn't works.
    }

    @Override
    public int getCharX() {
        switch(VarTracker.stage) {
        case 1:
            return firstStage.X;
        }
        return 0;
    }

    @Override
    public int getCharY() {
        switch(VarTracker.stage) {
        case 1:
            return firstStage.Y;
        }
        return 0;
    }

    public void setCharX(int i) {
        System.out.println("asdgagsd");
        switch(VarTracker.stage) {
        case 1:
            firstStage.X += i;
        }
    }

    public void setCharY(int i) {
        System.out.println("asdgagsd");
        switch(VarTracker.stage) {
        case 1:
            firstStage.Y += i;
        }
    }

    @Override
    public void update() {
        if(!isInit) return;

        _g.drawImage(Char, getCharX(), getCharY());//this code doesn't work, too.

        up = Keyboard.isKeyDown(Keyboard.KEY_UP);
        down = Keyboard.isKeyDown(Keyboard.KEY_DOWN);
        left = Keyboard.isKeyDown(Keyboard.KEY_LEFT);
        right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
        shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
        z = Keyboard.isKeyDown(Keyboard.KEY_Z);

        if(up && !shift) {
            setCharY(6);
        }

        if(down && !shift) {
            setCharY(-6);
        }

        if(left && !shift) {
            setCharX(-6);
        }

        if(right && !shift) {
            setCharX(6);
        }

        if(up && shift) {
            setCharY(2);
        }

        if(down && shift) {
            setCharY(-2);
        }

        if(left && shift) {
            setCharX(-2);
        }

        if(right && shift) {
            setCharX(2);
        }

        if(z) {
            new Bullet().isFiring = true;
        }

        if(!z) {
            new Bullet().isFiring = false;
        }
    }

    @Override
    public void init() {
        System.out.println("<Char> Initializing...");

        isInit = false;

        try {
            Char = new Image("res/char.png");
        } catch (SlickException e) {
            e.printStackTrace();
        }

        isInit = true;

        System.out.println("<Char> Done with init()");
    }

    private boolean up;
    private boolean down;
    private boolean left;
    private boolean right;
    private boolean shift;
    private boolean z;
    private boolean isInit;
    private Image Char;
    private Graphics _g;
}

I passed graphics to other class using getGraphics method, to put a image, but it doesn't work. at render method, it worked, but I can't put a image in other class.


Solution

  • The reason that it doesn't work is that you are using Graphics incorrectly. When Slick2d draws something, it uses the render method. This method is passed an instance of Graphics, to which you can draw stuff. When the call ends the Graphics object is no longer useful for anything. There is thus no reason to pass it to anything that doesn't use it immediately.

    What you want to do is create a render method in your Mob, Char and Bullet classes. Make instances of said classes outside of the render method, for instance in init and store them in some data structure, for instance a List. In the render method, you simple traverse the list and call render or draw on each element. A quick example:

    // Give the Entity interface two methods if they don't exist already:
    public interface Entity {
        void render(Graphics g);
        void update(int delta);
    }
    
    // In firststage.java
    List<Entity> list;
    
    // In the init() method
    public void init(GameContainer container, StateBasedGame game)
            throws SlickException {
        ...
        list = new ArrayList<Entity>();
        list.add(new Mob());
        list.add(new Char());
        list.add(new Bullet());
    }
    
    // In the render method
    public void render(GameContainer container, StateBasedGame game, Graphics g)
            throws SlickException {
        ...
        for (Entity e : list) {
            e.draw(g);
        }
    }
    
    // In the update method
    public void update(GameContainer container, StateBasedGame game, int delta)
            throws SlickException {
        ...
        for (Entity e : list) {
            e.update(delta);
        }
    }
    

    TL;DR version: The Graphics object exists only to be drawn to in a single render call. Render is called many times a second, so object creation in that method is not recommended. Object oriented programming is good at modeling objects. Games tend to model a lot of objects. Make use of it.