Reputation: 942
I have a game which uses a ViewPager
to display many mines which the player can purchase.
I have created a User
Class in order to help me store all user's info in there.
One of these values is gold
, which is used to purchase mines.
Fact is, I don't know where to create the user (suspect on the MainActivity
) and how to access this new user's info from the MineFragment
, which is the code of each page in the ViewPager
.
Note: I don't want to pass a User object to a fragment or any other classes. I want to be able to make an instance of a single User and then be able to access all of this user's data from anywhere in my code, but in this case, I care about accessing them from the Fragment (Minefragment).
public class User {
private String mName;
private int mGold;
private int mExperience;
private int mExperienceLevel;
public User(String name){
mName = name;
mGold = 0;
mExperience = 0;
mExperienceLevel = 1;
}
// Getters & Setters
[...]
}
public class MineFragment extends Fragment {
// Store instance variables
[...]
private User mUser;
private Button mineUnlockButton;
private View overlay;
[...]
// Store instance variables based on arguments passed
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
// HARD CODED VALUES
mUser = new User("Leonardo");
mUser.setGold(2000);
}
// Inflate the view for the fragment based on layout XML
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(mLayout, container, false);
[...]
// Unlock Button
mineUnlockButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mUser.getGold() >= mUnlockCost) {
overlay.setVisibility(View.GONE); // Remove overlay and button
mineUnlockButton.setVisibility(View.GONE);
System.out.println("Gold: " + mUser.getGold() + " | Cost: " + mUnlockCost);
mUser.setGold(mUser.getGold() - mUnlockCost); // Update user's gold
System.out.println("Gold: " + mUser.getGold());
System.out.println("### Mine Purchased ###");
} else { // Not enough money
Toast.makeText(getContext(), "Not enough money to purchase", Toast.LENGTH_SHORT).show();
}
}
});
return view;
}
}
public class MainActivity extends AppCompatActivity {
FragmentPagerAdapter adapterViewPager;
ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.vpPager);
adapterViewPager = new MineAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapterViewPager);
}
}
Here's the project on GitHub, where you can find the MainActivity
, the User
class, the MineFragment
and some extra stuff if you need.
Upvotes: 0
Views: 674
Reputation: 45072
You need to use Singleton pattern to store your Data in one Single place.
What I got from your code is there are number of levels
in your game and each level
requires some minimum number of golds
to unlock them.
This is how it look like for test data with 200 gold:-
Model classes
Lets start with Level class -lavel have name and minimum gold threashold
public class LevelModel {
private String levelName;
private int unlockCost;
public String getLevelName() {
return levelName;
}
public int getUnlockCost() {
return unlockCost;
}
public LevelModel(String levelName, int unlockCost) {
this.levelName = levelName;
this.unlockCost = unlockCost;
}
}
Next will be User class all fields are self explanatory
public class User {
private String userName;
private int gold;
private int experience;
private int experienceLevel = 1;
/**
* @param userName
* @param gold
* @param experience
* @param experienceLevel
*/
public User(String userName, int gold, int experience, int experienceLevel) {
this.userName = userName;
this.gold = gold;
this.experience = experience;
this.experienceLevel = experienceLevel;
}
//Setters
public void setGold(int gold) {
this.gold = gold;
}
public void setExperience(int experience) {
this.experience = experience;
}
public void setExperienceLevel(int experienceLevel) {
this.experienceLevel = experienceLevel;
}
//Getters
public String getUserName() {
return userName;
}
public int getGold() {
return gold;
}
public int getExperience() {
return experience;
}
public int getExperienceLevel() {
return experienceLevel;
}
}
Now You need a single place to store, update and access your game data here this class will act as Singleton class to hold all your game data.
public class CenterRepository {
public void setCurrentUser(User currentUser) {
this.currentUser = currentUser;
}
private User currentUser;
ArrayList<LevelModel> listOfLavels = new ArrayList<>();
private static CenterRepository singletonInstance;
private CenterRepository() {
}
public static CenterRepository getSingletonInstance() {
if (null == singletonInstance) {
singletonInstance = new CenterRepository();
}
return singletonInstance;
}
public User getCurrentUser() {
return currentUser;
}
public ArrayList<LevelModel> getListOfLavels() {
return listOfLavels;
}
}
Now For the second Part how to access and update data from ViewPager
. I have enhanced your view pager to use view instead of fragment
MineAdapter Updated**
package com.fet.minebeta.ui;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.fet.minebeta.R;
import com.fet.minebeta.data.CenterRepository;
/**
* Created by FET on 08/09/2016.
* All rights reserved.
* Please contact @[email protected]
*/
public class MineAdapter extends PagerAdapter {
private Context mContext;
private LayoutInflater mLayoutInflater;
public MineAdapter(Context context) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
//Fill Data directly from Repository
return CenterRepository.getSingletonInstance().getListOfLavels().size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((FrameLayout) object);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final View itemView = mLayoutInflater.inflate(R.layout.carousal_page, container,
false);
switch (position) {
case 0:
itemView.setBackgroundResource(R.color.iron);
break;
case 1:
itemView.setBackgroundResource(R.color.coal);
break;
case 2:
itemView.setBackgroundResource(R.color.gold);
break;
}
//Mine Name
((TextView) itemView.findViewById(R.id.mineName)).setText(
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getmName());
//Mine Cost
((TextView) itemView.findViewById(R.id.mineCost)).setText("" +
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost());
//Mine Cost
((TextView) itemView.findViewById(R.id.mineDropRate)).setText("" +
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getDropRate());
//Mineral Name
((TextView) itemView.findViewById(R.id.mineMineral)).setText(
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getMineral().getName());
//Mineral Drop Rate
((TextView) itemView.findViewById(R.id.mineDropRate)).setText("" +
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getMineral().getValue());
// Unlock Button
itemView.findViewById(R.id.unlockButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (CenterRepository.getSingletonInstance().getCurrentUser().getGold() >=
CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()) {
//If User has more gold than cost to unlock hide lock image and buy it
CenterRepository.getSingletonInstance().getCurrentUser().setGold(
CenterRepository.getSingletonInstance().getCurrentUser().getGold()
- CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()); // Update user's gold
Toast.makeText(mContext,
"Reduced " + CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost() +
"\n Updated Gold " + CenterRepository.getSingletonInstance()
.getCurrentUser().getGold(), Toast.LENGTH_LONG).show();
} else {
// Not enough money
Toast.makeText(mContext, "Not enough money to purchase You need " +
(CenterRepository.getSingletonInstance().getListOfLavels().get(position).getUnlockCost()
- CenterRepository.getSingletonInstance().getCurrentUser().getGold()) + "More", Toast.LENGTH_SHORT).show();
}
}
});
container.addView(itemView);
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((FrameLayout) object);
}
}
One thing to note here carousal page have FrameLayout as rootlayout . if you plan to use any other update addview and remove view function accordingly
carousal_page.xml **updated you dont need separate layouts for each mineral
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/mineName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="COAL MINE"
android:textColor="@android:color/white"
android:textSize="25sp" />
<TextView
android:id="@+id/mineCost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:gravity="center"
android:text="1000"
android:textColor="@android:color/white"
android:textSize="50sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:paddingEnd="100dp"
android:paddingStart="100dp">
<TextView
android:id="@+id/mineMineral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignTop="@+id/mineDropRate"
android:text="COAL"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="25sp" />
<TextView
android:id="@+id/mineDropRate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="1"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="25sp" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/unlockButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Unlock" />
</RelativeLayout>
Model class is so loosely coupled that you can move it anywhere and it work just fine.
Activity Class with test Data Updated**
public class MainActivity extends AppCompatActivity {
PagerAdapter adapterViewPager;
ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add Test User from Activity
CenterRepository.getSingletonInstance().setCurrentUser(new User("FET", 200, 20, 10));
//Add Test Mines
CenterRepository.getSingletonInstance().getListOfLavels().add(new Mine("Iron", new Mineral("Iron Mineral", 1), 100, 2));
CenterRepository.getSingletonInstance().getListOfLavels().add(new Mine("Coal", new Mineral("Coal Mineral", 3), 200, 2));
CenterRepository.getSingletonInstance().getListOfLavels().add(new Mine("Gold", new Mineral("Gold Mineral", 2), 300, 2));
viewPager = (ViewPager) findViewById(R.id.vpPager);
viewPager.setAdapter(new MineAdapter(this));
Toast.makeText(getApplicationContext(), "Current Credits " + CenterRepository.getSingletonInstance()
.getCurrentUser().getGold(), Toast.LENGTH_LONG).show();
}
}
Upvotes: 2
Reputation: 113
In Your User Class Create A Static User Which Represents The Person Who is Playing The Game:
public class User {
public static User user = new User("Name Here");
private String mName;
private int mGold;
private int mExperience;
private int mExperienceLevel;
public User(String name){
mName = name;
mGold = 0;
mExperience = 0;
mExperienceLevel = 1;
}
// Getters & Setters
[...]
Access it with eg:
User.user.setGold(User.user.getGold() + 1);
Upvotes: 0
Reputation: 3476
It is not a bad start...
Since that will probably your only game initialization class, you need to make it singleton. One of the tricks in java is that if you change the class to enum and make a field called INSTANCE
to use in your MainActivity in your onCreate call
User.INSTANCE
That will initialize the game with the default values you have in the User class. Than you have access to all the methods of the User class and fields.
Upvotes: 1