Need some general classes advice - swift

I appreciate this is not Swift specific, but I am writing a small game in Swift thus I have tagged it with the relevant tag. I am new to the Swift language but picking it up quickly, and while not new to programming in general, do often question my approaches.
Here is my scenario:
I am writing a small 2D platform game with a player character and various obstacles. The player can have different textures but generally shares the same capabilities, such as jump and sprint. Likewise, the obstacles generally have different textures, but otherwise share the same capabilities.
Both the characters and obstacles also share common capabilities but not all, for example an obstacle can't jump. With this in mind, this is how I have written my classes...
class GameObject {
let node : SKSpriteNode!
}
Class GameObstacle: GameObject {
init() {
super.init()
}
func explode() {
// explode code
}
}
class GameCharacter: GameObject {
init() {
super.init()
}
func jump() {
// jump code
}
}
class GameCharacter_Sheep : GameCharacter {
init() {
super.init()
self.node = SKSpriteNode(namedFile: "sheep")
}
}
My logic behind this approach is that all of the common object functionality is included in the GameObject class, all of the common character functionality (such as jump) is included in the character class and the unique stuff, down at the class level.
One question I have, am I correct to initialize my node (defined in my GameObject class) in my GameCharacter_Sheep class? My rationale is that because the texture, and thus physics body will differ from character to character, that is the correct place to do the implementation?
Again, I appreciate that this may be basic OOP and not really Swift specific but I'm just looking for some guidance.
Many Thanks,
Jon

If all your game objects are going to have an instance of SKSpriteNode which is passed data from a named file, you can move it's creation into the base class, and just have the file named passed into the call to super.init().
More generally, inheritance isn't the only option for sharing functionality between different game objects. Don't forget about composition, which is often preferred when defining game objects to avoid deep, inflexible inheritance hierarchies which sometimes cannot model the desired behaviour. There are a whole bunch of ways to approach all the way through to a full blown game object component based system.

Related

Unity - Game modes as state machine?

