2013-05-01 75 views
0

我製作了一個帶有兩個類的Sokoban,邏輯和SokobanGUI。我的2D遊戲Sokoban正在工作,但我想知道如果我改進設計

基本上,logicpart建立從輸入字符串數組一個ArrayList>,f.ex:

String[] level1 = 
       {"*###########*", 
       "#   #", 
       "# ... ... #", 
       "# *$$ $.$ #", 
       "# $*+$ $*$$ #", 
       "# *$$ $.$ #", 
       "# ... . #", 
       "#   #", 
       "*###########*"}; 

其中 '+' 是玩家位置。

無論如何,該ArrayList在邏輯類更新爲遊戲的玩法是(播放機正在移動時,字符被交互等)

遊戲的圖形部分通過分配圖片到每個字符和循環解決通過arraylist>。然後,這更新inn一個無限的while循環,這樣當邏輯部分中的arraylist>更新時,它將被再次打印。

如果這很難遵循,我打印下面的代碼。

問題1:我不認爲這是輸出遊戲的最佳方式(帶有一段時間的Lopp),因爲我始終以圖形方式輸出遊戲,即使沒有進行任何更改。這通常如何處理?擺動什麼可以幫助醫治這件事?

問題2:另外,在下面的代碼中,我沒有使用main方法,我使用run()。主要方法不喜歡我做非靜態引用,並且運行起作用,所以我去了它...我應該如何使用主要方法來使遊戲工作?

也許是更容易看到我的代碼:

邏輯類

package Sokoban2; 

import java.util.ArrayList; 

public class Logic { 


int player_x; 
int player_y; 
int nextMove_x; 
int nextMove_y; 
ArrayList<ArrayList<Boolean>> targets; 
ArrayList<ArrayList<Character>> grid; 
Boolean canMove; 


public Logic(){ 
    buildGrid(); 
    buildTargets(); 
    findPlayer(); 
} 

    public void move(int dx, int dy){ 
    if(CheckCanMove(dx, dy)){ 
    moveBox(dx, dy); 
    movePlayer(dx, dy); 
    } 


} 


public void movePlayer(int dx, int dy){ 

    boolean boxAhead = (getChar(dx,dy) == '#'); 

    if(!boxAhead){ 

    char pChar = grid.get(player_x).get(player_y); 
    char pCharNext = grid.get(player_x +dx).get(player_y +dy); 

    if(pChar == '@'){ 
     if(pCharNext == ' ' || pCharNext == '$'){ 
      grid.get(player_x + dx).set(player_y + dy, '@'); 
      grid.get(player_x).set(player_y, ' '); 
     } 
     if(pCharNext == '.' || pCharNext == '*'){ 
      grid.get(player_x + dx).set(player_y + dy, '+'); 
      if(pChar == '+'){ 
       grid.get(player_x).set(player_y, '.'); 
      } 
      else{ 
       grid.get(player_x).set(player_y, ' '); 
      } 
     } 
    } 

    else if(pChar == '+'){ 
     if(pCharNext == ' ' || pCharNext == '$'){ 
      grid.get(player_x + dx).set(player_y + dy, '@'); 
      grid.get(player_x).set(player_y, '.'); 
     } 
     if(pCharNext == '.' || pCharNext == '*'){ 
      grid.get(player_x + dx).set(player_y + dy, '+'); 
      grid.get(player_x).set(player_y, '.'); 


     } 
    } 




    player_x += dx; 
    player_y += dy; 

    } 



} 


public void buildGrid(){ 
    char c = '"'; 


    grid = new ArrayList<ArrayList<Character>>(); 

    String[] level1 = 
       {"*###########*", 
       "#   #", 
       "# ... ... #", 
       "# *$$ $.$ #", 
       "# $*+$ $*$$ #", 
       "# *$$ $.$ #", 
       "# ... . #", 
       "#   #", 
       "*###########*"}; 



    int length_i = level1.length; 
    System.out.println(length_i); 
    int length_i_j = level1[length_i-1].length(); 



    for(int i = 0; length_i>i; i++){ 
     grid.add(i, new ArrayList<Character>()); 
     for(int j = 0; length_i_j>j; j++){ 
      c = level1[i].charAt(j);     
      grid.get(i).add(c); 
     } 
    } 


} 


public void buildTargets(){ 


    targets = new ArrayList<ArrayList<Boolean>>(); 

    char c = ' '; 
    int length_i = grid.size(); 

    for(int i = 0; length_i>i; i++){ 
     targets.add(i, new ArrayList<Boolean>()); 
     for(int j = 0; grid.get(i).size()>j; j++){ 
      c = grid.get(i).get(j); 
      if(c == '.'){ 
       targets.get(i).add(false); 
      } 
      else{ 
       targets.get(i).add(true); 
      } 

     } 
    } 

} 

public void findPlayer(){ 
    char c = ' '; 
    int length_i = grid.size(); 

    for(int i = 0; length_i>i; i++){ 
     for(int j = 0; grid.get(i).size()>j; j++){ 
      c = grid.get(i).get(j); 
      if(c == '@' || c == '+'){ 
       player_x = i; 
       player_y = j; 
      } 
     } 
    } 


} 

public Character getChar(int dx, int dy){ 

    char c = ' '; 
    c = grid.get(player_x + dx).get(player_y + dy); 
    return c; 

} 



public void moveBox(int dx, int dy){ 
    char c1 = getChar((dx),(dy)); 
    char c2 = getChar((2*dx),(2*dy)); 


    if(c1 == '*' || c1 == '$'){ 
     if(c2 == '.'){ 
      grid.get(player_x +2*dx).set(player_y +2*dy, '*'); 
     } 
     if(c2 == ' '){ 
      grid.get(player_x +2*dx).set(player_y +2*dy, '$'); 
     } 
    } 




} 

public boolean CheckCanMove(int dx, int dy){ 
    canMove = true; 

    boolean boxAhead = (getChar(dx,dy) == '#'); 
    boolean boxAhead2 = (getChar(2*dx,2*dy) == '#'); 
    boolean movableAhead = (getChar(dx,dy) == '$'); 
    boolean movableAhead2 = (getChar(2*dx,2*dy) == '$'); 
    boolean movableAheadS = (getChar(dx,dy) == '*'); 
    boolean movableAheadS2 = (getChar(2*dx,2*dy) == '*'); 


    if(boxAhead || (movableAhead && boxAhead2) || (movableAhead &&  
       movableAhead2) || (movableAheadS && movableAheadS2) || (movableAheadS && 
       boxAhead2)){ 
     canMove = false; 
    } 

    return canMove; 
} 





void setPlayerX(int player_x){ 
    this.player_x = player_x; 
} 

void setPlayerY(int player_y){ 
    this.player_y = player_y; 
} 

} 

