2016-09-01 5 views
0

개인 프로젝트 용으로 Jet Set Willy를 기반으로 한 게임을 작성하고 있습니다. 알 수 있듯이, 캐릭터는 방에서 방으로 이동하여 그가가는 동안 아이템을 수집 할 수 있습니다.Java/LibGDX - 수집 된 항목을 방에서 방으로 추적

저는 LibGDX와 Tiled Map 편집기를 사용하고 있습니다.

I 현재 아래에 따라, '항목'라는 레이어에 내지도의 개체 타일을 기반으로 내 항목을로드 다음과 같이

public void loadItems() { 
    ////////////////////////////////////////////////////////////////////////// 
    //create all Items 
    for(MapObject object : map.getLayers().get(4).getObjects().getByType(RectangleMapObject.class)){ 
     Rectangle rect = ((RectangleMapObject) object).getRectangle(); 
     //new Item(screen, object); 
     items.add(new Item(this, object, (rect.getX() + rect.getWidth()/2)/Engine.PPM, (rect.getY() + rect.getHeight()/2)/Engine.PPM)); 
    } 
} 

항목

내 Playscreen에 배열에 저장된다 :

public static Array<Item> items; 

항목을 수집 할 때 간단히 화면에서 제거합니다.

방을 바꾸려면 기본적으로 새지도를로드하고 해당 레벨의 항목 등을 가져옵니다. 문제는 원래 방으로 다시 이동하면 항목을 다시 가져와 다시 모두 그려야한다는 것입니다. 다음과 같이

////////////////////////////////////////////////////////////////////////////// 
/** 
* Load the next Level 
*/ 
public void changeMap(int roomNumber, float x, float y) { 
    map.dispose(); 
    loadMap(roomNumber); 


    this.current_level = roomNumber; 

    renderer.getMap().dispose(); //dispose the old map 
    renderer.setMap(map); //set the map in your renderer 

    world = new World(new Vector2(0,-4), true); 
    world.setContactListener(new WorldContactListener()); 

    creator = new B2WorldCreator(this); 
    loadItems(); 

    //Reposition Player 
    player = new Player(world, this, x * Engine.TILE_WIDTH, y * Engine.TILE_HEIGHT); 
} 

내 항목 클래스는 다음과 같습니다

