Mouse tracking doesn't translate in fullscreen mode

You can pass it directly. A lot of it depends on how you structure your code, but if your Screen needs an instance of SpriteBatch to do work, give it that instance.

public Screen(Game game, SpriteBatch spriteBatch)
{
  ...
}

public PlayScreen(GameRoot game, SpriteBatch spriteBatch)
  : base(game, spriteBatch)
{
  ...
}

// In some GameRoot object which has a SpriteBatch named mySpriteBatch
var playScreen = new PlayScreen(gameInstance, mySpriteBatch);

Same deal, give the screen an instance of viewport that it can use to do work. Constructor injection is fairly common and an easy way to get dependencies into your objects. Keep an eye out though… sometimes you find your constructors growing. If you think it’s starting to get unreasonable you can explore other options, such as using a dependency container. You can also pass dependencies in as method parameters, typically if they’re single use and not used anywhere except that method. Kinda one of those things you do by feel… at least for me. Others may have better ideas :slight_smile:

The nice thing about dependency injection though is it makes your code much easier to unit test since you don’t need to worry about staging anything. Everything your object needs is given to it, it doesn’t have to get it from anywhere.

Not sure I am explaining the problem correctly.

Let’s suppose GameRoot has a definition for mySpriteBatch. and there is a custom class CustomSpriteBatch both in the game project.
Then:

public PlayScreen(GameRoot game, CustomSpriteBatch spriteBatch)
: base(game, spriteBatch)
{

}

Now:
In library project

public Screen(Game game, SpriteBatch spriteBatch)
{
  ...
}

game.mySpriteBatch raises an error because mySpriteBatch is not defined in library project.

Similarly,
spriteBatch cannot be downcast as CustomSpriteBatch because CustomSpriteBatch is only known in the game project.

One can use reflection by referencing the types in the game project but this gets messy and contravenes the rule of good coding.

So, how do you reference these properties in the library project?

If you’ve created another class to wrap SpriteBatch and provide other functionality, you’ll need to move that to either the same library that Screen is in, or a completely separate library that both of them can reference.

If you absolutely do need to have CustomSpriteBatch defined in the same library as PlayScreen, but still used by Screen, create an interface (ICustomSpriteBatch) that defines all the functionality you plan to use and let both reference that instead.

I have many examples of this and I find myself moving classes between projects to get the solution to compile.

It also seems that Microsoft get around this problem in .net. How do they do it?

I have a dozen controls, buttons, forms, textboxes, etc. based on Control. In my game I have a control tree. ScreenManager, Screens, Forms, Controls and sub-controls in the tree. Each parent calls a child to initialize, update and draw. But because of this problem the child does not have access to any properties of the parent unless it is in the same project and then can be downcast.

For example:

When the Form changes its state i.e. minimized, maximized then the controls need to know this. The properties of the Form are unavailable to the control unless they are in the same project. Consequently, I have put all the classes in a library which kind of defeats the purpose of a library.

I would like to make the library transportable. But, if I put specific game logic in the library that is no longer possible.

Is there a description of game design that shows how this can be accomplished?

Are you aware that I live in Calgary?

I would definitely suggest you look into and become more experienced with using interfaces in your code. This will definitely help you solve the issue you’re running into right now. Your children, defined in Project A, should be able to interact with an interface that you implement in project B.

Let me try to create an example using what you have described so far…

Lets say you have defined Button, which inherits from Control, in one project…

public class Control { }
public class Button : Control { }

Then in another project, you’ve defined Form which stores a list of Controls. Then, in your game Initialize, you add a Button to it…

public class Form
{
  public event EventHandler<EventArgs> FormResized;
  public List<Control> Controls { get; private set; } = new List<Control>();

  public void TriggerFormResized()
  {
    if (this.FormResized != null)
      this.FormResized(this, new EventArgs());
  }
}

public class MyGame : Game
{
  private Form _form = new Form();
  public Initialize()
  {
    _form.Controls.Add(new Button());
    _form.TriggerResize();
  }
}

If I’m reading you correctly, this is an example of where you’re at now. We’ve created a form that can trigger some kind of resize event, but Button can’t know about it because Form is defined in another project which cannot be referenced since the Form project already references the Button project.

This is where you can use an interface to define what is available on a Form. You’re effectively creating a contract where you’re saying “Hey, anybody who implements this interface… I don’t really care what other things you do, but you will at least provide these things.”

So, in the project that defines button (or some project below that in the hierarchy), we can define an interface for Form which says that it has an event on it, FormResized.

public interface IForm
{
  event EventHandler<EventArgs> FormResized;
}

Now, we can give an instance of IForm to Button, so it can do things.

public class Button : Control
{
  private IForm _parent;
  public Button(IForm parent)
  {
    _parent = parent ?? throw new ArgumentNullException();
    _parent.FormResized += (sender, e) => System.Diagnostics.Debug.WriteLine("Parent form has resized!");
  }
}

Now, we just have Form inherit from the interface…

public class Form : IForm
{
  // All the other stuff
}

Now, in the example game above, when we tell Form to trigger a resize event, button will know about it.