I am making a quiz game in Unity and I've come across architectural problem.
I want the game to have few game modes, like standard, faster answer - more points, etc. Each of which will behave in its own specific way but some things will be very similar like answering questions, starting timer, etc.
Currently its structured based on this. There is a QuizSystem that holds reference to QuestionDatabase, UIReferences(buttons,score text, etc) and GameSettings (questions per game/per mode etc).
To start the game you need to call QuizSystem.Start() and it starts its current GameMode which derives from abstract StateMachine and is a monobehaviour (dont know if neccesary). I also have abstract State class from which different game states will derive from. It has a constructor with (GameMode owner) as paramenter and 3 functions: Start(), Tick(), End().
So, this way I can have Standard game mode which will instatiate lets say StandardPreparationState, which on end will call StandardAnswerState which will start the timer and wait for user input and again call StandardPreparationState. Cycle will repeat until questions per mode amount is reached and then delegate next action to QuizSystem.
The advantage of this approach is that every mode can behave in its own way like add additional steps in between but it kinda limits reusability. What I mean by that is if some OtherMode would have the same preparation functionality but different action afterwards, it wouldn't work beacause
StandardPreparationState would transition to StandardAnswerState.
I could add another parameter such as (GameMode owner, State transitionTo) to the State constructor but that somehow seems wrong I don't know why xD
What I want to know is how do you guys implement different game modes for your games? Do you make each mode as separate scene? Or maybe use States Machine pattern and have Manager class that takes care of starting/swaping modes?
I know that each game is different but are there maybe some common approaches for that?
Thanks in advance!
This question is quite open and opinion-based. However there are few "common" approaches, one of the most important is to make game "data-driven".
What? Why? How?
Imagine you are having space shooter, where you have your ship flying around and picking guns. Each time you add new gun, you will have to code its damage, kind of projectiles and how many of them you shoot, their color, in what pattern they spawn, speed, size, ...
Everytime you would want to add a new gun, you would need to enter the code and change it there, compile, ... Lot of work.
Instead people thought, "why don't we create simple class that holds all the parameters? We will make it editable from Unity, instatiate it in the project and we won't need to code that much."
This is when Unity brought Scriptable objects.
Scriptable objects
A ScriptableObject is a data container that you can use to save large amounts of data, independent of class instances. One of the main use cases for ScriptableObjects is to reduce your Project’s memory usage by avoiding copies of values.
The idea is to create scriptable object for your mode and set up multiple kinds of modifiers that will the mode use. Folder structure might look like:
> ScriptableObjects
| |--> Modes
| |-> NormalSO (instance)
| |-> HardWithLotOfExpSO (instance)
| |-> EasyWithLowerExpSO (instance)
> Script
|--> ScriptableObjects
|-> ModeSO
ScriptableObject is class that doesn't really have the logic inside, just creates "structure" for keeping data. Example of such class would be:
public class ModeSO : ScriptableObject
{
public string modeName;
public float scoreMultiplier;
public int numberOfEnemiesMaxAlive;
public int numberOfEnemiesTotal;
public Vector3[] spawnPoints;
}
In the Unity itself you would then create instance of such objects. And what about interaction with other classes? Well, they would just work as:
Game manager hold single instance of active mode
Class that would be handling score (e.g. player / scoreboard) or Enemy would ask GameManager what is current multiplier for score
WorldSpawner would ask GameManager how many enemies should he spawn, where, and when to spawn next ones
At the beginning of the game you would be able to select difficulty by its name
Example of one of the classes (Scoreboard):
public class ScoreBoard: MonoBehavior
{
GameManager manager;
private float totalScore;
OnEnemyDestroyed(float scoreForEnemy)
{
totalScore += scoreForEnemy * (manager?.activeMode?.modifier ?? 1);
}
}
And the best is, whenever you will change some data, you will just modify the existing instance in the Unity. No need to go into code. No need to recompile whole game.
I think having different scenes for each game mode, especially if the modes are very similar save for a few settings, is unnecessary. I'd have to see more of your design to know how your game logic is being handled (is it all managed in one GameManager script? Or are there multiple scripts in the scene that take values from this manager script to handle game mechanics?)
One way I've handled different game modes before is to use a public int value in the GameManager that represents the different modes (i.e 1 = easy, 2 = medium, 3 = hard). I would then use a switch statement in any scripts whose behavior/values depend on this mode and reference that public int to determine game settings.
Game Manager:
public class GameManager: MonoBehavior
{
public int gameMode = 0; //set to 1,2, or 3 by UI
[...] //rest of game manager code
}
Example Behavior Script:
public class EnemySpawn: MonoBehavior
{
public GameObject enemy;
GameManager gm;
private float spawnRate;
Start()
{
switch(gm.gameMode)
{
case 1:
spawnRate = 15f;
break;
case 2:
spawnRate = 10f;
break;
case 3:
spawnRate = 5f;
break;
default:
spawnRate = 10000f;
Debug.log("invalid mode");
break;
}
}
Awake()
{
InvokeRepeating("SpawnEnemy", spawnRate, 0f);
}
[...] //rest of EnemySpawn code, including a SpawnEnemy() function.
}
This example would reference the GameManager's gameMode int to determine what speed to spawn enemies at, assuming there is a SpawnEnemy() function somewhere down in the code. I can't verify if this example is syntactically correct, but it's just to show one way to handle game modes.

Why aren't Image and SpriteRenderer components inherited from one common base class?

I'm righting a script that loads some sprites and want to use it on both UI and in the game.
But there are two types of renderers for each and without any common base class, although they both have Sprite in common!
I want to use both Image and SpriteRenderer, so i want to write sth like this:
class SpriteLoader<T> where T: SomeRendererBaseClass {
T renderer;
void Load(){
renderer.sprite = GetSprite();
}
}
but to use "renderer.sprite" i have to specify T, for which i found no common base class.
If i'm gonna show game characters in UI i should load sprites on Image component, but in the game, i have to do the same behaviour but on SpriteRenderer, and as programmers we don't like duplicate codes.
Just because they both have a sprite doesn't mean anything.
You're going to just have to deal with the fact that the two classes aren't related to each other in the way that you'd like. This is no different than having a Player class that has a name property and trying to find a common parent class with GameObject ("it has a name too!")
The two classes have nothing else in common and should not inherit from some common ancestor (beyond whatever ancestor they do share).
At least they should have a common interface. I've seen that Unity API doesn't use interface at there best like .Net Does

