Skip to main content
GameDev.net gamedev.net
🔒 Locked

Interacting Classes

Started by K3NT Aug 13, 2006 at 6:46 AM 5 replies 500+ views
Original Post
K3NT
K3NT
I am reasonably new to C# and although I have known about the concepts of OOP for about a year, it has only been within the last 3 months that I have really started to understand it. Currently I am developing a car simulator, just the physics of the car (no graphics yet). I have setup separate classes for each item in the drivetrain; engine, clutch, transmission etc. I initially set these up as static classes with static methods. The reason I did this was that so methods in the Engine class could access properties of say, the Clutch class. However, it is probably likely that in the future I will want to create instances of these so that I can have more than one car. If I convert these classes to non-static classes, I cannot access properties from Clutch class from within the Engine class as I could before. This must be a common problem for programmers, so there must be a reasonably simple solution to it. Can any one help?
Zahlman
Zahlman
The usual means of communication, for one-to-one relationships, are:

- Have A include a B by value, i.e. actually contain a B as a component.
- Have A include a B by reference, i.e. every A "knows about" some B. In C++ you typically accomplish this by having a B* data member in A, and arranging for it to point to the appropriate B instance.
- Have A functions that involve a B, accept a B reference (in C++ you typically pass an actually reference, i.e. B& or const B&) as a parameter, and/or return a B reference.
- Indirect the process by having an A and B contained by some larger class, which components can query to access each other. In your case you might have a class Car { Engine e; Clutch c; etc. };, where each of those components communicates with the Car by one of the previous methods in order to access the other components.

Many-to-one and many-to-many relationships are similar; just use more references/values, stored in a homogeneous container.

Sorry I don't know the exact syntax for this stuff in C#. :\
OrangyTang
OrangyTang
Quote:
Original post by K3NT
I am reasonably new to C# and although I have known about the concepts of OOP for about a year, it has only been within the last 3 months that I have really started to understand it.

I have setup separate classes for each item in the drivetrain; engine, clutch, transmission etc. I initially set these up as static classes with static methods. The reason I did this was that so methods in the Engine class could access properties of say, the Clutch class.

Wow. Just, wow.

Seriously, you've got too much wrong here to correct with a simple reply. Until you can grasp the actual concept and purpose of a class you won't be able to even think about multiple classes interacting.

Go back to your books and start again. Think about why you would want to use classes in the first place, and why you'd like to be able to create multiple instances.
TheTroll
TheTroll
Lets go back to thinking about the way the car works and it will answer your question.

Does the engine have access to the clutch? Can the engine tell the clutch to engage? Disengage? Does the engine know how far the clutch is engages? Does the engine know how much wear the the clutch has?

Starting to see my point? You are giving the engine access to things that it has no need to know or understand.

So lets think about the clutch as a non-static class.

First we have some properties, those are class members. As a general rules class members should not be accessable by anything but the class itself.

float engage; // the percent the clutch is engaged
double clutch_plate_rpm; // well that is easy
double drive_side_rpm; // output of the clutch;
float clutch_wear; // just in case you want to track clutch wear;

Now we have actions, member functions if you will.

public void push_clutch_petal(float push) // the amount the clutch petal is pushed.
public void clutch_plate_speed_set(double) // changes the speed of the clutch plate
public double get_drive_side_rmp(void) // returns the speed of the output of the clutch
public float Get_wear(void)
private void Calculate_wear(float no_idea_here)

That is how to talk to your clutch class.

hope that makes sense.

theTroll
K3NT
K3NT
TheTroll: The engine rpm is determined by the load that is applied to it. So the engine does need to have access to some members of the clutch. For example, if the clutch was disengaged then the angular acceleration of the crankshaft would be determinted by the torque output of the engine divided by the moment of inertia.

OrangyTang: My understanding is that a class is designed to contain number of properties and methods. Each element in the drivechain has it's own methods and properties. For example, the engine has an rpm, torque curve lookup etc. Why do I wish to create multiple instances; more than one car!
OrangyTang
OrangyTang
Quote:
Original post by K3NT
OrangyTang: My understanding is that a class is designed to contain number of properties and methods. Each element in the drivechain has it's own methods and properties. For example, the engine has an rpm, torque curve lookup etc. Why do I wish to create multiple instances; more than one car!


I'm not asking you, I'm suggesting you go away and actually think about it yourself. If you've "known the concepts of OOP for about a year" yet you've still not grasped the basics then you're obviously not actually thinking about something.

OOP is not just writing your code inside separate classes.
Wyrframe
Wyrframe
What you need, K3NT, is members in each component that indicate what components it is connected to.

Try this idea (requires cleverness or multiple inheritance)...

You have two kinds of parts. Those that deliver torque, and those that receive torque. A third kind of part can receive and deliver torque.

The engine is solely a "Deliver" part. It generates a certain amount of torque each time unit, based on its throttle.

Clutches, transmissions, and axles are middle parts, which receive torque, modulate or transform it somehow (in the case of an axle, just transmit it), and then deliver the torque to the next piece(s) down the line.

Lastly, the wheels are solely "Receive" parts; they take the force inbound and apply it to the ground.

For complexity, you could add feedback force into the system (wheels encounter friction; they transmit this back through the axle and other parts, going upstream, and the engine reacts to feedback by lowering its output on the next time unit by the amount of feedback received in the last time unit).

Now to actually pull this off, you have to store references in each component to the parts which are upstream and downstream from it. So, imagine this setup...

// Car 1; a high-end sedan with automatic transmission.Component engA = new Engine(200); // Engine(horsepower)Component tranA = new AutoTransmission(); // Clutches and shifts based on input rev.Component axlA = new Axle(0.98); // Axle with 3% powerloss to friction (98% efficiency)Component whlA = new Wheels(); // Powered wheelbase.engA.setOutput(tranA);  tranA.setInput(engA);tranA.setOutput(axlA);  axlA.setInput(tranA);axlA.setOutput(whlA);   whlA.setInput(axlA);// Car 2; a 4-wheel drive truckComponent engB = new Engine(350); // Engine(horsepower)Component tranB = new StdTransmission(5); // Number of forward gearsComponent axlB = new HalfAxle(0.42, 0.42); // Split axle, delivering 42% power to each forkComponent whlFB = new Wheels(); // Front wheelbase.Component whlBB = new Wheels(); // Back wheelbase.engB.setOutput(tranB);  tranA.setInput(engB);tranB.setOutput(axlB);  axlA.setInput(tranB);axlB.setOutput(whlFB,0);   whlFB.setInput(axlB);axlB.setOutput(whlBB,1);   whlBB.setInput(axlB);


This isn't production code; this is just demonstrative of principle. And yeah; I really hate those "Object Orientation" tutorials that use kinds of or parts of cars for the metaphor; they just don't do the concept sufficient justice. You want to explain object orientation? Point someone at a Smalltalk implementation and say "good luck".

========= EDIT =========
Looking again, your requirements need a feedback system; it's how you push back on the engine to simulate the clutch and friction. So... your wheels apply feedback to their input. That input takes the feedback and applies its own additional feedback force, and sends it to its input. This repeats, going back, until you reach the engine, which uses the previous cycle's feedback to push back against its desired drive strength in this cycle.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.