How to make a mechanic (With example!) - matan1905/GameMechanicManager GitHub Wiki
In this example we would learn how to make a mechanic! and we will make a Fishing mechanic along the way.
The way this page explains is:
- "Abstract" what to do
- code example with a simple Fishing mechanic
So first of all, write the possible lifecycle of your mechanic(it could save a lot of time and rewriting)
Fishing mechanic (Game developer perspective):
The player would start fishing. which will wait a random amount of time and then show a subtle indicator of a fish biting for a small window of time, if the player recognized it and pulled the fishing rod in time he will get a fish! otherwise if the player pull too early or too late he will get nothing!
To make a mechanic, first make sure you have Defined the following:
- Events and their arguments (and callback arguments, if any)
- Notifications and their arguments.
- Any possible setting and their defaults
Fishing mechanic events and notifications:
Events:
* start_fishing (no arguments,no callback arguments)
-When the player starts fishing
* cancel_fishing (no arguments,no callback arguments)
-When the player no longer desire fishing
* pull_rod (no arguments,callback arguments: boolean: caught a fish)
-The player has decided to pull the fishing rod to see if a fish has bite the bait
Notifications:
* fish_bite
-A fish has bitten the bait! tell the game to show their indication
Settings:
* fish_rod_window_time (10 seconds)
-The amount of time the player could still pull his fishing rod
* min_fishing_time (5 seconds)
-Minimum time the player needs to wait before any fish will start biting
* max_fishing_time (15 seconds)
-Maximum time the player needs to wait before any fish will start biting
after you have defined those you need to create your class , extend GameMechanic and implement required methods and write your logic.
Pay attention to the comments:
import com.opedea.GameMechanicManager;
import com.opedea.datasource.DataSource;
import com.opedea.mechanics.EventReceiver;
import com.opedea.mechanics.GameMechanic;
import com.opedea.mechanics.Settings;
public class FishingMechanicExample extends GameMechanic {
//These are the settings
private float windowTime;
private float minFishingTime;
private float maxFishingTime;
private boolean fishing=false;//Whether the player is fishing or not
private float timePassed=0;//the time passed in seconds
private boolean fishInBait=false;//whether a fish is eating the bait or not
private float fishTime;//a random value between min-max fishing time, used to tell when a fish is biting in a simple manner
//Using the event receivers as fields makes the code look cleaner in my opinion, Do as you please though!
EventReceiver startFishing = new EventReceiver() {
@Override
public void receive(Callback callback, Object... objects) {
fishing=true;
reset();
}
};
EventReceiver cancelFishing = new EventReceiver() {
@Override
public void receive(Callback callback, Object... objects) {
fishing=false;
reset();
}
};
EventReceiver pullRod = new EventReceiver() {
@Override
public void receive(Callback callback, Object... objects) {
callback.callback(fishing&&fishInBait);//returns if the player got himself a fish
}
};
//Reset everything and get ready to a new session
private void reset(){
fishInBait=false;
timePassed=0;
fishTime = (float) (Math.random()*maxFishingTime +minFishingTime);//a random value between min and max
}
//Overriding a none abstract method to keep track of the time.
//It is important to use gameMechanicManager.tick() in the main game loop for this to work!
@Override
public void tick(float delta) {
if(fishing) {//we don't want to do this while the player isn't fishing
timePassed += delta;//updating the time
if(!fishInBait){
if(timePassed-fishTime >= 0){
//it's biting time!
fishInBait=true;
getGameMechanicManager().sendNotification("fish_bite",null);//sends the notification
timePassed=0;
}
} else{
if(timePassed-windowTime>0){
//the player missed his chance! the fish escaped
reset();
}
}
}
}
@Override
protected void registerAllEvents(GameMechanicManager gmm) {
gmm.registerReceiver("start_fishing",startFishing);
gmm.registerReceiver("cancel_fishing",cancelFishing);
gmm.registerReceiver("pull_rod",pullRod);
}
@Override
protected void loadModels(DataSource dataSource) {
//Unused for this example as we don't need persistent data storage
}
@Override
protected void loadSettings(Settings settings) {
//Any setting that doesn't exist already will be created.
//All values are Strings, so we need to parse them first.
windowTime = Float.parseFloat(settings.getSetting("fish_rod_window_time","10"));
minFishingTime = Float.parseFloat(settings.getSetting("min_fishing_time","5"));
maxFishingTime = Float.parseFloat(settings.getSetting("max_fishing_time","15"));
}
@Override
public void reloadSettings(Settings settings) {
//this gets called everytime the developer desires to reload the settings, because we might need to reload all of the
//settings, might as well just forward it to the regular loadSettings(but remember you can force settings to only be reloaded after restart).
loadSettings(settings);
}
}
And there you have it!
in the page "how to implement a mechanic" we will go through how to implement this very mechanic in a game