I am developing an iOS card game with Swift and have a question about good practice when it comes to designing the framework for games with SpriteKit and iOS. My basic structure is as follows:
class Card: SpriteKitNode {
cardValue: Int
func action() {}
}
struct Player {
playerName = "Joe"
playerPile = [Card]()
playerStack = [Card]()
}
struct Game {
// Create players and deals out the cards to each player pile.
}
Each player has a few piles of cards and they all come together in the game struct. Most of the cards in my game are independent cards. So, if player 1 plays a card, it has no impact on other players. However, some of the cards in my games have actions which are designed to impact other players decks depending on which card is played.
My question is, a card "action" sounds like it should be defined within the card class. It is a feature of the card itself that it has this ability. However, when I think about how I would implement this, I am not sure how it could impact at the game level to access other player piles. So what is the best practice when it comes to trying to define actions that have upstream impacts when the "Card" does not know how many players there are, which player it belongs to, and how to access another player's pile.
Example of an action I would like to implement: Player 1 can move the top card in any player stack to the top card in any other player's stack. So, player 1 could move the top card from player 2 to 1, 2 to 3, or any other combination based on the number of players on the board. I thought I could be able to do this by passing a lot of parameters to the action function action(moveFrom: Player1, moveTo: Player3), but thought I would come here to find out best practices.
There are also a few other actions which may have different inputs based on the card played. Should these be separate functions, or all built into one "Card Action" function?
// Possibly how this function might look.
func action(moveFrom: Player, moveTo: Player) {
let cardMoved = moveFrom.playerPile[0]
moveTo.playerPile.append(cardMoved)
}
Edit - Follow Up Question
After changing to a POP, I have a few further questions that are stumping me on how to implement.
My action function does not allow me to mutate the player's piles that have been selected. Error = "Cannot use mutating member on immutable value: 'fromPlayer' is a 'let' constant". Does this mean I would have to destroy and create and return new piles for each player each time it was called rather than just modifying the existing ones? This seems pretty inefficient is there a better way to do this?
I get another error when trying to call my action function. I have already checked that my card is indeed a "Slice Card", but I get the error "Value of type 'Card' has no member 'action'".
protocol ActionCard {
func action(fromPlayer: Player, toPlayer: Player)
}
class Card {
}
class SliceCard: Card, ActionCard {
func action(fromPlayer: Player, toPlayer: Player) {
let cardTaken = fromPlayer.stack.removeLast()
toPlayer.stack.append(cardTaken)
}
}
struct Player {
var stack = [Card]()
func playCard(card: Card, fromPlayer: Player, toPlayer: Player) {
if card is SliceCard {
card.action(fromPlayer: fromPlayer, toPlayer: toPlayer)
}
}
}
let player1 = Player()
let player2 = Player()
let cardSelected = SliceCard()
player1.playCard(card: cardSelected, fromPlayer: player1, toPlayer: player2)
Interesting question. I would suggest you a POP (Protocol Oriented Programming) approach.
The Player type
First of all I would suggest using a class for the Player type because you want to pass the same instance to other methods/actions and want these method to be able to mutate the original instance.
You could still use a struct + inout parameters but using a class feels more correct.
class Player {
let name: String
var pile: [Card] = []
var stack: [Card] = []
init(name: String) {
self.name = name
}
}
The ActionError enum
Just create an enum and add a case for every possible error an action can throw
enum ActionError: Error {
case playerHasNoCards
// add more errors here
}
The BaseCard class
You put here all the stuff common to any Card.
class BaseCard: SKSpriteNode {
let cardValue: Int
init(cardValue: Int) {
self.cardValue = cardValue
let texture = SKTexture(imageNamed: "card_image")
super.init(texture: texture, color: .clear, size: texture.size())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
The Card protocol
Here you required that in order to conform to Card a type must
be a class that inherits from BaseCard
and must have an action(...) method
Here's the code
protocol Card: BaseCard {
func action(currentPlayer: Player, destinatonPlayer: Player, allPlayers: [Player]) throws
}
Please note that the action method should receive all the parameters needed for any action you want to implement.
Your first card
Finally you can implement your first card
class CardToStoleACardFromAnotherPlayer: BaseCard, Card {
func action(currentPlayer: Player, destinatonPlayer: Player, allPlayers: [Player]) throws {
guard destinatonPlayer.pile.isEmpty == false else { throw ActionError.playerHasNoCards }
let card = destinatonPlayer.pile.removeFirst()
currentPlayer.pile.append(card)
}
}
Create as many classes as you want, you will write a different logic into each class.
Examples
class CardToStoleAllCardsFromAllPlayers: BaseCard, Card {
func action(currentPlayer: Player, destinatonPlayer: Player, allPlayers: [Player]) throws {
// ...
}
}
class CardToGiftACardToAnotherPlayer: BaseCard, Card {
func action(currentPlayer: Player, destinatonPlayer: Player, allPlayers: [Player]) throws {
// ...
}
}
Considerations
Now you when you pick a Card and you want to execute its action just call the action method passing all the parameters.
Depending on the type of the instance (CardToStoleACardFromAnotherPlayer, CardToStoleAllCardsFromAllPlayers, CardToGiftACardToAnotherPlayer, ...) contained into that variable a different logic will be executed.
Related
I know state is the enemy of Reactive programming but I'm dealing with it in my process of learning RxSwift.
My app is very simple, the first screen is a list and a search of books and the second a detail of the book in which you can add/remove a book to your shelf and mark it as read/unread.
To show the detail of the book I create a BookViewModel passing a BooksService to perform network operations and the current Book to show.
The problem is that I have to keep track of the changes in the book in order to change the UI: for example, after removing the book the button that previously says "Remove" now it has to say "Add".
I achieve this behavior using a Variable<Book> exposed to the observers as a Driver<Book>, but I'm messing a lot with it when the network operation returns and I have to update the value of the Variable<Book> in order to trigger the update of the UI.
This is the initializer of the view model:
init(book: Book, booksService: BooksService) {
self._book = Variable(book)
self.booksService = booksService
}
This is the observable I expose
var book: Driver<Book> {
return _book.asDriver()
}
And here it is my function to add/remove the book:
func set(toggleInShelfTrigger: Observable<Void>) {
toggleInShelfTrigger // An observable from a UIBarButtonItem tap
.map({ self._book.value }) // I have to map the variable's value to the actual book
.flatMap({ [booksService] book -> Observable<Book> in
return (book.isInShelf ?
booksService.delete(book: book) :
booksService.add(book: book))
}) // Here I have to know if the books is in the shelf or not in order to perform one operation or another.
.subscribe(onNext: { self._book.value = $0 }) // I have to update the variable's value in order to trigger the UI update
.disposed(by: disposeBag)
}
I am very unhappy with this code and the whole view model. It works but it is clunky, and essentially wrong because if the network operation fails the subscription will be disposed and my button will became unresponsive.
If I get rid of the Variable<Book> and return a Driver<Book> from the method set(toggleInShelfTrigger: Observable<Void>) I won't have this mess but I will not be able to know if I have to add or to remove the book.
So, what is the real world way to keep track of the state of an object in this kind of app? How can I achieve this by only using Rx operators?
EDIT
I've managed to clean that crappy code but I'm still trying to achieve state without Variable and using scan operator.
This is my new BookViewModel initializer:
init(book: Book, booksService: BooksService) {
self.bookVariable = Variable(book)
let addResult = addBook
.mapBookFrom(bookVariable)
.flatMapLatest({ booksService.add(book: $0) })
.updateBookVariable(bookVariable)
let removeResult = ... // Similar to addResult, changing service call
let markReadResult = ... // Similar to addResult, changing service call
let markUnreadResult = ... // Similar to addResult, changing service call
self.book = Observable.of(addResult, removeResult, markReadResult, markUnreadResult).merge()
.startWith(.success(book))
}
I made a couple of custom operators to help me manage the Variable<Book>, one to get the real Book:
private extension ObservableType where E == Void {
func mapBookFrom(_ variable: Variable<Book>) -> Observable<Book> {
return map({ _ in return variable.value })
}
}
And another to update the Variable after the service returns:
private extension ObservableType where E == BookResult<Book> {
func updateBookVariable(_ variable: Variable<Book>) -> Observable<BookResult<Book>> {
return self.do(onNext: { result in
if case let .success(book) = result {
variable.value = book
}
})
}
}
Now I have a very clean view model, but not "perfect".
I would place the responsibility of the observing changes to the model object (Book) with the View.
Also, Variable is deprecated, best to use PublishRelay instead.
Of course, it depends how far you want to engineer this architecture, but something not too far from your example would be:
class BookDetailViewController: UIViewController {
let viewModel = BookViewModel(book: Book, booksService: BooksService)
func loadView() {
view = BookDetailView(viewModel: viewModel)
}
// ...
}
class BookDetailViewModel {
let book: PublishRelay<Book>
func addBook() {
book
.flatMap(booksService.add)
.bind(to: book)
.subscribe()
}
// ...
}
class BookDetailView: UIView {
let button: UIButton
init(viewModel: BookDetailViewModel) {
viewModel.book
.asObservable()
.subscribe(onNext: { book [button] in
button.setText(book.isSaved ? "Remove" : "Add")
})
button.rx.tap
.map { _ in viewModel.book.isSaved }
.subscribe(onNext: {
$0 ? viewModel.removeBook() : viewModel.addBook()
})
}
}
You could also implement a func toggle() in the view model instead, and just forward the button tap to call that method. It might be more accurate, semantically, depending on your interpretation of business logic and the extent to which you want to gather all of it in the view model.
Also note the example code is missing dispose bags, but that's another topic.
ANSWERED! I posted an answer with code that I modified from Arbitur. Thanks to Phillip as well for the key advice that lead me to redirect my searches.
TLDR:
is there a way to run a function from a string? Like RunFunction("myfunction_" + number + "()"), or, is a way to hardcode like myfunction_\&number() ?
I'm Justin and this is my first post. I've worked hard the past 2 months to not ask a question, but I'm finally breaking bad. I'll try to be brief but I'm terribly wordy (and this long intro doesn't help). Appreciation in advance for your patience.
Basically, I'm making an engine that transforms simple words and phrases into Swift code; the goal of this is to have something to quickly make Text games, educational apps, and anything involving a non-linear set of questions / answers that change based on how you respond.
Now, I'm working on what I thought would be an easy part: storing the actual text for the Labels and Buttons (I'm working in Xcode / iOS atm). I decided to model it like film-makers / novelists do: a movie is composed of Scenes which are composed of Clips. You can also think of this as Chapters / Paragraphs
So (not actual code):
App = (Scene 1 -> Scene 2 -> Scene 3, etc)
Scene 1 = (Clip 1 -> Clip 2 -> Clip 3, etc)
Scene 2 = Clip 2 -> Clip 5 -> Clip 1, based on responses
....And so on.
The way I think (and program), I tend to avoid Classes as much as possible, outside of being strictly data or strictly function structures.
So, my first solution was to create a struct (or class) with nested functions:
struct SceneList {
//fScene calls, and passes the clip# from the button click
func fPlayClip(clipNUM: Int)
{
//Do logic stuff, then play the correct clip
}
//Called from button clicks on main screen; passes in clip#
func fScene1(play_clip clipNumber: Int){
//sub functions(S1)
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}
fPlayClip(clipNumber)
}
func fScene2(play_clip clipNumber: Int){
//sub functions(S2)
func fClip1(){ print("Yo, scene 2, clip 1")}
func fClip2(){ print ("Yo, scene 2, clip 2")}
fPlayClip(clipNumber)
}
}
Unfortunately, this design failed because there is no way for me to call sub-functions from fPlayClip(), so I took another approach:
//////////////////////////
/////SceneList.swift//////
//////////////////////////
struct Scene1{
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}}
struct Scene2{
func fClip1(){ print("Yo, scene 2, clip 1")}
func fClip2(){ print ("Yo, scene 2, clip 2")}}
//////////////////////////
////////Main.swift////////
//////////////////////////
// Implemention of the structs / clips.
// (playScene is called in button click method.)
func playScene(/*button prams go here*/){
// Switch(){ case desired: // Solve for X,
var oScenePlayer = SceneX() // where X is the desired scene
// Switch(){ case desired: // Solve for Z,
oScenePlayer.fClipZ() // where Z is the desired clip
}
Again, this failed because I couldn't use just one object, [oScenePlayer], because each struct was a different type.
I then went around for a while trying to figure out a way to destroy the object, then recreate it, but I couldn't do that. Then, I looked around for a way to reassign one object to another class type, but couldn't. Then, I peered into the extensions, protocols, generic types, etc, trying to figure out a way to extend / inherent to get this to work, but failed.
So now, my final two /working/ solutions, are to just create a new object on scene changes, and wait for ARC or whatever to destroy the old one; or, for me to go back to the first example, and simply embed [fPlayScene] into every function:
//SOLUTION 1:
struct SceneList {
func fScene1(play_clip clipNumber: Int){
//sub functions(S1)
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}
//Do logic stuff below, solving for Y
case desired:
fClipY()
}
}
//SOLUTION 2:
//////////////////////////
/////SceneList.swift//////
//////////////////////////
struct Scene1{
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}}
}
//And so on...
//////////////////////////
////////Main.swift////////
//////////////////////////
//////////////////////////
// Inside the globalish area:
let oScene1: Scene1,
oScene2: Scene2
//And so on...
var global_next_scene = 1
var global_next_clip = 1
/////////////////////////////////
// Inside the button call method:
func playScene(next_scene: Int, next_clip: Int){
switch(next_scene){ //Find the scene
case 1:
oScene1 = Scene1()
switch(next_clip){ //Play the clip
case 1:
oScene1.fClip1()
}
}
Basically, I feel that I'm using WAY too many switch statements, and in way too many places, (there could be hundreds of scenes and thousands of clips), when something as simple as a RunFunction("fClip" + next_clip + "()") would work, but I don't know of any 'execute a swift command from a string' functions :[, or something where I could hardcode like fClip\&next_clip\() which I think was possible in c++ 15 years ago when I last programmed anything
I came up with a few other crazy ideas to implement this, I even thought about OOP (shudder) embedded classes and having member variables hold instances of the subclasses, but with my current knowledge / resources I can't find a simpler way to do this than the last 2 snippets.
All of the structs, member functions, switch statements, etc, are going to be auto-generated via my engine--so it's not that I'm looking for a faster way to do this, it just seems like an inefficient / taxing way to do it.
Any guidance would be appreciated. Thanks much in advance, and I'm surprised it's taken me this long to need to ask a question here ^-^()
Peace and blessings
It seems to me that you're mixing what is naturally data into your code. That is, you're creating functions that know which element they're responsible for...and that's what leads to all the duplication you're wondering about.
Perhaps there are parts of the problem I don't understand, but why not have a structure such as:
class Clip {
func play() {
print("Playing \(self)")
}
}
class Scene {
var clips = [Clip]()
func play() {
print("Playing \(self)")
for aClip in clips {
aClip.play()
}
}
func playClip(number: Int) {
if number >= 0 && number < clips.count {
clips[number].play()
}
}
}
class SceneList {
var scenes = [Scene]()
func play() {
print("Playing \(self)")
for aScene in scenes {
aScene.play()
}
}
func playScene(number: Int) {
if number >= 0 && number < scenes.count {
scenes[number].play()
}
}
}
var list = SceneList()
for _ in 0..<2 {
var scene = Scene()
list.scenes.append(scene)
for _ in 0..<3 {
scene.clips.append(Clip())
}
}
list.play()
Add whatever other properties and logic you like but the main point is to turn those numbered functions into generic functions with data references.
Phillip's answer inspired me to look more into arrays and separating data from functions, and indeed what I was looking for was available closures--I didn't know that you could call a closure simply from stating (unwrapping) a variable :) What a neat language!
This works perfectly, and now I don't need any classes or structs ^-^() (all the better!!)
//initializer
var clips_for_scene = [
1: { print("initialized") }
]
//SceneList
var scenes = [
1: { clips_for_scene = [
1: { print("scene 1, clip 1") },
2: { print("s1, c2") }]},
2: { clips_for_scene = [
1: { print("scene 2, clip 1") },
2: { print("s2, c2") }]}]
func playClip(which_scene: Int, _ which_clip:Int){
scenes[which_scene]?()
clips_for_scene[which_clip]?()
}
playClip(1, 1)
playClip(1, 2)
playClip(2, 1)
playClip(2, 2)
//output:
//scene 1, clip 1
//s1, c2
//scene 2, clip 1
//s2, c2
Thanks to Arbitur as well, as their answer on a separate question:
https://stackoverflow.com/a/30286375/6593818
I have a view controller that contains instances (objects) of a few related classes that need to intercommunicate.
I can easily set these up by creating instances of the objects within the VC:
var house = House ()
var road = Road ()
var town = Town ()
But how do I get a method in the House object to 'speak'/send data to the Road object? In some languages I could invoke the parent object and target the other class and its methods that way:
func sendHouseData (num: Int) {
_parent.road.getHouseData (num)
}
Obviously the _parent keyword is not swift code so won't work.
The only way I can think of doing this is to create an instance of road inside the House object as a child object, thus exposing it directly in scope to the method code. Having a lot of external code in the VC to do all the heavy lifting is another idea that seems like bad practice and inelegant.
Any ideas?
Many thanks.
Kw
One way would be to use the Delegation pattern. Each class should declare a protocol with all the messages it can send, and the class that needs to listen to those messages should implement the protocol, register as the (or one of the) delegate(s) and respond accordingly.
Here's a good example how to implement Delegation Pattern.
And a sample implementation for your objects:
protocol HouseDelegate {
func readData(data:Int)
}
class House {
var delegate:HouseDelegate
var data:Int = 0
init(delegate:HouseDelegate) {
self.delegate = delegate
}
func sendData() {
self.delegate.readData(data)
}
}
class Road: HouseDelegate {
var data:Int = 0
func readData(data: Int) {
print("Read data \(data)")
self.data = data
}
}
var road = Road ()
var house = House (delegate: road)
house.sendData() //prints "Read data 0"
Best way to handle this is by using mediator pattern, if you need to establish communication between House, Road, Town you can set it in a way that they communicate to 'mediator' (parent object). In this case parent object can mediate and coordinate between the objects
Or, you can use NSNotificationCenter, post a notification from one object and listen to the notification in another object, but this is hard to track as soon as your app gets more complex.
Let's say the Word class is parent class of the House, Road, Town.
Here you can establish communication between Word, House and Town, and inter-communication between House and Town.
Be advised this is more pseudo code I'm writting it in browser but you'll get idea
class Word {
let house = House()
let town = Town()
init() {
// Here World will be notified when the house hasReceivedVisitor and the town hasBuiltRoad.
self.house.hasReceivedVisitor = { visitorName in
print("\(visitorName) has visited the house!")
// Communication between house and town ...
self.town.doSometingWithVisitor(visitorName)
}
self.town.hasBuiltRoad = { roadNumber in
print("A road \(roadNumber) has been built!")
// Communication between town and house ...
self.house.doSometingWithRoad(roadNumber)
}
}
}
class House {
var hasReceivedVisitor: ((vistorName: String) -> ())?
func createVisitor() {
let vistor = Visitor("Mike")
self.hasReceivedVisitor?(vistor.vistorName)
}
func doSometingWithRoad(roadNumber: Int) {
// .....
}
}
class Town {
var hasBuiltRoad: ((roadNumber: Int) -> ())?
func createRoad() {
let road = Road(66)
self.hasBuiltRoad?(road.roadNumber)
}
func doSometingWithVisitor(visitorName: String) {
// .....
}
}
The same thing above can be accomplished via delegation but I like blocks more.
Basically you have 3 options: Notifications (the worst), delegation or callbacks.
I am developing an app using swift. I create a subclass from SCNNode for this:
class Charge: SCNNode {
static var tagCounter = 0 //to give every charge a unique tag
static var charges = [Charge]() //to have a pointer that can access all charges
static var selectedCharge: Charge? //pointer to selected charge
override init() {
super.init()
super.geometry = Charge.carbonAtom()
Charge.tagCounter++
self.chargeTag = Charge.tagCounter
Charge.charges.append(self)
}
}
Then after initiating the class several times in ViewController, I want to access them by using Charge.charges. But for some unknown reason, only the last instance is available, and it occupies Charge.charges[0].
I tried to track the object movement by adding property in ViewController var test = [Charge]() and call test.append(charge) every time I initiate charge in ViewController. Then, when I want to access all the charges, Charge.charges loses most of its charges but test does not! Can anyone enlighten me on this? Or is it a bug in Xcode?
n.b. I use debugging tool to track this problem. It turns out that Charge.charges loses its first content as soon as the second initialization is finished, but the first content still exists right after the execution of Charge.charges.append(self)
edit: carbonAtom function
class func carbonAtom() -> SCNGeometry {
let carbonAtom = SCNSphere(radius: 0.8)
carbonAtom.firstMaterial!.diffuse.contents = UIColor.redColor()
carbonAtom.firstMaterial!.specular.contents = UIColor.whiteColor()
return carbonAtom
}
I have just tested, there is not any Xcode bug.
class Charge: NSObject {
static var tagCounter = 0 //to give every charge a unique tag
static var charges = [Charge]() //to have a pointer that can access all charges
override init() {
super.init()
// super.geometry = Charge.carbonAtom()
Charge.tagCounter++
// self.chargeTag = Charge.tagCounter
Charge.charges.append(self)
}
}
Create 3 Changes instance:
for var i = 0; i < 3; i++ {
_ = Charge()
}
print(Charge.charges.count)
The console prints 3.
Try to check your Charge.carbonAtom() static method. I doubt it clear value of the charges array.
OKAY GUYS I FOUND IT!
There are infos that I dont provide (I thought it was irrelevant) in Charge class:
override func removeFromParentNode() {
super.removeFromParentNode()
for var i = 0; i<Charge.charges.count; i++ {
let charge = Charge.charges[i]
if Charge.selectedCharge != nil {
if charge == Charge.selectedCharge! {
Charge.charges.removeAtIndex(i)
}
}
break
}
}
and in ViewController
#IBAction func addCharge(sender: AnyObject) {
let charge = Charge()
scene.rootNode.addChildNode(charge) //root of problem
Charge.selectedCharge = charge
print(Charge.charges.count)
}
what happen is, in the line scene.rootNode.addChildNode(charge), the method automatically calls removeFromParentNode() from charge. Because of that, the charge pointed by Charge.selectedCharge will be removed from Charge.charges when the second charge is initialized.
I try to search for this info in Apple documentation but no avail. If only they document it more comprehensively :/
Thank you for the help guys :) the divide and conquer method I use to replicate the bug really helps narrowing down the problem
I am working in between three files: Menu.swift, Main.swift and Game.swift.
In my Main.swift, I define the variable swipeNumber:
class Main {
var swipeNumber: Int = 0 {
didSet{
println("The new swipe number is \(swipeNumber)")
}
}
}
N.B. It is in a class so that I can reference the variable from other files, and the didSet property observer will function.
As you can see, its initial value (I think) is 0.
Then, in my Menu.swift, I retrieve the information from the Main class in Main.swift.
let main = Main()
I then have three buttons, which will, on touch, change the swipeNumber variable, based on which button was pressed.
class Menu: UIViewController {
#IBAction func pressedThreeSwipes(sender: AnyObject) {
main.swipeNumber = 3
}
#IBAction func pressedFiveSwipes(sender: AnyObject) {
main.swipeNumber = 5
}
#IBAction func pressedTenSwipes(sender: AnyObject) {
main.swipeNumber = 10
}
//...
}
When I run the program, my property observer appears to work, printing messages such as:
The new swipe number is 3
The new swipe number is 5
The new swipe number is 10
And in the Game class, (for troubleshooting purposes), I have another property observer, checking the integer of the variable swipeNumber when the button test is pressed:
class Game: UIView {
let main = Main()
func didMoveToView(view: UIView) {
/* Setup your scene here */
println("now")
println("\(main.swipeNumber)"
//Nothing happens here, suggesting that didMoveToView is failing
}
#IBAction func test(sender: AnyObject) {
println("\(main.swipeNumber)")
}
}
My func test prints a number, but sadly that number is not 3, 5, or 10. It's 0.
I think that the problem lies with my variable in Main.swift, however I am not sure.
Any advice or 'fixes', whether quick or lengthy, would be very greatly appreciated.
Thank you,
Will
You have different instances of your class Main, and they each carry a different value for the same properties.
You should try the Singleton pattern (see e.g. here or here).
When you call Main(), you are creating a new object...emphasis on NEW. It has no knowledge of what you've done to other objects of the same type. If you want to use the same object in different places, you need to make it a parameter and pass it into methods rather than creating a different object.