圖形類 包Sokoban2;

import acm.graphics.GImage; 
import java.awt.event.KeyEvent; 

import acm.graphics.GImage; 
import acm.program.GraphicsProgram; 

public class SokobanGUI extends GraphicsProgram { 


Logic logic = new Logic(); 
GImage wall; 
GImage blank; 


    @Override 
public void init() { 
    logic = new Logic(); 
    addKeyListeners(); // This is required for listening to key events 

} 


@Override 
public void run() { 
    System.out.println(logic.player_x); 
    System.out.println(logic.player_y); 
    while(true){ 
     paint(); 
     println("hah"); 
    } 
//  System.out.println("win"); 
} 


public void paint(){ 
    char c =' '; 
    int length_i = logic.grid.size(); 

    for(int i = 0; length_i>i; i++){ 
     for(int j = 0; logic.grid.get(i).size()>j; j++){ 
      c = logic.grid.get(i).get(j); 
      switch (c) { 
      case '#': 
       GImage wall = new GImage("sokoban/wall16x16.png"); 
       wall.setLocation(16*j,16*i); 
       add(wall);   
       break; 
      case ' ': 
       GImage blank = new GImage("sokoban/blank16x16.png"); 
       blank.setLocation(16*j,16*i); 
       add(blank);   
       break; 
      case '@': 
       GImage player = new GImage("sokoban/mover16x16.png"); 
       player.setLocation(16*j,16*i); 
       add(player);   
       break; 
      case '$': 
       GImage movable = new GImage("sokoban/movable16x16.png"); 
       movable.setLocation(16*j,16*i); 
       add(movable);   
       break; 
      case '.': 
       GImage target = new GImage("sokoban/target16x16.png"); 
       target.setLocation(16*j,16*i); 
       add(target);   
       break; 
      case '*': 
       GImage movable_on_target = new  
GImage("sokoban/movable_on_target16x16.png"); 
       movable_on_target.setLocation(16*j,16*i); 
       add(movable_on_target);   
       break; 
      case '+': 
       GImage mover_on_target = new 
GImage("sokoban/mover_on_target16x16.png"); 
       mover_on_target.setLocation(16*j,16*i); 
       add(mover_on_target);   
       break; 

      } 
      } 
     } 
} 

public boolean win(){ 
    int length_i = logic.targets.size(); 
    int win = 0; 
    for(int i = 0; length_i>i; i++){ 
     for(int j = 0; logic.targets.get(i).size()>j; j++){ 
      if(!logic.targets.get(i).get(j)){ 
       win += 1; 
      } 
     } 
    } 
    return (!(win>0)); 
} 

@Override 
public void keyPressed(KeyEvent event) { 
    int key; 
    if (Character.isLetter(event.getKeyChar())) 
     key = event.getKeyChar(); 
    else 
     key = event.getKeyCode(); 

    switch (key) { 

    case 'w': 
     logic.move(-1, 0); 
     break; 
    case 's': 
     logic.move(1, 0); 
     break; 
    case 'a': 
     logic.move(0, -1); 
     break; 
    case 'd': 
     logic.move(0, 1); 
     break; 

    } 
} 

} 

回答

2

問題1:爲了防止不必不斷作畫,甚至沒有任何投入,只需要檢查看看是否有什麼改變(怪物移動,移動播放器等)。我認爲這是一個Roguelike,所以你可能只需要檢查一下球員是否移動。

if(playerMoved()) { 
    paint(); 
} 

問題2:我不知道是什麼GraphicsProgram包含,但我相信在它的main()正在使用。使用run()方法來運行遊戲循環並沒有什麼本質的錯誤,事實上,這是大多數遊戲的工作原理。就像現在一樣,您的main()最多隻會啓用run()方法。所以你很好!

HTH

+0

非常感謝!這就說得通了! :) – tore 2013-05-01 15:12:50

相關問題