diff --git a/.gitignore b/.gitignore index a7109a5..092c281 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .settings +.DS_store .gradle .idea bin @@ -8,6 +9,7 @@ nbandroid private build app/src/main/res/values/version.xml +app/release compiler/compiler.obj compiler/compiler.exe compiler/test/compiler.exe diff --git a/app/build.gradle b/app/build.gradle index f78daa0..da0f27e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,12 +2,14 @@ plugins { id 'com.android.application' } +apply plugin: "androidx.navigation.safeargs" + // // Creates version.xml // task createVersionXML { doLast { - def versionP = 'git describe --tags --long --dirty=-x --abbrev=8' + def versionP = 'git describe --tags --long --dirty=-x --always --abbrev=8' .execute() versionP.waitFor() def version = versionP.text.trim() @@ -72,13 +74,29 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildFeatures { + viewBinding true + } } dependencies { + def nav_version = "2.3.5" implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + // Java language implementation + implementation "androidx.navigation:navigation-fragment:$nav_version" + implementation "androidx.navigation:navigation-ui:$nav_version" + // Feature module Support + implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" + // Testing Navigation + androidTestImplementation "androidx.navigation:navigation-testing:$nav_version" + // Jetpack Compose Integration + implementation "androidx.navigation:navigation-compose:2.4.0-alpha10" } + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7c97d1d..f1b1398 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,31 +1,24 @@ - - - + package="org.vostan.banvor" + android:versionName="@string/git_version"> + + + - - - - + + \ No newline at end of file diff --git a/app/src/main/java/org/vostan/banvor/App.java b/app/src/main/java/org/vostan/banvor/App.java index bc7c3b8..326e21e 100644 --- a/app/src/main/java/org/vostan/banvor/App.java +++ b/app/src/main/java/org/vostan/banvor/App.java @@ -4,20 +4,20 @@ import android.app.Application; import android.content.SharedPreferences; import android.util.Log; +import org.vostan.banvor.game.State; +import org.vostan.banvor.model.PuzzleContainer; +import org.vostan.banvor.model.IPuzzleSource; + public class App extends Application { public static final String TAG = "Sokoban"; public static final String PREFS = "org.dyndns.vahagn.sokoban.prefs"; public static final int MIN_LEVEL = 1; - + private static App mApp = null; - protected PuzzleContainer pc; - protected int current_level; - protected int achieved_level; - protected int max_level; + protected State gameState; protected SharedPreferences prefs; - protected SharedPreferences.Editor prefsEdit; - + /* * */ @@ -26,98 +26,26 @@ public class App extends Application { super.onCreate(); mApp = this; - pc = new PuzzleContainer(); + + PuzzleContainer pc = new PuzzleContainer(); + gameState = new State(pc); prefs = getSharedPreferences(PREFS, MODE_PRIVATE); - prefsEdit = prefs.edit(); - max_level = pc.getCount(); - current_level = prefs.getInt("current_level", MIN_LEVEL); - achieved_level = prefs.getInt("achieved_level", MIN_LEVEL+10); + + gameState.loadState(prefs); } + + public void storeGameState(){ + gameState.storeState(prefs.edit()); + } + // // This is a singleton object. // - public static App theApp() - { + public static App theApp() { return mApp; } - // - // Puzzles. - // - public Puzzle getPuzzle( int level ) - { - return pc.getPuzzle( level-1 ); - } - public Puzzle getCurrentPuzzle() - { - return getPuzzle( getCurrentLevel() ); - } - public Puzzle getPrevPuzzle() - { - if ( current_level != MIN_LEVEL ) - return getPuzzle( getCurrentLevel()-1 ); - else - return null; - } - public Puzzle getNextPuzzle() - { - if ( current_level != achieved_level ) - return getPuzzle( getCurrentLevel()+1 ); - else - return null; - } - // - // Provide amount of puzzles. - // - public final int getPuzzleCount() - { - return max_level; - } - // - // Provide highest solved puzzle. - // - public final int getAchivedLevel() - { - return achieved_level; - } - // - // Provide last played puzzle. - // - public final int getCurrentLevel() - { - return current_level; - } - // - // Set the current puzzle level. - // - public void setCurrentLevel( int l ) - { - if ( l > achieved_level ) - l = MIN_LEVEL; - if ( l < MIN_LEVEL ) - l = achieved_level; - if ( l != current_level ) - { - current_level = l; - prefsEdit.putInt("current_level", current_level); - prefsEdit.apply(); - if ( !prefs.edit().commit() ) - Log.d(TAG, "prefs.edit().commit() failed."); - } - } - // - // Set achieved level. - // - public void advanceAchivedLevel( int l ) - { - if ( l > max_level ) - l = max_level; - if ( l > achieved_level ) - { - achieved_level = l; - prefsEdit.putInt("achieved_level", achieved_level); - prefsEdit.apply(); - if ( !prefs.edit().commit() ) - Log.d(TAG, "prefs.edit().commit() failed."); - } + + public State state(){ + return gameState; } } diff --git a/app/src/main/java/org/vostan/banvor/PuzzleBoardFragment.java b/app/src/main/java/org/vostan/banvor/PuzzleBoardFragment.java new file mode 100644 index 0000000..b480fd9 --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/PuzzleBoardFragment.java @@ -0,0 +1,147 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.vostan.banvor; + +import static org.vostan.banvor.App.theApp; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; + +import org.vostan.banvor.board.PuzzleControl; +import org.vostan.banvor.databinding.FragmentPuzzleBoardBinding; +import org.vostan.banvor.game.State; + +/** + * + */ +public class PuzzleBoardFragment extends Fragment +{ + private FragmentPuzzleBoardBinding binding; + private State gameState; + private PuzzleControl mPuzzleView; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + gameState = theApp().state(); + binding = FragmentPuzzleBoardBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + int gameLevel = PuzzleBoardFragmentArgs.fromBundle(getArguments()).getLevel(); + gameState.setCurrentLevel(gameLevel); + + initAndShowCurrentPuzzle(); + + binding.gameBoard.setPuzzleControlLister(new PuzzleControl.PuzzleControlLister() { + @Override + public void onSolved() { + PuzzleBoardFragment.this.onSolved(); + } + + @Override + public void onLongPress() { + } + + @Override + public void onTouch() { + } + }); + binding.btnPrev.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + gameState.setCurrentLevel(gameState.getCurrentLevel()-1); + PuzzleBoardFragment.this.initAndShowCurrentPuzzle(); + } + }); + binding.btnNext.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + gameState.setCurrentLevel(gameState.getCurrentLevel()+1); + PuzzleBoardFragment.this.initAndShowCurrentPuzzle(); + } + }); + binding.btnReset.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + PuzzleBoardFragment.this.initAndShowCurrentPuzzle(); + } + }); + binding.btnUndo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + createNextLevelDialog(new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface d, int w){ + gameState.advanceCurrentLevel(); + initAndShowCurrentPuzzle(); + } + }).show(); + } + }); + } + + private void initAndShowCurrentPuzzle() { + int gameLevel = gameState.getCurrentLevel(); + binding.levelNumber.setText(Integer.toString(gameLevel)); + binding.gameBoard.setPuzzle(gameState.getCurrentPuzzle()); + } + + private void onSolved(){ + // + // Since the puzzle is solved, we need to unlock next level if still locked. + // + gameState.levelSolved(gameState.getCurrentLevel()); + // + // Bring a dialog for user to choose to continue or stop. + // +// DialogFragment df = new DialogFragment() { +// public Dialog onCreateDialog(Bundle savedInstanceState) { +// return createNextLevelDialog(new DialogInterface.OnClickListener(){ +// public void onClick(DialogInterface d, int w){ +// gameState.advanceCurrentLevel(); +// initAndShowCurrentPuzzle(); +// } +// }); +// } +// }; +// df.show(getChildFragmentManager(), null); + createNextLevelDialog(new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface d, int w){ + gameState.advanceCurrentLevel(); + initAndShowCurrentPuzzle(); + } + }).show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + + private Dialog createNextLevelDialog(DialogInterface.OnClickListener listener){ + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle("Congratulations! You Won!"); + builder.setMessage( "Would you like to try the next puzzle?" ); + builder.setPositiveButton("Yes, please.", listener); + // Create the AlertDialog object and return it + Dialog dlg = builder.create(); + dlg.setCancelable(true); + return dlg; + } +} diff --git a/app/src/main/java/org/vostan/banvor/PuzzleListFragment.java b/app/src/main/java/org/vostan/banvor/PuzzleListFragment.java new file mode 100644 index 0000000..c4b02cc --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/PuzzleListFragment.java @@ -0,0 +1,197 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.vostan.banvor; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.navigation.fragment.NavHostFragment; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; + +import static org.vostan.banvor.App.theApp; + +import org.vostan.banvor.databinding.FragmentPuzzleListBinding; +import org.vostan.banvor.game.State; + +/** + * + */ +class PuzzlesAdapter extends BaseAdapter +{ + private State gameState; + private Context context; + private int icon_size; + private int text_size; + private int text_x; + private int text_y; + private Bitmap lock_icon; + private Bitmap unlock_icon; + private Paint paint; + + public PuzzlesAdapter(Context c) + { + super(); + + gameState = theApp().state(); + context = c; + icon_size = (int)c.getResources().getDimension(R.dimen.puzzle_list_icon_size); + text_size = (int)c.getResources().getDimension(R.dimen.puzzle_list_number_size); + text_x = (int)c.getResources().getDimension(R.dimen.puzzle_list_number_x_coord); + text_y = (int)c.getResources().getDimension(R.dimen.puzzle_list_number_y_coord); + + // + // Load locked icon + // + Bitmap lock_icon_tmp = BitmapFactory.decodeResource( c.getResources(), R.drawable.lock ); + lock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888); + Canvas lock_canvas = new Canvas(lock_icon); + lock_canvas.drawBitmap(lock_icon_tmp, + new Rect(0,0,lock_icon_tmp.getWidth()-1,lock_icon_tmp.getHeight()-1), + new Rect(0,0, icon_size, icon_size), + null); + + // + // Load unlock icon + // + Bitmap unlock_icon_tmp = BitmapFactory.decodeResource( c.getResources(), R.drawable.unlock ); + unlock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888); + Canvas unlock_canvas = new Canvas(unlock_icon); + unlock_canvas.drawBitmap(unlock_icon_tmp, + new Rect(0,0,unlock_icon_tmp.getWidth()-1,unlock_icon_tmp.getHeight()-1), + new Rect(0,0,icon_size, icon_size), + null); + + paint = new Paint(); + } + + @Override + public int getCount() + { + return gameState.getPuzzleCount(); + } + + @Override + public Object getItem(int position) + { + return null; + } + + public int getPositionLevel(int position) + { + return position+1; + } + + @Override + public long getItemId(int position) + { + return getPositionLevel(position); + } + + // create a new ImageView for each item referenced by the Adapter + @Override + public View getView(int position, View convertView, ViewGroup parent) + { + ImageView imageView; + if (convertView == null) + { // if it's not recycled, initialize some attributes + imageView = new ImageView(context); + imageView.setLayoutParams(new GridView.LayoutParams(icon_size, icon_size)); + imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + } + else + imageView = (ImageView) convertView; + + imageView.setImageBitmap(getIcon(position)); + return imageView; + } + + private Bitmap getIcon(int position) + { + paint.setColor( Color.WHITE ); + paint.setTextSize( text_size ); + paint.setTextAlign(Paint.Align.RIGHT); + + int level = getPositionLevel(position); + Bitmap icon = ( gameState.isLocked(level) ) + ? lock_icon.copy(Bitmap.Config.ARGB_8888,true) + : unlock_icon.copy(Bitmap.Config.ARGB_8888,true); + + Canvas canvas = new Canvas(icon); + canvas.drawText( Integer.toString(level), text_x, text_y, paint); + return icon; + } +} + + +/** + * + */ +public class PuzzleListFragment extends Fragment +{ + private FragmentPuzzleListBinding binding; + private PuzzlesAdapter puzzleGridAdapter; + private State gameState; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + gameState = theApp().state(); + binding = FragmentPuzzleListBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + puzzleGridAdapter = new PuzzlesAdapter(getActivity()); + binding.puzzleGrid.setAdapter(puzzleGridAdapter); + + binding.puzzleGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View v, int position, long id) { + int level = puzzleGridAdapter.getPositionLevel(position); + if (!gameState.isLocked(level)){ + PuzzleListFragmentDirections.ActionPuzzleListFragmentToPuzzleBoardFragment action = + PuzzleListFragmentDirections.actionPuzzleListFragmentToPuzzleBoardFragment(); + action.setLevel(level); + NavHostFragment.findNavController(PuzzleListFragment.this) + .navigate(action); + } + } + }); + } + + @Override + public void onResume() + { + super.onResume(); + if ( binding != null && binding.puzzleGrid != null ) { + puzzleGridAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onDestroyView () { + super.onDestroyView(); + binding = null; + } +} diff --git a/app/src/main/java/org/vostan/banvor/WelcomeActivity.java b/app/src/main/java/org/vostan/banvor/WelcomeActivity.java new file mode 100644 index 0000000..10031d7 --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/WelcomeActivity.java @@ -0,0 +1,77 @@ +package org.vostan.banvor; + +import android.os.Bundle; + +import com.google.android.material.snackbar.Snackbar; + +import androidx.appcompat.app.AppCompatActivity; + +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import androidx.navigation.NavController; +import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; +import androidx.navigation.ui.NavigationUI; + +import org.vostan.banvor.databinding.ActivityWelcomeBinding; + +public class WelcomeActivity extends AppCompatActivity { + + private AppBarConfiguration appBarConfiguration; + private ActivityWelcomeBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityWelcomeBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + +// setSupportActionBar(binding.toolbar); + + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_welcome); + +// appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); +// NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); + +// binding.fab.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) +// .setAction("Action", null).show(); +// } +// }); + } + +// @Override +// public boolean onCreateOptionsMenu(Menu menu) { +// // Inflate the menu; this adds items to the action bar if it is present. +//// getMenuInflater().inflate(R.menu.menu_main, menu); +// return true; +// } +// +// @Override +// public boolean onOptionsItemSelected(MenuItem item) { +// // Handle action bar item clicks here. The action bar will +// // automatically handle clicks on the Home/Up button, so long +// // as you specify a parent activity in AndroidManifest.xml. +// int id = item.getItemId(); +// +// //noinspection SimplifiableIfStatement +// if (id == R.id.puzzle_grid) { +// return true; +// } +// +// return super.onOptionsItemSelected(item); +// } + + + @Override + public boolean onSupportNavigateUp() { + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_welcome); + return NavigationUI.navigateUp(navController, appBarConfiguration) + || super.onSupportNavigateUp(); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/vostan/banvor/WelcomeFragment.java b/app/src/main/java/org/vostan/banvor/WelcomeFragment.java new file mode 100644 index 0000000..53b4b67 --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/WelcomeFragment.java @@ -0,0 +1,68 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.vostan.banvor; + +import static org.vostan.banvor.App.theApp; + +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.navigation.fragment.NavHostFragment; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +//import android.widget.Button; +//import android.widget.TextView; +//import static org.vostan.banvor.App.theApp; + +import org.vostan.banvor.databinding.FragmentWelcomeBinding; +import org.vostan.banvor.game.State; + +/** + * + */ +public class WelcomeFragment extends Fragment +{ + private FragmentWelcomeBinding binding; + private State gameState; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + gameState = theApp().state(); + binding = FragmentWelcomeBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + binding.btnContinue.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + WelcomeFragmentDirections.ActionWelcomeFragmentToPuzzleBoardFragment action = + WelcomeFragmentDirections.actionWelcomeFragmentToPuzzleBoardFragment(); + action.setLevel(gameState.getCurrentLevel()); + NavHostFragment.findNavController(WelcomeFragment.this) + .navigate(action); + } + }); + binding.btnPuzzles.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavHostFragment.findNavController(WelcomeFragment.this) + .navigate(R.id.action_WelcomeFragment_to_PuzzleListFragment); + } + }); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} diff --git a/app/src/main/java/org/vostan/banvor/play/Animator.java b/app/src/main/java/org/vostan/banvor/board/Animator.java similarity index 97% rename from app/src/main/java/org/vostan/banvor/play/Animator.java rename to app/src/main/java/org/vostan/banvor/board/Animator.java index ef6cc71..f751e8a 100644 --- a/app/src/main/java/org/vostan/banvor/play/Animator.java +++ b/app/src/main/java/org/vostan/banvor/board/Animator.java @@ -2,7 +2,7 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.vostan.banvor.play; +package org.vostan.banvor.board; import androidx.core.view.ViewCompat; import java.util.LinkedList; @@ -13,6 +13,113 @@ import java.util.LinkedList; */ public class Animator implements Runnable { + public static abstract class Action + { + public int steps; + + public Action() + { + steps = 0; + } + + public abstract void intermediate( Animator ap, int step ); + public abstract void last( Animator ap ); + } + + protected static abstract class XYAction extends Action + { + int x; + int y; + + public XYAction( int _x, int _y ) + { + x = _x; + y = _y; + } + } + + public static class Move extends XYAction + { + public Move( int x, int y ) + { + super(x,y); + } + + public void intermediate( Animator ap, int step ) + {} + + public void last( Animator ap ) + { + ap.view.getPuzzle().walk(x,y); + ap.view.invalidate(); + } + } + + public static class Push extends XYAction + { + public Push( int x, int y ) + { + super(x,y); + } + + public void intermediate( Animator ap, int step ) + { + } + + public void last( Animator ap ) + { + ap.view.getPuzzle().push(x,y); + ap.view.invalidate(); + } + } + + public static class Select extends XYAction + { + public Select(int x, int y ) + { + super(x,y); + } + + public void intermediate( Animator ap, int step ) + { + } + + public void last( Animator ap ) + { + ap.view.getPuzzle().select(x,y); + ap.view.invalidate(); + } + } + + public static class Unselect extends Action + { + public Unselect() + {} + + public void intermediate( Animator ap, int step ) + {} + + public void last( Animator ap ) + { + ap.view.getPuzzle().unselect(); + ap.view.invalidate(); + } + } + + public static class NoMove extends XYAction + { + public NoMove( int x, int y ) + { + super(x,y); + } + + public void intermediate( Animator ap, int step ) + {} + + public void last( Animator ap ) + {} + } + protected PuzzleView view; protected LinkedList actions = new LinkedList(); protected boolean stop; @@ -98,111 +205,4 @@ public class Animator implements Runnable } } } - - public static abstract class Action - { - public int steps; - - public Action() - { - steps = 0; - } - - public abstract void intermediate( Animator ap, int step ); - public abstract void last( Animator ap ); - } - - protected static abstract class XYAction extends Action - { - int x; - int y; - - public XYAction( int _x, int _y ) - { - x = _x; - y = _y; - } - } - - public static class Move extends XYAction - { - public Move( int x, int y ) - { - super(x,y); - } - - public void intermediate( Animator ap, int step ) - {} - - public void last( Animator ap ) - { - ap.view.getPuzzle().walk(x,y); - ap.view.invalidate(); - } - } - - public static class Push extends XYAction - { - public Push( int x, int y ) - { - super(x,y); - } - - public void intermediate( Animator ap, int step ) - { - } - - public void last( Animator ap ) - { - ap.view.getPuzzle().push(x,y); - ap.view.invalidate(); - } - } - - public static class Select extends XYAction - { - public Select(int x, int y ) - { - super(x,y); - } - - public void intermediate( Animator ap, int step ) - { - } - - public void last( Animator ap ) - { - ap.view.getPuzzle().select(x,y); - ap.view.invalidate(); - } - } - - public static class Unselect extends Action - { - public Unselect() - {} - - public void intermediate( Animator ap, int step ) - {} - - public void last( Animator ap ) - { - ap.view.getPuzzle().unselect(); - ap.view.invalidate(); - } - } - - public static class NoMove extends XYAction - { - public NoMove( int x, int y ) - { - super(x,y); - } - - public void intermediate( Animator ap, int step ) - {} - - public void last( Animator ap ) - {} - } } diff --git a/app/src/main/java/org/vostan/banvor/play/PlayActivity.java b/app/src/main/java/org/vostan/banvor/board/PlayActivity.java similarity index 81% rename from app/src/main/java/org/vostan/banvor/play/PlayActivity.java rename to app/src/main/java/org/vostan/banvor/board/PlayActivity.java index 4ae14ec..d1180a9 100644 --- a/app/src/main/java/org/vostan/banvor/play/PlayActivity.java +++ b/app/src/main/java/org/vostan/banvor/board/PlayActivity.java @@ -1,4 +1,4 @@ -package org.vostan.banvor.play; +package org.vostan.banvor.board; import android.app.AlertDialog; import android.app.Dialog; @@ -6,6 +6,8 @@ import android.content.DialogInterface; import android.os.Bundle; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentActivity; + +import android.util.AttributeSet; import android.view.View; import android.view.Window; import android.view.animation.Animation; @@ -17,7 +19,7 @@ import org.vostan.banvor.App; import static org.vostan.banvor.App.theApp; import org.vostan.banvor.R; -import org.vostan.banvor.Puzzle; +import org.vostan.banvor.model.Puzzle; public class PlayActivity extends FragmentActivity implements PuzzleControl.PuzzleControlLister @@ -41,16 +43,17 @@ public class PlayActivity extends FragmentActivity // // Create and set up the puzzle_view. // - puzzle_view = new PuzzleControl( this ); +// puzzle_view = new PuzzleControl(this, new AttributeSet() { +// }); setContentView( puzzle_view ); puzzle_view.setPuzzleControlLister( this ); // // Create action bar. // FrameLayout rootLayout = (FrameLayout)findViewById(android.R.id.content); - View.inflate(this, R.layout.puzzle_view_title, rootLayout); - title_text = (TextView)findViewById(R.id.title_text); - title_view = findViewById(R.id.puzzle_view_title_layout); + View.inflate(this, R.layout.fragment_puzzle_board, rootLayout); + title_text = (TextView)findViewById(R.id.level_text); +// title_view = findViewById(R.id.puzzle_view_title_layout); // // Load the puzzle. // @@ -62,9 +65,9 @@ public class PlayActivity extends FragmentActivity // // Advance current level and achieved level. // - final int nextl = theApp().getCurrentLevel()+1; - theApp().advanceAchivedLevel(nextl); - theApp().setCurrentLevel(nextl); + final int nextl = theApp().state().getCurrentLevel()+1; +// theApp().state().(nextl); + theApp().state().setCurrentLevel(nextl); // // Bring a dialog for user to choose to continue or stop. // @@ -146,9 +149,9 @@ public class PlayActivity extends FragmentActivity // If current level is less than achived level the move to next // puzzle. // - if ( theApp().getCurrentLevel() > App.MIN_LEVEL ) + if ( theApp().state().getCurrentLevel() > App.MIN_LEVEL ) { - theApp().setCurrentLevel( theApp().getCurrentLevel()-1 ); + theApp().state().setCurrentLevel( theApp().state().getCurrentLevel()-1 ); loadCurrentPuzzle(); puzzle_view.invalidate(); } @@ -163,9 +166,9 @@ public class PlayActivity extends FragmentActivity // If current level is less than achived level the move to next // puzzle. // - if ( theApp().getCurrentLevel() < theApp().getAchivedLevel() ) + if ( theApp().state().getCurrentLevel() < theApp().state().getHighestSolvedLevel() ) { - theApp().setCurrentLevel( theApp().getCurrentLevel()+1 ); + theApp().state().setCurrentLevel( theApp().state().getCurrentLevel()+1 ); loadCurrentPuzzle(); puzzle_view.invalidate(); @@ -189,13 +192,13 @@ public class PlayActivity extends FragmentActivity private void loadCurrentPuzzle() { - puzzle = theApp().getCurrentPuzzle(); + puzzle = theApp().state().getCurrentPuzzle(); puzzle_view.setPuzzle(puzzle); updateTitle(); } public void updateTitle() { - String title = "Level " + new Integer(theApp().getCurrentLevel()).toString(); + String title = "Level " + new Integer(theApp().state().getCurrentLevel()).toString(); setTitle(title); } public void setTitle(CharSequence title) diff --git a/app/src/main/java/org/vostan/banvor/play/PuzzleControl.java b/app/src/main/java/org/vostan/banvor/board/PuzzleControl.java similarity index 93% rename from app/src/main/java/org/vostan/banvor/play/PuzzleControl.java rename to app/src/main/java/org/vostan/banvor/board/PuzzleControl.java index 137499c..889c262 100644 --- a/app/src/main/java/org/vostan/banvor/play/PuzzleControl.java +++ b/app/src/main/java/org/vostan/banvor/board/PuzzleControl.java @@ -2,14 +2,17 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.vostan.banvor.play; +package org.vostan.banvor.board; import android.content.Context; import android.graphics.Point; +import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; -import org.vostan.banvor.Puzzle; + +import org.vostan.banvor.game.PuzzleLogic; +import org.vostan.banvor.model.Puzzle; //import android.support.v4.view.GestureDetectorCompat; @@ -39,9 +42,9 @@ public class PuzzleControl extends PuzzleView public void onTouch(); } - public PuzzleControl(Context c) + public PuzzleControl(Context c, AttributeSet attributeSet) { - super(c); + super(c,attributeSet); logic = new PuzzleLogic(); animator = new Animator( this ); animator.setAnimationLister(this); diff --git a/app/src/main/java/org/vostan/banvor/play/PuzzleView.java b/app/src/main/java/org/vostan/banvor/board/PuzzleView.java similarity index 96% rename from app/src/main/java/org/vostan/banvor/play/PuzzleView.java rename to app/src/main/java/org/vostan/banvor/board/PuzzleView.java index 6a96e51..5e8ba3e 100644 --- a/app/src/main/java/org/vostan/banvor/play/PuzzleView.java +++ b/app/src/main/java/org/vostan/banvor/board/PuzzleView.java @@ -1,4 +1,4 @@ -package org.vostan.banvor.play; +package org.vostan.banvor.board; import android.content.Context; import android.graphics.Bitmap; @@ -10,11 +10,13 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import androidx.core.view.ViewCompat; + +import android.util.AttributeSet; import android.view.View; import static java.lang.Math.*; -import org.vostan.banvor.Puzzle; -import static org.vostan.banvor.Puzzle.*; +import org.vostan.banvor.model.Puzzle; +import static org.vostan.banvor.model.Puzzle.*; import org.vostan.banvor.R; /** @@ -38,9 +40,9 @@ public class PuzzleView extends View private Rect tile_src = new Rect(); private RectF tile_dest = new RectF(); - public PuzzleView(Context context) + public PuzzleView(Context context, AttributeSet attributeSet) { - super(context); + super(context, attributeSet); setFocusable(true); // @@ -53,24 +55,22 @@ public class PuzzleView extends View // a.recycle(); } - public void setPuzzle( Puzzle p ) - { + public void setPuzzle( Puzzle p ){ puzzle = p; board.set(0,0,puzzle.getColumnCount(),puzzle.getRowCount()); viewport.set(board); tile_size.set(0,0); calcTransforms(); initTiles(); + invalidate(); } - public Puzzle getPuzzle() - { + public Puzzle getPuzzle(){ return puzzle; } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) - { + protected void onSizeChanged(int w, int h, int oldw, int oldh){ screen.set(0, 0, w, h); tile_size.set(0,0); calcTransforms(); @@ -78,8 +78,7 @@ public class PuzzleView extends View } - public void scaleViewport( float focusX, float focusY, float scale ) - { + public void scaleViewport( float focusX, float focusY, float scale ){ float left = scale*(focusX - screen.left); float right = scale*(screen.right - focusX); float top = scale*(focusY - screen.top); @@ -91,14 +90,12 @@ public class PuzzleView extends View ViewCompat.postInvalidateOnAnimation(this); } - public void scaleViewportDone() - { + public void scaleViewportDone(){ //initTiles(); ViewCompat.postInvalidateOnAnimation(this); } - public void scrollViewport( float distanceX, float distanceY ) - { + public void scrollViewport( float distanceX, float distanceY ){ viewport.set( screen.left+distanceX, screen.top+distanceY, screen.right+distanceX, @@ -338,7 +335,7 @@ public class PuzzleView extends View } private Bitmap createWorkerTile() { - Bitmap tmp = BitmapFactory.decodeResource( getResources(), R.drawable.worker ); + Bitmap tmp = BitmapFactory.decodeResource( getResources(), R.drawable.worker); Bitmap bitmap = Bitmap.createBitmap(tile_size.x, tile_size.y, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(tmp, diff --git a/app/src/main/java/org/vostan/banvor/play/PuzzleLogic.java b/app/src/main/java/org/vostan/banvor/game/PuzzleLogic.java similarity index 99% rename from app/src/main/java/org/vostan/banvor/play/PuzzleLogic.java rename to app/src/main/java/org/vostan/banvor/game/PuzzleLogic.java index 29661d0..474d6dc 100644 --- a/app/src/main/java/org/vostan/banvor/play/PuzzleLogic.java +++ b/app/src/main/java/org/vostan/banvor/game/PuzzleLogic.java @@ -2,15 +2,16 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.vostan.banvor.play; +package org.vostan.banvor.game; import static java.lang.Math.*; import java.util.Arrays; -import org.vostan.banvor.Puzzle; + +import org.vostan.banvor.board.Animator; +import org.vostan.banvor.model.Puzzle; /** * - * @author vahagnk */ public class PuzzleLogic { diff --git a/app/src/main/java/org/vostan/banvor/game/State.java b/app/src/main/java/org/vostan/banvor/game/State.java new file mode 100644 index 0000000..3bd3802 --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/game/State.java @@ -0,0 +1,134 @@ +package org.vostan.banvor.game; + +import static org.vostan.banvor.App.theApp; + +import android.content.SharedPreferences; +import android.util.Log; + +import androidx.annotation.NonNull; + +import org.vostan.banvor.model.IPuzzleSource; +import org.vostan.banvor.model.Puzzle; + +public class State { + public static final String TAG = "Sokoban.Sate"; + public static final String CUR_LEVEL = "current_level"; + public static final String HIGH_LEVEL = "highest_unlocked_level"; + + protected IPuzzleSource mPuzzleSource; + protected int mCurrentLevel; + protected int mHighestUnlockedLevel; + public static final int MIN_LEVEL = 1; + protected int mMaxLevel; + + public State(@NonNull IPuzzleSource ps){ + mPuzzleSource = ps; + mCurrentLevel = 0; + mHighestUnlockedLevel = 0; + mMaxLevel = mPuzzleSource.getCount(); + } + + // + // These are to save the game state and restore it. + // + public void storeState(@NonNull SharedPreferences.Editor prefs){ + prefs.putInt(CUR_LEVEL, mCurrentLevel); + prefs.putInt(HIGH_LEVEL, mHighestUnlockedLevel); + prefs.apply(); + if ( !prefs.commit() ) { + Log.d(TAG, "prefs.edit().commit() failed."); + } + } + + public void loadState(@NonNull SharedPreferences prefs){ + mCurrentLevel = prefs.getInt(CUR_LEVEL, MIN_LEVEL); + mHighestUnlockedLevel = prefs.getInt(HIGH_LEVEL, MIN_LEVEL); + } + + // + // Provide amount of puzzles. + // + public final int getPuzzleCount() + { + return mPuzzleSource.getCount(); + } + + // + // Puzzles. + // + public Puzzle getPuzzle(int level ) + { + return mPuzzleSource.getPuzzle( level-1 ); + } + public Puzzle getCurrentPuzzle() + { + return getPuzzle( getCurrentLevel() ); + } + public Puzzle getPrevPuzzle() + { + if ( mCurrentLevel != MIN_LEVEL ) { + return getPuzzle(getCurrentLevel() - 1); + } + else { + return null; + } + } + public Puzzle getNextPuzzle() + { + if ( mCurrentLevel != mHighestUnlockedLevel) { + return getPuzzle(getCurrentLevel() + 1); + } + else { + return null; + } + } + + // + // Level Unlock logic + // + public Boolean isLocked(int level){ + return level > mHighestUnlockedLevel; + } + private void unlockLevel( int l ) + { + if ( l > mMaxLevel){ + l = mMaxLevel; + } + if ( l > mHighestUnlockedLevel) { + mHighestUnlockedLevel = l; + } + theApp().storeGameState(); + } + public void levelSolved(int l){ + unlockLevel(l+1); + } + + // + // Provide highest solved puzzle. + // + public final int getHighestSolvedLevel(){ + return mHighestUnlockedLevel; + } + // + // Provide last played puzzle. + // + public final int getCurrentLevel(){ + return mCurrentLevel; + } + // + // Set the current puzzle level. + // + public void setCurrentLevel( int l ) { + if ( l > mHighestUnlockedLevel){ + l = MIN_LEVEL; + } + else if ( l < MIN_LEVEL ) { + l = mHighestUnlockedLevel; + } + mCurrentLevel = l; + theApp().storeGameState(); + } + public void advanceCurrentLevel(){ + setCurrentLevel(mCurrentLevel+1); + } +} diff --git a/app/src/main/java/org/vostan/banvor/menu/MainActivity.java b/app/src/main/java/org/vostan/banvor/menu/MainActivity.java deleted file mode 100644 index 17e606c..0000000 --- a/app/src/main/java/org/vostan/banvor/menu/MainActivity.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.vostan.banvor.menu; - -import org.vostan.banvor.play.PlayActivity; - -import android.content.Intent; -import android.view.View; -import android.os.Bundle; -//import androidx.fragment.app.Fragment; -//support.v4.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; -import android.view.Window; - -import androidx.appcompat.app.AppCompatActivity; - -import org.vostan.banvor.R; -import static org.vostan.banvor.App.theApp; - -public class MainActivity extends AppCompatActivity -{ - protected final String TAG = "SokobanMenu"; - protected final String LEVEL= "org.dyndns.vahagn.sokoban.LEVEL"; - protected MainFragment mainFragment; - protected PuzzleListFragment puzzleListFragment; - protected float puzzleListXScroll; - protected float puzzleListXScrollMax; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) - { - requestWindowFeature(Window.FEATURE_NO_TITLE); - - super.onCreate(savedInstanceState); - setContentView(R.layout.main_activity); - - mainFragment = new MainFragment(); - puzzleListFragment = new PuzzleListFragment(); - puzzleListFragment.setOnPuzzleListAction(new PuzzleListFragment.OnPuzzleListAction() { - public boolean onPuzzleGridDown() { - return onPuzzleGridDown1(); - } - public boolean onPuzzleGridXScroll(float x) { - return onPuzzleGridXScroll1(x); - } - public void onPuzzleLevelClicked(int level) { - onPuzzleClicked1(level); - } - }); - puzzleListXScrollMax = getWindowManager().getDefaultDisplay().getWidth(); - - // - // Set initila fragment. - // - FragmentManager fragmentManager = getSupportFragmentManager(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.add(R.id.fragment_container, mainFragment); -// fragmentTransaction.add(R.id.fragment_container, puzzleListFragment); - fragmentTransaction.commit(); - } - - //@Override - public void onConfigurationChanged() - { - // super.onConfigurationChanged(); - // setContentView(R.layout-l.menu); - } - - public void onStartCurrentPuzzle(View v) - { - Intent intent = new Intent(this, PlayActivity.class); - startActivity( intent ); - } - - public void onPuzzleListShow(View v) - { - getSupportFragmentManager() - .beginTransaction() - .setCustomAnimations(R.animator.fragment_slide_left_enter, - R.animator.fragment_slide_left_exit) - .replace(R.id.fragment_container, puzzleListFragment) - .commit(); - } - - public boolean onPuzzleGridDown1() - { - puzzleListXScroll = 0; - return true; - } - - public boolean onPuzzleGridXScroll1( float x ) - { - puzzleListXScroll += x; - /* - getSupportFragmentManager() - .beginTransaction() - .setCustomAnimations(R.animator.fragment_slide_right_enter, - R.animator.fragment_slide_right_exit) - .commit(); - */ - if ( -puzzleListXScroll/puzzleListXScrollMax > 0.5 ) - { - getSupportFragmentManager() - .beginTransaction() - .setCustomAnimations(R.animator.fragment_slide_right_enter, - R.animator.fragment_slide_right_exit) - .replace(R.id.fragment_container, mainFragment) - .commit(); - } - return true; - } - - public void onPuzzleClicked1( int level ) - { - if ( level <= theApp().getAchivedLevel() ) - { - theApp().setCurrentLevel(level); - Intent intent = new Intent(this, PlayActivity.class); - startActivity( intent ); - } - } -} diff --git a/app/src/main/java/org/vostan/banvor/menu/MainFragment.java b/app/src/main/java/org/vostan/banvor/menu/MainFragment.java deleted file mode 100644 index ee821ce..0000000 --- a/app/src/main/java/org/vostan/banvor/menu/MainFragment.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.vostan.banvor.menu; - -import android.os.Bundle; -import androidx.fragment.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; -import static org.vostan.banvor.App.theApp; -import org.vostan.banvor.R; - -/** - * - * @author vahagnk - */ -public class MainFragment extends Fragment -{ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) - { - super.onCreate(icicle); - View v = inflater.inflate(R.layout.main_fragment, container, false); - if ( theApp().getAchivedLevel() == 1 ) - ((Button)v.findViewById(R.id.btn_start)).setText(R.string.btn_start_begin); - // - // Set Footer. - // - String str = getString(R.string.copyright) + "\n" - +getString(R.string.version_tag) + " " + getString(R.string.git_version); - ((TextView)v.findViewById(R.id.footer_txt)).setText(str); - - return v; - } -} diff --git a/app/src/main/java/org/vostan/banvor/menu/PuzzleListFragment.java b/app/src/main/java/org/vostan/banvor/menu/PuzzleListFragment.java deleted file mode 100644 index fd776e0..0000000 --- a/app/src/main/java/org/vostan/banvor/menu/PuzzleListFragment.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.vostan.banvor.menu; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Bundle; -import androidx.fragment.app.Fragment; -import android.util.TypedValue; -import android.view.GestureDetector; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.GridView; -import android.widget.ImageView; - -import org.vostan.banvor.R; - -import static org.vostan.banvor.App.theApp; - -/** - * - */ -public class PuzzleListFragment extends Fragment -{ - protected GridView puzzleGrid; - protected PuzzlesAdapter puzzleGridAdapter; - protected GestureDetector gridViewXScrollDetector; - protected OnPuzzleListAction actionListener; - - /* - * These are events which the fragments delegates to activity. - */ - public interface OnPuzzleListAction - { - public boolean onPuzzleGridDown(); - public boolean onPuzzleGridXScroll( float x ); - public void onPuzzleLevelClicked( int level ); - } - public void setOnPuzzleListAction( OnPuzzleListAction l ) - { - actionListener = l; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) - { - super.onCreate(icicle); - View v = inflater.inflate(R.layout.puzzle_list_fragment, container, false); - // - // Configure GridView. - // - puzzleGrid = (GridView)v.findViewById(R.id.puzzle_grid); - puzzleGridAdapter = new PuzzlesAdapter(getActivity()); - puzzleGrid.setAdapter( puzzleGridAdapter ); - puzzleGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View v, int position, long id) - { - onPuzzleClicked(v,(int)id); - } - }); - puzzleGrid.setOnTouchListener( new View.OnTouchListener() { - public boolean onTouch(View view, MotionEvent me) { - gridViewXScrollDetector.onTouchEvent( me ); - return false; - } - }); - gridViewXScrollDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() { - public boolean onDown(MotionEvent e) { - return (actionListener!=null) ? actionListener.onPuzzleGridDown() : false; - } - public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) { - return (actionListener!=null) ? actionListener.onPuzzleGridXScroll(dx) : false; - } - }); - - return v; - } - - @Override - public void onResume() - { - super.onResume(); - if ( puzzleGrid != null ) - puzzleGridAdapter.notifyDataSetChanged(); - } - - public void onPuzzleClicked(View v, int level ) - { - if (actionListener!=null) - actionListener.onPuzzleLevelClicked(level); - } - - public class PuzzlesAdapter extends BaseAdapter - { - private Context context; - private int icon_size; - private int text_x; - private int text_y; - private Bitmap lock_icon; - private Bitmap unlock_icon; - private Paint paint; - - public PuzzlesAdapter(Context c) - { - context = c; - icon_size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 10, getResources().getDisplayMetrics() ); - int text_size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 4, getResources().getDisplayMetrics() ); - text_x = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 9, getResources().getDisplayMetrics() ); - text_y = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 9, getResources().getDisplayMetrics() ); - - Bitmap lock_icon_tmp = BitmapFactory.decodeResource( getResources(), R.drawable.lock ); - lock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888); - Canvas lock_canvas = new Canvas(lock_icon); - lock_canvas.drawBitmap(lock_icon_tmp, - new Rect(0,0,lock_icon_tmp.getWidth()-1,lock_icon_tmp.getHeight()-1), - new Rect(0,0,icon_size, icon_size), - null); - - Bitmap unlock_icon_tmp = BitmapFactory.decodeResource( getResources(), R.drawable.unlock ); - unlock_icon = Bitmap.createBitmap(icon_size,icon_size,Bitmap.Config.ARGB_8888); - Canvas unlock_canvas = new Canvas(unlock_icon); - unlock_canvas.drawBitmap(unlock_icon_tmp, - new Rect(0,0,unlock_icon_tmp.getWidth()-1,unlock_icon_tmp.getHeight()-1), - new Rect(0,0,icon_size, icon_size), - null); - - paint = new Paint(); - paint.setColor( Color.WHITE ); - paint.setTextSize( text_size ); - paint.setTextAlign(Paint.Align.RIGHT); - } - - public int getCount() - { - return theApp().getPuzzleCount(); - } - - public Object getItem(int position) - { - return null; - } - - public long getItemId(int position) - { - return position+1; - } - - // create a new ImageView for each item referenced by the Adapter - public View getView(int position, View convertView, ViewGroup parent) - { - ImageView imageView; - if (convertView == null) - { // if it's not recycled, initialize some attributes - imageView = new ImageView(context); - imageView.setLayoutParams(new GridView.LayoutParams(icon_size, icon_size)); - imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - } - else - imageView = (ImageView) convertView; - - int id = (int)getItemId(position); - Bitmap icon = ( id <= theApp().getAchivedLevel() ) - ? unlock_icon.copy(Bitmap.Config.ARGB_8888,true) - : lock_icon.copy(Bitmap.Config.ARGB_8888,true); - Canvas canvas = new Canvas(icon); - canvas.drawText( Integer.toString(id), text_x, text_y, paint); - imageView.setImageBitmap(icon); - return imageView; - } - } - -} diff --git a/app/src/main/java/org/vostan/banvor/model/Coord.java b/app/src/main/java/org/vostan/banvor/model/Coord.java new file mode 100644 index 0000000..4d37602 --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/model/Coord.java @@ -0,0 +1,6 @@ +package org.vostan.banvor.model; + +public class Coord { + public int x; + public int y; +} diff --git a/app/src/main/java/org/vostan/banvor/model/IPuzzleSource.java b/app/src/main/java/org/vostan/banvor/model/IPuzzleSource.java new file mode 100644 index 0000000..3016e9a --- /dev/null +++ b/app/src/main/java/org/vostan/banvor/model/IPuzzleSource.java @@ -0,0 +1,6 @@ +package org.vostan.banvor.model; + +public interface IPuzzleSource { + public int getCount(); + public Puzzle getPuzzle( int i ); +} diff --git a/app/src/main/java/org/vostan/banvor/Puzzle.java b/app/src/main/java/org/vostan/banvor/model/Puzzle.java similarity index 99% rename from app/src/main/java/org/vostan/banvor/Puzzle.java rename to app/src/main/java/org/vostan/banvor/model/Puzzle.java index 1e6974a..a6df76a 100644 --- a/app/src/main/java/org/vostan/banvor/Puzzle.java +++ b/app/src/main/java/org/vostan/banvor/model/Puzzle.java @@ -1,4 +1,4 @@ -package org.vostan.banvor; +package org.vostan.banvor.model; //import java.lang.Exception; import java.io.*; diff --git a/app/src/main/java/org/vostan/banvor/PuzzleContainer.java b/app/src/main/java/org/vostan/banvor/model/PuzzleContainer.java similarity index 91% rename from app/src/main/java/org/vostan/banvor/PuzzleContainer.java rename to app/src/main/java/org/vostan/banvor/model/PuzzleContainer.java index 3a5792a..efe8e92 100644 --- a/app/src/main/java/org/vostan/banvor/PuzzleContainer.java +++ b/app/src/main/java/org/vostan/banvor/model/PuzzleContainer.java @@ -1,12 +1,13 @@ -package org.vostan.banvor; +package org.vostan.banvor.model; import java.io.InputStream; import java.io.IOException; import static org.vostan.banvor.App.theApp; +import org.vostan.banvor.model.Puzzle; import org.vostan.banvor.R; -public class PuzzleContainer +public class PuzzleContainer implements IPuzzleSource { protected int count; diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml new file mode 100644 index 0000000..c05fedf --- /dev/null +++ b/app/src/main/res/layout/activity_welcome.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_welcome.xml b/app/src/main/res/layout/content_welcome.xml new file mode 100644 index 0000000..d93f42d --- /dev/null +++ b/app/src/main/res/layout/content_welcome.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_puzzle_board.xml b/app/src/main/res/layout/fragment_puzzle_board.xml new file mode 100644 index 0000000..44e51c2 --- /dev/null +++ b/app/src/main/res/layout/fragment_puzzle_board.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_puzzle_list.xml b/app/src/main/res/layout/fragment_puzzle_list.xml new file mode 100644 index 0000000..6c2ed12 --- /dev/null +++ b/app/src/main/res/layout/fragment_puzzle_list.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_welcome.xml b/app/src/main/res/layout/fragment_welcome.xml new file mode 100644 index 0000000..1189602 --- /dev/null +++ b/app/src/main/res/layout/fragment_welcome.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + +