We already know the different kinds of fish that will be available to the player within a specific level. We have extracted the value set into the ListOfFish
custom property of the world and stored it in the fish_list_
variable of the GameWorld
class. We now use this variable to create the various fishes in the CreateFish
function of GameWorld.cpp
:
void GameWorld::CreateFish() { Fish* fish = NULL; // get integer list from comma separated string vector<int> fish_type_vec = GameGlobals::GetIntListFromString(fish_list_); // this list consists of throwable fish num_throwable_fish_ = fish_type_vec.size(); // initially, we will only have throwable fish num_total_fish_ = num_throwable_fish_; for(int i = 0; i < num_throwable_fish_; ++i) { // create each type of fish EFishType fish_type = (EFishType)fish_type_vec[i]; switch(fish_type) { case E_FISH_SIMPLE: fish = Fish::create(this); break; case E_FISH_SHOOTING: fish = ShootingFish::create(this); break; case E_FISH_SPLITTING: fish = SplittingFish::create(this); break; case E_FISH_BOMBING: fish = BombingFish::create(this); break; case E_FISH_EXPLODING: fish = ExplodingFish::create(this); break; } if(fish != NULL) { // tell this fish it is throwable...default is false fish->SetIsThrowable(true); // initially no Update processing fish->setVisible(false); // add & save this fish addChild(fish, E_LAYER_FISH); fish_.push_back(fish); } fish = NULL; } }
We pass in the fish_list_
string into the GetIntListFromString
function of the GameGlobals
class to return a vector of int
. Since the list contained only the type of fish, we can now simply iterate over the vector and create specific types of fish.
When we defined the Fish
class, we discussed the use of the is_throwable_
member variable. We set the fish created within this function as "throwable" fish. Thus, only these fish will be able to ask GameWorld
to spawn the next fish when they have finished. We finally hide the fish before adding it to GameWorld
and vector fish_
.
Let's now look at the SpawnFish
function that is called every time a fish finishes and when the level is first created:
void GameWorld::SpawnFish(float dt) { // DON'T spawn if current_fish_ is out of bounds AND // if the current fish has not been fired if(current_fish_ >= 0 && current_fish_ < num_throwable_fish_ && fish_[current_fish_]->GetHasBeenFired() == false) { return; } // if there are no fish left, its game over! if(++ current_fish_ >= num_throwable_fish_) { GameOver(); return; } // spawn the current fish fish_[current_fish_]->Spawn(); // weld the fish to the catapult...else it might fall off b2WeldJointDef weld_jd; weld_jd.Initialize(fish_[current_fish_]->GetBody(), catapult_body_, fish_spawn_point_); weld_joint_ = (b2WeldJoint*)world_->CreateJoint(&weld_jd); // welding complete, catapult ready is_catapult_ready_ = true; }
The first condition ensures that the counter current_fish_
doesn't violate any bounds and also that the current fish has not been fired before proceeding further. This function must also check to see whether there are any fish left to spawn. If not, it means that the player has run out of fish and has failed the current level.
If all is well, we call the Spawn
function on the current fish. We then create a weld joint between the catapult_body_
and the fish's body. A weld joint simply constrains all relative motion between two bodies, thereby welding them together. We need this because when the player pulls the catapult back, we don't want the fish to fall off the catapult. Once the weld joint is created, we set the is_catapult_ready_
flag to true
. We can now write the remaining code to pull and release the catapult.
3.149.213.44