Obviously this is a contrived example, but hopefully you get what I mean :slight_smile:

No, that’s cool :slight_smile: How long have you lived here?

Out of curiosity, how did you know I do?

I did a search for Gary Texmo on the web

Maybe we can meet up and you can tutor me in person?!

lionelthomas46(at)gmail(dot)com

Cheers.

Ahhh you googled me, cool :wink: That’s a little out of date, though I would appreciate it if you’d take my personal information out of this forum post. Make others google me as well :stuck_out_tongue:

I don’t know that I’m comfortable taking on any kind of personal, one on one tutor role at this time, but I’m happy to try to help out here! Have a read on my previous post above and let me know what you think. Have you any experience working with interfaces?

That’s OK, I just thought we were getting off topic and there was a better way to communicate i.e via email.

I think I understand interfaces and have used them although not too extensively. I still don’t see how this solves the compiler reference problem. If Form is in the game project and control is in the library project, then how does one reference the properties of Form in Control in the library project whether through a derivation or an interface?

All good :slight_smile: The benefit of a thread like this is that others coming along looking for similar help can benefit from what we’ve written here.

Just linking to this for clarity. I wish there was a way to make it not preview it >.<

In this example, Control references the properties of IForm, not Form (though Form also provides that property). Form simply implements the interface, satisfying the contract that IForm has established. Control (or Button) doesn’t interact with Form directly, it does it via the interface. Because you define IForm in the library, Control (or Button) knows what it can do.

You should be able to set up exactly the scenario I described in that thread. Give it a try in projects separate from your actual game. I know for me, sometimes it really helps to isolate things in a different environment to remove the distractions. Then you can play in that isolated sandbox and not have to worry about anything except what you’re focusing on learning.

Thanks, I use interfaces in many places in my game in particular in the InputHandler(). The game doesn’t care how the handler implements the mouse actions like LeftButtonPressed in just uses the function. So if I change the way the handler works the rest of the I/O works just fine as long as the contract is abided by.

The interface works well provided no custom classes that are defined in the game project are passed in the interface. So my game class GameRoot cannot be passed in the interface because it is not known in the Library project. However the XNA Game class can because it is known in both the game and library projects.

So, I still don’t see how to get around this reference problem.

It can if the interface is defined in the library project.

Bear in mind that you don’t need to create an interface for the entire GameRoot object, nor does it need to be a single interface. Your object in the library project wants to either do something with, or know something about, your GameRoot project. You can utilize the Interface Segregation Principle in SOLID (The I) to accomplish your goal here.

Your library class wants to do something with that GameRoot object. Whatever that something is, put it on your interface and then, in your game project, have GameRoot satisfy that interface.

I think you’re almost there, just remember that the interfaces that describe the objects that your library project controls need to interact with are defined in the actual library project. Your game project classes that are given to the library object classes need to implement those interfaces.

This just sounds like a workaround.

Many years ago I developed systems using what is now called SOLID principles without object-oriented languages. Now supposedly, C# and .net offers the discipline to make reliable software.
But what I find is that C# is very difficult to work with. If one is very conversant with C# and .net classes then possibly one can design a system that does not require an enormous number of changes. C# and .net do not allow you to design by building.

If you used the .net version 1 classes in the beginning you would have to roll your own to a great extent. Now version 2 arrives and duplicates some of your own classes that might be similar in functionality but the call signatures and interfaces are different. What does one choose to do?

In the time when .net had no collections we wrote our own based on an array. Now we have a plethora of Collections to choose from. Just try and upgrade that code.

As I build my game I find that there is much I didn’t know at the beginning. I started using XNA 2.0 and tried to evolve my game while Microsoft evolved their platform. I had several games that would run on an Xbox and Windows. But then found that I couldn’t run these on the web and had to use Silverlight. Anyway, the woes continued until I was doing nothing but trying to understand the different technologies. Each one pointing out that I should have done things differently in the first place.

Well enough soapboxing. Is there a SOLID game design template? A template that handles all the elements. I have followed the Microsoft XNA Game Studio 3.0 unleashed by Chad Carter. I have tried to convert all the examples to Monogame but am not there yet. But, I think there is a better way to do some of the things.

C# and .net are not very forgiving. If you don’t do it right in the first place you get overwhelmed with changes and it gets worse when you find a class you might like to use then you have to make lots of changes.

Not sure what you do???

It’s not a workaround… but I don’t really know what else to tell you. Your object needs to interact with a thing, you need to define what kinds of things that thing can do. I think you’re very close here but it might be a good idea to sleep on it.

I’m sorry I should have said refactoring not workaround. I’m familiar with all these techniques.

What I am driving at is how to make the decisions as to what goes into an abstract class or interface.

It seems that rather than being a decision on SOLID principles it is predicated by how the compiler project system works.

You have given me some good ideas and I will try to apply them.

Thanks.

I see. Well, my approach of late has tended to be, “Do I need this?” If the answer is yes, then I add it. If the answer is no, then I don’t… and when that changes, I add it then.

