using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D=Microsoft.DirectX.Direct3D;
namespace EIN.axiom
{
// The base class off all things represented by vertexes in my world
// Chiefly used as an include in tiles and characters
class Model
{
//1.Indivual Transform Matrix group
//2.Reference to a vertex buffer
}
class AxiomEnginge
{
// Might this be world
//Hold vertex buffers for the models,
//Create common and custom vertex models
//Help out with the rendering
// Texture stuff
// Methods for creating Tiles with a nod to textures
}
class Tile
{
private model TilePiece;
//all other tile realted stuff
}
}
About Game Development with particular focus on C#, Lua and procedural content generation.
Monday, June 30, 2003
I've sketched out this so far. I'll be filling in the details.
Read Chapter6 of my directx book. Proven enlightening. I think I should now be able to create my tile engine. Its thrown up a number of question. I'll discuss these questions as soon as I implement it which shouldn't be too long now.
End of the week: Scrolling multiloading RPG vertexual engine
So that should be fun fun cool.
End of the week: Scrolling multiloading RPG vertexual engine
So that should be fun fun cool.
Sunday, June 29, 2003
Not done too much today far too sunny. Though a good thread here. All sounds a little complicated though. I intend to have a try tommorrow.
Friday, June 27, 2003
Not really progressed too mych from this morning.
Read a article on 2D using DX8 but it was true 2D not vertex processed.
Mentioned a sprite interface, I cant find it in the DXutils and DX3D extra helper modules for C#
Bah.
I've been routing around function calls.
Got some cool web articles that I need to read through.
Top Priorites:
Another few chapters of my 3D book! (Done by tommorrow)
Tile a set of polygons across my window, from higher order functions
Read a article on 2D using DX8 but it was true 2D not vertex processed.
Mentioned a sprite interface, I cant find it in the DXutils and DX3D extra helper modules for C#
Bah.
I've been routing around function calls.
Got some cool web articles that I need to read through.
Top Priorites:
Another few chapters of my 3D book! (Done by tommorrow)
Tile a set of polygons across my window, from higher order functions
Oh I also have a full screen mode working now as well. Certain parts of the device property must also be set.
Yesterday I read two chapters in Programming Windows in C#.
I'm getting a better grasp of delegates though I need to get a program where I fiddle with the code myself going.
The chapters are massive though :(
It's not such a bad book on the whole so far.
Yesterday I read two chapters in Programming Windows in C#.
I'm getting a better grasp of delegates though I need to get a program where I fiddle with the code myself going.
The chapters are massive though :(
It's not such a bad book on the whole so far.
Ah-ha using the same vertex buffer I've now drawn two matrixes in different places in my world.
I'm not sure I've done it the correct way but it seem to work.
Call DrawPrimatives from the device and drawn my quad.
device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
The first 0 being the vertex to start with, the second 2 is the number of triangles. In this case two to make a square.
There seem to be calls to draw rects and such but this way is good for now. I can, if I so wish, have odd shapes in my world.
So that sets the first one down at what is 0,0 dead center of where I am looking.
This seems to be where 'I' place no matter what.
Therefore I need to move myself, place and move myself back.
There are the three Transform types, world, view and projection. I can't really remember too much about each. Projection can be thouht to be the lense of a camera it deals wit transforming 3D co-ords ot 2D space. I'm not sure of the differences between view and world. Here I change the view.
So I create a matrix, they have handy functions to be tinkered with.
change.Translate(10,1,0); // I've called my matrix change.
device.SetTransform(TransformType.View, change)
These are x, y, z. So I was it to move 10 units on the X, and 1 unit on the Y.
So then I change the view vector.
Then I call the draw primatives with the same call again.
Then I cal translate with negative numbers to return me to my origin.
Then set the transform to the view again.
If I don't return to my starting position I can only see the most recently placed I'm not sure why. It could be do with my movement calues or mixing view and world up.
I'm not sure I've done it the correct way but it seem to work.
Call DrawPrimatives from the device and drawn my quad.
device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
The first 0 being the vertex to start with, the second 2 is the number of triangles. In this case two to make a square.
There seem to be calls to draw rects and such but this way is good for now. I can, if I so wish, have odd shapes in my world.
So that sets the first one down at what is 0,0 dead center of where I am looking.
This seems to be where 'I' place no matter what.
Therefore I need to move myself, place and move myself back.
There are the three Transform types, world, view and projection. I can't really remember too much about each. Projection can be thouht to be the lense of a camera it deals wit transforming 3D co-ords ot 2D space. I'm not sure of the differences between view and world. Here I change the view.
So I create a matrix, they have handy functions to be tinkered with.
change.Translate(10,1,0); // I've called my matrix change.
device.SetTransform(TransformType.View, change)
These are x, y, z. So I was it to move 10 units on the X, and 1 unit on the Y.
So then I change the view vector.
Then I call the draw primatives with the same call again.
Then I cal translate with negative numbers to return me to my origin.
Then set the transform to the view again.
If I don't return to my starting position I can only see the most recently placed I'm not sure why. It could be do with my movement calues or mixing view and world up.
Wednesday, June 25, 2003
What was done yesterday:
Looked into the first few SDKs tutorials reasonably deeply. that was pretty much it :(
Today - had a look though an old tutorial for DX8 in C++. Converted it and messed around. The code is a bit of a hack job and is overwriting the 3rd SDK tutorial example.
But it works - images to screen orthagonal view.
Currently awfully user unfriendly. It needs wrapping into a nice class.
I want to be able to plot a said polygon and a said place with a said texture with a few function calls.
Currently it puts the polygon on the screen with a bitmap texture.
I'll have mess with the code and make it nicer today / tommorrow and the write the important bits out here.
I only want to unlock / lock the vertex buffer once per frame so I need figure out a way to but all my graphical changes in a group before sending them off the the unlock lock buffer.
Looked into the first few SDKs tutorials reasonably deeply. that was pretty much it :(
Today - had a look though an old tutorial for DX8 in C++. Converted it and messed around. The code is a bit of a hack job and is overwriting the 3rd SDK tutorial example.
But it works - images to screen orthagonal view.
Currently awfully user unfriendly. It needs wrapping into a nice class.
I want to be able to plot a said polygon and a said place with a said texture with a few function calls.
Currently it puts the polygon on the screen with a bitmap texture.
I'll have mess with the code and make it nicer today / tommorrow and the write the important bits out here.
I only want to unlock / lock the vertex buffer once per frame so I need figure out a way to but all my graphical changes in a group before sending them off the the unlock lock buffer.
Tuesday, June 24, 2003
Okay so its currently in Windowed mode that needs changing or giving an option to change.
Currently its simply and I understand most of it. There seem to be some uncessary uses of delegations but I left it like the tutorials give it.
The Simple Overview
1. Create a window / from
2. Create device, in this case a 3dDirectX device. Linked to the form
3. Create a vertex buffer
- lock the vertex buffer
- stick in all the vertexes you want to render, in an array
- unlock it
4. Render by adding it to the scene while the scene is locked in the render function.
All the stuff going to the screen has to go through the render function. Meaning it has to go through the vertex buffer to get there. Or they're the looks of it so far.
This is using the tutorials avaliable at the Microsoft site.
Going through the window C# book might be an idea too.
There are only five tutorials and my disk copies differ from the web copies slightly. Though they all work, they don't provide much background though.
So I've got to polish off the last three tutorials. I'm going over them slowly making notes. These should be useful later for when I try to tie in my book on DirectX for C++.
Currently its simply and I understand most of it. There seem to be some uncessary uses of delegations but I left it like the tutorials give it.
The Simple Overview
1. Create a window / from
2. Create device, in this case a 3dDirectX device. Linked to the form
3. Create a vertex buffer
- lock the vertex buffer
- stick in all the vertexes you want to render, in an array
- unlock it
4. Render by adding it to the scene while the scene is locked in the render function.
All the stuff going to the screen has to go through the render function. Meaning it has to go through the vertex buffer to get there. Or they're the looks of it so far.
This is using the tutorials avaliable at the Microsoft site.
Going through the window C# book might be an idea too.
There are only five tutorials and my disk copies differ from the web copies slightly. Though they all work, they don't provide much background though.
So I've got to polish off the last three tutorials. I'm going over them slowly making notes. These should be useful later for when I try to tie in my book on DirectX for C++.
What work occured yesterday:
-Wrote a small console based game that uses inheritance and dynamic binding as well as overloading. Just to make sure I still had my flow. It seems I do as that worked fine. It would have been much harder in C++.
-Finished C# For Programmers. A very good book, I now feel I have a broad understanding of the language.
-Wrote up some of my 'broad understanding of the language notes'
-Read a chapter of a book specifcally based on the C# IDE, i.e. the .NET IDE so far its pretty worthless.
What I failed to do:
Get a bitmap on the screen Bah!
It doesn't seem too hard in the GDK+ but I want to use Direct3D.
Todays plan:
-Write up notes.
-Do SDK tutorials right up until the end. They may seems like gibberish to me but using the Direct3D book I should be able to piece together the meaning.
-Have a look at the other C# books specifically the windows one and do a few chapters.
-Wrote a small console based game that uses inheritance and dynamic binding as well as overloading. Just to make sure I still had my flow. It seems I do as that worked fine. It would have been much harder in C++.
-Finished C# For Programmers. A very good book, I now feel I have a broad understanding of the language.
-Wrote up some of my 'broad understanding of the language notes'
-Read a chapter of a book specifcally based on the C# IDE, i.e. the .NET IDE so far its pretty worthless.
What I failed to do:
Get a bitmap on the screen Bah!
It doesn't seem too hard in the GDK+ but I want to use Direct3D.
Todays plan:
-Write up notes.
-Do SDK tutorials right up until the end. They may seems like gibberish to me but using the Direct3D book I should be able to piece together the meaning.
-Have a look at the other C# books specifically the windows one and do a few chapters.
Monday, June 23, 2003
Last week I've been working my way through a book on C# for programmers. In a ringbound smallish notebook I've made a few notes as I've gone along. I'll digitize them now, which should refresh my memory.
My C# Notes
The .Net frame work is component based. All C# objects can be thought of as components.
Each object is associcated with metadata, i.e. data about that object.
Each program requires a main function.
The main function is static. Main is the function that controls everything, static prevents you creating more instances of the class containing the main function.
Code is seperated into classes. Its an OOP paradaigm so each class should attempt to represent some distinct object. Classes that interact with each other, are grouped together in the same scope space. These spaces are defined using the namespace keyword. Namespaces are used to group and order classes, they can be nested in each other much like Russian Dolls.
Once these namespaces are carved out, other parts of the program can gain some level of access to them by using the using keyword. You may want to use a deeply nested namespace this can be done by using an alias.
.Net allows you to write in any programming language it supports. You can the package up whatever you've written and access its functionality in any other programming class. Package up some code is turning it into an assembly. To access other users objects in assemblies you must locate them and add them as references in the IDE.
Structs exist in C# also. They are mainly used for lightweight datatypes. Made to be used as the built in datatypes are used. So adding matrices or vectors or complex numbers etc.
Attributes are a part of the metadata mentioned earlier. Attributes are stored in square brackets.
e.g
The specific of the attribute are defined usng a special class we'll come to later.
Attributes can be accessed during runtime!
C# supports exception heavily. Rather than have some function returning a HRESULT choc-a-block with various error codes, errors are thrown as exceptions. This makes the code much less buggy, as error handling is seperated and all the expensive checking and such is used only when needed. If an error occurs the program throws it down the code, until it reaches the relevant ctach statement. If it doesn't find the catch statement, it goes up a level in scope and tries again. If it once failes all the way to the top level of scope a little window will come up and the program will be halted. Such as DivdeByZeroException press okay.
They work like this
A catcher might do some clean up code and then throw the exeception again. It may throw a new expection so another program can do some more cleaning up.
Users can defined their own expections. Using inheritance and making sure to use the right overloaders.
So there's the new exception and we might use it as below.
The Finally keyword, with all these exception hoping out at unknown times, it may leave resouces open, and not properly shut down. Such as I/O for example. This is where the finally keyword comes into play. No matter what before a function is exited the finally cdoe block is called.
Classes
X and Y must both be intialized
X and Y do not have to be intialized
Overwriting
If a base class has a function 'foo' and the inhertiting class has a function 'foo' which is an unrelated class. Then the child class must make this clear to the complier by adding in the keyword 'new'.
What if we wish the function to replace the base classes function? The base function must be declared to be virtual and the child must use the override keyword.
Now if the child class was referenced as the base class and the update function was called, then the complier would check the type of the object. It would then check if the function was overridden and if so would call the overriding class.
So new is for a seperate unrelated class that happen to share the same name
But virtual and override mean that the functions is to be overwritten by its child function.
Programming Style: The Virtual Keyword should only be added when used. (only added when there is a base class overriding)
Abstract Class
An abstract class is a class with one or more abstract functions.
An abstract function is a function that has no functionality. Its just saying there should be a function that takes this and this and returns this.
An abstract class therefore can be instaiated. You cannot create a class with function that have no code.
Any child of an anstract class that is not abstract must include code for the abstract functions. Using the override keyword.
This is a powerful enforcing tool.
The Sealed keyword means a class cannot be inherited from.
Class privacy
Internal - used to write helper classes, that you would rather the final user of the class did not see.
access to the class is avaliable to all classes in the same assembly.
it can also be used on members of a class, when you wish to share members but not allow public access.
Internal may be combined to internal protected. So that those classes accessing through protected or internal have access.
Classes as we said earlier can be nested. This is useful if only the current class is going to make use of that type of object. Not only classes can be nested in classes so can structs, enumerations and interfaces.
Constructors
A function that is called as soon as an object is created from the class.
The function must be public, share the same name as the class and not have any return types.
It is often useful to call the base classes constructor first and this is done as following:
Constructors often repeat a lot of code, for the various ways they can be constructed. Usually building up from simplier intializations in this way forwarding can be useful.
The second constructor calls the first. Less code has to be written.
Elements in a class can automatically be intialzed to some value.
This is done simply
Static members and functions are those that are not asssociated with any particular instance but rather the class itself in general.
One of there uses is as class counters.
Outside of the class, in the main code. To access the static member the class name must be used not the name of one of its object instances. So it would be MyClass.instanceCount, rather than someObject.instanceCount. That would not work.
Static constructor can also exist, before the first objecti s intialized the function is called and my do necessary setup work.
Constants use the keyword const, and must be set at compile time, they will not change.
If we wish to have something like a constant but do not know its value until the program is running the readonly keyword can be used. Once assigned a value this value cannot be changed.
If you choose to create a class of all static members it is best to declare it private so that it cannot accidently be initailized.
Creating A Variable Length Parameter List
Such as writeln(string1, string2, .... stringn). They can all be written out. This can be achieved in user-defined classes also. The keyword params is used.
My C# Notes
The .Net frame work is component based. All C# objects can be thought of as components.
Each object is associcated with metadata, i.e. data about that object.
Each program requires a main function.
public static void Main(string[] args)
{
}
The main function is static. Main is the function that controls everything, static prevents you creating more instances of the class containing the main function.
Code is seperated into classes. Its an OOP paradaigm so each class should attempt to represent some distinct object. Classes that interact with each other, are grouped together in the same scope space. These spaces are defined using the namespace keyword. Namespaces are used to group and order classes, they can be nested in each other much like Russian Dolls.
namespace DanSpace
{
//classes concerning the operation of DanSpace
}
Once these namespaces are carved out, other parts of the program can gain some level of access to them by using the using keyword. You may want to use a deeply nested namespace this can be done by using an alias.
using theConsoleClass = System.Console;
...
theConsoleClass.Writeln("I'm using an alias!");
.Net allows you to write in any programming language it supports. You can the package up whatever you've written and access its functionality in any other programming class. Package up some code is turning it into an assembly. To access other users objects in assemblies you must locate them and add them as references in the IDE.
Structs exist in C# also. They are mainly used for lightweight datatypes. Made to be used as the built in datatypes are used. So adding matrices or vectors or complex numbers etc.
Attributes are a part of the metadata mentioned earlier. Attributes are stored in square brackets.
e.g
[Code Review("1.02.2003", Comment = "Well Done"]
The specific of the attribute are defined usng a special class we'll come to later.
Attributes can be accessed during runtime!
C# supports exception heavily. Rather than have some function returning a HRESULT choc-a-block with various error codes, errors are thrown as exceptions. This makes the code much less buggy, as error handling is seperated and all the expensive checking and such is used only when needed. If an error occurs the program throws it down the code, until it reaches the relevant ctach statement. If it doesn't find the catch statement, it goes up a level in scope and tries again. If it once failes all the way to the top level of scope a little window will come up and the program will be halted. Such as DivdeByZeroException press okay.
They work like this
try
{
int j = 9 / ZERO
}
catch (DivideByZeroException e)
{
//Do correction code.
}
A catcher might do some clean up code and then throw the exeception again. It may throw a new expection so another program can do some more cleaning up.
Users can defined their own expections. Using inheritance and making sure to use the right overloaders.
public class CountIsZeroException : Exception
{
public CountIsZeroException()
{
}
public CountIsZeroException(string message) : base (message)
{
}
}
So there's the new exception and we might use it as below.
public void DoAverage()
{
if (count == 0)
throw( new CountIsZeroException("Zero Exception in DoAverage")
else
average = sum / count;
}
The Finally keyword, with all these exception hoping out at unknown times, it may leave resouces open, and not properly shut down. Such as I/O for example. This is where the finally keyword comes into play. No matter what before a function is exited the finally cdoe block is called.
finally
{
file.Close();
}
Classes
myPoint.GetMyPoint(ref x, ref y);
X and Y must both be intialized
myPoint.GetMyPoint(out x, out y);
X and Y do not have to be intialized
Overwriting
If a base class has a function 'foo' and the inhertiting class has a function 'foo' which is an unrelated class. Then the child class must make this clear to the complier by adding in the keyword 'new'.
public new update ( params )
{
}
What if we wish the function to replace the base classes function? The base function must be declared to be virtual and the child must use the override keyword.
virtual public update(); // in base class
override public update(); // in child class
Now if the child class was referenced as the base class and the update function was called, then the complier would check the type of the object. It would then check if the function was overridden and if so would call the overriding class.
So new is for a seperate unrelated class that happen to share the same name
But virtual and override mean that the functions is to be overwritten by its child function.
Programming Style: The Virtual Keyword should only be added when used. (only added when there is a base class overriding)
Abstract Class
An abstract class is a class with one or more abstract functions.
An abstract function is a function that has no functionality. Its just saying there should be a function that takes this and this and returns this.
An abstract class therefore can be instaiated. You cannot create a class with function that have no code.
Any child of an anstract class that is not abstract must include code for the abstract functions. Using the override keyword.
This is a powerful enforcing tool.
The Sealed keyword means a class cannot be inherited from.
sealed class MyClass
{
}
Class privacy
Internal - used to write helper classes, that you would rather the final user of the class did not see.
access to the class is avaliable to all classes in the same assembly.
it can also be used on members of a class, when you wish to share members but not allow public access.
Internal may be combined to internal protected. So that those classes accessing through protected or internal have access.
Classes as we said earlier can be nested. This is useful if only the current class is going to make use of that type of object. Not only classes can be nested in classes so can structs, enumerations and interfaces.
Constructors
A function that is called as soon as an object is created from the class.
The function must be public, share the same name as the class and not have any return types.
It is often useful to call the base classes constructor first and this is done as following:
public class Derived : BaseClass
{
public Derived (int x) : Base(x)
{
}
}
Constructors often repeat a lot of code, for the various ways they can be constructed. Usually building up from simplier intializations in this way forwarding can be useful.
public MyObject(int x)
{
this.x = x
}
public MyObject(int x, int y): this(x)
{
this.y = y
}
The second constructor calls the first. Less code has to be written.
Elements in a class can automatically be intialzed to some value.
This is done simply
int x = 0;
Static members and functions are those that are not asssociated with any particular instance but rather the class itself in general.
One of there uses is as class counters.
class MyClass
{
public MyClass()
{
instanceCount++;
}
public static int instanceCount = 0;
}
Outside of the class, in the main code. To access the static member the class name must be used not the name of one of its object instances. So it would be MyClass.instanceCount, rather than someObject.instanceCount. That would not work.
Static constructor can also exist, before the first objecti s intialized the function is called and my do necessary setup work.
Constants use the keyword const, and must be set at compile time, they will not change.
If we wish to have something like a constant but do not know its value until the program is running the readonly keyword can be used. Once assigned a value this value cannot be changed.
If you choose to create a class of all static members it is best to declare it private so that it cannot accidently be initailized.
Creating A Variable Length Parameter List
Such as writeln(string1, string2, .... stringn). They can all be written out. This can be achieved in user-defined classes also. The keyword params is used.
//first deal with the single argument condition
public void Write(string label, object arg)
{
}
// the deal with the n-case, an array of arguments
public void Write (string label, params object[] args)
params keyword means that the function will accept variable length arguments.
It is good programming practice to include a few function for some of the simplier cases also. I.e. one argument, two arguments, three arguments and the array of arguments.
Structs
Structs are cheap fast to allocate and do not have a reference overhead.
They are the same as classes but
- cannot inherit from any other type
- other classes may not inherit from them
They should only be used for the basic types.
Interface
Interface classes are those classes that have all there methods abstract. A class may inherit from more that one interface but it may inherit only from one class.
interface IScalable
{
void ScaleX(float factor)
void ScaleY(float factor)
}
foreach (DiagramObject d in dArray)
{
IScalable scalable = d as IScalable;
if( scalable !=null)
{
scalable.ScaleX(10.0F)
scalable.ScaleY(10.0F);
}
}
The as keyword changes all objects to the type after the as, or sets the others to null, if it cannot be explicitly converted.
Choosing between Abstract and Interface: - If objects derived from base class would cary widely then Interface is the more suited choice.
Bits and Bobs
Case statements are more efficent than nested ifs.
foreach example
foreach (MyObject current in arr)
{
Console.Writeln("Item: {0}", current);
}
It can also be used to iterate across the keys of a hash table.
Blocks of code can be put into checked status by:
checked
{
//code
}
Any overflows will then thorw expections. Going out of range by repeatadly adding to a byte etc.
The entire program can be put into check by cheking a falg in the ide.
Then when you want something now to raise the exception you should but it in unchecked blocks.
Remainder (I always forget this one so I'm putting it in) x % y =~ x-(x/y) * y
Conditional operator
? :
int value - (x<10) ? 15 : 0;
If the condition evaluates to true then value is assigned 15 otherwise 0.
TypeOf - reutrns the type of the current object
Is - can an object be converter to a particular type, returns a bool.
Arrays
Operators: Reverse(), IndexOf(), LastIndexOf(), Sort(), BinarySearch()
The sort works for built in types and cane be extended so that it will work for user defined types also.
Accesors
public string Name
{
get
{
return Name;
}
set
{
value = Name;
}
}
If you have a getter only its is readonly.
If you have a setter only its is writeonly.
These are useful for effecient loading.
class CarDealer
{
public int ProductionCount
{
get
{
if(productionCount == -1)
{
// do expensive load operation from the database
}
}
}
int productionCount = -1;
}
Use the negative value of -1 to mean that we have not read in from the database. Thereby only doing a database access when need be.
Enumerators
Useful for a value in a program can only have a certain set of values.
Enumerators can also be used as Flags bits allowing them to be comibined using logical operations.
[Flags]
EnumBitValues
{
{
NoBits = 0;
Bit1 = 0x00000...1
...
}
}
Attributes - annotations that are placed in the source code.
Delegate
A bit like type safe fuction pointrers.
They are created at runtime and specify the form of a single function.
If two delegates are added together a delgate that calls both functions is the result.
Useful for when you want to change the behaviour of a function.
Example: A sorting function where the delegate defines the comparision function.
public delegate int CompareItemsCallback(object obj1, object obj2);
public void Sort(CompareItemsCallBack compare)
{
//inner loop
int order = compare(item1, item2)
}
public class Employee
{
public static int CompareName(Object obj1, Object obj2)
{
Employee emp1 = (Employee) obj1;
Employee emp2 = (Employee) obj2;
return(string.compare(emp1.name, emp2.name))
}
public static int CompareId(Object obj1, Object obj2)
{
//compare ids
}
}
...
//Main Function
//Create Delegate To Sort by Names!
Container.CompareItemsCallback sortByName = new Container.CompareItemsCallback(Employee.CompareName);
employees.Sort(sortbyName)
}
THats how delgates work how fiendishly clever. Things though can infact get cleverer. In the book I was perusing things got incrementally clever-ver. Rather than do that I'm going to jump to the last step of cleverness.
Create the delegates on the fly rather than always having them present.
public static Container.CompareItemsCallBack SortByName
{
get
{
return( new Container.CompareItemsCallBack SortByName
}
}
Now only created when needed.
Events - a class can use events to notify another class/ classes that something has happened.
Publish / Subscribe idiom.
A class publishes events it can raise. Classes that are interested in a specific event can subscribe to it.
Often used for GUIs, but can also be used for things like mail handlers.
User Defined Conversions - allow conversions between classes and structs and other objects in the system. The example for this was pretty awful.
Basically you have to take in account if you may loose data or not. Epxplicit and Implicit conversion. Currently I don't see myself using it so I've skimmed it.
Infix Operators!
We use the operator keyword to allow a class to use the +, - and others. Overload them!
public static Datatype operator + (Datatype D1, Datatype D2)
{
//Do the jazz return the result
}
Preprosssors
#define DEBUGLOG
...
//In code
# if DEBUGLOG
Console.Writeln("Main - Debug is enabled");
#else
Console.Writeln("No Debug in Main");
#endif
Verbatim Strings
Removes some of the string processing so you can write exactly what gets printed out.
string = "C:\\Program Files\\Microsoft Office\\Office"
instead we can have
string = @"C:\program Files\Microsfot Office\Office"
It will also keep all tabs and newline you phyically put in, using vertabim strings may span several lines.
Making Objects the fit in with the dotNet frame work
All objects have the operators '==', '!=' and toString. These can be overridden so that they are more useful.
ToString:
override public string ToString()
{
return ("{0} \n {1} \\ {2}", name, health, hits);
}
...
Console.Writeln("Pete's health:{0}", pete);
//Writes out pete name and what health he has out of his total
Equals() used by collections(hash tables, arrays ...) for ordering . For more useful ordering it should be overwritten with code that says when two of your classes should be considered equal. For example two pieces of wood should only stack if they have the same durability.
public override bool Equals(objects obj)
{
Item item2 = (item) obj;
if durability != item2.durability
return false;
if name != item2.name
return false;
return true;
}
Once equals is defined its easy to write in the '==' and '!=' equals operators.
public static bool operator == (Item I1, Item I2)
{
return(I1.Equals(I2));
}
public static bool operator != (Item I1, Item I2)
{
return(!I1.Equals(I2));
}
These operator '==' and '!=' must be overloaded as a pair. They cannot be overloaded seperately
GetHashCode() must return a unique integer id for the object. This id must be related to the value(s) used to determine if the object is equal or not to another object. If there is a unique field in the object it is probably a good idea to use this as the hash code.
public override int GetHashCode()
{
return(unique_id);
}
If there is no unique Id then one should be created from a function of values.
Making User Defined Types Sortable
Simplest way is to implement the IComparable interface.
This allows you to add sorting, but sorting only one way. What if you wanted to sort by different field, name, age, shoe size, well we'll come to that afterwards.
First the IComparable Interface
int IComparable.CompareTo(object obj)
{
Employee emp2 = (Employee) obj;
if (this.id > emp2.id)
return(1);
if (this.id < emp2.id)
return(-1)
else
return(0);
}
So a int for the three possiblities of greater than(1), less than(-1) and equal(0)
This could be seens as a default sort. Though it does not let the user deicde what he would like a group of classes to sorte by.
To do this the IComparer interface must be used.
The sorting classes are nested in the class they define the sort for.
pubic class Employee : IComparable
{
public Employee() {} // constructor
int IComparable.CompareTo(Object obj) //default sort
public class sortByNameClass : IComparer // User defined sort using nested class
{
public int Compare(Object obj1, Object obj2)
{
//Do comparision using string.Compare
}
}
}
....
// In the main body of code
Array.Sort(arr, (IComparer) new Employee.SortByNameClass());
//Now the array is sorted by name
The syntax is a little messy with the 'new Employee.SortByNameClass());' The user shouldn't have to create a new object, if we make it staic the call be comes a lot simplier as the class doesn't have to be intialized.
public static.IComparerSortByName
{
get
{
return( (IComparer) new SortByNameClass());
}
}
public static.IComparer.SortById
{
get
{
return(IComparer) new SortByIdClass());
}
}
These make the calls to the instaitated the classes, so the user no longer has to instead he just calls the accessors.
As below:
Array.Sort(arr, Employee.SortByName);
For completeness the Relational Operators should also be overloaded.
(<,>, <=, >=)
This is done as before. Note they must be overloaded in pairs you cannot just overload one.
public static bool operator < (Employee emp1, Employee emp2)
{
IComparable icomp = (IComparable) emp1
return(icomp.CompareTo(Emp2) > 0);
}
Advanced Hashing
Very similar to adding new sort classes.
When you wish for an object to have more than one hash. i.e. based on the EmployeesID and another based on the EmployeesName.
IHashCodeProvider Interface should be used.
IClonable
Object.MemberWiseClone();
Creates merely a shallow clone. All references are copied, rather than creating new objects to be referenced to.
What is needed is a deep copy, where new objects are created.
This is done by implementing the IClonable Interface
class ContainedValue
{
public ContainedValue(int Count)
{
this.count = count;
}
public int count;
}
class MyObject : ICloneable
{
public MyObject(int Count)
{
this.contained = new ContainedValue(Count);
}
public Object Clone()
{
Console.Writeln("Clone")
return new MyObject(this.Contained.Count);
}
public ContainedValue Contained;
}
Some brief I/O
class Test
{
public static void Main()
{
FileStream f = new FileStream("output.txt", filemode.create);
StreamWriter s = new StreamWriter(f);
s.WriteLine("{0} {1}", "text", 55);
s.close;
f.close;
}
}
Style
PascalCasing - anything that would be visible externally from the class
camelCasing - private members, method parameters.
Interfaces should start with I.
Assert
using System.Diagnostics;
Debug.Assert(i==0, "BadState");
If i equals 0 then bad state is outputted.
In main:
Debug.Listeners.Clear(); //remove default Error Outputs
Debug.Listeners.Add(new TextWriter.Trace.Listener(Console.Out));
The default output is a windows message box, here its changed to the console window.
WriteIf and WriteLineIf, only write out if there first parameter is true.
Debug.WriteLineIf(debugOutput, "In VerifyState");
Aim for today: Get textured bitmaps to the screen via some loadbitmap function.
Detail: Basically I'd like to do this using a 3D framework. A screen full of quads each a tile each with a tecture.
I've been fiddling with Direct X. There are hardly any web tutorials dealing with DX9 and C#. The Microsoft SDK is a bit lacking and 'subject to change' bah.
I may use the GTK or whatever its called instead. Its a lot simplier and I can write my code in such a way that I cam swap in some faster later.
Right now I'm going to read this and see if things suddenly become clearer.
Detail: Basically I'd like to do this using a 3D framework. A screen full of quads each a tile each with a tecture.
I've been fiddling with Direct X. There are hardly any web tutorials dealing with DX9 and C#. The Microsoft SDK is a bit lacking and 'subject to change' bah.
I may use the GTK or whatever its called instead. Its a lot simplier and I can write my code in such a way that I cam swap in some faster later.
Right now I'm going to read this and see if things suddenly become clearer.
Subscribe to:
Posts (Atom)