public class Item extends Sprite { 

protected World world; 
protected PlayScreen screen; 

private float stateTime; 
protected TiledMap map; 
protected MapObject object; 

private Animation animation; 
private Array<TextureRegion> frames; 
private boolean setToDestroy; 
private boolean destroyed; 
float angle; 
public Body b2body; 

FixtureDef fdef; 

private Texture tex; 
private Texture blank_texture; 
private int item_number; 

//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Constructor 
* @param screen 
* @param object 
* @param x 
* @param y 
*/ 
public Item(PlayScreen screen, MapObject object, float x, float y){ 
    this.world = screen.getWorld(); 
    this.screen = screen; 
    this.map = screen.getMap(); 
    //this.item_number = item_number; 

    setPosition(x, y); 

    Random rn = new Random(); 
    int max = 2; 
    int min = 1; 
    int random = rn.nextInt(5) + 1; 

    tex = new Texture(Gdx.files.internal("sprites/item" + random + ".png")); 

    frames = new Array<TextureRegion>(); 

    for(int i = 0; i < 4; i++) { 
     frames.add(new TextureRegion(tex, i * 16, 0, 16, 16)); 
    } 

    animation = new Animation(0.1f, frames); 

    blank_texture = new Texture(Gdx.files.internal("sprites/blank_item.png")); 

    setBounds(getX(), getY(), 15/Engine.PPM, 15/Engine.PPM); 
    setToDestroy = false; 
    destroyed = false; 
    angle = 0; 

    stateTime = 0; 

    define_item(); 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
*Define the Box2D body for the item 
*/ 
public void define_item() { 


    BodyDef bdef = new BodyDef(); 
    bdef.position.set(getX(), getY()); 
    bdef.type = BodyDef.BodyType.StaticBody; 
    b2body = world.createBody(bdef); 

    fdef = new FixtureDef(); 
    fdef.filter.categoryBits = Engine.ITEM_BIT; 
    fdef.filter.maskBits = Engine.PLAYER_BIT; 

    PolygonShape shape = new PolygonShape(); 
    shape.setAsBox(7/Engine.PPM, 7/Engine.PPM); 

    fdef.shape = shape; 

    b2body.createFixture(fdef).setUserData(this); 
    b2body.setGravityScale(0); 
    b2body.setActive(true); 
} 


public void redefineItem() { 

    Gdx.app.log("redefineItem", "Item"); 

    Vector2 position = b2body.getPosition(); 
    world.destroyBody(b2body); 

    BodyDef bdef = new BodyDef(); 
    bdef.position.set(position); 
    bdef.type = BodyDef.BodyType.StaticBody; 
    b2body = world.createBody(bdef); 

    fdef = new FixtureDef(); 
    fdef.filter.categoryBits = Engine.ITEM_BIT; 
    fdef.filter.maskBits = Engine.PLAYER_BIT; 

    PolygonShape shape = new PolygonShape(); 
    shape.setAsBox(7/Engine.PPM, 7/Engine.PPM); 

    fdef.shape = shape; 

    b2body.createFixture(fdef).setUserData(this); 
    b2body.setGravityScale(0); 
    b2body.setActive(true); 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Draw Method 
* @param batch 
*/ 
@Override 
public void draw(Batch batch) { 
    if(!destroyed) { 
     super.draw(batch); 
    } 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Update the Items 
* @param dt 
*/ 
public void update(float dt){ 

    setRegion(getFrame(dt)); 
    stateTime += dt; 

    if(setToDestroy && !destroyed){ 
     world.destroyBody(b2body); 
     destroyed = true; 
     setRegion(blank_texture); 
     stateTime = 0; 
    } 
    else if(!destroyed) { 
     setRegion(animation.getKeyFrame(stateTime, true)); 
     setPosition(b2body.getPosition().x - getWidth()/2, b2body.getPosition().y - getHeight()/2); 
    } 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Get the Texture 
* @param dt 
* @return 
*/ 
public TextureRegion getFrame(float dt){ 
    TextureRegion region; 
    region = animation.getKeyFrame(stateTime, true); 
    return region; 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Item has been collected 
* @param player 
*/ 
public void collected(Player player) { 
    if(Engine.bPlaySounds) { 
     Sound sound = Gdx.audio.newSound(Gdx.files.internal("audio/sounds/collect_item.wav")); 
     sound.play(1.0f); 
    } 

    //Change the Category Bit, so that it is no longer collidable 
    fdef.filter.categoryBits = Engine.COLLECTED_BIT; 
    this.setToDestroy = true; 

    Gdx.app.log("Collected Item ", "" + this.item_number + " from room " + screen.getCurrentLevel()); 

    //Increment the counter on the HUD 
    screen.incrementItemCounter(); 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Set the category Filter 
* @param filterBit 
*/ 
public void setCategoryFilter(short filterBit){ 
    Filter filter = new Filter(); 
    filter.categoryBits = filterBit; 
} 


//////////////////////////////////////////////////////////////////////////////////////////// 
/** 
* Get the Tilemap cell 
* @return 
*/ 
public TiledMapTileLayer.Cell getCell(){ 
    TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(0); 
    return layer.getCell((int)(b2body.getPosition().x * Engine.PPM/16), (int)(b2body.getPosition().y * Engine.PPM/16)); 
} 

}

내가 방 번호가 포함 배열의 어떤 종류에서 수집 각 항목을 저장, 그리고하려는 항목의 X/Y 위치. 항목을 다시 그릴 때 수집 된 목록에있는 항목을 건너 뜁니다. 문제는 Java에서이 작업을 수행하는 방법을 잘 모르겠습니다.

누구에게 내가 이것을 어떻게 달성 할 수있는 제안이 있습니까?

감사

제임스

+0

레벨, 항목 및 저장하려는 데이터의 수에 따라 libGDX의 환경 설정이 가장 쉽습니다. "작은 게임 상태 저장"에 대한 정의에 따라 달라 지거나 roomItemStates를 문자열 또는 숫자로 인코딩하는 영리한 방법을 찾을 수 있다면 - https://github.com/libgdx/libgdx/wiki/ Preferences –

+0

고마워, 나는 그것이 단순한 배열 [room_number, item_number] 일 수 있다고 생각했다. 항목을로드 할 때 아마도이 배열과 비교할 수 있으며 수집 된 배열에없는 항목 만 렌더링합니다. 게임을하는 동안에 만 기억할 필요가 있습니다. 게임 저장 등을 할 생각이 없습니다. 어떻게 생각하십니까? –

+0

아, 그래. 나는 오해했다. 나는 네가 끈기를 찾고 있다고 생각했다. 메모리에만 있으면 더 간단합니다. 해시 맵은 키가 방 번호 인 가장 쉬운 방법 일 수 있으며 값은 수집 된 항목 (목록, 배열 등)을 저장하려고 할 수 있습니다. –

답변

2

당신이 할 수있는 여러 가지 방법이 있습니다. 여기에 한 가지 제안이 있습니다.

지도 개체에 모든 객실의 항목 목록을 저장하고 적절한 경우 loadItems()에있는지도를 읽습니다. 또한 실제로 필요하지 않는 한 static의 사용을 피할 것입니다. Java에 대해 조금 익숙하지 않은 경우에는 쉽게 부적절한 버그가 발생할 수 있으며 대개는 객체 지향적 인 방법이 아닙니다.

private final IntMap<Array<Item>> roomsToItems = new IntMap(); 
private Array<Item> items; 

//... 

public void loadItems(int roomNumber) { 
    items = roomsToItems.get(roomNumber); //get this room's previous list if it exists 
    if (items == null) { //this room hasn't been loaded yet 
     items = new Array<>(); 

     //TODO: Load the items into "items" 

     //store the items list so it can be retrieved instead of loaded next time: 
     roomsToItems.put(roomNumber, items); 
    } 
} 

그럼 당신은 안전하게 items에서 항목을 제거 할 수 있으며 목록은 다음 번에 당신이 방에 들어갈 것을 반영합니다.

+0

당신은 또한 자바의'HashMap >'을 사용할 수 있지만, LibGDX IntMap은 게임에 더 잘 최적화되어 있습니다. int를 Integer 인스턴스에 box 할 필요는 없습니다. – Tenfour04

+0

감사합니다 Tenfour04, 좋은 생각입니다. 나는 그것에 균열을 확실히 가질 것이다. 시간을내어 다시 한번 감사드립니다. –

+0

이것은 스프라이트를 다시 그리는 관점에서 완벽하게 작동하지만, 방을 다시 들어올 때 다시로드 될 때, 그들은 모두 Box2D 바디를 잃어버린 것이므로 더 이상 수집 할 수 없습니다. redefineItem()이라는 Item에 box2D 본문을 다시 작성하지만 여전히 작동하지 않는 메서드를 호출하겠습니다. 이 문제를 해결할 수있는 아이디어가 있습니까? –