As an example, here is my current interface for a wrapper of MediaPlayer (plays music in MonoGame/XNA). There’s a lot of functionality in MediaPlayer, but I’ve only created the things I need. Later on, if I need something like, say, functionality to manage playing a collection of songs, I’ll just extend my interface and implement that functionality on my wrapper. Since I don’t need it right now though, I don’t bother.

using ArbitraryPixel.Common.Audio.Factory;
using System;

namespace ArbitraryPixel.Common.Audio
{
    /// <summary>
    /// Represents an object that will play an ISong object.
    /// </summary>
    public interface ISongPlayer
    {
        /// <summary>
        /// A factory that can create ISong objects.
        /// </summary>
        ISongFactory Factory { get; }

        /// <summary>
        /// Whether or not the currently playing song should repeat.
        /// </summary>
        bool IsRepeating { get; set; }

        /// <summary>
        /// Whether or not song playback is muted.
        /// </summary>
        bool IsMuted { get; set; }

        /// <summary>
        /// The volume, between 0 and 1, to play the song at.
        /// </summary>
        float Volume { get; set; }

        /// <summary>
        /// The current position that song playback is at.
        /// </summary>
        TimeSpan PlayPosition { get; }

        /// <summary>
        /// Play the supplied song.
        /// </summary>
        /// <param name="song">The song to play.</param>
        void Play(ISong song);

        /// <summary>
        /// Play the supplied song at, starting at the supplied position.
        /// </summary>
        /// <param name="song">The song to play.</param>
        /// <param name="startPosition">The position to start playback at.</param>
        void Play(ISong song, TimeSpan startPosition);

        /// <summary>
        /// Stop any currently playing song.
        /// </summary>
        void Stop();
    }
}

Here is the implementation…

using ArbitraryPixel.Common.Audio.Factory;
using Microsoft.Xna.Framework.Media;
using System;

#pragma warning disable 1591

namespace ArbitraryPixel.Common.Audio.MonoGame
{
    public class MonoGameSongPlayer : ISongPlayer
    {
        public MonoGameSongPlayer(ISongFactory factory)
        {
            this.Factory = factory ?? throw new ArgumentNullException();
        }

        #region ISongManager Implementation
        public ISongFactory Factory { get; private set; }

        public bool IsRepeating
        {
            get { return MediaPlayer.IsRepeating; }
            set { MediaPlayer.IsRepeating = value; }
        }

        public bool IsMuted
        {
            get { return MediaPlayer.IsMuted; }
            set { MediaPlayer.IsMuted = value; }
        }

        public float Volume
        {
            get { return MediaPlayer.Volume; }
            set { MediaPlayer.Volume = value; }
        }

        public TimeSpan PlayPosition
        {
            get { return MediaPlayer.PlayPosition; }
        }

        public void Play(ISong song)
        {
            MediaPlayer.Play(song.GetWrappedObject<Song>());
        }

        public void Play(ISong song, TimeSpan startPosition)
        {
            MediaPlayer.Play(song.GetWrappedObject<Song>(), startPosition);
        }

        public void Stop()
        {
            MediaPlayer.Stop();
        }
        #endregion
    }
}

Yes I have something similar for audio in my game. I had put it aside because Monogame windows version did not work. It now does so I can implement my audio.

It seems to me that when you want to add some function you still need to make changes in 3 places. the class where the songs are used, the interface ISongPlayer and MonoGameSongPlayer. I suppose having the interface groups the functionality in one place. I don’t see how it reduces the refactoring. To replace MediaPlayer with another player will still require lots of changes and unless the call signatures are identical the interface will have to be reworked.

In my case, I have an interface in my InputHandler. At some point, I will have to rework the handler to properly accommodate touch input. I still see that this will require a lot of changes to my code in 3 places, the input routines. the interface and where I use the functions. It would be nice to find a portable input handler that is open source.

Cheers.

You’re correct in that I will have to make changes in three places if I want to add functionality. It’s very quick though since I’m adding functionality, not replacing it. Note that I’m not really following explicit Interface Segregation here. I feel that ISongPlayer is contained enough and am ok with making changes to that interface and anybody who implements it. This is a design choice I made.

Replacing MediaPlayer with another implementation is very easy. I can just write a new class that implements the interface and give that as an instance for ISongPlayer instead. I just have to ensure that my new implementation can work with the interface and object structure I’ve defined. I’ve used the names of things as they appear in MonoGame, but it’s really the method calls and properties I’m interested in. Even changing to another player, I would expect to have that functionality.

Interesting that you brought up input handling because I did exactly this. I have an interface, ISurfaceInputHandler. I then have two implementations of this… MouseSurfaceInputHandler and TouchScreenSurfaceInputHandler. I’m currently supporting Windows and Android and, in the entry point for each, I instantiate the appropriate dependency. Since my game interacts only with ISurfaceInputHandler, I don’t really need to worry about anything other than the things ISurfaceInputHandler lets me do.

I actually don’t mind sharing my input handler with you at all if you think it would help here.

Thanks, that would be great. I will have to add the translation code because I use monogame.extended’s boxing viewport adapter. Not a big change though.

Funny we have come full circle on this post.