best practice to show possible positions and put object on one of them Unity

I have a lot of Game Objects I need to Instantiate and put on scene on possible positions.
I have a list of rules where GameObject can be put by player (e.g. small box only at big box, sphere only on small box etc.)
I know I can put every rule into an "if", but I think it's not the most efficienty way. How should I keep a list of rules where can user put GameObjects? How my scripts should check and show possible positions? I will be thankful for any ideas how to start, to make it elegant and efficient.
There are many ways to do this.
What i would prefer is to keep everything organized and configurable per object (looking at the object oriënted programming structure).
I suggest defining per object where it can be placed. Here an example.
public yourClass
{
public GameObject ObjectToPlace;
public List<GameObject> ObjectToPlaceOnList;
public bool CanObjectBePlaced(GameObject targetObjectToPlaceUpon)
{
if (ObjectToPlaceOnList.Contains(targetObjectToPlaceUpon))
{
return true;
}
return false;
}
}
Your script may look different ofcourse, based on your current scripts.

Unreal Engine: Load static mesh from file path

Good day! I just started studying Unreal Engine 4.12 for a week now. For your discretion - I have little knowledge in C++ programming. (Although I code using PHP so I understanding OOP to some extent) - and, I'm just getting a little familiar with visual scripting (blueprint).
What I want to do is change the players weapon by loading a new static mesh, that static mesh would be from a file path. There are currently no blueprint node that does that, many articles/forums are suggesting to build my own blueprint node.
I've done some research and I have found this: Dynamic Load Object C++ - and it is very promising - but, I have no knowledge of implementing it. I tried opening MyProject.h and pasted it there, I'm not sure what to do next - does it become a function? Or a blueprint node?
I 'am open to other suggestions (or directions) on how to achieve what I wanted. If there are other methods to achieve this, please share and educate me. Thank you very much!
Sincerely,
Chris
That static load is only helper. You can call C++ function only if you mark header of that function by UFUNCTION(...) macro. See this link.
So you can create your function and in it's implementation, you can call that helper. For example:
// Helpers.h
static FORCEINLINE UTexture2D* GetTexture2DByName(const FName& name) {
return LoadObjFromPath<UTexture2D>(name);
}
UFUNCTION(BlueprintCallable, Category = TCF2Helpers)
static UTexture2D* GetTexture2DForBlock(UBuildableBlockInfo* blockInfo);
// Helpers.cpp
UTexture2D* UHelpers::GetTexture2DForBlock(UBuildableBlockInfo* blockInfo)
{
if (!blockInfo)
return nullptr;
const FString baseFolder = TEXT("Texture2D'/Game/Textures/HUD/%s");
if (blockInfo->IsEmptyHand)
return GetTexture2DByName(*FString::Printf(*baseFolder, TEXT("EmptyHand.EmptyHand'")));
// another lines of implementation
}
But you need to ask yourself, if you really need to have it hardcoded. You can specify something like
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widgets")
TSubclassOf<class UObjectWidget> wInGameMenu;
UPROPERTY(BlueprintReadOnly, Category = "Widgets")
UObjectWidget* InGameMenu;
where in override of function BeginPlay (this is due to creating widget on the fly) I have:
if (wInGameMenu)
{
InGameMenu = CreateWidget<UObjectWidget>(this, wInGameMenu);
}
UObjectWidget is successor of UUserWidget and my widgets (created in Editor) are reparented to have that widget as an inheretance base. I define which widget should be created on archetype of my object which holds it.
I'd implement it like that: (this may be changed if anyone tells me better way)
Create WeaponManager as ActorComponent
Create Weapon as SceneComponent (so you can attach it on skeleton socket)
Every Weapon will have it's own implementation based on same interface (maybe override of some functions defined in common ancestor?)
You can have multiple sub-childs (Energy weapon, shooting weapon etc) so you have correct inheritance and you avoid multiple implementation of same thing.
Every Weapon will define it's mesh and properties - again, if you hardcoded mesh path (it's OK since it is implementation), you can use code like that in the end of that list) or you can set that on archetype, if you'd like to code something in blueprint.
Then in WeaponManager you define all weapons (for example TArray<TSubclassOf<UWeapon>>
Every Weapon should define EWeaponType - enum af all weapons in game, so I can match defined weapons with it's type in TMap and then simply work with it on demand (show, hide, change weapon etc.) That type should be hardcoded to all implementations of weapons.
Load mesh in constructor:
//TerminalObject.h
UCLASS()
class TAUCETIF2_API ATerminalObject : public AStaticMeshActor
{
GENERATED_UCLASS_BODY()
};
// TerminalObject.cpp
ATerminalObject::ATerminalObject(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
static ConstructorHelpers::FObjectFinder<UStaticMesh> mesh(TEXT("StaticMesh'/Game/BuildingObjects/Meshes/terminal.terminal'"));
checkf(mesh.Succeeded(), TEXT("Failed to find mesh"));
auto mc = GetStaticMeshComponent();
checkf(mc, TEXT("Failed to find mesh component"));
mc->SetStaticMesh(mesh.Object);
}

Where should I put my functions?

I'm working on an app and I wrote a large part of an SKScene in a single class. It works great, but when I took a (java) course this past semester, it seems that accepted industry practice is to separate it into many classes.
More specifically, my (SpriteKit) app contains a cat and a mouse and after finishing said course, I decide that instead of containing all their info in the SKScene, I should separate some of it into multiple classes (a Player superclass with Cat and Mouse subclasses) each containing their relevant info (such as x and y position,) and functions (such as moveCat) with only Scene related functions and info in the Scene class.
The problem lies in the content of the functions.
Particularly one of the functions, pathBlocked(which checks if there are any barriers blocking the desired path of movement) uses a lot of info that wouldn't make sense to contain inside the Player object (such as all the info about the barriers on the board, and how much cheese was collected).
I can't just leave pathBlocked as a Scene function because there's a function that should belong to the cat (catAI) which uses pathBlocked to navigate. If it's a method of the scene, then it won't work. I'd need to instantiate a Scene object every time I wanted to call pathBlocked.
Should I just forget about making the Cat and Mouse Classes or should I fill the Player class with info that doesn't quite belong?
or is there a third option I'm not thinking of?
If you need a snippet of the code, I could include some of it.
Thanks!
Ok, so what you should do is
class Cat {
var sceneRef: GameScene? //or whatever scene is called
var xPos: CGFloat!
var yPos: CGFloat!
init(s: GameScene){//just example stuff
sceneRef = s
xPos = sceneRef!.childNodeWithName("cat").position.x
yPos = sceneRef!.childNodeWithName("cat").position.y //However, these variables will not stay up to date. If you need them current, you would have to do the same thing again, xPos = sceneRef!.childNode...etc.
}
func doStuff{
}
func createNewPath()
//create a new path
}
}
Then in the scene, you can do:
class GameScene: SKScene {
var cat: Cat?
override init(size: CGSize){
super.init(size: size)
cat = Cat(s: self)
func whatever() {
if (pathBlocked()){
cat!.createNewPath()
}
}
I think you will just have to unwrap it each time you use it, but XCode will tell you that.
^ credit for that should go to AMomchilov, I didn't know about weak references at all before this. It was a fun learning experience XD.
If you are looking to organize your code, another way you could do it is have an extension file for your scene, and throw all the low level function stuff in there, and keep all the high level stuff in the actual scene class. Make a new class, and call it SceneExtension or something:
import SpriteKit
//import whatever else you need
extension GameScene { //<- Or whatever your previous scene that you want to extend is called
func pathBlocked() {
//function code
}
//other functions
}
And just basically throw all the other functions that you don't want to look at and just take up space in the actual scene file. It acts like its in the same file, so you can call any of the functions in here, or use any variables from either class.